1
0

ProtectionAreas: Implemented reloading areas when a player moves

git-svn-id: http://mc-server.googlecode.com/svn/trunk@1575 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
madmaxoft@gmail.com 2013-06-10 07:21:52 +00:00
parent ed06d13b5c
commit 2adf62e22e
4 changed files with 78 additions and 13 deletions

View File

@ -6,10 +6,12 @@
--- Registers all the hooks that the plugin needs to know about
function InitializeHooks(a_Plugin) function InitializeHooks(a_Plugin)
local PlgMgr = cRoot:Get():GetPluginManager(); local PlgMgr = cRoot:Get():GetPluginManager();
PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_DISCONNECT); PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_DISCONNECT);
PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_PLAYER_LEFT_CLICK); 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_RIGHT_CLICK);
PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_PLAYER_SPAWNED); PlgMgr:AddHook(a_Plugin, cPluginManager.HOOK_PLAYER_SPAWNED);
end 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) function OnDisconnect(a_Player, a_Reason)
-- Remove the player's cProtectionArea object -- Remove the player's cProtectionArea object
-- TODO: What if there are two players with the same name? need to check -- 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) function OnPlayerSpawned(a_Player)
-- Create a new cPlayerAreas object for this player -- Create a new cPlayerAreas object for this player
if (g_PlayerAreas[a_Player:GetUniqueID()] == nil) then 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) 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 the player has lclked with the wand; regardless of their permissions, let's set the coords:
if (cConfig:IsWand(a_Player:GetEquippedItem())) then 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 -- Check the player areas to see whether to disable this action
local Areas = g_PlayerAreas[a_Player:GetUniqueID()]; 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; return true;
end 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) 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 the player has rclked with the wand; regardless of their permissions, let's set the coords
if (cConfig:IsWand(a_Player:GetEquippedItem())) then 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 -- Set the coords in the CommandState
GetCommandStateForPlayer(a_Player):SetCoords2(a_BlockX, a_BlockZ); GetCommandStateForPlayer(a_Player):SetCoords2(a_BlockX, a_BlockZ);
a_Player:SendMessage("Coords2 set as {" .. 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 -- Check the player areas to see whether to disable this action
local Areas = g_PlayerAreas[a_Player:GetUniqueID()]; local Areas = g_PlayerAreas[a_Player:GetUniqueID()];
if not(Areas:CanInteractWithBlock(a_BlockX, a_BlockZ)) then if not(Areas:CanInteractWithBlock(a_BlockX, a_BlockZ)) then
a_Player:SendMessage("You are not allowed to build here!");
return true; return true;
end end

View File

@ -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: A player can interact with a block if either one of these is true:
1, There are no areas covering the block 1, There are no areas covering the block
2, There is at least one area covering the block with IsAllowed set to true 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 Also, a global table g_PlayerAreas is the actual map of PlayerID -> cPlayerAreas
--]] --]]
@ -25,10 +26,16 @@ g_PlayerAreas = {};
function cPlayerAreas:new(obj) function cPlayerAreas:new(a_SafeMinX, a_SafeMinZ, a_SafeMaxX, a_SafeMaxZ)
obj = obj or {}; assert(a_SafeMinX);
assert(a_SafeMinZ);
assert(a_SafeMaxX);
assert(a_SafeMaxZ);
local obj = {};
setmetatable(obj, self); setmetatable(obj, self);
self.__index = self; self.__index = self;
self.m_SafeCuboid = cCuboid(a_SafeMinX, 0, a_SafeMinZ, a_SafeMaxX, 255, a_SafeMaxZ);
return obj; return obj;
end end
@ -46,6 +53,8 @@ end
--- returns true if the player owning this object can interact with the specified block --- returns true if the player owning this object can interact with the specified block
function cPlayerAreas:CanInteractWithBlock(a_BlockX, a_BlockZ) function cPlayerAreas:CanInteractWithBlock(a_BlockX, a_BlockZ)
assert(self);
-- iterate through all the stored areas: -- iterate through all the stored areas:
local IsInsideAnyArea = false; local IsInsideAnyArea = false;
for idx, Area in ipairs(self) do for idx, Area in ipairs(self) do
@ -76,6 +85,8 @@ end
-- a_Callback has a signature: function(a_Cuboid, a_IsAllowed) -- 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 -- Returns true if all areas have been enumerated, false if the callback has aborted by returning true
function cPlayerAreas:ForEachArea(a_Callback) function cPlayerAreas:ForEachArea(a_Callback)
assert(self);
for idx, Area in ipairs(self) do for idx, Area in ipairs(self) do
if (a_Callback(Area.m_Cuboid, Area.m_IsAllowed)) then if (a_Callback(Area.m_Cuboid, Area.m_IsAllowed)) then
return false; 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

View File

@ -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 --- Bounds for the area loading. Areas less this far in any direction from the player will be loaded into cPlayerAreas
g_AreaBounds = 48; g_AreaBounds = 48;
--- If a player moves this close to the PlayerAreas bounds, the PlayerAreas will be re-queried
g_AreaSafeEdge = 12;

View File

@ -192,7 +192,17 @@ function cStorage:LoadPlayerAreas(a_PlayerName, a_PlayerX, a_PlayerZ, a_WorldNam
local BoundsMinZ = a_PlayerZ - g_AreaBounds; local BoundsMinZ = a_PlayerZ - g_AreaBounds;
local BoundsMaxZ = 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 -- Load the areas from the DB, based on the player's location
local sql = local sql =