Add first Create logistics test controller
This commit is contained in:
@@ -0,0 +1,309 @@
|
||||
-- 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
|
||||
Reference in New Issue
Block a user