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:
parent
ed06d13b5c
commit
2adf62e22e
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 =
|
||||||
|
Loading…
Reference in New Issue
Block a user