diff options
Diffstat (limited to 'util_layout.lua')
-rw-r--r-- | util_layout.lua | 359 |
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 |