110 lines
2.8 KiB
Lua
110 lines
2.8 KiB
Lua
|
|
-- PlayerAreas.lua
|
|
-- Implements the cPlayerAreas class representing the per-player area storage object
|
|
|
|
--[[
|
|
Each player instance is expected to have a separate object of type cPlayerAreas.
|
|
Each object has an array of {cuboid, IsAllowed} tables, one for each area that is "within reach"
|
|
The code can then ask each object, whether the player can interact with a certain block or not.
|
|
A player can interact with a block if either one of these is true:
|
|
1, There are no areas covering the block
|
|
2, There is at least one area covering the block with IsAllowed set to true
|
|
The object also has a m_SafeCuboid object that specified the area within which the player may move
|
|
without the PlayerAreas needing a re-query.
|
|
|
|
Also, a global table g_PlayerAreas is the actual map of PlayerID -> cPlayerAreas
|
|
--]]
|
|
|
|
|
|
|
|
|
|
cPlayerAreas = {};
|
|
|
|
g_PlayerAreas = {};
|
|
|
|
|
|
|
|
|
|
|
|
function cPlayerAreas:new(a_SafeMinX, a_SafeMinZ, a_SafeMaxX, a_SafeMaxZ)
|
|
assert(a_SafeMinX);
|
|
assert(a_SafeMinZ);
|
|
assert(a_SafeMaxX);
|
|
assert(a_SafeMaxZ);
|
|
|
|
local obj = {};
|
|
setmetatable(obj, self);
|
|
self.__index = self;
|
|
self.m_SafeCuboid = cCuboid(a_SafeMinX, 0, a_SafeMinZ, a_SafeMaxX, 255, a_SafeMaxZ);
|
|
return obj;
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Adds a new cuboid to the area list, where the player is either allowed or not, depending on the IsAllowed param
|
|
function cPlayerAreas:AddArea(a_Cuboid, a_IsAllowed)
|
|
table.insert(self, {m_Cuboid = a_Cuboid, m_IsAllowed = a_IsAllowed});
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
--- returns true if the player owning this object can interact with the specified block
|
|
function cPlayerAreas:CanInteractWithBlock(a_BlockX, a_BlockZ)
|
|
assert(self);
|
|
|
|
-- iterate through all the stored areas:
|
|
local IsInsideAnyArea = false;
|
|
for idx, Area in ipairs(self) do
|
|
if (Area.m_Cuboid:IsInside(a_BlockX, 1, a_BlockZ)) then -- We don't care about Y coords, so use a dummy value
|
|
if (Area.m_IsAllowed) then
|
|
return true;
|
|
end
|
|
-- The coords are inside a cuboid for which the player doesn't have access, take a note of it
|
|
IsInsideAnyArea = true;
|
|
end
|
|
end
|
|
|
|
if (IsInsideAnyArea) then
|
|
-- The specified coords are inside at least one area, but none of them allow the player to interact
|
|
return false;
|
|
end
|
|
|
|
-- The coords are not inside any area
|
|
return cConfig.m_AllowInteractNoArea;
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
--- Calls the specified callback for each area contained within
|
|
-- a_Callback has a signature: function(a_Cuboid, a_IsAllowed)
|
|
-- Returns true if all areas have been enumerated, false if the callback has aborted by returning true
|
|
function cPlayerAreas:ForEachArea(a_Callback)
|
|
assert(self);
|
|
|
|
for idx, Area in ipairs(self) do
|
|
if (a_Callback(Area.m_Cuboid, Area.m_IsAllowed)) then
|
|
return false;
|
|
end
|
|
end
|
|
return true;
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
--- Returns true if the player is withing the safe cuboid (no need to re-query the areas)
|
|
function cPlayerAreas:IsInSafe(a_BlockX, a_BlockZ)
|
|
assert(self);
|
|
return self.m_SafeCuboid:IsInside(a_BlockX, 0, a_BlockZ);
|
|
end
|
|
|
|
|
|
|
|
|