Buckaroo Banzai 9cd093046d
schematic rotation (#1)
* schematic rotation

* fixes

* remove auto-rotation code

* schematic encoding v2

* testing

* working encode/decode

* rotate schematic

* spec

* rotate dialog

* skip if rotation == 0

* wip

* wip

* wip

* fix order

* fix metadata rotation

---------

Co-authored-by: BuckarooBanzay <BuckarooBanzay@users.noreply.github.com>
2024-02-29 13:15:18 +01:00

101 lines
2.8 KiB
Lua

local char, byte = string.char, string.byte
local function encode_uint16(int)
local a, b = int % 0x100, int / 0x100
return char(a, b)
end
local function decode_uint16(str, ofs)
ofs = ofs or 1
local a = byte(str, ofs)
local b = byte(str, ofs + 1)
return a + b * 0x100
end
-- nodeid -> name
local nodeid_name_mapping = {}
function pick_and_place.encode_schematic(schematic)
-- list of strings
local node_id_data = {}
local param2_data = {}
local nodeid_mapping = {}
-- nodeid -> true
local nodeids = {}
for i = 1, #schematic.node_id_data do
local node_id = schematic.node_id_data[i]
nodeids[node_id] = true
table.insert(node_id_data, encode_uint16(node_id))
table.insert(param2_data, char(schematic.param2_data[i]))
end
for nodeid in pairs(nodeids) do
local name = nodeid_name_mapping[nodeid]
if not name then
name = minetest.get_name_from_content_id(nodeid)
nodeid_name_mapping[nodeid] = name
end
nodeid_mapping[nodeid] = name
end
local serialized_data = minetest.serialize({
version = 2,
node_id_data = table.concat(node_id_data),
param2_data = table.concat(param2_data),
metadata = schematic.metadata,
nodeid_mapping = nodeid_mapping,
size = schematic.size
})
local compressed_data = minetest.compress(serialized_data, "deflate")
local encoded_data = minetest.encode_base64(compressed_data)
return encoded_data
end
-- name -> nodeid
local name_nodeid_mapping = {}
function pick_and_place.decode_schematic(encoded_data)
local compressed_data = minetest.decode_base64(encoded_data)
local serialized_data = minetest.decompress(compressed_data, "deflate")
local data = minetest.deserialize(serialized_data)
if data.version ~= 2 then
return false, "invalid version: " .. (data.version or "nil")
end
local schematic = {
node_id_data = {},
param2_data = {},
metadata = data.metadata,
size = data.size
}
-- foreign_nodeid -> local_nodeid
local localized_id_mapping = {}
for foreign_nodeid, name in pairs(data.nodeid_mapping) do
local local_nodeid = name_nodeid_mapping[name]
if not local_nodeid then
local_nodeid = minetest.get_content_id(name)
name_nodeid_mapping[name] = local_nodeid
end
localized_id_mapping[foreign_nodeid] = local_nodeid
end
for i = 1, #data.param2_data do
-- localize nodeid mapping
local foreign_nodeid = decode_uint16(data.node_id_data, 1 + ((i-1) * 2))
local local_nodeid = localized_id_mapping[foreign_nodeid]
table.insert(schematic.node_id_data, local_nodeid)
table.insert(schematic.param2_data, byte(data.param2_data, i))
end
return schematic
end