diff --git a/api.lua b/api.lua index 1a4026b..38646f9 100644 --- a/api.lua +++ b/api.lua @@ -3,17 +3,48 @@ 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 @@ -52,30 +83,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 diff --git a/internal.lua b/internal.lua index f1b048d..2234cb1 100644 --- a/internal.lua +++ b/internal.lua @@ -18,6 +18,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") @@ -29,6 +46,7 @@ function areas:load() if type(self.areas) ~= "table" then self.areas = {} end + populateStore(self) file:close() end @@ -46,6 +64,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 @@ -73,6 +97,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