-
-
Save VentedSun/3e3e154dfdd0417a1814f7a21d455bc0 to your computer and use it in GitHub Desktop.
Minecolonies x ComputerCraft (CC:Tweaked) x Advanced Peripherals x ME/RS script to automatically fulfill open work requests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ---@diagnostic disable: undefined-global | |
| --++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- | |
| --** ULTIMATE CC X MINECOLONIES PROGRAM **-- | |
| --++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- | |
| ---------------------------------------------------------------------------- | |
| ---------------------------------------------------------------------------- | |
| --* VARIABLES | |
| ---------------------------------------------------------------------------- | |
| local refreshInterval = 10 | |
| local bShowInGameLog = false -- Set to true for detailed in-game terminal logs | |
| local logFileName = "CCxM" | |
| ---------------------------------------------------------------------------- | |
| --* LOG (FATAL ERROR WARN_ INFO_ DEBUG TRACE) | |
| ---------------------------------------------------------------------------- | |
| local VERSION = 1.21 -- Version incremented to exclude gold equipment (non-paxel) | |
| local logCounter = 0 | |
| function logToFile(message, level, bPrint) | |
| level = level or "INFO_" | |
| bPrint = bPrint or bShowInGameLog | |
| local logFolder = logFileName .. "_logs" | |
| local logFilePath = logFolder .. "/" .. logFileName .. "_log_latest.txt" | |
| if not fs.exists(logFolder) then | |
| local success, err = pcall(function() fs.makeDir(logFolder) end) | |
| if not success then | |
| print(string.format("Failed to create log folder: %s", err)) | |
| return | |
| end | |
| end | |
| local success, err = pcall(function() | |
| local logFile = fs.open(logFilePath, "a") | |
| if logFile then | |
| logFile.writeLine(string.format("[%s] [%s] %s", os.date("%Y-%m-%d %H:%M:%S"), level, message)) | |
| logFile.close() | |
| else | |
| error("Unable to open log file.") | |
| end | |
| end) | |
| if not success then | |
| print(string.format("Error writing to log file: %s", err)) | |
| return | |
| end | |
| if bPrint then | |
| if level == "ERROR" or level == "FATAL" then print("") end | |
| print(string.format("[%s] %s", level, message)) | |
| if level == "ERROR" or level == "FATAL" then print("") end | |
| end | |
| logCounter = (logCounter or 0) + 1 | |
| if logCounter >= 250 then | |
| rotateLogs(logFolder, logFilePath) | |
| logCounter = 0 | |
| end | |
| end | |
| function rotateLogs(logFolder, logFilePath) | |
| local maxLogs = 5 | |
| local timestamp = os.date("%Y-%m-%d_%H-%M-%S") | |
| local archivedLog = string.format("%s/log_%s.txt", logFolder, timestamp) | |
| local success, err = pcall(function() | |
| if fs.exists(logFilePath) then | |
| fs.move(logFilePath, archivedLog) | |
| end | |
| end) | |
| if not success then | |
| print(string.format("Failed to rotate log file: %s", err)) | |
| return | |
| end | |
| local logs = fs.list(logFolder) | |
| table.sort(logs) | |
| while #logs > maxLogs do | |
| local oldestLog = logFolder .. "/" .. logs[1] | |
| local deleteSuccess, deleteErr = pcall(function() fs.delete(oldestLog) end) | |
| if not deleteSuccess then | |
| print(string.format("Failed to delete old log file: %s", deleteErr)) | |
| break | |
| end | |
| table.remove(logs, 1) | |
| end | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* ERROR-HANDLING FUNCTION | |
| ---------------------------------------------------------------------------- | |
| function safeCall(func, ...) | |
| local success, result = pcall(func, ...) | |
| if not success then | |
| if type(result) == "string" and result == "Terminated" then | |
| error("Terminated", 0) | |
| end | |
| logToFile((result or "Unknown error"), "ERROR", true) | |
| return false, result | |
| end | |
| return true, result | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* NBT TO SNBT STRING CONVERSION HELPER (SIMPLIFIED) | |
| ---------------------------------------------------------------------------- | |
| function convertNbtToSnbtString(nbtTable) | |
| if type(nbtTable) ~= "table" then | |
| logToFile("convertNbtToSnbtString: Input is not a table, returning nil. Type: " .. type(nbtTable), "WARN_") | |
| return nil | |
| end | |
| if next(nbtTable) == nil then | |
| logToFile("convertNbtToSnbtString: Input table is empty, returning empty SNBT string '{}'.", "DEBUG") | |
| return "{}" | |
| end | |
| local parts = {} | |
| for key, value in pairs(nbtTable) do | |
| local keyStr = tostring(key) | |
| if type(value) == "string" then | |
| local escapedValue = string.gsub(value, "\\", "\\\\") | |
| escapedValue = string.gsub(escapedValue, "\"", "\\\"") | |
| table.insert(parts, string.format("%s:\"%s\"", keyStr, escapedValue)) | |
| elseif type(value) == "number" then | |
| table.insert(parts, string.format("%s:%s", keyStr, tostring(value))) | |
| elseif type(value) == "boolean" then | |
| table.insert(parts, string.format("%s:%s", keyStr, tostring(value))) | |
| elseif keyStr == "textureData" and type(value) == "table" then | |
| local textureParts = {} | |
| for texKey, texValue in pairs(value) do | |
| if type(texValue) == "string" then | |
| local escapedTexKey = string.gsub(tostring(texKey), "\\", "\\\\") | |
| escapedTexKey = string.gsub(escapedTexKey, "\"", "\\\"") | |
| local escapedTexValue = string.gsub(texValue, "\\", "\\\\") | |
| escapedTexValue = string.gsub(escapedTexValue, "\"", "\\\"") | |
| table.insert(textureParts, string.format("\"%s\":\"%s\"", escapedTexKey, escapedTexValue)) | |
| else | |
| logToFile("convertNbtToSnbtString: Non-string value found in textureData for key '" .. tostring(texKey) .. "'. Skipping.", "WARN_") | |
| end | |
| end | |
| table.insert(parts, string.format("%s:{%s}", keyStr, table.concat(textureParts, ","))) | |
| else | |
| logToFile(string.format("convertNbtToSnbtString: Unsupported type '%s' for key '%s' or unhandled complex table. Value: %s", type(value), keyStr, tableToString(value)), "WARN_") | |
| end | |
| end | |
| local snbtString = "{" .. table.concat(parts, ",") .. "}" | |
| logToFile("convertNbtToSnbtString: Converted NBT table to SNBT string: " .. snbtString, "TRACE") | |
| return snbtString | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* GENERIC HELPER FUNCTIONS | |
| ---------------------------------------------------------------------------- | |
| local function trimLeadingWhitespace(str) | |
| return str:match("^%s*(.*)$") | |
| end | |
| function getLastWord(str) | |
| local words = {} | |
| for word in string.gmatch(str, "%S+") do | |
| table.insert(words, word) | |
| end | |
| return words[#words] or "" | |
| end | |
| function tableToString(tbl, indent) | |
| indent = indent or 0 | |
| if type(tbl) ~= "table" then return tostring(tbl) end | |
| local result_string = string.rep(" ", indent) .. "{\n" | |
| for key, value in pairs(tbl) do | |
| local formattedKey = type(key) == "string" and string.format("%q", key) or tostring(key) | |
| if type(value) == "table" then | |
| result_string = result_string .. | |
| string.rep(" ", indent + 1) .. | |
| "[" .. formattedKey .. "] = " .. tableToString(value, indent + 1) .. ",\n" | |
| else | |
| local formattedValue = type(value) == "string" and string.format("%q", value) or tostring(value) | |
| result_string = result_string .. | |
| string.rep(" ", indent + 1) .. "[" .. formattedKey .. "] = " .. formattedValue .. ",\n" | |
| end | |
| end | |
| return result_string .. string.rep(" ", indent) .. "}" | |
| end | |
| function writeToLogFile(fileName, equipment_list, builder_list_standard, builder_list_domum, others_list) | |
| local success, file_or_err = pcall(io.open, fileName, "w") | |
| if not success then | |
| logToFile("Could not open file for writing: " .. fileName .. " Error: " .. tostring(file_or_err), "ERROR", true) | |
| return | |
| end | |
| local file = file_or_err | |
| file:write("Equipment List:\n") | |
| file:write(tableToString(equipment_list) .. "\n\n") | |
| file:write("Standard Builder List:\n") | |
| file:write(tableToString(builder_list_standard) .. "\n\n") | |
| file:write("Domum Builder List:\n") | |
| file:write(tableToString(builder_list_domum) .. "\n\n") | |
| file:write("Others List:\n") | |
| file:write(tableToString(others_list) .. "\n\n") | |
| file:close() | |
| end | |
| local function ensure_width(line, width, pos) | |
| width = width or term.getSize() | |
| line = tostring(line) | |
| if pos ~= "left" then | |
| if #line > width then | |
| line = line:sub(1, width) | |
| end | |
| if #line < width then | |
| line = line .. (" "):rep(width - #line) | |
| end | |
| end | |
| return line | |
| end | |
| --[[---------------------------------------------------------------------------- | |
| --* VANILLA EQUIPMENT ID MAPPING | |
| ----------------------------------------------------------------------------]] | |
| local function getBaseEquipmentType(requestName) | |
| local knownTypes = { | |
| "Helmet", "Chestplate", "Leggings", "Boots", | |
| "Sword", "Pickaxe", "Axe", "Shovel", "Hoe", "Shears", "Bow" | |
| } | |
| local lowerRequestName = string.lower(requestName or "") | |
| for _, typeName in ipairs(knownTypes) do | |
| if string.find(lowerRequestName, string.lower(typeName)) then | |
| return typeName | |
| end | |
| end | |
| logToFile("getBaseEquipmentType: Could not determine base type from '" .. tostring(requestName) .. "'", "DEBUG") | |
| return getLastWord(requestName or "") | |
| end | |
| local function getVanillaEquivalentId(baseEquipmentType, materialLevel) | |
| if not baseEquipmentType or baseEquipmentType == "" or not materialLevel then return nil end | |
| local baseTypeLower = string.lower(baseEquipmentType) | |
| local materialLower = string.lower(materialLevel) | |
| local vanillaPrefix = "minecraft:" | |
| local materialPrefix = "" | |
| local itemSuffix = "" | |
| -- Map materialLevel to the prefix used in vanilla item IDs | |
| if materialLower == "diamond" then materialPrefix = "diamond_" | |
| elseif materialLower == "iron" then materialPrefix = "iron_" | |
| elseif materialLower == "chain" or materialLower == "chainmail" then materialPrefix = "chainmail_" | |
| elseif materialLower == "stone" then materialPrefix = "stone_" | |
| elseif materialLower == "wood" or materialLower == "wooden" then materialPrefix = "wooden_" | |
| -- REMOVED: elseif materialLower == "gold" or materialLower == "golden" then materialPrefix = "golden_" | |
| else | |
| logToFile("getVanillaEquivalentId: Material level '" .. materialLevel .. "' not mapped for standard vanilla items (excluding gold).", "DEBUG") | |
| return nil -- Material not mapped for standard vanilla items (or it's gold) | |
| end | |
| if baseTypeLower == "helmet" then itemSuffix = "helmet" | |
| elseif baseTypeLower == "chestplate" then itemSuffix = "chestplate" | |
| elseif baseTypeLower == "leggings" then itemSuffix = "leggings" | |
| elseif baseTypeLower == "boots" then itemSuffix = "boots" | |
| elseif baseTypeLower == "sword" then itemSuffix = "sword" | |
| elseif baseTypeLower == "pickaxe" then itemSuffix = "pickaxe" | |
| elseif baseTypeLower == "axe" then itemSuffix = "axe" | |
| elseif baseTypeLower == "shovel" then itemSuffix = "shovel" | |
| elseif baseTypeLower == "hoe" then itemSuffix = "hoe" | |
| elseif baseTypeLower == "bow" then return vanillaPrefix .. "bow" | |
| else | |
| logToFile("getVanillaEquivalentId: Unsupported base equipment type '" .. baseEquipmentType .. "' for vanilla mapping.", "DEBUG") | |
| return nil | |
| end | |
| if (materialPrefix == "chainmail_") and | |
| (itemSuffix == "sword" or itemSuffix == "pickaxe" or itemSuffix == "axe" or | |
| itemSuffix == "shovel" or itemSuffix == "hoe") then | |
| logToFile("getVanillaEquivalentId: Chainmail tools like '" .. itemSuffix .. "' do not exist in vanilla.", "DEBUG") | |
| return nil | |
| end | |
| if materialLower == "leather" and (itemSuffix == "helmet" or itemSuffix == "chestplate" or itemSuffix == "leggings" or itemSuffix == "boots") then | |
| return vanillaPrefix .. "leather_" .. itemSuffix | |
| end | |
| return vanillaPrefix .. materialPrefix .. itemSuffix | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* CHECK REQUIREMENTS | |
| -- ... (This section is unchanged) | |
| ---------------------------------------------------------------------------- | |
| local monitor = peripheral.find("monitor") | |
| local colony | |
| local bridge | |
| local storage | |
| function getPeripheral(type) | |
| local p = peripheral.find(type) | |
| if not p then | |
| logToFile(type .. " peripheral not found.", "WARN_") | |
| return nil | |
| end | |
| logToFile(type .. " peripheral found.") | |
| return p | |
| end | |
| function updatePeripheralMonitor() | |
| monitor = getPeripheral("monitor") | |
| return monitor ~= nil | |
| end | |
| function checkMonitorSize() | |
| if not monitor then return false end | |
| monitor.setTextScale(0.5) | |
| local width, height = monitor.getSize() | |
| if width < 79 or height < 38 then | |
| logToFile("Use more Monitors! (min 4x3)", "WARN_") | |
| return false | |
| end | |
| return true | |
| end | |
| function updatePeripheralColonyIntegrator() | |
| colony = getPeripheral("colonyIntegrator") | |
| return colony ~= nil | |
| end | |
| function getStorageBridge() | |
| local meBridgeP = getPeripheral("meBridge") | |
| if meBridgeP then return meBridgeP end | |
| local rsBridgeP = getPeripheral("rsBridge") | |
| if rsBridgeP then return rsBridgeP end | |
| logToFile("Neither ME Storage Bridge nor RS Storage Bridge found.", "WARN_") | |
| return nil | |
| end | |
| function updatePeripheralStorageBridge() | |
| bridge = getStorageBridge() | |
| return bridge ~= nil | |
| end | |
| function autodetectStorage() | |
| for _, side in pairs(peripheral.getNames()) do | |
| if peripheral.hasType(side, "inventory") then | |
| logToFile("Storage detected on " .. side) | |
| return side | |
| end | |
| end | |
| logToFile("No storage container detected!", "WARN_") | |
| return nil | |
| end | |
| function updatePeripheralStorage() | |
| storage = autodetectStorage() | |
| return storage ~= nil | |
| end | |
| ---------------------------------------------------------------------------- | |
| -- MONITOR DASHBOARD NAME | |
| -- ... (This section is unchanged) | |
| ---------------------------------------------------------------------------- | |
| local dashboardName = "MineColonies DASHBOARD" | |
| local rainbowColors = { | |
| colors.red, colors.orange, colors.yellow, | |
| colors.green, colors.cyan, colors.blue, | |
| colors.purple, colors.magenta, colors.pink | |
| } | |
| function monitorDisplayDashboardName(mon, y, text, colorsTable) | |
| if not mon then return end | |
| local w, _ = mon.getSize() | |
| local x = math.floor((w - #text) / 2) + 1 | |
| for i = 1, #text do | |
| local char = text:sub(i, i) | |
| local colorIdx = ((i-1) % #colorsTable) + 1 | |
| mon.setTextColor(colorsTable[colorIdx]) | |
| mon.setCursorPos(x + i - 1, y) | |
| mon.write(char) | |
| end | |
| end | |
| function dashboardGenerateTransitionColors(progress, length) | |
| local colorsTable = {} | |
| local threshold = math.floor(progress * length) | |
| for i = 1, length do | |
| colorsTable[i] = (i <= threshold) and colors.orange or colors.white | |
| end | |
| return colorsTable | |
| end | |
| function dashboardGenerateRainbowColors(baseColors, length) | |
| local result = {} | |
| for i = 1, length do | |
| result[i] = baseColors[((i - 1) % #baseColors) + 1] | |
| end | |
| return result | |
| end | |
| function monitorDashboardName() | |
| if not monitor then return end | |
| local localStartTime = os.clock() | |
| local y = 1 | |
| local animationCycleDuration = 3.0 | |
| local transitionEndTime = animationCycleDuration * 0.7 | |
| while true do | |
| local currentElapsedTime = os.clock() - localStartTime | |
| if currentElapsedTime < transitionEndTime then | |
| local progress = currentElapsedTime / transitionEndTime | |
| local colorsTable = dashboardGenerateTransitionColors(progress, #dashboardName) | |
| monitorDisplayDashboardName(monitor, y, dashboardName, colorsTable) | |
| else | |
| local rainbowPhaseDuration = animationCycleDuration - transitionEndTime | |
| local rainbowProgress = (currentElapsedTime - transitionEndTime) / rainbowPhaseDuration | |
| local rainbowIdxStart = math.floor(rainbowProgress * #rainbowColors * 2) | |
| local tempRainbowColors = {} | |
| for i=1, #dashboardName do | |
| table.insert(tempRainbowColors, rainbowColors[ ((rainbowIdxStart + i -1) % #rainbowColors) +1 ]) | |
| end | |
| monitorDisplayDashboardName(monitor, y, dashboardName, tempRainbowColors) | |
| end | |
| if currentElapsedTime >= animationCycleDuration then | |
| break | |
| end | |
| sleep(0.05) | |
| end | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* ART | |
| -- ... (This section is unchanged) | |
| ---------------------------------------------------------------------------- | |
| local artUltimateCCxM_Logo = [[ | |
| _ _ _ _ _ _ | |
| | | | | | |_(_)_ __ ___ __ _| |_ ___ | |
| | | | | | __| | '_ ` _ \ / _` | __/ _ \ | |
| | |_| | | |_| | | | | | | (_| | || __/ | |
| \____|_____|_|_| |_|___|_____|\__\___| | |
| / ___/ ___|__ __| \/ (_)_ __ ___ | |
| | | | | \ \/ /| |\/| | | '_ \ / _ \ | |
| | |__| |___ > < | | | | | | | | __/ | |
| \____\____|/_/\_\|_| |_|_|_| |_|\___| | |
| / ___|___ | | ___ _ __ (_) ___ ___ | |
| | | / _ \| |/ _ \| '_ \| |/ _ \/ __| | |
| | |__| (_) | | (_) | | | | | __/\__ \ | |
| \____\___/|_|\___/|_| \_| |___/||___/ | |
| ]] | |
| ---------------------------------------------------------------------------- | |
| --* MONITOR OR TERMINAL OUTPUT | |
| -- ... (This section is unchanged) | |
| ---------------------------------------------------------------------------- | |
| function resetDefault(screen) | |
| if not screen then return end | |
| screen.setTextColor(colors.white) | |
| screen.setBackgroundColor(colors.black) | |
| screen.setCursorPos(1, 1) | |
| screen.clear() | |
| end | |
| function drawLoadingBar(screen, x, y, width, progress, bgColor, barColor) | |
| if not screen then return end | |
| local originalBg = screen.getBackgroundColor() | |
| local originalFg = screen.getTextColor() | |
| screen.setBackgroundColor(bgColor or colors.gray) | |
| screen.setCursorPos(x, y) | |
| screen.write(string.rep(" ", width)) | |
| local filledWidth = math.floor(progress * width) | |
| if filledWidth > 0 then | |
| screen.setCursorPos(x, y) | |
| screen.setBackgroundColor(barColor or colors.green) | |
| screen.write(string.rep(" ", filledWidth)) | |
| end | |
| screen.setBackgroundColor(originalBg) | |
| screen.setTextColor(originalFg) | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* MONITOR OUTPUT | |
| -- ... (This section is unchanged) | |
| ---------------------------------------------------------------------------- | |
| function monitorDisplayArt(asciiArt, mon_) | |
| if not mon_ then return end | |
| resetDefault(mon_) | |
| mon_.setTextScale(1) | |
| local x, y = 1, 2 | |
| for line in asciiArt:gmatch("[^\n]+") do | |
| mon_.setCursorPos(x, y) | |
| mon_.write(line) | |
| y = y + 1 | |
| end | |
| end | |
| function monitorLoadingAnimation() | |
| if not monitor then return end | |
| resetDefault(monitor) | |
| monitor.setTextScale(1) | |
| local w, h = monitor.getSize() | |
| local barWidth = math.floor(w * 0.9) | |
| local barX = math.floor((w - barWidth) / 2) + 1 | |
| local barY = 17 | |
| monitorDisplayArt(artUltimateCCxM_Logo, monitor) | |
| local barSpeed = 30 | |
| for i = 0, barSpeed do | |
| drawLoadingBar(monitor, barX, barY, barWidth, i / barSpeed, colors.gray, colors.orange) | |
| sleep(0.1) | |
| end | |
| resetDefault(monitor) | |
| monitor.setTextScale(0.5) | |
| end | |
| function monitorPrintText(y, pos, text, ...) | |
| if not monitor then return end | |
| local w, h = monitor.getSize() | |
| local fg = monitor.getTextColor() | |
| local bg = monitor.getBackgroundColor() | |
| text = tostring(text) | |
| local x_coord = 1 | |
| if pos == "left" then | |
| x_coord = 4 | |
| text = ensure_width(text, math.floor(w / 2) - 2, pos) | |
| elseif pos == "center" then | |
| text = ensure_width(text, w - 2, pos) | |
| x_coord = math.floor((w - #text) / 2) + 1 | |
| elseif pos == "right" then | |
| text = ensure_width(text, math.floor(w / 2) - 2, pos) | |
| x_coord = w - #text - 2 | |
| elseif pos == "middle" then | |
| text = ensure_width(text, w - 2, pos) | |
| x_coord = math.floor((w - #text) / 2) + 1 | |
| y = math.floor(h / 2) - 2 | |
| end | |
| if select("#", ...) > 0 then monitor.setTextColor(select(1, ...)) end | |
| if select("#", ...) > 1 then monitor.setBackgroundColor(select(2, ...)) end | |
| monitor.setCursorPos(x_coord, y) | |
| monitor.write(text) | |
| monitor.setTextColor(fg) | |
| monitor.setBackgroundColor(bg) | |
| end | |
| function drawBox(xMin, xMax, yMin, yMax, title, bcolor, tcolor) | |
| if not monitor then return end | |
| monitor.setBackgroundColor(bcolor) | |
| for xPos = xMin, xMax, 1 do | |
| monitor.setCursorPos(xPos, yMin) | |
| monitor.write(" ") | |
| end | |
| for yPos = yMin, yMax, 1 do | |
| monitor.setCursorPos(xMin, yPos) | |
| monitor.write(" ") | |
| monitor.setCursorPos(xMax, yPos) | |
| monitor.write(" ") | |
| end | |
| for xPos = xMin, xMax, 1 do | |
| monitor.setCursorPos(xPos, yMax) | |
| monitor.write(" ") | |
| end | |
| monitor.setCursorPos(xMin + 2, yMin) | |
| monitor.setBackgroundColor(colors.black) | |
| monitor.setTextColor(tcolor) | |
| monitor.write(" ") | |
| monitor.write(title) | |
| monitor.write(" ") | |
| monitor.setTextColor(colors.white) | |
| monitor.setBackgroundColor(colors.black) | |
| end | |
| function monitorDashboardRequests(equipment_list, builder_list_standard, builder_list_domum, others_list) | |
| if not monitor then return end | |
| local x_size, y_size = monitor.getSize() | |
| local equipment_count = #equipment_list | |
| local standard_builder_count = #builder_list_standard | |
| local domum_builder_count = #builder_list_domum | |
| local others_count = #others_list | |
| local actual_standard_builder_lines = math.ceil(standard_builder_count / 2) | |
| local actual_domum_builder_lines = domum_builder_count | |
| local actual_builder_lines = actual_standard_builder_lines + actual_domum_builder_lines | |
| if actual_standard_builder_lines > 0 and actual_domum_builder_lines > 0 then | |
| actual_builder_lines = actual_builder_lines + 1 | |
| end | |
| local estimated_box_height = (equipment_count + actual_builder_lines + others_count) + 11 | |
| estimated_box_height = math.min(estimated_box_height, y_size -1) | |
| drawBox(2, x_size - 1, 3, estimated_box_height, "REQUESTS", colors.gray, colors.purple) | |
| monitorPrintText(5, "center", "Builder", colors.orange) | |
| local current_y = 6 | |
| local i = 1 | |
| while i <= standard_builder_count do | |
| if current_y >= estimated_box_height -1 then break end | |
| local currentItem = builder_list_standard[i] | |
| local nextItem = builder_list_standard[i+1] | |
| if nextItem and (i+1 <= standard_builder_count) then | |
| monitorPrintText(current_y, "left", (currentItem.provided .. "/" .. currentItem.count .. " " .. currentItem.name), currentItem.displayColor) | |
| monitorPrintText(current_y, "right", (nextItem.provided .. "/" .. nextItem.count .. " " .. nextItem.name), nextItem.displayColor) | |
| i = i + 2 | |
| else | |
| monitorPrintText(current_y, "left", (currentItem.provided .. "/" .. currentItem.count .. " " .. currentItem.name), currentItem.displayColor) | |
| i = i + 1 | |
| end | |
| current_y = current_y + 1 | |
| end | |
| if actual_standard_builder_lines > 0 and actual_domum_builder_lines > 0 then | |
| if current_y < estimated_box_height -1 then | |
| current_y = current_y + 1 | |
| end | |
| end | |
| for _, item in ipairs(builder_list_domum) do | |
| if current_y >= estimated_box_height -1 then break end | |
| monitorPrintText(current_y, "left", (item.provided .. "/" .. item.count .. " " .. item.name), item.displayColor) | |
| current_y = current_y + 1 | |
| end | |
| current_y = current_y + 1 | |
| if current_y < estimated_box_height -1 then | |
| monitorPrintText(current_y, "center", "Equipment", colors.orange) | |
| current_y = current_y + 1 | |
| for _, item in ipairs(equipment_list) do | |
| if current_y >= estimated_box_height -1 then break end | |
| monitorPrintText(current_y, "left", item.name, item.displayColor) | |
| monitorPrintText(current_y, "right", item.target, colors.lightGray) | |
| current_y = current_y + 1 | |
| end | |
| end | |
| current_y = current_y + 1 | |
| if current_y < estimated_box_height -1 then | |
| monitorPrintText(current_y, "center", "Other", colors.orange) | |
| current_y = current_y + 1 | |
| for _, item in ipairs(others_list) do | |
| if current_y >= estimated_box_height -1 then break end | |
| monitorPrintText(current_y, "left", (item.provided .. "/" .. item.count .. " " .. item.name), item.displayColor) | |
| monitorPrintText(current_y, "right", item.target, colors.lightGray) | |
| current_y = current_y + 1 | |
| end | |
| end | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* TERMINAL OUTPUT | |
| -- ... (This section is unchanged) | |
| ---------------------------------------------------------------------------- | |
| local termWidth, termHeight | |
| local needTermDrawRequirements = true | |
| local needTermDrawRequirements_executed = false | |
| function termDisplayArt(asciiArt) | |
| term.clear() | |
| local x, y = 6, 2 | |
| for line in asciiArt:gmatch("[^\n]+") do | |
| term.setCursorPos(x, y) | |
| term.write(line) | |
| y = y + 1 | |
| end | |
| end | |
| function termLoadingAnimation() | |
| resetDefault(term) | |
| termWidth, termHeight = term.getSize() | |
| local barWidth = math.floor(termWidth * 0.8) | |
| local barX = math.floor((termWidth - barWidth) / 2) + 1 | |
| local barY = math.floor(termHeight * 0.9) | |
| term.setTextColor(colors.orange) | |
| term.setCursorPos(1, 1) | |
| termDisplayArt(artUltimateCCxM_Logo) | |
| local barSpeed = 25 | |
| for i = 0, barSpeed do | |
| drawLoadingBar(term, barX, barY, barWidth, i / barSpeed, colors.gray, colors.orange) | |
| sleep(0.1) | |
| end | |
| resetDefault(term) | |
| end | |
| function termDrawProgramReq_helper(y, isRequirementMet) | |
| if isRequirementMet then | |
| term.setTextColor(colors.green) | |
| term.setCursorPos(49, y) | |
| term.write("[O]") | |
| else | |
| term.setTextColor(colors.red) | |
| term.setCursorPos(49, y) | |
| term.write("[X]") | |
| end | |
| term.setTextColor(colors.white) | |
| end | |
| function termDrawProgramReq_Header() | |
| termWidth, termHeight = term.getSize() | |
| local text_Divider = "-------------------------------------------------------" | |
| term.setCursorPos(math.floor((termWidth - #text_Divider) / 2) + 1, 4) | |
| term.write(text_Divider) | |
| local text_Requirements = "\187 Program Requirements \171" | |
| term.setCursorPos(math.floor((termWidth - #text_Requirements) / 2) + 1, 2) | |
| textutils.slowWrite(text_Requirements, 16) | |
| end | |
| function termDrawCheckRequirements() | |
| if not needTermDrawRequirements_executed then | |
| term.clear() | |
| termDrawProgramReq_Header() | |
| needTermDrawRequirements_executed = true | |
| end | |
| termWidth, termHeight = term.getSize() | |
| local allRequirementsMet = true | |
| term.setCursorPos(2, 6); term.write("\16 Monitor attached") | |
| if updatePeripheralMonitor() then termDrawProgramReq_helper(6, true) | |
| term.setCursorPos(2, 8); term.write("\16 Monitor size (min 4x3)") | |
| if checkMonitorSize() then termDrawProgramReq_helper(8, true) else termDrawProgramReq_helper(8, false); allRequirementsMet = false end | |
| else | |
| termDrawProgramReq_helper(6, false); allRequirementsMet = false | |
| term.setCursorPos(2, 8); term.write("\16 Monitor size (min 4x3)") | |
| termDrawProgramReq_helper(8, false); allRequirementsMet = false | |
| end | |
| term.setCursorPos(2, 10); term.write("\16 Colony Integrator attached") | |
| if updatePeripheralColonyIntegrator() then termDrawProgramReq_helper(10, true) | |
| term.setCursorPos(2, 12); term.write("\16 Colony Integrator in a colony") | |
| if colony and colony.isInColony() then termDrawProgramReq_helper(12, true) else termDrawProgramReq_helper(12, false); allRequirementsMet = false end | |
| else | |
| termDrawProgramReq_helper(10, false); allRequirementsMet = false | |
| term.setCursorPos(2, 12); term.write("\16 Colony Integrator in a colony") | |
| termDrawProgramReq_helper(12, false); allRequirementsMet = false | |
| end | |
| term.setCursorPos(2, 14); term.write("\16 ME or RS Bridge attached") | |
| if updatePeripheralStorageBridge() then termDrawProgramReq_helper(14, true) else termDrawProgramReq_helper(14, false); allRequirementsMet = false end | |
| term.setCursorPos(2, 16); term.write("\16 Storage/Warehouse attached") | |
| if updatePeripheralStorage() then termDrawProgramReq_helper(16, true) else termDrawProgramReq_helper(16, false); allRequirementsMet = false end | |
| if allRequirementsMet then | |
| needTermDrawRequirements = false | |
| needTermDrawRequirements_executed = false | |
| local text_Fullfilled = "Requirements fullfilled" | |
| term.setCursorPos(math.floor((termWidth - #text_Fullfilled) / 2), 19) | |
| term.setTextColor(colors.green) | |
| sleep(0.5); textutils.slowWrite(text_Fullfilled, 16); textutils.slowWrite(" . . .", 5); sleep(1) | |
| resetDefault(term) | |
| return true | |
| end | |
| return false | |
| end | |
| function termShowLog() | |
| termWidth, termHeight = term.getSize() | |
| term.setCursorPos(1, 1); term.clearLine() | |
| term.setCursorPos(1, 2); term.clearLine() | |
| term.setCursorPos(1, 3); term.clearLine() | |
| local text_Divider = "-------------------------------------------------------" | |
| term.setCursorPos(math.floor((termWidth - #text_Divider) / 2) + 1, 4) | |
| term.write(text_Divider) | |
| local text_LogTitle = "\187 MineColonies Logs \171 v" .. VERSION | |
| term.setCursorPos(math.floor((termWidth - #text_LogTitle) / 2) + 1, 2) | |
| textutils.slowWrite(text_LogTitle, 16) | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* MINECOLONIES | |
| ---------------------------------------------------------------------------- | |
| function removeNamespace(itemName) | |
| if type(itemName) ~= "string" then return tostring(itemName) end | |
| local colonIndex = string.find(itemName, ":") | |
| if colonIndex then | |
| return string.sub(itemName, colonIndex + 1) | |
| end | |
| return itemName | |
| end | |
| local function isEquipment(desc) | |
| if type(desc) ~= "string" then return false end | |
| local equipmentKeywords = { | |
| "Sword ", "Bow ", "Pickaxe ", "Axe ", "Shovel ", "Hoe ", "Shears ", | |
| "Helmet ", "Chestplate ", "Leggings ", "Boots " | |
| } | |
| for _, keyword in ipairs(equipmentKeywords) do | |
| if string.find(desc, keyword) then | |
| return true | |
| end | |
| end | |
| return false | |
| end | |
| function colonyCategorizeRequests() | |
| local equipment_list = {} | |
| local builder_list_standard = {} | |
| local builder_list_domum = {} | |
| local others_list = {} | |
| if not colony then | |
| logToFile("Colony Integrator not available for categorizing requests.", "WARN_", true) | |
| return equipment_list, builder_list_standard, builder_list_domum, others_list | |
| end | |
| local success, requests = safeCall(colony.getRequests) | |
| if not success or not requests or #requests == 0 then | |
| logToFile("Failed to get colony requests or no requests found.", "INFO_") | |
| return equipment_list, builder_list_standard, builder_list_domum, others_list | |
| end | |
| for _, req in ipairs(requests) do | |
| if not req.items or not req.items[1] then | |
| logToFile("Skipping request due to missing item data: " .. tableToString(req), "DEBUG") | |
| goto continue_categorize_loop | |
| end | |
| local name_from_req = req.name or "Unknown" | |
| local target = req.target or "" | |
| local desc = req.desc or "" | |
| local count = req.count or 0 | |
| local item_displayName = trimLeadingWhitespace(req.items[1].displayName or name_from_req) | |
| local item_name_raw = req.items[1].name or "" | |
| local itemIsEquipment = isEquipment(desc) | |
| local nbtToStore = req.items[1].nbt | |
| local fingerprintToStore = req.items[1].fingerprint | |
| local formattedName = name_from_req | |
| local isDomumOrnamentumItem = string.find(item_name_raw, "domum_ornamentum:", 1, true) == 1 | |
| local itemEntry = { | |
| name = formattedName, | |
| target = target, | |
| count = count, | |
| item_displayName = item_displayName, | |
| item_name_raw = item_name_raw, | |
| item_name = item_name_raw, | |
| desc = desc, | |
| provided = 0, | |
| isCraftable = false, | |
| equipment = itemIsEquipment, | |
| displayColor = colors.white, | |
| level = "Any Level", | |
| nbtData = nbtToStore, | |
| fingerprint = fingerprintToStore | |
| } | |
| if string.find(target, "Builder", 1, true) then | |
| if isDomumOrnamentumItem then | |
| local blockType = removeNamespace(item_name_raw) | |
| local textureData = nbtToStore and nbtToStore["textureData"] | |
| local textureDataSize = 0 | |
| if type(textureData) == 'table' then | |
| for _ in pairs(textureData) do textureDataSize = textureDataSize + 1 end | |
| end | |
| if textureDataSize == 1 and nbtToStore and nbtToStore.type then | |
| local singleMaterial = "UnknownMaterial" | |
| if type(textureData) == 'table' then | |
| for _, mat_val in pairs(textureData) do singleMaterial = removeNamespace(tostring(mat_val)); break end | |
| end | |
| local style = tostring(nbtToStore.type):gsub("_", " ") :gsub("^%l", string.upper):gsub("%s%l", function(c) return string.upper(c) end) | |
| itemEntry.name = string.format("%s (%s, %s)", item_displayName, style, singleMaterial) | |
| elseif textureDataSize == 2 and nbtToStore then | |
| local materialsExtracted = {} | |
| if type(textureData) == 'table' then | |
| local matKeys = {} | |
| for k_mat in pairs(textureData) do table.insert(matKeys, k_mat) end | |
| if matKeys[1] then table.insert(materialsExtracted, removeNamespace(tostring(textureData[matKeys[1]]))) end | |
| if matKeys[2] then table.insert(materialsExtracted, removeNamespace(tostring(textureData[matKeys[2]]))) end | |
| end | |
| if #materialsExtracted == 2 then | |
| itemEntry.name = string.format("%s (%s, %s, %s)", item_displayName, blockType, materialsExtracted[1], materialsExtracted[2]) | |
| else | |
| itemEntry.name = string.format("%s (%s, MaterialsErr)", item_displayName, blockType) | |
| logToFile("Domum 2-mat block " .. item_displayName .. " issue extracting 2 materials.", "WARN_") | |
| end | |
| else | |
| itemEntry.name = string.format("%s (%s, NBT_Err)", item_displayName, blockType) | |
| logToFile("Unhandled Domum block: " .. item_displayName .. " textureDataSize: " .. textureDataSize .. " NBT: " .. tableToString(nbtToStore or {}), "WARN_") | |
| end | |
| table.insert(builder_list_domum, itemEntry) | |
| else | |
| itemEntry.name = name_from_req | |
| table.insert(builder_list_standard, itemEntry) | |
| end | |
| elseif itemIsEquipment then | |
| local levelTable = { | |
| ["and with maximal level: Leather"] = "Leather", ["and with maximal level: Stone"] = "Stone", | |
| ["and with maximal level: Chain"] = "Chain", ["and with maximal level: Gold"] = "Gold", | |
| ["and with maximal level: Iron"] = "Iron", ["and with maximal level: Diamond"] = "Diamond", | |
| ["with maximal level: Wood or Gold"] = "Wood or Gold" | |
| } | |
| local extractedLevel = "Any Level" | |
| for pattern, mappedLevel in pairs(levelTable) do | |
| if string.find(desc, pattern) then | |
| extractedLevel = mappedLevel | |
| break | |
| end | |
| end | |
| if extractedLevel == "Any Level" then | |
| if string.find(desc, "Diamond") then extractedLevel = "Diamond" | |
| elseif string.find(desc, "Iron") then extractedLevel = "Iron" | |
| elseif string.find(desc, "Chain") then extractedLevel = "Chain" | |
| elseif string.find(desc, "Stone") then extractedLevel = "Stone" | |
| elseif string.find(desc, "Gold") then extractedLevel = "Gold" | |
| elseif string.find(desc, "Leather") then extractedLevel = "Leather" | |
| elseif string.find(desc, "Wood") then extractedLevel = "Wood" | |
| end | |
| end | |
| itemEntry.level = extractedLevel | |
| itemEntry.name = extractedLevel .. " " .. name_from_req | |
| table.insert(equipment_list, itemEntry) | |
| else | |
| itemEntry.name = name_from_req | |
| table.insert(others_list, itemEntry) | |
| end | |
| ::continue_categorize_loop:: | |
| end | |
| return equipment_list, builder_list_standard, builder_list_domum, others_list | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* STORAGE SYSTEM REQUEST AND SEND | |
| ---------------------------------------------------------------------------- | |
| local b_craftEquipment = true | |
| local item_quantity_field = nil | |
| function equipmentCraft(formatted_request_name, request_level, original_item_id_from_colony) | |
| local baseType = getBaseEquipmentType(formatted_request_name) | |
| if not baseType or baseType == "" then | |
| logToFile("equipmentCraft: Could not determine base equipment type from formatted name: '" .. formatted_request_name .. "'. Not crafting.", "WARN_") | |
| return original_item_id_from_colony, false | |
| end | |
| if baseType == "Bow" then | |
| logToFile("equipmentCraft: Request is for a Bow. Targeting vanilla minecraft:bow.", "INFO_") | |
| return "minecraft:bow", true | |
| end | |
| -- Paxel Substitution Logic | |
| if baseType == "Pickaxe" or baseType == "Axe" or baseType == "Shovel" then | |
| local paxelMaterial = nil | |
| local rl_lower = string.lower(request_level or "") | |
| if rl_lower == "diamond" then paxelMaterial = "diamond" | |
| elseif rl_lower == "iron" then paxelMaterial = "iron" | |
| elseif rl_lower == "stone" then paxelMaterial = "stone" | |
| elseif rl_lower == "wood" or rl_lower == "wooden" then paxelMaterial = "wood" | |
| elseif rl_lower == "gold" or rl_lower == "golden" then paxelMaterial = "gold" | |
| end | |
| if paxelMaterial then | |
| local paxelId = "mekanismtools:" .. paxelMaterial .. "_paxel" | |
| logToFile("equipmentCraft: Substituting " .. formatted_request_name .. " (Level: " .. request_level .. ") with MEKANISM PAXEL: " .. paxelId, "INFO_") | |
| return paxelId, true | |
| else | |
| logToFile("equipmentCraft: Request for " .. baseType .. " of level '" .. request_level .. "' does not map to a supported Mekanism Paxel tier. Falling back to vanilla/original.", "INFO_") | |
| end | |
| end | |
| -- Standard Vanilla Equivalent Logic (for non-paxel tools/armor) | |
| local targetVanillaId = getVanillaEquivalentId(baseType, request_level) | |
| if targetVanillaId then | |
| logToFile("equipmentCraft: For request '" .. formatted_request_name .. "' (Level: " .. request_level .. "), determined target VANILLA item: " .. targetVanillaId, "INFO_") | |
| return targetVanillaId, true | |
| else | |
| logToFile("equipmentCraft: Request '" .. formatted_request_name .. "' (Level: " .. request_level .. ") does not map to a craftable vanilla equivalent or supported paxel. Original ID: "..original_item_id_from_colony..". Not crafting.", "INFO_") | |
| return original_item_id_from_colony, false | |
| end | |
| end | |
| function detectQuantityFieldOnce(itemName, nbtTable, fingerprint) | |
| if item_quantity_field then return item_quantity_field end | |
| local spec | |
| if fingerprint then | |
| spec = {fingerprint = fingerprint} | |
| else | |
| spec = {name = itemName} | |
| if nbtTable then | |
| local nbtString = convertNbtToSnbtString(nbtTable) | |
| if nbtString then spec.nbt = nbtString end | |
| end | |
| end | |
| local success, itemDataResult = safeCall(bridge.getItem, spec) | |
| if success and itemDataResult then | |
| if type(itemDataResult.amount) == "number" then item_quantity_field = "amount"; return "amount" end | |
| if type(itemDataResult.count) == "number" then item_quantity_field = "count"; return "count" end | |
| logToFile("Could not detect quantity field (amount/count) for " .. itemName .. ". Spec: " ..tableToString(spec), "WARN_") | |
| else | |
| logToFile("Failed to getItem for quantity field detection: " .. itemName .. ". Error: " ..tostring(itemDataResult) .. ". Spec: " .. tableToString(spec), "WARN_") | |
| end | |
| logToFile("Defaulting quantity field to 'amount' for " .. itemName, "DEBUG") | |
| item_quantity_field = "amount" | |
| return item_quantity_field | |
| end | |
| function storageSystemHandleRequests(request_list) | |
| if not bridge or not storage then | |
| logToFile("Bridge or storage not available for handling requests.", "WARN_", true) | |
| return | |
| end | |
| for _, item in ipairs(request_list) do | |
| local itemToRequest = item.item_name_raw | |
| local nbtTableForRequest = item.nbtData | |
| local fingerprintForRequest = item.fingerprint | |
| local canCraftThisItemBasedOnRules = true | |
| local isDomumItem = string.find(item.item_name_raw, "domum_ornamentum:", 1, true) == 1 | |
| local useOriginalNbtAndFingerprint = fingerprintForRequest ~= nil | |
| if isDomumItem then | |
| logToFile("Processing Domum Request: " .. item.item_displayName, "DEBUG", bShowInGameLog) | |
| logToFile(" Original Raw ID: " .. item.item_name_raw, "DEBUG", bShowInGameLog) | |
| end | |
| if item.equipment and b_craftEquipment then | |
| local potentialTargetItem, tierCraftableByRules | |
| potentialTargetItem, tierCraftableByRules = equipmentCraft(item.name, item.level, item.item_name_raw) | |
| if tierCraftableByRules then | |
| if potentialTargetItem ~= item.item_name_raw then | |
| logToFile(" EquipmentCraft: Mapped '"..item.item_name_raw.."' to TARGET '" .. potentialTargetItem .. "'. Will use this for AE2.", "INFO_") | |
| itemToRequest = potentialTargetItem | |
| useOriginalNbtAndFingerprint = false | |
| nbtTableForRequest = nil | |
| fingerprintForRequest = nil | |
| else | |
| logToFile(" EquipmentCraft: Target '" .. itemToRequest .. "' is same as original. Tier rules allow. Using original NBT/FP if present.", "INFO_") | |
| end | |
| canCraftThisItemBasedOnRules = true | |
| else | |
| logToFile(" EquipmentCraft: Rules prevent crafting for: " .. item.name .. " (Level: " .. item.level .. ", Original ID: " .. item.item_name_raw .. ")", "INFO_") | |
| canCraftThisItemBasedOnRules = false | |
| useOriginalNbtAndFingerprint = false | |
| end | |
| elseif item.equipment and not b_craftEquipment then | |
| canCraftThisItemBasedOnRules = false | |
| logToFile(" Master equipment crafting switch b_craftEquipment is OFF. Cannot craft: ".. item.item_displayName, "INFO_") | |
| useOriginalNbtAndFingerprint = false | |
| end | |
| local qtyField = detectQuantityFieldOnce(itemToRequest, (useOriginalNbtAndFingerprint and nbtTableForRequest) or nil, (useOriginalNbtAndFingerprint and fingerprintForRequest) or nil) | |
| if isDomumItem then logToFile(" Using Qty Field: " .. qtyField .. " for item: " .. itemToRequest, "DEBUG", bShowInGameLog) end | |
| local itemData, itemStoredSystem, itemIsCraftableSystemAE | |
| local getItemSpec = { name = itemToRequest } | |
| if useOriginalNbtAndFingerprint and fingerprintForRequest then | |
| getItemSpec.fingerprint = fingerprintForRequest | |
| if isDomumItem or item.equipment then logToFile(" Calling bridge.getItem with fingerprint spec: " .. tableToString(getItemSpec), "DEBUG", bShowInGameLog) end | |
| else | |
| if not useOriginalNbtAndFingerprint and nbtTableForRequest then | |
| local nbtString = convertNbtToSnbtString(nbtTableForRequest) | |
| if nbtString then getItemSpec.nbt = nbtString end | |
| elseif useOriginalNbtAndFingerprint and nbtTableForRequest and not fingerprintForRequest then | |
| local nbtString = convertNbtToSnbtString(nbtTableForRequest) | |
| if nbtString then getItemSpec.nbt = nbtString end | |
| end | |
| if isDomumItem or item.equipment then logToFile(" Calling bridge.getItem for '"..itemToRequest.."' with name/NBT string spec: " .. tableToString(getItemSpec), "DEBUG", bShowInGameLog) end | |
| end | |
| local successGetItem, resultGetItem = safeCall(bridge.getItem, getItemSpec) | |
| if successGetItem and resultGetItem then | |
| itemData = resultGetItem | |
| itemStoredSystem = itemData[qtyField] or 0 | |
| itemIsCraftableSystemAE = itemData.isCraftable | |
| if isDomumItem or item.equipment then logToFile(" bridge.getItem result for '"..itemToRequest.."' - Stored: " .. itemStoredSystem .. ", AE Craftable: " .. tostring(itemIsCraftableSystemAE), "DEBUG", bShowInGameLog) end | |
| else | |
| logToFile(item.item_displayName .. " (target ID: "..itemToRequest..", FP: "..tostring(fingerprintForRequest)..") not in system or error. getItemSpec: " .. tableToString(getItemSpec) .. " Err: " .. tostring(resultGetItem), "WARN_", true) | |
| item.displayColor = colors.red | |
| goto continue_request_loop | |
| end | |
| item.isCraftable = itemIsCraftableSystemAE | |
| if itemStoredSystem > 0 then | |
| local countToExport = item.count - item.provided | |
| if countToExport > 0 then | |
| local exportSpec = { name = itemToRequest, count = countToExport } | |
| if useOriginalNbtAndFingerprint and fingerprintForRequest then | |
| exportSpec.fingerprint = fingerprintForRequest | |
| if isDomumItem or item.equipment then logToFile(" Calling bridge.exportItemToPeripheral with fingerprint spec: " .. tableToString(exportSpec), "DEBUG", bShowInGameLog) end | |
| else | |
| if not useOriginalNbtAndFingerprint and nbtTableForRequest then | |
| local nbtString = convertNbtToSnbtString(nbtTableForRequest) | |
| if nbtString then exportSpec.nbt = nbtString end | |
| elseif useOriginalNbtAndFingerprint and nbtTableForRequest and not fingerprintForRequest then | |
| local nbtString = convertNbtToSnbtString(nbtTableForRequest) | |
| if nbtString then exportSpec.nbt = nbtString end | |
| end | |
| if isDomumItem or item.equipment then logToFile(" Calling bridge.exportItemToPeripheral for '"..itemToRequest.."' with name/NBT string spec: " .. tableToString(exportSpec), "DEBUG", bShowInGameLog) end | |
| end | |
| local successExport, exportedResult = safeCall(bridge.exportItemToPeripheral, exportSpec, storage) | |
| if successExport and exportedResult then | |
| local exportedAmountValue = 0 | |
| if type(exportedResult) == "number" then | |
| exportedAmountValue = exportedResult | |
| elseif type(exportedResult) == "table" and exportedResult[qtyField] then | |
| exportedAmountValue = exportedResult[qtyField] | |
| elseif type(exportedResult) == "table" and exportedResult["count"] then | |
| exportedAmountValue = exportedResult["count"] | |
| elseif type(exportedResult) == "table" and exportedResult["amount"] then | |
| exportedAmountValue = exportedResult["amount"] | |
| else | |
| logToFile("Unexpected result type/structure from exportItemToPeripheral for " .. item.item_displayName .. " ("..itemToRequest.."): " .. type(exportedResult) .. " Value: " .. tableToString(exportedResult or {}), "WARN_", bShowInGameLog) | |
| end | |
| item.provided = item.provided + (tonumber(exportedAmountValue) or 0) | |
| if isDomumItem or item.equipment then logToFile(" Exported: " .. exportedAmountValue .. " of "..itemToRequest..", New Provided: " .. item.provided, "DEBUG", bShowInGameLog) end | |
| else | |
| logToFile("Failed to export " .. item.item_displayName .. " (as "..itemToRequest.."). exportSpec: " .. tableToString(exportSpec) .. " Err: " .. tostring(exportedResult), "WARN_", true) | |
| end | |
| end | |
| end | |
| if item.provided >= item.count then | |
| item.displayColor = colors.green | |
| else | |
| local currentItemInSystem = itemStoredSystem | |
| if item.provided > 0 and item.provided < item.count then | |
| local recheckSpec = { name = itemToRequest } | |
| if useOriginalNbtAndFingerprint and fingerprintForRequest then | |
| recheckSpec.fingerprint = fingerprintForRequest | |
| elseif useOriginalNbtAndFingerprint and nbtTableForRequest and not fingerprintForRequest then | |
| local nbtString = convertNbtToSnbtString(nbtTableForRequest) | |
| if nbtString then recheckSpec.nbt = nbtString end | |
| end | |
| local successRecheck, recheckResultData = safeCall(bridge.getItem, recheckSpec) | |
| if successRecheck and recheckResultData then | |
| currentItemInSystem = recheckResultData[qtyField] or 0 | |
| end | |
| end | |
| if item.provided < item.count and currentItemInSystem == 0 and not item.isCraftable then | |
| item.displayColor = colors.red | |
| else | |
| item.displayColor = colors.yellow | |
| end | |
| end | |
| if item.provided < item.count and item.isCraftable and canCraftThisItemBasedOnRules then | |
| local nbtStringToCraft = nil | |
| if itemToRequest == item.item_name_raw and nbtTableForRequest then | |
| nbtStringToCraft = convertNbtToSnbtString(nbtTableForRequest) | |
| elseif isDomumItem and nbtTableForRequest then | |
| nbtStringToCraft = convertNbtToSnbtString(nbtTableForRequest) | |
| end | |
| local isItemCraftingSpec = { name = itemToRequest } | |
| if nbtStringToCraft then isItemCraftingSpec.nbt = nbtStringToCraft end | |
| if isDomumItem or item.equipment or nbtStringToCraft then logToFile(" Calling bridge.isItemCrafting for '"..itemToRequest.."' with spec: " .. tableToString(isItemCraftingSpec), "DEBUG", bShowInGameLog) end | |
| local successCraftingCheck, isCurrentlyCrafting = safeCall(bridge.isItemCrafting, isItemCraftingSpec) | |
| if successCraftingCheck and isCurrentlyCrafting then | |
| item.displayColor = colors.blue | |
| if isDomumItem or item.equipment or nbtStringToCraft then logToFile(" Item '"..itemToRequest.."' is already crafting.", "DEBUG", bShowInGameLog) end | |
| else | |
| local craftSpec = { name = itemToRequest, count = item.count - item.provided } | |
| if nbtStringToCraft then craftSpec.nbt = nbtStringToCraft end | |
| if isDomumItem or item.equipment or nbtStringToCraft then logToFile(" Calling bridge.craftItem for '"..itemToRequest.."' with spec: " .. tableToString(craftSpec), "DEBUG", bShowInGameLog) end | |
| local successCraft, craftInitiateResult = safeCall(bridge.craftItem, craftSpec) | |
| if successCraft and craftInitiateResult then | |
| item.displayColor = colors.blue | |
| logToFile("Crafting initiated for: " .. item.item_displayName .. " (as " .. itemToRequest .. ")", "INFO_", bShowInGameLog) | |
| else | |
| logToFile("Crafting request failed for " .. item.item_displayName .. " (as " .. itemToRequest .. "). craftSpec: " .. tableToString(craftSpec) .. " Err: " ..tostring(craftInitiateResult), "WARN_", true) | |
| if item.provided == 0 then item.displayColor = colors.red else item.displayColor = colors.yellow end | |
| end | |
| end | |
| elseif item.provided < item.count and not item.isCraftable then | |
| item.displayColor = colors.red | |
| if item.equipment then logToFile(" Cannot craft "..item.item_displayName.." (target ID: "..itemToRequest.."): AE system reports not craftable.", "INFO_", bShowInGameLog) end | |
| elseif item.provided < item.count and item.isCraftable and not canCraftThisItemBasedOnRules then | |
| if item.equipment then logToFile(" Skipping crafting for equipment (script rules prevent crafting this tier): " .. item.item_displayName .. " (requested as " .. item.level .. ", evaluated to not craft " .. itemToRequest .. ")", "INFO_", bShowInGameLog) end | |
| if item.provided == 0 then item.displayColor = colors.yellow else item.displayColor = colors.yellow end | |
| end | |
| ::continue_request_loop:: | |
| end | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* MAIN LOGIC FUNCTIONS | |
| -- ... (This section is unchanged) | |
| ---------------------------------------------------------------------------- | |
| function updatePeripheralAll() | |
| local allOk = true | |
| if not updatePeripheralMonitor() then allOk = false end | |
| if allOk and not checkMonitorSize() then allOk = false end | |
| if not updatePeripheralColonyIntegrator() then allOk = false end | |
| if allOk and colony and not colony.isInColony() then allOk = false end | |
| if not updatePeripheralStorageBridge() then allOk = false end | |
| if not updatePeripheralStorage() then allOk = false end | |
| needTermDrawRequirements = not allOk | |
| while needTermDrawRequirements do | |
| if not termDrawCheckRequirements() then | |
| sleep(1) | |
| else | |
| needTermDrawRequirements = false | |
| end | |
| end | |
| end | |
| function requestAndFulfill() | |
| local equipment_list, builder_list_standard, builder_list_domum, others_list = colonyCategorizeRequests() | |
| storageSystemHandleRequests(equipment_list) | |
| storageSystemHandleRequests(builder_list_standard) | |
| storageSystemHandleRequests(builder_list_domum) | |
| storageSystemHandleRequests(others_list) | |
| return equipment_list, builder_list_standard, builder_list_domum, others_list | |
| end | |
| function monitorShowDashboard(equipment_list, builder_list_standard, builder_list_domum, others_list) | |
| if not monitor then return end | |
| monitor.clear() | |
| monitorDashboardRequests(equipment_list, builder_list_standard, builder_list_domum, others_list) | |
| monitorDashboardName() | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* MAIN | |
| -- ... (This section is unchanged) | |
| ---------------------------------------------------------------------------- | |
| function main() | |
| termWidth, termHeight = term.getSize() | |
| termLoadingAnimation() | |
| updatePeripheralAll() | |
| monitorLoadingAnimation() | |
| while true do | |
| updatePeripheralAll() | |
| if bShowInGameLog then termShowLog() end | |
| local equipment_list, builder_list_standard, builder_list_domum, others_list = requestAndFulfill() | |
| monitorShowDashboard(equipment_list, builder_list_standard, builder_list_domum, others_list) | |
| sleep(0.1) | |
| end | |
| end | |
| main() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment