remove pointset class - much simpler to use a table with hashed vector keys
This commit is contained in:
parent
40e86f91a7
commit
81756a6207
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user