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

Allow custom checks before allowing a player to protect new areas #74

Merged
merged 4 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions api.lua
@@ -1,9 +1,22 @@
local hudHandlers = {}

areas.registered_protection_conditions = {}
areas.registered_on_adds = {}
areas.registered_on_removes = {}
areas.registered_on_moves = {}

areas.callback_origins = {}

function areas:registerProtectionCondition(func)
table.insert(areas.registered_protection_conditions, func)
local debug_info = debug.getinfo(func, "S")
areas.callback_origins[func] = {
mod = core.get_current_modname() or "??",
source = debug_info.short_src or "??",
line = debug_info.linedefined or "??"
}
end

function areas:registerOnAdd(func)
table.insert(areas.registered_on_adds, func)
end
Expand Down
16 changes: 16 additions & 0 deletions api.md
Expand Up @@ -5,11 +5,27 @@ API list
---

* `areas:registerHudHandler(handler)` - Registers a handler to add items to the Areas HUD. See [HUD](#hud).
* `areas:registerProtectionCondition(func(pos1, pos2, name))` -
See [Protection Conditions](#Protection-Conditions)
* `areas:registerOnAdd(func(id, area))`
* `areas:registerOnRemove(func(id))`
* `areas:registerOnMove(func(id, area, pos1, pos2))`


Protection Conditions
---

With `areas:registerProtectionCondition(func(pos1, pos2, name))`
you can register rules to control whether to allow or prohibit the creation of an area.

Return values:
* `true` Forcefully allows the area creation. This overwrites the outcome of any
previously executed conditions, including the default ones registered by this mod.
* `false, errMsg` Disable the creation of the area and return an error message.
* `nil` (or no return value) Enable the creation of the area,
unless specified otherwise by the other registered callbacks.


HUD
---

Expand Down
70 changes: 50 additions & 20 deletions internal.lua
Expand Up @@ -206,60 +206,90 @@ function areas:getChildren(id)
return children
end

-- Checks if the user has sufficient privileges.
-- If the player is not a administrator it also checks
-- if the area intersects other areas that they do not own.
-- Also checks the size of the area and if the user already
-- has more than max_areas.
-- checks all possible restrictions registered with
-- areas:registerProtectionCondition
-- builtin callbacks below
function areas:canPlayerAddArea(pos1, pos2, name)
local allowed = true
local errMsg
for i=1, #areas.registered_protection_conditions do
local res, msg = areas.registered_protection_conditions[i](pos1, pos2, name)
if res == true then
-- always allow to protect, no matter of other conditions
return true
elseif res == false then
-- there might be another callback that returns true, so we can't break here
allowed = false
-- save the first error that occurred
errMsg = errMsg or msg
elseif res ~= nil then
local origin = areas.callback_origins[areas.registered_protection_conditions[i]]
error("\n[Mod] areas: Invalid api usage from mod '" ..
origin.mod .. "' in callback registerProtectionCondition() at " ..
origin.source .. ":" .. origin.line)
end
a-tour-ist marked this conversation as resolved.
Show resolved Hide resolved
end

return allowed, errMsg
end

-- Checks if the user has sufficient privileges.
areas:registerProtectionCondition(function(pos1, pos2, name)
local privs = minetest.get_player_privs(name)
if privs.areas then
-- always allow administrators to create areas
return true
end

-- Check self protection privilege, if it is enabled,
-- and if the area is too big.
if not self.config.self_protection or
-- Check self protection privilege
if not areas.config.self_protection or
not privs[areas.config.self_protection_privilege] then
return false, S("Self protection is disabled or you do not have"
.." the necessary privilege.")
end
end)

-- check if the area is too big
areas:registerProtectionCondition(function(pos1, pos2, name)
local privs = minetest.get_player_privs(name)
local max_size = privs.areas_high_limit and
self.config.self_protection_max_size_high or
self.config.self_protection_max_size
areas.config.self_protection_max_size_high or
areas.config.self_protection_max_size
if
(pos2.x - pos1.x + 1) > max_size.x or
(pos2.y - pos1.y + 1) > max_size.y or
(pos2.z - pos1.z + 1) > max_size.z then
return false, S("Area is too big.")
end
end)

-- Check number of areas the user has and make sure it not above the max
-- Check number of areas the user has and make sure it not above the max
areas:registerProtectionCondition(function(pos1, pos2, name)
local privs = minetest.get_player_privs(name)
local count = 0
for _, area in pairs(self.areas) do
for _, area in pairs(areas.areas) do
if area.owner == name then
count = count + 1
end
end
local max_areas = privs.areas_high_limit and
self.config.self_protection_max_areas_high or
self.config.self_protection_max_areas
areas.config.self_protection_max_areas_high or
areas.config.self_protection_max_areas
if count >= max_areas then
return false, S("You have reached the maximum amount of"
.." areas that you are allowed to protect.")
end
end)

-- Check intersecting areas
local can, id = self:canInteractInArea(pos1, pos2, name)
-- checks if the area intersects other areas that the player do not own.
areas:registerProtectionCondition(function(pos1, pos2, name)
local can, id = areas:canInteractInArea(pos1, pos2, name)
if not can then
local area = self.areas[id]
local area = areas.areas[id]
return false, S("The area intersects with @1 [@2] (@3).",
area.name, id, area.owner)
end

return true
end
end)

-- Given a id returns a string in the format:
-- "name [id]: owner (x1, y1, z1) (x2, y2, z2) -> children"
Expand Down