diff --git a/api.lua b/api.lua index d872577..8042785 100644 --- a/api.lua +++ b/api.lua @@ -101,9 +101,9 @@ function areas:getSmallestAreaAtPos(pos) 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) + volume = (area.pos2.x - area.pos1.x + 1) + * (area.pos2.y - area.pos1.y + 1) + * (area.pos2.z - area.pos1.z + 1) if smallest_volume >= volume then smallest_area = area smallest_id = id @@ -114,37 +114,44 @@ function areas:getSmallestAreaAtPos(pos) end -- Checks if the area is unprotected, open, owned by player --- or player is part of faction of smallest area at position. +-- 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 area - or 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 + local areas_list + if areas.config.use_smallest_area_precedence then + local smallest_area, _ = self:getSmallestAreaAtPos(pos) + areas_list = { smallest_area } + else + areas_list = self:getAreasAtPos(pos) + end + local owned = false + for _, area in pairs(areas_list) do + -- Player owns the area or area is open + 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) do + if faction_name == fname then + return true + end + end + end + else + for _, fname in ipairs(area.faction_open) do + if factions.player_is_in_faction(fname, name) 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 - return true - end - end end + owned = true end - return false + return not owned end -- Returns a table (list) of all players that own an area diff --git a/settingtypes.txt b/settingtypes.txt index 9abffa4..1ca0d3f 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -3,6 +3,20 @@ # Static paths do not work well with settings #areas.filename (Configuration file path) string (world_path)/areas.dat +# Use smallest area volume precedence concept. (experimental; may change) +# +# If set to `true`: +# The interaction permission is defined by the smallest area volume that +# contains the interaction position. Granting access to areas is achieved +# by factions instead of using `/add_owner`. +# This allows players to have private areas within a greater open/shared +# area and also define open/shared areas within those private areas. +# If set to `false`: (default) +# Interacting is permitted if the interaction position resides in any of the +# player's own areas, shared or open areas. +# This permission is not impacted by more restrictive, intersecting areas. +areas.use_smallest_area_precedence (Smallest area rules) bool false + # Allow players with a privilege create their own areas using /protect # within the specified size and amount limits. areas.self_protection (Self protection) bool false