201 lines
5.4 KiB
Lua
201 lines
5.4 KiB
Lua
-- ATM10 Create factory peripheral discovery
|
|
-- Read-only: this program does not send packages or change redstone outputs.
|
|
|
|
local OUTPUT_FILE = "factory_peripheral_debug.txt"
|
|
local MAX_TABLE_ENTRIES = 500
|
|
local MAX_DEPTH = 5
|
|
local MAX_VALUE_LENGTH = 30000
|
|
|
|
local lines = {}
|
|
|
|
local function emit(value)
|
|
local line = tostring(value)
|
|
lines[#lines + 1] = line
|
|
print(line)
|
|
end
|
|
|
|
local function sortedKeys(value)
|
|
local keys = {}
|
|
for key in pairs(value) do
|
|
keys[#keys + 1] = key
|
|
end
|
|
table.sort(keys, function(a, b)
|
|
return tostring(a) < tostring(b)
|
|
end)
|
|
return keys
|
|
end
|
|
|
|
local function serialize(value, depth, seen)
|
|
depth = depth or 0
|
|
seen = seen or {}
|
|
|
|
local valueType = type(value)
|
|
if valueType == "string" then
|
|
return string.format("%q", value)
|
|
elseif valueType ~= "table" then
|
|
return tostring(value)
|
|
end
|
|
|
|
if seen[value] then
|
|
return "<cycle>"
|
|
end
|
|
if depth >= MAX_DEPTH then
|
|
return "<max-depth>"
|
|
end
|
|
|
|
seen[value] = true
|
|
local parts = { "{" }
|
|
local keys = sortedKeys(value)
|
|
local limit = math.min(#keys, MAX_TABLE_ENTRIES)
|
|
|
|
for index = 1, limit do
|
|
local key = keys[index]
|
|
parts[#parts + 1] = " " .. string.rep(" ", depth)
|
|
.. "[" .. serialize(key, depth + 1, seen) .. "] = "
|
|
.. serialize(value[key], depth + 1, seen) .. ","
|
|
end
|
|
|
|
if #keys > limit then
|
|
parts[#parts + 1] = " " .. string.rep(" ", depth)
|
|
.. "<truncated " .. tostring(#keys - limit) .. " entries>"
|
|
end
|
|
|
|
parts[#parts + 1] = string.rep(" ", depth) .. "}"
|
|
seen[value] = nil
|
|
return table.concat(parts, "\n")
|
|
end
|
|
|
|
local function packResults(...)
|
|
return { n = select("#", ...), ... }
|
|
end
|
|
|
|
local function hasMethod(methods, wanted)
|
|
for _, method in ipairs(methods) do
|
|
if method == wanted then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function safeRead(name, method)
|
|
local result = packResults(pcall(peripheral.call, name, method))
|
|
if not result[1] then
|
|
return false, tostring(result[2])
|
|
end
|
|
|
|
local values = { n = result.n - 1 }
|
|
for index = 2, result.n do
|
|
values[index - 1] = result[index]
|
|
end
|
|
return true, values
|
|
end
|
|
|
|
local function truncate(value)
|
|
if #value <= MAX_VALUE_LENGTH then
|
|
return value
|
|
end
|
|
return value:sub(1, MAX_VALUE_LENGTH)
|
|
.. "\n<truncated " .. tostring(#value - MAX_VALUE_LENGTH) .. " characters>"
|
|
end
|
|
|
|
local function typeList(name)
|
|
local result = packResults(peripheral.getType(name))
|
|
local types = {}
|
|
for index = 1, result.n do
|
|
if result[index] ~= nil then
|
|
types[#types + 1] = tostring(result[index])
|
|
end
|
|
end
|
|
return types
|
|
end
|
|
|
|
local names = peripheral.getNames()
|
|
table.sort(names)
|
|
|
|
emit("ATM10 CREATE FACTORY PERIPHERAL DEBUG")
|
|
emit("Computer ID: " .. tostring(os.getComputerID()))
|
|
emit("Computer label: " .. tostring(os.getComputerLabel()))
|
|
emit("Uptime timer/clock: " .. tostring(os.clock()))
|
|
emit("Peripheral count: " .. tostring(#names))
|
|
emit(string.rep("=", 72))
|
|
|
|
-- Only no-argument, read-only methods belong in this list.
|
|
local readMethods = {
|
|
"getAddress",
|
|
"getName",
|
|
"getSize",
|
|
"getNetworkId",
|
|
"getFrequency",
|
|
"isConnected",
|
|
"list",
|
|
"stock",
|
|
}
|
|
|
|
local monitorName = nil
|
|
|
|
for peripheralIndex, name in ipairs(names) do
|
|
local methods = peripheral.getMethods(name) or {}
|
|
table.sort(methods)
|
|
local types = typeList(name)
|
|
|
|
emit("")
|
|
emit("PERIPHERAL " .. tostring(peripheralIndex) .. "/" .. tostring(#names))
|
|
emit("Name: " .. name)
|
|
emit("Type(s): " .. table.concat(types, ", "))
|
|
emit("Methods (" .. tostring(#methods) .. "): " .. table.concat(methods, ", "))
|
|
|
|
for _, peripheralType in ipairs(types) do
|
|
if peripheralType == "monitor" and monitorName == nil then
|
|
monitorName = name
|
|
end
|
|
end
|
|
|
|
for _, method in ipairs(readMethods) do
|
|
if hasMethod(methods, method) then
|
|
local ok, value = safeRead(name, method)
|
|
if ok then
|
|
emit("READ " .. method .. " OK:")
|
|
emit(truncate(serialize(value)))
|
|
else
|
|
emit("READ " .. method .. " ERROR: " .. value)
|
|
end
|
|
end
|
|
end
|
|
|
|
emit(string.rep("-", 72))
|
|
end
|
|
|
|
local file = assert(fs.open(OUTPUT_FILE, "w"))
|
|
file.write(table.concat(lines, "\n"))
|
|
file.write("\n")
|
|
file.close()
|
|
|
|
if monitorName then
|
|
local monitor = peripheral.wrap(monitorName)
|
|
monitor.setBackgroundColor(colors.black)
|
|
monitor.setTextColor(colors.white)
|
|
monitor.setTextScale(0.5)
|
|
monitor.clear()
|
|
|
|
local width, height = monitor.getSize()
|
|
local function centered(row, text, color)
|
|
if row < 1 or row > height then
|
|
return
|
|
end
|
|
monitor.setTextColor(color or colors.white)
|
|
monitor.setCursorPos(math.max(1, math.floor((width - #text) / 2) + 1), row)
|
|
monitor.write(text:sub(1, width))
|
|
end
|
|
|
|
centered(math.max(1, math.floor(height / 2) - 2), "CREATE FACTORY DEBUG", colors.cyan)
|
|
centered(math.max(1, math.floor(height / 2)), "DUMP COMPLETE", colors.lime)
|
|
centered(math.max(1, math.floor(height / 2) + 1), tostring(#names) .. " peripherals found", colors.white)
|
|
centered(math.max(1, math.floor(height / 2) + 3), OUTPUT_FILE, colors.lightGray)
|
|
end
|
|
|
|
print("")
|
|
print("Debug complete.")
|
|
print("Created: " .. OUTPUT_FILE)
|
|
print("Please send this TXT file to Codex.")
|