Updated areas, including megabuilder-like privilege

- Added area_high_limits privilege, similar to (buggy) megabuilder
This commit is contained in:
LeMagnesium 2015-03-02 21:20:50 +01:00
parent b4f294fba2
commit 911f49faa4
8 changed files with 226 additions and 121 deletions

View File

@ -1,103 +1,104 @@
Areas mod for Minetest 0.4.8+
=============================
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Configuration
-------------
If you wish to specify configuration options, such as whether players are
allowed to protect their own areas with /protect (Disabled by default), you
should check config.lua and set the appropriate settings in your minetest.conf.
allowed to protect their own areas with the `protect` command (disabled by
default), you should check config.lua and set the appropriate settings in your
server's configuration file (probably `minetest.conf`).
Tutorial
--------
To protect an area you must first set the corner positions of the area.
In order to set the corner positions you run:
1. "/area\_pos set" punch the two border nodes.
2. "/area\_pos set1/2" punch only the first or second border node.
3. "/area\_pos1/2" set position one or two to your current position.
4. "/area\_pos1/2 X Y Z" set position one or two to the specified coordinates.
In order to set the corner positions you can run:
* `/area_pos set` and punch the two corner nodes to set them.
* `/area_pos set1/set2` and punch only the first or second corner node to
set them one at a time.
* `/area_pos1/2` to set one of the positions to your current position.
* `/area_pos1/2 X Y Z` to set one of the positions to the specified
coordinates.
Once you have set the border positions you can protect the area by running:
1. "/set\_owner <OwnerName> <AreaName>"
-- If you are a administrator or moderator with the "areas" privilege.
2. "/protect <AreaName>"
-- If the server administraor has enabled area self-protection.
Once you have set the border positions you can protect the area by running one
of the following commands:
* `/set_owner <OwnerName> <AreaName>` -- If you have the `areas` privilege.
* `/protect <AreaName>` -- If you have the `areas` privilege or the server
administrator has enabled area self-protection.
The area name is used so that you can easily find the area that you want when
using a command like /list\_areas. It is not used for any other purpose.
For example: /set\_owner SomePlayer Diamond city
The area name is used only for informational purposes (so that you know what
an area is for). It is not used for any other purpose.
For example: `/set_owner SomePlayer Mese city`
Now that you own an area you may want to add sub-owners to it. You can do this
with the /add\_owner command. Anyone with an area can use the add\_owner
command on their areas. Before using the add\_owner command you have to select
the corners of the sub-area as you did for set\_owner. If your markers are
still around your original area and you want to grant access to your entire
area you will not have to re-set them. You can also use select\_area to place
the markers at the corners of an existing area.
The add\_owner command expects three arguments:
1. The id of the parent area. (The area that you want it to be a sub-area of)
2. The name of the player that will own the sub-area.
3. The name of the sub-area.
with the `add_owner` command. Anyone with an area can use the `add_owner`
command on their areas. Before using the `add_owner` command you have to
select the corners of the sub-area as you did for `set_owner`. If your markers
are still around your original area and you want to grant access to your
entire area you will not have to re-set them. You can also use `select_area` to
place the markers at the corners of an existing area if you've reset your
markers and want to grant access to a full area.
The `add_owner` command expects three arguments:
1. The ID number of the parent area (the area that you want to add a
sub-area to).
2. The name of the player that will own the sub-area.
3. The name of the sub-area. (can contain spaces)
For example: /add\_owner 123 BobTheBuilder Diamond lighthouse
For example: `/add_owner 123 BobTheBuilder Diamond lighthouse`
Chat commands
-------------
* /protect &lt;AreaName&gt;
Protects an area for yourself. (If self-protection is enabled)
* /set\_owner &lt;OwnerName&gt; &lt;AreaName&gt;
Protects an area. (Requires the "areas" privilege)
Commands
--------
* /add\_owner &lt;ParentID&gt; &lt;OwnerName&gt; &lt;ChildName&gt;
Grants another player control over part (or all) of an area.
* `/protect <AreaName>` -- Protects an area for yourself. (if
self-protection is enabled)
* /rename\_area &lt;ID&gt; &lt;NewName&gt;
Renames an existing area, useful after converting from node_ownership
when all areas are unnamed.
* `/set_owner <OwnerName> <AreaName>` -- Protects an area for a specified
player. (requires the `areas` privilege)
* /list\_areas
Lists all of the areas that you own.
(Or all of them if you have the "areas" privilege)
* `/add_owner <ParentID> <OwnerName> <ChildName>` -- Grants another player
control over part (or all) of an area.
* /find\_areas &lt;Regex&gt;
Finds areas using a Lua regular expresion.
For example:
/find_areas [Cc]astle To find castles.
* `/rename_area <ID> <NewName>` -- Renames an existing area.
* /remove\_area &lt;ID&gt;
Removes an area that you own. Any sub-areas of that area are made sub-areas
of the removed area's parent, if it exists. Otherwise they will have no
parent.
* `/list_areas` -- Lists all of the areas that you own, or all areas if you
have the `areas` privilege.
* /recursive\_remove\_areas &lt;ID&gt;
Removes an area and all sub-areas of it.
* `/find_areas <Regex>` -- Finds areas using a Lua regular expresion.
For example, to find castles:
* /change\_owner &lt;ID&gt; &lt;NewOwner&gt;
Change the owner of an area.
/find_areas [Cc]astle
* /select\_area &lt;ID&gt;
Sets the area positions to those of an existing area.
* `/remove_area <ID>` -- Removes an area that you own. Any sub-areas of that
area are made sub-areas of the removed area's parent, if it exists.
If the removed area has no parent it's sub-areas will have no parent.
* /area\_pos {set,set1,set2,get}
Sets the area positions by punching nodes or shows the current area positions.
* `/recursive_remove_areas <ID>` -- Removes an area and all sub-areas of it.
* /area\_pos1 \[X,Y,Z|X Y Z\]
Sets area position one to your position or the one supplied.
* `/change_owner <ID> <NewOwner>` -- Change the owner of an area.
* /area\_pos2 \[X,Y,Z|X Y Z\]
Sets area position two to your position or the one supplied.
* `/area_info` -- Returns information about area configuration and usage.
* `/area_open <ID>` -- Sets the area open, anyone can interact.
* `/area_openfarming <ID>` -- Sets the area openfarming, anyone can interact only farming mod.
* `/select_area <ID>` -- Sets the area positions to those of an existing
area.
* `/area_pos {set,set1,set2,get}` -- Sets the area positions by punching
nodes or shows the current area positions.
* `/area_pos1 [X,Y,Z|X Y Z]` -- Sets area position one to your position or
the one supplied.
* `/area_pos2 [X,Y,Z|X Y Z]` -- Sets area position two to your position or
the one supplied.
License
-------
Copyright (C) 2013 ShadowNinja
Licensed under the GNU LGPL version 2.1 or higher.
Licensed under the GNU LGPL version 2.1 or later.
See LICENSE.txt and http://www.gnu.org/licenses/lgpl-2.1.txt

View File

@ -1,4 +1,3 @@
---
-- Returns a list of areas that include the provided position
function areas:getAreasAtPos(pos)
@ -72,7 +71,7 @@ function areas:canInteractInArea(pos1, pos2, name, allow_open)
end
end
end
-- Then check for intersecting (non-owned) areas
-- 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

View File

@ -2,7 +2,7 @@
minetest.register_chatcommand("protect", {
params = "<AreaName>",
description = "Protect your own area",
privs = {[areas.self_protection_privilege]=true},
privs = {[areas.config.self_protection_privilege]=true},
func = function(name, param)
if param == "" then
return false, "Invalid usage, see /help protect."
@ -157,8 +157,8 @@ minetest.register_chatcommand("find_areas", {
return false, "Invalid regular expression."
end
local matches = {}
for id, area in pairs(areas.areas) do
local matches = {}
for id, area in pairs(areas.areas) do
local str = areas:toString(id)
if str:find(param) then
table.insert(matches, str)
@ -334,3 +334,93 @@ minetest.register_chatcommand("move_area", {
return true, "Area successfully moved."
end,
})
minetest.register_chatcommand("area_info", {
description = "Get information about area configuration and usage.",
func = function(name, param)
local lines = {}
local privs = minetest.get_player_privs(name)
-- Short (and fast to access) names
local cfg = areas.config
local self_prot = cfg.self_protection
local prot_priv = cfg.self_protection_privilege
local limit = cfg.self_protection_max_areas
local limit_high = cfg.self_protection_max_areas_high
local size_limit = cfg.self_protection_max_size
local size_limit_high = cfg.self_protection_max_size_high
local has_high_limit = privs.areas_high_limit
local has_prot_priv = not prot_priv or privs[prot_priv]
local can_prot = privs.areas or (self_prot and has_prot_priv)
local max_count = can_prot and
(has_high_limit and limit_high or limit) or 0
local max_size = has_high_limit and
size_limit_high or size_limit
-- Privilege information
local self_prot_line = ("Self protection is %sabled"):format(
self_prot and "en" or "dis")
if self_prot and prot_priv then
self_prot_line = self_prot_line..
(" %s have the neccessary privilege (%q).")
:format(
has_prot_priv and "and you" or
"but you don't",
prot_priv)
else
self_prot_line = self_prot_line.."."
end
table.insert(lines, self_prot_line)
if privs.areas then
table.insert(lines, "You are an area"..
" administrator (\"areas\" privilege).")
elseif has_high_limit then
table.insert(lines,
"You have extended area protection"..
" limits (\"areas_high_limit\" privilege).")
end
-- Area count
local area_num = 0
for id, area in pairs(areas.areas) do
if area.owner == name then
area_num = area_num + 1
end
end
local count_line = ("You have %d area%s"):format(
area_num, area_num == 1 and "" or "s")
if privs.areas then
count_line = count_line..
" and have no area protection limits."
elseif can_prot then
count_line = count_line..(", out of a maximum of %d.")
:format(max_count)
end
table.insert(lines, count_line)
-- Area size limits
local function size_info(str, size)
table.insert(lines, ("%s spanning up to %dx%dx%d.")
:format(str, size.x, size.y, size.z))
end
local function priv_limit_info(priv, max_count, max_size)
size_info(("Players with the %q privilege"..
" can protect up to %d areas"):format(
priv, max_count), max_size)
end
if self_prot then
if privs.areas then
priv_limit_info(prot_priv,
limit, size_limit)
priv_limit_info("areas_high_limit",
limit_high, size_limit_high)
elseif has_prot_priv then
size_info("You can protect areas", max_size)
end
end
return true, table.concat(lines, "\n")
end,
})

View File

@ -22,7 +22,7 @@ minetest.register_globalstep(function(dtime)
hud = {}
areas.hud[name] = hud
hud.areasId = player:hud_add({
hud_elem_type = "text",
hud_elem_type = "text",
name = "Areas",
number = 0xFFFFFF,
position = {x=0, y=1},

View File

@ -19,11 +19,16 @@ dofile(areas.modpath.."/hud.lua")
areas:load()
minetest.register_privilege("areas", {description = "Can administer areas"})
minetest.register_privilege("areas", {
description = "Can administer areas."
})
minetest.register_privilege("areas_high_limit", {
description = "Can can more, bigger areas."
})
if not minetest.registered_privileges[areas.self_protection_privilege] then
minetest.register_privilege(areas.self_protection_privilege, {
description = "Can protect areas",
if not minetest.registered_privileges[areas.config.self_protection_privilege] then
minetest.register_privilege(areas.config.self_protection_privilege, {
description = "Can protect areas.",
})
end

View File

@ -1,4 +1,3 @@
-- Mega_builder privilege
minetest.register_privilege("megabuilder","Can protect an infinite amount of areas.")
@ -13,7 +12,7 @@ function areas:save()
minetest.log("error", "[areas] Failed to serialize area data!")
return
end
local file, err = io.open(self.filename, "w")
local file, err = io.open(self.config.filename, "w")
if err then
return err
end
@ -23,7 +22,7 @@ end
-- Load the areas table from the save file
function areas:load()
local file, err = io.open(self.filename, "r")
local file, err = io.open(self.config.filename, "r")
if err then
self.areas = self.areas or {}
return err
@ -55,12 +54,12 @@ end
-- Remove a area, and optionally it's children recursively.
-- If a area is deleted non-recursively the children will
-- have the removed area's parent as their new parent.
function areas:remove(id, recurse, secondrun)
function areas:remove(id, recurse)
if recurse then
-- Recursively find child entries and remove them
local cids = self:getChildren(id)
for _, cid in pairs(cids) do
self:remove(cid, true, true)
self:remove(cid, true)
end
else
-- Update parents
@ -112,23 +111,26 @@ end
-- Also checks the size of the area and if the user already
-- has more than max_areas.
function areas:canPlayerAddArea(pos1, pos2, name)
if minetest.check_player_privs(name, self.adminPrivs) then
--return true
local privs = minetest.get_player_privs(name)
if privs.areas then
return true
end
-- Check self protection privilege, if it is enabled,
-- and if the area is too big.
--[[if (not self.self_protection) or
(not minetest.check_player_privs(name,
{[areas.self_protection_privilege]=true})) then
if not self.config.self_protection or
not privs[areas.config.self_protection_privilege] then
return false, "Self protection is disabled or you do not have"
.." the necessary privilege."
end]]--
end
if ((pos2.x - pos1.x) > self.self_protection_max_size.x or
(pos2.y - pos1.y) > self.self_protection_max_size.y or
(pos2.z - pos1.z) > self.self_protection_max_size.z)
and minetest.get_player_privs(name)["megabuilder"] == false then
local max_size = privs.areas_high_limit and
self.config.self_protection_max_size_high or
self.config.self_protection_max_size
if
(pos2.x - pos1.x) > max_size.x or
(pos2.y - pos1.y) > max_size.y or
(pos2.z - pos1.z) > max_size.z then
return false, "Area is too big."
end
@ -139,8 +141,10 @@ function areas:canPlayerAddArea(pos1, pos2, name)
count = count + 1
end
end
if count >= self.self_protection_max_areas
and minetest.get_player_privs(name)["megabuilder"] == false then
local max_areas = privs.areas_high_limit and
self.config.self_protection_max_areas_high or
self.config.self_protection_max_areas
if count >= max_areas and minetest.get_player_privs(name)["megabuilder"] == false then
return false, "You have reached the maximum amount of"
.." areas that you are allowed to protect."
end
@ -149,7 +153,7 @@ function areas:canPlayerAddArea(pos1, pos2, name)
local can, id = self:canInteractInArea(pos1, pos2, name)
if not can then
local area = self.areas[id]
return false, ("The area intersects with %s [%u] owned by %s.")
return false, ("The area intersects with %s [%u] (%s).")
:format(area.name, id, area.owner)
end

View File

@ -110,7 +110,7 @@ GetNodeOwnerName = areas.getNodeOwnerName
HasOwner = areas.hasOwner
-- This is entirely untested and may break in strange and new ways.
if areas.legacy_table then
if areas.config.legacy_table then
owner_defs = setmetatable({}, {
__index = function(table, key)
local a = rawget(areas.areas, key)

View File

@ -1,37 +1,43 @@
local worldpath = minetest.get_worldpath()
local world_path = minetest.get_worldpath()
local function setting_getbool_default(setting, default)
local value = minetest.setting_getbool(setting)
areas.config = {}
local function setting(tp, name, default)
local full_name = "areas."..name
local value
if tp == "boolean" then
value = minetest.setting_getbool(full_name)
elseif tp == "string" then
value = minetest.setting_get(full_name)
elseif tp == "position" then
value = minetest.setting_get_pos(full_name)
elseif tp == "number" then
value = tonumber(minetest.setting_get(full_name))
else
error("Invalid setting type!")
end
if value == nil then
value = default
end
return value
areas.config[name] = value
end
areas.filename =
minetest.setting_get("areas.filename") or worldpath.."/areas.dat"
--------------
-- Settings --
--------------
setting("string", "filename", world_path.."/areas.dat")
-- Allow players with a privilege create their own areas
-- within the max_size and number
areas.self_protection =
setting_getbool_default("areas.self_protection", false)
areas.self_protection_privilege =
minetest.setting_get("areas.self_protection_privilege") or "interact"
areas.self_protection_max_size =
minetest.setting_get_pos("areas.self_protection_max_size") or
{x=50, y=100, z=50}
areas.self_protection_max_areas =
tonumber(minetest.setting_get("areas.self_protection_max_areas")) or 3
-- within the maximum size and number.
setting("boolean", "self_protection", false)
setting("string", "self_protection_privilege", "interact")
setting("position", "self_protection_max_size", {x=64, y=128, z=64})
setting("number", "self_protection_max_areas", 4)
-- For players with the areas_high_limit privilege.
setting("position", "self_protection_max_size_high", {x=512, y=512, z=512})
setting("number", "self_protection_max_areas_high", 32)
-- Register compatability functions for node_ownership.
-- legacy_table (owner_defs) compatibility is untested
-- and can not be used if security_safe_mod_api is on.
areas.legacy_table =
setting_getbool_default("areas.legacy_table", false)
-- Prevent players from punching nodes in a protected area.
-- Usefull for things like delayers, usualy annoying and
-- prevents usage of things like buttons.
areas.protect_punches =
setting_getbool_default("areas.protect_punches", false)
-- legacy_table (owner_defs) compatibility. Untested and has known issues.
setting("boolean", "legacy_table", false)