Merge remote-tracking branch 'upstream/master' into nalc-1.2-dev

This commit is contained in:
Sys Quatre 2020-06-14 23:38:20 +02:00
commit 0b2baacb92
16 changed files with 606 additions and 227 deletions

17
.github/workflows/luacheck.yml vendored Normal file
View File

@ -0,0 +1,17 @@
name: luacheck
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: apt
run: sudo apt-get install -y luarocks
- name: luacheck install
run: luarocks install --local luacheck
- name: luacheck run
run: $HOME/.luarocks/bin/luacheck ./

View File

@ -1,5 +1,4 @@
unused_args = false
allow_defined_top = true
read_globals = {
"DIR_DELIM",
@ -9,11 +8,17 @@ read_globals = {
"VoxelManip", "VoxelArea",
"PseudoRandom", "ItemStack",
"AreaStore",
"intllib",
"default",
"factions",
table = { fields = { "copy", "getn" } }
}
globals = {
"minetest"
"minetest",
-- mod namespace
"areas"
}
files["legacy.lua"] = {
ignore = {"512"}
}

View File

@ -101,6 +101,9 @@ Commands
* `/area_pos2 [X,Y,Z|X Y Z]` -- Sets area position two to your position or
the one supplied.
* `/areas_cleanup` -- Removes all ownerless areas.
Useful for cleaning after user deletion, for example using /remove_player.
License
-------
@ -109,4 +112,3 @@ Copyright (C) 2013 ShadowNinja
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

@ -26,13 +26,11 @@ function areas:registerOnMove(func)
table.insert(areas.registered_on_moves, func)
end
--- Adds a function as a HUD handler, it will be able to add items to the Areas HUD element.
function areas:registerHudHandler(handler)
table.insert(hudHandlers, handler)
end
function areas:getExternalHudEntries(pos)
local areas = {}
for _, func in pairs(hudHandlers) do
@ -145,7 +143,7 @@ end
-- Note that this fails and returns false when the specified area is fully
-- owned by the player, but with multiple protection zones, none of which
-- cover the entire checked area.
-- @param name (optional) Player name. If not specified checks for any intersecting areas.
-- @param name (optional) Player name. If not specified checks for any intersecting areas.
-- @param allow_open Whether open areas should be counted as if they didn't exist.
-- @return Boolean indicating whether the player can interact in that area.
-- @return Un-owned intersecting area ID, if found.

View File

@ -1,15 +1,16 @@
local S = minetest.get_translator("areas")
minetest.register_chatcommand("protect", {
params = "<AreaName>",
description = "Protect your own area",
params = S("<AreaName>"),
description = S("Protect your own area"),
privs = {[areas.config.self_protection_privilege]=true},
func = function(name, param)
if param == "" then
return false, "Invalid usage, see /help protect."
return false, S("Invalid usage, see /help @1.", "protect")
end
local pos1, pos2 = areas:getPos(name)
if not (pos1 and pos2) then
return false, "You need to select an area first."
return false, S("You need to select an area first.")
end
minetest.log("action", "/protect invoked, owner="..name..
@ -19,38 +20,37 @@ minetest.register_chatcommand("protect", {
local canAdd, errMsg = areas:canPlayerAddArea(pos1, pos2, name)
if not canAdd then
return false, "You can't protect that area: "..errMsg
return false, S("You can't protect that area: @1", errMsg)
end
local id = areas:add(name, param, pos1, pos2, nil)
areas:save()
return true, "Area protected. ID: "..id
return true, S("Area protected. ID: @1", id)
end
})
minetest.register_chatcommand("set_owner", {
params = "<PlayerName> <AreaName>",
description = "Protect an area beetween two positions and give"
params = S("<PlayerName>").." "..S("<AreaName>"),
description = S("Protect an area between two positions and give"
.." a player access to it without setting the parent of the"
.." area to any existing area",
.." area to any existing area"),
privs = areas.adminPrivs,
func = function(name, param)
local ownerName, areaName = param:match('^(%S+)%s(.+)$')
if not ownerName then
return false, "Incorrect usage, see /help set_owner."
return false, S("Invalid usage, see /help @1.", "set_owner")
end
local pos1, pos2 = areas:getPos(name)
if not (pos1 and pos2) then
return false, "You need to select an area first."
return false, S("You need to select an area first.")
end
if not areas:player_exists(ownerName) then
return false, "The player \""
..ownerName.."\" does not exist."
return false, S("The player \"@1\" does not exist.", ownerName)
end
minetest.log("action", name.." runs /set_owner. Owner = "..ownerName..
@ -62,34 +62,33 @@ minetest.register_chatcommand("set_owner", {
areas:save()
minetest.chat_send_player(ownerName,
"You have been granted control over area #"..
id..". Type /list_areas to show your areas.")
return true, "Area protected. ID: "..id
S("You have been granted control over area #@1. "..
"Type /list_areas to show your areas.", id))
return true, S("Area protected. ID: @1", id)
end
})
minetest.register_chatcommand("add_owner", {
params = "<ParentID> <Player> <AreaName>",
description = "Give a player access to a sub-area beetween two"
params = S("<ParentID>").." "..S("<PlayerName>").." "..S("<AreaName>"),
description = S("Give a player access to a sub-area beetween two"
.." positions that have already been protected,"
.." Use set_owner if you don't want the parent to be set.",
.." Use set_owner if you don't want the parent to be set."),
func = function(name, param)
local pid, ownerName, areaName
= param:match('^(%d+) ([^ ]+) (.+)$')
local pid, ownerName, areaName = param:match('^(%d+) ([^ ]+) (.+)$')
if not pid then
minetest.chat_send_player(name, "Incorrect usage, see /help add_owner")
minetest.chat_send_player(name, S("Invalid usage, see /help @1.", "add_owner"))
return
end
local pos1, pos2 = areas:getPos(name)
if not (pos1 and pos2) then
return false, "You need to select an area first."
return false, S("You need to select an area first.")
end
if not areas:player_exists(ownerName) then
return false, "The player \""..ownerName.."\" does not exist."
return false, S("The player \"@1\" does not exist.", ownerName)
end
minetest.log("action", name.." runs /add_owner. Owner = "..ownerName..
@ -101,52 +100,52 @@ minetest.register_chatcommand("add_owner", {
pid = tonumber(pid)
if (not areas:isAreaOwner(pid, name)) or
(not areas:isSubarea(pos1, pos2, pid)) then
return false, "You can't protect that area."
return false, S("You can't protect that area.")
end
local id = areas:add(ownerName, areaName, pos1, pos2, pid)
areas:save()
minetest.chat_send_player(ownerName,
"You have been granted control over area #"..
id..". Type /list_areas to show your areas.")
return true, "Area protected. ID: "..id
S("You have been granted control over area #@1. "..
"Type /list_areas to show your areas.", id))
return true, S("Area protected. ID: @1", id)
end
})
minetest.register_chatcommand("rename_area", {
params = "<ID> <newName>",
description = "Rename a area that you own",
params = S("<ID>").." "..S("<newName>"),
description = S("Rename an area that you own"),
func = function(name, param)
local id, newName = param:match("^(%d+)%s(.+)$")
if not id then
return false, "Invalid usage, see /help rename_area."
return false, S("Invalid usage, see /help @1.", "rename_area")
end
id = tonumber(id)
if not id then
return false, "That area doesn't exist."
return false, S("That area doesn't exist.")
end
if not areas:isAreaOwner(id, name) then
return true, "You don't own that area."
return true, S("You don't own that area.")
end
areas.areas[id].name = newName
areas:save()
return true, "Area renamed."
return true, S("Area renamed.")
end
})
minetest.register_chatcommand("find_areas", {
params = "<regexp>",
description = "Find areas using a Lua regular expression",
description = S("Find areas using a Lua regular expression"),
privs = areas.adminPrivs,
func = function(name, param)
if param == "" then
return false, "A regular expression is required."
return false, S("A regular expression is required.")
end
-- Check expression for validity
@ -154,7 +153,7 @@ minetest.register_chatcommand("find_areas", {
("Test [1]: Player (0,0,0) (0,0,0)"):find(param)
end
if not pcall(testRegExp) then
return false, "Invalid regular expression."
return false, S("Invalid regular expression.")
end
local matches = {}
@ -167,14 +166,14 @@ minetest.register_chatcommand("find_areas", {
if #matches > 0 then
return true, table.concat(matches, "\n")
else
return true, "No matches found."
return true, S("No matches found.")
end
end
})
minetest.register_chatcommand("list_areas", {
description = "List your areas, or all areas if you are an admin.",
description = S("List your areas, or all areas if you are an admin."),
func = function(name, param)
local admin = minetest.check_player_privs(name, areas.adminPrivs)
local areaStrings = {}
@ -184,7 +183,7 @@ minetest.register_chatcommand("list_areas", {
end
end
if #areaStrings == 0 then
return true, "No visible areas."
return true, S("No visible areas.")
end
return true, table.concat(areaStrings, "\n")
end
@ -192,96 +191,95 @@ minetest.register_chatcommand("list_areas", {
minetest.register_chatcommand("recursive_remove_areas", {
params = "<id>",
description = "Recursively remove areas using an id",
params = S("<ID>"),
description = S("Recursively remove areas using an ID"),
func = function(name, param)
local id = tonumber(param)
if not id then
return false, "Invalid usage, see"
.." /help recursive_remove_areas"
return false, S("Invalid usage, see"
.." /help @1.", "recursive_remove_areas")
end
if not areas:isAreaOwner(id, name) then
return false, "Area "..id.." does not exist or is"
.." not owned by you."
return false, S("Area @1 does not exist or is"
.." not owned by you.", id)
end
areas:remove(id, true)
areas:save()
return true, "Removed area "..id.." and it's sub areas."
return true, S("Removed area @1 and it's sub areas.", id)
end
})
minetest.register_chatcommand("remove_area", {
params = "<id>",
description = "Remove an area using an id",
params = S("<ID>"),
description = S("Remove an area using an ID"),
func = function(name, param)
local id = tonumber(param)
if not id then
return false, "Invalid usage, see /help remove_area"
return false, S("Invalid usage, see /help @1.", "remove_area")
end
if not areas:isAreaOwner(id, name) then
return false, "Area "..id.." does not exist or"
.." is not owned by you."
return false, S("Area @1 does not exist or"
.." is not owned by you.", id)
end
areas:remove(id)
areas:save()
return true, "Removed area "..id
return true, S("Removed area @1", id)
end
})
minetest.register_chatcommand("change_owner", {
params = "<ID> <NewOwner>",
description = "Change the owner of an area using it's ID",
params = S("<ID>").." "..S("<NewOwner>"),
description = S("Change the owner of an area using its ID"),
func = function(name, param)
local id, newOwner = param:match("^(%d+)%s(%S+)$")
if not id then
return false, "Invalid usage, see"
.." /help change_owner."
return false, S("Invalid usage, see"
.." /help @1.", "change_owner")
end
if not areas:player_exists(newOwner) then
return false, "The player \""..newOwner
.."\" does not exist."
return false, S("The player \"@1\" does not exist.", newOwner)
end
id = tonumber(id)
if not areas:isAreaOwner(id, name) then
return false, "Area "..id.." does not exist"
.." or is not owned by you."
return false, S("Area @1 does not exist"
.." or is not owned by you.", id)
end
areas.areas[id].owner = newOwner
areas:save()
minetest.chat_send_player(newOwner,
("%s has given you control over the area %q (ID %d).")
:format(name, areas.areas[id].name, id))
return true, "Owner changed."
S("@1 has given you control over the area \"@2\" (ID @3).",
name, areas.areas[id].name, id))
return true, S("Owner changed.")
end
})
minetest.register_chatcommand("area_open", {
params = "<ID>",
description = "Toggle an area open (anyone can interact) or closed",
params = S("<ID>"),
description = S("Toggle an area open (anyone can interact) or closed"),
func = function(name, param)
local id = tonumber(param)
if not id then
return false, "Invalid usage, see /help area_open."
return false, S("Invalid usage, see /help @1.", "area_open")
end
if not areas:isAreaOwner(id, name) then
return false, "Area "..id.." does not exist"
.." or is not owned by you."
return false, S("Area @1 does not exist"
.." or is not owned by you.", id)
end
local open = not areas.areas[id].open
-- Save false as nil to avoid inflating the DB.
areas.areas[id].open = open or nil
areas:save()
return true, ("Area %s."):format(open and "opened" or "closed")
return true, open and S("Area opened.") or S("Area closed.")
end
})
@ -310,58 +308,59 @@ minetest.register_chatcommand(
if areas.factions_available then
minetest.register_chatcommand("area_faction_open", {
params = "<ID>",
description = "Toggle an area open/closed for members in your faction.",
params = S("<ID>"),
description = S("Toggle an area open/closed for members in your faction."),
func = function(name, param)
local id = tonumber(param)
if not id then
return false, "Invalid usage, see /help area_faction_open."
return false, S("Invalid usage, see /help @1.", "area_faction_open")
end
if not areas:isAreaOwner(id, name) then
return false, "Area "..id.." does not exist"
.." or is not owned by you."
return false, S("Area @1 does not exist"
.." or is not owned by you.", id)
end
local open = not areas.areas[id].faction_open
-- Save false as nil to avoid inflating the DB.
areas.areas[id].faction_open = open or nil
areas:save()
return true, ("Area %s for faction members."):format(open and "opened" or "closed")
return true, open and S("Area opened for faction members.")
or S("Area closed for faction members.")
end
})
end
minetest.register_chatcommand("move_area", {
params = "<ID>",
description = "Move (or resize) an area to the current positions.",
params = S("<ID>"),
description = S("Move (or resize) an area to the current positions."),
privs = areas.adminPrivs,
func = function(name, param)
local id = tonumber(param)
if not id then
return false, "Invalid usage, see /help move_area."
return false, S("Invalid usage, see /help @1.", "move_area")
end
local area = areas.areas[id]
if not area then
return false, "Area does not exist."
return false, S("Area does not exist.")
end
local pos1, pos2 = areas:getPos(name)
if not pos1 then
return false, "You need to select an area first."
return false, S("You need to select an area first.")
end
areas:move(id, area, pos1, pos2)
areas:save()
return true, "Area successfully moved."
return true, S("Area successfully moved.")
end,
})
minetest.register_chatcommand("area_info", {
description = "Get information about area configuration and usage.",
description = S("Get information about area configuration and usage."),
func = function(name, param)
local lines = {}
local privs = minetest.get_player_privs(name)
@ -383,26 +382,21 @@ minetest.register_chatcommand("area_info", {
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
-- Self protection information
local self_prot_line = self_prot and S("Self protection is enabled.") or
S("Self protection is disabled.")
table.insert(lines, self_prot_line)
-- Privilege information
local priv_line = has_prot_priv and
S("You have the necessary privilege (\"@1\").", prot_priv) or
S("You don't have the necessary privilege (\"@1\").", prot_priv)
table.insert(lines, priv_line)
if privs.areas then
table.insert(lines, "You are an area"..
" administrator (\"areas\" privilege).")
table.insert(lines, S("You are an area"..
" administrator (\"areas\" privilege)."))
elseif has_high_limit then
table.insert(lines,
"You have extended area protection"..
S("You have extended area protection"..
" limits (\"areas_high_limit\" privilege).")
elseif privs.megabuilder then
table.insert(lines, "You are a megabuilder (\"megabuilder\" privilege).")
@ -415,26 +409,23 @@ minetest.register_chatcommand("area_info", {
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 or privs.megabuilder 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)
table.insert(lines, S("You have @1 areas.", area_num))
-- Area limit
local area_limit_line = (privs.areas or privs.megabuilder) and
S("Limit: no area count limit") or
S("Limit: @1 areas", max_count)
table.insert(lines, area_limit_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))
table.insert(lines, S("@1 spanning up to @2x@3x@4.",
str, size.x, size.y, size.z))
end
local function priv_limit_info(lpriv, lmax_count, lmax_size)
size_info(("Players with the %q privilege"..
" can protect up to %d areas"):format(
lpriv, lmax_count), lmax_size)
size_info(S("Players with the \"@1\" privilege"..
" can protect up to @2 areas", lpriv, lmax_count),
lmax_size)
end
if self_prot then
if privs.areas then
@ -446,10 +437,35 @@ minetest.register_chatcommand("area_info", {
elseif privs.megabuilder then
table.insert(lines, "You can protect areas unlimited in size and number.")
elseif has_prot_priv then
size_info("You can protect areas", max_size)
size_info(S("You can protect areas"), max_size)
end
end
return true, table.concat(lines, "\n")
end,
})
minetest.register_chatcommand("areas_cleanup", {
description = S("Removes all ownerless areas"),
privs = areas.adminPrivs,
func = function()
local total, count = 0, 0
local aareas = areas.areas
for id, _ in pairs(aareas) do
local owner = aareas[id].owner
if not areas:player_exists(owner) then
areas:remove(id)
count = count + 1
end
total = total + 1
end
areas:save()
return true, "Total areas: " .. total .. ", Removed " ..
count .. " areas. New count: " .. (total - count)
end
})

View File

@ -1,10 +1,9 @@
-- This is inspired by the landrush mod by Bremaweb
local S = minetest.get_translator("areas")
areas.hud = {}
areas.hud.refresh = 0
minetest.register_globalstep(function(dtime)
areas.hud.refresh = areas.hud.refresh + dtime
if areas.hud.refresh > areas.config["tick"] then
areas.hud.refresh = 0
@ -26,7 +25,7 @@ minetest.register_globalstep(function(dtime)
area.faction_open = faction_info
table.insert(areaStrings, ("%s [%u] (%s%s%s)")
:format(area.name, id, area.owner,
area.open and ":open" or area.openfarming and ":openfarming" or "",
area.open and S(":open") or area.openfarming and ":openfarming" or "",
faction_info and ":"..faction_info or ""))
end
@ -38,7 +37,7 @@ minetest.register_globalstep(function(dtime)
table.insert(areaStrings, str)
end
local areaString = "Areas:"
local areaString = S("Areas:")
if #areaStrings > 0 then
areaString = areaString.."\n"..
table.concat(areaStrings, "\n")
@ -69,4 +68,3 @@ end)
minetest.register_on_leaveplayer(function(player)
areas.hud[player:get_player_name()] = nil
end)

View File

@ -25,7 +25,7 @@ minetest.register_privilege("areas", {
description = "Can administer areas."
})
minetest.register_privilege("areas_high_limit", {
description = "Can do more bigger areas."
description = "Can protect more, bigger areas."
})
-- Mega_builder privilege -- MFF
minetest.register_privilege("megabuilder", {
@ -42,4 +42,3 @@ if minetest.settings:get_bool("log_mods") then
local diffTime = os.clock() - areas.startTime
minetest.log("action", "areas loaded in "..diffTime.."s.")
end

View File

@ -1,3 +1,4 @@
local S = minetest.get_translator("areas")
local old_is_protected = minetest.is_protected
function minetest.is_protected(pos, name)
@ -11,9 +12,8 @@ minetest.register_on_protection_violation(function(pos, name)
if not areas:canInteract(pos, name) then
local owners = areas:getNodeOwners(pos)
minetest.chat_send_player(name,
("%s is protected by %s."):format(
S("@1 is protected by @2.",
minetest.pos_to_string(pos),
table.concat(owners, ", ")))
end
end)

View File

@ -1,3 +1,5 @@
local S = minetest.get_translator("areas")
function areas:player_exists(name)
return minetest.get_auth_handler().get_auth(name) ~= nil
end
@ -46,7 +48,7 @@ end
function areas:checkAreaStoreId(sid)
if not sid then
minetest.log("error", "AreaStore failed to find an ID for an "
.."area! Falling back to iterative area checking.")
.."area! Falling back to iterative area checking.")
self.store = nil
self.store_ids = nil
end
@ -148,7 +150,6 @@ function areas:move(id, area, pos1, pos2)
area.pos1 = pos1
area.pos2 = pos2
for i=1, #areas.registered_on_moves do
areas.registered_on_moves[i](id, area, pos1, pos2)
end
@ -211,8 +212,8 @@ function areas:canPlayerAddArea(pos1, pos2, name)
-- and if the area is too big.
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."
return false, S("Self protection is disabled or you do not have"
.." the necessary privilege.")
end
-- MFF: megabuilders skip checks on size and number of areas
@ -223,9 +224,9 @@ function areas:canPlayerAddArea(pos1, pos2, name)
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
(pos2.z - pos1.z) > max_size.z then
return false, S("Area is too big.")
end
-- Check number of areas the user has and make sure it not above the max
local count = 0
@ -237,18 +238,17 @@ function areas:canPlayerAddArea(pos1, pos2, name)
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 then
return false, "You have reached the maximum amount of"
.." areas that you are allowed to protect."
end
if count >= max_areas then
return false, S("You have reached the maximum amount of"
.." areas that you are allowed to protect.")
end
-- Check intersecting areas
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] (%s).")
:format(area.name, id, area.owner)
end
-- Check intersecting areas
local can, id = self:canInteractInArea(pos1, pos2, name)
if not can then
local area = self.areas[id]
return false, S("The area intersects with @1 [@2] (@3).",
area.name, id, area.owner)
end
return true
end

View File

@ -1,25 +1,26 @@
-- This file contains functions to convert from
-- the old areas format and other compatability code.
local S = minetest.get_translator("areas")
minetest.register_chatcommand("legacy_load_areas", {
params = "<version>",
description = "Loads, converts, and saves the areas from"
.." a legacy save file.",
params = S("<version>"),
description = S("Loads, converts, and saves the areas from"
.." a legacy save file."),
privs = {areas=true, server=true},
func = function(name, param)
minetest.chat_send_player(name, "Converting areas...")
minetest.chat_send_player(name, S("Converting areas…"))
local version = tonumber(param)
if version == 0 then
local err = areas:node_ownership_load()
if err then
minetest.chat_send_player(name, "Error loading legacy file: "..err)
minetest.chat_send_player(name, S("Error loading legacy file: @1", err))
return
end
else
minetest.chat_send_player(name, "Invalid version number. (0 allowed)")
minetest.chat_send_player(name, S("Invalid version number. (0 allowed)"))
return
end
minetest.chat_send_player(name, "Legacy file loaded.")
minetest.chat_send_player(name, S("Legacy file loaded."))
for k, area in pairs(areas.areas) do
-- New position format
@ -34,15 +35,15 @@ minetest.register_chatcommand("legacy_load_areas", {
areas:sortPos(area.pos1, area.pos2)
-- Add name
area.name = "unnamed"
area.name = S("unnamed")
-- Remove ID
area.id = nil
end
minetest.chat_send_player(name, "Table format updated.")
minetest.chat_send_player(name, S("Table format updated."))
areas:save()
minetest.chat_send_player(name, "Converted areas saved. Done.")
minetest.chat_send_player(name, S("Converted areas saved. Done."))
end
})
@ -105,35 +106,3 @@ function areas.hasOwner(pos)
end
return false
end
IsPlayerNodeOwner = areas.isNodeOwner
GetNodeOwnerName = areas.getNodeOwnerName
HasOwner = areas.hasOwner
-- This is entirely untested and may break in strange and new ways.
if areas.config.legacy_table then
owner_defs = setmetatable({}, {
__index = function(table, key)
local a = rawget(areas.areas, key)
if not a then return a end
local b = {}
for k, v in pairs(a) do b[k] = v end
b.x1, b.y1, b.z1 = b.pos1.x, b.pos1.y, b.pos1.z
b.x2, b.y1, b.z2 = b.pos2.x, b.pos2.y, b.pos2.z
b.pos1, b.pos2 = nil, nil
b.id = key
return b
end,
__newindex = function(table, key, value)
local a = value
a.pos1, a.pos2 = {x=a.x1, y=a.y1, z=a.z1},
{x=a.x2, y=a.y2, z=a.z2}
a.x1, a.y1, a.z1, a.x2, a.y2, a.z2 =
nil, nil, nil, nil, nil, nil
a.name = a.name or "unnamed"
a.id = nil
return rawset(areas.areas, key, a)
end
})
end

125
locale/areas.fr.tr Normal file
View File

@ -0,0 +1,125 @@
# textdomain: areas
### chatcommands.lua ###
<AreaName>=<NomZone>
<NewOwner>=<NouveauPropriétaire>
<ParentID>=<IDZonePrincipale>
<PlayerName>=<NomJoueur>
<newName>=<NouveauNom>
@1 has given you control over the area "@2" (ID @3).=@1 vous a donné le contrôle de la zone "@2" (ID @3).
@1 spanning up to @2x@3x@4.=@1 sétendant jusquà @2x@3x@4.
A regular expression is required.=Une expression régulière est requise.
Area @1 does not exist or is not owned by you.=La zone @1 nexiste pas ou ne vous appartient pas.
Area closed for faction members.=Zone fermée aux membres de la faction.
Area closed.=Zone fermée.
Area does not exist.=La zone nexiste pas.
Area opened for faction members.=Zone ouverte aux membres de la faction.
Area opened.=Zone ouverte.
Area protected. ID: @1=Zone protégée. ID : @1
Area renamed.=Zone renommée.
Area successfully moved.=Zone déplacée avec succès.
Change the owner of an area using its ID=Change le propriétaire dune zone en utilisant son ID.
Find areas using a Lua regular expression=Trouve les zones en utilisant une expression régulière Lua.
Get information about area configuration and usage.=Obtient des informations sur la configuration des zones et lutilisation des zones.
Give a player access to a sub-area beetween two positions that have already been protected, Use set_owner if you don't want the parent to be set.=Donne au joueur accès aux sous-zones entre deux positions qui ont déjà été protégées ; utilisez set_owner si vous ne voulez pas que la zone pricipale soit définie.
Invalid regular expression.=Expression régulière invalide.
Limit: @1 areas=Limite: @1 zones.
Limit: no area count limit=Limite: pas de limite de nombre de zones.
List your areas, or all areas if you are an admin.=Liste vos zones, ou toutes les zones si vous êtes administrateur.
Move (or resize) an area to the current positions.=Déplace (ou redimensionne) une zone aux positions actuelles.
No matches found.=Aucun résultat.
No visible areas.=Pas de zone visible.
Owner changed.=Propriétaire changé.
Players with the "@1" privilege can protect up to @2 areas=Les joueurs avec le privilège "@1" peuvent protéger jusquà @2 zones
Protect an area between two positions and give a player access to it without setting the parent of the area to any existing area=Protège une zone entre deux positions et donne à un joueur accès à cette zone sans définir la zone principale de cette zone ni aucune zone existante.
Protect your own area=Protège votre zone.
Recursively remove areas using an ID=Supprime les zones récursivement en utilisant un ID.
Remove an area using an ID=Supprime une zone en utilisant son ID.
Removed area @1=Zone @1 supprimée.
Removed area @1 and it's sub areas.=Zone @1 et ses sous-zones supprimées.
Rename an area that you own=Renomme une zone qui vous appartient.
Self protection is disabled.=Lautoprotection est désactivée.
Self protection is enabled.=Lautoprotection est activée.
That area doesn't exist.=La zone nexiste pas.
The player "@1" does not exist.=Le joueur "@1" nexiste pas.
Toggle an area open (anyone can interact) or closed=Bascule entre zone ouverte (tout le monde peut intéragir) ou fermée.
Toggle an area open/closed for members in your faction.=Bascule entre zone ouverte/fermée pour les membres de votre faction.
You are an area administrator ("areas" privilege).=Vous êtes un administrateur de zone (privilège "areas").
You can protect areas=Vous pouvez protéger des zones.
You can't protect that area.=Vous ne pouvez pas protéger cette zone.
You can't protect that area: @1=Vous ne pouvez pas protéger cette zone : @1.
You don't have the necessary privilege ("@1").=Vous navez pas le privilège nécessaire ("@1").
You don't own that area.=Vous ne possédez pas cette zone.
You have @1 areas.=Vous avez @1 zones.
You have been granted control over area #@1. Type /list_areas to show your areas.=Vous avez reçu lautorisation de contrôler la zone #@1.
You have extended area protection limits ("areas_high_limit" privilege).=Votre limite de protection de zones est étendue (privilège "areas_high_limit").
You have the necessary privilege ("@1").=Vous avez le privilège nécessaire ("@1").
You need to select an area first.=Vous devez sélectionner une zone dabord.
### chatcommands.lua ###
### pos.lua ###
<ID>=<ID>
Invalid usage, see /help @1.=Utilisation incorrecte, voir /help @1.
### hud.lua ###
:open= : ouverte
Areas:=Zones :
### interact.lua ###
@1 is protected by @2.=@1 est protégée par @2.
### internal.lua ###
Area is too big.=La zone est trop grande.
Self protection is disabled or you do not have the necessary privilege.=Lautoprotection est désactivée ou vous navez pas le privilège nécessaire.
The area intersects with @1 [@2] (@3).=La zone a une intersection avec @1 [@2] (@3).
You have reached the maximum amount of areas that you are allowed to protect.=Vous avez atteint le nombre maximum de zones que vous êtes autorisé à protéger.
### legacy.lua ###
<version>=<version>
Converted areas saved. Done.=Zones converties sauvegardées. Fait.
Converting areas…=Conversion des zones…
Error loading legacy file: @1=Erreur lors du chargement du fichier : @1
Invalid version number. (0 allowed)=Numéro de version invalide. (0 autorisé)
Legacy file loaded.=Fichier obsolète chargé.
Loads, converts, and saves the areas from a legacy save file.=Charge, fait la conversion et sauvegarde les zones depuis un fichier de sauvegarde obsolète.
Table format updated.=Format de tableau mis à jour.
unnamed=Non nommé
### pos.lua ###
<not set>=<no définie>
Area @1 selected.=Zone @1 sélectionnée.
Area position @1 set to @2=Position @1 de la zone définie à @2.
Position @1 set to @2=Position @1 définie à @2.
Position @1: =Position @1 :
Select an area by ID.=Sélectionnez une zone par son ID.
Select position @1 by punching a node.=Sélectionnez une position en frappant un bloc.
Select positions by punching two nodes.=Sélectionnez une position en frappant deux blocs.
Set area protection region position @1 to your location or the one specified=Définit la position @1 de la région de protection de zone à votre position ou à celle spécifiée.
Set area protection region, position 1, or position 2 by punching nodes, or display the region=Définit la région de protection de zone, la position 1, ou la position 2 en frappant des blocs, ou en affichant la région.
The area @1 does not exist.=La zone @1 nexiste pas.
Unable to get position.=Impossible dobtenir la position.
Unknown subcommand: @1=Sous-commande inconnue : @1

125
locale/areas.it.tr Normal file
View File

@ -0,0 +1,125 @@
# textdomain: areas
### chatcommands.lua ###
<AreaName>=<NomeArea>
<NewOwner>=<NuovoProprietario>
<ParentID>=<IDparent>
<PlayerName>=<NomeGiocatore>
<newName>=<nuovoNome>
@1 has given you control over the area "@2" (ID @3).=@1 ti ha dato il controllo sull'area "@2" (ID @3).
@1 spanning up to @2x@3x@4.=@1 si estende fino a @2x@3@4.
A regular expression is required.=È necessaria una espressione regolare.
Area @1 does not exist or is not owned by you.=L'area @1 non esiste o non è di tua proprietà.
Area closed for faction members.=Area chiusa per i membri della fazione.
Area closed.=Area chiusa.
Area does not exist.=L'area non esiste.
Area opened for faction members.=Area aperta per i membri della fazione.
Area opened.=Area aperta.
Area protected. ID: @1=Area protetta. ID: @1
Area renamed.=Area rinominata.
Area successfully moved.=Area spostata con successo.
Change the owner of an area using its ID=Cambia il proprietario di un'area usando il suo ID
Find areas using a Lua regular expression=Trova aree usando una espressione regolare Lua
Get information about area configuration and usage.=Ottieni informazioni sulla configurazione e l'uso delle aree.
Give a player access to a sub-area beetween two positions that have already been protected, Use set_owner if you don't want the parent to be set.=Dai a un giocatore l'accesso a una sotto-area tra due posizioni che sono già state protette, usa set_owner se non vuoi che sia impostato il parent.
Invalid regular expression.=Espressione regolare non valida.
Limit: @1 areas=Limite: @1 aree
Limit: no area count limit=Limite: nessun limite al numero delle aree
List your areas, or all areas if you are an admin.=Elenca le tue aree, o tutte le aree se sei un amministratore.
Move (or resize) an area to the current positions.=Sposta (o ridimensiona) un'area alle posizioni attuali.
No matches found.=Nessuna corrispondenza trovata.
No visible areas.=Nessuna area visibile.
Owner changed.=Proprietario cambiato.
Players with the "@1" privilege can protect up to @2 areas=I giocatori col privilegio "@1" possono proteggere fino a @2 aree
Protect an area between two positions and give a player access to it without setting the parent of the area to any existing area=Proteggi un'area tra due posizioni e danne l'accesso a un giocatore senza impostare il parent dell'area a qualsiasi area esistente
Protect your own area=Proteggi la tua area
Recursively remove areas using an ID=Elimina ricorsivamente delle aree usando un ID
Remove an area using an ID=Elimina un'area usando un ID
Removed area @1=Eliminata l'area @1
Removed area @1 and it's sub areas.=Eliminata l'area @1 e le sue sotto-aree.
Rename an area that you own=Rinomina un'area che ti appartiene
Self protection is disabled.=L'auto-protezione è disattivata.
Self protection is enabled.=L'auto-protezione è attivata.
That area doesn't exist.=Quell'area non esiste.
The player "@1" does not exist.=Il giocatore "@1" non esiste.
Toggle an area open (anyone can interact) or closed=Apri o chiudi un'area (chiunque può interagirvi)
Toggle an area open/closed for members in your faction.=Apri o chiudi un'area per i membri della tua fazione.
You are an area administrator ("areas" privilege).=Sei un amministratore di aree (privilegio "areas")
You can protect areas=Puoi proteggere aree
You can't protect that area.=Non puoi proteggere quell'area.
You can't protect that area: @1=Non puoi proteggere quell'area: @1
You don't have the necessary privilege ("@1").=Non hai il privilegio necessario ("@1")
You don't own that area.=Non possiedi quell'area.
You have @1 areas.=Hai @1 aree.
You have been granted control over area #@1. Type /list_areas to show your areas.=Ti è stato concesso il controllo sull'area #@1. Digita /list_areas per mostrare le tue aree.
You have extended area protection limits ("areas_high_limit" privilege).=Hai limiti di protezione aree estesi (privilegio "areas_high_limit")
You have the necessary privilege ("@1").=Hai il privilegio necessario ("@1")
You need to select an area first.=Prima devi selezionare un'area.
### chatcommands.lua ###
### pos.lua ###
<ID>=<ID>
Invalid usage, see /help @1.=Utilizzo non valido, si veda /help @1.
### hud.lua ###
:open=:aperta
Areas:=Aree:
### interact.lua ###
@1 is protected by @2.=@1 è protetta da @2.
### internal.lua ###
Area is too big.=L'area è troppo grande.
Self protection is disabled or you do not have the necessary privilege.=L'auto-protezione è disattivata o non possiedi il privilegio necessario.
The area intersects with @1 [@2] (@3).=L'area interseca con @1 [@2] (@3).
You have reached the maximum amount of areas that you are allowed to protect.=Hai raggiunto il numero massimo di aree che ti è consentito proteggere.
### legacy.lua ###
<version>=<versione>
Converted areas saved. Done.=Aree convertite salvate. Fatto.
Converting areas…=Conversione delle aree...
Error loading legacy file: @1=Errore nel caricamento del file precedente: @1
Invalid version number. (0 allowed)=Numero di versione non valido. (0 permesso)
Legacy file loaded.=File precedente caricato.
Loads, converts, and saves the areas from a legacy save file.=Carica, converte e salva le aree da un file di salvataggio precedente.
Table format updated.=Aggiornato il formato della tabella.
unnamed=innominato
### pos.lua ###
<not set>=<non impostato>
Area @1 selected.=Area @1 selezionata.
Area position @1 set to @2=Posizione @1 dell'area impostata a @2
Position @1 set to @2=Posizione @1 impostata a @2
Position @1: =Posizione @1:
Select an area by ID.=Scegli un'area tramite l'ID.
Select position @1 by punching a node.=Seleziona la posizione @1 colpendo un nodo.
Select positions by punching two nodes.=Seleziona le posizioni colpendo due nodi.
Set area protection region position @1 to your location or the one specified=Imposta la protezione area della posizione @1 della regione alla tua posizione o quella specificata
Set area protection region, position 1, or position 2 by punching nodes, or display the region=Imposta la protezione area della regione, posizione 1, o posizione 2, colpendo due nodi, o mostra la regione
The area @1 does not exist.=L'area @1 non esiste.
Unable to get position.=Impossibile ottenere la posizione.
Unknown subcommand: @1=Sotto-comando sconosciuto: @1

127
locale/template.txt Normal file
View File

@ -0,0 +1,127 @@
# textdomain: areas
### chatcommands.lua ###
<AreaName>=
<NewOwner>=
<ParentID>=
<PlayerName>=
<newName>=
@1 has given you control over the area "@2" (ID @3).=
@1 spanning up to @2x@3x@4.=
A regular expression is required.=
Area @1 does not exist or is not owned by you.=
Area closed for faction members.=
Area closed.=
Area does not exist.=
Area opened for faction members.=
Area opened.=
Area protected. ID: @1=
Area renamed.=
Area successfully moved.=
Change the owner of an area using its ID=
Find areas using a Lua regular expression=
Get information about area configuration and usage.=
Give a player access to a sub-area beetween two positions that have already been protected, Use set_owner if you don't want the parent to be set.=
Invalid regular expression.=
Limit: @1 areas=
Limit: no area count limit=
List your areas, or all areas if you are an admin.=
Move (or resize) an area to the current positions.=
No matches found.=
No visible areas.=
Owner changed.=
Players with the "@1" privilege can protect up to @2 areas=
Protect an area between two positions and give a player access to it without setting the parent of the area to any existing area=
Protect your own area=
Recursively remove areas using an ID=
Remove an area using an ID=
Removed area @1=
Removed area @1 and it's sub areas.=
Rename an area that you own=
Self protection is disabled.=
Self protection is enabled.=
That area doesn't exist.=
The player "@1" does not exist.=
Toggle an area open (anyone can interact) or closed=
Toggle an area open/closed for members in your faction.=
You are an area administrator ("areas" privilege).=
You can protect areas=
You can't protect that area.=
You can't protect that area: @1=
You don't have the necessary privilege ("@1").=
You don't own that area.=
You have @1 areas.=
You have been granted control over area #@1. Type /list_areas to show your areas.=
You have extended area protection limits ("areas_high_limit" privilege).=
You have the necessary privilege ("@1").=
You need to select an area first.=
Removes all ownerless areas.=
### chatcommands.lua ###
### pos.lua ###
<ID>=
Invalid usage, see /help @1.=
### hud.lua ###
:open=
Areas:=
### interact.lua ###
@1 is protected by @2.=
### internal.lua ###
Area is too big.=
Self protection is disabled or you do not have the necessary privilege.=
The area intersects with @1 [@2] (@3).=
You have reached the maximum amount of areas that you are allowed to protect.=
### legacy.lua ###
<version>=
Converted areas saved. Done.=
Converting areas…=
Error loading legacy file: @1=
Invalid version number. (0 allowed)=
Legacy file loaded.=
Loads, converts, and saves the areas from a legacy save file.=
Table format updated.=
unnamed=
### pos.lua ###
<not set>=
Area @1 selected.=
Area position @1 set to @2=
Position @1 set to @2=
Position @1: =
Select an area by ID.=
Select position @1 by punching a node.=
Select positions by punching two nodes.=
Set area protection region position @1 to your location or the one specified=
Set area protection region, position 1, or position 2 by punching nodes, or display the region=
The area @1 does not exist.=
Unable to get position.=
Unknown subcommand: @1=

66
pos.lua
View File

@ -1,3 +1,4 @@
local S = minetest.get_translator("areas")
-- I could depend on WorldEdit for this, but you need to have the 'worldedit'
-- permission to use those commands and you don't have
@ -22,27 +23,27 @@ local function posLimit(pos)
end
minetest.register_chatcommand("select_area", {
params = "<ID>",
description = "Select a area by id.",
params = S("<ID>"),
description = S("Select an area by ID."),
func = function(name, param)
local id = tonumber(param)
if not id then
return false, "Invalid usage, see /help select_area."
return false, S("Invalid usage, see /help @1.", "select_area")
end
if not areas.areas[id] then
return false, "The area "..id.." does not exist."
return false, S("The area @1 does not exist.", id)
end
areas:setPos1(name, areas.areas[id].pos1)
areas:setPos2(name, areas.areas[id].pos2)
return true, "Area "..id.." selected."
return true, S("Area @1 selected.", id)
end,
})
minetest.register_chatcommand("area_pos1", {
params = "[X Y Z|X,Y,Z]",
description = "Set area protection region position 1 to your"
.." location or the one specified",
description = S("Set area protection region position @1 to your"
.." location or the one specified", "1"),
privs = {},
func = function(name, param)
local pos
@ -55,22 +56,22 @@ minetest.register_chatcommand("area_pos1", {
if player then
pos = player:get_pos()
else
return false, "Unable to get position."
return false, S("Unable to get position.")
end
else
return false, "Invalid usage, see /help area_pos1."
return false, S("Invalid usage, see /help @1.", "area_pos1")
end
pos = posLimit(vector.round(pos))
areas:setPos1(name, pos)
return true, "Area position 1 set to "
..minetest.pos_to_string(pos)
return true, S("Area position @1 set to @2", "1",
minetest.pos_to_string(pos))
end,
})
minetest.register_chatcommand("area_pos2", {
params = "[X Y Z|X,Y,Z]",
description = "Set area protection region position 2 to your"
.." location or the one specified",
description = S("Set area protection region position @1 to your"
.." location or the one specified", "2"),
func = function(name, param)
local pos
local found, _, x, y, z = param:find(
@ -82,48 +83,48 @@ minetest.register_chatcommand("area_pos2", {
if player then
pos = player:get_pos()
else
return false, "Unable to get position."
return false, S("Unable to get position.")
end
else
return false, "Invalid usage, see /help area_pos2."
return false, S("Invalid usage, see /help @1.", "area_pos2")
end
pos = posLimit(vector.round(pos))
areas:setPos2(name, pos)
return true, "Area position 2 set to "
..minetest.pos_to_string(pos)
return true, S("Area position @1 set to @2", "2",
minetest.pos_to_string(pos))
end,
})
minetest.register_chatcommand("area_pos", {
params = "set/set1/set2/get",
description = "Set area protection region, position 1, or position 2"
.." by punching nodes, or display the region",
description = S("Set area protection region, position 1, or position 2"
.." by punching nodes, or display the region"),
func = function(name, param)
if param == "set" then -- Set both area positions
areas.set_pos[name] = "pos1"
return true, "Select positions by punching two nodes."
return true, S("Select positions by punching two nodes.")
elseif param == "set1" then -- Set area position 1
areas.set_pos[name] = "pos1only"
return true, "Select position 1 by punching a node."
return true, S("Select position @1 by punching a node.", "1")
elseif param == "set2" then -- Set area position 2
areas.set_pos[name] = "pos2"
return true, "Select position 2 by punching a node."
return true, S("Select position @1 by punching a node.", "2")
elseif param == "get" then -- Display current area positions
local pos1str, pos2str = "Position 1: ", "Position 2: "
local pos1str, pos2str = S("Position @1: ", "1"), S("Position @1: ", "2")
if areas.pos1[name] then
pos1str = pos1str..minetest.pos_to_string(areas.pos1[name])
else
pos1str = pos1str.."<not set>"
pos1str = pos1str..S("<not set>")
end
if areas.pos2[name] then
pos2str = pos2str..minetest.pos_to_string(areas.pos2[name])
else
pos2str = pos2str.."<not set>"
pos2str = pos2str..S("<not set>")
end
return true, pos1str.."\n"..pos2str
else
return false, "Unknown subcommand: "..param
return false, S("Unknown subcommand: @1", param)
end
end,
})
@ -159,22 +160,22 @@ minetest.register_on_punchnode(function(pos, node, puncher)
areas.markPos1(name)
areas.set_pos[name] = "pos2"
minetest.chat_send_player(name,
"Position 1 set to "
..minetest.pos_to_string(pos))
S("Position @1 set to @2", "1",
minetest.pos_to_string(pos)))
elseif areas.set_pos[name] == "pos1only" then
areas.pos1[name] = pos
areas.markPos1(name)
areas.set_pos[name] = nil
minetest.chat_send_player(name,
"Position 1 set to "
..minetest.pos_to_string(pos))
S("Position @1 set to @2", "1",
minetest.pos_to_string(pos)))
elseif areas.set_pos[name] == "pos2" then
areas.pos2[name] = pos
areas.markPos2(name)
areas.set_pos[name] = nil
minetest.chat_send_player(name,
"Position 2 set to "
..minetest.pos_to_string(pos))
S("Position @1 set to @2", "2",
minetest.pos_to_string(pos)))
end
end
end)
@ -262,4 +263,3 @@ minetest.register_entity("areas:pos2", {
areas.marker2[name] = nil
end,
})

View File

@ -43,4 +43,3 @@ file:close()
--------------
setting("filename", "string", world_path.."/areas.dat")

View File

@ -35,4 +35,3 @@ areas.self_protection_max_size_high (Maximal area size) v3f (512, 512, 512)
# Only enter positive whole numbers for the coordinate values or you'll mess up stuff.
# This setting applies for plyaers with the privilege 'areas_high_limit'
areas.self_protection_max_areas_high (Maximal area count) float 32