summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFaceDeer <derksenmobile@gmail.com>2017-01-08 01:23:10 -0700
committerFaceDeer <derksenmobile@gmail.com>2017-01-08 01:23:10 -0700
commitd7e5309833bc7044447982424dc8431d84d7a1a0 (patch)
treedb1081d61fd650db0593ef190b0bb32f93a19b3a
parente704249735372a3232883cc8b7f25679f4949a8d (diff)
Added a rotation controller
Well that was a lot of work. Also, switched the "waiting" timer management to the actual on_timer system - I noticed that minetest.after wasn't persisting through server shutdown and restart, that could put a controller in a "broken" state.
-rw-r--r--README.txt5
-rw-r--r--init.lua3
-rw-r--r--node_axle.lua58
-rw-r--r--node_builders.lua6
-rw-r--r--node_controllers.lua32
-rw-r--r--recipes.lua17
-rw-r--r--sounds/license.txt3
-rw-r--r--sounds/whirr.oggbin0 -> 22337 bytes
-rw-r--r--textures/digtron_axel_side.pngbin0 -> 737 bytes
-rw-r--r--textures/digtron_axel_top.pngbin0 -> 743 bytes
-rw-r--r--util_execute_cycle.lua12
-rw-r--r--util_layout.lua250
-rw-r--r--util_movement.lua6
13 files changed, 361 insertions, 31 deletions
diff --git a/README.txt b/README.txt
index a2103ea..6cd65b9 100644
--- a/README.txt
+++ b/README.txt
@@ -52,6 +52,11 @@ Aka the "can you rebuild it six inches to the left" module. This is a much simpl
Since movement alone does not require fuel, a pusher module has no internal furnace.
+Rotation Unit
+-----------
+
+This magical module can rotate a Digtron array in place around itself. Right-clicking on it will rotate the Digtron 90 degrees in the direction the orange arrows on its sides indicate (widdershins around the Y axis by default, use the screwdriver to change this) assuming there's space for the Digtron in its new orientation. Builders and diggers will not trigger.
+
Digger Head
-----------
diff --git a/init.lua b/init.lua
index eed2ad7..af0492c 100644
--- a/init.lua
+++ b/init.lua
@@ -6,7 +6,8 @@ dofile( minetest.get_modpath( "digtron" ) .. "/node_storage.lua" ) -- contains i
dofile( minetest.get_modpath( "digtron" ) .. "/node_diggers.lua" ) -- contains all diggers
dofile( minetest.get_modpath( "digtron" ) .. "/node_builders.lua" ) -- contains all builders (there's just one currently)
dofile( minetest.get_modpath( "digtron" ) .. "/node_controllers.lua" ) -- controllers
-dofile( minetest.get_modpath( "digtron" ) .."/recipes.lua" )
+dofile( minetest.get_modpath( "digtron" ) .. "/node_axle.lua" ) -- Rotation controller
+dofile( minetest.get_modpath( "digtron" ) .. "/recipes.lua" )
digtron.creative_mode = false -- this causes digtrons to operate without consuming fuel or building materials.
digtron.particle_effects = true -- Enables the spray of particles out the back of a digger head and puffs of smoke from the controller
diff --git a/node_axle.lua b/node_axle.lua
new file mode 100644
index 0000000..5859777
--- /dev/null
+++ b/node_axle.lua
@@ -0,0 +1,58 @@
+minetest.register_node("digtron:axle", {
+ description = "Digtron Rotation Unit",
+ groups = {cracky = 3, oddly_breakable_by_hand=3, digtron = 1},
+ drop = "digtron:axel",
+ sounds = digtron.metal_sounds,
+ paramtype = "light",
+ paramtype2= "facedir",
+ is_ground_content = false,
+ -- Aims in the +Z direction by default
+ tiles = {
+ "digtron_axel_top.png",
+ "digtron_axel_top.png",
+ "digtron_axel_side.png",
+ "digtron_axel_side.png",
+ "digtron_axel_side.png",
+ "digtron_axel_side.png",
+ },
+
+ drawtype = "nodebox",
+ node_box = {
+ type = "fixed",
+ fixed = {
+ {-0.5, 0.3125, -0.3125, 0.5, 0.5, 0.3125}, -- Uppercap
+ {-0.5, -0.5, -0.3125, 0.5, -0.3125, 0.3125}, -- Lowercap
+ {-0.3125, 0.3125, -0.5, 0.3125, 0.5, -0.3125}, -- Uppercap_edge2
+ {-0.3125, 0.3125, 0.3125, 0.3125, 0.5, 0.5}, -- Uppercap_edge1
+ {-0.3125, -0.5, -0.5, 0.3125, -0.3125, -0.3125}, -- Lowercap_edge1
+ {-0.3125, -0.5, 0.3125, 0.3125, -0.3125, 0.5}, -- Lowercap_edge2
+ {-0.25, -0.3125, -0.25, 0.25, 0.3125, 0.25}, -- Axel
+ }
+ },
+
+ on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
+ local meta = minetest.get_meta(pos)
+ if meta:get_string("waiting") == "true" then
+ -- Been too soon since last time the digtron rotated.
+ return
+ end
+ local image = digtron.get_layout_image(pos, clicker)
+ digtron.rotate_layout_image(image, node.param2)
+ if digtron.can_write_layout_image(image, clicker) then
+ digtron.write_layout_image(image)
+
+ minetest.sound_play("whirr", {gain=1.0, pos=pos})
+ meta = minetest.get_meta(pos)
+ meta:set_string("waiting", "true")
+ meta:set_string("infotext", nil)
+ minetest.get_node_timer(pos):start(digtron.cycle_time*2)
+ else
+ minetest.sound_play("buzzer", {gain=1.0, pos=pos})
+ meta:set_string("infotext", "Digtron is obstructed.")
+ end
+ end,
+
+ on_timer = function(pos, elapsed)
+ minetest.get_meta(pos):set_string("waiting", nil)
+ end,
+}) \ No newline at end of file
diff --git a/node_builders.lua b/node_builders.lua
index 94467a8..9e348cc 100644
--- a/node_builders.lua
+++ b/node_builders.lua
@@ -89,6 +89,8 @@ minetest.register_node("digtron:builder", {
offset = meta:get_int("offset")
end
if build_facing and build_facing >= 0 and build_facing < 24 then
+ -- TODO: wallmounted facings only run from 0-5, a player could theoretically put a wallmounted item into the builder and then manually set the build facing to an invalid number
+ -- Should prevent that somehow. But not tonight.
meta:set_int("build_facing", math.floor(build_facing))
end
@@ -134,6 +136,10 @@ minetest.register_node("digtron:builder", {
on_destruct = function(pos)
digtron.remove_builder_item(pos)
end,
+
+ after_place_node = function(pos)
+ digtron.update_builder_item(pos)
+ end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
local inv = minetest.get_inventory({type="node", pos=pos})
diff --git a/node_controllers.lua b/node_controllers.lua
index 323b8f2..7dc1e7f 100644
--- a/node_controllers.lua
+++ b/node_controllers.lua
@@ -58,11 +58,11 @@ minetest.register_node("digtron:controller", {
-- Start the delay before digtron can run again.
minetest.get_meta(newpos):set_string("waiting", "true")
- minetest.after(digtron.cycle_time,
- function (pos)
- minetest.get_meta(pos):set_string("waiting", nil)
- end, newpos
- )
+ minetest.get_node_timer(newpos):start(digtron.cycle_time)
+ end,
+
+ on_timer = function(pos, elapsed)
+ minetest.get_meta(pos):set_string("waiting", nil)
end,
})
@@ -180,6 +180,11 @@ minetest.register_node("digtron:auto_controller", {
meta:set_string("waiting", "true")
meta:set_string("formspec", auto_formspec)
end,
+
+ on_timer = function(pos, elapsed)
+ minetest.get_meta(pos):set_string("waiting", nil)
+ end,
+
})
---------------------------------------------------------------------------------------------------------------
@@ -250,11 +255,7 @@ minetest.register_node("digtron:pusher", {
if not can_move then
-- mark this node as waiting, will clear this flag in digtron.cycle_time seconds
meta:set_string("waiting", "true")
- minetest.after(digtron.cycle_time,
- function (pos)
- minetest.get_meta(pos):set_string("waiting", nil)
- end, pos
- )
+ minetest.get_node_timer(pos):start(digtron.cycle_time)
minetest.sound_play("squeal", {gain=1.0, pos=pos})
minetest.sound_play("buzzer", {gain=0.5, pos=pos})
meta:set_string("infotext", "Digtron is obstructed.")
@@ -283,10 +284,11 @@ minetest.register_node("digtron:pusher", {
-- Start the delay before digtron can run again. Do this after moving the array or pos will be wrong.
minetest.get_meta(pos):set_string("waiting", "true")
- minetest.after(digtron.cycle_time,
- function (pos)
- minetest.get_meta(pos):set_string("waiting", nil)
- end, pos
- )
+ minetest.get_node_timer(pos):start(digtron.cycle_time)
+ end,
+
+ on_timer = function(pos, elapsed)
+ minetest.get_meta(pos):set_string("waiting", nil)
end,
+
}) \ No newline at end of file
diff --git a/recipes.lua b/recipes.lua
index 141ebf2..7f368cf 100644
--- a/recipes.lua
+++ b/recipes.lua
@@ -102,6 +102,15 @@ minetest.register_craft({
}
})
+minetest.register_craft({
+ output = "digtron:axle",
+ recipe = {
+ {"default:coal_lump","default:coal_lump","default:coal_lump"},
+ {"default:coal_lump","digtron:digtron_core","default:coal_lump"},
+ {"default:coal_lump","default:coal_lump","default:coal_lump"}
+ }
+})
+
-- Structural
minetest.register_craft({
@@ -193,7 +202,6 @@ minetest.register_craft({
}
})
-
minetest.register_craft({
output = "digtron:digtron_core",
recipe = {
@@ -227,4 +235,11 @@ minetest.register_craft({
recipe = {
{"digtron:pusher"},
}
+})
+
+minetest.register_craft({
+ output = "digtron:digtron_core",
+ recipe = {
+ {"digtron:axle"},
+ }
}) \ No newline at end of file
diff --git a/sounds/license.txt b/sounds/license.txt
index 165e797..afaaa45 100644
--- a/sounds/license.txt
+++ b/sounds/license.txt
@@ -1,13 +1,14 @@
The sounds in this folder were sampled from source .wavs from Freesound.org. Specifically:
buzzer.ogg - https://freesound.org/people/hypocore/sounds/164090/ - public domain via CC 1.0 by hypocore
-construction.ogg - https://www.freesound.org/people/mediapetros/sounds/109117/ - under the CC by 3.0 license by mediapetros
+construction.ogg - https://www.freesound.org/people/mediapetros/sounds/109117/ - under the CC BY 3.0 license by mediapetros
dingding.ogg - https://www.freesound.org/people/JohnsonBrandEditing/sounds/173932/ public domain via CC 1.0 by JohnsonBrandEditing
squeal.ogg - https://www.freesound.org/people/RutgerMuller/sounds/104026/ public domain via CC 1.0 by RutgerMuller
honk.ogg - https://freesound.org/people/bigmanjoe/sounds/349922/ public domain via CC 1.0 by bigmanjoe
truck.ogg - https://www.freesound.org/people/jberkuta14/sounds/134898/ public domain via CC 1.0 by jberkuta14
sploosh.ogg - https://www.freesound.org/people/mr_marcello/sounds/257609/ public domain via CC 1.0 by mr_marcello
woopwoopwoop.ogg - https://www.freesound.org/people/gregconquest/sounds/188012/ public domain via CC 1.0 by gregconquest
+whirr.ogg - https://www.freesound.org/people/daveincamas/sounds/25034/ - under the CC BY 3.0 license by daveincamas
Creative Commons Attribution 3.0 license:
diff --git a/sounds/whirr.ogg b/sounds/whirr.ogg
new file mode 100644
index 0000000..ebb3dc7
--- /dev/null
+++ b/sounds/whirr.ogg
Binary files differ
diff --git a/textures/digtron_axel_side.png b/textures/digtron_axel_side.png
new file mode 100644
index 0000000..b69b221
--- /dev/null
+++ b/textures/digtron_axel_side.png
Binary files differ
diff --git a/textures/digtron_axel_top.png b/textures/digtron_axel_top.png
new file mode 100644
index 0000000..86f292f
--- /dev/null
+++ b/textures/digtron_axel_top.png
Binary files differ
diff --git a/util_execute_cycle.lua b/util_execute_cycle.lua
index 0fe212e..c9614d5 100644
--- a/util_execute_cycle.lua
+++ b/util_execute_cycle.lua
@@ -122,11 +122,7 @@ digtron.execute_cycle = function(pos, clicker)
if not can_move then
-- mark this node as waiting, will clear this flag in digtron.cycle_time seconds
minetest.get_meta(pos):set_string("waiting", "true")
- minetest.after(digtron.cycle_time,
- function (pos)
- minetest.get_meta(pos):set_string("waiting", nil)
- end, pos
- )
+ minetest.get_node_timer(pos):start(digtron.cycle_time)
minetest.sound_play("squeal", {gain=1.0, pos=pos})
minetest.sound_play("buzzer", {gain=0.5, pos=pos})
return pos, "Digtron is obstructed.\n" .. status_text, 3 --Abort, don't dig and don't build.
@@ -181,11 +177,7 @@ digtron.execute_cycle = function(pos, clicker)
if not can_build then
minetest.get_meta(pos):set_string("waiting", "true")
- minetest.after(digtron.cycle_time,
- function (pos)
- minetest.get_meta(pos):set_string("waiting", nil)
- end, pos
- )
+ minetest.get_node_timer(pos):start(digtron.cycle_time)
local return_string = nil
local return_code = 5
if test_build_return_code == 3 then
diff --git a/util_layout.lua b/util_layout.lua
index bae75fd..5b68919 100644
--- a/util_layout.lua
+++ b/util_layout.lua
@@ -108,4 +108,252 @@ digtron.get_all_digtron_neighbours = function(pos, player)
end
return layout
-end \ No newline at end of file
+end
+
+-- Rotation magic
+--------------------------------------------------------------------------------------------------------
+
+local facedir_rotate = {
+ ['x'] = {
+ [-1] = {[0]=4, 5, 6, 7, 22, 23, 20, 21, 0, 1, 2, 3, 13, 14, 15, 12, 19, 16, 17, 18, 10, 11, 8, 9}, -- 270 degrees
+ [1] = {[0]=8, 9, 10, 11, 0, 1, 2, 3, 22, 23, 20, 21, 15, 12, 13, 14, 17, 18, 19, 16, 6, 7, 4, 5}, -- 90 degrees
+ },
+ ['y'] = {
+ [-1] = {[0]=3, 0, 1, 2, 19, 16, 17, 18, 15, 12, 13, 14, 7, 4, 5, 6, 11, 8, 9, 10, 21, 22, 23, 20}, -- 270 degrees
+ [1] = {[0]=1, 2, 3, 0, 13, 14, 15, 12, 17, 18, 19, 16, 9, 10, 11, 8, 5, 6, 7, 4, 23, 20, 21, 22}, -- 90 degrees
+ },
+ ['z'] = {
+ [-1] = {[0]=16, 17, 18, 19, 5, 6, 7, 4, 11, 8, 9, 10, 0, 1, 2, 3, 20, 21, 22, 23, 12, 13, 14, 15}, -- 270 degrees
+ [1] = {[0]=12, 13, 14, 15, 7, 4, 5, 6, 9, 10, 11, 8, 20, 21, 22, 23, 0, 1, 2, 3, 16, 17, 18, 19}, -- 90 degrees
+ }
+}
+
+local wallmounted_rotate = {
+ ['x'] = {
+ [-1] = {[0]=4, 5, 2, 3, 1, 0}, -- 270 degrees
+ [1] = {[0]=5, 4, 2, 3, 0, 1}, -- 90 degrees
+ },
+ ['y'] = {
+ [-1] = {[0]=0, 1, 4, 5, 3, 2}, -- 270 degrees
+ [1] = {[0]=0, 1, 5, 4, 2, 3}, -- 90 degrees
+ },
+ ['z'] = {
+ [-1] = {[0]=3, 2, 0, 1, 4, 5}, -- 270 degrees
+ [1] = {[0]=2, 3, 1, 0, 4, 5}, -- 90 degrees
+ }
+}
+
+ --90 degrees CW about x-axis: (x, y, z) -> (x, -z, y)
+ --90 degrees CCW about x-axis: (x, y, z) -> (x, z, -y)
+ --90 degrees CW about y-axis: (x, y, z) -> (-z, y, x)
+ --90 degrees CCW about y-axis: (x, y, z) -> (z, y, -x)
+ --90 degrees CW about z-axis: (x, y, z) -> (y, -x, z)
+ --90 degrees CCW about z-axis: (x, y, z) -> (-y, x, z)
+local rotate_pos = function(axis, direction, pos)
+ if axis == "x" then
+ if direction < 0 then
+ return {x= pos.x, y= -pos.z, z= pos.y}
+ else
+ return {x= pos.x, y= pos.z, z= -pos.y}
+ end
+ elseif axis == "y" then
+ if direction < 0 then
+ return {x= -pos.z, y= pos.y, z= pos.x}
+ else
+ return {x= pos.z, y= pos.y, z= -pos.x}
+ end
+ else
+ if direction < 0 then
+ return {x= -pos.y, y= pos.x, z= pos.z}
+ else
+ return {x= pos.y, y= -pos.x, z= pos.z}
+ end
+ end
+end
+
+local get_node_image = function(pos, node)
+ local node_image = {node=node, pos={x=pos.x, y=pos.y, z=pos.z}}
+ node_image.paramtype2 = minetest.registered_nodes[node.name].paramtype2
+ local meta = minetest.get_meta(pos)
+ node_image.meta = meta:to_table()
+
+ -- Record what kind of thing we've got in a builder node so its facing can be rotated properly
+ if minetest.get_item_group(node.name, "digtron") == 4 then
+ local build_item = node_image.meta.inventory.main[1]
+ if build_item ~= "" then
+ local build_item_def = minetest.registered_nodes[ItemStack(build_item):get_name()]
+ node_image.build_item_paramtype2 = build_item_def.paramtype2
+ end
+ end
+ return node_image
+end
+
+local rotate_node_image = function(node_image, origin, axis, direction, old_pos_pointset)
+ -- Facings
+ if node_image.paramtype2 == "wallmounted" then
+ node_image.node.param2 = wallmounted_rotate[axis][direction][node_image.node.param2]
+ elseif node_image.paramtype2 == "facedir" then
+ node_image.node.param2 = facedir_rotate[axis][direction][node_image.node.param2]
+ end
+
+ if node_image.build_item_paramtype2 == "wallmounted" then
+ node_image.meta.fields.build_facing = wallmounted_rotate[axis][direction][node_image.meta.fields.build_facing]
+ elseif node_image.build_item_paramtype2 == "facedir" then
+ node_image.meta.fields.build_facing = facedir_rotate[axis][direction][node_image.meta.fields.build_facing]
+ end
+
+ node_image.meta.fields.waiting = nil -- If we're rotating a controller that's in the "waiting" state, clear it. Otherwise it may stick like that.
+
+ -- record the old location so we can destroy the old node if the rotation operation is possible
+ old_pos_pointset:set(node_image.pos.x, node_image.pos.y, node_image.pos.z, true)
+
+ -- position in space relative to origin
+ local pos = vector.subtract(node_image.pos, origin)
+ pos = rotate_pos(axis, direction, pos)
+ -- Move back to original reference frame
+ node_image.pos = vector.add(pos, origin)
+
+ return node_image
+end
+
+digtron.rotate_layout_image = function(layout_image, facedir)
+ -- To convert this into the direction the "top" of the axel node is pointing in:
+ -- 0, 1, 2, 3 == (0,1,0)
+ -- 4, 5, 6, 7 == (0,0,1)
+ -- 8, 9, 10, 11 == (0,0,-1)
+ -- 12, 13, 14, 15 == (1,0,0)
+ -- 16, 17, 18, 19 == (-1,0,0)
+ -- 20, 21, 22, 23== (0,-1,0)
+
+ local top = {
+ [0]={axis="y", dir=-1},
+ {axis="z", dir=1},
+ {axis="z", dir=-1},
+ {axis="x", dir=1},
+ {axis="x", dir=-1},
+ {axis="y", dir=1},
+ }
+ local params = top[math.floor(facedir/4)]
+
+ layout_image.old_pos_pointset = Pointset:create()
+
+ for k, node_image in pairs(layout_image.all) do
+ rotate_node_image(node_image, layout_image.controller, params.axis, params.dir, layout_image.old_pos_pointset)
+ end
+ return layout_image
+end
+
+digtron.can_write_layout_image = function(layout_image, player)
+ for k, node_image in pairs(layout_image.all) do
+ if not layout_image.old_pos_pointset:get(node_image.pos.x, node_image.pos.y, node_image.pos.z)
+ and not minetest.registered_nodes[minetest.get_node(node_image.pos).name].buildable_to then
+ return false
+ elseif minetest.is_protected(node_image.pos, player:get_player_name()) and not minetest.check_player_privs(player, "protection_bypass") then
+ return false
+ end
+ end
+ return true
+end
+
+digtron.write_layout_image = function(layout_image)
+ -- destroy the old digtron
+ local oldpos, _ = layout_image.old_pos_pointset:pop()
+ while oldpos ~= nil do
+ local old_def = minetest.registered_nodes[minetest.get_node(oldpos).name]
+ minetest.remove_node(oldpos)
+ if old_def.after_dig_node ~= nil then
+ old_def.after_dig_node(oldpos)
+ end
+ oldpos, _ = layout_image.old_pos_pointset:pop()
+ end
+
+ -- create the new one
+ for k, node_image in pairs(layout_image.all) do
+ minetest.add_node(node_image.pos, node_image.node)
+ minetest.get_meta(node_image.pos):from_table(node_image.meta)
+
+ local new_def = minetest.registered_nodes[node_image.node.name]
+ if new_def.after_place_node ~= nil then
+ new_def.after_place_node(node_image.pos)
+ end
+ end
+end
+
+-- Similar to get_layout, but far more comprehensive. This produces a data structure plus a set of temporary inventories that will allow the digtron to be rotated and then recreated.
+digtron.get_layout_image = function(pos, player)
+
+ local image = {}
+ --initialize. We're assuming that the start position is a controller digtron, should be a safe assumption since only the controller node should call this
+ image.all = {}
+ image.extents = {}
+ image.controller = {x=pos.x, y=pos.y, z=pos.z} --Make a deep copy of the pos parameter just in case the calling code wants to play silly buggers with it
+ image.contains_protected_node = false -- used to indicate if at least one node in this digtron array is protected from the player.
+
+ table.insert(image.all, get_node_image(pos, minetest.get_node(pos)))
+
+ image.extents.max_x = pos.x
+ image.extents.min_x = pos.x
+ image.extents.max_y = pos.y
+ image.extents.min_y = pos.y
+ image.extents.max_z = pos.z
+ image.extents.min_z = pos.z
+
+ -- temporary pointsets used while searching
+ local to_test = Pointset.create()
+ local tested = Pointset.create()
+
+ tested:set(pos.x, pos.y, pos.z, true)
+ to_test:set(pos.x + 1, pos.y, pos.z, true)
+ to_test:set(pos.x - 1, pos.y, pos.z, true)
+ to_test:set(pos.x, pos.y + 1, pos.z, true)
+ to_test:set(pos.x, pos.y - 1, pos.z, true)
+ to_test:set(pos.x, pos.y, pos.z + 1, true)
+ to_test:set(pos.x, pos.y, pos.z - 1, true)
+
+ if minetest.is_protected(pos, player:get_player_name()) and not minetest.check_player_privs(player, "protection_bypass") then
+ image.contains_protected_node = true
+ end
+
+ -- Do a loop on to_test positions, adding new to_test positions as we find digtron nodes. This is a flood fill operation
+ -- that follows node faces (no diagonals)
+ local testpos, _ = to_test:pop()
+ while testpos ~= nil do
+ tested:set(testpos.x, testpos.y, testpos.z, true) -- track nodes we've looked at to prevent infinite loops
+ local node = minetest.get_node(testpos)
+
+ if node.name == "ignore" then
+ --buildtron array is next to unloaded nodes, too dangerous to do anything. Abort.
+ return nil
+ end
+
+ local group_number = minetest.get_item_group(node.name, "digtron")
+ if group_number > 0 then
+ --found one. Add it to the digtrons output
+ table.insert(image.all, get_node_image(testpos, node))
+
+ if minetest.is_protected(pos, player:get_player_name()) and not minetest.check_player_privs(player, "protection_bypass") then
+ image.contains_protected_node = true
+ end
+
+ -- update extents
+ image.extents.max_x = math.max(image.extents.max_x, testpos.x)
+ image.extents.min_x = math.min(image.extents.min_x, testpos.x)
+ image.extents.max_y = math.max(image.extents.max_y, testpos.y)
+ image.extents.min_y = math.min(image.extents.min_y, testpos.y)
+ image.extents.max_z = math.max(image.extents.max_z, testpos.z)
+ image.extents.min_z = math.min(image.extents.min_z, testpos.z)
+
+ --queue up potential new test points adjacent to this digtron node
+ to_test:set_if_not_in(tested, testpos.x + 1, testpos.y, testpos.z, true)
+ to_test:set_if_not_in(tested, testpos.x - 1, testpos.y, testpos.z, true)
+ to_test:set_if_not_in(tested, testpos.x, testpos.y + 1, testpos.z, true)
+ to_test:set_if_not_in(tested, testpos.x, testpos.y - 1, testpos.z, true)
+ to_test:set_if_not_in(tested, testpos.x, testpos.y, testpos.z + 1, true)
+ to_test:set_if_not_in(tested, testpos.x, testpos.y, testpos.z - 1, true)
+ end
+
+ testpos, _ = to_test:pop()
+ end
+
+ return image
+end
diff --git a/util_movement.lua b/util_movement.lua
index 218ba48..f7c36dd 100644
--- a/util_movement.lua
+++ b/util_movement.lua
@@ -6,8 +6,10 @@ digtron.move_node = function(pos, newpos, player_name)
minetest.log("action", string.format("%s moves %s from (%d, %d, %d) to (%d, %d, %d), displacing %s", player_name, node.name, pos.x, pos.y, pos.z, newpos.x, newpos.y, newpos.z, oldnode.name))
minetest.add_node(newpos, { name=node.name, param1=node.param1, param2=node.param2 })
-- copy the metadata
- local oldmeta = minetest.get_meta(pos):to_table()
- minetest.get_meta(newpos):from_table(oldmeta)
+ local oldmeta_table = minetest.get_meta(pos):to_table()
+ local meta = minetest.get_meta(newpos)
+ meta:from_table(oldmeta_table)
+ meta:set_string("waiting", nil) -- If a controller moves another controller that's in the waiting state, clear the waiting state otherwise it might get stuck like that (we've moved it away from the target of the pending 'clear the waiting state' delegate call). That means you can run a digtron as fast as you want by rapidly clicking between two different controllers, but shhh - don't tell the player that.
-- Move the little floaty entity inside the builders
if minetest.get_item_group(node.name, "digtron") == 4 then