/lib/service.lua
- local c = require('component')
- local text = require('text')
- local event = require('event')
- local process = require('process')
- local unicode = require('unicode')
- local computer = require('computer')
- local serialization = require('serialization')
- local service = {}
- local log_gpu
- local cursorX, cursorY = 1, 1
- do
- local config_file = io.open('/etc/service-log.cfg')
- if config_file then
- local data = serialization.unserialize(config_file:read('*a'))
- log_gpu = c.proxy(c.get(data.gpu))
- local success, msg = log_gpu.bind(c.get(data.screen))
- if not success then
- error(msg)
- end
- if data.resolution then
- log_gpu.setResolution(table.unpack(data.resolution))
- end
- config_file:close()
- end
- end
- function service.log(msg, ...)
- local value = string.format('[%08.0f] ' .. msg .. '\n',
- computer.uptime(), ...)
- if not log_gpu then
- return
- end
- value = text.detab(value)
- local w, h = log_gpu.getResolution()
- if not w then
- return -- gpu lost its screen but the signal wasn't processed yet.
- end
- local line, nl
- repeat
- local wrapAfter, margin = math.huge, math.huge
- wrapAfter, margin = w - (cursorX - 1), w
- line, value, nl = text.wrap(value, wrapAfter, margin)
- log_gpu.set(cursorX, cursorY, line)
- cursorX = cursorX + unicode.wlen(line)
- if nl or cursorX > w then
- cursorX = 1
- cursorY = cursorY + 1
- end
- if cursorY > h then
- log_gpu.copy(1, 1, w, h, 0, -1)
- log_gpu.fill(1, h, w, 1, " ")
- cursorY = h
- end
- until not value
- end
- local function step_coroutine(c, return_on_error)
- local status = coroutine.status(c)
- if status == 'dead' then
- return false
- elseif status ~= 'suspended' then
- return true
- end
- local t = {coroutine.resume(c)}
- if not t[1] then
- service.log('problem in %s: %s', c, t[2])
- service.log('%s', debug.traceback(c))
- if return_on_error then
- return false
- else
- error('coroutine failure')
- end
- else
- return true
- end
- end
- function service.periodic(name, period, f, env)
- local t
- local want_up = false
- local function service_coroutine()
- while true do
- local c = coroutine.create(f)
- while true do
- if not step_coroutine(c) then
- break
- end
- coroutine.yield()
- end
- end
- end
- function start_service()
- if t then
- return
- end
- local c = process.spawn(service_coroutine)
- local function step()
- if not step_coroutine(c, true) then
- stop_service()
- end
- end
- t = event.timer(period, step, math.huge)
- service.log('Started %s', name)
- end
- local function stop_service()
- if not t then
- return
- end
- event.cancel(t)
- t = nil
- service.log('Stopped %s', name)
- if want_up then
- start_service()
- end
- end
- function env.start()
- want_up = true
- start_service()
- end
- function env.stop()
- want_up = false
- stop_service()
- end
- function env.status()
- if t then
- print('running')
- else
- print('stopped')
- end
- end
- end
- return service
an extra bit in /lib/process.lua
- function process.spawn(f, env, name, path)
- checkArg(1, f, "function")
- checkArg(2, env, "table", "nil")
- checkArg(3, name, "string", "nil")
- checkArg(4, path, "string", "nil")
- local process = findProcess()
- if process then
- env = env or process.env
- end
- if not path then
- path = '<function>'
- end
- env = setmetatable({}, {__index=env or _G})
- local thread = coroutine_create(f)
- running[thread] = {
- path = path,
- command = name,
- env = env,
- data = setmetatable({}, {__index=process and process.data or nil}),
- parent = process,
- instances = setmetatable({}, {__mode="v"})
- }
- return thread
- end
/etc/rc.d/autocraft.lua
- local serialization = require('serialization')
- local sides = require('sides')
- local computer = require('computer')
- local c = require('component')
- local service = require('service')
- local log = service.log
- local controller = c.me_controller
- local required_levels = {
- ['Wool'] = 8,
- ['Transistor'] = 10,
- ['Microchip (Tier 1)'] = 10,
- ['Microchip (Tier 2)'] = 10,
- ['Microchip (Tier 3)'] = 10,
- ['Iron Nugget'] = 10,
- ['Gold Nugget'] = 10,
- ['Basic Universal Cable'] = 32,
- ['Ultimate Universal Cable'] = 32,
- ['Redstone Torch'] = 4,
- ['Machine Frame (Basic)'] = 2,
- ['Redstone Reception Coil'] = 2,
- ['Paper'] = {128, 256},
- ['Book'] = {128, 256},
- ['ME Glass Cable - Fluix'] = 32,
- ['Logic Processor'] = 4,
- ['Calculation Processor'] = 4,
- ['Engineering Processor'] = 4,
- ['Speed Upgrade'] = 8,
- ['Energy Upgrade'] = 8,
- ['ME Smart Cable - Fluix'] = 8,
- ['ME Dense Cable - Fluix'] = 8,
- ['ME Storage Housing'] = 2,
- ['Arithmetic Logic Unit (ALU)'] = 2,
- ['Control Unit (CU)'] = 2,
- ['EEPROM (Lua BIOS)'] = 2,
- ['EEPROM'] = 2,
- ['Printed Silicon'] = {128, 256},
- }
- function ensure_level(label, desired)
- local filter = {label = label}
- local items = controller.getItemsInNetwork(filter)
- local count = 0
- for i = 1, items.n do
- count = count + items[i].size
- end
- local lower_bound = desired
- if type(desired) == 'table' then
- lower_bound, desired = table.unpack(desired)
- end
- if count >= lower_bound then
- return
- end
- local crafting = controller.getCraftables(filter)[1]
- if not crafting then
- log('No crafting available for %s', label)
- return
- end
- local stack_size = crafting.getItemStack().size
- local n_jobs = math.ceil((desired - count) / stack_size)
- log('Crafting %s (%d → %d)',
- label, count, count + stack_size * n_jobs, n_jobs)
- local status = crafting.request(desired - count)
- while not (status.isCanceled() or status.isDone()) do
- os.sleep(1)
- end
- end
- function tick()
- for label, count in pairs(required_levels) do
- ensure_level(label, count)
- coroutine.yield()
- end
- end
- service.periodic('autocraft', 0.1, tick, _ENV)
/etc/rc.d/export-damaged.lua
- local serialization = require('serialization')
- local sides = require('sides')
- local computer = require('computer')
- local c = require('component')
- local service = require('service')
- local controller = c.me_controller
- local export = c.me_exportbus
- local db = c.database
- local label_patterns = {
- 'Boots',
- 'Leggings',
- 'Chestplate',
- 'Helmet',
- '^Bow$',
- 'Fishing Rod',
- 'Sword',
- 'Pickaxe',
- 'Shovel',
- 'Axe',
- 'Shears',
- }
- function label_ok(item)
- for _, pattern in pairs(label_patterns) do
- if item.label:find(pattern) then
- return true
- end
- end
- return false
- end
- function clear_whole_db()
- for i = 1, 9 do
- db.clear(i)
- end
- end
- function export_relevant_items()
- local items = controller.getItemsInNetwork()
- local n_done = 0
- for i = 1, items.n do
- local item = items[i]
- if label_ok(item) and item.damage > 0 and not item.enchantments then
- controller.store(item, db.address)
- n_done = n_done + 1
- if n_done >= 9 then
- break
- end
- end
- end
- for i = 1, 9 do
- local item = db.get(i)
- if not item then
- break
- end
- service.log('Exporting %s@%d', item.label, item.damage)
- export.setExportConfiguration(sides.back, i, db.address, i)
- end
- end
- function tick()
- clear_whole_db()
- export_relevant_items()
- end
- service.periodic('export-damaged', 10, tick, _ENV)