mirror of
https://github.com/minetest-mods/digtron.git
synced 2024-08-19 12:24:04 +02:00
hide digtron_id from clients, change "construct" to "assemble", various other tidbits
This commit is contained in:
parent
03c9a81b6b
commit
2283cdbbea
@ -2,6 +2,11 @@
|
|||||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||||
local S, NS = dofile(MP.."/intllib.lua")
|
local S, NS = dofile(MP.."/intllib.lua")
|
||||||
|
|
||||||
|
-- This allows us to know which digtron the player has a formspec open for without
|
||||||
|
-- sending the digtron_id over the network
|
||||||
|
local player_interacting_with_digtron_id = {}
|
||||||
|
local player_interacting_with_digtron_pos = {}
|
||||||
|
|
||||||
local controller_nodebox = {
|
local controller_nodebox = {
|
||||||
type = "fixed",
|
type = "fixed",
|
||||||
fixed = {
|
fixed = {
|
||||||
@ -18,23 +23,24 @@ local controller_nodebox = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
local get_controller_unconstructed_formspec = function(pos, player_name)
|
local get_controller_unassembled_formspec = function(pos, player_name)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
return "size[9,9]"
|
return "size[9,9]"
|
||||||
.. "container[0.5,0]"
|
.. "container[0.5,0]"
|
||||||
.. "button[0,0;1,1;construct;Construct]"
|
.. "button[0,0;1,1;assemble;Assemble]"
|
||||||
.. "field[1.2,0.25;2,1;digtron_name;Digtron name;"..meta:get_string("infotext").."]"
|
.. "field[1.2,0.25;2,1;digtron_name;Digtron name;"..meta:get_string("infotext").."]"
|
||||||
.. "field_close_on_enter[digtron_name;false]"
|
.. "field_close_on_enter[digtron_name;false]"
|
||||||
.. "container_end[]"
|
.. "container_end[]"
|
||||||
end
|
end
|
||||||
|
|
||||||
local get_controller_constructed_formspec = function(pos, digtron_id, player_name)
|
local get_controller_assembled_formspec = function(pos, digtron_id, player_name)
|
||||||
digtron.retrieve_inventory(digtron_id) -- ensures the detatched inventory exists and is populated
|
digtron.retrieve_inventory(digtron_id) -- ensures the detatched inventory exists and is populated
|
||||||
return "size[9,9]"
|
return "size[9,9]"
|
||||||
.. "container[0.5,0]"
|
.. "container[0.5,0]"
|
||||||
.. "button[0,0;1,1;deconstruct;Deconstruct]"
|
.. "button[0,0;1,1;disassemble;Disassemble]"
|
||||||
.. "field[1.2,0.25;2,1;digtron_name;Digtron name;"..digtron.get_name(digtron_id).."]"
|
.. "field[1.2,0.25;2,1;digtron_name;Digtron name;"..digtron.get_name(digtron_id).."]"
|
||||||
.. "field_close_on_enter[digtron_name;false]"
|
.. "field_close_on_enter[digtron_name;false]"
|
||||||
|
.. "button[3,0;1,1;move_forward;Move forward]"
|
||||||
.. "container_end[]"
|
.. "container_end[]"
|
||||||
.. "container[0.5,1]"
|
.. "container[0.5,1]"
|
||||||
.. "list[detached:" .. digtron_id .. ";main;0,0;8,2]" -- TODO: paging system for inventory, guard against non-existent listname
|
.. "list[detached:" .. digtron_id .. ";main;0,0;8,2]" -- TODO: paging system for inventory, guard against non-existent listname
|
||||||
@ -141,23 +147,26 @@ minetest.register_node("digtron:controller", {
|
|||||||
|
|
||||||
meta:set_string("infotext", title)
|
meta:set_string("infotext", title)
|
||||||
meta:set_string("digtron_id", digtron_id)
|
meta:set_string("digtron_id", digtron_id)
|
||||||
|
meta:mark_as_private("digtron_id")
|
||||||
end,
|
end,
|
||||||
|
|
||||||
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||||
|
if clicker == nil then return end
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
local digtron_id = meta:get_string("digtron_id")
|
local digtron_id = meta:get_string("digtron_id")
|
||||||
local player_name
|
local player_name = clicker:get_player_name()
|
||||||
if clicker then player_name = clicker:get_player_name() end
|
|
||||||
|
|
||||||
if digtron_id == "" then
|
if digtron_id == "" then
|
||||||
|
player_interacting_with_digtron_pos[player_name] = pos
|
||||||
minetest.show_formspec(player_name,
|
minetest.show_formspec(player_name,
|
||||||
"digtron_controller_unconstructed:"..minetest.pos_to_string(pos)..":"..player_name,
|
"digtron:controller_unassembled",
|
||||||
get_controller_unconstructed_formspec(pos, player_name))
|
get_controller_unassembled_formspec(pos, player_name))
|
||||||
else
|
else
|
||||||
-- initialized
|
-- initialized
|
||||||
|
player_interacting_with_digtron_id[player_name] = digtron_id
|
||||||
minetest.show_formspec(player_name,
|
minetest.show_formspec(player_name,
|
||||||
"digtron_controller_constructed:"..minetest.pos_to_string(pos)..":"..player_name..":"..digtron_id,
|
"digtron:controller_assembled",
|
||||||
get_controller_constructed_formspec(pos, digtron_id, player_name))
|
get_controller_assembled_formspec(pos, digtron_id, player_name))
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@ -167,30 +176,26 @@ minetest.register_node("digtron:controller", {
|
|||||||
on_blast = digtron.on_blast,
|
on_blast = digtron.on_blast,
|
||||||
})
|
})
|
||||||
|
|
||||||
-- Dealing with an unconstructed Digtron controller
|
-- Dealing with an unassembled Digtron controller
|
||||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
local formname_split = formname:split(":")
|
if formname ~= "digtron:controller_unassembled" then
|
||||||
if #formname_split ~= 3 or formname_split[1] ~= "digtron_controller_unconstructed" then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local pos = minetest.string_to_pos(formname_split[2])
|
|
||||||
if pos == nil then
|
|
||||||
minetest.log("error", "[Digtron] Unable to parse position from formspec name " .. formname)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local name = formname_split[3]
|
|
||||||
if player:get_player_name() ~= name then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
local name = player:get_player_name()
|
||||||
|
local pos = player_interacting_with_digtron_pos[name]
|
||||||
|
|
||||||
if fields.construct then
|
if pos == nil then return end
|
||||||
local digtron_id = digtron.construct(pos, name)
|
|
||||||
|
if fields.assemble then
|
||||||
|
local digtron_id = digtron.assemble(pos, name)
|
||||||
if digtron_id then
|
if digtron_id then
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
meta:set_string("digtron_id", digtron_id)
|
meta:set_string("digtron_id", digtron_id)
|
||||||
|
meta:mark_as_private("digtron_id")
|
||||||
|
player_interacting_with_digtron_id[name] = digtron_id
|
||||||
minetest.show_formspec(name,
|
minetest.show_formspec(name,
|
||||||
"digtron_controller_constructed:"..minetest.pos_to_string(pos)..":"..name..":"..digtron_id,
|
"digtron:controller_assembled",
|
||||||
get_controller_constructed_formspec(pos, digtron_id, name))
|
get_controller_assembled_formspec(pos, digtron_id, name))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -203,39 +208,30 @@ end)
|
|||||||
|
|
||||||
-- Controlling a fully armed and operational Digtron
|
-- Controlling a fully armed and operational Digtron
|
||||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
local formname_split = formname:split(":")
|
if formname ~= "digtron:controller_assembled" then
|
||||||
if #formname_split ~= 4 or formname_split[1] ~= "digtron_controller_constructed" then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local pos = minetest.string_to_pos(formname_split[2])
|
local name = player:get_player_name()
|
||||||
if pos == nil then
|
local digtron_id = player_interacting_with_digtron_id[name]
|
||||||
minetest.log("error", "[Digtron] Unable to parse position from formspec name " .. formname)
|
if digtron_id == nil then return end
|
||||||
return
|
|
||||||
end
|
|
||||||
local name = formname_split[3]
|
|
||||||
if player:get_player_name() ~= name then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local digtron_id = formname_split[4]
|
|
||||||
|
|
||||||
if fields.deconstruct then
|
if fields.disassemble then
|
||||||
minetest.chat_send_all("Deconstructing " .. digtron_id)
|
local pos = digtron.disassemble(digtron_id, name)
|
||||||
|
if pos then
|
||||||
local meta = minetest.get_meta(pos)
|
player_interacting_with_digtron_pos[name] = pos
|
||||||
local digtron_id = meta:get_string("digtron_id")
|
|
||||||
if digtron_id == "" then
|
|
||||||
minetest.log("error", "[Digtron] tried to deconstruct Digtron at pos "
|
|
||||||
.. minetest.pos_to_string(pos) .. " but it had no digtron_id in the node's metadata")
|
|
||||||
else
|
|
||||||
digtron.deconstruct(digtron_id, pos, name)
|
|
||||||
minetest.show_formspec(name,
|
minetest.show_formspec(name,
|
||||||
"digtron_controller_unconstructed:"..minetest.pos_to_string(pos)..":"..name,
|
"digtron:controller_unassembled",
|
||||||
get_controller_unconstructed_formspec(pos, name))
|
get_controller_unassembled_formspec(pos, name))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if fields.move_forward then
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--TODO: this isn't recording the field when using ESC to exit the formspec
|
--TODO: this isn't recording the field when using ESC to exit the formspec
|
||||||
if fields.key_enter_field == "digtron_name" or fields.digtron_name then
|
if fields.key_enter_field == "digtron_name" or fields.digtron_name then
|
||||||
|
local pos = digtron.get_pos(digtron_id)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
meta:set_string("infotext", fields.digtron_name)
|
meta:set_string("infotext", fields.digtron_name)
|
||||||
digtron.set_name(digtron_id, fields.digtron_name)
|
digtron.set_name(digtron_id, fields.digtron_name)
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
default
|
default
|
||||||
intllib?
|
intllib?
|
||||||
|
creative?
|
172
functions.lua
172
functions.lua
@ -3,6 +3,7 @@ local mod_meta = minetest.get_mod_storage()
|
|||||||
digtron.layout = {}
|
digtron.layout = {}
|
||||||
digtron.adjacent = {}
|
digtron.adjacent = {}
|
||||||
digtron.bounding_box = {}
|
digtron.bounding_box = {}
|
||||||
|
digtron.pos = {}
|
||||||
|
|
||||||
--minetest.debug(dump(mod_meta:to_table()))
|
--minetest.debug(dump(mod_meta:to_table()))
|
||||||
|
|
||||||
@ -120,17 +121,17 @@ end)
|
|||||||
--------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
local create_new_id = function()
|
local create_new_id = function()
|
||||||
local last_id = mod_meta:get_int("last_id") -- returns 0 when uninitialized, so 0 will never be a valid digtron_id.
|
local digtron_id = "digtron" .. tostring(math.random(1, 2^21)) -- TODO: use SecureRandom()
|
||||||
local new_id = last_id + 1
|
-- It's super unlikely that we'll get a collision, but what the heck - maybe something will go
|
||||||
mod_meta:set_int("last_id", new_id) -- ensure each call to this method gets a unique number
|
-- wrong with the random number source
|
||||||
|
while mod_meta:get_string(digtron_id..":layout") ~= "" do
|
||||||
local digtron_id = "digtron" .. tostring(new_id)
|
digtron_id = "digtron" .. tostring(math.random(1, 2^21))
|
||||||
|
end
|
||||||
local inv = minetest.create_detached_inventory(digtron_id, detached_inventory_callbacks)
|
local inv = minetest.create_detached_inventory(digtron_id, detached_inventory_callbacks)
|
||||||
|
|
||||||
return digtron_id, inv
|
return digtron_id, inv
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Deletes a Digtron record. Note: just throws everything away, this is not digtron.deconstruct.
|
-- Deletes a Digtron record. Note: just throws everything away, this is not digtron.disassemble.
|
||||||
local dispose_id = function(digtron_id)
|
local dispose_id = function(digtron_id)
|
||||||
minetest.remove_detached_inventory(digtron_id)
|
minetest.remove_detached_inventory(digtron_id)
|
||||||
digtron.layout[digtron_id] = nil
|
digtron.layout[digtron_id] = nil
|
||||||
@ -140,17 +141,22 @@ local dispose_id = function(digtron_id)
|
|||||||
mod_meta:set_string(digtron_id..":adjacent", "")
|
mod_meta:set_string(digtron_id..":adjacent", "")
|
||||||
mod_meta:set_string(digtron_id..":name", "")
|
mod_meta:set_string(digtron_id..":name", "")
|
||||||
mod_meta:set_string(digtron_id..":bounding_box", "")
|
mod_meta:set_string(digtron_id..":bounding_box", "")
|
||||||
|
mod_meta:set_string(digtron_id..":pos", "")
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------
|
||||||
-- Name
|
-- Name
|
||||||
|
|
||||||
|
-- Not bothering with a dynamic table store for names, they're just strings with no need for serialization or deserialization
|
||||||
digtron.get_name = function(digtron_id)
|
digtron.get_name = function(digtron_id)
|
||||||
return mod_meta:get_string(digtron_id..":name")
|
return mod_meta:get_string(digtron_id..":name")
|
||||||
end
|
end
|
||||||
|
|
||||||
digtron.set_name = function(digtron_id, digtron_name)
|
digtron.set_name = function(digtron_id, digtron_name)
|
||||||
|
-- Don't allow a name to be set for a non-existent Digtron
|
||||||
|
if mod_meta:get(digtron_id..":layout") then
|
||||||
mod_meta:set_string(digtron_id..":name", digtron_name)
|
mod_meta:set_string(digtron_id..":name", digtron_name)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------
|
||||||
@ -186,6 +192,10 @@ local persist_adjacent = get_persist_table_function("adjacent")
|
|||||||
local retrieve_adjacent = get_retrieve_table_function("adjacent")
|
local retrieve_adjacent = get_retrieve_table_function("adjacent")
|
||||||
local persist_bounding_box = get_persist_table_function("bounding_box")
|
local persist_bounding_box = get_persist_table_function("bounding_box")
|
||||||
local retrieve_bounding_box = get_retrieve_table_function("bounding_box")
|
local retrieve_bounding_box = get_retrieve_table_function("bounding_box")
|
||||||
|
local persist_pos = get_persist_table_function("pos")
|
||||||
|
local retrieve_pos = get_retrieve_table_function("pos")
|
||||||
|
|
||||||
|
digtron.get_pos = retrieve_pos
|
||||||
|
|
||||||
local cardinal_directions = {
|
local cardinal_directions = {
|
||||||
{x=1,y=0,z=0},
|
{x=1,y=0,z=0},
|
||||||
@ -235,32 +245,32 @@ get_all_adjacent_digtron_nodes = function(pos, digtron_nodes, digtron_adjacent,
|
|||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------------------
|
||||||
-- Construct and deconstruct
|
-- assemble and disassemble
|
||||||
|
|
||||||
local origin_hash = minetest.hash_node_position({x=0,y=0,z=0})
|
local origin_hash = minetest.hash_node_position({x=0,y=0,z=0})
|
||||||
|
|
||||||
-- Returns the id of the new Digtron record, or nil on failure
|
-- Returns the id of the new Digtron record, or nil on failure
|
||||||
digtron.construct = function(root_pos, player_name)
|
digtron.assemble = function(root_pos, player_name)
|
||||||
local node = minetest.get_node(root_pos)
|
local node = minetest.get_node(root_pos)
|
||||||
-- TODO: a more generic test? Not needed with the more generic controller design, as far as I can tell. There's only going to be the one type of controller.
|
-- TODO: a more generic test? Not needed with the more generic controller design, as far as I can tell. There's only going to be the one type of controller.
|
||||||
if node.name ~= "digtron:controller" then
|
if node.name ~= "digtron:controller" then
|
||||||
-- Called on an incorrect node
|
-- Called on an incorrect node
|
||||||
minetest.log("error", "[Digtron] digtron.construct called with pos " .. minetest.pos_to_string(root_pos)
|
minetest.log("error", "[Digtron] digtron.assemble called with pos " .. minetest.pos_to_string(root_pos)
|
||||||
.. " but the node at this location was " .. node.name)
|
.. " but the node at this location was " .. node.name)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
local root_meta = minetest.get_meta(root_pos)
|
local root_meta = minetest.get_meta(root_pos)
|
||||||
if root_meta:contains("digtron_id") then
|
if root_meta:contains("digtron_id") then
|
||||||
-- Already constructed. TODO: validate that the digtron_id actually exists as well
|
-- Already assembled. TODO: validate that the digtron_id actually exists as well
|
||||||
minetest.log("error", "[Digtron] digtron.construct called with pos " .. minetest.pos_to_string(root_pos)
|
minetest.log("error", "[Digtron] digtron.assemble called with pos " .. minetest.pos_to_string(root_pos)
|
||||||
.. " but the controller at this location was already part of a constructed Digtron.")
|
.. " but the controller at this location was already part of a assembled Digtron.")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
local root_hash = minetest.hash_node_position(root_pos)
|
local root_hash = minetest.hash_node_position(root_pos)
|
||||||
local digtron_nodes = {[root_hash] = node} -- Nodes that are part of Digtron.
|
local digtron_nodes = {[root_hash] = node} -- Nodes that are part of Digtron.
|
||||||
-- Initialize with the controller, it won't be added by get_all_adjacent_digtron_nodes
|
-- Initialize with the controller, it won't be added by get_all_adjacent_digtron_nodes
|
||||||
local digtron_adjacent = {} -- Nodes that are adjacent to Digtron but not a part of it
|
local digtron_adjacent = {} -- Nodes that are adjacent to Digtron but not a part of it
|
||||||
local bounding_box = {minp=vector.new(root_pos), maxp=vector.new(root_pos), root = root_pos}
|
local bounding_box = {minp=vector.new(root_pos), maxp=vector.new(root_pos)}
|
||||||
get_all_adjacent_digtron_nodes(root_pos, digtron_nodes, digtron_adjacent, bounding_box, player_name)
|
get_all_adjacent_digtron_nodes(root_pos, digtron_nodes, digtron_adjacent, bounding_box, player_name)
|
||||||
|
|
||||||
local digtron_id, digtron_inv = create_new_id(root_pos)
|
local digtron_id, digtron_inv = create_new_id(root_pos)
|
||||||
@ -280,7 +290,7 @@ digtron.construct = function(root_pos, player_name)
|
|||||||
|
|
||||||
if current_meta_table.fields.digtron_id then
|
if current_meta_table.fields.digtron_id then
|
||||||
-- Trying to incorporate part of an existing digtron, should be impossible.
|
-- Trying to incorporate part of an existing digtron, should be impossible.
|
||||||
minetest.log("error", "[Digtron] digtron.construct tried to incorporate a Digtron node of type "
|
minetest.log("error", "[Digtron] digtron.assemble tried to incorporate a Digtron node of type "
|
||||||
.. node.name .. " at " .. minetest.pos_to_string(minetest.get_position_from_hash(hash))
|
.. node.name .. " at " .. minetest.pos_to_string(minetest.get_position_from_hash(hash))
|
||||||
.. " that was already assigned to digtron id " .. current_meta_table.fields.digtron_id)
|
.. " that was already assigned to digtron id " .. current_meta_table.fields.digtron_id)
|
||||||
dispose_id(digtron_id)
|
dispose_id(digtron_id)
|
||||||
@ -313,17 +323,18 @@ digtron.construct = function(root_pos, player_name)
|
|||||||
persist_layout(digtron_id, layout)
|
persist_layout(digtron_id, layout)
|
||||||
persist_adjacent(digtron_id, digtron_adjacent)
|
persist_adjacent(digtron_id, digtron_adjacent)
|
||||||
persist_bounding_box(digtron_id, bounding_box)
|
persist_bounding_box(digtron_id, bounding_box)
|
||||||
|
persist_pos(digtron_id, root_pos)
|
||||||
|
|
||||||
-- Wipe out the inventories of all in-world nodes, it's stored in the mod_meta now.
|
-- Wipe out the inventories of all in-world nodes, it's stored in the mod_meta now.
|
||||||
-- Wait until now to do it in case the above loop fails partway through.
|
-- Wait until now to do it in case the above loop fails partway through.
|
||||||
for hash, node in pairs(digtron_nodes) do
|
for hash, node in pairs(digtron_nodes) do
|
||||||
local digtron_meta
|
local node_meta
|
||||||
if hash == root_hash then
|
if hash == root_hash then
|
||||||
digtron_meta = root_meta -- we're processing the controller, we already have a reference to its meta
|
node_meta = root_meta -- we're processing the controller, we already have a reference to its meta
|
||||||
else
|
else
|
||||||
digtron_meta = minetest.get_meta(minetest.get_position_from_hash(hash))
|
node_meta = minetest.get_meta(minetest.get_position_from_hash(hash))
|
||||||
end
|
end
|
||||||
local inv = digtron_meta:get_inventory()
|
local inv = node_meta:get_inventory()
|
||||||
|
|
||||||
for listname, items in pairs(inv:get_lists()) do
|
for listname, items in pairs(inv:get_lists()) do
|
||||||
for i = 1, #items do
|
for i = 1, #items do
|
||||||
@ -331,10 +342,13 @@ digtron.construct = function(root_pos, player_name)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
digtron_meta:set_string("digtron_id", digtron_id)
|
node_meta:set_string("digtron_id", digtron_id)
|
||||||
|
node_meta:mark_as_private("digtron_id")
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.debug("constructed id " .. digtron_id)
|
minetest.log("action", "Digtron " .. digtron_id .. " assembled at " .. minetest.pos_to_string(root_pos)
|
||||||
|
.. " by " .. player_name)
|
||||||
|
|
||||||
return digtron_id
|
return digtron_id
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -342,38 +356,41 @@ end
|
|||||||
-- Returns pos, node, and meta for the digtron node provided the in-world node matches the layout
|
-- Returns pos, node, and meta for the digtron node provided the in-world node matches the layout
|
||||||
-- returns nil otherwise
|
-- returns nil otherwise
|
||||||
local get_valid_data = function(digtron_id, root_hash, hash, data, function_name)
|
local get_valid_data = function(digtron_id, root_hash, hash, data, function_name)
|
||||||
local ipos = minetest.get_position_from_hash(hash + root_hash - origin_hash)
|
local node_pos = minetest.get_position_from_hash(hash + root_hash - origin_hash)
|
||||||
local node = minetest.get_node(ipos)
|
local node = minetest.get_node(node_pos)
|
||||||
local imeta = minetest.get_meta(ipos)
|
local node_meta = minetest.get_meta(node_pos)
|
||||||
local target_digtron_id = imeta:get_string("digtron_id")
|
local target_digtron_id = node_meta:get_string("digtron_id")
|
||||||
|
|
||||||
if data.node.name ~= node.name then
|
if data.node.name ~= node.name then
|
||||||
minetest.log("error", "[Digtron] " .. function_name .. " tried interacting with one of ".. digtron_id .. "'s "
|
minetest.log("error", "[Digtron] " .. function_name .. " tried interacting with one of ".. digtron_id .. "'s "
|
||||||
.. data.node.name .. "s at " .. minetest.pos_to_string(ipos) .. " but the node at that location was of type "
|
.. data.node.name .. "s at " .. minetest.pos_to_string(node_pos) .. " but the node at that location was of type "
|
||||||
.. node.name)
|
.. node.name)
|
||||||
return
|
return
|
||||||
elseif target_digtron_id ~= digtron_id then
|
elseif target_digtron_id ~= digtron_id then
|
||||||
if target_digtron_id ~= "" then
|
if target_digtron_id ~= "" then
|
||||||
minetest.log("error", "[Digtron] " .. function_name .. " tried interacting with ".. digtron_id .. "'s "
|
minetest.log("error", "[Digtron] " .. function_name .. " tried interacting with ".. digtron_id .. "'s "
|
||||||
.. data.node.name .. " at " .. minetest.pos_to_string(ipos)
|
.. data.node.name .. " at " .. minetest.pos_to_string(node_pos)
|
||||||
.. " but the node at that location had a non-matching digtron_id value of \""
|
.. " but the node at that location had a non-matching digtron_id value of \""
|
||||||
.. target_digtron_id .. "\"")
|
.. target_digtron_id .. "\"")
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
-- Allow digtron to recover from bad map metadata writes, the bane of Digtron 1.0's existence
|
-- Allow digtron to recover from bad map metadata writes, the bane of Digtron 1.0's existence
|
||||||
minetest.log("warning", "[Digtron] " .. function_name .. " tried interacting with ".. digtron_id .. "'s "
|
minetest.log("warning", "[Digtron] " .. function_name .. " tried interacting with ".. digtron_id .. "'s "
|
||||||
.. data.node.name .. " at " .. minetest.pos_to_string(ipos)
|
.. data.node.name .. " at " .. minetest.pos_to_string(node_pos)
|
||||||
.. " but the node at that location had no digtron_id in its metadata. "
|
.. " but the node at that location had no digtron_id in its metadata. "
|
||||||
.. "Since the node type matched the layout, however, it was included anyway. It's possible "
|
.. "Since the node type matched the layout, however, it was included anyway. It's possible "
|
||||||
.. "its metadata was not written correctly by a previous Digtron activity.")
|
.. "its metadata was not written correctly by a previous Digtron activity.")
|
||||||
return ipos, node, imeta
|
return node_pos, node, node_meta
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return ipos, node, imeta
|
return node_pos, node, node_meta
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Turns the Digtron back into pieces
|
-- Turns the Digtron back into pieces
|
||||||
digtron.deconstruct = function(digtron_id, root_pos, player_name)
|
digtron.disassemble = function(digtron_id, player_name)
|
||||||
|
local bbox = retrieve_bounding_box(digtron_id)
|
||||||
|
local root_pos = retrieve_pos(digtron_id)
|
||||||
|
|
||||||
local root_meta = minetest.get_meta(root_pos)
|
local root_meta = minetest.get_meta(root_pos)
|
||||||
root_meta:set_string("infotext", digtron.get_name(digtron_id))
|
root_meta:set_string("infotext", digtron.get_name(digtron_id))
|
||||||
|
|
||||||
@ -381,8 +398,8 @@ digtron.deconstruct = function(digtron_id, root_pos, player_name)
|
|||||||
local inv = digtron.retrieve_inventory(digtron_id)
|
local inv = digtron.retrieve_inventory(digtron_id)
|
||||||
|
|
||||||
if not (layout and inv) then
|
if not (layout and inv) then
|
||||||
minetest.log("error", "digtron.deconstruct was unable to find either layout or inventory record for " .. digtron_id
|
minetest.log("error", "digtron.disassemble was unable to find either layout or inventory record for " .. digtron_id
|
||||||
.. ", deconstruction was impossible. Clearing any other remaining data for this id.")
|
.. ", disassembly was impossible. Clearing any other remaining data for this id.")
|
||||||
dispose_id(digtron_id)
|
dispose_id(digtron_id)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -391,15 +408,15 @@ digtron.deconstruct = function(digtron_id, root_pos, player_name)
|
|||||||
|
|
||||||
-- Write metadata and inventory to in-world node at this location
|
-- Write metadata and inventory to in-world node at this location
|
||||||
for hash, data in pairs(layout) do
|
for hash, data in pairs(layout) do
|
||||||
local ipos, node, imeta = get_valid_data(digtron_id, root_hash, hash, data, "digtron.deconstruct")
|
local node_pos, node, node_meta = get_valid_data(digtron_id, root_hash, hash, data, "digtron.disassemble")
|
||||||
|
|
||||||
if ipos then
|
if node_pos then
|
||||||
local iinv = imeta:get_inventory()
|
local node_inv = node_meta:get_inventory()
|
||||||
for listname, size in pairs(data.meta.inventory) do
|
for listname, size in pairs(data.meta.inventory) do
|
||||||
iinv:set_size(listname, size)
|
node_inv:set_size(listname, size)
|
||||||
for i, itemstack in ipairs(inv:get_list(listname)) do
|
for i, itemstack in ipairs(inv:get_list(listname)) do
|
||||||
-- add everything, putting leftovers back in the main inventory
|
-- add everything, putting leftovers back in the main inventory
|
||||||
inv:set_stack(listname, i, iinv:add_item(listname, itemstack))
|
inv:set_stack(listname, i, node_inv:add_item(listname, itemstack))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -407,15 +424,17 @@ digtron.deconstruct = function(digtron_id, root_pos, player_name)
|
|||||||
|
|
||||||
-- Ensure node metadata fields are all set, too
|
-- Ensure node metadata fields are all set, too
|
||||||
for field, value in pairs(data.meta.fields) do
|
for field, value in pairs(data.meta.fields) do
|
||||||
imeta:set_string(field, value)
|
node_meta:set_string(field, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Clear digtron_id, this node is no longer part of an active digtron
|
-- Clear digtron_id, this node is no longer part of an active digtron
|
||||||
imeta:set_string("digtron_id", "")
|
node_meta:set_string("digtron_id", "")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
dispose_id(digtron_id)
|
dispose_id(digtron_id)
|
||||||
|
|
||||||
|
return root_pos
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Removes the in-world nodes of a digtron
|
-- Removes the in-world nodes of a digtron
|
||||||
@ -435,9 +454,9 @@ digtron.remove_from_world = function(digtron_id, root_pos, player_name)
|
|||||||
local root_hash = minetest.hash_node_position(root_pos)
|
local root_hash = minetest.hash_node_position(root_pos)
|
||||||
local nodes_to_destroy = {}
|
local nodes_to_destroy = {}
|
||||||
for hash, data in pairs(layout) do
|
for hash, data in pairs(layout) do
|
||||||
local ipos, node, imeta = get_valid_data(digtron_id, root_hash, hash, data, "digtron.destroy")
|
local node_pos, node, node_meta = get_valid_data(digtron_id, root_hash, hash, data, "digtron.destroy")
|
||||||
if ipos then
|
if node_pos then
|
||||||
table.insert(nodes_to_destroy, ipos)
|
table.insert(nodes_to_destroy, node_pos)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -452,12 +471,12 @@ digtron.build_to_world = function(digtron_id, root_pos, player_name)
|
|||||||
|
|
||||||
local permitted = true
|
local permitted = true
|
||||||
for hash, data in pairs(layout) do
|
for hash, data in pairs(layout) do
|
||||||
local ipos = minetest.get_position_from_hash(hash + root_hash - origin_hash)
|
local node_pos = minetest.get_position_from_hash(hash + root_hash - origin_hash)
|
||||||
local node = minetest.get_node(ipos)
|
local node = minetest.get_node(node_pos)
|
||||||
local node_def = minetest.registered_nodes[node.name]
|
local node_def = minetest.registered_nodes[node.name]
|
||||||
-- TODO: lots of testing needed here
|
-- TODO: lots of testing needed here
|
||||||
if not (node_def and node_def.buildable_to) then
|
if not (node_def and node_def.buildable_to) then
|
||||||
minetest.chat_send_all("not permitted due to " .. node.name .. " at " .. minetest.pos_to_string(ipos))
|
minetest.chat_send_all("not permitted due to " .. node.name .. " at " .. minetest.pos_to_string(node_pos))
|
||||||
permitted = false
|
permitted = false
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@ -466,22 +485,23 @@ digtron.build_to_world = function(digtron_id, root_pos, player_name)
|
|||||||
if permitted then
|
if permitted then
|
||||||
-- TODO: voxelmanip might be better here, less likely than with destroy though since metadata needs to be written
|
-- TODO: voxelmanip might be better here, less likely than with destroy though since metadata needs to be written
|
||||||
for hash, data in pairs(layout) do
|
for hash, data in pairs(layout) do
|
||||||
local ipos = minetest.get_position_from_hash(hash + root_hash - origin_hash)
|
local node_pos = minetest.get_position_from_hash(hash + root_hash - origin_hash)
|
||||||
minetest.set_node(ipos, data.node)
|
minetest.set_node(node_pos, data.node)
|
||||||
local meta = minetest.get_meta(ipos)
|
local meta = minetest.get_meta(node_pos)
|
||||||
meta:set_string("digtron_id", digtron_id)
|
|
||||||
for field, value in pairs(data.meta.fields) do
|
for field, value in pairs(data.meta.fields) do
|
||||||
meta:set_string(field, value)
|
meta:set_string(field, value)
|
||||||
end
|
end
|
||||||
-- Not needed - local inventories not used by active digtron, will be restored if deconstructed
|
meta:set_string("digtron_id", digtron_id)
|
||||||
|
meta:mark_as_private("digtron_id")
|
||||||
|
-- Not needed - local inventories not used by active digtron, will be restored if disassembled
|
||||||
-- local inv = meta:get_inventory()
|
-- local inv = meta:get_inventory()
|
||||||
-- for listname, size in pairs(data.meta.inventory) do
|
-- for listname, size in pairs(data.meta.inventory) do
|
||||||
-- inv:set_size(listname, size)
|
-- inv:set_size(listname, size)
|
||||||
-- end
|
-- end
|
||||||
end
|
end
|
||||||
local bbox = retrieve_bounding_box(digtron_id)
|
local bbox = retrieve_bounding_box(digtron_id)
|
||||||
bbox.root = root_pos
|
|
||||||
persist_bounding_box(digtron_id, bbox)
|
persist_bounding_box(digtron_id, bbox)
|
||||||
|
persist_pos(digtron_id, root_pos)
|
||||||
end
|
end
|
||||||
|
|
||||||
return permitted
|
return permitted
|
||||||
@ -503,12 +523,13 @@ digtron.can_dig = function(pos, digger)
|
|||||||
local node = minetest.get_node(pos)
|
local node = minetest.get_node(pos)
|
||||||
|
|
||||||
local bbox = retrieve_bounding_box(digtron_id)
|
local bbox = retrieve_bounding_box(digtron_id)
|
||||||
|
local root_pos = retrieve_pos(digtron_id)
|
||||||
local layout = retrieve_layout(digtron_id)
|
local layout = retrieve_layout(digtron_id)
|
||||||
if bbox == nil or bbox.root == nil or layout == nil then
|
if bbox == nil or root_pos == nil or layout == nil then
|
||||||
-- Somehow, this belongs to a digtron id that's missing information that should exist in persistence.
|
-- Somehow, this belongs to a digtron id that's missing information that should exist in persistence.
|
||||||
local missing = ""
|
local missing = ""
|
||||||
if bbox == nil then missing = missing .. "bounding_box " end
|
if bbox == nil then missing = missing .. "bounding_box " end
|
||||||
if bbox ~= nil and bbox.root == nil then missing = missing .. "root_pos " end
|
if root_pos == nil then missing = missing .. "root_pos " end
|
||||||
if layout == nil then missing = missing .. "layout " end
|
if layout == nil then missing = missing .. "layout " end
|
||||||
|
|
||||||
minetest.log("error", "[Digtron] can_dig was called on a " .. node.name .. " at location "
|
minetest.log("error", "[Digtron] can_dig was called on a " .. node.name .. " at location "
|
||||||
@ -520,7 +541,7 @@ digtron.can_dig = function(pos, digger)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local root_hash = minetest.hash_node_position(bbox.root)
|
local root_hash = minetest.hash_node_position(root_pos)
|
||||||
local here_hash = minetest.hash_node_position(pos)
|
local here_hash = minetest.hash_node_position(pos)
|
||||||
local layout_hash = here_hash - root_hash + origin_hash
|
local layout_hash = here_hash - root_hash + origin_hash
|
||||||
local layout_data = layout[layout_hash]
|
local layout_data = layout[layout_hash]
|
||||||
@ -550,13 +571,10 @@ digtron.on_blast = function(pos, intensity)
|
|||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
local digtron_id = meta:get_string("digtron_id")
|
local digtron_id = meta:get_string("digtron_id")
|
||||||
if digtron_id ~= "" then
|
if digtron_id ~= "" then
|
||||||
local bbox = retrieve_bounding_box(digtron_id)
|
if not digtron.disassemble(digtron_id, "an explosion") then
|
||||||
if bbox.root then
|
|
||||||
digtron.deconstruct(digtron_id, bbox.root, "an explosion")
|
|
||||||
else
|
|
||||||
minetest.log("error", "[Digtron] a digtron node at " .. minetest.pos_to_string(pos)
|
minetest.log("error", "[Digtron] a digtron node at " .. minetest.pos_to_string(pos)
|
||||||
.. " was hit by an explosion and had digtron_id " .. digtron_id
|
.. " was hit by an explosion and had digtron_id " .. digtron_id
|
||||||
.. " but didn't have a root position recorded, so it could not be deconstructed.")
|
.. " but didn't have a root position recorded, so it could not be disassembled.")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -569,3 +587,37 @@ digtron.on_blast = function(pos, intensity)
|
|||||||
minetest.remove_node(pos)
|
minetest.remove_node(pos)
|
||||||
return drops
|
return drops
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
-- Creative trash
|
||||||
|
|
||||||
|
-- This is wrapped in an after() call as a workaround for to https://github.com/minetest/minetest/issues/8827
|
||||||
|
if minetest.get_modpath("creative") then
|
||||||
|
minetest.after(1, function()
|
||||||
|
if minetest.get_inventory({type="detached", name="creative_trash"}) then
|
||||||
|
if minetest.remove_detached_inventory("creative_trash") then
|
||||||
|
-- Create the trash field
|
||||||
|
local trash = minetest.create_detached_inventory("creative_trash", {
|
||||||
|
-- Allow the stack to be placed and remove it in on_put()
|
||||||
|
-- This allows the creative inventory to restore the stack
|
||||||
|
allow_put = function(inv, listname, index, stack, player)
|
||||||
|
return stack:get_count()
|
||||||
|
end,
|
||||||
|
on_put = function(inv, listname, index, stack, player)
|
||||||
|
local stack = inv:get_stack(listname, index)
|
||||||
|
local stack_meta = stack:get_meta()
|
||||||
|
local digtron_id = stack_meta:get_string("digtron_id")
|
||||||
|
if digtron_id ~= "" then
|
||||||
|
minetest.log("action", player:get_player_name() .. " disposed of " .. digtron_id
|
||||||
|
.. " in the creative inventory's trash receptacle.")
|
||||||
|
dispose_id(digtron_id)
|
||||||
|
end
|
||||||
|
inv:set_list(listname, {})
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
trash:set_size("main", 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user