From 2adf62e22e1a12a16318431dfe37516a1c945776 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Mon, 10 Jun 2013 07:21:52 +0000 Subject: ProtectionAreas: Implemented reloading areas when a player moves git-svn-id: http://mc-server.googlecode.com/svn/trunk@1575 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- MCServer/Plugins/ProtectionAreas/HookHandlers.lua | 49 ++++++++++++++++++---- MCServer/Plugins/ProtectionAreas/PlayerAreas.lua | 27 ++++++++++-- .../Plugins/ProtectionAreas/ProtectionAreas.lua | 3 ++ MCServer/Plugins/ProtectionAreas/Storage.lua | 12 +++++- 4 files changed, 78 insertions(+), 13 deletions(-) (limited to 'MCServer') 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 = -- cgit v1.2.3