diff --git a/class_pointset.lua b/class_pointset.lua deleted file mode 100644 index 3cbbd89..0000000 --- a/class_pointset.lua +++ /dev/null @@ -1,101 +0,0 @@ --- A simple special-purpose class, this is used for building up sets of three-dimensional points for fast reference - -Pointset = {} -Pointset.__index = Pointset - -function Pointset.create() - local set = {} - setmetatable(set,Pointset) - set.points = {} - return set -end - -function Pointset:set(x, y, z, value) - -- sets a value in the 3D array "points". - if self.points[x] == nil then - self.points[x] = {} - end - if self.points[x][y] == nil then - self.points[x][y] = {} - end - self.points[x][y][z] = value -end - -function Pointset:set_if_not_in(excluded, x, y, z, value) - -- If a value is not already set for this point in the 3D array "excluded", set it in "points" - if excluded:get(x, y, z) ~= nil then - return - end - self:set(x, y, z, value) -end - -function Pointset:get(x, y, z) - -- return a value from the 3D array "points" - if self.points[x] == nil or self.points[x][y] == nil then - return nil - end - return self.points[x][y][z] -end - -function Pointset:set_pos(pos, value) - self:set(pos.x, pos.y, pos.z, value) -end - -function Pointset:set_pos_if_not_in(excluded, pos, value) - self:set_if_not_in(excluded, pos.x, pos.y, pos.z, value) -end - -function Pointset:get_pos(pos) - return self:get(pos.x, pos.y, pos.z) -end - -function Pointset:pop() - -- returns a point that's in the 3D array, and then removes it. - local pos = {} - local ytable - local ztable - local val - - local count = 0 - for _ in pairs(self.points) do count = count + 1 end - if count == 0 then - return nil - end - - pos.x, ytable = next(self.points) - pos.y, ztable = next(ytable) - pos.z, val = next(ztable) - - self.points[pos.x][pos.y][pos.z] = nil - - count = 0 - for _ in pairs(self.points[pos.x][pos.y]) do count = count + 1 end - if count == 0 then - self.points[pos.x][pos.y] = nil - end - - count = 0 - for _ in pairs(self.points[pos.x]) do count = count + 1 end - if count == 0 then - self.points[pos.x] = nil - end - - return pos, val -end - -function Pointset:get_pos_list(value) - -- Returns a list of all points with the given value in standard Minetest vector format. If no value is provided, returns all points - local outlist = {} - for x, ytable in ipairs(self.points) do - for y, ztable in ipairs(ytable) do - for z, val in ipairs(ztable) do - if (value == nil and val ~= nil ) or val == value then - table.insert(outlist, {x=x, y=y, z=z}) - end - end - end - end - return outlist -end - - \ No newline at end of file diff --git a/gate_functions.lua b/gate_functions.lua index c44cda5..41cecfc 100644 --- a/gate_functions.lua +++ b/gate_functions.lua @@ -1,5 +1,4 @@ local MP = minetest.get_modpath(minetest.get_current_modname()) -dofile(MP.."/class_pointset.lua") -- Given a facedir, returns a set of all the corresponding directions local get_dirs = function(facedir) @@ -130,17 +129,16 @@ local get_door_layout = function(pos, facedir, player) door.previous_move = minetest.get_meta(pos):get_string("previous_move") -- temporary pointsets used while searching - local to_test = Pointset.create() - local tested = Pointset.create() - local can_slide_to = Pointset.create() + local to_test = {} + local tested = {} + local can_slide_to = {} local castle_gate_group_value -- this will be populated from the first gate node we encounter, which will be the one that was clicked on - to_test:set_pos(pos, true) - - local test_pos, _ = to_test:pop() + local test_pos = pos while test_pos ~= nil do - tested:set_pos(test_pos, true) -- track nodes we've looked at + local test_pos_hash = minetest.hash_node_position(test_pos) + tested[test_pos_hash] = true -- track nodes we've looked at local test_node = minetest.get_node(test_pos) if test_node.name == "ignore" then @@ -153,7 +151,9 @@ local get_door_layout = function(pos, facedir, player) end local test_node_def = minetest.registered_nodes[test_node.name] - can_slide_to:set_pos(test_pos, test_node_def.buildable_to == true) + if test_node_def.buildable_to then + can_slide_to[test_pos_hash] = true + end if test_node_def.paramtype2 == "facedir" and test_node.param2 <= 23 then -- prospective door nodes need to be of type facedir and have a valid param2 local test_node_dirs = get_dirs(test_node.param2) @@ -183,19 +183,23 @@ local get_door_layout = function(pos, facedir, player) end end - can_slide_to:set_pos(test_pos, true) -- since this is part of the door, other parts of the door can slide into it + can_slide_to[test_pos_hash] = true -- since this is part of the door, other parts of the door can slide into it local test_directions = {"top", "bottom", "left", "right"} for _, dir in pairs(test_directions) do local adjacent_pos = vector.add(test_pos, door.directions[dir]) local adjacent_node = minetest.get_node(adjacent_pos) local adjacent_def = minetest.registered_nodes[adjacent_node.name] - can_slide_to:set_pos(adjacent_pos, adjacent_def.buildable_to == true or adjacent_def.groups.castle_gate) + local adjacent_pos_hash = minetest.hash_node_position(adjacent_pos) + + if adjacent_def.buildable_to then + can_slide_to[adjacent_pos_hash] = true + end if test_node_def._gate_edges == nil or not test_node_def._gate_edges[dir] then -- if we ourselves are an edge node, don't look in the direction we're an edge in - if tested:get_pos(adjacent_pos) == nil then -- don't look at nodes that have already been looked at + + if tested[adjacent_pos_hash] == nil then -- don't look at nodes that have already been looked at if adjacent_def.paramtype2 == "facedir" then -- all doors are facedir nodes so we can pre-screen some targets - local edge_points_back_at_test_pos = false -- Look at the adjacent node's definition. If it's got gate edges, check if they point back at us. if adjacent_def._gate_edges ~= nil then @@ -209,7 +213,7 @@ local get_door_layout = function(pos, facedir, player) end if not edge_points_back_at_test_pos then - to_test:set_pos(adjacent_pos, true) + table.insert(to_test, adjacent_pos_hash) end end end @@ -218,17 +222,20 @@ local get_door_layout = function(pos, facedir, player) end end - test_pos, _ = to_test:pop() + test_pos = table.remove(to_test) + if test_pos ~= nil then + test_pos = minetest.get_position_from_hash(test_pos) + end end if door.hinge == nil then --sliding door, evaluate which directions it can go door.can_slide = {top=true, bottom=true, left=true, right=true} for _,door_node in pairs(door.all) do - door.can_slide.top = door.can_slide.top and can_slide_to:get_pos(vector.add(door_node.pos, door.directions.top)) - door.can_slide.bottom = door.can_slide.bottom and can_slide_to:get_pos(vector.add(door_node.pos, door.directions.bottom)) - door.can_slide.left = door.can_slide.left and can_slide_to:get_pos(vector.add(door_node.pos, door.directions.left)) - door.can_slide.right = door.can_slide.right and can_slide_to:get_pos(vector.add(door_node.pos, door.directions.right)) + door.can_slide.top = door.can_slide.top and can_slide_to[minetest.hash_node_position(vector.add(door_node.pos, door.directions.top))] + door.can_slide.bottom = door.can_slide.bottom and can_slide_to[minetest.hash_node_position(vector.add(door_node.pos, door.directions.bottom))] + door.can_slide.left = door.can_slide.left and can_slide_to[minetest.hash_node_position(vector.add(door_node.pos, door.directions.left))] + door.can_slide.right = door.can_slide.right and can_slide_to[minetest.hash_node_position(vector.add(door_node.pos, door.directions.right))] end else --rotating door, evaluate which direction it can go. Slightly more complicated.