From 6c165c7344593df3fb863c6ce6ec63b3218b1fc5 Mon Sep 17 00:00:00 2001 From: BuckarooBanzay Date: Sat, 24 Jun 2023 12:07:47 +0200 Subject: [PATCH] localize nodeids for portability --- place_tool.lua | 5 ++++- serialize.lua | 52 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/place_tool.lua b/place_tool.lua index e7459c5..1c7c5e7 100644 --- a/place_tool.lua +++ b/place_tool.lua @@ -13,7 +13,10 @@ minetest.register_tool("pick_and_place:place", { local distance = vector.distance(vector.new(), size) local pos1 = pick_and_place.get_pointed_position(player, math.max(10, distance)) - pick_and_place.deserialize(pos1, schematic) + local success, msg = pick_and_place.deserialize(pos1, schematic) + if not success then + minetest.chat_send_player(player:get_player_name(), "Placement error: " .. msg) + end end, on_step = function(itemstack, player) local playername = player:get_player_name() diff --git a/serialize.lua b/serialize.lua index 16e3966..209c882 100644 --- a/serialize.lua +++ b/serialize.lua @@ -13,6 +13,9 @@ local function decode_uint16(str, ofs) return a + b * 0x100 end +-- nodeid -> name +local nodeid_name_mapping = {} + function pick_and_place.serialize(pos1, pos2) local manip = minetest.get_voxel_manip() local e1, e2 = manip:read_from_map(pos1, pos2) @@ -24,23 +27,42 @@ function pick_and_place.serialize(pos1, pos2) local mapdata = {} local metadata = {} + -- nodeid -> true + local nodeids = {} + for z=pos1.z,pos2.z do for x=pos1.x,pos2.x do for y=pos1.y,pos2.y do local i = area:index(x,y,z) + nodeids[node_data[i]] = true table.insert(mapdata, encode_uint16(node_data[i])) table.insert(mapdata, char(param2[i])) end end end + -- id -> name + local nodeid_mapping = {} + + 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 + -- TODO: metadata local size = vector.add(vector.subtract(pos2, pos1), 1) local data = { + version = 1, mapdata = table.concat(mapdata), metadata = metadata, + nodeid_mapping = nodeid_mapping, size = size } @@ -51,13 +73,18 @@ function pick_and_place.serialize(pos1, pos2) return encoded_data end +-- name -> nodeid +local name_nodeid_mapping = {} function pick_and_place.deserialize(pos1, 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 ~= 1 then + return false, "invalid version: " .. (data.version or "nil") + end + local pos2 = vector.add(pos1, vector.subtract(data.size, 1)) local manip = minetest.get_voxel_manip() @@ -67,13 +94,30 @@ function pick_and_place.deserialize(pos1, encoded_data) local node_data = manip:get_data() local param2 = manip:get_param2_data() - local j = 1 + -- 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 + + local j = 1 for z=pos1.z,pos2.z do for x=pos1.x,pos2.x do for y=pos1.y,pos2.y do local i = area:index(x,y,z) - node_data[i] = decode_uint16(data.mapdata, j) + local foreign_nodeid = decode_uint16(data.mapdata, j) + + -- localize nodeid mapping + local local_nodeid = localized_id_mapping[foreign_nodeid] + node_data[i] = local_nodeid + j = j + 2 param2[i] = byte(data.mapdata, j) j = j + 1 @@ -84,4 +128,6 @@ function pick_and_place.deserialize(pos1, encoded_data) manip:set_data(node_data) manip:set_param2_data(param2) manip:write_to_map() + + return true end