mirror of
https://github.com/minetest-mods/digtron.git
synced 2024-10-02 07:33:07 +02:00
make it possible to edit builders that are part of an assembled digtron
Should make it possible to edit other components too, later on.
This commit is contained in:
parent
6745446fcd
commit
3c0fbca66f
@ -802,10 +802,8 @@ minetest.register_node("digtron:controller_unassembled", combine_defs(base_def,
|
||||
local player_name = clicker:get_player_name()
|
||||
local digtron_id = digtron.assemble(pos, player_name)
|
||||
if digtron_id then
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("digtron_id", digtron_id)
|
||||
meta:mark_as_private("digtron_id")
|
||||
get_context(digtron_id, player_name)
|
||||
local player_context = get_context(digtron_id, player_name)
|
||||
player_context.open = true
|
||||
minetest.show_formspec(player_name,
|
||||
"digtron:controller_assembled",
|
||||
get_controller_assembled_formspec(digtron_id, player_name))
|
||||
@ -833,10 +831,12 @@ minetest.register_node("digtron:controller", combine_defs(base_def, {
|
||||
end
|
||||
local meta = minetest.get_meta(pos)
|
||||
local digtron_id = meta:get_string("digtron_id")
|
||||
local digtron_layout_node_id = meta:get_int("digtron_layout_node_id")
|
||||
|
||||
local stack = ItemStack({name=node.name, count=1, wear=0})
|
||||
local stack_meta = stack:get_meta()
|
||||
stack_meta:set_string("digtron_id", digtron_id)
|
||||
stack_meta:set_int("digtron_layout_node_id", digtron_layout_node_id)
|
||||
stack_meta:set_string("description", digtron.get_name(digtron_id))
|
||||
local inv = digger:get_inventory()
|
||||
local stack = inv:add_item("main", stack)
|
||||
@ -863,6 +863,7 @@ minetest.register_node("digtron:controller", combine_defs(base_def, {
|
||||
if dropped:get_name() == "digtron:controller" then
|
||||
local stack_meta = dropped:get_meta()
|
||||
stack_meta:set_string("digtron_id", oldmeta:get_string("digtron_id"))
|
||||
stack_meta:set_int("digtron_layout_node_id", oldmeta:get_int("digtron_layout_node_id"))
|
||||
stack_meta:set_string("description", oldmeta:get_string("infotext"))
|
||||
return
|
||||
end
|
||||
|
12
entities.lua
12
entities.lua
@ -161,7 +161,7 @@ end
|
||||
-- Used by unassembled builders
|
||||
digtron.update_builder_item = function(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
if minetest.get_node_group(node.name, "digtron") ~= 4 then
|
||||
if minetest.get_item_group(node.name, "digtron") ~= 4 then
|
||||
return
|
||||
end
|
||||
local target_pos = vector.add(pos, minetest.facedir_to_dir(node.param2))
|
||||
@ -179,11 +179,11 @@ digtron.update_builder_items = function(digtron_id)
|
||||
local layout = digtron.get_layout(digtron_id)
|
||||
local root_pos = digtron.get_pos(digtron_id)
|
||||
|
||||
for hash, data in pairs(layout) do
|
||||
for layout_node_id, data in pairs(layout) do
|
||||
local node = data.node
|
||||
if minetest.get_node_group(node.name, "digtron") == 4 then
|
||||
if minetest.get_item_group(node.name, "digtron") == 4 then
|
||||
local item = data.meta.fields.item
|
||||
local pos = vector.add(minetest.get_position_from_hash(hash), root_pos)
|
||||
local pos = vector.add(data.pos, root_pos)
|
||||
local target_pos = vector.add(pos, minetest.facedir_to_dir(node.param2))
|
||||
digtron.remove_builder_item(target_pos)
|
||||
if item ~= "" then
|
||||
@ -210,12 +210,12 @@ minetest.register_entity("digtron:builder_item", {
|
||||
on_activate = function(self, staticdata)
|
||||
local props = self.object:get_properties()
|
||||
if staticdata ~= nil and staticdata ~= "" then
|
||||
local pos = self.object:getpos()
|
||||
local pos = self.object:get_pos()
|
||||
local adjacent_builder = false
|
||||
for _, dir in ipairs(digtron.cardinal_dirs) do
|
||||
local target_pos = vector.add(pos, dir)
|
||||
local node = minetest.get_node(target_pos)
|
||||
if minetest.get_node_group(node.name, "digtron") == 4 then
|
||||
if minetest.get_item_group(node.name, "digtron") == 4 then
|
||||
-- Not checking whether the adjacent builder is aimed right,
|
||||
-- has the right builder_item, etc. This is just a failsafe
|
||||
-- to clean up entities that somehow got left behind when a
|
||||
|
211
functions.lua
211
functions.lua
@ -4,21 +4,36 @@ local cache = {}
|
||||
|
||||
local S = digtron.S
|
||||
|
||||
local zero_pos = {x=0, y=0, z=0}
|
||||
|
||||
--minetest.debug(dump(mod_meta:to_table()))
|
||||
minetest.register_chatcommand("digtron_dump", {
|
||||
--params = "<name> <privilege>", -- Short parameter description
|
||||
description = "dump digtron data to debug", -- Full description
|
||||
privs = {server=true}, -- Require the "privs" privilege to run
|
||||
func = function(name, param)
|
||||
minetest.debug(dump(mod_meta:to_table()))
|
||||
end,
|
||||
})
|
||||
|
||||
-- Wipes mod_meta
|
||||
--for field, value in pairs(mod_meta:to_table().fields) do
|
||||
-- mod_meta:set_string(field, "")
|
||||
--end
|
||||
minetest.register_chatcommand("digtron_wipe", {
|
||||
--params = "<name> <privilege>", -- Short parameter description
|
||||
description = "dump digtron data to debug", -- Full description
|
||||
privs = {server=true}, -- Require the "privs" privilege to run
|
||||
func = function(name, param)
|
||||
-- Wipes mod_meta
|
||||
for field, value in pairs(mod_meta:to_table().fields) do
|
||||
mod_meta:set_string(field, "")
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
local damage_hp = digtron.config.damage_hp
|
||||
-- see predict_dig for how punch_data gets calculated
|
||||
local damage_creatures = function(root_pos, punch_data, items_dropped)
|
||||
local damage_creatures = function(punch_data, items_dropped)
|
||||
local target_pos = punch_data[2]
|
||||
local objects = minetest.get_objects_inside_radius(target_pos, 1.0)
|
||||
if objects ~= nil then
|
||||
local source_pos = vector.add(minetest.get_position_from_hash(punch_data[1]), root_pos)
|
||||
local source_pos = punch_data[1]
|
||||
for _, obj in ipairs(objects) do
|
||||
local dir = vector.normalize(vector.subtract(obj:get_pos(), source_pos))
|
||||
local armour_multiplier = 1
|
||||
@ -195,7 +210,7 @@ local persist_sequence, retrieve_sequence = get_table_functions("sequence")
|
||||
-------------------------------------------------------------------------------------------------------
|
||||
-- Layout creation helpers
|
||||
|
||||
digtron.duplicate = function(digtron_id)
|
||||
local duplicate = function(digtron_id)
|
||||
local layout = retrieve_layout(digtron_id)
|
||||
if layout == nil then
|
||||
minetest.log("error", "[Digtron] digtron.duplicate called with non-existent id " .. digtron_id)
|
||||
@ -218,6 +233,7 @@ digtron.duplicate = function(digtron_id)
|
||||
local new_controller = ItemStack("digtron:controller")
|
||||
local meta = new_controller:get_meta()
|
||||
meta:set_string("digtron_id", new_id)
|
||||
meta:set_int("digtron_layout_node_id", 1) -- the root node is always in index 1, see "assemble"
|
||||
meta:set_string("description", new_name)
|
||||
return new_controller
|
||||
end
|
||||
@ -270,8 +286,8 @@ local retrieve_bounding_box = function(digtron_id)
|
||||
if layout == nil then return nil end
|
||||
|
||||
local bbox = {minp = {x=0, y=0, z=0}, maxp = {x=0, y=0, z=0}}
|
||||
for hash, data in pairs(layout) do
|
||||
update_bounding_box(bbox, minetest.get_position_from_hash(hash))
|
||||
for layout_node_id, data in pairs(layout) do
|
||||
update_bounding_box(bbox, data.pos)
|
||||
end
|
||||
cache_bounding_box[digtron_id] = bbox
|
||||
return bbox
|
||||
@ -287,10 +303,20 @@ local refresh_adjacent = function(digtron_id)
|
||||
local adjacent = {} -- all adjacent nodes. TODO: if implementing traction wheels, won't be needed
|
||||
local adjacent_to_diggers = {}
|
||||
local adjacent_to_builders = {}
|
||||
for hash, data in pairs(layout) do
|
||||
|
||||
local all_digtron_node_hashes = {} -- track the locations of the digtron nodes themselves, these will be omitted from adjacency
|
||||
for layout_node_id, data in pairs(layout) do
|
||||
local hash = minetest.hash_node_position(data.pos)
|
||||
data.hash = hash
|
||||
all_digtron_node_hashes[hash] = true
|
||||
end
|
||||
|
||||
for layout_node_id, data in pairs(layout) do
|
||||
local hash = data.hash
|
||||
|
||||
for _, dir_hash in ipairs(digtron.cardinal_dirs_hash) do
|
||||
local potential_adjacent = hash + dir_hash
|
||||
if layout[potential_adjacent] == nil then
|
||||
if not all_digtron_node_hashes[potential_adjacent] then
|
||||
adjacent[potential_adjacent] = true
|
||||
end
|
||||
end
|
||||
@ -300,19 +326,19 @@ local refresh_adjacent = function(digtron_id)
|
||||
-- Diggers
|
||||
if digtron_group >= 10 and digtron_group <= 13 then
|
||||
-- All diggers target the node directly in front of them
|
||||
local dir_hashes = {}
|
||||
local targets = {}
|
||||
local dir_hash = digtron.facedir_to_dir_hash(data.node.param2)
|
||||
local potential_target = hash + dir_hash -- pointed at this hash
|
||||
if layout[potential_target] == nil then -- not pointed at another Digtron node
|
||||
table.insert(dir_hashes, dir_hash)
|
||||
if not all_digtron_node_hashes[potential_target] then
|
||||
table.insert(targets, minetest.get_position_from_hash(potential_target))
|
||||
end
|
||||
|
||||
-- If it's a dual digger, add a second dir
|
||||
if digtron_group == 11 or digtron_group == 13 then
|
||||
dir_hash = digtron.facedir_to_down_hash(data.node.param2)
|
||||
potential_target = hash + dir_hash -- pointed at this hash
|
||||
if layout[potential_target] == nil then -- not pointed at another Digtron node
|
||||
table.insert(dir_hashes, dir_hash)
|
||||
if not all_digtron_node_hashes[potential_target] then
|
||||
table.insert(targets, minetest.get_position_from_hash(potential_target))
|
||||
end
|
||||
end
|
||||
|
||||
@ -322,14 +348,15 @@ local refresh_adjacent = function(digtron_id)
|
||||
soft = true
|
||||
end
|
||||
|
||||
if #dir_hashes > 0 then
|
||||
local fields = data.meta.fields
|
||||
adjacent_to_diggers[hash] = {
|
||||
if #targets > 0 then
|
||||
table.insert(adjacent_to_diggers, {
|
||||
pos = data.pos,
|
||||
period = tonumber(fields.period) or 1,
|
||||
offset = tonumber(fields.offset) or 0,
|
||||
dir_hashes = dir_hashes,
|
||||
targets = targets,
|
||||
soft = soft,
|
||||
}
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
@ -337,20 +364,24 @@ local refresh_adjacent = function(digtron_id)
|
||||
if digtron_group == 4 then
|
||||
local dir_hash = digtron.facedir_to_dir_hash(data.node.param2)
|
||||
local potential_target = hash + dir_hash
|
||||
if layout[potential_target] == nil then
|
||||
if not all_digtron_node_hashes[potential_target] then
|
||||
local fields = data.meta.fields
|
||||
-- TODO: trace extrusion and if it intersects Digtron layout cap it there.
|
||||
adjacent_to_builders[hash] = {
|
||||
-- This is getting pretty edge case, though, don't worry about it until you're
|
||||
-- completely bored
|
||||
table.insert(adjacent_to_builders, {
|
||||
pos = data.pos,
|
||||
period = tonumber(fields.period) or 1,
|
||||
offset = tonumber(fields.offset) or 0,
|
||||
item = fields.item,
|
||||
facing = tonumber(fields.facing) or 0, -- facing of built node
|
||||
extrusion = tonumber(fields.extrusion) or 1,
|
||||
dir_hash = dir_hash, -- Record in table form, it'll be more convenient for use later
|
||||
}
|
||||
dir = minetest.facedir_to_dir(data.node.param2),
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cache_all_adjacent_pos[digtron_id] = adjacent
|
||||
cache_all_digger_targets[digtron_id] = adjacent_to_diggers
|
||||
cache_all_builder_targets[digtron_id] = adjacent_to_builders
|
||||
@ -423,7 +454,7 @@ local assemble = function(root_pos, player_name)
|
||||
|
||||
for hash, node in pairs(digtron_nodes) do
|
||||
local pos = minetest.get_position_from_hash(hash)
|
||||
local relative_hash = minetest.hash_node_position(vector.subtract(pos, root_pos))
|
||||
local relative_pos = vector.subtract(pos, root_pos)
|
||||
|
||||
local current_meta
|
||||
if hash == root_hash then
|
||||
@ -455,6 +486,8 @@ local assemble = function(root_pos, player_name)
|
||||
current_meta_table.inventory[listname] = #items
|
||||
end
|
||||
|
||||
-- If the node being incorporated into the assembled digtron has a "_digtron_assembled_node" property
|
||||
-- defined, then pretend it's that node rather than the actual node.
|
||||
local node_def = minetest.registered_nodes[node.name]
|
||||
if node_def and node_def._digtron_assembled_node then
|
||||
node.name = node_def._digtron_assembled_node
|
||||
@ -462,10 +495,17 @@ local assemble = function(root_pos, player_name)
|
||||
end
|
||||
|
||||
node.param1 = nil -- we don't care about param1, wipe it to save space
|
||||
layout[relative_hash] = {meta = current_meta_table, node = node}
|
||||
table.insert(layout, {meta = current_meta_table, node = node, pos = relative_pos})
|
||||
local meta = minetest.get_meta(pos)
|
||||
-- track this so that we can interact with individual node settings in the assembled digtron
|
||||
meta:set_string("digtron_relative_hash", relative_hash)
|
||||
end
|
||||
|
||||
-- Ensure the root node is in position 1
|
||||
for layout_node_id, data in ipairs(layout) do
|
||||
if vector.equals(data.pos, zero_pos) then
|
||||
layout[layout_node_id] = layout[1]
|
||||
layout[1] = data
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
persist_inventory(digtron_id)
|
||||
@ -476,13 +516,14 @@ local assemble = function(root_pos, player_name)
|
||||
persist_sequence(digtron_id, digtron.default_sequence())
|
||||
|
||||
-- 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.
|
||||
for hash, node in pairs(digtron_nodes) do
|
||||
-- Wait until now to do it in case the above loop fails partway through and we need to abort.
|
||||
for layout_node_id, data in ipairs(layout) do
|
||||
local node_pos = vector.add(root_pos, data.pos)
|
||||
local node_meta
|
||||
if hash == root_hash then
|
||||
if vector.equals(root_pos, node_pos) then
|
||||
node_meta = root_meta -- we're processing the controller, we already have a reference to its meta
|
||||
else
|
||||
node_meta = minetest.get_meta(minetest.get_position_from_hash(hash))
|
||||
node_meta = minetest.get_meta(node_pos)
|
||||
end
|
||||
local inv = node_meta:get_inventory()
|
||||
|
||||
@ -492,8 +533,11 @@ local assemble = function(root_pos, player_name)
|
||||
end
|
||||
end
|
||||
|
||||
-- Set metadata on the nodes to indicate that they've been incorporated into an assembled Digtron
|
||||
node_meta:set_string("digtron_id", digtron_id)
|
||||
node_meta:set_int("digtron_layout_node_id", layout_node_id)
|
||||
node_meta:mark_as_private("digtron_id")
|
||||
node_meta:mark_as_private("digtron_layout_node_id")
|
||||
end
|
||||
|
||||
minetest.log("action", "Digtron " .. digtron_id .. " assembled at " .. minetest.pos_to_string(root_pos)
|
||||
@ -503,30 +547,48 @@ local assemble = function(root_pos, player_name)
|
||||
return digtron_id
|
||||
end
|
||||
|
||||
local function log_prefix(function_name, digtron_id, target_name, target_pos)
|
||||
return "[Digtron] " .. function_name .. " tried interacting with one of ".. digtron_id .. "'s "
|
||||
.. target_name .. "s at " .. minetest.pos_to_string(target_pos)
|
||||
end
|
||||
|
||||
-- Returns pos, node, and meta for the digtron node provided the in-world node matches the layout
|
||||
-- returns nil otherwise
|
||||
local get_valid_data = function(digtron_id, root_pos, hash, data, function_name)
|
||||
local node_pos = vector.add(minetest.get_position_from_hash(hash), root_pos)
|
||||
local get_valid_data = function(digtron_id, layout_node_id, root_pos, data, function_name)
|
||||
local node_pos = data.pos
|
||||
if not node_pos then
|
||||
minetest.log("error", "[Digtron] " .. function_name .. " tried interacting with " .. digtron_id
|
||||
.. " node id " .. layout_node_id .. " but there was no pos in its data: " .. dump(data))
|
||||
return
|
||||
end
|
||||
node_pos = vector.add(root_pos, node_pos)
|
||||
local data_node_name = data.node.name
|
||||
local node = minetest.get_node(node_pos)
|
||||
local node_meta = minetest.get_meta(node_pos)
|
||||
local target_digtron_id = node_meta:get_string("digtron_id")
|
||||
local target_node_id = node_meta:get_int("digtron_layout_node_id")
|
||||
|
||||
if data.node.name ~= node.name then
|
||||
minetest.log("error", "[Digtron] " .. function_name .. " tried interacting with one of ".. digtron_id .. "'s "
|
||||
.. data.node.name .. "s at " .. minetest.pos_to_string(node_pos) .. " but the node at that location was of type "
|
||||
.. node.name)
|
||||
if target_node_id ~= layout_node_id then
|
||||
-- A recoverable error, but may indicate something's wrong elsewhere.
|
||||
minetest.log("warning", log_prefix(function_name, digtron_id, data_node_name, node_pos)
|
||||
.. " but the node at that location was marked as layout id " .. target_node_id
|
||||
.. " instead of " .. layout_node_id)
|
||||
node_meta:set_int("digtron_layout_node_id", layout_node_id)
|
||||
node_meta:mark_as_private("digtron_layout_node_id")
|
||||
end
|
||||
if data_node_name ~= node.name then
|
||||
minetest.log("error", log_prefix(function_name, digtron_id, data_node_name, node_pos)
|
||||
.. " but the node at that location was of type " .. node.name)
|
||||
return
|
||||
elseif target_digtron_id ~= digtron_id then
|
||||
if target_digtron_id ~= "" then
|
||||
minetest.log("error", "[Digtron] " .. function_name .. " tried interacting with ".. digtron_id .. "'s "
|
||||
.. data.node.name .. " at " .. minetest.pos_to_string(node_pos)
|
||||
minetest.log("error", log_prefix(function_name, digtron_id, data_node_name, node_pos)
|
||||
.. " but the node at that location had a non-matching digtron_id value of \""
|
||||
.. 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(node_pos)
|
||||
minetest.log("warning", log_prefix(function_name, digtron_id, data_node_name, node_pos)
|
||||
.. " 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.")
|
||||
@ -558,8 +620,8 @@ local disassemble = function(digtron_id, player_name)
|
||||
end
|
||||
|
||||
-- Write metadata and inventory to in-world node at this location
|
||||
for hash, data in pairs(layout) do
|
||||
local node_pos, node, node_meta = get_valid_data(digtron_id, root_pos, hash, data, "disassemble")
|
||||
for layout_node_id, data in pairs(layout) do
|
||||
local node_pos, node, node_meta = get_valid_data(digtron_id, layout_node_id, root_pos, data, "disassemble")
|
||||
|
||||
if node_pos then
|
||||
local node_inv = node_meta:get_inventory()
|
||||
@ -640,8 +702,8 @@ local remove_from_world = function(digtron_id, player_name)
|
||||
end
|
||||
|
||||
local nodes_to_destroy = {}
|
||||
for hash, data in pairs(layout) do
|
||||
local node_pos = get_valid_data(digtron_id, root_pos, hash, data, "remove_from_world")
|
||||
for layout_node_id, data in pairs(layout) do
|
||||
local node_pos = get_valid_data(digtron_id, layout_node_id, root_pos, data, "remove_from_world")
|
||||
if node_pos then
|
||||
table.insert(nodes_to_destroy, node_pos)
|
||||
end
|
||||
@ -664,8 +726,8 @@ local is_buildable_to = function(digtron_id, layout, root_pos, player_name, igno
|
||||
|
||||
local ignore_hashes = {}
|
||||
if old_root_pos then
|
||||
for hash, _ in pairs(old_layout) do
|
||||
local old_hash = minetest.hash_node_position(vector.add(minetest.get_position_from_hash(hash), old_root_pos))
|
||||
for layout_node_id, data in pairs(old_layout) do
|
||||
local old_hash = minetest.hash_node_position(vector.add(data.pos, old_root_pos))
|
||||
ignore_hashes[old_hash] = true
|
||||
end
|
||||
end
|
||||
@ -710,16 +772,20 @@ local build_to_world = function(digtron_id, layout, root_pos, player_name)
|
||||
layout = retrieve_layout(digtron_id)
|
||||
end
|
||||
local built_positions = {}
|
||||
for hash, data in pairs(layout) do
|
||||
for layout_node_id, data in pairs(layout) do
|
||||
-- Don't use get_valid_data, the Digtron isn't in-world yet
|
||||
local node_pos = vector.add(minetest.get_position_from_hash(hash), root_pos)
|
||||
local node_pos = vector.add(data.pos, root_pos)
|
||||
minetest.debug("setting root at " .. minetest.pos_to_string(root_pos))
|
||||
minetest.debug("setting node at " .. minetest.pos_to_string(data.pos))
|
||||
minetest.set_node(node_pos, data.node)
|
||||
local meta = minetest.get_meta(node_pos)
|
||||
for field, value in pairs(data.meta.fields) do
|
||||
meta:set_string(field, value)
|
||||
end
|
||||
meta:set_string("digtron_id", digtron_id)
|
||||
meta:set_int("digtron_layout_node_id", layout_node_id)
|
||||
meta:mark_as_private("digtron_id")
|
||||
meta:mark_as_private("digtron_layout_node_id")
|
||||
table.insert(built_positions, node_pos)
|
||||
end
|
||||
persist_pos(digtron_id, root_pos)
|
||||
@ -754,7 +820,7 @@ local rotate_layout = function(digtron_id, axis)
|
||||
local layout = retrieve_layout(digtron_id)
|
||||
local axis_hash = minetest.hash_node_position(axis)
|
||||
local rotated_layout = {}
|
||||
for hash, data in pairs(layout) do
|
||||
for layout_node_id, data in pairs(layout) do
|
||||
local duplicate_data = deep_copy(data)
|
||||
-- Facings
|
||||
local node_name = duplicate_data.node.name
|
||||
@ -777,10 +843,9 @@ local rotate_layout = function(digtron_id, axis)
|
||||
end
|
||||
|
||||
-- Position
|
||||
local pos = minetest.get_position_from_hash(hash)
|
||||
pos = digtron.rotate_pos(axis_hash, pos)
|
||||
local new_hash = minetest.hash_node_position(pos)
|
||||
rotated_layout[new_hash] = duplicate_data
|
||||
local pos = data.pos
|
||||
duplicate_data.pos = digtron.rotate_pos(axis_hash, pos)
|
||||
rotated_layout[layout_node_id] = duplicate_data
|
||||
end
|
||||
|
||||
return rotated_layout
|
||||
@ -865,11 +930,11 @@ local predict_dig = function(digtron_id, player_name, controlling_coordinate)
|
||||
punches_thrown = {}
|
||||
end
|
||||
|
||||
for digger_hash, digger_data in pairs(retrieve_all_digger_targets(digtron_id)) do
|
||||
for _, dir_hash in ipairs(digger_data.dir_hashes) do
|
||||
local target_hash = digger_hash + dir_hash
|
||||
for _, digger_data in pairs(retrieve_all_digger_targets(digtron_id)) do
|
||||
for _, target in ipairs(digger_data.targets) do
|
||||
local target_pos = vector.add(root_pos, target)
|
||||
local target_hash = minetest.hash_node_position(target_pos)
|
||||
if not dug_hashes[target_hash] then
|
||||
local target_pos = vector.add(minetest.get_position_from_hash(target_hash), root_pos)
|
||||
local target_node = minetest.get_node(target_pos)
|
||||
local target_name = target_node.name
|
||||
local targetdef = minetest.registered_nodes[target_name]
|
||||
@ -887,10 +952,7 @@ local predict_dig = function(digtron_id, player_name, controlling_coordinate)
|
||||
and (not digger_data.soft or is_soft_material(target_name))
|
||||
then
|
||||
if punches_thrown then
|
||||
-- storing digger_hash rather than converting it into a vector because
|
||||
-- in most cases there won't be something to punch and that calculation can be skipped
|
||||
-- convert to digger_pos by adding root_pos
|
||||
table.insert(punches_thrown, {digger_hash, target_pos})
|
||||
table.insert(punches_thrown, {vector.add(root_pos, digger_data.pos), target_pos})
|
||||
end
|
||||
if target_name ~= "air" then -- TODO: generalise this somehow for liquids and other undiggables
|
||||
if digtron.config.uses_resources then
|
||||
@ -992,11 +1054,11 @@ local predict_build = function(digtron_id, root_pos, player_name, ignore_nodes,
|
||||
local built_nodes = {}
|
||||
local cost = 0
|
||||
|
||||
for target_hash, builder_data in pairs(retrieve_all_builder_targets(digtron_id)) do
|
||||
local dir_hash = builder_data.dir_hash
|
||||
for _, builder_data in pairs(retrieve_all_builder_targets(digtron_id)) do
|
||||
local dir = builder_data.dir
|
||||
local periodicity_permitted = nil
|
||||
for i = 1, builder_data.extrusion do
|
||||
local target_pos = vector.add(minetest.get_position_from_hash(target_hash + i * dir_hash), root_pos)
|
||||
local target_pos = vector.add(vector.add(builder_data.pos, vector.multiply(dir, i)), root_pos)
|
||||
local test_hash = minetest.hash_node_position(target_pos)
|
||||
if periodicity_permitted == nil then
|
||||
-- test periodicity and offset once
|
||||
@ -1189,12 +1251,12 @@ local execute_dig_move_build_cycle = function(digtron_id, player_name, dig_down)
|
||||
local items_dropped = {}
|
||||
if punches_thrown then
|
||||
for _, punch_data in ipairs(punches_thrown) do
|
||||
damage_creatures(old_root_pos, punch_data, items_dropped)
|
||||
damage_creatures(punch_data, items_dropped)
|
||||
end
|
||||
end
|
||||
|
||||
-- Building new Digtron
|
||||
digtron.build_to_world(digtron_id, layout, new_root_pos, player_name)
|
||||
build_to_world(digtron_id, layout, new_root_pos, player_name)
|
||||
minetest.sound_play("digtron_construction", {gain = 0.5, pos=new_root_pos})
|
||||
|
||||
local build_leftovers, success_count = build_nodes(built_nodes, player_name)
|
||||
@ -1360,9 +1422,10 @@ local recover_digtron_id = function(root_pos)
|
||||
.."recover_digtron_id will now attempt to restore the digtron_id metadata key to all "
|
||||
.."nodes in this Digtron's layout.")
|
||||
local layout = retrieve_layout(digtron_id)
|
||||
for hash, data in pairs(layout) do
|
||||
local root_pos = retrieve_pos(digtron_id)
|
||||
for layout_node_id, data in pairs(layout) do
|
||||
-- get_valid_data will attempt to repair node metadata that's missing digtron_id
|
||||
local node_pos, node, node_meta = get_valid_data(digtron_id, root_pos, hash, data, "recover_digtron_id")
|
||||
local node_pos, node, node_meta = get_valid_data(digtron_id, layout_node_id, root_pos, data, "recover_digtron_id")
|
||||
end
|
||||
return true
|
||||
end
|
||||
@ -1388,8 +1451,12 @@ digtron.get_inventory = retrieve_inventory
|
||||
digtron.set_sequence = persist_sequence
|
||||
digtron.get_sequence = retrieve_sequence
|
||||
|
||||
-- Used by duplicator
|
||||
digtron.get_layout = retrieve_layout
|
||||
digtron.set_layout = function(digtron_id, layout)
|
||||
invalidate_layout_cache(digtron_id)
|
||||
persist_layout(digtron_id, layout)
|
||||
end
|
||||
digtron.duplicate = duplicate
|
||||
|
||||
digtron.assemble = assemble
|
||||
digtron.disassemble = disassemble
|
||||
|
1
init.lua
1
init.lua
@ -57,7 +57,6 @@ dofile(modpath.."/nodes/node_builder.lua")
|
||||
dofile(modpath.."/nodes/node_duplicator.lua")
|
||||
dofile(modpath.."/nodes/recipes.lua")
|
||||
|
||||
|
||||
-- digtron group numbers:
|
||||
-- 1 - generic digtron node, nothing special is done with these. They're just dragged along.
|
||||
-- 2 - inventory-holding digtron, has a "main" inventory that the digtron can add to and take from.
|
||||
|
@ -6,15 +6,13 @@ local S = digtron.S
|
||||
-- TODO make this global
|
||||
local player_interacting_with_builder_pos = {}
|
||||
|
||||
local get_formspec = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
|
||||
local period = meta:get_int("period")
|
||||
local get_formspec = function(meta_fields)
|
||||
local period = tonumber(meta_fields.period)
|
||||
if period < 1 then period = 1 end
|
||||
local offset = meta:get_int("offset")
|
||||
local extrusion = meta:get_int("extrusion")
|
||||
local facing = meta:get_int("facing")
|
||||
local item_name = meta:get_string("item")
|
||||
local offset = tonumber(meta_fields.offset)
|
||||
local extrusion = tonumber(meta_fields.extrusion)
|
||||
local facing = tonumber(meta_fields.facing)
|
||||
local item_name = meta_fields.item
|
||||
|
||||
return "size[8,5.2]" ..
|
||||
"item_image[0,0;1,1;" .. item_name .. "]"..
|
||||
@ -87,22 +85,40 @@ local inv = minetest.create_detached_inventory("digtron:builder_item", {
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
local digtron_id = meta:get_string("digtron_id")
|
||||
if digtron_id ~= "" then
|
||||
minetest.log("warning", "[Digtron] builder detached inventory had player " .. player_name
|
||||
.. " attempt to set " .. item .. " at " .. minetest.pos_to_string(pos) ..
|
||||
" but the builder node at that location was already assembled into " .. digtron_id)
|
||||
return 0
|
||||
local digtron_layout_id = meta:get_int("digtron_layout_node_id")
|
||||
|
||||
local layout
|
||||
local layout_fields
|
||||
minetest.chat_send_all(digtron_id)
|
||||
minetest.chat_send_all(digtron_layout_id)
|
||||
if digtron_id ~= "" and digtron_layout_id ~= 0 then
|
||||
layout = digtron.get_layout(digtron_id)
|
||||
layout_fields = layout[digtron_layout_id].meta.fields
|
||||
end
|
||||
|
||||
-- If we're adding a wallmounted item and the build facing is greater than 5, reset it to 0
|
||||
if stack_def ~= nil and stack_def.paramtype2 == "wallmounted" and tonumber(meta:get_int("facing")) > 5 then
|
||||
meta:set_int("facing", 0)
|
||||
if layout_fields then
|
||||
layout_fields.facing = 0
|
||||
end
|
||||
end
|
||||
|
||||
meta:set_string("item", item)
|
||||
digtron.update_builder_item(pos)
|
||||
minetest.show_formspec(player_name, "digtron:builder", get_formspec(pos))
|
||||
if layout_fields then
|
||||
layout_fields.item = item
|
||||
end
|
||||
|
||||
if layout_fields then
|
||||
minetest.chat_send_all("setting layout")
|
||||
digtron.set_layout(digtron_id, layout)
|
||||
else
|
||||
layout_fields = meta:to_table().fields
|
||||
end
|
||||
|
||||
digtron.update_builder_item(pos)
|
||||
|
||||
minetest.show_formspec(player_name, "digtron:builder", get_formspec(layout_fields))
|
||||
return 0
|
||||
end,
|
||||
allow_take = function(inv, listname, index, stack, player)
|
||||
@ -123,17 +139,19 @@ local builder_on_rightclick = function(pos, node, clicker, itemstack, pointed_th
|
||||
local meta = minetest.get_meta(pos)
|
||||
|
||||
local digtron_id = meta:get_string("digtron_id")
|
||||
if digtron_id ~= "" then
|
||||
minetest.sound_play({name = "digtron_error", gain = 0.1}, {to_player=player_name})
|
||||
minetest.chat_send_player(player_name, S("This Digtron is active, interact with it via the controller node."))
|
||||
digtron.update_builder_items(digtron_id)
|
||||
local digtron_node_id = meta:get_int("digtron_layout_node_id")
|
||||
if digtron_id ~= "" and digtron_node_id ~= 0 then
|
||||
player_interacting_with_builder_pos[player_name] = pos
|
||||
local layout = digtron.get_layout(digtron_id)
|
||||
local data = layout[digtron_node_id]
|
||||
if data then
|
||||
minetest.show_formspec(player_name, "digtron:builder", get_formspec(data.meta.fields))
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
player_interacting_with_builder_pos[player_name] = pos
|
||||
minetest.show_formspec(player_name,
|
||||
"digtron:builder",
|
||||
get_formspec(pos))
|
||||
minetest.show_formspec(player_name, "digtron:builder", get_formspec(meta:to_table().fields))
|
||||
end
|
||||
|
||||
minetest.register_on_player_receive_fields(function(sender, formname, fields)
|
||||
@ -150,47 +168,62 @@ minetest.register_on_player_receive_fields(function(sender, formname, fields)
|
||||
end
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
local meta_table
|
||||
|
||||
local item = meta:get_string("item")
|
||||
local digtron_id = meta:get_string("digtron_id")
|
||||
local digtron_layout_id = meta:get_int("digtron_layout_node_id")
|
||||
|
||||
local layout
|
||||
if digtron_id ~= "" and digtron_layout_id ~= 0 then
|
||||
-- If this builder is part of an assembled Digtron, then the persisted Digtron
|
||||
-- layout will have primacy over any other metadata this node might have.
|
||||
layout = digtron.get_layout(digtron_id)
|
||||
meta_table = layout[digtron_layout_id].meta
|
||||
else
|
||||
meta_table = meta:to_table()
|
||||
end
|
||||
local meta_fields = meta_table.fields
|
||||
|
||||
local item = meta_fields.item
|
||||
|
||||
local period = tonumber(fields.period)
|
||||
if period and period > 0 then
|
||||
meta:set_int("period", math.floor(period))
|
||||
meta_fields.period = math.floor(period)
|
||||
else
|
||||
period = meta:get_int("period")
|
||||
period = tonumber(meta_fields.period) or 1
|
||||
end
|
||||
|
||||
local offset = tonumber(fields.offset)
|
||||
if offset then
|
||||
meta:set_int("offset", math.floor(offset))
|
||||
meta_fields.offset = math.floor(offset)
|
||||
else
|
||||
offset = meta:get_int("offset")
|
||||
offset = tonumber(meta_fields.offset) or 0
|
||||
end
|
||||
|
||||
local facing = tonumber(fields.facing)
|
||||
if facing and facing >= 0 and facing < 24 then
|
||||
local target_item = ItemStack(item)
|
||||
if target_item:get_definition().paramtype2 == "wallmounted" then
|
||||
if facing < 6 then
|
||||
meta:set_int("facing", math.floor(facing))
|
||||
-- wallmounted facings only run from 0-5
|
||||
if facing < 6 then
|
||||
meta_fields.facing = math.floor(facing)
|
||||
end
|
||||
else
|
||||
meta:set_int("facing", math.floor(facing))
|
||||
meta_fields.facing = math.floor(facing)
|
||||
end
|
||||
else
|
||||
facing = meta:get_int("facing")
|
||||
facing = tonumber(meta_fields.facing) or 0
|
||||
end
|
||||
|
||||
local extrusion = tonumber(fields.extrusion)
|
||||
if extrusion and extrusion > 0 and extrusion <= digtron.config.maximum_extrusion then
|
||||
meta:set_int("extrusion", math.floor(extrusion))
|
||||
meta_fields.extrusion = math.floor(extrusion)
|
||||
else
|
||||
extrusion = meta:get_int("extrusion")
|
||||
extrusion = tonumber(meta_fields.extrusion) or 1
|
||||
end
|
||||
|
||||
if fields.set then
|
||||
--digtron.show_offset_markers(pos, offset, period)
|
||||
--TODO digtron.show_offset_markers(pos, offset, period)
|
||||
end
|
||||
|
||||
if fields.read then
|
||||
@ -202,10 +235,9 @@ minetest.register_on_player_receive_fields(function(sender, formname, fields)
|
||||
target_name = digtron.builder_read_item_substitutions[target_name]
|
||||
end
|
||||
if target_name ~= "air" and is_item_allowed(target_name) then
|
||||
local meta = minetest.get_meta(pos)
|
||||
item = target_name
|
||||
meta:set_string("item", item)
|
||||
meta:set_int("facing", target_node.param2)
|
||||
meta_fields.item = item
|
||||
meta_fields.facing = target_node.param2
|
||||
end
|
||||
end
|
||||
|
||||
@ -214,14 +246,21 @@ minetest.register_on_player_receive_fields(function(sender, formname, fields)
|
||||
end
|
||||
|
||||
local item_def = minetest.registered_items[item]
|
||||
local item_desc = "Nothing"
|
||||
local item_desc = S("Nothing")
|
||||
if item_def then
|
||||
item_desc = item_def.description
|
||||
end
|
||||
|
||||
meta:set_string("infotext", S("Builder for @1\nperiod @2, offset @3, extrusion @4", item_desc, period, offset, extrusion))
|
||||
meta_fields.infotext = S("Builder for @1\nperiod @2, offset @3, extrusion @4", item_desc, period, offset, extrusion)
|
||||
if layout then
|
||||
digtron.set_layout(digtron_id, layout)
|
||||
end
|
||||
meta_fields.digtron_id = digtron_id
|
||||
meta_fields.digtron_layout_node_id = digtron_layout_id
|
||||
meta:from_table(meta_table)
|
||||
|
||||
digtron.update_builder_item(pos)
|
||||
minetest.show_formspec(player_name, "digtron:builder", get_formspec(pos))
|
||||
minetest.show_formspec(player_name, "digtron:builder", get_formspec(meta_fields))
|
||||
|
||||
end)
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
local S = digtron.S
|
||||
|
||||
-- Determines how many of each type of Digtron node is needed to build another Digtron
|
||||
local get_manifest = function(pos)
|
||||
local manifest = {}
|
||||
local meta = minetest.get_meta(pos)
|
||||
@ -9,9 +10,11 @@ local get_manifest = function(pos)
|
||||
local digtron_id = stack_meta:get_string("digtron_id")
|
||||
if digtron_id ~= "" then
|
||||
local layout = digtron.get_layout(digtron_id)
|
||||
for hash, data in pairs(layout) do
|
||||
for layout_node_id, data in pairs(layout) do
|
||||
local item = data.node.name
|
||||
local item_def = minetest.registered_items[item]
|
||||
-- Some digtron nodes change into other nodes when they become active.
|
||||
-- This determines what the original node was in those cases
|
||||
if item_def._digtron_disassembled_node then
|
||||
item = item_def._digtron_disassembled_node
|
||||
item_def = minetest.registered_items[item]
|
||||
|
Loading…
Reference in New Issue
Block a user