Compare commits

20 Commits

Author SHA1 Message Date
aca830fd22 Add support for playerfactions mod (#37)
Add faction indicator to HUD
2019-09-21 15:33:42 +02:00
95c1165e28 Add and parse from settingtypes.txt. Update readme 2019-07-11 20:02:32 +02:00
5527dc8945 Replace deprecated functions with newer ones (#36)
This commit replaces a few deprecated calls to getpos with get_pos
2019-07-10 20:26:42 +02:00
6218e5884d Limit areas to -30992,30992 due to MABLOCK_SIZE=16
Internally, when allocating an AreaStore, the limits are required
to be within the last full block, and so, you cannot create one "on"
the edge, as it will trigger an exception. When limited to the last
full mapblock, it all works fine.
2019-04-03 11:10:59 -07:00
cfd4bb2423 Last of the luacheck cleanups. 2019-04-03 10:26:20 -07:00
6e2b9a0a51 Needs to be defined earlier. 2019-04-03 10:24:02 -07:00
024424ee8b Also limit chatcommand area_pos[12] positions. 2019-04-03 10:17:47 -07:00
f70600db30 oops, commas would be nice. 2019-04-02 16:06:19 -07:00
9508a004d0 fix posLimit(pos) to process and return a position table 2019-04-02 14:53:54 -07:00
630bdefd98 Don't allow areas to cross outside mapgen world limits.
Limit any area to within [-31000,31000].
2019-04-01 21:28:03 -07:00
a303abe51b Add template .luacheckrc 2019-04-01 21:22:31 -07:00
7b51f84404 Limit recalculations.
Setting based - limit area recalculation and allow tuning of the
interval.
2019-04-01 21:21:31 -07:00
1bbb997c7a Add callbacks for area operations 2019-04-01 20:28:50 -07:00
09c030352f Use the new minetest.safe_file_write API if possible when saving database. 2019-04-01 20:27:17 -07:00
2637876555 Fix pos big (#1)
* fix pos being to big

* improve

* make the change instead in hud.lua
2019-04-01 20:24:59 -07:00
289d0e623c Update usage of settings API 2017-06-09 13:00:12 -04:00
d3d43d9511 Reference 'settings.lua' instead of 'config.lua' (#21) 2017-05-06 13:41:45 -04:00
6080ff065e Add API for adding areas to HUD 2016-12-19 16:36:37 +00:00
23f81f6278 Add mod.conf 2016-12-04 04:12:27 +00:00
7cb8787beb Use get_auth_handler().get_auth() instead of auth_table
minetest.auth_table is an implementation detail of the default auth handler.
No guarantee is made that it even exists and using this table directly is incompatible
with custom auth handlers.  Instead, use the proper auth handler API.
2016-09-03 21:05:52 -04:00
24 changed files with 341 additions and 328 deletions

19
.luacheckrc Normal file
View File

@ -0,0 +1,19 @@
unused_args = false
allow_defined_top = true
read_globals = {
"DIR_DELIM",
"core",
"dump",
"vector", "nodeupdate",
"VoxelManip", "VoxelArea",
"PseudoRandom", "ItemStack",
"AreaStore",
"intllib",
"default",
table = { fields = { "copy", "getn" } }
}
globals = {
"minetest"
}

View File

@ -1,21 +1,29 @@
Areas mod for Minetest 0.4.8+ Areas mod for Minetest
============================= ======================
Dependencies
------------
Minetest 5.0.0+ is recommended, but 0.4.16+ should work as well.
Configuration Configuration
------------- -------------
If you wish to specify configuration options, such as whether players are Open the tab `Settings -> All Settings -> Mods -> areas` to get a list of all
allowed to protect their own areas with the `protect` command (disabled by possible settings.
default), you should check config.lua and set the appropriate settings in your
server's configuration file (probably `minetest.conf`). For server owners: Check `settingtypes.txt` and modify your `minetest.conf`
according to the wanted setting changes.
Tutorial Tutorial
-------- --------
To protect an area you must first set the corner positions of the area. 1) Specify the corner positions of the area you would like to protect.
In order to set the corner positions you can run: Use one of the following commands:
* `/area_pos set` and punch the two corner nodes to set them. * `/area_pos set` and punch the two corner nodes to set them.
* `/area_pos set1/set2` and punch only the first or second corner node to * `/area_pos set1/set2` and punch only the first or second corner node to
set them one at a time. set them one at a time.
@ -23,25 +31,25 @@ In order to set the corner positions you can run:
* `/area_pos1/2 X Y Z` to set one of the positions to the specified * `/area_pos1/2 X Y Z` to set one of the positions to the specified
coordinates. coordinates.
Once you have set the border positions you can protect the area by running one 2) Protect the selected area by running one of the following commands:
of the following commands:
* `/set_owner <OwnerName> <AreaName>` -- If you have the `areas` privilege. * `/set_owner <OwnerName> <AreaName>` -- If you have the `areas` privilege.
* `/protect <AreaName>` -- If you have the `areas` privilege or the server * `/protect <AreaName>` -- If you have the `areas` privilege or the server
administrator has enabled area self-protection. administrator has enabled area self-protection.
The area name is used only for informational purposes (so that you know what The area name is used only for informational purposes and has no functional
an area is for). It is not used for any other purpose. importance.
For example: `/set_owner SomePlayer Mese city` For example: `/set_owner SomePlayer Mese city`
Now that you own an area you may want to add sub-owners to it. You can do this 3) You now own an area. You may now add sub-owners to it if you want to (see command `/add_owner`). Before using the `/add_owner` command you have to
with the `add_owner` command. Anyone with an area can use the `add_owner` select the corners of the sub-area as you did in step 1.
command on their areas. Before using the `add_owner` command you have to
select the corners of the sub-area as you did for `set_owner`. If your markers If your markers are still around your original area and you want to grant
are still around your original area and you want to grant access to your access to your entire area you will not have to re-set them. Use `/select_area` to place the markers at the corners of an existing area if you've reset your
entire area you will not have to re-set them. You can also use `select_area` to
place the markers at the corners of an existing area if you've reset your
markers and want to grant access to a full area. markers and want to grant access to a full area.
The `add_owner` command expects three arguments:
The `/add_owner` command expects three arguments:
1. The ID number of the parent area (the area that you want to add a 1. The ID number of the parent area (the area that you want to add a
sub-area to). sub-area to).
2. The name of the player that will own the sub-area. 2. The name of the player that will own the sub-area.

135
api.lua
View File

@ -1,14 +1,41 @@
local hudHandlers = {}
--plants to place in openfarming
local plants = { ["farming:blueberries"]="air", ["farming:carrot"]="air", ["farming:coffee_beans"]="air", ["farming:corn"]="air", ["farming:cucumber"]="air", areas.registered_on_adds = {}
["farming:melon_slice"]="air", ["farming:potato"]="air", ["farming:pumpkin_slice"]="air", ["farming:raspberries"]="air", ["farming:rhubarb"]="air", areas.registered_on_removes = {}
["farming:tomato"]="air", ["farming:seed_cotton"]="air", ["farming:seed_wheat"]="air",["default:papyrus"]="air", ["farming:trellis"]="air", areas.registered_on_moves = {}
["farming:grapes"]="farming:trellis", ["farming:beanpole"]="air", ["farming:beans"]="farming:beanpole",
} function areas:registerOnAdd(func)
table.insert(areas.registered_on_adds, func)
end
function areas:registerOnRemove(func)
table.insert(areas.registered_on_removes, func)
end
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
func(pos, areas)
end
return areas
end
--- Returns a list of areas that include the provided position. --- Returns a list of areas that include the provided position.
function areas:getAreasAtPos(pos) function areas:getAreasAtPos(pos)
local res = {} local res = {}
if self.store then if self.store then
local a = self.store:get_areas_for_pos(pos, false, true) local a = self.store:get_areas_for_pos(pos, false, true)
for store_id, store_area in pairs(a) do for store_id, store_area in pairs(a) do
@ -64,33 +91,16 @@ function areas:canInteract(pos, name)
return true return true
end end
local owned = false local owned = false
if pos == nil then return not owned end -- pour éviter crash avec nénuphar
for _, area in pairs(self:getAreasAtPos(pos)) do for _, area in pairs(self:getAreasAtPos(pos)) do
if area.owner == name or area.open then if area.owner == name or area.open then
return true return true
elseif area.openfarming then elseif areas.factions_available and area.faction_open then
-- if area is openfarming local faction_name = factions.get_player_faction(area.owner)
local node = minetest.get_node(pos).name if faction_name ~= nil and faction_name == factions.get_player_faction(name) then
if not minetest.registered_nodes[node] then return false end
local player = minetest.get_player_by_name(name)
if not player then return false end
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 return true
end end
--on_place
if plants[wstack] ~= nil and plants[wstack] == node then
return true
end
owned = true
else
owned = true
end end
owned = true
end end
return not owned return not owned
end end
@ -153,74 +163,3 @@ function areas:canInteractInArea(pos1, pos2, name, allow_open)
-- intersecting areas and they are all owned by the player. -- intersecting areas and they are all owned by the player.
return true return true
end end
function areas:canMakeArea(pos1, pos2, name) --MFF crabman(25/02/2016) fix areas in areas
if name and minetest.check_player_privs(name, self.adminPrivs) then
return true
end
areas:sortPos(pos1, pos2)
local id_areas_intersect = {}
local areas = self:getAreasIntersectingArea(pos1, pos2)
if not areas then return true end
for id, area in pairs(areas) do
if area.owner == name and self:isSubarea(pos1, pos2, id) then
return true
end
if not area.open and not self:isAreaOwner(id, name) then
table.insert(id_areas_intersect, id)
end
end
if #id_areas_intersect > 0 then
return false, id_areas_intersect[1]
end
return true
end
--MFF crabman(5/03/2016 ) return special area pos if a spawn is set.
--1 party (2 party in beds mod)
function areas:getSpawn(pos)
for _, area in pairs(areas:getAreasAtPos(pos)) do
if area.spawn and area.spawn.x then
return area.spawn
end
end
return nil
end
--MFF DEBUT crabman(17/09/2015 ) respawn player in special area(event) if a spawn is set.
--1 party (2 party in beds mod)
local dead_players = {}
minetest.register_on_dieplayer(function(player)
local player_name = player:get_player_name()
if not player_name then return end
local pos = player:getpos()
if pos then
dead_players[player_name] = pos
end
end)
function areas:onRespawn(player)
local player_name = player:get_player_name()
if not player_name or not dead_players[player_name] then return false end
local pos = dead_players[player_name]
dead_players[player_name] = nil
if pos then
for _, area in pairs(areas:getAreasAtPos(pos)) do
if area.spawn then
player:setpos(area.spawn)
return true
end
end
end
return false
end
--FIN

48
api.md Normal file
View File

@ -0,0 +1,48 @@
Areas mod API
===
API list
---
* `areas:registerHudHandler(handler)` - Registers a handler to add items to the Areas HUD. See [HUD](#hud).
* `areas:registerOnAdd(func(id, area))`
* `areas:registerOnRemove(func(id))`
* `areas:registerOnMove(func(id, area, pos1, pos2))`
HUD
---
If you are making a protection mod or a similar mod that adds invisible regions
to the world, and you would like then to show up in the areas HUD element, you
can register a callback to show your areas.
HUD handler specification:
* `handler(pos, list)`
* `pos` - The position to check.
* `list` - The list of area HUD elements, this should be modified in-place.
The area list item is a table containing a list of tables with the following fields:
* `id` - An identifier for the area. This should be a unique string in the format `mod:id`.
* `name` - The name of the area.
* `owner` - The player name of the region owner, if any.
All of the fields are optional but at least one of them must be set.
### Example
local function areas_hud_handler(pos, areas)
local val = find_my_protection(pos)
if val then
table.insert(areas, {
id = "mod:"..val.id,
name = val.name,
owner = val.owner,
})
end
end
areas:registerHudHandler(areas_hud_handler)

View File

@ -286,26 +286,28 @@ minetest.register_chatcommand("area_open", {
}) })
minetest.register_chatcommand("area_openfarming", { if areas.factions_available then
params = "<ID>", minetest.register_chatcommand("area_faction_open", {
description = "Toggle an area open (anyone can interact farming) or closed", params = "<ID>",
func = function(name, param) description = "Toggle an area open/closed for members in your faction.",
local id = tonumber(param) func = function(name, param)
if not id then local id = tonumber(param)
return false, "Invalid usage, see /help area_openfarming." if not id then
end return false, "Invalid usage, see /help area_faction_open."
end
if not areas:isAreaOwner(id, name) then if not areas:isAreaOwner(id, name) then
return false, "Area "..id.." does not exist" return false, "Area "..id.." does not exist"
.." or is not owned by you." .." or is not owned by you."
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")
end end
local openfarming = not areas.areas[id].openfarming })
-- Save false as nil to avoid inflating the DB. end
areas.areas[id].openfarming = openfarming or nil
areas:save()
return true, ("Area %s to farming."):format(openfarming and "opened" or "closed")
end
})
minetest.register_chatcommand("move_area", { minetest.register_chatcommand("move_area", {
@ -405,10 +407,10 @@ minetest.register_chatcommand("area_info", {
table.insert(lines, ("%s spanning up to %dx%dx%d.") table.insert(lines, ("%s spanning up to %dx%dx%d.")
:format(str, size.x, size.y, size.z)) :format(str, size.x, size.y, size.z))
end end
local function priv_limit_info(priv, max_count, max_size) local function priv_limit_info(lpriv, lmax_count, lmax_size)
size_info(("Players with the %q privilege".. size_info(("Players with the %q privilege"..
" can protect up to %d areas"):format( " can protect up to %d areas"):format(
priv, max_count), max_size) lpriv, lmax_count), lmax_size)
end end
if self_prot then if self_prot then
if privs.areas then if privs.areas then
@ -425,63 +427,3 @@ minetest.register_chatcommand("area_info", {
end, end,
}) })
--MFF DEBUT crabman(17/09/2015 ) respawn player at in special area(event) if a spawn is set.
minetest.register_chatcommand("area_addspawn", {
params = "<ID>",
privs = areas.adminPrivs,
description = "Define special spawn for area",
func = function(name, param)
local id = param:match("^(%d+)")
if not id then
return false, "Invalid usage, see /help area_addspawn."
end
id = tonumber(id)
if not id then
return false, "Error, Param id must be int."
end
local player = minetest.get_player_by_name(name)
if not player then
return false, "Error, there is not player"
end
local pos = player:getpos()
if not pos then
return false, "Error, there is not pos."
end
if not areas.areas[id] then
return false, "Area ".. id .." does not exist."
end
areas.areas[id].spawn = pos
areas:save()
return true, "spawn of area ".. id .." defined."
end
})
minetest.register_chatcommand("area_delspawn", {
params = "<ID>",
privs = areas.adminPrivs,
description = "Delete special spawn of area",
func = function(name, param)
local id = param:match("^(%d+)")
if not id then
return false, "Invalid usage, see /help area_delspawn."
end
id = tonumber(id)
if not id then
return false, "Error, Param id must be int."
end
if not areas.areas[id] then
return false, "Area ".. id .." does not exist."
end
areas.areas[id].spawn = nil
areas:save()
return true, "spawn of area ".. id .." deleted."
end
})
-- FIN

109
hud.lua
View File

@ -1,83 +1,70 @@
-- This is inspired by the landrush mod by Bremaweb -- This is inspired by the landrush mod by Bremaweb
areas.hud = {} 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
else
return
end
local function tick()
for _, player in pairs(minetest.get_connected_players()) do for _, player in pairs(minetest.get_connected_players()) do
local name = player:get_player_name() local name = player:get_player_name()
local pos = vector.round(player:getpos()) local pos = vector.round(player:get_pos())
local area_text = "No area(s)\n\n" pos = vector.apply(pos, function(p)
local area_owner_name = "" return math.max(math.min(p, 2147483), -2147483)
local mod_owner = 0 end)
local mod_open = 0 local areaStrings = {}
local mod_farming = 0
local area_name = ""
local nb_areas = 0
for id, area in pairs(areas:getAreasAtPos(pos)) do for id, area in pairs(areas:getAreasAtPos(pos)) do
nb_areas = nb_areas+1 local faction_info = area.faction_open and areas.factions_available and
if areas:isAreaOwner(id, name) then factions.get_player_faction(area.owner)
mod_owner = 1 area.faction_open = faction_info
end table.insert(areaStrings, ("%s [%u] (%s%s%s)")
:format(area.name, id, area.owner,
if area.open then area.open and ":open" or "",
mod_open = 1 faction_info and ":"..faction_info or ""))
end
if area.openfarming then
mod_farming = 1
end
if not area.parent then
area_owner_name = area.owner
area_name = area.name
end
end end
local icon = "areas_not_area.png" for i, area in pairs(areas:getExternalHudEntries(pos)) do
if nb_areas > 0 then local str = ""
local plural = "" if area.name then str = area.name .. " " end
if nb_areas > 1 then if area.id then str = str.."["..area.id.."] " end
plural = "s" if area.owner then str = str.."("..area.owner..")" end
end table.insert(areaStrings, str)
area_text = ("%s\nOwner: %s\n%u area" .. plural):format(area_name, area_owner_name, nb_areas)
icon = ("areas_%u_%u_%u.png"):format(mod_owner, mod_open, mod_farming)
end end
if not areas.hud[name] then
areas.hud[name] = {}
areas.hud[name].icon = player:hud_add({
hud_elem_type = "image",
position = {x=0,y=1},
scale = {x=1,y=1},
offset = {x=26,y=-60},
text = icon,
})
areas.hud[name].areas_id = player:hud_add({ local areaString = "Areas:"
if #areaStrings > 0 then
areaString = areaString.."\n"..
table.concat(areaStrings, "\n")
end
local hud = areas.hud[name]
if not hud then
hud = {}
areas.hud[name] = hud
hud.areasId = player:hud_add({
hud_elem_type = "text", hud_elem_type = "text",
name = "Areas", name = "Areas",
number = 0xFFFFFF, number = 0xFFFFFF,
position = {x=0, y=1}, position = {x=0, y=1},
offset = {x=48, y=-40}, offset = {x=8, y=-8},
text = area_text, text = areaString,
scale = {x=1, y=1}, scale = {x=200, y=60},
alignment = {x=1, y=-1}, alignment = {x=1, y=-1},
}) })
areas.hud[name].old_area_text = area_text hud.oldAreas = areaString
areas.hud[name].old_icon = icon return
else elseif hud.oldAreas ~= areaString then
if areas.hud[name].old_area_text ~= area_text then player:hud_change(hud.areasId, "text", areaString)
player:hud_change(areas.hud[name].areas_id, "text", area_text) hud.oldAreas = areaString
areas.hud[name].old_area_text = area_text
end
if areas.hud[name].old_icon ~= icon then
player:hud_change(areas.hud[name].icon, "text", icon)
areas.hud[name].old_icon = icon
end
end end
end end
minetest.after(1.5, tick) end)
end
tick()
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
areas.hud[player:get_player_name()] = nil areas.hud[player:get_player_name()] = nil

View File

@ -4,6 +4,8 @@
areas = {} areas = {}
areas.factions_available = minetest.global_exists("factions")
areas.adminPrivs = {areas=true} areas.adminPrivs = {areas=true}
areas.startTime = os.clock() areas.startTime = os.clock()
@ -32,7 +34,7 @@ if not minetest.registered_privileges[areas.config.self_protection_privilege] th
}) })
end end
if minetest.setting_getbool("log_mods") then if minetest.settings:get_bool("log_mods") then
local diffTime = os.clock() - areas.startTime local diffTime = os.clock() - areas.startTime
minetest.log("action", "areas loaded in "..diffTime.."s.") minetest.log("action", "areas loaded in "..diffTime.."s.")
end end

View File

@ -1,10 +1,20 @@
-- Mega_builder privilege
minetest.register_privilege("megabuilder","Can protect an infinite amount of areas.")
function areas:player_exists(name) function areas:player_exists(name)
return minetest.get_auth_handler().get_auth(name) ~= nil return minetest.get_auth_handler().get_auth(name) ~= nil
end 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
-- Save the areas table to a file -- Save the areas table to a file
function areas:save() function areas:save()
local datastr = minetest.serialize(self.areas) local datastr = minetest.serialize(self.areas)
@ -12,12 +22,7 @@ function areas:save()
minetest.log("error", "[areas] Failed to serialize area data!") minetest.log("error", "[areas] Failed to serialize area data!")
return return
end end
local file, err = io.open(self.config.filename, "w") return safe_file_write(self.config.filename, datastr)
if err then
return err
end
file:write(datastr)
file:close()
end end
-- Load the areas table from the save file -- Load the areas table from the save file
@ -88,6 +93,11 @@ function areas:add(owner, name, pos1, pos2, parent)
owner = owner, owner = owner,
parent = parent parent = parent
} }
for i=1, #areas.registered_on_adds do
areas.registered_on_adds[i](id, self.areas[id])
end
-- Add to AreaStore -- Add to AreaStore
if self.store then if self.store then
local sid = self.store:insert_area(pos1, pos2, tostring(id)) local sid = self.store:insert_area(pos1, pos2, tostring(id))
@ -120,6 +130,10 @@ function areas:remove(id, recurse)
end end
end end
for i=1, #areas.registered_on_removes do
areas.registered_on_removes[i](id)
end
-- Remove main entry -- Remove main entry
self.areas[id] = nil self.areas[id] = nil
@ -135,6 +149,11 @@ function areas:move(id, area, pos1, pos2)
area.pos1 = pos1 area.pos1 = pos1
area.pos2 = pos2 area.pos2 = pos2
for i=1, #areas.registered_on_moves do
areas.registered_on_moves[i](id, area, pos1, pos2)
end
if self.store then if self.store then
self.store:remove_area(areas.store_ids[id]) self.store:remove_area(areas.store_ids[id])
local sid = self.store:insert_area(pos1, pos2, tostring(id)) local sid = self.store:insert_area(pos1, pos2, tostring(id))
@ -197,37 +216,33 @@ function areas:canPlayerAddArea(pos1, pos2, name)
.." the necessary privilege." .." the necessary privilege."
end end
-- MFF: megabuilders skip checks on size and number of areas. local max_size = privs.areas_high_limit and
if not privs["megabuilder"] then self.config.self_protection_max_size_high or
-- Check size self.config.self_protection_max_size
local max_size = privs.areas_high_limit and if
self.config.self_protection_max_size_high or (pos2.x - pos1.x) > max_size.x or
self.config.self_protection_max_size (pos2.y - pos1.y) > max_size.y or
if (pos2.z - pos1.z) > max_size.z then
(pos2.x - pos1.x) > max_size.x or return false, "Area is too big."
(pos2.y - pos1.y) > max_size.y or end
(pos2.z - pos1.z) > max_size.z then
return false, "Area is too big."
end
-- Check number of areas the user has and make sure it not above the max -- Check number of areas the user has and make sure it not above the max
local count = 0 local count = 0
for _, area in pairs(self.areas) do for _, area in pairs(self.areas) do
if area.owner == name then if area.owner == name then
count = count + 1 count = count + 1
end
end
local max_areas = privs.areas_high_limit and
self.config.self_protection_max_areas_high or
self.config.self_protection_max_areas
if count >= max_areas then
return false, "You have reached the maximum amount of"
.." areas that you are allowed to protect."
end end
end end
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
-- Check intersecting areas -- Check intersecting areas
local can, id = self:canMakeArea(pos1, pos2, name) --MFF crabman(25/02/2016) fix areas in areas local can, id = self:canInteractInArea(pos1, pos2, name)
if not can then if not can then
local area = self.areas[id] local area = self.areas[id]
return false, ("The area intersects with %s [%u] (%s).") return false, ("The area intersects with %s [%u] (%s).")
@ -288,4 +303,3 @@ function areas:isAreaOwner(id, name)
end end
return false return false
end end

View File

@ -10,7 +10,7 @@ minetest.register_chatcommand("legacy_load_areas", {
minetest.chat_send_player(name, "Converting areas...") minetest.chat_send_player(name, "Converting areas...")
local version = tonumber(param) local version = tonumber(param)
if version == 0 then if version == 0 then
err = areas:node_ownership_load() local err = areas:node_ownership_load()
if err then if err then
minetest.chat_send_player(name, "Error loading legacy file: "..err) minetest.chat_send_player(name, "Error loading legacy file: "..err)
return return
@ -48,6 +48,7 @@ minetest.register_chatcommand("legacy_load_areas", {
function areas:node_ownership_load() function areas:node_ownership_load()
local filename = minetest.get_worldpath().."/owners.tbl" local filename = minetest.get_worldpath().."/owners.tbl"
local tables, err
tables, err = loadfile(filename) tables, err = loadfile(filename)
if err then if err then
return err return err

2
mod.conf Normal file
View File

@ -0,0 +1,2 @@
name = areas
optional_depends = playerfactions

26
pos.lua
View File

@ -11,6 +11,16 @@ areas.set_pos = {}
areas.pos1 = {} areas.pos1 = {}
areas.pos2 = {} areas.pos2 = {}
local LIMIT = 30992 -- this is due to MAPBLOCK_SIZE=16!
local function posLimit(pos)
return {
x = math.max(math.min(pos.x, LIMIT), -LIMIT),
y = math.max(math.min(pos.y, LIMIT), -LIMIT),
z = math.max(math.min(pos.z, LIMIT), -LIMIT)
}
end
minetest.register_chatcommand("select_area", { minetest.register_chatcommand("select_area", {
params = "<ID>", params = "<ID>",
description = "Select a area by id.", description = "Select a area by id.",
@ -35,7 +45,7 @@ minetest.register_chatcommand("area_pos1", {
.." location or the one specified", .." location or the one specified",
privs = {}, privs = {},
func = function(name, param) func = function(name, param)
local pos = nil local pos
local found, _, x, y, z = param:find( local found, _, x, y, z = param:find(
"^(-?%d+)[, ](-?%d+)[, ](-?%d+)$") "^(-?%d+)[, ](-?%d+)[, ](-?%d+)$")
if found then if found then
@ -43,14 +53,14 @@ minetest.register_chatcommand("area_pos1", {
elseif param == "" then elseif param == "" then
local player = minetest.get_player_by_name(name) local player = minetest.get_player_by_name(name)
if player then if player then
pos = player:getpos() pos = player:get_pos()
else else
return false, "Unable to get position." return false, "Unable to get position."
end end
else else
return false, "Invalid usage, see /help area_pos1." return false, "Invalid usage, see /help area_pos1."
end end
pos = vector.round(pos) pos = posLimit(vector.round(pos))
areas:setPos1(name, pos) areas:setPos1(name, pos)
return true, "Area position 1 set to " return true, "Area position 1 set to "
..minetest.pos_to_string(pos) ..minetest.pos_to_string(pos)
@ -62,7 +72,7 @@ minetest.register_chatcommand("area_pos2", {
description = "Set area protection region position 2 to your" description = "Set area protection region position 2 to your"
.." location or the one specified", .." location or the one specified",
func = function(name, param) func = function(name, param)
local pos = nil local pos
local found, _, x, y, z = param:find( local found, _, x, y, z = param:find(
"^(-?%d+)[, ](-?%d+)[, ](-?%d+)$") "^(-?%d+)[, ](-?%d+)[, ](-?%d+)$")
if found then if found then
@ -70,14 +80,14 @@ minetest.register_chatcommand("area_pos2", {
elseif param == "" then elseif param == "" then
local player = minetest.get_player_by_name(name) local player = minetest.get_player_by_name(name)
if player then if player then
pos = player:getpos() pos = player:get_pos()
else else
return false, "Unable to get position." return false, "Unable to get position."
end end
else else
return false, "Invalid usage, see /help area_pos2." return false, "Invalid usage, see /help area_pos2."
end end
pos = vector.round(pos) pos = posLimit(vector.round(pos))
areas:setPos2(name, pos) areas:setPos2(name, pos)
return true, "Area position 2 set to " return true, "Area position 2 set to "
..minetest.pos_to_string(pos) ..minetest.pos_to_string(pos)
@ -130,12 +140,12 @@ function areas:getPos(playerName)
end end
function areas:setPos1(playerName, pos) function areas:setPos1(playerName, pos)
areas.pos1[playerName] = pos areas.pos1[playerName] = posLimit(pos)
areas.markPos1(playerName) areas.markPos1(playerName)
end end
function areas:setPos2(playerName, pos) function areas:setPos2(playerName, pos)
areas.pos2[playerName] = pos areas.pos2[playerName] = posLimit(pos)
areas.markPos2(playerName) areas.markPos2(playerName)
end end

View File

@ -2,42 +2,45 @@ local world_path = minetest.get_worldpath()
areas.config = {} areas.config = {}
local function setting(tp, name, default) local function setting(name, tp, default)
local full_name = "areas."..name local full_name = "areas." .. name
local value local value
if tp == "boolean" then if tp == "bool" then
value = minetest.setting_getbool(full_name) value = minetest.settings:get_bool(full_name)
default = value == nil and minetest.is_yes(default)
elseif tp == "string" then elseif tp == "string" then
value = minetest.setting_get(full_name) value = minetest.settings:get(full_name)
elseif tp == "position" then elseif tp == "v3f" then
value = minetest.setting_get_pos(full_name) value = minetest.setting_get_pos(full_name)
elseif tp == "number" then default = value == nil and minetest.string_to_pos(default)
value = tonumber(minetest.setting_get(full_name)) elseif tp == "float" or tp == "int" then
value = tonumber(minetest.settings:get(full_name))
local v, other = default:match("^(%S+) (.+)")
default = value == nil and tonumber(other and v or default)
else else
error("Invalid setting type!") error("Cannot parse setting type " .. tp)
end end
if value == nil then if value == nil then
value = default value = default
assert(default ~= nil, "Cannot parse default for " .. full_name)
end end
--print("add", name, default, value)
areas.config[name] = value areas.config[name] = value
end end
local file = io.open(areas.modpath .. "/settingtypes.txt", "r")
for line in file:lines() do
local name, tp, value = line:match("^areas%.(%S+) %(.*%) (%S+) (.*)")
if value then
setting(name, tp, value)
end
end
file:close()
-------------- --------------
-- Settings -- -- Settings --
-------------- --------------
setting("string", "filename", world_path.."/areas.dat") setting("filename", "string", world_path.."/areas.dat")
-- Allow players with a privilege create their own areas
-- within the maximum size and number.
setting("boolean", "self_protection", false)
setting("string", "self_protection_privilege", "interact")
setting("position", "self_protection_max_size", {x=64, y=128, z=64})
setting("number", "self_protection_max_areas", 4)
-- For players with the areas_high_limit privilege.
setting("position", "self_protection_max_size_high", {x=512, y=512, z=512})
setting("number", "self_protection_max_areas_high", 32)
-- legacy_table (owner_defs) compatibility. Untested and has known issues.
setting("boolean", "legacy_table", false)

38
settingtypes.txt Normal file
View File

@ -0,0 +1,38 @@
# This file is parsed in "settings.lua". Check regex first.
# Static paths do not work well with settings
#areas.filename (Configuration file path) string (world_path)/areas.dat
# 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
# Self protection: Privilege required to protect an area
areas.self_protection_privilege (Self protection: Required privs) string interact
# Refresh delay for the name displays in the HUD in seconds
areas.tick (HUD update delay) float 0.5 0 100
# Enable the legacy owner_defs metatable mode. Untested and possibly unstable
areas.legacy_table (Legacy owner_defs metatable) bool false
[Self protection (normal)]
# Self protection (normal): Maximal size of the protectable area
# Only enter positive whole numbers for the coordinate values or you'll mess up stuff.
areas.self_protection_max_size (Maximal area size) v3f (64, 128, 64)
# Self protection (normal): Maximal amount of protected areas per player
areas.self_protection_max_areas (Maximal area count) int 4
[Self protection (high)]
# Self protection (normal): Maximal size of the protectable area
# This setting applies for plyaers with the privilege 'areas_high_limit'
areas.self_protection_max_size_high (Maximal area size) v3f (512, 512, 512)
# Self protection (normal): Maximal amount of protected areas per player
# 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 440 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 495 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 B

After

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 B

After

Width:  |  Height:  |  Size: 157 B