summaryrefslogtreecommitdiff
path: root/util_layout.lua
diff options
context:
space:
mode:
Diffstat (limited to 'util_layout.lua')
-rw-r--r--util_layout.lua359
1 files changed, 0 insertions, 359 deletions
diff --git a/util_layout.lua b/util_layout.lua
deleted file mode 100644
index 5077944..0000000
--- a/util_layout.lua
+++ /dev/null
@@ -1,359 +0,0 @@
-digtron.get_all_digtron_neighbours = function(pos, player)
- -- returns table containing a list of all digtron node locations, lists of special digtron node types, a table of the coordinate extents of the digtron array, a Pointset of protected nodes, and a number to determine how many adjacent solid non-digtron nodes there are (for traction)
-
- local layout = {}
- --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
- layout.traction = 0
- layout.all = {}
- layout.inventories = {}
- layout.fuelstores = {}
- layout.diggers = {}
- layout.builders = {}
- layout.extents = {}
- layout.water_touching = false
- layout.lava_touching = false
- layout.protected = Pointset.create() -- if any nodes we look at are protected, make note of that. That way we don't need to keep re-testing protection state later.
- layout.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
-
- table.insert(layout.all, layout.controller)
- layout.extents.max_x = pos.x
- layout.extents.min_x = pos.x
- layout.extents.max_y = pos.y
- layout.extents.min_y = pos.y
- layout.extents.max_z = pos.z
- layout.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
- layout.protected:set(pos.x, pos.y, pos.z, 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.
- layout.all = nil
- return layout
- end
-
- if minetest.is_protected(pos, player:get_player_name()) and not minetest.check_player_privs(player, "protection_bypass") then
- layout.protected:set(testpos.x, testpos.y, testpos.z, true)
- end
-
- if minetest.get_item_group(node.name, "water") ~= 0 then
- layout.water_touching = true
- elseif minetest.get_item_group(node.name, "lava") ~= 0 then
- layout.lava_touching = true
- if digtron.lava_impassible == true then
- layout.protected:set(testpos.x, testpos.y, testpos.z, true)
- end
- 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(layout.all, testpos)
-
- -- update extents
- layout.extents.max_x = math.max(layout.extents.max_x, testpos.x)
- layout.extents.min_x = math.min(layout.extents.min_x, testpos.x)
- layout.extents.max_y = math.max(layout.extents.max_y, testpos.y)
- layout.extents.min_y = math.min(layout.extents.min_y, testpos.y)
- layout.extents.max_z = math.max(layout.extents.max_z, testpos.z)
- layout.extents.min_z = math.min(layout.extents.min_z, testpos.z)
-
- -- add a reference to this node's position to special node lists
- if group_number == 2 then
- table.insert(layout.inventories, testpos)
- elseif group_number == 3 then
- table.insert(layout.diggers, testpos)
- elseif group_number == 4 then
- table.insert(layout.builders, testpos)
- elseif group_number == 5 then
- table.insert(layout.fuelstores, testpos)
- elseif group_number == 6 then
- table.insert(layout.inventories, testpos)
- table.insert(layout.fuelstores, testpos)
- end
-
- --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)
- elseif minetest.registered_nodes[node.name].buildable_to ~= true then
- -- Tracks whether the digtron is hovering in mid-air. If any part of the digtron array touches something solid it gains traction.
- layout.traction = layout.traction + 1
- end
-
- testpos, _ = to_test:pop()
- end
-
- return layout
-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][tonumber(node_image.meta.fields.build_facing)]
- elseif node_image.build_item_paramtype2 == "facedir" then
- node_image.meta.fields.build_facing = facedir_rotate[axis][direction][tonumber(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