test: add block_reader NBT dumper for advanced display
Reads the adjacent block (Advanced Display) via Advanced Peripherals block_reader and writes registry name, block state, and NBT data as structured text to blockreader_display_nbt.txt.
This commit is contained in:
@@ -0,0 +1,228 @@
|
||||
-- BlockReader NBT Dumper for Advanced Display Block
|
||||
-- Reads block NBT via Advanced Peripherals block_reader and writes to txt
|
||||
|
||||
local COLORS = {
|
||||
INFO = colors.white,
|
||||
WARN = colors.yellow,
|
||||
ERROR = colors.red,
|
||||
SUCCESS = colors.green
|
||||
}
|
||||
|
||||
local OUTPUT_FILE = "blockreader_display_nbt.txt"
|
||||
|
||||
local function log(level, message)
|
||||
local timestamp = os.date("%H:%M:%S")
|
||||
local logMessage = string.format("[%s][%s] %s", timestamp, level, message)
|
||||
local color = COLORS[level] or colors.white
|
||||
local oldColor = term.getTextColor()
|
||||
term.setTextColor(color)
|
||||
print(logMessage)
|
||||
term.setTextColor(oldColor)
|
||||
end
|
||||
|
||||
local function serializeValue(value, indent)
|
||||
indent = indent or 0
|
||||
local pad = string.rep(" ", indent)
|
||||
|
||||
local t = type(value)
|
||||
if t == "nil" then
|
||||
return "nil"
|
||||
elseif t == "boolean" then
|
||||
return value and "true" or "false"
|
||||
elseif t == "number" then
|
||||
return tostring(value)
|
||||
elseif t == "string" then
|
||||
local escaped = value:gsub("\\", "\\\\"):gsub("\n", "\\n"):gsub("\r", "\\r"):gsub("\t", "\\t")
|
||||
return string.format("%q", escaped)
|
||||
elseif t == "table" then
|
||||
local lines = {}
|
||||
local isArray = true
|
||||
local maxIndex = 0
|
||||
for k, v in pairs(value) do
|
||||
if type(k) ~= "number" or k < 1 or math.floor(k) ~= k then
|
||||
isArray = false
|
||||
break
|
||||
end
|
||||
if k > maxIndex then maxIndex = k end
|
||||
end
|
||||
if isArray then
|
||||
for i = 1, maxIndex do
|
||||
if value[i] ~= nil then
|
||||
table.insert(lines, pad .. " [" .. tostring(i) .. "] = " .. serializeValue(value[i], indent + 1))
|
||||
end
|
||||
end
|
||||
else
|
||||
local keys = {}
|
||||
for k, _ in pairs(value) do
|
||||
table.insert(keys, k)
|
||||
end
|
||||
table.sort(keys, function(a, b)
|
||||
local ta, tb = type(a), type(b)
|
||||
if ta == tb then
|
||||
if ta == "number" then return a < b end
|
||||
return tostring(a) < tostring(b)
|
||||
end
|
||||
return ta < tb
|
||||
end)
|
||||
for _, k in ipairs(keys) do
|
||||
local keyStr
|
||||
if type(k) == "string" and k:match("^[%a_][%w_]*$") then
|
||||
keyStr = k
|
||||
else
|
||||
keyStr = "[" .. serializeValue(k, 0) .. "]"
|
||||
end
|
||||
local v = value[k]
|
||||
if type(v) == "table" and next(v) ~= nil then
|
||||
table.insert(lines, pad .. " " .. keyStr .. " = {")
|
||||
table.insert(lines, serializeValue(v, indent + 1))
|
||||
table.insert(lines, pad .. " }")
|
||||
else
|
||||
table.insert(lines, pad .. " " .. keyStr .. " = " .. serializeValue(v, indent + 1))
|
||||
end
|
||||
end
|
||||
end
|
||||
if #lines == 0 then
|
||||
return "{}"
|
||||
end
|
||||
if isArray then
|
||||
return table.concat(lines, "\n")
|
||||
end
|
||||
table.insert(lines, 1, pad .. "{")
|
||||
table.insert(lines, pad .. "}")
|
||||
return table.concat(lines, "\n")
|
||||
else
|
||||
return "<" .. t .. ">"
|
||||
end
|
||||
end
|
||||
|
||||
local function findBlockReader()
|
||||
local readers = { peripheral.find("blockReader") }
|
||||
if #readers > 0 then
|
||||
return readers[1], peripheral.getName(readers[1])
|
||||
end
|
||||
for _, side in ipairs(rs.getSides()) do
|
||||
if peripheral.isPresent(side) and peripheral.getType(side) == "blockReader" then
|
||||
return peripheral.wrap(side), side
|
||||
end
|
||||
end
|
||||
local names = peripheral.getNames()
|
||||
for _, name in ipairs(names) do
|
||||
if peripheral.getType(name) == "blockReader" then
|
||||
return peripheral.wrap(name), name
|
||||
end
|
||||
end
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
local function writeToFile(content)
|
||||
local handle = fs.open(OUTPUT_FILE, "w")
|
||||
if not handle then
|
||||
return false, "Cannot open output file"
|
||||
end
|
||||
handle.write(content)
|
||||
handle.close()
|
||||
return true, nil
|
||||
end
|
||||
|
||||
local function main()
|
||||
term.clear()
|
||||
term.setCursorPos(1, 1)
|
||||
print("=== BlockReader Advanced Display NBT Dumper ===")
|
||||
print("Output file: " .. OUTPUT_FILE)
|
||||
print()
|
||||
|
||||
log("INFO", "Looking for block_reader peripheral...")
|
||||
local reader, readerName = findBlockReader()
|
||||
if not reader then
|
||||
log("ERROR", "block_reader not found. Connect a block_reader Advanced Peripheral to the computer.")
|
||||
return 1
|
||||
end
|
||||
log("SUCCESS", "block_reader found: " .. tostring(readerName))
|
||||
|
||||
if type(reader.isBlockPresent) ~= "function" then
|
||||
log("WARN", "isBlockPresent() not available on this block_reader, trying direct read...")
|
||||
else
|
||||
local ok, present = pcall(function() return reader.isBlockPresent() end)
|
||||
if ok and not present then
|
||||
log("ERROR", "No block in front of block_reader. Place the Advanced Display block adjacent to the block_reader.")
|
||||
return 2
|
||||
end
|
||||
end
|
||||
|
||||
local output = {}
|
||||
table.insert(output, "Advanced Display Block NBT Dump")
|
||||
table.insert(output, "Generated: " .. os.date("%Y-%m-%d %H:%M:%S"))
|
||||
table.insert(output, "BlockReader: " .. tostring(readerName))
|
||||
table.insert(output, string.rep("=", 60))
|
||||
table.insert(output, "")
|
||||
|
||||
if type(reader.getBlockName) == "function" then
|
||||
local ok, name = pcall(function() return reader.getBlockName() end)
|
||||
if ok and name then
|
||||
table.insert(output, "[Block Registry Name]")
|
||||
table.insert(output, " " .. tostring(name))
|
||||
table.insert(output, "")
|
||||
end
|
||||
end
|
||||
|
||||
if type(reader.getBlockState) == "function" then
|
||||
local ok, state = pcall(function() return reader.getBlockState() end)
|
||||
if ok and state then
|
||||
table.insert(output, "[Block State]")
|
||||
if type(state) == "table" and next(state) == nil then
|
||||
table.insert(output, " (empty)")
|
||||
else
|
||||
table.insert(output, serializeValue(state, 0))
|
||||
end
|
||||
table.insert(output, "")
|
||||
end
|
||||
end
|
||||
|
||||
if type(reader.getBlockData) == "function" then
|
||||
local ok, data = pcall(function() return reader.getBlockData() end)
|
||||
if ok and data then
|
||||
table.insert(output, "[Block NBT Data]")
|
||||
if type(data) == "table" and next(data) == nil then
|
||||
table.insert(output, " (empty)")
|
||||
else
|
||||
table.insert(output, serializeValue(data, 0))
|
||||
end
|
||||
table.insert(output, "")
|
||||
else
|
||||
log("WARN", "getBlockData() failed or returned nothing: " .. tostring(data))
|
||||
end
|
||||
else
|
||||
log("WARN", "getBlockData() not found on this block_reader")
|
||||
end
|
||||
|
||||
local fullContent = table.concat(output, "\n")
|
||||
local ok, err = writeToFile(fullContent)
|
||||
if not ok then
|
||||
log("ERROR", "Failed to write file: " .. tostring(err))
|
||||
return 3
|
||||
end
|
||||
|
||||
log("SUCCESS", "NBT data written to " .. OUTPUT_FILE)
|
||||
local size = fs.getSize(OUTPUT_FILE)
|
||||
log("INFO", "File size: " .. tostring(size) .. " bytes")
|
||||
|
||||
print()
|
||||
print("Press any key to exit...")
|
||||
os.pullEvent("key")
|
||||
return 0
|
||||
end
|
||||
|
||||
local exitCode = 0
|
||||
local ok, err = pcall(main)
|
||||
if not ok then
|
||||
log("ERROR", "Program crashed: " .. tostring(err))
|
||||
exitCode = 99
|
||||
end
|
||||
|
||||
if exitCode ~= 0 then
|
||||
print()
|
||||
print("Press any key to exit...")
|
||||
os.pullEvent("key")
|
||||
end
|
||||
|
||||
error("", exitCode)
|
||||
Reference in New Issue
Block a user