summaryrefslogtreecommitdiff
path: root/api.lua
diff options
context:
space:
mode:
Diffstat (limited to 'api.lua')
-rw-r--r--api.lua119
1 files changed, 82 insertions, 37 deletions
diff --git a/api.lua b/api.lua
index 1a4026b..e8b9c7a 100644
--- a/api.lua
+++ b/api.lua
@@ -1,17 +1,54 @@
--- Returns a list of areas that include the provided position
+--- Returns a list of areas that include the provided position.
function areas:getAreasAtPos(pos)
- local a = {}
- local px, py, pz = pos.x, pos.y, pos.z
- for id, area in pairs(self.areas) do
- local ap1, ap2 = area.pos1, area.pos2
- if px >= ap1.x and px <= ap2.x and
- py >= ap1.y and py <= ap2.y and
- pz >= ap1.z and pz <= ap2.z then
- a[id] = area
+ local res = {}
+ if self.store then
+ local a = self.store:get_areas_for_pos(pos, false, true)
+ for store_id, store_area in pairs(a) do
+ local id = tonumber(store_area.data)
+ res[id] = self.areas[id]
+ end
+ else
+ local px, py, pz = pos.x, pos.y, pos.z
+ for id, area in pairs(self.areas) do
+ local ap1, ap2 = area.pos1, area.pos2
+ if
+ (px >= ap1.x and px <= ap2.x) and
+ (py >= ap1.y and py <= ap2.y) and
+ (pz >= ap1.z and pz <= ap2.z) then
+ res[id] = area
+ end
end
end
- return a
+ return res
+end
+
+--- Returns areas that intersect with the passed area.
+function areas:getAreasIntersectingArea(pos1, pos2)
+ local res = {}
+ if self.store then
+ local a = self.store:get_areas_in_area(pos1, pos2,
+ true, false, true)
+ for store_id, store_area in pairs(a) do
+ local id = tonumber(store_area.data)
+ res[id] = self.areas[id]
+ end
+ else
+ self:sortPos(pos1, pos2)
+ local p1x, p1y, p1z = pos1.x, pos1.y, pos1.z
+ local p2x, p2y, p2z = pos2.x, pos2.y, pos2.z
+ for id, area in pairs(self.areas) do
+ local ap1, ap2 = area.pos1, area.pos2
+ if
+ (ap1.x <= p2x and ap2.x >= p1x) and
+ (ap1.y <= p2y and ap2.y >= p1y) and
+ (ap1.z <= p2z and ap2.z >= p1z) then
+ -- Found an intersecting area.
+ res[id] = area
+ end
+ end
+ end
+ return res
end
-- Checks if the area is unprotected or owned by you
@@ -43,41 +80,49 @@ end
-- Note that this fails and returns false when the specified area is fully
-- owned by the player, but with multiple protection zones, none of which
-- cover the entire checked area.
--- @param name (optional) player name. If not specified checks for any intersecting areas.
--- @param allow_open Whether open areas should be counted as is they didn't exist.
+-- @param name (optional) Player name. If not specified checks for any intersecting areas.
+-- @param allow_open Whether open areas should be counted as if they didn't exist.
-- @return Boolean indicating whether the player can interact in that area.
--- @return Un-owned intersecting area id, if found.
+-- @return Un-owned intersecting area ID, if found.
function areas:canInteractInArea(pos1, pos2, name, allow_open)
if name and minetest.check_player_privs(name, self.adminPrivs) then
return true
end
- areas:sortPos(pos1, pos2)
- -- First check for a fully enclosing owned area.
- if name then
- for id, area in pairs(self.areas) do
- -- A little optimization: isAreaOwner isn't necessary
- -- here since we're iterating through all areas.
- if area.owner == name and
- self:isSubarea(pos1, pos2, id) then
- return true
- end
+ self:sortPos(pos1, pos2)
+
+ -- Intersecting non-owned area ID, if found.
+ local blocking_area = nil
+
+ local areas = self:getAreasIntersectingArea(pos1, pos2)
+ for id, area in pairs(areas) do
+ -- First check for a fully enclosing owned area.
+ -- A little optimization: isAreaOwner isn't necessary
+ -- here since we're iterating over all relevant areas.
+ if area.owner == name and
+ self:isSubarea(pos1, pos2, id) then
+ return true
end
- end
- -- Then check for intersecting (non-owned) areas.
- for id, area in pairs(self.areas) do
- local p1, p2 = area.pos1, area.pos2
- if (p1.x <= pos2.x and p2.x >= pos1.x) and
- (p1.y <= pos2.y and p2.y >= pos1.y) and
- (p1.z <= pos2.z and p2.z >= pos1.z) then
- -- Found an intersecting area.
- -- Return if the area is closed or open areas aren't
- -- allowed, and the area isn't owned.
- if (not allow_open or not area.open) and
- (not name or not areas:isAreaOwner(id, name)) then
- return false, id
- end
+
+ -- Then check for intersecting non-owned (blocking) areas.
+ -- We don't bother with this check if we've already found a
+ -- blocking area, as the check is somewhat expensive.
+ -- The area blocks if the area is closed or open areas aren't
+ -- acceptable to the caller, and the area isn't owned.
+ -- Note: We can't return directly here, because there might be
+ -- an exclosing owned area that we haven't gotten to yet.
+ if not blocking_area and
+ (not allow_open or not area.open) and
+ (not name or not self:isAreaOwner(id, name)) then
+ blocking_area = id
end
end
+
+ if blocking_area then
+ return false, blocking_area
+ end
+
+ -- There are no intersecting areas or they are only partially
+ -- intersecting areas and they are all owned by the player.
return true
end