explosions automatically deconstruct Digtrons.

This commit is contained in:
FaceDeer 2019-08-19 20:02:16 -06:00
parent 1c732ae1cd
commit a9420ea805
4 changed files with 68 additions and 15 deletions

@ -37,8 +37,8 @@ local get_controller_constructed_formspec = function(pos, digtron_id, player_nam
.. "field_close_on_enter[digtron_name;false]" .. "field_close_on_enter[digtron_name;false]"
.. "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 .. "list[detached:" .. digtron_id .. ";main;0,0;8,2]" -- TODO: paging system for inventory, guard against non-existent listname
.. "list[detached:" .. digtron_id .. ";fuel;0,2.5;8,2]" -- TODO: paging system for inventory .. "list[detached:" .. digtron_id .. ";fuel;0,2.5;8,2]" -- TODO: paging system for inventory, guard against non-existent listname
.. "container_end[]" .. "container_end[]"
.. "container[0.5,5]list[current_player;main;0,0;8,1;]list[current_player;main;0,1.25;8,3;8]container_end[]" .. "container[0.5,5]list[current_player;main;0,0;8,1;]list[current_player;main;0,1.25;8,3;8]container_end[]"
.. "listring[current_player;main]" .. "listring[current_player;main]"
@ -49,7 +49,9 @@ minetest.register_node("digtron:controller", {
description = S("Digtron Control Module"), description = S("Digtron Control Module"),
_doc_items_longdesc = nil, _doc_items_longdesc = nil,
_doc_items_usagehelp = nil, _doc_items_usagehelp = nil,
groups = {cracky = 3, oddly_breakable_by_hand = 3, digtron = 1}, -- Note: this is not in the "digtron" group because we do not want it to be incorporated
-- into digtrons by mere adjacency; it must be the root node and only one root node is allowed.
groups = {cracky = 3, oddly_breakable_by_hand = 3},
paramtype = "light", paramtype = "light",
paramtype2= "facedir", paramtype2= "facedir",
is_ground_content = false, is_ground_content = false,
@ -162,6 +164,8 @@ minetest.register_node("digtron:controller", {
on_timer = function(pos, elapsed) on_timer = function(pos, elapsed)
end, end,
on_blast = digtron.on_blast,
}) })
-- Dealing with an unconstructed Digtron controller -- Dealing with an unconstructed Digtron controller

@ -4,6 +4,8 @@ digtron.layout = {}
digtron.adjacent = {} digtron.adjacent = {}
digtron.bounding_box = {} digtron.bounding_box = {}
--minetest.debug(dump(mod_meta:to_table()))
-- Wipes mod_meta -- Wipes mod_meta
--for field, value in pairs(mod_meta:to_table().fields) do --for field, value in pairs(mod_meta:to_table().fields) do
-- mod_meta:set_string(field, "") -- mod_meta:set_string(field, "")
@ -240,7 +242,7 @@ 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.construct = 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 -- 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.construct called with pos " .. minetest.pos_to_string(root_pos)
@ -255,9 +257,10 @@ digtron.construct = function(root_pos, player_name)
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
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)} local bounding_box = {minp=vector.new(root_pos), maxp=vector.new(root_pos), root = 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)
@ -342,19 +345,31 @@ 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 ipos = minetest.get_position_from_hash(hash + root_hash - origin_hash)
local node = minetest.get_node(ipos) local node = minetest.get_node(ipos)
local imeta = minetest.get_meta(ipos) local imeta = minetest.get_meta(ipos)
local target_digtron_id = imeta: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(ipos) .. " but the node at that location was of type "
.. node.name) .. node.name)
elseif imeta:get_string("digtron_id") ~= digtron_id then return
minetest.log("error", "[Digtron] " .. function_name .. " tried interacting with ".. digtron_id .. "'s " elseif target_digtron_id ~= digtron_id then
.. data.node.name .. " at " .. minetest.pos_to_string(ipos) if target_digtron_id ~= "" then
.. " but the node at that location had a non-matching digtron_id value of \"" minetest.log("error", "[Digtron] " .. function_name .. " tried interacting with ".. digtron_id .. "'s "
.. imeta:get_string("digtron_id") .. "\"") .. data.node.name .. " at " .. minetest.pos_to_string(ipos)
else .. " but the node at that location had a non-matching digtron_id value of \""
return ipos, node, imeta .. target_digtron_id .. "\"")
return
else
-- 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 "
.. data.node.name .. " at " .. minetest.pos_to_string(ipos)
.. " 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 "
.. "its metadata was not written correctly by a previous Digtron activity.")
return ipos, node, imeta
end
end end
return ipos, node, imeta
end end
-- Turns the Digtron back into pieces -- Turns the Digtron back into pieces
@ -366,8 +381,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", "Unable to find layout or inventory record for " .. digtron_id minetest.log("error", "digtron.deconstruct was unable to find either layout or inventory record for " .. digtron_id
.. ", wiping any remaining metadata for this id to prevent corruption. Sorry!") .. ", deconstruction was impossible. Clearing any other remaining data for this id.")
dispose_id(digtron_id) dispose_id(digtron_id)
return return
end end
@ -480,3 +495,29 @@ digtron.can_dig = function(pos, digger)
end end
return true return true
end end
digtron.on_blast = function(pos, intensity)
if intensity < 1.0 then return end -- The Almighty Digtron ignores weak-ass explosions
local meta = minetest.get_meta(pos)
local digtron_id = meta:get_string("digtron_id")
if digtron_id ~= "" then
local bbox = retrieve_bounding_box(digtron_id)
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)
.. " 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.")
return
end
end
local drops = {}
default.get_inventory_drops(pos, "main", drops)
default.get_inventory_drops(pos, "fuel", drops)
local node = minetest.get_node(pos)
table.insert(drops, ItemStack(node.name))
minetest.remove_node(pos)
return drops
end

@ -33,6 +33,7 @@ minetest.register_node("digtron:structure", {
} }
}, },
can_dig = digtron.can_dig, can_dig = digtron.can_dig,
on_blast = digtron.on_blast,
}) })
-- A modest light source that will move with the digtron, handy for working in a tunnel you aren't bothering to install permanent lights in. -- A modest light source that will move with the digtron, handy for working in a tunnel you aren't bothering to install permanent lights in.
@ -55,6 +56,7 @@ minetest.register_node("digtron:light", {
wall_side = {-0.5, -0.25, -0.25, -0.1875, 0.25, 0.25}, wall_side = {-0.5, -0.25, -0.25, -0.1875, 0.25, 0.25},
}, },
can_dig = digtron.can_dig, can_dig = digtron.can_dig,
on_blast = digtron.on_blast,
}) })
-- A simple structural panel -- A simple structural panel
@ -78,6 +80,7 @@ minetest.register_node("digtron:panel", {
fixed = {-0.5, -0.5, -0.5, 0.5, -0.4375, 0.5}, fixed = {-0.5, -0.5, -0.5, 0.5, -0.4375, 0.5},
}, },
can_dig = digtron.can_dig, can_dig = digtron.can_dig,
on_blast = digtron.on_blast,
}) })
-- A simple structural panel -- A simple structural panel
@ -107,6 +110,7 @@ minetest.register_node("digtron:edge_panel", {
}, },
}, },
can_dig = digtron.can_dig, can_dig = digtron.can_dig,
on_blast = digtron.on_blast,
}) })
minetest.register_node("digtron:corner_panel", { minetest.register_node("digtron:corner_panel", {
@ -137,4 +141,5 @@ minetest.register_node("digtron:corner_panel", {
}, },
}, },
can_dig = digtron.can_dig, can_dig = digtron.can_dig,
on_blast = digtron.on_blast,
}) })

@ -54,6 +54,7 @@ minetest.register_node("digtron:inventory", {
local inv = minetest.get_inventory({type="node", pos=pos}) local inv = minetest.get_inventory({type="node", pos=pos})
return inv:is_empty("main") and digtron.can_dig(pos,player) return inv:is_empty("main") and digtron.can_dig(pos,player)
end, end,
on_blast = digtron.on_blast,
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
@ -153,6 +154,7 @@ minetest.register_node("digtron:fuelstore", {
local inv = minetest.get_inventory({type="node", pos=pos}) local inv = minetest.get_inventory({type="node", pos=pos})
return inv:is_empty("fuel") and digtron.can_dig(pos,player) return inv:is_empty("fuel") and digtron.can_dig(pos,player)
end, end,
on_blast = digtron.on_blast,
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
@ -274,6 +276,7 @@ minetest.register_node("digtron:combined_storage", {
local inv = minetest.get_inventory({type="node", pos=pos}) local inv = minetest.get_inventory({type="node", pos=pos})
return inv:is_empty("fuel") and inv:is_empty("main") and digtron.can_dig(pos,player) return inv:is_empty("fuel") and inv:is_empty("main") and digtron.can_dig(pos,player)
end, end,
on_blast = digtron.on_blast,
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)