1
0
mirror of https://github.com/sys4-fr/server-nalc.git synced 2024-12-25 02:00:37 +01:00

Optimize areas with AreaStore (by est31)

This commit is contained in:
Gael-de-Sailly 2015-10-27 11:40:52 +01:00
parent 1e49bd6d20
commit 6cb835f75e
2 changed files with 84 additions and 29 deletions

View File

@ -10,17 +10,48 @@ local plants = { ["farming:blueberries"]=1, ["farming:carrot"]=1, ["farming:coff
function areas:getAreasAtPos(pos)
local a = {}
local px, py, pz = pos.x, pos.y, pos.z
for id, area in pairs(self.areas) do
local ap1, ap2 = area.pos1, area.pos2
if px >= ap1.x and px <= ap2.x and
py >= ap1.y and py <= ap2.y and
pz >= ap1.z and pz <= ap2.z then
a[id] = area
if self.store then
local areas = self.store:get_areas_for_pos(pos, false, true)
for store_id, store_area in pairs(areas) do
local id = tonumber(store_area.data)
a[id] = self.areas[id]
end
else
for id, area in pairs(self.areas) do
local ap1, ap2 = area.pos1, area.pos2
if px >= ap1.x and px <= ap2.x and
py >= ap1.y and py <= ap2.y and
pz >= ap1.z and pz <= ap2.z then
a[id] = area
end
end
end
return a
end
function areas:getAreasForArea(pos1, pos2)
local res = {}
if self.store then
local areas = self.store:get_areas_in_area(pos1,
pos2, true, false, true)
for store_id, store_area in pairs(areas) do
local id = tonumber(store_area.data)
res[id] = self.areas[id]
end
else
for id, area in pairs(self.areas) do
local p1, p2 = area.pos1, area.pos2
if (p1.x <= pos2.x and p2.x >= pos1.x) and
(p1.y <= pos2.y and p2.y >= pos1.y) and
(p1.z <= pos2.z and p2.z >= pos1.z) then
-- Found an intersecting area.
res[id] = area
end
end
end
return res
end
-- Checks if the area is unprotected or owned by you
function areas:canInteract(pos, name)
if minetest.check_player_privs(name, self.adminPrivs) then
@ -80,30 +111,23 @@ function areas:canInteractInArea(pos1, pos2, name, allow_open)
return true
end
areas:sortPos(pos1, pos2)
-- First check for a fully enclosing owned area.
if name then
for id, area in pairs(self.areas) do
-- A little optimization: isAreaOwner isn't necessary
-- here since we're iterating through all areas.
if area.owner == name and
self:isSubarea(pos1, pos2, id) then
return true
end
local areas = self:getAreasForArea(pos1, pos2)
for id, area in pairs(areas) do
-- First check for a fully enclosing owned area.
-- A little optimization: isAreaOwner isn't necessary
-- here since we're iterating through all relevant areas.
if area.owner == name and
self:isSubarea(pos1, pos2, id) then
return true
end
end
-- Then check for intersecting (non-owned) areas.
for id, area in pairs(self.areas) do
local p1, p2 = area.pos1, area.pos2
if (p1.x <= pos2.x and p2.x >= pos1.x) and
(p1.y <= pos2.y and p2.y >= pos1.y) and
(p1.z <= pos2.z and p2.z >= pos1.z) then
-- Found an intersecting area.
-- Return if the area is closed or open areas aren't
-- allowed, and the area isn't owned.
if (not allow_open or not area.open) and
(not name or not areas:isAreaOwner(id, name)) then
return false, id
end
-- Then check for intersecting (non-owned) areas.
-- Return if the area is closed or open areas aren't
-- allowed, and the area isn't owned.
if (not allow_open or not area.open) and
(not name or not self:isAreaOwner(id, name)) then
return false, id
end
end
return true

View File

@ -20,6 +20,23 @@ function areas:save()
file:close()
end
local function populateStore(self)
if not rawget(_G, "AreaStore") then
return
end
local store = AreaStore()
local store_ids = {}
store:reserve(#self.areas)
for id, area in pairs(areas.areas) do
local sid = store:insert_area(area.pos1,
area.pos2, tostring(id))
assert(sid ~= nil) -- if its nil, no id could be found
store_ids[id] = sid
end
self.store = store
self.store_ids = store_ids
end
-- Load the areas table from the save file
function areas:load()
local file, err = io.open(self.config.filename, "r")
@ -31,6 +48,7 @@ function areas:load()
if type(self.areas) ~= "table" then
self.areas = {}
end
populateStore(self)
file:close()
end
@ -48,6 +66,12 @@ function areas:add(owner, name, pos1, pos2, parent)
local id = findFirstUnusedIndex(self.areas)
self.areas[id] = {name=name, pos1=pos1, pos2=pos2, owner=owner,
parent=parent}
-- add to AreaStore
if self.store then
local sid = self.store:insert_area(pos1, pos2, dump(id))
assert(sid ~= nil) -- if its nil, no id could be found
self.store_ids[id] = sid
end
return id
end
@ -75,6 +99,13 @@ function areas:remove(id, recurse)
-- Remove main entry
self.areas[id] = nil
-- remove from AreaStore
if self.store then
local sid = self.store_ids[id]
self.store_ids[id] = nil
self.store:remove_area(sid)
end
end
-- Checks if a area between two points is entirely contained by another area