Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Original author: Scott Adkins <[email protected]> (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("%d" .. 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()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement