diff --git a/.github/workflows/luacheck.yml b/.github/workflows/luacheck.yml new file mode 100644 index 0000000..4077f41 --- /dev/null +++ b/.github/workflows/luacheck.yml @@ -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 ./ diff --git a/.luacheckrc b/.luacheckrc index c0ea991..c47f79b 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -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"} } diff --git a/README.md b/README.md index 5db5bad..e665e52 100644 --- a/README.md +++ b/README.md @@ -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 - diff --git a/api.lua b/api.lua index 3df4eb2..3a6158f 100644 --- a/api.lua +++ b/api.lua @@ -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. diff --git a/chatcommands.lua b/chatcommands.lua index c98b499..6af4df2 100644 --- a/chatcommands.lua +++ b/chatcommands.lua @@ -1,15 +1,16 @@ +local S = minetest.get_translator("areas") minetest.register_chatcommand("protect", { - params = "", - description = "Protect your own area", + params = S(""), + 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 = " ", - description = "Protect an area beetween two positions and give" + params = S("").." "..S(""), + 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 = " ", - description = "Give a player access to a sub-area beetween two" + params = S("").." "..S("").." "..S(""), + 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 = " ", - description = "Rename a area that you own", + params = S("").." "..S(""), + 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 = "", - 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 = "", - description = "Recursively remove areas using an id", + params = S(""), + 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 = "", - description = "Remove an area using an id", + params = S(""), + 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 = " ", - description = "Change the owner of an area using it's ID", + params = S("").." "..S(""), + 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 = "", - description = "Toggle an area open (anyone can interact) or closed", + params = S(""), + 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 = "", - description = "Toggle an area open/closed for members in your faction.", + params = S(""), + 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 = "", - description = "Move (or resize) an area to the current positions.", + params = S(""), + 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 +}) diff --git a/hud.lua b/hud.lua index 3c16a4f..79ef907 100644 --- a/hud.lua +++ b/hud.lua @@ -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) - diff --git a/init.lua b/init.lua index cd741c7..d94d453 100644 --- a/init.lua +++ b/init.lua @@ -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 - diff --git a/interact.lua b/interact.lua index 2e54800..9cd44e2 100644 --- a/interact.lua +++ b/interact.lua @@ -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) - diff --git a/internal.lua b/internal.lua index 718744c..39a9a00 100644 --- a/internal.lua +++ b/internal.lua @@ -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 diff --git a/legacy.lua b/legacy.lua index 876b88d..2f333fe 100644 --- a/legacy.lua +++ b/legacy.lua @@ -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 = "", - description = "Loads, converts, and saves the areas from" - .." a legacy save file.", + params = S(""), + 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 - diff --git a/locale/areas.fr.tr b/locale/areas.fr.tr new file mode 100644 index 0000000..4ca4c8d --- /dev/null +++ b/locale/areas.fr.tr @@ -0,0 +1,125 @@ +# textdomain: areas + + +### chatcommands.lua ### + += += += += += +@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 n’existe 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 n’existe 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 d’une 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 l’utilisation 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.=L’autoprotection est désactivée. +Self protection is enabled.=L’autoprotection est activée. +That area doesn't exist.=La zone n’existe pas. +The player "@1" does not exist.=Le joueur "@1" n’existe 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 n’avez 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 l’autorisation 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 d’abord. + +### chatcommands.lua ### +### pos.lua ### + += +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.=L’autoprotection est désactivée ou vous n’avez 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 ### + += +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 ### + += +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 n’existe pas. +Unable to get position.=Impossible d’obtenir la position. +Unknown subcommand: @1=Sous-commande inconnue : @1 diff --git a/locale/areas.it.tr b/locale/areas.it.tr new file mode 100644 index 0000000..009697c --- /dev/null +++ b/locale/areas.it.tr @@ -0,0 +1,125 @@ +# textdomain: areas + + +### chatcommands.lua ### + += += += += += +@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 ### + += +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 ### + += +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 ### + += +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 diff --git a/locale/template.txt b/locale/template.txt new file mode 100644 index 0000000..02b9c77 --- /dev/null +++ b/locale/template.txt @@ -0,0 +1,127 @@ +# textdomain: areas + + +### chatcommands.lua ### + += += += += += +@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 ### + += +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 ### + += +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 ### + += +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= diff --git a/pos.lua b/pos.lua index 323d55d..7a9cbd2 100644 --- a/pos.lua +++ b/pos.lua @@ -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 = "", - description = "Select a area by id.", + params = S(""), + 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.."" + pos1str = pos1str..S("") end if areas.pos2[name] then pos2str = pos2str..minetest.pos_to_string(areas.pos2[name]) else - pos2str = pos2str.."" + pos2str = pos2str..S("") 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, }) - diff --git a/settings.lua b/settings.lua index 22af52c..17d290c 100644 --- a/settings.lua +++ b/settings.lua @@ -43,4 +43,3 @@ file:close() -------------- setting("filename", "string", world_path.."/areas.dat") - diff --git a/settingtypes.txt b/settingtypes.txt index 6316523..9abffa4 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -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 -