mirror of
https://github.com/sys4-fr/server-nalc.git
synced 2024-11-16 15:30:30 +01:00
Merge pull request #314 from Gael-de-Sailly/areastore
Optimize areas with AreaStore
This commit is contained in:
commit
dd1c65b5e5
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user