diff --git a/basis/node_store.lua b/basis/node_store.lua index f22c554..9e823e2 100644 --- a/basis/node_store.lua +++ b/basis/node_store.lua @@ -153,6 +153,18 @@ function techage.get_nvm(pos) return block[key2] end +-- Returns true/false +function techage.has_nvm(pos) + local key1, key2 = get_keys(pos) + + if not NvmStore[key1] then + NvmStore[key1] = backend.get_mapblock_data(key1) + push(key1) + end + + return NvmStore[key1][key2] ~= nil +end + function techage.peek_nvm(pos) local key1, key2 = get_keys(pos) local block = NvmStore[key1] or {} diff --git a/basis/pack_lib.lua b/basis/pack_lib.lua new file mode 100644 index 0000000..155cd3a --- /dev/null +++ b/basis/pack_lib.lua @@ -0,0 +1,88 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019-2024 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + Packing functions + +]]-- + +-- for lazy programmers +local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end +local M = minetest.get_meta + +-- string/usercode conversion +local function usercode_to_string(tbl) + if tbl and tbl.inventory then + for list_name,list in pairs(tbl.inventory) do + for i,item in ipairs(list) do + tbl.inventory[list_name][i] = item:to_string() + end + end + end +end + +local function string_to_usercode(tbl) + if tbl and tbl.inventory then + for list_name,list in pairs(tbl.inventory) do + for i,item in ipairs(list) do + tbl.inventory[list_name][i] = ItemStack(item) + end + end + end +end + +-- pack/unpack node nvm data +local function pack_nvm(pos) + if techage.has_nvm(pos) then + local s = minetest.serialize(techage.get_nvm(pos)) + techage.del_mem(pos) + return s + end +end + +local function unpack_nvm(pos, s) + if s and s ~= "" then + local tbl = minetest.deserialize(s) + local nvm = techage.get_nvm(pos) + for k,v in pairs(tbl) do + nvm.k = v + end + end +end + +-- pack/unpack node metedata +local function pack_meta(pos) + local tbl = M(pos):to_table() or {} + usercode_to_string(tbl) + return minetest.serialize(tbl) +end + +local function unpack_meta(pos, s) + if s and s ~= "" then + local tbl = minetest.deserialize(s) or {} + string_to_usercode(tbl) + M(pos):from_table(tbl) + end +end + +------------------------------------------------------------------------------- +-- preserve/restore API functions +------------------------------------------------------------------------------- + +function techage.preserve_nodedata(pos) + local smeta = pack_meta(pos) + local snvm = pack_nvm(pos) + return minetest.serialize({smeta = smeta, snvm = snvm}) +end + +function techage.restore_nodedata(pos, s) + local tbl = minetest.deserialize(s) or {} + unpack_nvm(pos, tbl.snvm) + unpack_meta(pos, tbl.smeta) +end diff --git a/init.lua b/init.lua index b0d2009..f359717 100644 --- a/init.lua +++ b/init.lua @@ -106,6 +106,7 @@ dofile(MP.."/basis/shared_inv.lua") dofile(MP.."/basis/shared_tank.lua") dofile(MP.."/basis/teleport.lua") dofile(MP.."/basis/fly_lib.lua") +dofile(MP.."/basis/pack_lib.lua") -- Main doc dofile(MP.."/doc/guide.lua") diff --git a/logic/terminal.lua b/logic/terminal.lua index c8776f6..cf6887e 100644 --- a/logic/terminal.lua +++ b/logic/terminal.lua @@ -3,7 +3,7 @@ Terminal ======== - Copyright (C) 2018-2021 Joachim Stolberg + Copyright (C) 2018-2024 Joachim Stolberg AGPL v3 See LICENSE.txt for more information @@ -334,6 +334,9 @@ local function register_terminal(name, description, tiles, node_box, selection_b techage.remove_node(pos, oldnode, oldmetadata) end, + preserve_nodedata = techage.preserve_nodedata, + restore_nodedata = techage.restore_nodedata, + paramtype = "light", use_texture_alpha = techage.CLIP, sunlight_propagates = true, diff --git a/tools/assembly_tool.lua b/tools/assembly_tool.lua index 53cb6a5..7378d9d 100644 --- a/tools/assembly_tool.lua +++ b/tools/assembly_tool.lua @@ -72,12 +72,27 @@ local function remove_node(pos, digger) if InvalidBlocks[node.name] then return end - + if ndef.can_dig and not ndef.can_dig(pos, digger) then return end - if number ~= "" and ndef and ndef.after_dig_node then + if ndef and ndef.preserve_nodedata then + local s = ndef.preserve_nodedata(pos, node) + imeta:set_string("node_data", s) + minetest.remove_node(pos) + if ndef.after_dig_node then + ndef.after_dig_node(pos, node, oldmetadata, digger) + end + if number ~= "" then + techage.post_remove_node(pos) + imeta:set_string("node_number", number) + imeta:set_string("description", ndef.description .. " : " .. number) + else + imeta:set_string("description", ndef.description .. " (preserved)") + end + return item + elseif number ~= "" and ndef and ndef.after_dig_node then minetest.remove_node(pos) ndef.after_dig_node(pos, node, oldmetadata, digger) techage.post_remove_node(pos) @@ -93,8 +108,16 @@ local function place_node(pos, item, placer, pointed_thing) local name = item:get_name() local param2 = minetest.dir_to_facedir(placer:get_look_dir()) local ndef = minetest.registered_nodes[name] - - if number ~= "" and ndef and ndef.after_place_node then + + if ndef and ndef.restore_nodedata then + if number ~= "" then + techage.pre_add_node(pos, number) + end + minetest.add_node(pos, {name = name, param2 = param2}) + local s = imeta:get_string("node_data") + ndef.restore_nodedata(pos, s) + return true + elseif number ~= "" and ndef and ndef.after_place_node then techage.pre_add_node(pos, number) minetest.add_node(pos, {name = name, param2 = param2}) ndef.after_place_node(pos, placer, item, pointed_thing)