* 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>
101 lines
2.8 KiB
Lua
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 |