Skip to content

Instantly share code, notes, and snippets.

@nguyen-vh
Forked from adkinss/RSWarehouse.lua
Last active December 9, 2025 01:16
Show Gist options
  • Select an option

  • Save nguyen-vh/56ce79dc58a6c5b3136c46230eb4f052 to your computer and use it in GitHub Desktop.

Select an option

Save nguyen-vh/56ce79dc58a6c5b3136c46230eb4f052 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
---@diagnostic disable: undefined-global
--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
--** ULTIMATE CC X MINECOLONIES PROGRAM **--
--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
----------------------------------------------------------------------------
----------------------------------------------------------------------------
--* 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"
----------------------------------------------------------------------------
--* LOG (FATAL ERROR WARN_ INFO_ DEBUG TRACE)
----------------------------------------------------------------------------
-- Keeps track of the revisions
local VERSION = 1.15
-- Log a message to a file and optionally print it to the console
function logToFile(message, level, bPrint)
if not bDisableLog then
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
-- Write the log entry with a timestamp and level
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
-- Optionally print the message to the console
if bPrint then
if level == "ERROR" or level == "FATAL" then
print("")
end
print(string.format("%s", message))
if level == "ERROR" or level == "FATAL" then
print("")
end
end
free = fs.getFreeSpace("/")
logCounter = (logCounter or 0) + 1
if logCounter >= 250 or free < 80000 then
rotateLogs(logFolder, logFilePath)
logCounter = 0
end
end
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
----------------------------------------------------------------------------
--* DEBUG FUNCTIONS
----------------------------------------------------------------------------
function debugDiskSpace()
local free = fs.getFreeSpace("/")
print("Free disk space:", free, "bytes")
for _, f in ipairs(fs.list("/")) do
local path = "/" .. f
if not fs.isDir(path) then
print(path, fs.getSize(path))
end
end
end
function debugPrintTableToLog(t, logFile, indent)
indent = indent or 0
local prefix = string.rep(" ", indent)
for key, value in pairs(t) do
if type(value) == "table" then
logFile:write(prefix .. tostring(key) .. ":\n")
debugPrintTableToLog(value, logFile, indent + 1)
else
logFile:write(prefix .. tostring(key) .. ": " .. tostring(value) .. "\n")
end
end
end
function debugTableTest()
local logFile = io.open("M_log.txt", "w")
if not logFile then
error("Could not open log file for writing")
end
local success, result = pcall(function()
local requests = peripheral.find("colony_integrator").getRequests()
debugPrintTableToLog(requests, logFile)
end)
if not success then
logFile:write("Error: " .. tostring(result) .. "\n")
end
logFile:close()
print(result or "Table logged successfully")
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
function writeToLogFile(fileName, equipment_list, builder_list, others_list)
local file = io.open(fileName, "w") -- Open file in write mode
if not file then
error("Could not open file for writing: " .. fileName)
end
-- Write the contents of each list
file:write("Equipment List:\n")
file:write(tableToString(equipment_list) .. "\n\n")
file:write("Builder List:\n")
file:write(tableToString(builder_list) .. "\n\n")
file:write("Others List:\n")
file:write(tableToString(others_list) .. "\n\n")
file:close() -- Close the file
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
----------------------------------------------------------------------------
--* CHECK REQUIREMENTS
----------------------------------------------------------------------------
local monitor = peripheral.find("monitor")
local colony
local bridge
local storage
function getPeripheral(type)
local peripheral = peripheral.find(type)
if not peripheral then
-- logToFile(type .. " peripheral not found.", "WARN_")
return nil
end
-- logToFile(type .. " peripheral found.")
return peripheral
end
function updatePeripheralMonitor()
monitor = getPeripheral("monitor")
if monitor then
return true
else
return false
end
end
function checkMonitorSize()
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") or getPeripheral("colony_integrator")
if colony then
return true
else
return false
end
end
function getStorageBridge()
local meBridge = getPeripheral("meBridge") or getPeripheral("me_bridge")
local rsBridge = getPeripheral("rsBridge") or getPeripheral("rs_bridge")
if meBridge then
return meBridge
elseif rsBridge then
return rsBridge
else
logToFile("Neither ME Storage Bridge nor RS Storage Bridge found.", "WARN_")
return nil
end
end
function updatePeripheralStorageBridge()
bridge = getStorageBridge()
if bridge then
return true
else
return false
end
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()
if storage then
return true
else
return false
end
end
----------------------------------------------------------------------------
-- MONITOR DASHBOARD NAME
----------------------------------------------------------------------------
-- 1st line on dashboard with color changing depending on the refreshInterval
-- Reset through a rainbow
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(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 to simulate the loading process
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 or RS 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 = {}
for _, req in ipairs(colony.getRequests()) do
local name = req.name
local target = req.target or ""
local desc = req.desc or ""
local count = req.count
local item_displayName = trimLeadingWhitespace(req.items[1].displayName)
local item_name = req.items[1].name
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 = item_displayName,
item_name = item_name,
desc = desc,
provided = 0,
isCraftable = false,
equipment = itemIsEquipment,
displayColor = colors.white,
level = level
})
-- Builder Categorization
elseif string.find(target, "Builder") then
table.insert(builder_list, {
name = name,
target = target,
count = count,
item_displayName = item_displayName,
item_name = 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 = item_displayName,
item_name = item_name,
desc = desc,
provided = 0,
isCraftable = false,
equipment = itemIsEquipment,
displayColor = colors.white,
level = ""
})
end
end
return equipment_list, builder_list, others_list
end
----------------------------------------------------------------------------
--* STORAGE SYSTEM REQUEST AND SEND
----------------------------------------------------------------------------
-- 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
if type(itemData.amount) == "number" then
return "amount"
elseif type(itemData.count) == "number" then
return "count"
end
end
return nil
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
b_functionGetItem = pcall(function()
local itemData = bridge.getItem({ name = item.item_name })
itemStored = itemData[item_quantity_field] or 0
item.isCraftable = itemData.isCraftable
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
b_functionExportItemToPeripheral = pcall(function()
item.provided = bridge.exportItemToPeripheral({ name = item.item_name, count = item.count }, storage)
end) or pcall(function()
item.provided = bridge.exportItem({ name = item.item_name, count = item.count }, storage)
end)
if not b_functionExportItemToPeripheral then
logToFile("Failed to export item.", "WARN_", true)
item.displayColor = colors.yellow
end
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
b_functionIsItemCrafting = safeCall(function()
b_CurrentlyCrafting = bridge.isItemCrafting({ name = item.item_name })
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
b_functionCraftItem = safeCall(function()
local craftedItem = { name = item.item_name, count = item.count - item.provided }
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
while true do
local success, err = pcall(function()
equipment_list, builder_list, others_list = colonyCategorizeRequests()
end)
if success then
break
else
logToFile("Failed to get requests, retrying... (" .. err .. ")", "WARN_", true)
sleep(5)
end
end
-- writeToLogFile("log1.txt", equipment_list, builder_list, others_list)
storageSystemHandleRequests(equipment_list)
storageSystemHandleRequests(builder_list)
storageSystemHandleRequests(others_list)
-- writeToLogFile("log2.txt", equipment_list, builder_list, others_list)
return equipment_list, builder_list, others_list
end
--TODO
function monitorShowDashboard(equipment_list, builder_list, others_list)
monitor.clear()
monitorDashboardRequests(equipment_list, builder_list, others_list)
-- monitorDashboardResearch()
-- monitorDashboardStats()
monitorDashboardName()
end
----------------------------------------------------------------------------
--* MAIN
----------------------------------------------------------------------------
function main()
termLoadingAnimation()
updatePeripheralAll()
monitorLoadingAnimation()
while true do
updatePeripheralAll()
-- debugTableTest()
-- sleep(2)
-- debugDiskSpace()
termShowLog()
term.setCursorPos(1, 5)
local equipment_list, builder_list, others_list = requestAndFulfill()
monitorShowDashboard(equipment_list, builder_list, others_list)
end
end
main()
@katsuo
Copy link

katsuo commented Apr 29, 2025 via email

@nguyen-vh
Copy link
Author

@katsuo So you used a normal chest or barrel (not entangled) and it didn’t transfer into it? Can you check if only one storage is touching the advanced computer because it can’t differentiate between many.

@katsuo
Copy link

katsuo commented Apr 29, 2025

i try whit entangled linked to the warehouse and linked to the chest,i try only a chest connected to the Computer and i have the same result,item is crafted but not transfered,
image

@nguyen-vh
Copy link
Author

@katsuo So do you receive the message that items are being transferred?

@katsuo
Copy link

katsuo commented May 1, 2025

@nguyen-vh no i only see the item being crafted in AE2 but not transfered, storage need to touch the ME bridge ?
[2025-05-01 19:38:50] [ERROR] /startup:963: attempt to index a nil value
[2025-05-01 19:38:50] [WARN_] [Gray Bed] isn't in system and isn't craftable.
[2025-05-01 19:39:05] [INFO_] monitor peripheral found.
[2025-05-01 19:39:05] [INFO_] colonyIntegrator peripheral found.
[2025-05-01 19:39:05] [INFO_] meBridge peripheral found.
[2025-05-01 19:39:05] [WARN_] rsBridge peripheral not found.
[2025-05-01 19:39:05] [INFO_] Storage detected on left
[2025-05-01 19:39:07] [ERROR] /startup:963: attempt to index a nil value
[2025-05-01 19:39:07] [WARN_] [Gray Bed] isn't in system and isn't craftable.
[2025-05-01 19:39:22] [INFO_] monitor peripheral found.
[2025-05-01 19:39:22] [INFO_] colonyIntegrator peripheral found.
[2025-05-01 19:39:22] [INFO_] meBridge peripheral found.
[2025-05-01 19:39:22] [WARN_] rsBridge peripheral not found.
[2025-05-01 19:39:22] [INFO_] Storage detected on left
[2025-05-01 19:39:36] [INFO_] monitor peripheral found.
[2025-05-01 19:39:36] [INFO_] colonyIntegrator peripheral found.

@nguyen-vh
Copy link
Author

@katsuo Can you try the updated code version. I just looked up what Fennsy mentioned, and in the Advanced Peripherals docs, “count” has been changed to “amount”. Let me know if it works.

@katsuo
Copy link

katsuo commented May 3, 2025

@nguyen-vh yes ! it work,the pending items is transfered in the warehouse. Thank for your help!

@toolboxmatch
Copy link

Hello, Im using ATM10 version 2.44 from with MC 1.21.1 and im having a bit of a problem with this system.
As you can see the system requirements have been fulfilled and I feel like the set up im using is the same as everybody else's setup. But the problem is, the items are not sent to the warehouse. The items that are requested in the computer are already ready in my storage system but it just wont send it. I have tried linking the ME Bridge directly to my AE2 storage system with cable but it doesnt work.
Is there any problem with my setup? or is it something else? pls help guys

Screenshot 2025-05-04 235856
Screenshot 2025-05-04 235921

@nguyen-vh
Copy link
Author

@toolboxmatch Can you check if you have my latest code version, because the problem seems to be the same.

@DEMONIC696
Copy link

@nguyen-vh I have the same issue. Ive updated to you latest code and still items wont transfer into the system. ive tried both with the entangled block as well as hooking the system directly to the warehouse block. it reads the AE@ system properly and crafts the times on the list every time it cycles. ive tried using busses as well encase the entangler was bugged but it doesnt seem to matter.

@nguyen-vh
Copy link
Author

@DEMONIC696 When you say that it requests the items every cycle, it either means that your ME system can make them and therefore doesn't send them, or that my program's logic is flawed because it shouldn't make them if it detects enough items in the system. Could you check this for me and also send me the item it wants to make?

@DEMONIC696
Copy link

@nguyen-vh so i reverted my script to you old one with count instead of amount and my scrip started to work properly. so whomever came up with that fix might have had a different issue. as for what yo asked me it was every item. any item in my system that the colony wanted that was "craftable" would turn blue on screen and start crafting but the items would never actually send to the warehouse block. but as i said it fixed itself when i reverted the script to count instead of amount on line 963.

@nguyen-vh
Copy link
Author

@DEMONIC696 I originally wrote the script for 1.21.1, but there doesn't seem to be a solution that is downward compatible.

@nguyen-vh
Copy link
Author

I have added a check to use either .amount or .count depending on which of the two works. Would be nice if someone could give me some feedback on this. I have tested it for 1.21.1 ATM and it is running there.

@VentedSun
Copy link

Just found this and i have to say, WOW! Im running it on ATM9 and seems to be functioning fine, will let you know if i find any issues related to the above :)

@MarcosPibernus
Copy link

Java Exception Thrown:
java.lang.IllegalStateException: Element Reference{ResourceKey[minecraft:enchantment / minecraft:looting]=Enchantment Looting} is not valid in current registry set

i have this error, i dont know why its broken

@Aruise
Copy link

Aruise commented May 18, 2025

Hi!
Just got this bug, started after I upgraded warehouse from level 2 to 3
image

@Aruise
Copy link

Aruise commented May 18, 2025

Hi! Just got this bug, started after I upgraded warehouse from level 2 to 3 image

Messed up with the code a little, added enchantment check and skip in the colonyCategorizeRequests function

    for _, req in ipairs(colony.getRequests()) do
        local item = req.items[1]

        if item and item.components and item.components["minecraft:enchantments"] then
            goto continue
        end

        local name = req.name
        local target = req.target or ""
        local desc = req.desc or ""
        local count = req.count
        local item_displayName = trimLeadingWhitespace(item.displayName or "")
        local item_name = item.name or ""
        local itemIsEquipment = isEquipment(desc)

And a goto tag before the function end

        ::continue::
    end

    return equipment_list, builder_list, others_list
end

Doubt it's safe to skip them fully, but it worked for me, hopefully you'll find a correct solution

Edit: correction - it does not fix the problem nor does it ignores it. After a while I now receive aqua affinity exception, even though I tried to ignore enchantments fully...

@nguyen-vh
Copy link
Author

nguyen-vh commented May 18, 2025

Next week I will try to fix the problem. Could you please write down the ATM and Advanced Peripherals version so I can check if the mods have changed anything. @Aruise @marcospiber

@Aruise
Copy link

Aruise commented May 19, 2025

Next week I will try to fix the problem. Could you please write down the ATM and Advanced Peripherals version so I can check if the mods have changed anything. @Aruise @marcospiber

ATM10 - 2.47
AP - 0.7.49a

As I mentioned before it started when I upgraded the warehouse, colonial, to 3 level, the exact level that allows NPCs to have enchants on gear. I've build guard's tower at the same time. I had level 3 buildings before and it worked fine, so my bet is on the automatic gear requests. I'll try to manually fulfill guard's requests for armor and gear and see if it helps

Edit: It did, original code

@MarcosPibernus
Copy link

Same version here @Aruise @nguyen-vh

@MarcosPibernus
Copy link

The new ATM version 3.00, which includes the latest updates for all mods, has broken the Advanced Monitor

@Aruise
Copy link

Aruise commented May 21, 2025

The new ATM version 3.00, which includes the latest updates for all mods, has broken the Advanced Monitor

Mine monitor is working fine. Though, problem from the previous version with enchants persists. AP version hasn't changed

@nguyen-vh
Copy link
Author

@marcospiber Do you mean that the program is still running, but the monitor no longer displays anything? It could be that the shaders are making the display on the monitor more difficult to see if you have deactivated the shaders in the game. Try activating the shaders or deactivating the mod completely before loading the modpack.

If the monitor is broken because the program is broken, send the error message. I would like to see if you have the same error as me.

@nguyen-vh
Copy link
Author

Next week I will try to fix the problem. Could you please write down the ATM and Advanced Peripherals version so I can check if the mods have changed anything. @Aruise @marcospiber

ATM10 - 2.47 AP - 0.7.49a

As I mentioned before it started when I upgraded the warehouse, colonial, to 3 level, the exact level that allows NPCs to have enchants on gear. I've build guard's tower at the same time. I had level 3 buildings before and it worked fine, so my bet is on the automatic gear requests. I'll try to manually fulfill guard's requests for armor and gear and see if it helps

Edit: It did, original code

@Aruise Do you know the requirements for the guards to be able to request enchanted gear? I've been trying all afternoon, but I can't reproduce the error. My buildings are T5 and I have an enchanter, although no request is coming in.

@Aruise
Copy link

Aruise commented May 23, 2025

Next week I will try to fix the problem. Could you please write down the ATM and Advanced Peripherals version so I can check if the mods have changed anything. @Aruise @marcospiber

ATM10 - 2.47 AP - 0.7.49a
As I mentioned before it started when I upgraded the warehouse, colonial, to 3 level, the exact level that allows NPCs to have enchants on gear. I've build guard's tower at the same time. I had level 3 buildings before and it worked fine, so my bet is on the automatic gear requests. I'll try to manually fulfill guard's requests for armor and gear and see if it helps
Edit: It did, original code

@Aruise Do you know the requirements for the guards to be able to request enchanted gear? I've been trying all afternoon, but I can't reproduce the error. My buildings are T5 and I have an enchanter, although no request is coming in.

@nguyen-vh I don't have an enchanter, issue happens whenever ANY of the orders contains a tool or armor, I don't think I noticed a pattern with levels of buildings, but it says something about enchants in the log, mostly different ones but related to the tool/armor.

It happened to the builder requesting pickaxe and a shovel, to the farmer requesting a hoe, and to the guards requesting armor and a sword. It also happened when I made a completely new builder, that needed a wooden shovel to even build 1 level hut

Here is the list of the requirements, if it helps you
https://minecolonies.com/wiki/systems/worker/

@Victinifan963
Copy link

Hello
I'm currently on ATM 2.47 and have the system setup and the program is telling me that everything is connected.
However, no matter what i do the items stay yellow on the Monitor even if i supply them in the AE2 system. Am i doing something wrong?

@nguyen-vh
Copy link
Author

nguyen-vh commented May 24, 2025

@Victinifan963 If you could send me your setup, I could tell you, but usually the yellow color means the items are stuck and can't be transferred to the warehouse/chest. If you have a unique setup, try the default setup with all the required blocks touching the advanced computer. If the system does not work then, you can send the log files (in modpack > saves > "your world" > computercraft > computer > "folder there" > CCxM_logs > CCxM_latest.txt). Maybe I didn't get the export for different versions right last time.

@nguyen-vh
Copy link
Author

I've come across the issue now and it seems to be a problem with how Advanced Peripherals accesses information. The equipment with enchantments is stored in a deeper tree structure than normal items and Advanced Peripherals just calls them without checking. So the getRequests() function triggers the error regardless of how I access the information, just calling the function causes the error. I also noticed that the error occurs quite rarely (in my case I ran the game for 3 hours to get an error) and it disappears when a “clean” getRequests() comes (which in my case took 10 minutes).

In version 1.13 I added a failover for getRequests(), so at least the program doesn't stop anymore, but as long as it doesn't receive any requests, it obviously can't make or export items.

Hope this error wont occur for you anymore. @Aruise @marcospiber

@derrickmehaffy
Copy link

Adding a comment here in case anyone else runs into it:

I couldn't get it to put the items into the entangled block directly but I used the item pipe from the pipez mod between the colony integration and the entanged chest (pulling from the colony block into the entangled chest) and that seems to solve pushing items in.

Ignore my extra pipe, that leads to a manual input barrel

2025-06-02_16 38 04

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment