Files
ATM10_CC_Codes/create_factory_test.lua
T

310 lines
9.3 KiB
Lua

-- ATM10 Create factory logistics test controller
-- Phase 1: Stock Ticker requests and live stock display, no redstone control.
local REFRESH_SECONDS = 1.0
local CONFIRM_SECONDS = 6.0
local LOG_FILE = "factory_test_log.txt"
local trackedItems = {
{ id = "create:asurine", label = "Asurine" },
{ id = "minecraft:andesite", label = "Andesite" },
{ id = "create:andesite_alloy", label = "Andesite Alloy" },
{ id = "minecraft:oak_log", label = "Oak Logs" },
{ id = "minecraft:stripped_oak_log", label = "Stripped Oak" },
{ id = "minecraft:oak_planks", label = "Oak Planks" },
{ id = "alltheores:zinc_clump", label = "Zinc Clumps" },
{ id = "alltheores:zinc_nugget", label = "Zinc Nuggets" },
}
local actions = {
{
id = "crush_asurine",
label = "64 ASURINE -> crushing",
address = "crushing",
item = "create:asurine",
count = 64,
},
{
id = "strip_oak",
label = "64 OAK LOGS -> saw:2",
address = "saw:2",
item = "minecraft:oak_log",
count = 64,
},
{
id = "planks_oak",
label = "64 STRIPPED -> saw:2",
address = "saw:2",
item = "minecraft:stripped_oak_log",
count = 64,
},
{
id = "shafts",
label = "64 ALLOY -> saw:1",
address = "saw:1",
item = "create:andesite_alloy",
count = 64,
},
}
local function findPeripheral(wantedType)
for _, name in ipairs(peripheral.getNames()) do
local peripheralType = peripheral.getType(name)
if peripheralType == wantedType then
return name
end
end
return nil
end
local tickerName = findPeripheral("Create_StockTicker")
local monitorName = findPeripheral("monitor")
if not tickerName then
error("Kein Create Stock Ticker am Wired-Modem-Netz gefunden", 0)
end
if not monitorName then
error("Kein Monitor am Wired-Modem-Netz gefunden", 0)
end
local monitor = peripheral.wrap(monitorName)
monitor.setTextScale(0.5)
local stock = {}
local buttons = {}
local messages = {}
local armedAction = nil
local armedUntil = 0
local statusText = "Bereit - nur Testbetrieb, keine Redstone-Steuerung"
local statusColor = colors.lime
local function formatNumber(value)
local text = tostring(math.floor(tonumber(value) or 0))
local sign, digits = text:match("^([%-]?)(%d+)$")
if not digits then
return text
end
local formatted = digits:reverse():gsub("(%d%d%d)", "%1."):reverse():gsub("^%.", "")
return sign .. formatted
end
local function timeText()
return textutils.formatTime(os.time(), true)
end
local function appendLog(message)
local line = "[" .. timeText() .. "] " .. message
messages[#messages + 1] = line
while #messages > 4 do
table.remove(messages, 1)
end
local file = fs.open(LOG_FILE, "a")
if file then
file.writeLine(line)
file.close()
end
end
local function refreshStock()
local ok, result = pcall(peripheral.call, tickerName, "stock")
if not ok then
statusText = "Stock-Ticker-Fehler: " .. tostring(result)
statusColor = colors.red
return false
end
local nextStock = {}
for _, entry in pairs(result or {}) do
if type(entry) == "table" and entry.name then
nextStock[entry.name] = (nextStock[entry.name] or 0) + (tonumber(entry.count) or 0)
end
end
stock = nextStock
return true
end
local function writeAt(x, y, text, foreground, background)
local width, height = monitor.getSize()
if y < 1 or y > height or x > width then
return
end
monitor.setCursorPos(math.max(1, x), y)
monitor.setTextColor(foreground or colors.white)
monitor.setBackgroundColor(background or colors.black)
monitor.write(tostring(text):sub(1, math.max(0, width - x + 1)))
end
local function center(y, text, foreground, background)
local width = monitor.getSize()
local x = math.max(1, math.floor((width - #text) / 2) + 1)
writeAt(x, y, text, foreground, background)
end
local function drawButton(action, x1, y1, x2, y2)
local isArmed = armedAction == action.id and os.clock() <= armedUntil
local available = stock[action.item] or 0
local enabled = available > 0
local background = colors.gray
local foreground = colors.lightGray
if enabled then
background = isArmed and colors.orange or colors.green
foreground = isArmed and colors.black or colors.white
end
for y = y1, y2 do
writeAt(x1, y, string.rep(" ", x2 - x1 + 1), foreground, background)
end
local label = action.label
if isArmed then
label = "NOCHMALS: " .. label
elseif not enabled then
label = "KEIN BESTAND: " .. label
end
local labelX = math.max(x1, math.floor((x1 + x2 - #label) / 2))
writeAt(labelX, math.floor((y1 + y2) / 2), label, foreground, background)
buttons[#buttons + 1] = {
action = action,
x1 = x1,
y1 = y1,
x2 = x2,
y2 = y2,
enabled = enabled,
}
end
local function render()
local width, height = monitor.getSize()
monitor.setBackgroundColor(colors.black)
monitor.setTextColor(colors.white)
monitor.clear()
buttons = {}
center(1, "CREATE FACTORY - LOGISTIKTEST", colors.cyan)
center(2, "Ticker: " .. tickerName .. " | Monitor: " .. monitorName, colors.gray)
local columnWidth = math.floor((width - 6) / 2)
local leftX = 3
local rightX = leftX + columnWidth + 2
local firstStockRow = 4
for index, item in ipairs(trackedItems) do
local column = (index - 1) % 2
local row = firstStockRow + math.floor((index - 1) / 2)
local x = column == 0 and leftX or rightX
local amount = formatNumber(stock[item.id] or 0)
local text = item.label .. ": " .. amount
writeAt(x, row, text, (stock[item.id] or 0) > 0 and colors.lime or colors.gray)
end
local statusRow = firstStockRow + math.ceil(#trackedItems / 2) + 1
center(statusRow, statusText, statusColor)
local buttonTop = statusRow + 2
local gap = 2
local buttonWidth = math.floor((width - 6 - gap) / 2)
local xLeft = 3
local xRight = xLeft + buttonWidth + gap
local buttonHeight = 2
drawButton(actions[1], xLeft, buttonTop, xLeft + buttonWidth - 1, buttonTop + buttonHeight - 1)
drawButton(actions[2], xRight, buttonTop, xRight + buttonWidth - 1, buttonTop + buttonHeight - 1)
drawButton(actions[3], xLeft, buttonTop + 3, xLeft + buttonWidth - 1, buttonTop + 4)
drawButton(actions[4], xRight, buttonTop + 3, xRight + buttonWidth - 1, buttonTop + 4)
local logTitleRow = math.min(height - 4, buttonTop + 6)
writeAt(2, logTitleRow, "Letzte Ereignisse:", colors.yellow)
for index, message in ipairs(messages) do
writeAt(2, logTitleRow + index, message, colors.lightGray)
end
writeAt(2, height, "Jede Bestellung muss innerhalb 6 Sekunden zweimal beruehrt werden.", colors.gray)
end
local function submit(action)
local filter = {
name = action.item,
_requestCount = action.count,
}
local ok, sent = pcall(
peripheral.call,
tickerName,
"requestFiltered",
action.address,
filter
)
if not ok then
statusText = "BESTELLFEHLER: " .. tostring(sent)
statusColor = colors.red
appendLog(statusText)
return
end
local amount = tonumber(sent) or 0
statusText = formatNumber(amount) .. "x " .. action.item .. " -> " .. action.address
statusColor = amount > 0 and colors.lime or colors.orange
appendLog(statusText)
refreshStock()
end
local function handleTouch(x, y)
for _, button in ipairs(buttons) do
if x >= button.x1 and x <= button.x2 and y >= button.y1 and y <= button.y2 then
if not button.enabled then
statusText = "Kein passender Rohstoff im Stock-Ticker-Netz"
statusColor = colors.orange
appendLog(statusText)
return
end
local now = os.clock()
if armedAction == button.action.id and now <= armedUntil then
local selected = button.action
armedAction = nil
armedUntil = 0
submit(selected)
else
armedAction = button.action.id
armedUntil = now + CONFIRM_SECONDS
statusText = "Zur Bestaetigung denselben Knopf erneut beruehren"
statusColor = colors.orange
end
return
end
end
end
appendLog("Testcontroller gestartet auf Computer " .. tostring(os.getComputerID()))
refreshStock()
render()
local refreshTimer = os.startTimer(REFRESH_SECONDS)
while true do
local event, parameter1, parameter2, parameter3 = os.pullEvent()
if event == "monitor_touch" and parameter1 == monitorName then
handleTouch(parameter2, parameter3)
render()
elseif event == "timer" and parameter1 == refreshTimer then
if armedAction and os.clock() > armedUntil then
armedAction = nil
armedUntil = 0
statusText = "Bestaetigung abgelaufen"
statusColor = colors.gray
end
refreshStock()
render()
refreshTimer = os.startTimer(REFRESH_SECONDS)
elseif event == "peripheral_detach" or event == "peripheral" then
refreshStock()
render()
end
end