summaryrefslogtreecommitdiffstats
path: root/MCServer/Plugins/ProtectionAreas
diff options
context:
space:
mode:
Diffstat (limited to 'MCServer/Plugins/ProtectionAreas')
-rw-r--r--MCServer/Plugins/ProtectionAreas/HookHandlers.lua49
-rw-r--r--MCServer/Plugins/ProtectionAreas/PlayerAreas.lua27
-rw-r--r--MCServer/Plugins/ProtectionAreas/ProtectionAreas.lua3
-rw-r--r--MCServer/Plugins/ProtectionAreas/Storage.lua12
4 files changed, 78 insertions, 13 deletions
diff --git a/MCServer/Plugins/ProtectionAreas/HookHandlers.lua b/MCServer/Plugins/ProtectionAreas/HookHandlers.lua
index 1b22d0ceb..8869775f7 100644
--- a/MCServer/Plugins/ProtectionAreas/HookHandlers.lua
+++ b/MCServer/Plugins/ProtectionAreas/HookHandlers.lua
@@ -6,10 +6,12 @@
+--- Registers all the hooks that the plugin needs to know about
function InitializeHooks(a_Plugin)
local PlgMgr = cRoot:Get():GetPluginManager();
PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_DISCONNECT);
PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_PLAYER_LEFT_CLICK);
+ PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_PLAYER_MOVING);
PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_PLAYER_RIGHT_CLICK);
PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_PLAYER_SPAWNED);
end
@@ -18,6 +20,7 @@ end
+--- Called by MCS when a player's connectino is lost - either they disconnected or timed out
function OnDisconnect(a_Player, a_Reason)
-- Remove the player's cProtectionArea object
-- TODO: What if there are two players with the same name? need to check
@@ -33,6 +36,7 @@ end;
+--- Called by MCS whenever a player enters a world (is spawned)
function OnPlayerSpawned(a_Player)
-- Create a new cPlayerAreas object for this player
if (g_PlayerAreas[a_Player:GetUniqueID()] == nil) then
@@ -46,6 +50,29 @@ end
+--- Called by MCS whenever a player is moving (at most once every tick)
+function OnPlayerMoving(a_Player)
+ local PlayerID = a_Player:GetUniqueID();
+
+ -- If for some reason we don't have a cPlayerAreas object for this player, load it up
+ local PlayerAreas = g_PlayerAreas[PlayerID];
+ if (PlayerAreas == nil) then
+ LoadPlayerAreas(a_Player);
+ return false;
+ end;
+
+ -- If the player is outside their areas' safe space, reload
+ if (not(PlayerAreas:IsInSafe(a_Player:GetPosX(), a_Player:GetPosZ()))) then
+ LoadPlayerAreas(a_Player);
+ end
+ return false;
+end
+
+
+
+
+
+--- Called by MCS when a player left-clicks
function OnPlayerLeftClick(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_Status)
-- If the player has lclked with the wand; regardless of their permissions, let's set the coords:
if (cConfig:IsWand(a_Player:GetEquippedItem())) then
@@ -65,7 +92,8 @@ function OnPlayerLeftClick(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace,
-- Check the player areas to see whether to disable this action
local Areas = g_PlayerAreas[a_Player:GetUniqueID()];
- if not(Areas:CanInteractWithBlock(a_BlockX, a_BlockY, a_BlockZ)) then
+ if not(Areas:CanInteractWithBlock(a_BlockX, a_BlockZ)) then
+ a_Player:SendMessage("You are not allowed to dig here!");
return true;
end
@@ -77,17 +105,19 @@ end
+--- Called by MCS when a player right-clicks
function OnPlayerRightClick(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_Status)
+
+ -- BlockFace < 0 means "use item", for which the coords are not given by the client
+ if (a_BlockFace < 0) then
+ return true;
+ end
+
+ -- Convert the clicked coords into the block space
+ a_BlockX, a_BlockY, a_BlockZ = AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
+
-- If the player has rclked with the wand; regardless of their permissions, let's set the coords
if (cConfig:IsWand(a_Player:GetEquippedItem())) then
- -- BlockFace < 0 means "use item", for which the coords are not given by the client
- if (a_BlockFace < 0) then
- return true;
- end
-
- -- Convert the clicked coords into the block space
- a_BlockX, a_BlockY, a_BlockZ = AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
-
-- Set the coords in the CommandState
GetCommandStateForPlayer(a_Player):SetCoords2(a_BlockX, a_BlockZ);
a_Player:SendMessage("Coords2 set as {" .. a_BlockX .. ", " .. a_BlockZ .."}.");
@@ -97,6 +127,7 @@ function OnPlayerRightClick(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace,
-- Check the player areas to see whether to disable this action
local Areas = g_PlayerAreas[a_Player:GetUniqueID()];
if not(Areas:CanInteractWithBlock(a_BlockX, a_BlockZ)) then
+ a_Player:SendMessage("You are not allowed to build here!");
return true;
end
diff --git a/MCServer/Plugins/ProtectionAreas/PlayerAreas.lua b/MCServer/Plugins/ProtectionAreas/PlayerAreas.lua
index e77d4699f..4ff50d8ad 100644
--- a/MCServer/Plugins/ProtectionAreas/PlayerAreas.lua
+++ b/MCServer/Plugins/ProtectionAreas/PlayerAreas.lua
@@ -9,7 +9,8 @@ The code can then ask each object, whether the player can interact with a certai
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 OOP class implementation follows the PiL 16.1
+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
--]]
@@ -25,10 +26,16 @@ g_PlayerAreas = {};
-function cPlayerAreas:new(obj)
- obj = obj or {};
+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
@@ -46,6 +53,8 @@ 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
@@ -76,6 +85,8 @@ end
-- 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;
@@ -87,3 +98,13 @@ 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
+
+
+
+
diff --git a/MCServer/Plugins/ProtectionAreas/ProtectionAreas.lua b/MCServer/Plugins/ProtectionAreas/ProtectionAreas.lua
index a8219edf7..6e8881b72 100644
--- a/MCServer/Plugins/ProtectionAreas/ProtectionAreas.lua
+++ b/MCServer/Plugins/ProtectionAreas/ProtectionAreas.lua
@@ -12,6 +12,9 @@ PluginPrefix = "ProtectionAreas: ";
--- Bounds for the area loading. Areas less this far in any direction from the player will be loaded into cPlayerAreas
g_AreaBounds = 48;
+--- If a player moves this close to the PlayerAreas bounds, the PlayerAreas will be re-queried
+g_AreaSafeEdge = 12;
+
diff --git a/MCServer/Plugins/ProtectionAreas/Storage.lua b/MCServer/Plugins/ProtectionAreas/Storage.lua
index 10cc469e5..e21b128d5 100644
--- a/MCServer/Plugins/ProtectionAreas/Storage.lua
+++ b/MCServer/Plugins/ProtectionAreas/Storage.lua
@@ -192,7 +192,17 @@ function cStorage:LoadPlayerAreas(a_PlayerName, a_PlayerX, a_PlayerZ, a_WorldNam
local BoundsMinZ = a_PlayerZ - g_AreaBounds;
local BoundsMaxZ = a_PlayerZ + g_AreaBounds;
- local res = cPlayerAreas:new();
+ local res = cPlayerAreas:new(
+ BoundsMinX + g_AreaSafeEdge, BoundsMinZ + g_AreaSafeEdge,
+ BoundsMaxX - g_AreaSafeEdge, BoundsMaxZ - g_AreaSafeEdge
+ );
+
+ --[[
+ LOG("Loading protection areas for player " .. a_PlayerName .. " centered around {" .. a_PlayerX .. ", " .. a_PlayerZ ..
+ "}, bounds are {" .. BoundsMinX .. ", " .. BoundsMinZ .. "} - {" ..
+ BoundsMaxX .. ", " .. BoundsMaxZ .. "}"
+ );
+ --]]
-- Load the areas from the DB, based on the player's location
local sql =