diff options
author | Mattes D <github@xoft.cz> | 2019-12-20 22:10:24 +0100 |
---|---|---|
committer | Mattes D <github@xoft.cz> | 2019-12-28 22:43:35 +0100 |
commit | 2d6f6a574d8dd6a94dc13cb51628626d99c1853a (patch) | |
tree | 450b60da6dba1b8f7d603f6d3f2323235a0d83b7 /Tools/BlockTypePaletteGenerator/Generator.lua | |
parent | Moved ProtocolBlockTypePalette functionality into BlockTypePalette. (diff) | |
download | cuberite-2d6f6a574d8dd6a94dc13cb51628626d99c1853a.tar cuberite-2d6f6a574d8dd6a94dc13cb51628626d99c1853a.tar.gz cuberite-2d6f6a574d8dd6a94dc13cb51628626d99c1853a.tar.bz2 cuberite-2d6f6a574d8dd6a94dc13cb51628626d99c1853a.tar.lz cuberite-2d6f6a574d8dd6a94dc13cb51628626d99c1853a.tar.xz cuberite-2d6f6a574d8dd6a94dc13cb51628626d99c1853a.tar.zst cuberite-2d6f6a574d8dd6a94dc13cb51628626d99c1853a.zip |
Diffstat (limited to '')
-rw-r--r-- | Tools/BlockTypePaletteGenerator/Generator.lua | 180 |
1 files changed, 127 insertions, 53 deletions
diff --git a/Tools/BlockTypePaletteGenerator/Generator.lua b/Tools/BlockTypePaletteGenerator/Generator.lua index f33f2b789..b052ffa92 100644 --- a/Tools/BlockTypePaletteGenerator/Generator.lua +++ b/Tools/BlockTypePaletteGenerator/Generator.lua @@ -1,14 +1,33 @@ --- lib/lunajson/src/ is not in default Lua package paths +-- Generator.lua + +--[[ +Crafts an intermediate block palette format to be read by Cuberite. +It processes the blocks.json report file (https://wiki.vg/Data_Generators) +into a file that can be loaded into a BlockTypePalette (and is to be stored +as Server/Protocol/<version>/base.btp.txt). + +The output format is the regular TSV BlockTypePalette, described in the +$/src/BlockTypePalette.h file. +--]] + + + + +-- Allow Lua to load libraries in our subfolder: package.path = 'lib/lunajson/src/?.lua;' .. package.path; + + + + --- Prints usage instructions to stdout. --- If the optional `message` is passed, output is prepended by message _and_ +-- If the optional `aMessage` is passed, output is prepended by message _and_ -- redirected to stderr. -function usage(message) - if message then +local function usage(aMessage) + if aMessage then io.output(io.stderr); - io.write(message, "\n\n"); + io.write(aMessage, "\n\n"); end io.write( "Usage: lua Generator.lua INPUTFILE OUTPUTFILE\n".. @@ -22,70 +41,125 @@ function usage(message) end --- Test whether the script is run in a path where it can load it's libraries -if not pcall(function() require("lunajson.decoder") end) then - usage("Could not load required libraries, please run `Generator.lua` ".. - "within its directory and make sure to run `git submodule update`."); -end --- Check/Prepare CLI arguments -local inpath, outpath = ...; -io.input(io.stdin); -io.output(io.stdout); -if select("#", ...) ~= 2 then - usage("Incorrect number of arguments."); +--- Parses the JSON registry into a Lua table +--[[ The returned array-table has the following format: +{ + { id = 1, blockTypeName = "minecraft:stone", properties = {key = value, ...} }, + ... +} +--]] +local function parseRegistry(aBlockRegistryJsonStr) + assert(type(aBlockRegistryJsonStr) == "string") + + local lj = require("lunajson") + local input = lj.decode(aBlockRegistryJsonStr) + local registry = {} + local idx = 1 + for blockTypeName, blockData in pairs(input) do + for _, state in pairs(blockData.states) do + registry[idx] = { + id = state.id, + blockTypeName = blockTypeName, + properties = state.properties, + } + idx = idx + 1 + end + end + return registry end -if inpath ~= "-" then - local handle, err = io.open(inpath, "r"); - io.input(handle or usage(err)); -end -if outpath ~= "-" then - local handle, err = io.open(outpath, "w"); - io.output(handle or usage(err)); -end --- Main program starts here -local decode = (require("lunajson.decoder"))(); -local encode = (require("lunajson.encoder"))(); -local input = decode(io.input():read("*a")); -local registry = {}; -local max_id = -1; +--- Serializes the properties from the JSON / array table format into a single output string +-- Concatenates all properties with \t as the delimiting character +local function serializeProperties(aProperties) + local res = {} + local idx = 1 + for k, v in pairs(aProperties or {}) do + res[idx] = k + res[idx + 1] = v + idx = idx + 2 + end + return table.concat(res, "\t") +end + -for blockname, blockdata in pairs(input) do - for i = 1, #(blockdata.states or {}) do - local state = blockdata.states[i]; - assert(registry[state.id + 1] == nil, "Ensure no duplicate IDs"); - -- needed in the end to verify we got no holes in the array: - max_id = math.max(max_id, state.id); - registry[state.id + 1] = { - id = assert(state.id, "id is required."), - name = assert(blockname, "Block type name is required."), - -- default = state.default or nil, -- may need this later - props = state.properties, - }; +--- Returns the prefix that is common for all block type names in the registry +-- aRegistry is the parsed registry, as returned from parseRegistry() +local function findCommonPrefix(aRegistryTable) + local prefix = aRegistryTable[1].blockTypeName + local len = string.len(prefix) + local sub = string.sub + for _, block in ipairs(aRegistryTable) do + while (sub(block.blockTypeName, 1, len) ~= prefix) do + len = len - 1 + if (len == 0) then + return "" + end + prefix = sub(prefix, 1, len) + end end + return prefix end --- The following assertion is not necessary by the current spec, but is required --- by how lunajson distinguishes objects from arrays. Also if this fails, it is --- _very_ likely that the input file is faulty. -assert(#registry == max_id + 1, "Ensure that registry has contiguous keys"); -local out = { - Metadata = { - ProtocolBlockTypePaletteVersion = 1 - }, - Palette = registry -}; -io.write(encode(out), "\n"); + +-- Test whether the script is run in a path where it can load it's libraries +if not(pcall(function() require("lunajson") end)) then + usage( + "Could not load required libraries, please run `Generator.lua` " .. + "within its directory and make sure to run `git submodule update`." + ) +end + +-- Check/Prepare CLI arguments +local inpath, outpath = ...; +inpath = inpath or "blocks.json" +outpath = outpath or "base.btp.txt" +if (inpath ~= "-") then + local handle, err = io.open(inpath, "r") + io.input(handle or usage(err)) +end +if (outpath ~= "-") then + local handle, err = io.open(outpath, "w") + io.output(handle or usage(err)) +end + +-- Parse the registry: +local registry = parseRegistry(io.input():read("*a")) +local commonPrefix = findCommonPrefix(registry) + +-- Sort the entries: +table.sort(registry, + function (entry1, entry2) + return (entry1.id < entry2.id) + end +) + +-- Write out the output format: +io.write("BlockTypePalette\n") +io.write("FileVersion\t1\n") +io.write("CommonPrefix\t", commonPrefix, "\n") +io.write("\n") +local prefixLen = string.len(commonPrefix) + 1 +for _, entry in ipairs(registry) do + local props = serializeProperties(entry.properties) + if (props ~= "") then + props = "\t" .. props + end + io.write( + entry.id, "\t", + string.sub(entry.blockTypeName, prefixLen), + props, "\n" + ) +end |