Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ------------------------------------------------------------
- -- AE2ColonyWarehouse (Tile-Based)
- -- by Dww160 (based on Zucanthor logic)
- --
- -- Recommended Monitor Setup:
- -- For best results, use a 3x5 advanced monitor (3 tall x 5 wide).
- --
- -- Features:
- -- 1) Scans MineColonies requests
- -- 2) Checks AE2 (via meBridge) for items
- -- 3) Exports items to any connected inventory on the ME Bridge
- -- 4) Attempts to craft if not enough items are present
- -- 5) Displays requests as interactive color-coded "tiles"
- -- 6) Click a tile to see detail view (colonist name, skip reason, craftability, etc.)
- -- 7) In the detail view, tap the toggle option to add or remove the request from skip patterns.
- -- 8) In detail view, requests that fail are labeled as "none in inventory".
- -- 9) Auto-returns to tile menu after 30s or on a second click.
- -- 10) Runs every 30 seconds by default, with a visible scan timer.
- -- 11) When there are no requests to fulfill, displays an animated happy stick figure dance with the message "All requests filled! Hurray!"
- --
- -- Original Tutorial Lines:
- -- This script is based on the original tutorial code for AE2ColonyWarehouse.
- ------------------------------------------------------------
- --------------------
- -- USER SETTINGS
- --------------------
- local SCAN_INTERVAL = 10 -- seconds between scans
- local LOG_FILE = "ae2colonywarehouse.log"
- local DEBUG = true -- set to false to reduce console spam
- local DETAIL_TIMEOUT = 30 -- seconds to show detail view
- -- Crafting timeout in seconds (if no progress within this time, job is marked timed out)
- local CRAFT_TIMEOUT = 90
- local MAX_ATTEMPTS = 3 -- Maximum re-schedule attempts per item
- -- If you want to blacklist certain item requests or skip them,
- -- add them here.
- local SKIP_PATTERNS = {
- "Tool of class",
- "Hoe", "Shovel", "Axe", "Pickaxe", "Bow", "Sword", "Shield",
- "Helmet", "Chestplate", "Leggings", "Boots", "Tunic", "Leather Cap",
- "Rallying Banner", "Crafter", "Compostable", "Fertilizer",
- "Flowers", "Food", "Fuel", "Smeltable Ore", "Stack List"
- }
- --------------------
- -- GLOBAL CRAFTING TRACKER
- --------------------
- -- Stores pending craft jobs:
- -- craftingTracker[itemName] = { expected = number, timestamp = os.clock(), attempts = number, timedOut = boolean }
- local craftingTracker = {}
- --------------------
- -- HELPER FUNCTIONS
- --------------------
- local function dprint(...)
- if DEBUG then print("[DEBUG]", ...) end
- end
- local function safePeripheralCall(periph, method, ...)
- if type(periph[method]) ~= "function" then
- dprint("Method " .. method .. " not available on peripheral")
- return nil, "Method " .. method .. " not available"
- end
- local ok, result = pcall(periph[method], periph, ...)
- if not ok then
- dprint("Error calling " .. method .. ": " .. tostring(result))
- return nil, result
- end
- return result, nil
- end
- --------------------
- -- PERIPHERAL SETUP
- --------------------
- -- Now that all helper functions are defined, set up peripherals.
- local monitor = peripheral.find("monitor")
- if not monitor then error("No advanced monitor found. Attach an advanced monitor to the computer.") end
- monitor.setTextScale(0.5)
- monitor.setBackgroundColor(colors.black)
- monitor.setTextColor(colors.white)
- monitor.clear()
- monitor.setCursorPos(1, 1)
- monitor.setCursorBlink(false)
- local meBridge = peripheral.find("me_bridge")
- if not meBridge then error("No 'meBridge' found. Place an ME Bridge next to the computer.") end
- local colony = peripheral.find("colony_integrator")
- if not colony then error("No 'colonyIntegrator' found. Place a Colony Integrator next to the computer.") end
- if not colony.isInColony then error("Colony Integrator is not inside a colony. Please move it within your colony's boundaries.") end
- ----------------------------------------------------------------
- -- autoDetectOutputSide: Try common sides until one returns a positive export.
- ----------------------------------------------------------------
- local function autoDetectOutputSide(itemStack)
- local sides = {"top", "bottom", "left", "right", "front", "back"}
- for _, side in ipairs(sides) do
- local ok, result = pcall(function()
- return meBridge.exportItem(itemStack, side)
- end)
- if ok and type(result) == "number" and result > 0 then
- return side, result
- end
- end
- return nil, 0
- end
- ----------------------------------------------------------------
- -- safeExportItemToTop: new signature => exportItem(itemStack, side, [count?])
- ----------------------------------------------------------------
- local function safeExportItemToTop(stack)
- local itemStack = { name = stack.name, count = stack.count or 1 }
- local side, result = autoDetectOutputSide(itemStack)
- if side then
- dprint("Exporting " .. itemStack.count .. " of " .. itemStack.name .. " to side: " .. side)
- return result
- else
- dprint("Failed to export item (" .. (stack.name or "unknown") .. "): no output inventory found")
- return 0
- end
- end
- --------------------
- -- Updated safeCraftItem Function
- --------------------
- local function safeCraftItem(stack)
- local itemStack = { name = stack.name, count = stack.count or 1 }
- -- (Optional) Confirm it’s truly craftable
- local isReallyCraftable = false
- local craftableItems = meBridge.listCraftableItems() or {}
- for _, c in ipairs(craftableItems) do
- if c.name == stack.name then
- isReallyCraftable = true
- break
- end
- end
- if not isReallyCraftable then
- dprint("No valid pattern for " .. (stack.name or "unknown") .. " in AE2. Aborting craft.")
- return false
- end
- local ok, result = pcall(meBridge.craftItem, itemStack)
- if not ok then
- dprint("Error calling craftItem for " .. (stack.name or "unknown") .. ": " .. tostring(result))
- return false
- end
- dprint("craftItem raw result for " .. (stack.name or "unknown") .. ": " .. textutils.serialize(result))
- -- If result is a table with .status = "SUCCESS", good. If it's always 'true', might be a mod quirk.
- if type(result) == "table" then
- if result.status == "SUCCESS" then
- return true
- else
- dprint("craftItem returned status=" .. tostring(result.status) .. " for " .. (stack.name or "unknown"))
- return false
- end
- elseif result == true then
- -- Possibly always returns true. Let's do a quick check of meBridge.listCraftingJobs() if it exists:
- if type(meBridge.listCraftingJobs) == "function" then
- local jobs = meBridge.listCraftingJobs()
- local found = false
- for _, job in ipairs(jobs or {}) do
- if job.name == stack.name then
- found = true
- break
- end
- end
- if not found then
- dprint("WARNING: craftItem returned 'true' but job not found in listCraftingJobs()")
- return false
- end
- end
- return true
- end
- return false
- end
- local function shouldSkip(desc, name)
- for _, pattern in ipairs(SKIP_PATTERNS) do
- if string.find(desc, pattern) or string.find(name, pattern) then
- return true, pattern
- end
- end
- return false, nil
- end
- local function toggleSkipOption(req)
- if req.skip then
- local pattern = string.match(req.skipReason or "", 'Matched skip pattern: "(.+)"')
- if not pattern then pattern = req.name end
- for i, p in ipairs(SKIP_PATTERNS) do
- if p == pattern then
- table.remove(SKIP_PATTERNS, i)
- dprint("Removed skip pattern: " .. pattern)
- break
- end
- end
- else
- table.insert(SKIP_PATTERNS, req.name)
- dprint("Added skip pattern: " .. req.name)
- end
- end
- local function drawRect(mon, x1, y1, x2, y2, color)
- local oldBG, oldFG = mon.getBackgroundColor(), mon.getTextColor()
- mon.setBackgroundColor(color)
- for x = x1, x2 do
- mon.setCursorPos(x, y1) mon.write(" ")
- mon.setCursorPos(x, y2) mon.write(" ")
- end
- for y = y1, y2 do
- mon.setCursorPos(x1, y) mon.write(" ")
- mon.setCursorPos(x2, y) mon.write(" ")
- end
- mon.setBackgroundColor(colors.black)
- for yy = y1+1, y2-1 do
- mon.setCursorPos(x1+1, yy)
- mon.write(string.rep(" ", x2 - x1 - 1))
- end
- mon.setBackgroundColor(oldBG)
- mon.setTextColor(oldFG)
- end
- local function writeInTile(mon, x, y, text, fg)
- local oldBG, oldFG = mon.getBackgroundColor(), mon.getTextColor()
- if fg then mon.setTextColor(fg) end
- mon.setCursorPos(x, y)
- mon.write(text)
- mon.setBackgroundColor(oldBG)
- mon.setTextColor(oldFG)
- end
- local function colorToShortStatus(color)
- if color == colors.green then return "Fulfilled"
- elseif color == colors.yellow then return "Crafting"
- elseif color == colors.red then return "Failed"
- elseif color == colors.blue then return "Skipped" end
- return "Unknown"
- end
- local function colorToLongStatus(color)
- if color == colors.green then return "Fulfilled"
- elseif color == colors.yellow then return "Crafting/Partial"
- elseif color == colors.red then return "None in inventory"
- elseif color == colors.blue then return "Skipped/Manual" end
- return "Unknown"
- end
- -- Stub functions for meBridge (override if provided)
- function meBridge.isItemCrafting(stack)
- return false -- We rely on our own craftingTracker
- end
- function meBridge.exportItemToTop(stack)
- return safeExportItemToTop(stack)
- end
- if type(meBridge.craftItem) ~= "function" then
- function meBridge.craftItem(itemStack)
- dprint("craftItem not implemented on meBridge")
- return false
- end
- end
- --------------------
- -- ANIMATED HAPPY DANCE (When No Requests)
- --------------------
- local function displayHappyDance()
- local w, h = monitor.getSize()
- for y = 4, h do
- monitor.setCursorPos(1, y)
- monitor.clearLine()
- end
- local danceFrames = {
- " O \n /|\\ \n / \\ ",
- " O \n \\|/ \n / \\ ",
- " O \n /|\\ \n / \\ ",
- " O \n \\|/ \n / \\ "
- }
- local danceMsg = "All requests filled! Hurray!"
- local duration = 5
- local startTime = os.clock()
- while os.clock() - startTime < duration do
- for _, frame in ipairs(danceFrames) do
- for y = 4, h do
- monitor.setCursorPos(1, y)
- monitor.clearLine()
- end
- local lines = {}
- for line in frame:gmatch("[^\n]+") do
- table.insert(lines, line)
- end
- local totalLines = #lines
- local startRow = math.floor((h - totalLines) / 2)
- for i, text in ipairs(lines) do
- local x = math.floor((w - #text) / 2)
- if x < 1 then x = 1 end
- monitor.setCursorPos(x, startRow + i)
- monitor.write(text)
- end
- local msgX = math.floor((w - #danceMsg) / 2)
- monitor.setCursorPos(msgX, startRow + totalLines + 1)
- monitor.setTextColor(colors.green)
- monitor.write(danceMsg)
- monitor.setTextColor(colors.white)
- sleep(0.5)
- end
- end
- for y = 4, h do
- monitor.setCursorPos(1, y)
- monitor.clearLine()
- end
- end
- --------------------
- -- DISPLAY BANNER & LEGEND (Original Tutorial Lines Included)
- --------------------
- local function drawBanner()
- local w, _ = monitor.getSize()
- monitor.setCursorPos(1, 1)
- monitor.setBackgroundColor(colors.gray)
- monitor.setTextColor(colors.white)
- local text = "MineColonies AE2 Warehouse Manager"
- local x = math.floor((w - #text) / 2)
- if x < 1 then x = 1 end
- monitor.setCursorPos(x, 1)
- monitor.write(text)
- monitor.setBackgroundColor(colors.black)
- monitor.setTextColor(colors.white)
- end
- local function displayLegend()
- local legendText = "Legend: Green=Fulfilled | Yellow=Crafting | Red=None in inventory | Blue=Skipped"
- local w, _ = monitor.getSize()
- monitor.setCursorPos(1, 2)
- monitor.clearLine()
- local x = math.floor((w - #legendText) / 2)
- if x < 1 then x = 1 end
- monitor.setCursorPos(x, 2)
- monitor.write(legendText)
- end
- --------------------
- -- SCAN & FULFILL LOGIC
- --------------------
- local function logRequests(requests)
- local f = fs.open(LOG_FILE, "w")
- if not f then
- dprint("Failed to open log file: " .. LOG_FILE)
- return
- end
- local success, json = pcall(textutils.serializeJSON, requests, true)
- if success then
- f.write(json)
- else
- f.write("Could not JSON-serialize requests: " .. tostring(json))
- end
- f.close()
- end
- --------------------
- -- Revised processRequests Function
- --------------------
- local function processRequests()
- local allRequests = colony.getRequests()
- if not allRequests then
- dprint("No requests returned from colony.")
- return {}, {}, {}
- end
- logRequests(allRequests)
- local equipment_list = {}
- local builder_list = {}
- local nonbuilder_list = {}
- -- Build current AE2 item counts.
- local aeItems = {}
- local allAE = meBridge.listItems()
- for _, data in ipairs(allAE or {}) do
- if data.name then
- aeItems[data.name] = (aeItems[data.name] or 0) + (data.count or 0)
- end
- end
- -- Optional: Log current crafting jobs if available.
- if type(meBridge.listCraftingJobs) == "function" then
- local jobs = meBridge.listCraftingJobs()
- dprint("Current crafting jobs: " .. textutils.serialize(jobs))
- end
- -- Update craftingTracker: mark crafts as timed out if no progress.
- for item, info in pairs(craftingTracker) do
- local current = aeItems[item] or 0
- if current >= info.expected then
- dprint("Craft complete for " .. item)
- craftingTracker[item] = nil
- elseif os.clock() - info.timestamp > CRAFT_TIMEOUT then
- dprint("Crafting timed out for " .. item)
- info.timedOut = true
- elseif current <= (info.lastCount or 0) then
- dprint("No progress on " .. item .. ", forcing re-schedule")
- info.timedOut = true
- else
- info.lastCount = current
- end
- end
- -- Build craftable set.
- local craftableSet = {}
- local craftableItems = meBridge.listCraftableItems() or {}
- for _, citem in ipairs(craftableItems) do
- craftableSet[citem.name] = true
- end
- --------------------
- -- Pre-Aggregate Requests for Crafting
- --------------------
- local neededTotals = {}
- for _, req in ipairs(allRequests) do
- local item = req.items[1].name
- neededTotals[item] = (neededTotals[item] or 0) + req.count
- end
- for item, totalNeeded in pairs(neededTotals) do
- local available = aeItems[item] or 0
- if available < totalNeeded then
- local missing = totalNeeded - available
- if craftableSet[item] then
- if not craftingTracker[item] then
- local success = safeCraftItem({ name = item, count = missing })
- if success then
- craftingTracker[item] = {
- expected = missing,
- timestamp = os.clock(),
- attempts = 1,
- timedOut = false,
- lastCount = available
- }
- dprint("[Pre-aggregated scheduled craft] " .. missing .. "x " .. item)
- else
- dprint("[Pre-aggregated craft failed] " .. item)
- end
- else
- if not craftingTracker[item].timedOut then
- local success = safeCraftItem({ name = item, count = missing })
- if success then
- craftingTracker[item].expected = craftingTracker[item].expected + missing
- dprint("[Pre-aggregated re-triggered craft] Updated expected count for " .. item .. " by " .. missing)
- end
- end
- end
- else
- dprint("[Not craftable in pre-aggregation] " .. item)
- end
- end
- end
- --------------------
- -- Process Individual Requests for Display
- --------------------
- for _, req in pairs(allRequests) do
- local reqName = req.name
- local reqItem = req.items[1].name
- local reqTarget = req.target
- local reqDesc = req.desc
- local reqNeeded = req.count
- local provided = 0
- local skip, matchedPattern = shouldSkip(reqDesc, reqName)
- local color = colors.blue
- local haveCount = aeItems[reqItem] or 0
- local skipReason = nil
- if skip then
- skipReason = "Matched skip pattern: \"" .. matchedPattern .. "\""
- dprint("[Skipped request]", reqName, skipReason)
- else
- if haveCount > 0 then
- local toExport = math.min(haveCount, reqNeeded)
- dprint(string.format("Exporting up to %d/%d of %s", toExport, reqNeeded, reqItem))
- local actuallyExported = meBridge.exportItemToTop({ name = reqItem, count = toExport })
- provided = provided + actuallyExported
- end
- if provided < reqNeeded then
- local missing = reqNeeded - provided
- if not craftableSet[reqItem] then
- color = colors.red
- dprint("[Not craftable] " .. reqItem)
- elseif craftingTracker[reqItem] then
- if craftingTracker[reqItem].timedOut then
- if craftingTracker[reqItem].attempts < MAX_ATTEMPTS then
- local success = safeCraftItem({ name = reqItem, count = missing })
- if success then
- color = colors.yellow
- dprint("[Re-scheduled craft] " .. reqItem .. " attempt " ..
- (craftingTracker[reqItem].attempts + 1) .. " for additional " .. missing)
- craftingTracker[reqItem].attempts = craftingTracker[reqItem].attempts + 1
- craftingTracker[reqItem].timestamp = os.clock()
- craftingTracker[reqItem].timedOut = false
- craftingTracker[reqItem].expected = craftingTracker[reqItem].expected + missing
- craftingTracker[reqItem].lastCount = aeItems[reqItem] or 0
- else
- color = colors.red
- dprint("[Failed to re-schedule craft] " .. reqItem)
- end
- else
- color = colors.red
- dprint("[Max attempts reached for] " .. reqItem)
- end
- else
- -- Craft is already in progress; update expected count (pre-aggregation already called safeCraftItem).
- craftingTracker[reqItem].expected = craftingTracker[reqItem].expected + missing
- color = colors.yellow
- dprint("[Aggregated craft] Updated expected count for " .. reqItem ..
- " by " .. missing .. " to " .. craftingTracker[reqItem].expected)
- end
- else
- local success = safeCraftItem({ name = reqItem, count = missing })
- if success then
- color = colors.yellow
- dprint("[Scheduled craft] " .. missing .. "x " .. reqItem)
- craftingTracker[reqItem] = {
- expected = missing,
- timestamp = os.clock(),
- attempts = 1,
- timedOut = false,
- lastCount = aeItems[reqItem] or 0
- }
- else
- color = colors.red
- dprint("[Failed to craft] " .. reqItem)
- end
- end
- end
- if provided >= reqNeeded then
- color = colors.green
- dprint("[Provided]", reqItem)
- end
- end
- local newItem = {
- name = reqName,
- item = reqItem,
- target = reqTarget,
- desc = reqDesc,
- needed = reqNeeded,
- provided = provided,
- color = color,
- craftable = (craftableSet[reqItem] == true),
- skip = skip,
- skipReason = skipReason,
- }
- if string.find(reqDesc, "of class") then
- table.insert(equipment_list, newItem)
- elseif string.find(reqTarget, "Builder") then
- table.insert(builder_list, newItem)
- else
- table.insert(nonbuilder_list, newItem)
- end
- end
- return equipment_list, builder_list, nonbuilder_list
- end
- --------------------
- -- TILE-BASED MENU
- --------------------
- local tilePositions = {}
- local function flattenData(equipment, builder, nonbuilder)
- local merged = {}
- for _, v in ipairs(equipment) do table.insert(merged, v) end
- for _, v in ipairs(builder) do table.insert(merged, v) end
- for _, v in ipairs(nonbuilder) do table.insert(merged, v) end
- return merged
- end
- local function displayTileMenu(requests)
- tilePositions = {}
- local w, h = monitor.getSize()
- local startY = 4
- local columns = 3
- local rows = 3
- local tileCount = columns * rows
- local total = #requests
- local leftover = total - tileCount
- if leftover < 0 then leftover = 0 end
- local tileWidth = math.floor(w / columns)
- local tileHeight = 6
- for yy = 4, h do
- monitor.setCursorPos(1, yy)
- monitor.clearLine()
- end
- local idx = 1
- for r = 1, rows do
- for c = 1, columns do
- if idx > total or idx > tileCount then break end
- local req = requests[idx]
- local x1 = (c - 1) * tileWidth + 1
- local y1 = (r - 1) * tileHeight + startY
- local x2 = x1 + tileWidth - 1
- local y2 = y1 + tileHeight - 1
- if x2 > w then x2 = w end
- if y2 > h then y2 = h end
- drawRect(monitor, x1, y1, x2, y2, req.color)
- local lineY = y1 + 1
- local shortStatus = colorToShortStatus(req.color)
- writeInTile(monitor, x1 + 2, lineY, shortStatus, req.color)
- lineY = lineY + 1
- local displayName = ""
- if req.name:match("^[0-9]") then
- displayName = string.format("%d/%s", req.provided, req.name)
- else
- displayName = string.format("%d %s", req.needed, req.name)
- end
- writeInTile(monitor, x1 + 2, lineY, displayName, colors.white)
- table.insert(tilePositions, {
- x1 = x1, y1 = y1,
- x2 = x2, y2 = y2,
- requestRef = req
- })
- idx = idx + 1
- end
- if idx > tileCount then break end
- end
- if leftover > 0 then
- monitor.setCursorPos(1, h)
- monitor.clearLine()
- monitor.setCursorPos(1, h)
- monitor.setTextColor(colors.gray)
- monitor.write(string.format("(%d more requests not displayed)", leftover))
- monitor.setTextColor(colors.white)
- end
- end
- --------------------
- -- DETAIL VIEW
- --------------------
- local detailMode = false
- local detailTimeLeft = 0
- local detailRequest = nil
- local detailToggleButton = nil
- local function displayDetailScreen(req)
- detailMode = true
- detailRequest = req
- local w, h = monitor.getSize()
- for y = 3, h do
- monitor.setCursorPos(1, y)
- monitor.clearLine()
- end
- local row = 4
- local function line(text, col)
- monitor.setCursorPos(2, row)
- monitor.setTextColor(col or colors.white)
- monitor.clearLine()
- monitor.write(text)
- row = row + 1
- end
- line("Item: " .. req.name, req.color)
- line(string.format("Needed: %d / Provided: %d", req.needed, req.provided), req.color)
- line("Requested By: " .. req.target, req.color)
- row = row + 1
- local statusStr = (req.color == colors.red) and "None in inventory" or colorToLongStatus(req.color)
- line("Status: " .. statusStr, req.color)
- line("Craftable by AE2: " .. (req.craftable and "Yes" or "No"), req.color)
- row = row + 1
- if req.skip then
- line("Skip Reason: " .. (req.skipReason or "No reason found."), colors.blue)
- line("Suggestion: Remove from skip patterns", colors.lightBlue)
- else
- line("Skip Option: Not skipped", colors.lightBlue)
- end
- row = row + 1
- local toggleText = req.skip and "Tap to REMOVE skip pattern" or "Tap to ADD skip pattern"
- line(toggleText, colors.cyan)
- detailToggleButton = { x1 = 1, y = row - 1, x2 = w }
- monitor.setCursorPos(1, h)
- monitor.clearLine()
- local msg = string.format("(Detail view closes in %ds)", DETAIL_TIMEOUT)
- local x = math.floor((w - #msg) / 2)
- if x < 1 then x = 1 end
- monitor.setCursorPos(x, h)
- monitor.setTextColor(colors.gray)
- monitor.write(msg)
- end
- --------------------
- -- TIMERS & MAIN LOOP
- --------------------
- local scanTimeLeft = SCAN_INTERVAL
- local equipmentData, builderData, nonbuilderData
- local function updateCountdownLine()
- local w, _ = monitor.getSize()
- monitor.setCursorPos(1, 3)
- monitor.clearLine()
- if detailMode then
- local msg = string.format("Detail closes in %ds", detailTimeLeft)
- local x = math.floor((w - #msg) / 2)
- if x < 1 then x = 1 end
- monitor.setCursorPos(x, 3)
- monitor.write(msg)
- else
- local msg = string.format("Next scan in %ds", scanTimeLeft)
- local x = math.floor((w - #msg) / 2)
- if x < 1 then x = 1 end
- monitor.setCursorPos(x, 3)
- monitor.write(msg)
- end
- end
- local function runScan()
- scanTimeLeft = SCAN_INTERVAL
- equipmentData, builderData, nonbuilderData = processRequests()
- local all = flattenData(equipmentData, builderData, nonbuilderData)
- if #all == 0 then
- displayHappyDance()
- elseif not detailMode then
- displayTileMenu(all)
- end
- end
- drawBanner()
- displayLegend()
- runScan()
- local function countdownLoop()
- while true do
- sleep(1)
- if detailMode then
- detailTimeLeft = math.max(0, detailTimeLeft - 1)
- if detailTimeLeft <= 0 then
- detailMode = false
- detailRequest = nil
- detailTimeLeft = 0
- local all = flattenData(equipmentData, builderData, nonbuilderData)
- displayTileMenu(all)
- end
- else
- scanTimeLeft = math.max(0, scanTimeLeft - 1)
- if scanTimeLeft <= 0 then
- runScan()
- scanTimeLeft = SCAN_INTERVAL
- end
- end
- updateCountdownLine()
- end
- end
- local function eventLoop()
- while true do
- local ev = { os.pullEvent() }
- if ev[1] == "monitor_touch" then
- local _, touchX, touchY = ev[2], ev[3], ev[4]
- if detailMode then
- if detailToggleButton and touchY == detailToggleButton.y then
- toggleSkipOption(detailRequest)
- detailRequest.skip = not detailRequest.skip
- if detailRequest.skip then
- detailRequest.skipReason = "Manually added skip pattern: " .. detailRequest.name
- else
- detailRequest.skipReason = nil
- end
- detailTimeLeft = DETAIL_TIMEOUT
- displayDetailScreen(detailRequest)
- updateCountdownLine()
- else
- detailMode = false
- detailRequest = nil
- detailTimeLeft = 0
- local all = flattenData(equipmentData, builderData, nonbuilderData)
- displayTileMenu(all)
- updateCountdownLine()
- end
- else
- for _, tile in ipairs(tilePositions) do
- if touchX >= tile.x1 and touchX <= tile.x2 and touchY >= tile.y1 and touchY <= tile.y2 then
- displayDetailScreen(tile.requestRef)
- detailMode = true
- detailTimeLeft = DETAIL_TIMEOUT
- updateCountdownLine()
- break
- end
- end
- end
- end
- end
- end
- parallel.waitForAny(countdownLoop, eventLoop)
- ------------------------------------------------------------
- -- End of AE2ColonyWarehouse Script
- ------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment