-- Original author: Scott Adkins (Zucanthor) -- Heavy modifications: Zygmut -- -- This program monitors work requests for the Minecolonies Warehouse and -- tries to fulfill requests from the Applied Energistics 2 network. If the -- AE2 network doesn't have enough items and a crafting pattern exists, a -- crafting job is scheduled to restock the items in order to fulfill the -- work request. The script will continuously loop, monitoring for new -- requests and checking on crafting jobs to fulfill previous requests. -- -- The following is required for setup: -- * 1 ComputerCraft Computer -- * 1 or more ComputerCraft Monitors (recommend 3x3 advanced monitors) -- * 1 Advanced Peripheral Colony Integrator -- * 1 Advanced Peripheral AE2 Bridge -- * 1 Chest or other storage container -- Attach an AE2 Cable from the AE2 network to the AE2 Bridge. Connect the -- storage container to the Minecolonies Warehouse Hut block directly or -- to an ender chest and then pipe ender chest contents out to the warehouse -- racks. Latter makes it easier to upgrade warehouse. -- Prints strings left, centered, or right justified at a specific row and -- specific foreground/background color. function MonPrintRow(monitor, y, position, text, textColor, bgColor) local w = select(1, monitor.getSize()) local fg = monitor.getTextColor() local bg = monitor.getBackgroundColor() local positions = { left = 1, center = math.floor((w - #text) / 2), right = w - #text, } local x = positions[position] or 1 if textColor then monitor.setTextColor(textColor) end if bgColor then monitor.setBackgroundColor(bgColor) end monitor.setCursorPos(x, y) monitor.write(text) monitor.setTextColor(fg) monitor.setBackgroundColor(bg) return y + 1 end -- Utility function that displays current time and remaining time on timer. -- For time of day, yellow is day, orange is sunset/sunrise, and red is night. -- The countdown timer is orange over 15s, yellow under 15s, and red under 5s. -- At night, the countdown timer is red and shows PAUSED insted of a time. function DisplayTimer(monitor, time) local now = os.time() local cycle = "day" local cycle_color = colors.orange if now >= 4 and now < 6 then cycle = "sunrise" cycle_color = colors.orange elseif now >= 6 and now < 18 then cycle = "day" cycle_color = colors.yellow elseif now >= 18 and now < 19.5 then cycle = "sunset" cycle_color = colors.orange elseif now >= 19.5 or now < 5 then cycle = "night" cycle_color = colors.red end MonPrintRow(monitor, 1, "left", string.format("Time: %s [%s]", textutils.formatTime(now, false), cycle), cycle_color) if cycle ~= "night" then MonPrintRow(monitor, 1, "right", string.format("Remaining: %ss", time), colors.blue) else MonPrintRow(monitor, 1, "right", "Remaining: PAUSED", colors.red) end return cycle end -- Scan all open work requests from the Warehouse and attempt to satisfy those -- requests. This function is not called at night to save on some ticks, as the -- colonists are in bed anyways. Item colors go as follow: -- - Red: Work order can't be satisfied -- (lack of pattern or lack of required crafting ingredients). -- - Yellow: Order partially filled and a crafting job was scheduled for the -- rest. -- - Green: Order fully filled. function ScanWorkRequests(monitor, bridge, storage, colony) local requests = {} for _, request in pairs(colony.getRequests()) do local name = request.name local item = request.items[1].name local target = request.target local desc = request.desc local needed = request.count local target_words = {} local target_length = 0 local target_name for word in target:gmatch("%S+") do table.insert(target_words, word) target_length = target_length + 1 end if target_length >= 3 then target_name = target_words[target_length-2] .. " " .. target_words[target_length] else target_name = target end local target_type = "" local target_count = 1 repeat if target_type ~= "" then target_type = target_type .. " " end target_type = target_type .. target_words[target_count] target_count = target_count + 1 until target_count > target_length - 3 -- Items like armor or weapons are not strictly bound to one possible -- request. For example, a Tier 2 Guard Tower will ask you to provide -- a Stone Sword, but a Wooden one will also work. -- Ideally, we want to provide the best item for the given tier and -- if not possible, give it the next "worst" option -- It works by checking from the worst item and saving the one that -- either yyou ahve in storage or can craft until the tier that the -- guard asked. That is not even the "best" solution, as you can give -- better items that are not said within the GUI but can be explored -- through the request system. so it's a nice balance local display_name if string.find(desc, "with") then local level = "Any Level" if string.find(desc, "with maximal level: Leather") then level = "Leather" end if string.find(desc, "with maximal level: Gold") then level = "Gold" end if string.find(desc, "with maximal level: Chain") then level = "Chain" end if string.find(desc, "with maximal level: Wood or Gold") then level = "Wood or Gold" end if string.find(desc, "with maximal level: Stone") then level = "Stone" end if string.find(desc, "with maximal level: Iron") then level = "Iron" end if string.find(desc, "with maximal level: Diamond") then level = "Diamond" end local max_item local last_item for _, item in pairs(request.items) do if (bridge.getItem({name=item.name}) or {count = 0}).count > 0 then max_item = item end if bridge.isItemCraftable({name=item.name}) then max_item = item end last_item = item if string.find(item.displayName, level) then break end end local best_item if max_item ~= nil then best_item = max_item else best_item = last_item end display_name = string.gsub(best_item.displayName, "[%[%]]", "") item = best_item.name end local color local provided = (bridge.getItem({name=item}) or {count = 0}).count if provided >= needed then color = colors.green provided = bridge.exportItem({name=item, count=needed}, storage) elseif bridge.isItemCrafting({name=item}) then color = colors.yellow elseif bridge.isItemCraftable({name=item}) and bridge.craftItem({name=item, count=needed}) then color = colors.orange else color = colors.red end if string.find(desc, "with") then table.insert(requests, { name = needed .. " " .. display_name, target = target_type .. " " .. target_name, needed = needed, provided = provided, color = color }) elseif string.find(target, "Builder") then table.insert(requests, { name = string.gsub(name, "^%d%-", ""), item = item, target = target_name, needed = needed, provided = provided, color = color }) else local new_target = target_type .. " " .. target_name if target_length < 3 then new_target = target end table.insert(requests, { name = string.gsub(name, "^%d%-", ""), target = new_target, needed = needed, provided = provided, color = color }) end end table.sort(requests, function(left, right) return left.target < right.target end) monitor.clear() local row = 3 if #requests == 0 then MonPrintRow(monitor, row, "center", "No Open Requests") else row = MonPrintRow(monitor, row, "center", "REQUESTS") local padding = 0 for _, line in pairs(requests) do local number = string.match(line.needed, "^%d+") if number and #number > padding then padding = #number end end for _, request in pairs(requests) do local number, rest = string.match(request.name, "^(%d+)%s+(.*)") number = number or "" MonPrintRow(monitor, row, "left", string.format("%s" .. string.rep(" ", padding - #number) .. " %s", number, rest), request.color) MonPrintRow(monitor, row, "right", " " .. request.target, request.color) row = row + 1 end end end function Main() local monitor = peripheral.find("monitor") if not monitor then error("Monitor not found.") end monitor.setTextScale(0.5) monitor.clear() monitor.setTextColor(colors.white) monitor.setCursorPos(1, 1) monitor.setCursorBlink(false) print("Monitor initialized.") local bridge = peripheral.find("meBridge") if not bridge then error("ME Bridge not found.") end print("ME Bridge initialized.") local colony = peripheral.find("colonyIntegrator") if not colony then error("Colony Integrator not found.") end if not colony.isInColony then error("Colony Integrator is not in a colony.") end print("Colony Integrator initialized.") -- This can be changed to suit your needs. Remember that this will position -- will be relative to the ME bridge local storage = "down" print("Storage initialized.") local time_between_runs = 1 local current_run = time_between_runs ScanWorkRequests(monitor, bridge, storage, colony) DisplayTimer(monitor, current_run) local TIMER = os.startTimer(1) while true do local e = {os.pullEvent()} if e[1] == "timer" and e[2] == TIMER then local now = os.time() if now >= 5 and now < 19.5 then current_run = current_run - 1 if current_run <= 0 then ScanWorkRequests(monitor, bridge, storage, colony) current_run = time_between_runs end end DisplayTimer(monitor, current_run) TIMER = os.startTimer(1) elseif e[1] == "monitor_touch" then os.cancelTimer(TIMER) ScanWorkRequests(monitor, bridge, storage, colony) current_run = time_between_runs DisplayTimer(monitor, current_run) TIMER = os.startTimer(1) end end end Main()