### /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 = '' 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)