From aa14c9d7b66fa0621997de13ea2a9376ffe5ed29 Mon Sep 17 00:00:00 2001 From: Luke aka SwissalpS Date: Tue, 3 Sep 2024 00:06:00 +0200 Subject: [PATCH 1/4] check interact permission on smallest area at position --- api.lua | 51 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/api.lua b/api.lua index 8d6313f..2b4de2f 100644 --- a/api.lua +++ b/api.lua @@ -95,36 +95,49 @@ function areas:getAreasIntersectingArea(pos1, pos2) return res end --- Checks if the area is unprotected or owned by you +-- Checks if the area is unprotected, open, owned by player +-- or player is part of faction of smallest area at position. function areas:canInteract(pos, name) if minetest.check_player_privs(name, self.adminPrivs) then return true end - local owned = false + -- Determine smallest area at position + -- If multiple areas have the same volume, larger id takes precedence. + local smallest_area, smallest_volume, volume for _, area in pairs(self:getAreasAtPos(pos)) do - if area.owner == name or area.open then - return true - elseif areas.factions_available and area.faction_open then - if (factions.version or 0) < 2 then - local faction_name = factions.get_player_faction(name) - if faction_name then - for _, fname in ipairs(area.faction_open or {}) do - if faction_name == fname then - return true - end - end - end - else - for _, fname in ipairs(area.faction_open or {}) do - if factions.player_is_in_faction(fname, name) then + volume = (area.pos2.x - area.pos1.x + 1) + * (area.pos2.y - area.pos1.y + 1) + * (area.pos2.z - area.pos1.z + 1) + if not smallest_volume or smallest_volume >= volume then + smallest_area = area + smallest_volume = volume + end + end + -- No area, player owns it or area is open + if not smallest_area + or smallest_area.owner == name + or smallest_area.open + then + return true + elseif areas.factions_available and smallest_area.faction_open then + if (factions.version or 0) < 2 then + local faction_name = factions.get_player_faction(name) + if faction_name then + for _, fname in ipairs(smallest_area.faction_open or {}) do + if faction_name == fname then return true end end end + else + for _, fname in ipairs(smallest_area.faction_open or {}) do + if factions.player_is_in_faction(fname, name) then + return true + end + end end - owned = true end - return not owned + return false end -- Returns a table (list) of all players that own an area From 1b86480f3d6dbe04432c6faa9a18488651389438 Mon Sep 17 00:00:00 2001 From: Luke aka SwissalpS Date: Tue, 3 Sep 2024 09:53:40 +0200 Subject: [PATCH 2/4] expose getSmallestAreaAtPos() --- api.lua | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/api.lua b/api.lua index 2b4de2f..51cc943 100644 --- a/api.lua +++ b/api.lua @@ -95,15 +95,10 @@ function areas:getAreasIntersectingArea(pos1, pos2) return res end --- Checks if the area is unprotected, open, owned by player --- or player is part of faction of smallest area at position. -function areas:canInteract(pos, name) - if minetest.check_player_privs(name, self.adminPrivs) then - return true - end - -- Determine smallest area at position - -- If multiple areas have the same volume, larger id takes precedence. - local smallest_area, smallest_volume, volume +-- Returns smallest area at position or nil. +-- If multiple areas have the same volume, larger id takes precedence. +function areas:getSmallestAreaAtPos(pos) + local smallest_area, smallest_volume, volume = nil for _, area in pairs(self:getAreasAtPos(pos)) do volume = (area.pos2.x - area.pos1.x + 1) * (area.pos2.y - area.pos1.y + 1) @@ -113,24 +108,34 @@ function areas:canInteract(pos, name) smallest_volume = volume end end + return smallest_area +end + +-- Checks if the area is unprotected, open, owned by player +-- or player is part of faction of smallest area at position. +function areas:canInteract(pos, name) + if minetest.check_player_privs(name, self.adminPrivs) then + return true + end + local area = self:getSmallestAreaAtPos(pos) -- No area, player owns it or area is open - if not smallest_area - or smallest_area.owner == name - or smallest_area.open + if not area + or area.owner == name + or area.open then return true - elseif areas.factions_available and smallest_area.faction_open then + elseif areas.factions_available and area.faction_open then if (factions.version or 0) < 2 then local faction_name = factions.get_player_faction(name) if faction_name then - for _, fname in ipairs(smallest_area.faction_open or {}) do + for _, fname in ipairs(area.faction_open or {}) do if faction_name == fname then return true end end end else - for _, fname in ipairs(smallest_area.faction_open or {}) do + for _, fname in ipairs(area.faction_open or {}) do if factions.player_is_in_faction(fname, name) then return true end From fd6d7e4056ff7ca638cb45eada1ee3466a63b3f2 Mon Sep 17 00:00:00 2001 From: Luke aka SwissalpS Date: Tue, 3 Sep 2024 10:20:14 +0200 Subject: [PATCH 3/4] also return area id --- api.lua | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/api.lua b/api.lua index 51cc943..e96d6f5 100644 --- a/api.lua +++ b/api.lua @@ -95,20 +95,21 @@ function areas:getAreasIntersectingArea(pos1, pos2) return res end --- Returns smallest area at position or nil. +-- Returns smallest area at position and its id or nil. -- If multiple areas have the same volume, larger id takes precedence. function areas:getSmallestAreaAtPos(pos) - local smallest_area, smallest_volume, volume = nil - for _, area in pairs(self:getAreasAtPos(pos)) do + local smallest_area, smallest_id, smallest_volume, volume = nil + for id, area in pairs(self:getAreasAtPos(pos)) do volume = (area.pos2.x - area.pos1.x + 1) * (area.pos2.y - area.pos1.y + 1) * (area.pos2.z - area.pos1.z + 1) if not smallest_volume or smallest_volume >= volume then smallest_area = area + smallest_id = id smallest_volume = volume end end - return smallest_area + return smallest_area, smallest_id end -- Checks if the area is unprotected, open, owned by player From 56763e16f9b262059782935c27adb91bd84a3c99 Mon Sep 17 00:00:00 2001 From: Luke aka SwissalpS Date: Sun, 8 Sep 2024 09:47:40 +0200 Subject: [PATCH 4/4] cleanup as suggested by SmallJoker --- api.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/api.lua b/api.lua index e96d6f5..d872577 100644 --- a/api.lua +++ b/api.lua @@ -98,12 +98,13 @@ end -- Returns smallest area at position and its id or nil. -- If multiple areas have the same volume, larger id takes precedence. function areas:getSmallestAreaAtPos(pos) - local smallest_area, smallest_id, smallest_volume, volume = nil + local smallest_area, smallest_id, volume + local smallest_volume = math.huge for id, area in pairs(self:getAreasAtPos(pos)) do volume = (area.pos2.x - area.pos1.x + 1) * (area.pos2.y - area.pos1.y + 1) * (area.pos2.z - area.pos1.z + 1) - if not smallest_volume or smallest_volume >= volume then + if smallest_volume >= volume then smallest_area = area smallest_id = id smallest_volume = volume