diff --git a/api.lua b/api.lua index 86541ac..8c181ab 100644 --- a/api.lua +++ b/api.lua @@ -120,9 +120,9 @@ function areas:getSmallestAreaAtPos(pos) local smallest_area, smallest_id, volume local smallest_volume = math.huge for id, area in pairs(self:getAreasAtPos(pos)) do - volume = (area.pos2.x - area.pos1.x + 1) - * (area.pos2.y - area.pos1.y + 1) - * (area.pos2.z - area.pos1.z + 1) + volume = (area.pos2.x - area.pos1.x + 1) + * (area.pos2.y - area.pos1.y + 1) + * (area.pos2.z - area.pos1.z + 1) if smallest_volume >= volume then smallest_area = area smallest_id = id @@ -133,55 +133,60 @@ function areas:getSmallestAreaAtPos(pos) end -- Checks if the area is unprotected, open, owned by player --- or player is part of faction of smallest area at position. +-- or player is part of faction of [smallest] area at position. function areas:canInteract(pos, name) if minetest.check_player_privs(name, self.adminPrivs) then return true end - local area = self:getSmallestAreaAtPos(pos) - -- No area, player owns it or area is open - if not area - or area.owner == name - or area.open - then - return true - elseif area.openfarming then - -- if area is openfarming - local player = minetest.get_player_by_name(name) - local node = minetest.get_node(pos).name - if player and minetest.registered_nodes[node] then - local wstack = player:get_wielded_item():get_name() - if wstack == "" then wstack = "hand" end - - --on_dig - if minetest.get_item_group(node, "plant") == 1 and (wstack == "hand" or minetest.registered_tools[wstack]) then - return true + local areas_list + if areas.config.use_smallest_area_precedence then + local smallest_area, _ = self:getSmallestAreaAtPos(pos) + areas_list = { smallest_area } + else + areas_list = self:getAreasAtPos(pos) + end + local owned = false + for _, area in pairs(areas_list) do + -- Player owns the area or area is open + if area.owner == name or area.open then + return true + elseif area.openfarming then -- If area is openfarming + local player = minetest.get_player_by_name(name) + local node = minetest.get_node(pos).name + if player and minetest.registered_nodes[node] then + local wstack = player:get_wielded_item():get_name() + if wstack == "" then wstack = "hand" end + -- on_dig + if minetest.get_item_group(node, "plant") == 1 + and (wstack == "hand" or minetest.registered_tools[wstack]) then + return true + end + -- on_place + if plants[wstack] ~= nil and plants[wstack] == node then + return true + end end - - --on_place - if plants[wstack] ~= nil and plants[wstack] == node then - return true - end - end - elseif areas.factions_available and area.faction_open then - if (factions.version or 0) < 2 then - local faction_name = factions.get_player_faction(name) - if faction_name then - for _, fname in ipairs(area.faction_open or {}) do - if faction_name == fname then + elseif areas.factions_available and area.faction_open then + if (factions.version or 0) < 2 then + local faction_name = factions.get_player_faction(name) + if faction_name then + for _, fname in ipairs(area.faction_open) do + if faction_name == fname then + return true + end + end + end + else + for _, fname in ipairs(area.faction_open) do + if factions.player_is_in_faction(fname, name) then return true end end end - else - for _, fname in ipairs(area.faction_open or {}) do - if factions.player_is_in_faction(fname, name) then - return true - end - end end + owned = true end - return false + return not owned end -- Returns a table (list) of all players that own an area diff --git a/async.lua b/async.lua new file mode 100644 index 0000000..3e313e7 --- /dev/null +++ b/async.lua @@ -0,0 +1,23 @@ +areas = rawget(_G, "areas") or {} + +local safe_file_write = core.safe_file_write +if safe_file_write == nil then + safe_file_write = function(path, content) + local file, err = io.open(path, "w") + if err then + return err + end + file:write(content) + file:close() + end +end + +-- Save the areas table to a file +function areas._internal_do_save(areas_tb, filename) + local datastr = core.write_json(areas_tb) + if not datastr then + core.log("error", "[areas] Failed to serialize area data!") + return + end + return safe_file_write(filename, datastr) +end diff --git a/init.lua b/init.lua index 8c57eb2..9a30084 100644 --- a/init.lua +++ b/init.lua @@ -7,11 +7,15 @@ areas = {} areas.factions_available = minetest.get_modpath("playerfactions") and true areas.adminPrivs = {areas=true} -areas.startTime = os.clock() +local startTime = os.clock() areas.modpath = minetest.get_modpath("areas") dofile(areas.modpath.."/settings.lua") dofile(areas.modpath.."/api.lua") + +local async_dofile = core.register_async_dofile or dofile +async_dofile(areas.modpath.."/async.lua") + dofile(areas.modpath.."/internal.lua") dofile(areas.modpath.."/chatcommands.lua") dofile(areas.modpath.."/pos.lua") @@ -43,6 +47,6 @@ if not minetest.registered_privileges[areas.config.self_protection_privilege] th end if minetest.settings:get_bool("log_mods") then - local diffTime = os.clock() - areas.startTime + local diffTime = os.clock() - startTime minetest.log("action", "areas loaded in "..diffTime.."s.") end diff --git a/internal.lua b/internal.lua index 79330b5..fb71732 100644 --- a/internal.lua +++ b/internal.lua @@ -4,26 +4,38 @@ function areas:player_exists(name) return minetest.get_auth_handler().get_auth(name) ~= nil end -local safe_file_write = minetest.safe_file_write -if safe_file_write == nil then - function safe_file_write(path, content) - local file, err = io.open(path, "w") - if err then - return err - end - file:write(content) - file:close() - end -end +-- When saving is done in an async thread, the function will not be present in this global namespace. +if not areas._internal_do_save then + local saving_requested = false + local saving_locked = false --- Save the areas table to a file -function areas:save() - local datastr = minetest.write_json(self.areas) - if not datastr then - minetest.log("error", "[areas] Failed to serialize area data!") - return + -- Required cuz we are referring to _G.areas._internal_do_save *inside* + -- async env (it does not exist in the main thread) + local function async_func(...) + return areas._internal_do_save(...) + end + + local function done_callback() + saving_locked = false + if saving_requested == true then + saving_requested = false + return areas:save() + end + end + + function areas:save() + if saving_locked == true then + saving_requested = true + else + saving_locked = true + return core.handle_async(async_func, done_callback, self.areas, self.config.filename) + end + end +else + -- Save the areas table to a file + function areas:save() + return areas._internal_do_save(self.areas, self.config.filename) end - return safe_file_write(self.config.filename, datastr) end -- Load the areas table from the save file @@ -83,19 +95,19 @@ function areas:populateStore() self.store_ids = store_ids end --- Finds the first usable index in a table --- Eg: {[1]=false,[4]=true} -> 2 -local function findFirstUnusedIndex(t) - local i = 0 - repeat i = i + 1 - until t[i] == nil - return i +-- Guarentees returning an unused index in areas.areas +local index_cache = 0 +local function findFirstUnusedIndex() + local t = areas.areas + repeat index_cache = index_cache + 1 + until t[index_cache] == nil + return index_cache end ---- Add a area. +--- Add an area. -- @return The new area's ID. function areas:add(owner, name, pos1, pos2, parent) - local id = findFirstUnusedIndex(self.areas) + local id = findFirstUnusedIndex() self.areas[id] = { name = name, pos1 = pos1, @@ -118,8 +130,8 @@ function areas:add(owner, name, pos1, pos2, parent) return id end ---- Remove a area, and optionally its children recursively. --- If a area is deleted non-recursively the children will +--- Remove an area, and optionally its children recursively. +-- If an area is deleted non-recursively the children will -- have the removed area's parent as their new parent. function areas:remove(id, recurse) if recurse then @@ -136,7 +148,6 @@ function areas:remove(id, recurse) -- The subarea parent will be niled out if the -- removed area does not have a parent self.areas[cid].parent = parent - end end @@ -172,7 +183,7 @@ function areas:move(id, area, pos1, pos2) end end --- Checks if a area between two points is entirely contained by another area. +-- Checks if an area between two points is entirely contained by another area. -- Positions must be sorted. function areas:isSubarea(pos1, pos2, id) local area = self.areas[id] @@ -294,7 +305,7 @@ areas:registerProtectionCondition(function(pos1, pos2, name) end end) --- Given a id returns a string in the format: +-- Given an id returns a string in the format: -- "name [id]: owner (x1, y1, z1) (x2, y2, z2) -> children" function areas:toString(id) local area = self.areas[id] diff --git a/locale/areas.de.tr b/locale/areas.de.tr new file mode 100644 index 0000000..cca7650 --- /dev/null +++ b/locale/areas.de.tr @@ -0,0 +1,137 @@ +# textdomain: areas + + + +### chatcommands.lua ### + += + [faction_name]= [Fraktionsname] += += += += +@1 has given you control over the area "@2" (ID @3).=@1 hat dir die Kontrolle über den Bereich „@2“ (ID @3) gegeben. +@1 spanning up to @2x@3x@4.=@1 erstreckt sich bis zu @2x@3x@4. +A regular expression is required.=Ein regulärer Ausdruck ist erforderlich. +Area @1 does not exist or is not owned by you.=Bereich @1 existiert nicht oder gehört nicht dir. +Area closed for faction members.=Bereich für Fraktionsmitglieder geschlossen. +Area closed.=Bereich geschlossen. +Area does not exist.=Bereich existiert nicht. +Area is open for members of: @1=Bereich ist offen für Mitglieder von: @1 +Area opened.=Bereich geöffnet. +Area protected. ID: @1=Bereich geschützt. ID: @1 +Area renamed.=Bereich umbenannt. +Area successfully moved.=Bereich erfolgreich verschoben. +Change the owner of an area using its ID=Ändere den Besitzer eines Bereichs anhand seiner ID. +Faction doesn't exists=Fraktion existiert nicht. +Find areas using a Lua regular expression=Suche Bereiche mithilfe eines regulären Lua-Ausdrucks. +Get information about area configuration and usage.=Erhalte Informationen zur Bereichskonfiguration und -verwendung. + +Give a player access to a sub-area between two positions that have already been protected, Use set_owner if you don't want the parent to be set.=Gib einem Spieler Zugriff auf einen Unterbereich zwischen zwei Positionen, die bereits geschützt wurden. Benutze set_owner, wenn du nicht willst, dass der übergeordnete Bereich festgelegt wird. + +Invalid regular expression.=Ungültiger regulärer Ausdruck. +Limit: @1 areas=Begrenzung: @1 Bereiche +Limit: no area count limit=Begrenzung: keine Bereichsanzahlbegrenzung +List your areas, or all areas if you are an admin.=Liste deine Bereiche auf, oder alle Bereiche, wenn du ein Administrator bist. +Move (or resize) an area to the current positions.=Beweg (oder skaliere) einen Bereich auf die aktuellen Positionen. +No matches found.=Keine Übereinstimmungen gefunden. +No visible areas.=Keine sichtbaren Bereiche. +Owner changed.=Besitzer geändert. +Players with the "@1" privilege can protect up to @2 areas=Spieler mit dem Privileg „@1“ können bis zu @2 Bereiche schützen + +Protect an area between two positions and give a player access to it without setting the parent of the area to any existing area=Schütze einen Bereich zwischen zwei Positionen und gib einem Spieler Zugriff darauf, ohne den übergeordneten Bereich des Bereichs auf einen vorhandenen Bereich festzulegen + +Protect your own area=Schütze deinen eigenen Bereich +Recursively remove areas using an ID=Entferne Bereiche rekursiv anhand einer ID +Remove an area using an ID=Entferne einen Bereich anhand seiner ID +Removed area @1=Bereich @1 entfernt +Removed area @1 and its sub areas.=Bereich @1 und seine Unterbereiche entfernt. +Removes all ownerless areas=Entfernt alle herrenlosen Bereiche +Rename an area that you own=Benenne einen Bereich um, den du besitzt +Self protection is disabled.=Selbstschutz ist deaktiviert, Spieler können keine Bereiche bestimmen. +Self protection is enabled.=Selbstschutz ist aktiviert, Spieler können selbst Bereiche bestimmen. +That area doesn't exist.=Dieser Bereich existiert nicht. +The player "@1" does not exist.=Der Spieler „@1“ existiert nicht. +Toggle an area open (anyone can interact) or closed=Schalte einen Bereich offen (jeder kann interagieren) oder geschlossen +Toggle an area open/closed for members in your faction.=Schalte einen Bereich offen/geschlossen für Mitglieder deiner Fraktion. +You are an area administrator ("areas" privilege).=Du bist ein Bereichsadministrator (Berechtigung „areas“). +You can protect areas=Du kannst Bereiche schützen. +You can't protect that area.=Du kannst diesen Bereich nicht schützen. +You can't protect that area: @1=Du kannst diesen Bereich nicht schützen: @1 +You don't have the necessary privilege ("@1").=Du hast nicht die erforderliche Berechtigung („@1“). +You don't own that area.=Du besitzt diesen Bereich nicht. +You have @1 areas.=Du hast @1 Bereiche. + +You have been granted control over area #@1. Type /list_areas to show your areas.=Dir wurde die Kontrolle über Bereich #@1 gewährt. Gib /list_areas ein, um deine Bereiche anzuzeigen. + +You have extended area protection limits ("areas_high_limit" privilege).=Du hast erweiterte Bereichsschutzgrenzen (Berechtigung „areas_high_limit“). + +You have the necessary privilege ("@1").=Du hast die erforderliche Berechtigung („@1“). +You need to select an area first.=Du musst zuerst einen Bereich auswählen. + +### chatcommands.lua ### +### pos.lua ### + += +Invalid usage, see /help @1.=Ungültige Verwendung, siehe /help @1. + +### hud.lua ### + +:open=:offen +Areas:=Bereiche: + +### init.lua ### + +Can administer areas.=Kann Bereiche verwalten. +Can protect areas.=Kann Bereiche schützen. +Can protect more, bigger areas.=Kann mehr, grössere Bereiche schützen. + +### interact.lua ### + +@1 is protected by @2.=@1 wird durch @2 geschützt. + +### internal.lua ### + +Area is too big.=Bereich ist zu gross. + +Self protection is disabled or you do not have the necessary privilege.=Selbstschutz ist deaktiviert oder du hast nicht die erforderlichen Berechtigungen. + +The area intersects with @1 [@2] (@3).=Der Bereich überschneidet sich mit @1 [@2] (@3). + +You have reached the maximum amount of areas that you are allowed to protect.=Du hast die maximale Anzahl, der Bereiche, die du schützen darfst erreicht. + + +### legacy.lua ### + += +Converted areas saved. Done.=Konvertierte Bereiche gespeichert. Fertig. +Converting areas…=Bereiche werden konvertiert… +Error loading legacy file: @1=Fehler beim Laden der Vorgänger-Datei: @1 +Invalid version number. (0 allowed)=Ungültige Versionsnummer. (Erlaubt: 0) +Legacy file loaded.=Vorgänger-Datei geladen. + +Loads, converts, and saves the areas from a legacy save file.=Lädt, konvertiert und speichert die Bereiche aus einer Vorgänger-Speicherdatei. + +Table format updated.=Tabellenformat aktualisiert. +unnamed=unbenannt + +### pos.lua ### + += +Area @1 selected.=Bereich @1 ausgewählt. +Area position @1 set to @2=Bereichsposition @1 auf @2 festgelegt +Position @1 set to @2=Position @1 auf @2 festgelegt +Position @1:=Position @1: +Select an area by ID.=Wähle einen Bereich anhand seiner ID. +Select position @1 by punching a node.=Wähle Position @1, durch schlagen eines Knoten. +Select positions by punching two nodes.=Wähle Positionen, durch schlagen zweier Knoten. + +Set area protection region position @1 to your location or the one specified=Setzt die Bereichsschutzregion-Position @1 auf deinen Standort oder den angegebenen. + +Set area protection region, position 1, or position 2 by punching nodes, or display the region=Setzt die Bereichsschutzregion, Position 1 oder Position 2 fest, durch schlagen von Knoten, oder zeigt die Region an. + +The area @1 does not exist.=Der Bereich @1 existiert nicht. +Unable to get position.=Position konnte nicht ermittelt werden. +Unknown subcommand: @1=Unbekannter Unterbefehl: @1 + +Relative coordinates is not supported on this server. Please upgrade Minetest to 5.7.0 or newer versions.=Relative Koordinaten werden auf diesem Server nicht unterstützt. Bitte aktualisiere Minetest auf Version 5.7.0 oder neuer. diff --git a/locale/areas.es.tr b/locale/areas.es.tr new file mode 100644 index 0000000..ef3acaf --- /dev/null +++ b/locale/areas.es.tr @@ -0,0 +1,137 @@ +# textdomain: areas + + + +### chatcommands.lua ### + += + [faction_name]= [nombre_de_facción] += += += += +@1 has given you control over the area "@2" (ID @3).=@1 te ha dado control sobre el área "@2" (ID @3). +@1 spanning up to @2x@3x@4.=@1 abarca hasta @2x@3x@4. +A regular expression is required.=Se requiere una expresión regular. +Area @1 does not exist or is not owned by you.=El área @1 no existe o no es de tu propiedad. +Area closed for faction members.=Área cerrada para miembros de la facción. +Area closed.=Área cerrada. +Area does not exist.=El área no existe. +Area is open for members of: @1=El área está abierta para miembros de: @1 +Area opened.=Área abierta. +Area protected. ID: @1=Área protegida. ID: @1 +Area renamed.=Área renombrada. +Area successfully moved.=Área movida exitosamente. +Change the owner of an area using its ID=Cambia el propietario de un área usando su ID +Faction doesn't exists=La facción no existe +Find areas using a Lua regular expression=Encuentra áreas usando una expresión regular de Lua +Get information about area configuration and usage.=Obtén información sobre la configuración y el uso del área. + +Give a player access to a sub-area between two positions that have already been protected, Use set_owner if you don't want the parent to be set.=Otorgue a un jugador acceso a una área secundaria entre dos posiciones que ya han sido protegidas. Usa set_owner si no deseas que se configure la área principal como padre. + +Invalid regular expression.=Expresión regular no válida. +Limit: @1 areas=Límite: @1 áreas +Limit: no area count limit=Límite: sin límite de recuento de áreas +List your areas, or all areas if you are an admin.=Enumere tus áreas o todas las áreas si eres administrador. +Move (or resize) an area to the current positions.=Mueve (o redimensiona) una área a las posiciones actuales. +No matches found.=No se encontraron coincidencias. +No visible areas.=No hay áreas visibles. +Owner changed.=Se cambió el propietario. +Players with the "@1" privilege can protect up to @2 areas=Los jugadores con el privilegio "@1" pueden proteger hasta @2 áreas + +Protect an area between two positions and give a player access to it without setting the parent of the area to any existing area=Proteje una área entre dos posiciones y otorgue acceso a un jugador sin configurarle una área como padre + +Protect your own area=Proteje tu propia área +Recursively remove areas using an ID=Elimina áreas recursivamente usando una ID +Remove an area using an ID=Elimina una área usando una ID +Removed area @1=Área @1 eliminada +Removed area @1 and its sub areas.=Área @1 y sus subáreas eliminadas. +Removes all ownerless areas=Elimina todas las áreas sin propietario +Rename an area that you own=Cambia el nombre de una áreas que es de tu propiedad +Self protection is disabled.=La protección por sí mismo está deshabilitada. +Self protection is enabled.=La protección por sí mismo está habilitada. +That area doesn't exist.=Esa área no existe. +The player "@1" does not exist.=El jugador "@1" no existe. +Toggle an area open (anyone can interact) or closed=Activa o desactiva la apertura o el cierre de una área para todos los jugadores +Toggle an area open/closed for members in your faction.=Activa o desactiva la apertura o el cierre de una área para los miembros de tu facción. +You are an area administrator ("areas" privilege).=Eres un administrador de área (privilegio "areas"). +You can protect areas=Puedes proteger áreas +You can't protect that area.=No puedes proteger esa área. +You can't protect that area: @1=No puedes proteger esa área: @1 +You don't have the necessary privilege ("@1").=No tienes el privilegio necesario ("@1"). +You don't own that area.=No eres el propietario de esa área. +You have @1 areas.=Te pertenecen @1 áreas. + +You have been granted control over area #@1. Type /list_areas to show your areas.=Se te ha otorgado el control sobre el área #@1. Escribe /list_areas para mostrar tus áreas. + +You have extended area protection limits ("areas_high_limit" privilege).=Tienes límites de protección de área extendidos (privilegio "areas_high_limit"). + +You have the necessary privilege ("@1").=Tienes el privilegio necesario ("@1"). +You need to select an area first.=Primero debes seleccionar una área. + +### chatcommands.lua ### +### pos.lua ### + += +Invalid usage, see /help @1.=Uso no válido, consulta /help @1. + +### hud.lua ### + +:open=:abierta +Areas:=Áreas: + +### init.lua ### + +Can administer areas.=Puede administrar áreas. +Can protect areas.=Puede proteger áreas. +Can protect more, bigger areas.=Puede proteger más áreas, más grandes. + +### interact.lua ### + +@1 is protected by @2.=@1 está protegido por @2. + +### internal.lua ### + +Area is too big.=El área es demasiado grande. + +Self protection is disabled or you do not have the necessary privilege.=La protección por sí mismo está deshabilitada o no tienes el privilegio necesario. + +The area intersects with @1 [@2] (@3).=El área se interseca con @1 [@2] (@3). + +You have reached the maximum amount of areas that you are allowed to protect.=Has alcanzado la cantidad máxima de áreas que tienes permitido proteger. + + +### legacy.lua ### + += +Converted areas saved. Done.=Áreas convertidas guardadas. Listo. +Converting areas…=Convirtiendo áreas… +Error loading legacy file: @1=Error al cargar archivo heredado: @1 +Invalid version number. (0 allowed)=Número de versión no válido. (Solo se permite: 0) +Legacy file loaded.=Archivo heredado cargado. + +Loads, converts, and saves the areas from a legacy save file.=Carga, convierte y guarda las áreas desde un archivo guardado heredado. + +Table format updated.=Formato de tabla actualizado. +unnamed=sin nombre + +### pos.lua ### + += +Area @1 selected.=Área @1 seleccionada. +Area position @1 set to @2=Posición del área @1 establecida en @2 +Position @1 set to @2=Posición @1 establecida en @2 +Position @1:=Posición @1: +Select an area by ID.=Selecciona una área por ID. +Select position @1 by punching a node.=Selecciona la posición @1 golpeando un nodo. +Select positions by punching two nodes.=Selecciona las posiciones golpeando dos nodos. + +Set area protection region position @1 to your location or the one specified=Establece la posición de la región de protección del área @1 en tu ubicación o en la especificada + +Set area protection region, position 1, or position 2 by punching nodes, or display the region=Establece la región de protección del área, la posición 1 o la posición 2 golpeando nodos, o muestre la región + +The area @1 does not exist.=El área @1 no existe. +Unable to get position.=No se puede obtener la posición. +Unknown subcommand: @1=Subcomando desconocido: @1 + +Relative coordinates is not supported on this server. Please upgrade Minetest to 5.7.0 or newer versions.=Las coordenadas relativas no son compatibles con este servidor. Actualiza Minetest a 5.7.0 o versiones más nuevas. diff --git a/locale/areas.fr.tr b/locale/areas.fr.tr index b60726c..61bb187 100644 --- a/locale/areas.fr.tr +++ b/locale/areas.fr.tr @@ -4,16 +4,16 @@ ### chatcommands.lua ### -= += [faction_name]= [nom_de_faction] = = = -= -@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 has given you control over the area "@2" (ID @3).=@1 t'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 @1 does not exist or is not owned by you.=La zone @1 n’existe pas ou ne t'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. @@ -22,58 +22,58 @@ 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. +Change the owner of an area using its ID=Changer le propriétaire d’une zone en utilisant son ID. Faction doesn't exists=La faction n'existe pas -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. +Find areas using a Lua regular expression=Trouver les zones en utilisant une expression régulière Lua. +Get information about area configuration and usage.=Obtenir des informations sur la configuration des zones et l’utilisation des zones. -Give a player access to a sub-area between 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. +Give a player access to a sub-area between 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 tu ne veux pas que le parent 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. +List your areas, or all areas if you are an admin.=Liste tes zones, ou toutes les zones si tu es 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 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 (parent) de cette zone ni aucune zone existante. -Protect your own area=Protège votre zone. +Protect your own area=Protège ta propre 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 its sub areas.=Zone @1 et ses sous-zones supprimées. Removes all ownerless areas=Supprime toutes les zones sans propriétaire -Rename an area that you own=Renomme une zone qui vous appartient. +Rename an area that you own=Renomme une zone que tu possèdes. 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. +Toggle an area open/closed for members in your faction.=Bascule entre zone ouverte/fermée pour les membres de ta faction. +You are an area administrator ("areas" privilege).=Tu es un administrateur de zone (privilège "areas"). +You can protect areas=Tu peux protéger des zones. +You can't protect that area.=Tu ne peux pas protéger cette zone. +You can't protect that area: @1=Tu ne peux pas protéger cette zone : @1. +You don't have the necessary privilege ("@1").=Tu n'as pas le privilège nécessaire ("@1"). +You don't own that area.=Tu n'es pas propriétaire de cette zone. +You have @1 areas.=Tu as @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 been granted control over area #@1. Type /list_areas to show your areas.=Tu as 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 extended area protection limits ("areas_high_limit" privilege).=Tu 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. +You have the necessary privilege ("@1").=Tu as le privilège nécessaire ("@1"). +You need to select an area first.=Tu dois d'abord sélectionner une zone. ### chatcommands.lua ### ### pos.lua ### = -Invalid usage, see /help @1.=Utilisation incorrecte, voir /help @1. +Invalid usage, see /help @1.=Utilisation non valid, voir /help @1. ### hud.lua ### @@ -94,11 +94,11 @@ Can protect more, bigger areas.=Permet de protéger plus, et de plus grandes zon 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. +Self protection is disabled or you do not have the necessary privilege.=L’autoprotection est désactivée ou tu n’as 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. +You have reached the maximum amount of areas that you are allowed to protect.=Tu as atteint le nombre maximum de zones que tu es autorisé à protéger. ### legacy.lua ### @@ -113,7 +113,7 @@ 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é +unnamed=non nommé ### pos.lua ### @@ -121,12 +121,12 @@ unnamed=Non nommé 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 @1 en frappant un bloc. -Select positions by punching two nodes.=Sélectionnez une position en frappant deux blocs. +Position @1:=Position @1 : +Select an area by ID.=Sélectionne une zone par son ID. +Select position @1 by punching a node.=Sélectionne une position @1 en frappant un bloc. +Select positions by punching two nodes.=Sélectionne 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 to your location or the one specified=Définit la position @1 de la région de protection de zone à tu 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. @@ -134,4 +134,4 @@ 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 -Relative coordinates is not supported on this server. Please upgrade Minetest to 5.7.0 or newer versions.= +Relative coordinates is not supported on this server. Please upgrade Minetest to 5.7.0 or newer versions.=Les coordonnées relatives ne sont pas prises en charge sur ce serveur. Mets à niveau Minetest vers la version 5.7.0 ou une version plus récente. diff --git a/locale/areas.it.tr b/locale/areas.it.tr index 7fe77da..fe56c9d 100644 --- a/locale/areas.it.tr +++ b/locale/areas.it.tr @@ -121,7 +121,7 @@ unnamed=innominato 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: +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. diff --git a/locale/areas.ru.tr b/locale/areas.ru.tr index 11e8c74..4865f22 100644 --- a/locale/areas.ru.tr +++ b/locale/areas.ru.tr @@ -121,7 +121,7 @@ unnamed=без_названия Area @1 selected.=Территория @1 выбрана. Area position @1 set to @2=Позиция @1 установлена в @2 Position @1 set to @2=Позиция @1 установлена в @2 -Position @1: =Позиция @1: +Position @1:=Позиция @1: Select an area by ID.=Выбрать территорию по её ID. Select position @1 by punching a node.=Установите позицию @1, ударив по блоку. Select positions by punching two nodes.=Установите позиции, ударив по двум блокам. diff --git a/locale/areas.zh_CN.tr b/locale/areas.zh_CN.tr index 2ac2be1..22c0ac7 100644 --- a/locale/areas.zh_CN.tr +++ b/locale/areas.zh_CN.tr @@ -121,7 +121,7 @@ unnamed=未命名 Area @1 selected.=保护区 @1 已选择。 Area position @1 set to @2=保护区座标 @1 已设定为 @2。 Position @1 set to @2=保护区座标 @1 已设定为 @2。 -Position @1: =保护区座标 @1: +Position @1:=保护区座标 @1: Select an area by ID.=通过保护区编号选择区域 Select position @1 by punching a node.=请击打方块以设定保护区座标 @1 的位置。 Select positions by punching two nodes.=请击打两个方块,以设定保护区座标的位置。 @@ -134,4 +134,4 @@ The area @1 does not exist.=保护区 @1 不存在。 Unable to get position.=无法获得座标。 Unknown subcommand: @1=子指令不明:@1 -Relative coordinates is not supported on this server. Please upgrade Minetest to 5.7.0 or newer versions.=此服务器不支援相对座标。请更新Minetest至5.7.0或之后的版本。 \ No newline at end of file +Relative coordinates is not supported on this server. Please upgrade Minetest to 5.7.0 or newer versions.=此服务器不支援相对座标。请更新Minetest至5.7.0或之后的版本。 diff --git a/locale/areas.zh_TW.tr b/locale/areas.zh_TW.tr index 4a2c33f..a9687b8 100644 --- a/locale/areas.zh_TW.tr +++ b/locale/areas.zh_TW.tr @@ -121,7 +121,7 @@ unnamed=未命名 Area @1 selected.=保護區 @1 已選擇。 Area position @1 set to @2=保護區座標 @1 已設定爲 @2。 Position @1 set to @2=保護區座標 @1 已設定爲 @2。 -Position @1: =保護區座標 @1: +Position @1:=保護區座標 @1: Select an area by ID.=通過保護區編號選擇區域 Select position @1 by punching a node.=請擊打方塊,以設定保護區座標 @1 的位置。 Select positions by punching two nodes.=請擊打兩個方塊,以設定保護區座標的位置。 diff --git a/locale/template.txt b/locale/template.txt index 3508101..825c5d1 100644 --- a/locale/template.txt +++ b/locale/template.txt @@ -121,7 +121,7 @@ unnamed= Area @1 selected.= Area position @1 set to @2= Position @1 set to @2= -Position @1: = +Position @1:= Select an area by ID.= Select position @1 by punching a node.= Select positions by punching two nodes.= diff --git a/pos.lua b/pos.lua index f512eac..cc70486 100644 --- a/pos.lua +++ b/pos.lua @@ -4,10 +4,8 @@ local S = minetest.get_translator("areas") -- permission to use those commands and you don't have -- /area_pos{1,2} [X Y Z|X,Y,Z]. -- Since this is mostly copied from WorldEdit it is mostly --- licensed under the AGPL. (select_area is a exception) +-- licensed under the AGPL. (select_area is an exception) -areas.marker1 = {} -areas.marker2 = {} areas.set_pos = {} areas.pos1 = {} areas.pos2 = {} @@ -152,7 +150,7 @@ minetest.register_chatcommand("area_pos", { areas.set_pos[name] = "pos2" return true, S("Select position @1 by punching a node.", "2") elseif param == "get" then -- Display current area positions - local pos1str, pos2str = S("Position @1: ", "1"), S("Position @1: ", "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 @@ -181,42 +179,70 @@ function areas:getPos(playerName) return areas:sortPos(pos1, pos2) end -function areas:setPos1(playerName, pos) - areas.pos1[playerName] = posLimit(pos) - areas.markPos1(playerName) +function areas:setPos1(name, pos) + local old_pos = areas.pos1[name] + pos = posLimit(pos) + areas.pos1[name] = pos + + if old_pos then + -- TODO: use `core.objects_inside_radius` after Luanti 5.10.0 is well established. + for _, object in ipairs(core.get_objects_inside_radius(old_pos, 0.01)) do + local luaentity = object:get_luaentity() + if luaentity and luaentity.name == "areas:pos1" and luaentity.player == name then + object:remove() + end + end + end + + local entity = core.add_entity(pos, "areas:pos1") + if entity then + local luaentity = entity:get_luaentity() + if luaentity then + luaentity.player = name + end + end end -function areas:setPos2(playerName, pos) - areas.pos2[playerName] = posLimit(pos) - areas.markPos2(playerName) -end +function areas:setPos2(name, pos) + local old_pos = areas.pos2[name] + pos = posLimit(pos) + areas.pos2[name] = pos + if old_pos then + -- TODO: use `core.objects_inside_radius` after Luanti 5.10.0 is well established. + for _, object in ipairs(core.get_objects_inside_radius(old_pos, 0.01)) do + local luaentity = object:get_luaentity() + if luaentity and luaentity.name == "areas:pos2" and luaentity.player == name then + object:remove() + end + end + end + + local entity = core.add_entity(pos, "areas:pos2") + if entity then + local luaentity = entity:get_luaentity() + if luaentity then + luaentity.player = name + end + end +end minetest.register_on_punchnode(function(pos, node, puncher) local name = puncher:get_player_name() -- Currently setting position if name ~= "" and areas.set_pos[name] then - if areas.set_pos[name] == "pos1" then - areas.pos1[name] = pos - areas.markPos1(name) - areas.set_pos[name] = "pos2" - minetest.chat_send_player(name, - 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, - 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) + if areas.set_pos[name] == "pos2" then + areas:setPos2(name, pos) areas.set_pos[name] = nil minetest.chat_send_player(name, S("Position @1 set to @2", "2", minetest.pos_to_string(pos))) + else + areas:setPos1(name, pos) + areas.set_pos[name] = areas.set_pos[name] == "pos1" and "pos2" or nil + minetest.chat_send_player(name, + S("Position @1 set to @2", "1", + minetest.pos_to_string(pos))) end end end) @@ -237,32 +263,6 @@ function areas:sortPos(pos1, pos2) return pos1, pos2 end --- Marks area position 1 -areas.markPos1 = function(name) - local pos = areas.pos1[name] - if areas.marker1[name] ~= nil then -- Marker already exists - areas.marker1[name]:remove() -- Remove marker - areas.marker1[name] = nil - end - if pos ~= nil then -- Add marker - areas.marker1[name] = minetest.add_entity(pos, "areas:pos1") - areas.marker1[name]:get_luaentity().active = true - end -end - --- Marks area position 2 -areas.markPos2 = function(name) - local pos = areas.pos2[name] - if areas.marker2[name] ~= nil then -- Marker already exists - areas.marker2[name]:remove() -- Remove marker - areas.marker2[name] = nil - end - if pos ~= nil then -- Add marker - areas.marker2[name] = minetest.add_entity(pos, "areas:pos2") - areas.marker2[name]:get_luaentity().active = true - end -end - minetest.register_entity("areas:pos1", { initial_properties = { visual = "cube", @@ -271,17 +271,10 @@ minetest.register_entity("areas:pos1", { "areas_pos1.png", "areas_pos1.png", "areas_pos1.png", "areas_pos1.png"}, collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55}, + hp_max = 1, + armor_groups = {fleshy=100}, + static_save = false, }, - on_step = function(self, dtime) - if self.active == nil then - self.object:remove() - end - end, - on_punch = function(self, hitter) - self.object:remove() - local name = hitter:get_player_name() - areas.marker1[name] = nil - end, }) minetest.register_entity("areas:pos2", { @@ -292,15 +285,8 @@ minetest.register_entity("areas:pos2", { "areas_pos2.png", "areas_pos2.png", "areas_pos2.png", "areas_pos2.png"}, collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55}, + hp_max = 1, + armor_groups = {fleshy=100}, + static_save = false, }, - on_step = function(self, dtime) - if self.active == nil then - self.object:remove() - end - end, - on_punch = function(self, hitter) - self.object:remove() - local name = hitter:get_player_name() - areas.marker2[name] = nil - end, }) diff --git a/settingtypes.txt b/settingtypes.txt index 9abffa4..1ca0d3f 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -3,6 +3,20 @@ # Static paths do not work well with settings #areas.filename (Configuration file path) string (world_path)/areas.dat +# Use smallest area volume precedence concept. (experimental; may change) +# +# If set to `true`: +# The interaction permission is defined by the smallest area volume that +# contains the interaction position. Granting access to areas is achieved +# by factions instead of using `/add_owner`. +# This allows players to have private areas within a greater open/shared +# area and also define open/shared areas within those private areas. +# If set to `false`: (default) +# Interacting is permitted if the interaction position resides in any of the +# player's own areas, shared or open areas. +# This permission is not impacted by more restrictive, intersecting areas. +areas.use_smallest_area_precedence (Smallest area rules) bool false + # Allow players with a privilege create their own areas using /protect # within the specified size and amount limits. areas.self_protection (Self protection) bool false