Use AreaStore

This commit is contained in:
est31 2015-07-09 11:42:13 +02:00
parent 177f659f4e
commit fe932b6ea6
2 changed files with 84 additions and 29 deletions

82
api.lua
View File

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

View File

@ -18,6 +18,23 @@ function areas:save()
file:close() file:close()
end 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 -- Load the areas table from the save file
function areas:load() function areas:load()
local file, err = io.open(self.config.filename, "r") local file, err = io.open(self.config.filename, "r")
@ -29,6 +46,7 @@ function areas:load()
if type(self.areas) ~= "table" then if type(self.areas) ~= "table" then
self.areas = {} self.areas = {}
end end
populateStore(self)
file:close() file:close()
end end
@ -46,6 +64,12 @@ function areas:add(owner, name, pos1, pos2, parent)
local id = findFirstUnusedIndex(self.areas) local id = findFirstUnusedIndex(self.areas)
self.areas[id] = {name=name, pos1=pos1, pos2=pos2, owner=owner, self.areas[id] = {name=name, pos1=pos1, pos2=pos2, owner=owner,
parent=parent} 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 return id
end end
@ -73,6 +97,13 @@ function areas:remove(id, recurse)
-- Remove main entry -- Remove main entry
self.areas[id] = nil 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 end
-- Checks if a area between two points is entirely contained by another area -- Checks if a area between two points is entirely contained by another area