Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make smallest area concept optional #80

Merged
merged 12 commits into from
Oct 1, 2024
55 changes: 31 additions & 24 deletions api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
return true
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
end
else
for _, fname in ipairs(area.faction_open or {}) do
if factions.player_is_in_faction(fname, name) then
return true
else
for _, fname in ipairs(area.faction_open) do
if factions.player_is_in_faction(fname, name) then
return true
end
end
end
end
owned = true
end
return false
return not owned
end

-- Returns a table (list) of all players that own an area
Expand Down
14 changes: 14 additions & 0 deletions settingtypes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading