ProtectionAreas: Implemented reloading areas when a player moves
git-svn-id: http://mc-server.googlecode.com/svn/trunk@1575 0a769ca7-a7f5-676a-18bf-c427514a06d6master
parent
ed06d13b5c
commit
2adf62e22e
|
@ -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,9 +105,9 @@ 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)
|
||||
-- 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;
|
||||
|
@ -88,6 +116,8 @@ function OnPlayerRightClick(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace,
|
|||
-- 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
|
||||
-- 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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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 =
|
||||
|
|
Loading…
Reference in New Issue