-
-
Save FiegenbaumMC/c41c7124375a8163e8c5b7972d5b89bd 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
| -- ME Monitor für ATM10 - Nur funktionierende API-Calls | |
| -- Basiert auf Debug-Ergebnissen: getEnergyUsage und getCraftingCPUs funktionieren | |
| local me = peripheral.wrap("bottom") | |
| local monitor = peripheral.wrap("left") | |
| local output = monitor or term | |
| if not me then | |
| print("Error: No ME Bridge found!") | |
| return | |
| end | |
| if monitor then | |
| print("Monitor found - starting display...") | |
| if monitor.setTextScale then | |
| monitor.setTextScale(0.5) | |
| end | |
| end | |
| local function clearScreen() | |
| if output.clear then output.clear() end | |
| if output.setCursorPos then output.setCursorPos(1, 1) end | |
| end | |
| local function printLine(text, color) | |
| if color and output.setTextColor then | |
| output.setTextColor(color) | |
| end | |
| output.write((text or "") .. "\n") | |
| if output.setTextColor then | |
| output.setTextColor(colors.white) | |
| end | |
| end | |
| local function formatNumber(num) | |
| if num >= 1000000 then | |
| return string.format("%.1fM", num / 1000000) | |
| elseif num >= 1000 then | |
| return string.format("%.1fK", num / 1000) | |
| else | |
| return string.format("%.1f", num) | |
| end | |
| end | |
| local function showMEInfo() | |
| clearScreen() | |
| printLine("=== ME SYSTEM STATUS ===", colors.yellow) | |
| printLine("") | |
| -- Connection Status (always works) | |
| local success, connected = pcall(function() return true end) -- We know it's connected | |
| if success and connected then | |
| printLine("STATUS: ONLINE", colors.lime) | |
| else | |
| printLine("STATUS: UNKNOWN", colors.orange) | |
| end | |
| printLine("") | |
| -- Energy Usage (this works!) | |
| printLine("ENERGY:", colors.white) | |
| local success, usage = pcall(me.getEnergyUsage) | |
| if success and usage then | |
| printLine(" Usage: " .. formatNumber(usage) .. " AE/t", colors.white) | |
| -- Estimate based on usage | |
| if usage > 0 then | |
| printLine(" System: Active", colors.lime) | |
| else | |
| printLine(" System: Idle", colors.gray) | |
| end | |
| else | |
| printLine(" Usage: Not available", colors.orange) | |
| end | |
| printLine("") | |
| -- Crafting CPUs (this works!) | |
| printLine("CRAFTING:", colors.white) | |
| local success, cpus = pcall(me.getCraftingCPUs) | |
| if success and cpus and type(cpus) == "table" then | |
| local cpuCount = 0 | |
| local busyCount = 0 | |
| for _, cpu in pairs(cpus) do | |
| cpuCount = cpuCount + 1 | |
| if cpu.isBusy then | |
| busyCount = busyCount + 1 | |
| end | |
| end | |
| printLine(" Total CPUs: " .. cpuCount, colors.white) | |
| printLine(" Active: " .. busyCount, colors.white) | |
| if busyCount > 0 then | |
| printLine(" Free: " .. (cpuCount - busyCount), colors.orange) | |
| else | |
| printLine(" Free: " .. cpuCount, colors.lime) | |
| end | |
| -- Show CPU details if available | |
| if cpuCount > 0 then | |
| local totalStorage = 0 | |
| local totalCoprocessors = 0 | |
| for _, cpu in pairs(cpus) do | |
| if cpu.storage then | |
| totalStorage = totalStorage + cpu.storage | |
| end | |
| if cpu.coProcessors then | |
| totalCoprocessors = totalCoprocessors + cpu.coProcessors | |
| end | |
| end | |
| if totalStorage > 0 then | |
| printLine(" Storage: " .. formatNumber(totalStorage), colors.white) | |
| end | |
| if totalCoprocessors > 0 then | |
| printLine(" Coprocessors: " .. totalCoprocessors, colors.white) | |
| end | |
| end | |
| else | |
| printLine(" CPU info not available", colors.orange) | |
| end | |
| printLine("") | |
| -- Limitations | |
| printLine("LIMITATIONS:", colors.orange) | |
| printLine(" Energy storage: Not available", colors.gray) | |
| printLine(" Item lists: Not available", colors.gray) | |
| printLine(" This ME Bridge version has", colors.gray) | |
| printLine(" limited API functionality", colors.gray) | |
| printLine("") | |
| printLine("Update: " .. os.date("%H:%M:%S"), colors.gray) | |
| if not monitor then | |
| printLine("") | |
| printLine("Press any key to refresh...", colors.yellow) | |
| end | |
| end | |
| -- Monitoring loop | |
| local function startMonitoring() | |
| while true do | |
| local success, error = pcall(showMEInfo) | |
| if not success then | |
| clearScreen() | |
| printLine("ERROR: " .. tostring(error), colors.red) | |
| printLine("Restart in 3 seconds...", colors.yellow) | |
| sleep(3) | |
| end | |
| if monitor then | |
| sleep(5) -- Auto-update every 5 seconds | |
| else | |
| os.pullEvent("key") | |
| sleep(0.1) | |
| end | |
| end | |
| end | |
| -- Start | |
| if monitor then | |
| print("Starting limited ME monitoring...") | |
| print("Only energy usage and CPU info available") | |
| sleep(2) | |
| startMonitoring() | |
| else | |
| print("Limited ME Bridge functionality detected") | |
| print("Press Enter to start monitoring...") | |
| read() | |
| startMonitoring() | |
| end |
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
| function exportItemToStorage(itemName, amount) | |
| if not bridge or not bridge.exportItem then | |
| logToFile("Bridge or exportItem not available", "ERROR", true) | |
| return 0 | |
| end | |
| -- Ensure parameters are valid | |
| itemName = tostring(itemName or "") | |
| amount = tonumber(amount) or 0 | |
| if itemName == "" or amount <= 0 then | |
| logToFile("Invalid parameters for export: " .. itemName .. " x" .. amount, "WARN_", true) | |
| return 0 | |
| end | |
| -- Ensure storage direction is set | |
| if not storage then | |
| logToFile("No storage direction set - attempting to detect", "WARN_", true) | |
| updatePeripheralStorage() | |
| end | |
| local exportDirection = storage or "west" | |
| logToFile("Exporting " .. amount .. " x " .. itemName .. " to direction: " .. exportDirection, "INFO_", true) | |
| -- Advanced Peripherals v0.8 API - exportItem(item, direction) | |
| local success, result = pcall(function() | |
| return bridge.exportItem({ | |
| name = itemName, | |
| count = amount | |
| }, exportDirection) | |
| end) | |
| if success and result then | |
| local exported = 0 | |
| -- Handle different return types from v0.8 API | |
| if type(result) == "number" then | |
| exported = result | |
| elseif type(result) == "table" then | |
| -- v0.8 may return table with count or amount | |
| exported = result.count or result.amount or result.transferred or 0 | |
| end | |
| if exported > 0 then | |
| logToFile("Export SUCCESS: " .. exported .. " items (v0.8 API)", "INFO_", true) | |
| stats.requestsCompleted = stats.requestsCompleted + 1 | |
| return exported | |
| else | |
| logToFile("Export returned 0 items", "WARN_", true) | |
| return 0 | |
| end | |
| else | |
| logToFile("Export FAILED: " .. tostring(result), "ERROR", true) | |
| return 0 | |
| end | |
| end---@diagnostic disable: undefined-global | |
| --++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- | |
| --** ULTIMATE CC X MINECOLONIES PROGRAM **-- | |
| --** WITH WORKING ME BRIDGE EXPORT **-- | |
| --++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- | |
| ---------------------------------------------------------------------------- | |
| --* VARIABLES | |
| ---------------------------------------------------------------------------- | |
| -- Displays Ticker in the first row right-side. Default: 15 | |
| local refreshInterval = 15 | |
| -- If true, Advanced Computer will show all Log information. Default: false | |
| local bShowInGameLog = false | |
| local bDisableLog = false | |
| -- Name of the log file e.g. "logFileName"_log.txt | |
| local logFileName = "CCxM" | |
| -- VERSION | |
| local VERSION = 1.35 | |
| -- Global variables | |
| local monitor = nil | |
| local colony = nil | |
| local bridge = nil | |
| local storage = "west" -- CHEST WEST OF ME BRIDGE | |
| local workingAPIMethod = nil | |
| -- Statistics tracking | |
| local stats = { | |
| requestsCompleted = 0, | |
| itemsCrafted = 0, | |
| startTime = os.clock(), | |
| lastUpdateTime = os.clock() | |
| } | |
| ---------------------------------------------------------------------------- | |
| --* LOG FUNCTIONS (Enhanced from first script) | |
| ---------------------------------------------------------------------------- | |
| function logToFile(message, level, bPrint) | |
| if not bDisableLog then | |
| level = level or "INFO_" | |
| bPrint = bPrint or bShowInGameLog | |
| -- Ensure message is a string | |
| message = tostring(message or "") | |
| 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("Failed to create log folder: " .. tostring(err)) | |
| return | |
| end | |
| end | |
| local success, err = pcall(function() | |
| local logFile = fs.open(logFilePath, "a") | |
| if logFile then | |
| logFile.writeLine("[" .. os.date("%Y-%m-%d %H:%M:%S") .. "] [" .. tostring(level) .. "] " .. tostring(message)) | |
| logFile.close() | |
| else | |
| error("Unable to open log file.") | |
| end | |
| end) | |
| if not success then | |
| print("Error writing to log file: " .. tostring(err)) | |
| return | |
| end | |
| -- Optionally print the message to the console | |
| if bPrint then | |
| if level == "ERROR" or level == "FATAL" then | |
| print("") | |
| end | |
| print("[" .. tostring(level) .. "] " .. tostring(message)) | |
| if level == "ERROR" or level == "FATAL" then | |
| print("") | |
| end | |
| end | |
| if monitor then | |
| monitorDebugOutput(message, level) | |
| end | |
| local free = fs.getFreeSpace("/") | |
| local logCounter = (logCounter or 0) + 1 | |
| if logCounter >= 250 or free < 80000 then | |
| rotateLogs(logFolder, logFilePath) | |
| logCounter = 0 | |
| end | |
| end | |
| end | |
| function monitorDebugOutput(message, level) | |
| if not monitor or level ~= "ERROR" then return end | |
| local w, h = monitor.getSize() | |
| monitor.setCursorPos(1, h) | |
| monitor.clearLine() | |
| monitor.setTextColor(colors.red) | |
| monitor.setBackgroundColor(colors.black) | |
| local timestamp = os.date("%H:%M") | |
| local maxWidth = w - 8 | |
| if #message > maxWidth then | |
| message = message:sub(1, maxWidth - 3) .. "..." | |
| end | |
| monitor.write("[" .. timestamp .. "] " .. message) | |
| monitor.setTextColor(colors.white) | |
| end | |
| -- Rotates logs and limits the number of old logs stored | |
| function rotateLogs(logFolder, logFilePath) | |
| local maxLogs = 2 -- Maximum number of log files to keep | |
| 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) | |
| local logCount = #logs | |
| while logCount > 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) | |
| logCount = logCount - 1 | |
| end | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* ERROR-HANDLING FUNCTION | |
| ---------------------------------------------------------------------------- | |
| function safeCall(func, ...) | |
| local success, result = pcall(func, ...) | |
| if not success then | |
| logToFile((result or "Unknown error"), "ERROR") | |
| return false | |
| end | |
| return true | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* PERIPHERAL FUNCTIONS (Enhanced from first script) | |
| ---------------------------------------------------------------------------- | |
| function getPeripheral(type) | |
| local peripheral = peripheral.find(type) | |
| return peripheral | |
| end | |
| function updatePeripheralMonitor() | |
| monitor = getPeripheral("monitor") | |
| if monitor then | |
| return true | |
| end | |
| return false | |
| end | |
| function checkMonitorSize() | |
| if not monitor then return false end | |
| monitor.setTextScale(0.5) | |
| local width, height = monitor.getSize() | |
| logToFile("Monitor size: " .. width .. "x" .. height, "INFO_", true) | |
| if width < 79 or height < 38 then | |
| logToFile("Use more Monitors! (min 4x3)", "WARN_") | |
| return false | |
| end | |
| return true | |
| end | |
| function updatePeripheralColonyIntegrator() | |
| logToFile("=== SEARCHING FOR COLONY INTEGRATOR ===", "INFO_", true) | |
| -- Check top first (as specified in setup) | |
| if peripheral.isPresent("top") then | |
| local topType = peripheral.getType("top") | |
| logToFile("Top peripheral found: " .. topType, "INFO_", true) | |
| if topType == "colonyIntegrator" or topType == "colony_integrator" then | |
| logToFile("Colony Integrator found on top (as expected)", "INFO_", true) | |
| colony = peripheral.wrap("top") | |
| end | |
| end | |
| -- Fallback: search other sides | |
| if not colony then | |
| colony = getPeripheral("colonyIntegrator") or getPeripheral("colony_integrator") | |
| end | |
| if colony then | |
| logToFile("Colony Integrator connected", "INFO_", true) | |
| -- Test basic functionality | |
| local success, result = pcall(function() | |
| return colony.isInColony() | |
| end) | |
| if success then | |
| if result then | |
| logToFile("Colony Integrator connected to colony", "INFO_", true) | |
| -- Test getRequests function with detailed info | |
| local testSuccess, testResult = pcall(function() | |
| local requests = colony.getRequests() | |
| if requests and type(requests) == "table" then | |
| logToFile("Found " .. #requests .. " colony requests", "INFO_", true) | |
| -- Log first request for debugging | |
| if #requests > 0 then | |
| local firstReq = requests[1] | |
| logToFile("Sample request structure:", "INFO_", true) | |
| logToFile(" Name: " .. tostring(firstReq.name or "missing"), "INFO_", true) | |
| logToFile(" Target: " .. tostring(firstReq.target or "missing"), "INFO_", true) | |
| logToFile(" Count: " .. tostring(firstReq.count or "missing"), "INFO_", true) | |
| logToFile(" Items array: " .. (#(firstReq.items or {}) > 0 and "present" or "missing"), "INFO_", true) | |
| end | |
| return #requests | |
| else | |
| logToFile("getRequests() returned invalid data type: " .. type(requests), "WARN_", true) | |
| return 0 | |
| end | |
| end) | |
| if testSuccess then | |
| logToFile("Colony Integrator fully functional (" .. (testResult or 0) .. " requests)", "INFO_", true) | |
| return true | |
| else | |
| logToFile("getRequests() function failed: " .. tostring(testResult), "WARN_", true) | |
| return false | |
| end | |
| else | |
| logToFile("Colony Integrator not in a colony", "WARN_", true) | |
| return false | |
| end | |
| else | |
| logToFile("Colony Integrator connection test failed: " .. tostring(result), "ERROR", true) | |
| colony = nil | |
| return false | |
| end | |
| else | |
| logToFile("Colony Integrator not found", "WARN_", true) | |
| return false | |
| end | |
| end | |
| function updatePeripheralStorageBridge() | |
| logToFile("=== SEARCHING FOR ME BRIDGE (Advanced Peripherals v0.8) ===", "INFO_", true) | |
| -- Check bottom first (most common) | |
| if peripheral.isPresent("bottom") then | |
| local bottomType = peripheral.getType("bottom") | |
| logToFile("Bottom peripheral found: " .. bottomType, "INFO_", true) | |
| if bottomType == "meBridge" or bottomType == "me_bridge" then | |
| logToFile("ME Bridge detected under computer!", "INFO_", true) | |
| bridge = peripheral.wrap("bottom") | |
| if bridge then | |
| logToFile("ME Bridge successfully wrapped", "INFO_", true) | |
| -- Test connection (v0.8 API) | |
| if bridge.isConnected then | |
| local success, connected = pcall(function() return bridge.isConnected() end) | |
| if success and connected then | |
| logToFile("ME Bridge connected to network", "INFO_", true) | |
| else | |
| logToFile("ME Bridge NOT connected to network", "ERROR", true) | |
| bridge = nil | |
| return false | |
| end | |
| end | |
| -- Test API methods for Advanced Peripherals v0.8 | |
| local apiMethods = { | |
| {name = "listItems", func = function() return bridge.listItems() end}, | |
| {name = "getItems", func = function() return bridge.getItems() end}, | |
| {name = "getAllItems", func = function() return bridge.getAllItems() end} | |
| } | |
| local items = nil | |
| for _, method in ipairs(apiMethods) do | |
| local methodName = method.name:gsub("%(.*%)", "") | |
| if bridge[methodName] then | |
| logToFile("Testing method: " .. method.name, "INFO_", true) | |
| local success, result = pcall(method.func) | |
| if success and result and type(result) == "table" then | |
| workingAPIMethod = method.name | |
| items = result | |
| logToFile("SUCCESS with " .. method.name .. ": " .. #items .. " items", "INFO_", true) | |
| break | |
| else | |
| logToFile("Method " .. method.name .. " failed: " .. tostring(result), "WARN_", true) | |
| end | |
| end | |
| end | |
| if workingAPIMethod and items then | |
| logToFile("Found working API method: " .. workingAPIMethod, "INFO_", true) | |
| if #items > 0 then | |
| -- Show sample items with v0.8 data structure | |
| logToFile("Sample items in ME system:", "INFO_", true) | |
| for i = 1, math.min(3, #items) do | |
| local item = items[i] | |
| local amount = item.amount or item.count or 0 | |
| local itemName = item.name or item.displayName or "Unknown" | |
| logToFile(" " .. itemName .. " x" .. amount, "INFO_", true) | |
| end | |
| end | |
| -- Test export capability (v0.8 uses exportItem) | |
| if bridge.exportItem then | |
| logToFile("exportItem() function available (v0.8 API)", "INFO_", true) | |
| logToFile("Export direction set to: " .. tostring(storage or "west") .. " (CHEST)", "INFO_", true) | |
| else | |
| logToFile("exportItem() function NOT available", "ERROR", true) | |
| bridge = nil | |
| return false | |
| end | |
| logToFile("SUCCESS: ME Bridge fully functional with v0.8 API!", "INFO_", true) | |
| return true | |
| else | |
| logToFile("Cannot find working API method", "ERROR", true) | |
| bridge = nil | |
| return false | |
| end | |
| end | |
| end | |
| end | |
| -- Search other sides if not found on bottom | |
| logToFile("Searching other sides for ME Bridge...", "INFO_", true) | |
| local sides = {"top", "front", "back", "left", "right"} | |
| for _, side in ipairs(sides) do | |
| if peripheral.isPresent(side) then | |
| local sideType = peripheral.getType(side) | |
| if sideType == "meBridge" or sideType == "me_bridge" then | |
| logToFile("ME Bridge found on " .. side, "INFO_", true) | |
| bridge = peripheral.wrap(side) | |
| if bridge then | |
| -- Quick test with v0.8 API | |
| local success, items = pcall(function() return bridge.listItems() end) | |
| if success and items then | |
| workingAPIMethod = "listItems" | |
| logToFile("ME Bridge on " .. side .. " working with " .. #items .. " items", "INFO_", true) | |
| return true | |
| end | |
| end | |
| end | |
| end | |
| end | |
| logToFile("ERROR: No functional ME Bridge found", "ERROR", true) | |
| return false | |
| end | |
| function autodetectStorage() | |
| -- First, try to use the confirmed working direction - WEST for Chest | |
| if peripheral.isPresent("west") then | |
| local westType = peripheral.getType("west") | |
| logToFile("West peripheral found: " .. tostring(westType), "INFO_", true) | |
| -- Check for chest or other storage types | |
| if peripheral.hasType("west", "inventory") or | |
| westType == "minecraft:chest" or | |
| westType == "chest" or | |
| westType:find("chest") or | |
| westType:find("storage") or | |
| westType:find("barrel") or | |
| westType:find("shulker") then | |
| storage = "west" | |
| logToFile("Storage detected on west: " .. westType .. " (Chest)", "INFO_", true) | |
| return storage | |
| else | |
| logToFile("West peripheral is not a storage type: " .. westType, "WARN_", true) | |
| end | |
| else | |
| logToFile("No peripheral found on west side", "WARN_", true) | |
| end | |
| -- If west doesn't work, search all sides for any storage-like peripheral | |
| logToFile("Searching all sides for storage...", "INFO_", true) | |
| for _, side in pairs(peripheral.getNames()) do | |
| local sideType = peripheral.getType(side) | |
| logToFile("Checking " .. side .. ": " .. sideType, "INFO_", true) | |
| if peripheral.hasType(side, "inventory") or | |
| sideType == "minecraft:chest" or | |
| sideType == "chest" or | |
| sideType:find("chest") or | |
| sideType:find("storage") or | |
| sideType:find("barrel") or | |
| sideType:find("shulker") then | |
| storage = side | |
| logToFile("Storage detected on " .. side .. ": " .. sideType, "INFO_", true) | |
| return side | |
| end | |
| end | |
| -- If no storage found, default to west anyway (maybe it works despite type) | |
| logToFile("No storage container detected - defaulting to west", "WARN_", true) | |
| storage = "west" | |
| return "west" | |
| end | |
| function updatePeripheralStorage() | |
| storage = autodetectStorage() | |
| if storage then | |
| logToFile("Storage peripheral updated to: " .. tostring(storage), "INFO_", true) | |
| return true | |
| else | |
| logToFile("Storage peripheral not found", "WARN_", true) | |
| return false | |
| end | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* ME SYSTEM FUNCTIONS (From first script) | |
| ---------------------------------------------------------------------------- | |
| function getMEItems() | |
| if not bridge then | |
| logToFile("Bridge not available for item retrieval", "ERROR", true) | |
| return nil | |
| end | |
| if not workingAPIMethod then | |
| logToFile("No working API method available", "ERROR", true) | |
| return nil | |
| end | |
| logToFile("Retrieving ME items using: " .. workingAPIMethod .. " (v0.8 API)", "INFO_", false) | |
| local success, items = nil, nil | |
| -- Advanced Peripherals v0.8 API methods | |
| if workingAPIMethod == "listItems" then | |
| success, items = pcall(function() return bridge.listItems() end) | |
| elseif workingAPIMethod == "getItems" then | |
| success, items = pcall(function() return bridge.getItems() end) | |
| elseif workingAPIMethod == "getAllItems" then | |
| success, items = pcall(function() return bridge.getAllItems() end) | |
| end | |
| if success and items and type(items) == "table" then | |
| logToFile("Retrieved " .. #items .. " item types (v0.8)", "INFO_", false) | |
| return items, workingAPIMethod | |
| else | |
| logToFile("Failed to retrieve items: " .. tostring(items), "ERROR", true) | |
| return nil | |
| end | |
| end | |
| function exportItemToStorage(itemName, amount) | |
| if not bridge or not bridge.exportItem then | |
| logToFile("Bridge or exportItem not available", "ERROR", true) | |
| return 0 | |
| end | |
| logToFile("Exporting " .. amount .. " x " .. itemName .. " to direction: " .. storage, "INFO_", true) | |
| -- Advanced Peripherals v0.8 API - exportItem(item, direction) | |
| local success, result = pcall(function() | |
| return bridge.exportItem({ | |
| name = itemName, | |
| count = amount | |
| }, storage) | |
| end) | |
| if success and result then | |
| local exported = 0 | |
| -- Handle different return types from v0.8 API | |
| if type(result) == "number" then | |
| exported = result | |
| elseif type(result) == "table" then | |
| -- v0.8 may return table with count or amount | |
| exported = result.count or result.amount or result.transferred or 0 | |
| end | |
| if exported > 0 then | |
| logToFile("Export SUCCESS: " .. exported .. " items (v0.8 API)", "INFO_", true) | |
| stats.requestsCompleted = stats.requestsCompleted + 1 | |
| return exported | |
| else | |
| logToFile("Export returned 0 items", "WARN_", true) | |
| return 0 | |
| end | |
| else | |
| logToFile("Export FAILED: " .. tostring(result), "ERROR", true) | |
| return 0 | |
| end | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* GENERIC HELPER FUNCTIONS | |
| ---------------------------------------------------------------------------- | |
| function trimLeadingWhitespace(str) | |
| return str:match("^%s*(.*)$") | |
| end | |
| function getLastWord(str) | |
| return string.match(str, "%S+$") | |
| end | |
| function tableToString(tbl, indent) | |
| indent = indent or 0 | |
| local toString = 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 | |
| toString = toString .. | |
| string.rep(" ", indent + 1) .. | |
| "[" .. formattedKey .. "] = " .. tableToString(value, indent + 1) .. ",\n" | |
| else | |
| local formattedValue = type(value) == "string" and string.format("%q", value) or tostring(value) | |
| toString = toString .. | |
| string.rep(" ", indent + 1) .. "[" .. formattedKey .. "] = " .. formattedValue .. ",\n" | |
| end | |
| end | |
| return toString .. string.rep(" ", indent) .. "}" | |
| end | |
| local function ensure_width(line, width) | |
| width = width or term.getSize() | |
| line = line:sub(1, width) | |
| if #line < width then | |
| line = line .. (" "):rep(width - #line) | |
| end | |
| return line | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* MONITOR DASHBOARD NAME | |
| ---------------------------------------------------------------------------- | |
| local dashboardName = "MineColonies DASHBOARD v" .. VERSION | |
| local rainbowColors = { | |
| colors.red, colors.orange, colors.yellow, | |
| colors.green, colors.cyan, colors.blue, | |
| colors.purple, colors.magenta, colors.pink | |
| } | |
| function monitorDisplayDashboardName(monitor, y, text, colorsTable) | |
| local w, h = monitor.getSize() | |
| local x = math.floor((w - #text) / 2) + 1 | |
| for i = 1, #text do | |
| local char = text:sub(i, i) | |
| local color = colorsTable[i] | |
| monitor.setTextColor(color) | |
| monitor.setCursorPos(x + i - 1, y) | |
| monitor.write(char) | |
| sleep(0.01) | |
| end | |
| end | |
| function dashboardGenerateTransitionColors(progress, length) | |
| local colorsTable = {} | |
| local threshold = math.floor((progress) * length) | |
| for i = 1, length do | |
| if i <= threshold then | |
| table.insert(colorsTable, colors.orange) | |
| else | |
| table.insert(colorsTable, colors.white) | |
| end | |
| end | |
| return colorsTable | |
| end | |
| function dashboardGenerateRainbowColors(baseColors, length) | |
| local result = {} | |
| local totalColors = #baseColors | |
| for i = 1, length do | |
| result[i] = baseColors[((i - 1) % totalColors) + 1] | |
| end | |
| return result | |
| end | |
| function monitorDashboardName() | |
| local startTime = os.clock() | |
| local y = 1 | |
| while true do | |
| local elapsedTime = os.clock() - startTime | |
| local progress = math.min(elapsedTime / (refreshInterval - 1), 1) | |
| if elapsedTime >= refreshInterval then | |
| sleep(0.5) | |
| local rainbowColorsTable = dashboardGenerateRainbowColors(rainbowColors, #dashboardName) | |
| monitorDisplayDashboardName(monitor, y, dashboardName, rainbowColorsTable) | |
| sleep(0.1) | |
| else | |
| local colorsTable = dashboardGenerateTransitionColors(progress, #dashboardName) | |
| monitorDisplayDashboardName(monitor, y, dashboardName, colorsTable) | |
| sleep(0.1) | |
| end | |
| if elapsedTime >= refreshInterval then | |
| break | |
| end | |
| end | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* ART | |
| ---------------------------------------------------------------------------- | |
| local artUltimateCCxM_Logo = [[ | |
| _ _ _ _ _ _ | |
| | | | | | |_(_)_ __ ___ __ _| |_ ___ | |
| | | | | | __| | '_ ` _ \ / _` | __/ _ \ | |
| | |_| | | |_| | | | | | | (_| | || __/ | |
| \____|_____|_|_| |_|___|_____|\__\___| | |
| / ___/ ___|__ __| \/ (_)_ __ ___ | |
| | | | | \ \/ /| |\/| | | '_ \ / _ \ | |
| | |__| |___ > < | | | | | | | | __/ | |
| \____\____|/_/\_\|_| |_|_|_| |_|\___| | |
| / ___|___ | | ___ _ __ (_) ___ ___ | |
| | | / _ \| |/ _ \| '_ \| |/ _ \/ __| | |
| | |__| (_) | | (_) | | | | | __/\__ \ | |
| \____\___/|_|\___/|_| |_|_|\___||___/ | |
| ]] | |
| ---------------------------------------------------------------------------- | |
| --* MONITOR OR TERMINAL OUTPUT | |
| ---------------------------------------------------------------------------- | |
| function resetDefault(screen) | |
| screen.setTextColor(colors.white) | |
| screen.setBackgroundColor(colors.black) | |
| screen.setCursorPos(1, 1) | |
| screen.clear() | |
| end | |
| function drawLoadingBar(screen, x, y, width, progress, bgColor, barColor) | |
| screen.setBackgroundColor(bgColor or colors.gray) | |
| screen.setTextColor(colors.white) | |
| screen.setCursorPos(x, y) | |
| -- Draw the empty bar | |
| screen.write(string.rep(" ", width)) | |
| -- Draw the filled part | |
| local filledWidth = math.floor(progress * width) | |
| screen.setCursorPos(x, y) | |
| screen.setBackgroundColor(barColor or colors.green) | |
| screen.write(string.rep(" ", filledWidth)) | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* MONITOR OUTPUT | |
| ---------------------------------------------------------------------------- | |
| local x, y = 1, 1 | |
| function monitorDisplayArt(asciiArt, monitor_) | |
| monitor_.clear() | |
| local x, y = 1, 2 | |
| for line in asciiArt:gmatch("[^\n]+") do | |
| monitor_.setCursorPos(x, y) | |
| monitor_.write(line) | |
| y = y + 1 | |
| end | |
| end | |
| function monitorLoadingAnimation() | |
| resetDefault(monitor) | |
| monitor.setTextScale(1) | |
| local width, height = monitor.getSize() | |
| local barWidth = math.floor(width * 0.9) | |
| local barX = math.floor((width - barWidth) / 2 + 1) | |
| local barHeight = 17 | |
| monitor.setTextColor(colors.orange) | |
| monitor.setCursorPos(1, 1) | |
| monitorDisplayArt(artUltimateCCxM_Logo, monitor) | |
| local barSpeed = 30 | |
| for i = 0, barSpeed do | |
| local progress = i / barSpeed | |
| drawLoadingBar(monitor, barX, barHeight, barWidth, progress, colors.gray, colors.orange) | |
| sleep(0.1) | |
| end | |
| resetDefault(monitor) | |
| monitor.setTextScale(0.5) | |
| end | |
| function monitorPrintText(y, pos, text, ...) | |
| local w, h = monitor.getSize() | |
| local fg = monitor.getTextColor() | |
| local bg = monitor.getBackgroundColor() | |
| local x = 1 | |
| if pos == "left" then | |
| x = 4 | |
| text = ensure_width(text, math.floor(w / 2) - 2) | |
| elseif pos == "center" then | |
| x = math.floor((w - #text) / 2) | |
| elseif pos == "right" then | |
| x = w - #text - 2 | |
| elseif pos == "middle" then | |
| x = math.floor((w - #text) / 2) | |
| 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, y) | |
| monitor.write(text) | |
| monitor.setTextColor(fg) | |
| monitor.setBackgroundColor(bg) | |
| end | |
| function drawBox(xMin, xMax, yMin, yMax, title, bcolor, tcolor) | |
| 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) | |
| end | |
| function monitorDashboardRequests(equipment_list, builder_list, others_list) | |
| local x, y = monitor.getSize() | |
| local equipment_count = #equipment_list | |
| local builder_count = #builder_list | |
| local others_count = #others_list | |
| drawBox(2, x - 1, 3, (equipment_count + math.ceil(builder_count / 2) + others_count) + 11, "REQUESTS", colors.gray, colors.purple) | |
| --Builder | |
| monitorPrintText(5, "center", "Builder", colors.orange) | |
| local half = math.ceil(builder_count / 2) | |
| for i = 1, half do | |
| local item = builder_list[i] | |
| if item then | |
| monitorPrintText(i + 5, "left", (item.provided .. "/" .. item.name), item.displayColor) | |
| end | |
| end | |
| for i = half + 1, builder_count do | |
| local item = builder_list[i] | |
| if item then | |
| monitorPrintText(i - half + 5, "right", (item.provided .. "/" .. item.name), item.displayColor) | |
| end | |
| end | |
| --Equipment | |
| monitorPrintText(math.ceil(builder_count / 2) + 7, "center", "Equipment", colors.orange) | |
| for i, item in pairs(equipment_list) do | |
| monitorPrintText(math.ceil(builder_count / 2) + i + 7, "left", item.name, item.displayColor) | |
| monitorPrintText(math.ceil(builder_count / 2) + i + 7, "right", item.target, colors.lightGray) | |
| end | |
| --Others | |
| monitorPrintText(equipment_count + math.ceil(builder_count / 2) + 9, "center", "Other", colors.orange) | |
| for i, item in pairs(others_list) do | |
| monitorPrintText(i + equipment_count + math.ceil(builder_count / 2) + 9, "left", (item.provided .. "/" .. item.name), item.displayColor) | |
| monitorPrintText(i + equipment_count + math.ceil(builder_count / 2) + 9, "right", item.target, colors.lightGray) | |
| end | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* TERMINAL OUTPUT | |
| ---------------------------------------------------------------------------- | |
| local termWidth, termHeight = term.getSize() | |
| 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) | |
| local width, height = term.getSize() | |
| local barWidth = math.floor(width * 0.8) | |
| local barX = math.floor((width - barWidth) / 2 + 1) | |
| local barHeight = math.floor(height * 0.9) | |
| term.setTextColor(colors.orange) | |
| term.setCursorPos(1, 1) | |
| termDisplayArt(artUltimateCCxM_Logo) | |
| local barSpeed = 25 | |
| for i = 0, barSpeed do | |
| local progress = i / barSpeed | |
| drawLoadingBar(term, barX, barHeight, barWidth, progress, 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() | |
| 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() | |
| end | |
| local text_Monitor_1 = "\16 Monitor attached" | |
| term.setCursorPos(2, 6) | |
| term.write(text_Monitor_1) | |
| local text_Monitor_2 = "\16 Monitor size (min 4x3)" | |
| term.setCursorPos(2, 8) | |
| term.write(text_Monitor_2) | |
| local text_Colony_1 = "\16 Colony Integrator attached" | |
| term.setCursorPos(2, 10) | |
| term.write(text_Colony_1) | |
| local text_Colony_2 = "\16 Colony Integrator in a colony" | |
| term.setCursorPos(2, 12) | |
| term.write(text_Colony_2) | |
| local text_StoargeBridge = "\16 ME Bridge attached" | |
| term.setCursorPos(2, 14) | |
| term.write(text_StoargeBridge) | |
| local text_Stoarge = "\16 Storage/Warehouse attached" | |
| term.setCursorPos(2, 16) | |
| term.write(text_Stoarge) | |
| if updatePeripheralMonitor() then | |
| termDrawProgramReq_helper(6, true) | |
| if checkMonitorSize() then | |
| termDrawProgramReq_helper(8, true) | |
| else | |
| termDrawProgramReq_helper(8, false) | |
| end | |
| else | |
| termDrawProgramReq_helper(6, false) | |
| termDrawProgramReq_helper(8, false) | |
| end | |
| if updatePeripheralColonyIntegrator() then | |
| termDrawProgramReq_helper(10, true) | |
| if colony.isInColony() then | |
| termDrawProgramReq_helper(12, true) | |
| else | |
| termDrawProgramReq_helper(12, false) | |
| end | |
| else | |
| termDrawProgramReq_helper(10, false) | |
| termDrawProgramReq_helper(12, false) | |
| end | |
| if updatePeripheralStorageBridge() then | |
| termDrawProgramReq_helper(14, true) | |
| else | |
| termDrawProgramReq_helper(14, false) | |
| end | |
| if updatePeripheralStorage() then | |
| termDrawProgramReq_helper(16, true) | |
| else | |
| termDrawProgramReq_helper(16, false) | |
| end | |
| if not needTermDrawRequirements_executed then | |
| termDrawProgramReq_Header() | |
| needTermDrawRequirements_executed = true | |
| end | |
| if updatePeripheralMonitor() and updatePeripheralColonyIntegrator() and updatePeripheralStorageBridge() and updatePeripheralStorage() then | |
| if checkMonitorSize() and colony.isInColony() then | |
| termDrawProgramReq_helper(6, true) | |
| termDrawProgramReq_helper(8, true) | |
| termDrawProgramReq_helper(10, true) | |
| termDrawProgramReq_helper(12, true) | |
| termDrawProgramReq_helper(14, true) | |
| termDrawProgramReq_helper(16, true) | |
| needTermDrawRequirements = false | |
| needTermDrawRequirements_executed = false | |
| local text_RequirementsFullfilled = "Requirements fullfilled" | |
| term.setCursorPos(math.floor((termWidth - #text_RequirementsFullfilled) / 2), 19) | |
| term.setTextColor(colors.green) | |
| sleep(0.5) | |
| textutils.slowWrite(text_RequirementsFullfilled, 16) | |
| textutils.slowWrite(" . . .", 5) | |
| sleep(1) | |
| -- Cleanup | |
| term.setTextColor(colors.white) | |
| term.clear() | |
| term.setCursorPos(1, 1) | |
| return true | |
| end | |
| end | |
| return true | |
| end | |
| function termShowLog() | |
| 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_Requirements = "\187 MineColonies Logs \171 v" .. VERSION | |
| term.setCursorPos(math.floor((termWidth - #text_Requirements) / 2) + 1, 2) | |
| textutils.slowWrite(text_Requirements, 16) | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* MINECOLONIES | |
| ---------------------------------------------------------------------------- | |
| local function isEquipment(desc) | |
| local equipmentKeywords = { "Sword ", "Bow ", "Pickaxe ", "Axe ", "Shovel ", "Hoe ", "Shears ", "Helmet ", | |
| "Chestplate ", "Leggings ", "Boots ", "Shield" } | |
| 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 = {} | |
| local others_list = {} | |
| -- Check if colony integrator is available and connected | |
| if not colony then | |
| logToFile("Colony integrator not available", "ERROR", true) | |
| return equipment_list, builder_list, others_list | |
| end | |
| -- Check if we're in a colony | |
| local success, inColony = pcall(function() return colony.isInColony() end) | |
| if not success or not inColony then | |
| logToFile("Not in a colony or unable to check colony status", "WARN_", true) | |
| return equipment_list, builder_list, others_list | |
| end | |
| -- Get requests with error handling | |
| local requests = {} | |
| local success, result = pcall(function() | |
| return colony.getRequests() | |
| end) | |
| if not success then | |
| logToFile("Failed to get colony requests: " .. tostring(result), "ERROR", true) | |
| return equipment_list, builder_list, others_list | |
| end | |
| if not result or type(result) ~= "table" then | |
| logToFile("No requests found or invalid data structure", "INFO_", true) | |
| return equipment_list, builder_list, others_list | |
| end | |
| requests = result | |
| logToFile("Retrieved " .. #requests .. " colony requests", "INFO_", true) | |
| -- Debug: Test ME Bridge connectivity and item listing | |
| if bridge then | |
| logToFile("=== ME BRIDGE DEBUG (v0.8) ===", "INFO_", true) | |
| -- Test connection | |
| local connSuccess, connected = pcall(function() return bridge.isConnected() end) | |
| if connSuccess and connected then | |
| logToFile("ME Bridge is connected to network", "INFO_", true) | |
| -- Test item listing | |
| local itemSuccess, items = pcall(function() | |
| if workingAPIMethod == "listItems" then | |
| return bridge.listItems() | |
| elseif workingAPIMethod == "getItems" then | |
| return bridge.getItems() | |
| else | |
| return bridge.getAllItems() | |
| end | |
| end) | |
| if itemSuccess and items then | |
| logToFile("ME System has " .. #items .. " item types", "INFO_", true) | |
| if #items > 0 then | |
| local sample = items[1] | |
| logToFile("Sample item structure:", "INFO_", true) | |
| for key, value in pairs(sample) do | |
| logToFile(" " .. key .. ": " .. tostring(value), "INFO_", true) | |
| end | |
| end | |
| else | |
| logToFile("Failed to list ME items: " .. tostring(items), "ERROR", true) | |
| end | |
| else | |
| logToFile("ME Bridge not connected to network", "ERROR", true) | |
| end | |
| logToFile("=== END ME BRIDGE DEBUG ===", "INFO_", true) | |
| end | |
| -- Debug: Show all available request fields | |
| if #requests > 0 then | |
| local sampleReq = requests[1] | |
| logToFile("=== DEBUG: Sample Request Structure ===", "INFO_", true) | |
| for key, value in pairs(sampleReq) do | |
| if type(value) == "table" then | |
| logToFile(" " .. key .. ": [table with " .. #value .. " entries]", "INFO_", true) | |
| else | |
| logToFile(" " .. key .. ": " .. tostring(value), "INFO_", true) | |
| end | |
| end | |
| logToFile("=== END DEBUG ===", "INFO_", true) | |
| end | |
| -- Process each request with error handling | |
| for i, req in ipairs(requests) do | |
| local success, err = pcall(function() | |
| -- Validate request structure | |
| if not req or type(req) ~= "table" then | |
| logToFile("Invalid request at index " .. i, "WARN_", true) | |
| return | |
| end | |
| -- Try different field names for compatibility | |
| local name = req.name or req.displayName or req.itemName or "Unknown Item" | |
| local target = req.target or req.requester or req.citizen or "" | |
| local desc = req.desc or req.description or req.details or "" | |
| local count = req.count or req.amount or req.quantity or 1 | |
| -- Check if items array exists and has at least one item | |
| if not req.items or type(req.items) ~= "table" or #req.items == 0 then | |
| logToFile("Request missing items data: " .. name .. " (trying alternative fields)", "WARN_", true) | |
| -- Try alternative item access | |
| local item_name = req.item or req.itemName or req.name or "minecraft:air" | |
| local item_displayName = req.displayName or name | |
| if item_name == "minecraft:air" then | |
| logToFile("Could not determine item for request: " .. name, "ERROR", true) | |
| return | |
| end | |
| -- Create a pseudo item structure | |
| local itemData = { | |
| name = item_name, | |
| displayName = item_displayName, | |
| item_name = item_name, | |
| item_displayName = trimLeadingWhitespace(item_displayName) | |
| } | |
| processRequestItem(itemData, name, target, desc, count, equipment_list, builder_list, others_list) | |
| return | |
| end | |
| local firstItem = req.items[1] | |
| if not firstItem or type(firstItem) ~= "table" then | |
| logToFile("Invalid first item in request: " .. name, "WARN_", true) | |
| return | |
| end | |
| local item_displayName = trimLeadingWhitespace(firstItem.displayName or firstItem.name or name) | |
| local item_name = firstItem.name or firstItem.id or firstItem.item or "minecraft:air" | |
| local itemData = { | |
| name = item_name, | |
| displayName = item_displayName, | |
| item_name = item_name, | |
| item_displayName = item_displayName | |
| } | |
| processRequestItem(itemData, name, target, desc, count, equipment_list, builder_list, others_list) | |
| end) | |
| if not success then | |
| logToFile("Error processing request " .. i .. ": " .. tostring(err), "WARN_", true) | |
| end | |
| end | |
| logToFile("Categorized: " .. #equipment_list .. " equipment, " .. #builder_list .. " builder, " .. #others_list .. " others", "INFO_", true) | |
| return equipment_list, builder_list, others_list | |
| end | |
| function processRequestItem(itemData, name, target, desc, count, equipment_list, builder_list, others_list) | |
| local itemIsEquipment = isEquipment(desc) | |
| -- Equipment Categorization | |
| if 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 level = "Any Level" | |
| for pattern, mappedLevel in pairs(levelTable) do | |
| if string.find(desc, pattern) then | |
| level = mappedLevel | |
| break | |
| end | |
| end | |
| local new_name = level .. " " .. name | |
| table.insert(equipment_list, { | |
| name = new_name, | |
| target = target, | |
| count = count, | |
| item_displayName = itemData.item_displayName, | |
| item_name = itemData.item_name, | |
| desc = desc, | |
| provided = 0, | |
| isCraftable = false, | |
| equipment = itemIsEquipment, | |
| displayColor = colors.white, | |
| level = level | |
| }) | |
| -- Builder Categorization | |
| elseif string.find(target, "Builder") or string.find(string.lower(target), "builder") then | |
| table.insert(builder_list, { | |
| name = name, | |
| target = target, | |
| count = count, | |
| item_displayName = itemData.item_displayName, | |
| item_name = itemData.item_name, | |
| desc = desc, | |
| provided = 0, | |
| isCraftable = false, | |
| equipment = itemIsEquipment, | |
| displayColor = colors.white, | |
| level = "" | |
| }) | |
| -- Non-Builder Categorization | |
| else | |
| table.insert(others_list, { | |
| name = name, | |
| target = target, | |
| count = count, | |
| item_displayName = itemData.item_displayName, | |
| item_name = itemData.item_name, | |
| desc = desc, | |
| provided = 0, | |
| isCraftable = false, | |
| equipment = itemIsEquipment, | |
| displayColor = colors.white, | |
| level = "" | |
| }) | |
| end | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* STORAGE SYSTEM REQUEST AND SEND (Enhanced with working export) | |
| ---------------------------------------------------------------------------- | |
| -- Color code: red = not available | |
| -- yellow = stuck | |
| -- blue = crafting | |
| -- green = fully exported | |
| -- Try or skip equipment craft | |
| local b_craftEquipment = true | |
| -- Choose "Iron" or "Diamond" or "Iron and Diamond" | |
| local craftEquipmentOfLevel = "Iron" | |
| function equipmentCraft(name, level, item_name) | |
| if (item_name == "minecraft:bow") then | |
| return item_name, true | |
| end | |
| if (level == "Iron" or level == "Iron and Diamond" or level == "Any Level") and (craftEquipmentOfLevel == "Iron" or craftEquipmentOfLevel == "Iron and Diamond") then | |
| if level == "Any Level" then | |
| level = "Iron" | |
| end | |
| item_name = string.lower("minecraft:" .. level .. "_" .. getLastWord(name)) | |
| return item_name, true | |
| elseif (level == "Diamond" or level == "Iron and Diamond" or level == "Any Level") and craftEquipmentOfLevel == "Diamond" then | |
| if level == "Any Level" then | |
| level = "Diamond" | |
| end | |
| item_name = string.lower("minecraft:" .. level .. "_" .. getLastWord(name)) | |
| return item_name, true | |
| end | |
| return item_name, false | |
| end | |
| local item_quantity_field = nil | |
| local function detectQuantityField(itemName) | |
| local success, itemData = pcall(function() | |
| return bridge.getItem({ name = itemName }) | |
| end) | |
| if success and itemData then | |
| -- Advanced Peripherals v0.8 typically uses 'amount' | |
| if type(itemData.amount) == "number" then | |
| return "amount" | |
| elseif type(itemData.count) == "number" then | |
| return "count" | |
| end | |
| end | |
| return "amount" -- v0.8 default | |
| end | |
| function storageSystemHandleRequests(request_list) | |
| -- Add items that should not be crafted or send to the Warehouse | |
| local skip_items = { | |
| "minecraft:enchanted_book", | |
| } | |
| local skip_set = {} | |
| for _, name in ipairs(skip_items) do | |
| skip_set[name] = true | |
| end | |
| for _, item in ipairs(request_list) do | |
| local itemStored = 0 | |
| local b_CurrentlyCrafting = false | |
| local b_equipmentCraft = true | |
| if skip_set[item.item_name] then | |
| item.displayColor = colors.gray | |
| goto continue | |
| end | |
| if item.equipment then | |
| item.item_name, b_equipmentCraft = equipmentCraft(item.name, item.level, item.item_name) | |
| end | |
| -- Detect field once | |
| if not item_quantity_field then | |
| item_quantity_field = detectQuantityField(item.item_name) | |
| end | |
| -- getItem() to see if item in system (if not, error), count and if craftable | |
| -- Advanced Peripherals v0.8 API | |
| local b_functionGetItem = pcall(function() | |
| local itemData = bridge.getItem({ name = item.item_name }) | |
| if itemData then | |
| -- v0.8 uses 'amount' primarily, but check both for compatibility | |
| itemStored = itemData.amount or itemData.count or 0 | |
| -- v0.8 API for crafting check | |
| item.isCraftable = itemData.isCraftable or (itemData.craftable ~= nil and itemData.craftable) or false | |
| logToFile("Item " .. item.item_name .. " found: " .. itemStored .. " available, craftable: " .. tostring(item.isCraftable), "INFO_", false) | |
| else | |
| logToFile("Item " .. item.item_name .. " not found in ME system", "INFO_", false) | |
| end | |
| end) | |
| if not b_functionGetItem then | |
| logToFile(item.item_displayName .. " not in system or craftable.", "INFO_", true) | |
| item.displayColor = colors.red | |
| if string.sub(item.item_name, 1, 17) == "domum_ornamentum:" then | |
| item.displayColor = colors.lightBlue | |
| end | |
| goto continue | |
| end | |
| if not (itemStored == 0) then | |
| -- Use the enhanced export function from the first script | |
| local exportedAmount = exportItemToStorage(item.item_name, item.count) | |
| item.provided = exportedAmount | |
| if (item.provided == item.count) then | |
| item.displayColor = colors.green | |
| if string.sub(item.item_name, 1, 17) == "domum_ornamentum:" then | |
| item.displayColor = colors.lightBlue | |
| end | |
| else | |
| item.displayColor = colors.yellow | |
| end | |
| end | |
| if not b_craftEquipment and item.equipment then | |
| goto continue | |
| end | |
| if (item.provided < item.count) and item.isCraftable and b_equipmentCraft then | |
| local b_functionIsItemCrafting = safeCall(function() | |
| -- v0.8 API for checking crafting status | |
| if bridge.isItemCrafting then | |
| b_CurrentlyCrafting = bridge.isItemCrafting({ name = item.item_name }) | |
| elseif bridge.getCraftingJobs then | |
| -- Alternative method in some v0.8 versions | |
| local jobs = bridge.getCraftingJobs() | |
| for _, job in ipairs(jobs or {}) do | |
| if job.item and job.item.name == item.item_name then | |
| b_CurrentlyCrafting = true | |
| break | |
| end | |
| end | |
| end | |
| end) | |
| if not b_functionIsItemCrafting then | |
| logToFile("Asking for crafting job failed.", "WARN_") | |
| end | |
| if b_CurrentlyCrafting then | |
| item.displayColor = colors.blue | |
| goto continue | |
| end | |
| end | |
| local b_craftItem = not b_CurrentlyCrafting and item.isCraftable and (item.provided < item.count) | |
| if b_craftItem then | |
| -- Skip Equipments if set to false | |
| if not b_craftEquipment and item.equipment then | |
| goto continue | |
| end | |
| local b_functionCraftItem = safeCall(function() | |
| local craftedItem = { name = item.item_name, count = item.count - item.provided } | |
| -- v0.8 API supports craftItem | |
| return bridge.craftItem(craftedItem) | |
| end) | |
| if not b_functionCraftItem then | |
| logToFile("Crafting request failed. (Items missing)", "WARN_", true) | |
| item.displayColor = colors.yellow | |
| goto continue | |
| end | |
| item.displayColor = colors.blue | |
| end | |
| ::continue:: | |
| end | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* MAIN LOGIC FUNCTIONS | |
| ---------------------------------------------------------------------------- | |
| function updatePeripheralAll() | |
| if not updatePeripheralMonitor() or not checkMonitorSize() then | |
| needTermDrawRequirements = true | |
| end | |
| if not updatePeripheralColonyIntegrator() or not colony.isInColony() then | |
| needTermDrawRequirements = true | |
| end | |
| if not updatePeripheralStorageBridge() then | |
| needTermDrawRequirements = true | |
| end | |
| if not updatePeripheralStorage() then | |
| needTermDrawRequirements = true | |
| end | |
| while needTermDrawRequirements do | |
| termDrawCheckRequirements() | |
| sleep(1) | |
| end | |
| end | |
| function requestAndFulfill() | |
| local equipment_list, builder_list, others_list = {}, {}, {} | |
| -- Try to get colony requests with robust error handling | |
| local maxRetries = 3 | |
| local retryCount = 0 | |
| while retryCount < maxRetries do | |
| local success, err = pcall(function() | |
| equipment_list, builder_list, others_list = colonyCategorizeRequests() | |
| end) | |
| if success then | |
| logToFile("Successfully retrieved and categorized requests", "INFO_", false) | |
| break | |
| else | |
| retryCount = retryCount + 1 | |
| logToFile("Failed to get requests (attempt " .. retryCount .. "/" .. maxRetries .. "): " .. tostring(err), "WARN_", true) | |
| if retryCount < maxRetries then | |
| logToFile("Retrying in 2 seconds...", "INFO_", true) | |
| sleep(2) | |
| -- Try to reconnect colony integrator | |
| updatePeripheralColonyIntegrator() | |
| else | |
| logToFile("Max retries reached. Using empty request lists.", "ERROR", true) | |
| return {}, {}, {} | |
| end | |
| end | |
| end | |
| -- Only process requests if we have valid data | |
| if equipment_list and builder_list and others_list then | |
| if #equipment_list > 0 or #builder_list > 0 or #others_list > 0 then | |
| -- Process requests with error handling | |
| local success1 = pcall(function() storageSystemHandleRequests(equipment_list) end) | |
| local success2 = pcall(function() storageSystemHandleRequests(builder_list) end) | |
| local success3 = pcall(function() storageSystemHandleRequests(others_list) end) | |
| if not success1 then logToFile("Error processing equipment requests", "WARN_", true) end | |
| if not success2 then logToFile("Error processing builder requests", "WARN_", true) end | |
| if not success3 then logToFile("Error processing other requests", "WARN_", true) end | |
| else | |
| logToFile("No requests to process", "INFO_", false) | |
| end | |
| end | |
| return equipment_list or {}, builder_list or {}, others_list or {} | |
| end | |
| function monitorShowDashboard(equipment_list, builder_list, others_list) | |
| monitor.clear() | |
| monitorDashboardRequests(equipment_list, builder_list, others_list) | |
| monitorDashboardName() | |
| end | |
| ---------------------------------------------------------------------------- | |
| --* MAIN | |
| ---------------------------------------------------------------------------- | |
| function main() | |
| print("Ultimate CC x MineColonies Program v" .. VERSION) | |
| print("With Enhanced ME Bridge Export (Direction: " .. tostring(storage or "west") .. " -> Chest)") | |
| print("Starting...") | |
| stats.startTime = os.clock() | |
| termLoadingAnimation() | |
| updatePeripheralAll() | |
| if monitor then | |
| monitorLoadingAnimation() | |
| end | |
| logToFile("=== PROGRAM STARTED ===", "INFO_", true) | |
| logToFile("ME Bridge Export Direction: " .. tostring(storage or "west") .. " (Chest)", "INFO_", true) | |
| logToFile("Working API Method: " .. tostring(workingAPIMethod or "Unknown"), "INFO_", true) | |
| while true do | |
| local success, err = pcall(function() | |
| updatePeripheralAll() | |
| termShowLog() | |
| term.setCursorPos(1, 5) | |
| local equipment_list, builder_list, others_list = requestAndFulfill() | |
| if monitor then | |
| monitorShowDashboard(equipment_list, builder_list, others_list) | |
| end | |
| end) | |
| if not success then | |
| logToFile("Main loop error: " .. tostring(err), "ERROR", true) | |
| print("Main loop error: " .. tostring(err)) | |
| print("Attempting to reconnect peripherals...") | |
| updatePeripheralAll() | |
| sleep(5) | |
| else | |
| sleep(refreshInterval) | |
| end | |
| end | |
| end | |
| -- START THE PROGRAM | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment