summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/Bindings.cpp77
-rw-r--r--source/Bindings.h2
-rw-r--r--source/Blocks/BlockCarpet.h4
-rw-r--r--source/Blocks/BlockDoubleSlab.h43
-rw-r--r--source/Blocks/BlockHandler.cpp1
-rw-r--r--source/Blocks/BlockSlab.h113
-rw-r--r--source/ClientHandle.cpp91
-rw-r--r--source/ClientHandle.h4
-rw-r--r--source/Entities/Entity.h3
-rw-r--r--source/Entities/Pickup.cpp7
-rw-r--r--source/Entities/Player.cpp6
-rw-r--r--source/Entities/ProjectileEntity.h69
-rw-r--r--source/LeakFinder.cpp4
-rw-r--r--source/LuaState.cpp43
-rw-r--r--source/LuaState.h8
-rw-r--r--source/ManualBindings.cpp154
-rw-r--r--source/OSSupport/IsThread.cpp1
-rw-r--r--source/OSSupport/ListenThread.cpp2
-rw-r--r--source/OSSupport/Socket.cpp4
-rw-r--r--source/Plugin.h7
-rw-r--r--source/PluginLua.cpp723
-rw-r--r--source/PluginLua.h32
-rw-r--r--source/PluginManager.cpp17
-rw-r--r--source/PluginManager.h13
-rw-r--r--source/Protocol/Protocol132.cpp3
-rw-r--r--source/StringUtils.cpp43
-rw-r--r--source/Tracer.cpp4
-rw-r--r--source/World.cpp9
-rw-r--r--source/World.h20
29 files changed, 1164 insertions, 343 deletions
diff --git a/source/Bindings.cpp b/source/Bindings.cpp
index 7d51f7a4e..7bcf81b52 100644
--- a/source/Bindings.cpp
+++ b/source/Bindings.cpp
@@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
-** Generated automatically by tolua++-1.0.92 on 08/19/13 11:57:26.
+** Generated automatically by tolua++-1.0.92 on 08/25/13 15:54:49.
*/
#ifndef __cplusplus
@@ -8545,12 +8545,12 @@ static int tolua_AllToLua_cPlayer_SetFoodExhaustionLevel00(lua_State* tolua_S)
#endif
{
cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0);
- double a_FoodSaturationLevel = ((double) tolua_tonumber(tolua_S,2,0));
+ double a_FoodExhaustionLevel = ((double) tolua_tonumber(tolua_S,2,0));
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetFoodExhaustionLevel'", NULL);
#endif
{
- self->SetFoodExhaustionLevel(a_FoodSaturationLevel);
+ self->SetFoodExhaustionLevel(a_FoodExhaustionLevel);
}
}
return 0;
@@ -9307,41 +9307,6 @@ static int tolua_AllToLua_cPluginManager_ReloadPlugins00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
-/* method: AddHook of class cPluginManager */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_cPluginManager_AddHook00
-static int tolua_AllToLua_cPluginManager_AddHook00(lua_State* tolua_S)
-{
-#ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertype(tolua_S,1,"cPluginManager",0,&tolua_err) ||
- !tolua_isusertype(tolua_S,2,"cPlugin",0,&tolua_err) ||
- !tolua_isnumber(tolua_S,3,0,&tolua_err) ||
- !tolua_isnoobj(tolua_S,4,&tolua_err)
- )
- goto tolua_lerror;
- else
-#endif
- {
- cPluginManager* self = (cPluginManager*) tolua_tousertype(tolua_S,1,0);
- cPlugin* a_Plugin = ((cPlugin*) tolua_tousertype(tolua_S,2,0));
- cPluginManager::PluginHook a_Hook = ((cPluginManager::PluginHook) (int) tolua_tonumber(tolua_S,3,0));
-#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'AddHook'", NULL);
-#endif
- {
- self->AddHook(a_Plugin,a_Hook);
- }
- }
- return 0;
-#ifndef TOLUA_RELEASE
- tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'AddHook'.",&tolua_err);
- return 0;
-#endif
-}
-#endif //#ifndef TOLUA_DISABLE
-
/* method: GetNumPlugins of class cPluginManager */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPluginManager_GetNumPlugins00
static int tolua_AllToLua_cPluginManager_GetNumPlugins00(lua_State* tolua_S)
@@ -11982,6 +11947,38 @@ static int tolua_AllToLua_cWorld_GetName00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* method: GetIniFileName of class cWorld */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_GetIniFileName00
+static int tolua_AllToLua_cWorld_GetIniFileName00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const cWorld",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const cWorld* self = (const cWorld*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetIniFileName'", NULL);
+#endif
+ {
+ const AString tolua_ret = (const AString) self->GetIniFileName();
+ tolua_pushcppstring(tolua_S,(const char*)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'GetIniFileName'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: SaveAllChunks of class cWorld */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_SaveAllChunks00
static int tolua_AllToLua_cWorld_SaveAllChunks00(lua_State* tolua_S)
@@ -28048,11 +28045,12 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_constant(tolua_S,"HOOK_WEATHER_CHANGED",cPluginManager::HOOK_WEATHER_CHANGED);
tolua_constant(tolua_S,"HOOK_WEATHER_CHANGING",cPluginManager::HOOK_WEATHER_CHANGING);
tolua_constant(tolua_S,"HOOK_WORLD_TICK",cPluginManager::HOOK_WORLD_TICK);
+ tolua_constant(tolua_S,"HOOK_NUM_HOOKS",cPluginManager::HOOK_NUM_HOOKS);
+ tolua_constant(tolua_S,"HOOK_MAX",cPluginManager::HOOK_MAX);
tolua_function(tolua_S,"Get",tolua_AllToLua_cPluginManager_Get00);
tolua_function(tolua_S,"GetPlugin",tolua_AllToLua_cPluginManager_GetPlugin00);
tolua_function(tolua_S,"FindPlugins",tolua_AllToLua_cPluginManager_FindPlugins00);
tolua_function(tolua_S,"ReloadPlugins",tolua_AllToLua_cPluginManager_ReloadPlugins00);
- tolua_function(tolua_S,"AddHook",tolua_AllToLua_cPluginManager_AddHook00);
tolua_function(tolua_S,"GetNumPlugins",tolua_AllToLua_cPluginManager_GetNumPlugins00);
tolua_function(tolua_S,"DisablePlugin",tolua_AllToLua_cPluginManager_DisablePlugin00);
tolua_function(tolua_S,"LoadPlugin",tolua_AllToLua_cPluginManager_LoadPlugin00);
@@ -28140,6 +28138,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"GrowSugarcane",tolua_AllToLua_cWorld_GrowSugarcane00);
tolua_function(tolua_S,"GetBiomeAt",tolua_AllToLua_cWorld_GetBiomeAt00);
tolua_function(tolua_S,"GetName",tolua_AllToLua_cWorld_GetName00);
+ tolua_function(tolua_S,"GetIniFileName",tolua_AllToLua_cWorld_GetIniFileName00);
tolua_function(tolua_S,"SaveAllChunks",tolua_AllToLua_cWorld_SaveAllChunks00);
tolua_function(tolua_S,"QueueSaveAllChunks",tolua_AllToLua_cWorld_QueueSaveAllChunks00);
tolua_function(tolua_S,"GetNumChunks",tolua_AllToLua_cWorld_GetNumChunks00);
diff --git a/source/Bindings.h b/source/Bindings.h
index 4dee7f815..97c582582 100644
--- a/source/Bindings.h
+++ b/source/Bindings.h
@@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
-** Generated automatically by tolua++-1.0.92 on 08/19/13 11:57:27.
+** Generated automatically by tolua++-1.0.92 on 08/25/13 15:54:49.
*/
/* Exported function */
diff --git a/source/Blocks/BlockCarpet.h b/source/Blocks/BlockCarpet.h
index 9ac998131..5eafd8c21 100644
--- a/source/Blocks/BlockCarpet.h
+++ b/source/Blocks/BlockCarpet.h
@@ -18,8 +18,8 @@ class cBlockCarpetHandler :
public cBlockHandler
{
public:
- cBlockCarpetHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
+ cBlockCarpetHandler(BLOCKTYPE a_BlockType) :
+ cBlockHandler(a_BlockType)
{
}
diff --git a/source/Blocks/BlockDoubleSlab.h b/source/Blocks/BlockDoubleSlab.h
deleted file mode 100644
index ed6ae9a70..000000000
--- a/source/Blocks/BlockDoubleSlab.h
+++ /dev/null
@@ -1,43 +0,0 @@
-
-#pragma once
-
-#include "BlockHandler.h"
-#include "../Items/ItemHandler.h"
-
-
-
-
-
-class cBlockDoubleSlabHandler :
- public cBlockHandler
-{
-public:
- cBlockDoubleSlabHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
- {
- }
-
-
- virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
- {
- if (m_BlockType == E_BLOCK_DOUBLE_STONE_SLAB)
- {
- m_BlockType = E_BLOCK_STONE_SLAB;
- }
- else
- {
- m_BlockType = E_BLOCK_WOODEN_SLAB;
- }
- a_Pickups.push_back(cItem(m_BlockType, 2, a_BlockMeta));
- }
-
-
- virtual const char * GetStepSound(void) override
- {
- return ((m_BlockType == E_BLOCK_DOUBLE_WOODEN_SLAB) || (m_BlockType == E_BLOCK_DOUBLE_WOODEN_SLAB)) ? "step.wood" : "step.stone";
- }
-} ;
-
-
-
-
diff --git a/source/Blocks/BlockHandler.cpp b/source/Blocks/BlockHandler.cpp
index 22efa25f5..5134c1103 100644
--- a/source/Blocks/BlockHandler.cpp
+++ b/source/Blocks/BlockHandler.cpp
@@ -17,7 +17,6 @@
#include "BlockDeadBush.h"
#include "BlockDirt.h"
#include "BlockDoor.h"
-#include "BlockDoubleSlab.h"
#include "BlockDropSpenser.h"
#include "BlockEnderchest.h"
#include "BlockEntity.h"
diff --git a/source/Blocks/BlockSlab.h b/source/Blocks/BlockSlab.h
index 6caa3a27a..7c1251b28 100644
--- a/source/Blocks/BlockSlab.h
+++ b/source/Blocks/BlockSlab.h
@@ -1,7 +1,17 @@
+// BlockSlab.h
+
+// Declares cBlockSlabHandler and cBlockDoubleSlabHandler classes
+
+
+
+
+
#pragma once
#include "BlockHandler.h"
+#include "../Items/ItemHandler.h"
+
@@ -30,36 +40,26 @@ public:
) override
{
a_BlockType = m_BlockType;
- BLOCKTYPE Type = (BLOCKTYPE)(a_Player->GetEquippedItem().m_ItemType);
+ BLOCKTYPE Type = (BLOCKTYPE) (a_Player->GetEquippedItem().m_ItemType);
NIBBLETYPE Meta = (NIBBLETYPE)(a_Player->GetEquippedItem().m_ItemDamage & 0x07);
- int DoubleType;
- if (Type == E_BLOCK_STONE_SLAB)
- {
- DoubleType = 43; // Make it a double slab (with old type wood)
- }
- else
- {
- DoubleType = 125; // Make it a wooden double slab (new type)
- }
// HandlePlaceBlock wants a cItemHandler pointer thing, so let's give it one
- cItemHandler * ItemHandler = cItemHandler::GetItemHandler(DoubleType);
+ cItemHandler * ItemHandler = cItemHandler::GetItemHandler(GetDoubleSlabType(Type));
- // Check if the block at the coordinates is a slab. Eligibility for combining etc. were processed in ClientHandle
- BLOCKTYPE IsSlab;
- IsSlab = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
- if ((IsSlab == E_BLOCK_STONE_SLAB) || (IsSlab == E_BLOCK_WOODEN_SLAB))
+ // Check if the block at the coordinates is a slab. Eligibility for combining has already been processed in ClientHandle
+ if (IsAnySlabType(a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ)))
{
- // Special handling for non top/bottom clicks
+ // Call the function in ClientHandle that places a block when the client sends the packet,
+ // so that plugins may interfere with the placement.
+
if ((a_BlockFace == BLOCK_FACE_TOP) || (a_BlockFace == BLOCK_FACE_BOTTOM))
{
- // As with previous, call the function in ClientHandle that places a block when the client sends the packet
- // This effectively simulates a client placing a double slab, so it goes through plugins etc. so the slabbing can be cancelled
+ // Top and bottom faces need no parameter modification
a_Player->GetClientHandle()->HandlePlaceBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, *ItemHandler);
}
else
{
- // If player cursor is at top half of block
+ // The other faces need to distinguish between top and bottom cursor positions
if (a_CursorY > 7)
{
// Edit the call to use BLOCK_FACE_BOTTOM, otherwise it places incorrectly
@@ -71,19 +71,23 @@ public:
a_Player->GetClientHandle()->HandlePlaceBlock(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_BOTTOM, a_CursorX, a_CursorY, a_CursorZ, *ItemHandler);
}
}
- return false; // Cancel the event because dblslabs were already placed, nothing else needed
+ return false; // Cancel the event, because dblslabs were already placed, nothing else needed
}
+ // Place the single-slab with correct metas:
switch (a_BlockFace)
{
- // Previous IF condition didn't cancel the event (not a slab at coords), so place slab with correct metas
case BLOCK_FACE_TOP:
{
- a_BlockMeta = Meta & 0x7; break; // Bottom half slab block
+ // Bottom half slab block
+ a_BlockMeta = Meta & 0x7;
+ break;
}
case BLOCK_FACE_BOTTOM:
{
- a_BlockMeta = Meta | 0x8; break; // Top half slab block
+ // Top half slab block
+ a_BlockMeta = Meta | 0x8;
+ break;
}
case BLOCK_FACE_EAST:
case BLOCK_FACE_NORTH:
@@ -107,8 +111,69 @@ public:
virtual const char * GetStepSound(void) override
+ {
+ switch (m_BlockType)
+ {
+ case E_BLOCK_WOODEN_SLAB: return "step.wood";
+ case E_BLOCK_STONE_SLAB: return "step.stone";
+ }
+ ASSERT(!"Unhandled slab type!");
+ return "";
+ }
+
+
+ /// Returns true if the specified blocktype is one of the slabs handled by this handler
+ static bool IsAnySlabType(BLOCKTYPE a_BlockType)
+ {
+ return ((a_BlockType == E_BLOCK_WOODEN_SLAB) || (a_BlockType == E_BLOCK_STONE_SLAB));
+ }
+
+
+ /// Converts the single-slab blocktype to its equivalent double-slab blocktype
+ static BLOCKTYPE GetDoubleSlabType(BLOCKTYPE a_SingleSlabBlockType)
+ {
+ switch (a_SingleSlabBlockType)
+ {
+ case E_BLOCK_STONE_SLAB: return E_BLOCK_DOUBLE_STONE_SLAB;
+ case E_BLOCK_WOODEN_SLAB: return E_BLOCK_DOUBLE_WOODEN_SLAB;
+ }
+ ASSERT(!"Unhandled slab type!");
+ return E_BLOCK_AIR;
+ }
+
+} ;
+
+
+
+
+
+class cBlockDoubleSlabHandler :
+ public cBlockHandler
+{
+public:
+ cBlockDoubleSlabHandler(BLOCKTYPE a_BlockType)
+ : cBlockHandler(a_BlockType)
+ {
+ }
+
+
+ virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
+ {
+ if (m_BlockType == E_BLOCK_DOUBLE_STONE_SLAB)
+ {
+ m_BlockType = E_BLOCK_STONE_SLAB;
+ }
+ else
+ {
+ m_BlockType = E_BLOCK_WOODEN_SLAB;
+ }
+ a_Pickups.push_back(cItem(m_BlockType, 2, a_BlockMeta));
+ }
+
+
+ virtual const char * GetStepSound(void) override
{
- return ((m_BlockType == E_BLOCK_WOODEN_SLAB) || (m_BlockType == E_BLOCK_STONE_SLAB)) ? "step.wood" : "step.stone";
+ return ((m_BlockType == E_BLOCK_DOUBLE_WOODEN_SLAB) || (m_BlockType == E_BLOCK_DOUBLE_WOODEN_SLAB)) ? "step.wood" : "step.stone";
}
} ;
diff --git a/source/ClientHandle.cpp b/source/ClientHandle.cpp
index 199f43014..bed9fab92 100644
--- a/source/ClientHandle.cpp
+++ b/source/ClientHandle.cpp
@@ -19,6 +19,7 @@
#include "OSSupport/Timer.h"
#include "Items/ItemHandler.h"
#include "Blocks/BlockHandler.h"
+#include "Blocks/BlockSlab.h"
#include "Vector3f.h"
#include "Vector3d.h"
@@ -51,6 +52,9 @@ static const int MAX_EXPLOSIONS_PER_TICK = 100;
/// How many explosions in the recent history are allowed
static const int MAX_RUNNING_SUM_EXPLOSIONS = cClientHandle::NUM_CHECK_EXPLOSIONS_TICKS * MAX_EXPLOSIONS_PER_TICK / 8;
+/// How many ticks before the socket is closed after the client is destroyed (#31)
+static const int TICKS_BEFORE_CLOSE = 20;
+
@@ -84,6 +88,7 @@ cClientHandle::cClientHandle(const cSocket * a_Socket, int a_ViewDistance)
, m_bKeepThreadGoing(true)
, m_Ping(1000)
, m_PingID(1)
+ , m_TicksSinceDestruction(0)
, m_State(csConnected)
, m_LastStreamedChunkX(0x7fffffff) // bogus chunk coords to force streaming upon login
, m_LastStreamedChunkZ(0x7fffffff)
@@ -111,7 +116,7 @@ cClientHandle::cClientHandle(const cSocket * a_Socket, int a_ViewDistance)
cClientHandle::~cClientHandle()
{
- ASSERT(m_State == csDestroyed); // Has Destroy() been called?
+ ASSERT(m_State >= csDestroyedWaiting); // Has Destroy() been called?
LOGD("Deleting client \"%s\" at %p", GetUsername().c_str(), this);
@@ -189,7 +194,7 @@ void cClientHandle::Destroy(void)
RemoveFromAllChunks();
m_Player->GetWorld()->RemoveClientFromChunkSender(this);
}
- m_State = csDestroyed;
+ m_State = csDestroyedWaiting;
}
@@ -852,25 +857,24 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, c
BLOCKTYPE EquippedBlock = (BLOCKTYPE)(m_Player->GetEquippedItem().m_ItemType);
NIBBLETYPE EquippedBlockDamage = (NIBBLETYPE)(m_Player->GetEquippedItem().m_ItemDamage);
+ if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height))
+ {
+ // The block is being placed outside the world, ignore this packet altogether (#128)
+ return;
+ }
+
World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, ClickedBlock, ClickedBlockMeta);
- // Special slab handler coding
+ // Special slab handling - placing a slab onto another slab produces a dblslab instead:
if (
- // If clicked face top: is slab there in the "bottom" position?
- // If clicked face bottom: is the slab there in the "top" position?
- // This prevents a dblslab forming below if you click the top face of a "top" slab.
- (((a_BlockFace == BLOCK_FACE_TOP) && (ClickedBlockMeta == (EquippedBlockDamage & 0x07))) || ((a_BlockFace == BLOCK_FACE_BOTTOM) && (ClickedBlockMeta == (EquippedBlockDamage | 0x08)))) &&
-
- // Is clicked a slab? This is a SLAB handler, not stone or something!
- ((ClickedBlock == E_BLOCK_STONE_SLAB) || (ClickedBlock == E_BLOCK_WOODEN_SLAB)) &&
-
- // Is equipped a some type of slab?
- // This prevents a bug where, well, you get a dblslab by placing TNT or something not a slab.
- ((EquippedBlock == E_BLOCK_STONE_SLAB) || (EquippedBlock == E_BLOCK_WOODEN_SLAB)) &&
-
- // Is equipped slab type same as the slab in the world? After all, we can't combine different slabs!
- ((ClickedBlockMeta & 0x07) == (EquippedBlockDamage & 0x07))
+ cBlockSlabHandler::IsAnySlabType(ClickedBlock) && // Is there a slab already?
+ cBlockSlabHandler::IsAnySlabType(EquippedBlock) && // Is the player placing another slab?
+ ((ClickedBlockMeta & 0x07) == (EquippedBlockDamage & 0x07)) && // Is it the same slab type?
+ (
+ (a_BlockFace == BLOCK_FACE_TOP) || // Clicking the top of a bottom slab
+ (a_BlockFace == BLOCK_FACE_BOTTOM) // Clicking the bottom of a top slab
)
+ )
{
// Coordinates at CLICKED block, don't move them anywhere
}
@@ -881,17 +885,26 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, c
if (Handler->DoesIgnoreBuildCollision())
{
Handler->OnDestroyedByPlayer(World, m_Player, a_BlockX, a_BlockY, a_BlockZ);
- //World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
}
- else
+
+ BLOCKTYPE PlaceBlock = World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
+ if (!BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision())
{
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
+ if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height))
+ {
+ // The block is being placed outside the world, ignore this packet altogether (#128)
+ return;
+ }
+
+ BLOCKTYPE PlaceBlock = World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
+
// Clicked on side of block, make sure that placement won't be cancelled if there is a slab able to be double slabbed.
// No need to do combinability (dblslab) checks, client will do that here.
- if ((World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_STONE_SLAB) || (World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_WOODEN_SLAB))
+ if (cBlockSlabHandler::IsAnySlabType(PlaceBlock))
{
- //Is a slab, don't do checks and proceed to double-slabbing
+ // It's a slab, don't do checks and proceed to double-slabbing
}
else
{
@@ -899,13 +912,11 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, c
if ((a_BlockFace == BLOCK_FACE_TOP) && !Handler->DoesAllowBlockOnTop())
{
// Resend the old block
- // Some times the client still places the block O.o
+ // Sometimes the client still places the block O.o
World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
return;
}
-
-
- BLOCKTYPE PlaceBlock = World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
+
if (!BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision())
{
// Tried to place a block *into* another?
@@ -915,7 +926,6 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, c
}
}
}
- // Special slab handler coding end
BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta;
@@ -951,7 +961,7 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, c
NewBlock->OnPlacedByPlayer(World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
// Step sound with 0.8f pitch is used as block placement sound
- World->BroadcastSoundEffect(NewBlock->GetStepSound(),a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 1.0f, 0.8f);
+ World->BroadcastSoundEffect(NewBlock->GetStepSound(), a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 1.0f, 0.8f);
cRoot::Get()->GetPluginManager()->CallHookPlayerPlacedBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
}
@@ -1324,6 +1334,12 @@ void cClientHandle::HandleTabCompletion(const AString & a_Text)
void cClientHandle::SendData(const char * a_Data, int a_Size)
{
+ if (m_HasSentDC)
+ {
+ // This could crash the client, because they've already unloaded the world etc., and suddenly a wild packet appears (#31)
+ return;
+ }
+
{
cCSLock Lock(m_CSOutgoingData);
@@ -1438,6 +1454,17 @@ bool cClientHandle::CheckBlockInteractionsRate(void)
void cClientHandle::Tick(float a_Dt)
{
+ // Handle clients that are waiting for final close while destroyed:
+ if (m_State == csDestroyedWaiting)
+ {
+ m_TicksSinceDestruction += 1; // This field is misused for the timeout counting
+ if (m_TicksSinceDestruction > TICKS_BEFORE_CLOSE)
+ {
+ m_State = csDestroyed;
+ }
+ return;
+ }
+
// Process received network data:
AString IncomingData;
{
@@ -1563,6 +1590,16 @@ void cClientHandle::SendChat(const AString & a_Message)
void cClientHandle::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer)
{
+ ASSERT(m_Player != NULL);
+
+ if ((m_State == csAuthenticated) || (m_State == csDownloadingWorld))
+ {
+ if ((a_ChunkX == m_Player->GetChunkX()) && (a_ChunkZ == m_Player->GetChunkZ()))
+ {
+ m_Protocol->SendPlayerMoveLook();
+ }
+ }
+
// Check chunks being sent, erase them from m_ChunksToSend:
bool Found = false;
{
diff --git a/source/ClientHandle.h b/source/ClientHandle.h
index f1a2dbc3d..9fae93d95 100644
--- a/source/ClientHandle.h
+++ b/source/ClientHandle.h
@@ -257,6 +257,9 @@ private:
int m_LastDigBlockX;
int m_LastDigBlockY;
int m_LastDigBlockZ;
+
+ /// Used while csDestroyedWaiting for counting the ticks until the connection is closed
+ int m_TicksSinceDestruction;
enum eState
{
@@ -267,6 +270,7 @@ private:
csConfirmingPos, ///< The client has been sent the position packet, waiting for them to repeat the position back
csPlaying, ///< Normal gameplay
csDestroying, ///< The client is being destroyed, don't queue any more packets / don't add to chunks
+ csDestroyedWaiting, ///< The client has been destroyed, but is still kept so that the Kick packet is delivered (#31)
csDestroyed, ///< The client has been destroyed, the destructor is to be called from the owner thread
// TODO: Add Kicking here as well
diff --git a/source/Entities/Entity.h b/source/Entities/Entity.h
index 820405cb9..7a070a5dd 100644
--- a/source/Entities/Entity.h
+++ b/source/Entities/Entity.h
@@ -276,9 +276,8 @@ public:
/** Descendants override this function to send a command to the specified client to spawn the entity on the client.
To spawn on all eligible clients, use cChunkMap::BroadcastSpawnEntity()
- Needs to have a default implementation due to Lua bindings.
*/
- virtual void SpawnOn(cClientHandle & a_Client) {ASSERT(!"SpawnOn() unimplemented!"); }
+ virtual void SpawnOn(cClientHandle & a_Client) = 0;
// tolua_begin
diff --git a/source/Entities/Pickup.cpp b/source/Entities/Pickup.cpp
index 0417b861d..c8f36d503 100644
--- a/source/Entities/Pickup.cpp
+++ b/source/Entities/Pickup.cpp
@@ -73,18 +73,19 @@ void cPickup::Tick(float a_Dt, cChunk & a_Chunk)
if (!m_bCollected)
{
int BlockY = (int) floor(GetPosY());
- if (BlockY < cChunkDef::Height) // Don't do anything except for falling when above the world
+ if ((BlockY >= 0) && (BlockY < cChunkDef::Height)) // Don't do anything except for falling when outside the world
{
int BlockX = (int) floor(GetPosX());
int BlockZ = (int) floor(GetPosZ());
- //Position might have changed due to physics. So we have to make sure we have the correct chunk.
+ // Position might have changed due to physics. So we have to make sure we have the correct chunk.
cChunk * CurrentChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ);
if (CurrentChunk != NULL) // Make sure the chunk is loaded
{
int RelBlockX = BlockX - (CurrentChunk->GetPosX() * cChunkDef::Width);
int RelBlockZ = BlockZ - (CurrentChunk->GetPosZ() * cChunkDef::Width);
- BLOCKTYPE BlockBelow = CurrentChunk->GetBlock(RelBlockX, BlockY - 1, RelBlockZ);
+ // If the pickup is on the bottommost block position, make it think the void is made of air: (#131)
+ BLOCKTYPE BlockBelow = (BlockY > 0) ? CurrentChunk->GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR;
BLOCKTYPE BlockIn = CurrentChunk->GetBlock(RelBlockX, BlockY, RelBlockZ);
if (
diff --git a/source/Entities/Player.cpp b/source/Entities/Player.cpp
index 3ccb4ca1d..119afbafc 100644
--- a/source/Entities/Player.cpp
+++ b/source/Entities/Player.cpp
@@ -200,6 +200,12 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
}
}
+ if (!a_Chunk.IsValid())
+ {
+ // This may happen if the cPlayer is created before the chunks have the chance of being loaded / generated (#83)
+ return;
+ }
+
super::Tick(a_Dt, a_Chunk);
// Set player swimming state
diff --git a/source/Entities/ProjectileEntity.h b/source/Entities/ProjectileEntity.h
new file mode 100644
index 000000000..2e050068b
--- /dev/null
+++ b/source/Entities/ProjectileEntity.h
@@ -0,0 +1,69 @@
+
+// ProjectileEntity.h
+
+// Declares the cProjectileEntity class representing the common base class for projectiles
+
+
+
+
+
+#pragma once
+
+#include "Entity.h"
+
+
+
+
+
+// tolua_begin
+
+class cProjectileEntity :
+ public cEntity
+{
+ typedef cEntity super;
+
+public:
+ /// The kind of the projectile. The numbers correspond to the network type ID used for spawning via the 0x17 packet.
+ enum eKind
+ {
+ pkArrow = 60,
+ pkSnowball = 61,
+ pkEgg = 62,
+ pkGhastFireball = 63, // TODO: Unverified TypeID, check this in ProtoProxy
+ pkFireCharge = 64, // TODO: Unverified TypeID, check this in ProtoProxy
+ pkEnderPearl = 65,
+ pkExpBottle = 75,
+ pkSplashPotion = 73,
+ pkWitherSkull = 66,
+ pkFishingFloat = 90,
+ } ;
+
+ cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height);
+ cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height);
+
+ /// Called by the physics blocktracer when the entity hits a solid block, the coords and the face hit is given
+ virtual void OnHitSolidBlock(double a_BlockX, double a_BlockY, double a_BlockZ, char a_BlockFace) {};
+
+protected:
+ eKind m_Kind;
+
+ /// The entity who has created this projectile; may be NULL (e. g. for dispensers)
+ cEntity * m_Creator;
+} ;
+
+
+
+
+
+class cArrowEntity :
+ public cProjectileEntity
+{
+public:
+ cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height);
+ cArrowEntity(cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height);
+} ;
+
+// tolua_end
+
+
+
diff --git a/source/LeakFinder.cpp b/source/LeakFinder.cpp
index 3242bba04..9af259e88 100644
--- a/source/LeakFinder.cpp
+++ b/source/LeakFinder.cpp
@@ -942,10 +942,10 @@ static int MyAllocHook(int nAllocType, void *pvData,
g_CurrentMemUsage += nSize ;
g_pCRTTable->Insert(lRequest, c, nSize);
- if (g_CurrentMemUsage > 1073741824) //This is 1 gb = 1024 * 1024* 1024.
+ if (g_CurrentMemUsage > 1536 * 1024* 1024)
{
printf("******************************************\n");
- printf("** Server reached 1 GiB memory usage, **\n");
+ printf("** Server reached 1.5 GiB memory usage, **\n");
printf("** something is probably wrong. **\n");
printf("** Writing memory dump into memdump.xml **\n");
printf("******************************************\n");
diff --git a/source/LuaState.cpp b/source/LuaState.cpp
index bbf47fb27..8d2fa8eca 100644
--- a/source/LuaState.cpp
+++ b/source/LuaState.cpp
@@ -884,6 +884,49 @@ bool cLuaState::ReportErrors(lua_State * a_LuaState, int a_Status)
+void cLuaState::LogStackTrace(void)
+{
+ LOGWARNING("Stack trace:");
+ lua_Debug entry;
+ int depth = 0;
+ while (lua_getstack(m_LuaState, depth, &entry))
+ {
+ int status = lua_getinfo(m_LuaState, "Sln", &entry);
+ assert(status);
+
+ LOGWARNING(" %s(%d): %s", entry.short_src, entry.currentline, entry.name ? entry.name : "?");
+ depth++;
+ }
+ LOGWARNING("Stack trace end");
+}
+
+
+
+
+
+AString cLuaState::GetTypeText(int a_StackPos)
+{
+ int Type = lua_type(m_LuaState, a_StackPos);
+ switch (Type)
+ {
+ case LUA_TNONE: return "TNONE";
+ case LUA_TNIL: return "TNIL";
+ case LUA_TBOOLEAN: return "TBOOLEAN";
+ case LUA_TLIGHTUSERDATA: return "TLIGHTUSERDATA";
+ case LUA_TNUMBER: return "TNUMBER";
+ case LUA_TSTRING: return "TSTRING";
+ case LUA_TTABLE: return "TTABLE";
+ case LUA_TFUNCTION: return "TFUNCTION";
+ case LUA_TUSERDATA: return "TUSERDATA";
+ case LUA_TTHREAD: return "TTHREAD";
+ }
+ return Printf("Unknown (%d)", Type);
+}
+
+
+
+
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cLuaState::cRef:
diff --git a/source/LuaState.h b/source/LuaState.h
index 0eae8206d..caba2484d 100644
--- a/source/LuaState.h
+++ b/source/LuaState.h
@@ -77,7 +77,7 @@ public:
bool IsValid(void) const {return (m_Ref != LUA_REFNIL); }
/// Allows to use this class wherever an int (i. e. ref) is to be used
- operator int(void) { return m_Ref; }
+ operator int(void) const { return m_Ref; }
protected:
cLuaState & m_LuaState;
@@ -782,6 +782,12 @@ public:
/// If the status is nonzero, prints the text on the top of Lua stack and returns true
static bool ReportErrors(lua_State * a_LuaState, int status);
+ /// Logs all items in the current stack trace to the server console
+ void LogStackTrace(void);
+
+ /// Returns the type of the item on the specified position in the stack
+ AString GetTypeText(int a_StackPos);
+
protected:
lua_State * m_LuaState;
diff --git a/source/ManualBindings.cpp b/source/ManualBindings.cpp
index c975997a5..27c6684f2 100644
--- a/source/ManualBindings.cpp
+++ b/source/ManualBindings.cpp
@@ -755,6 +755,159 @@ static int tolua_cPluginManager_GetAllPlugins(lua_State * tolua_S)
+static int tolua_cPluginManager_AddHook_FnRef(cPluginManager * a_PluginManager, cLuaState & S, int a_ParamIdx)
+{
+ // Helper function for cPluginmanager:AddHook() binding
+ // Takes care of the new case (#121): args are HOOK_TYPE and CallbackFunction
+ // The arg types have already been checked
+
+ // Retrieve the cPlugin from the LuaState:
+ cPluginLua * Plugin = GetLuaPlugin(S);
+ if (Plugin == NULL)
+ {
+ // An error message has been already printed in GetLuaPlugin()
+ return 0;
+ }
+
+ // Retrieve and check the hook type
+ int HookType = (int)tolua_tonumber(S, a_ParamIdx, -1);
+ if (!a_PluginManager->IsValidHookType(HookType))
+ {
+ LOGWARNING("cPluginManager.AddHook(): Invalid HOOK_TYPE parameter: %d", HookType);
+ S.LogStackTrace();
+ return 0;
+ }
+
+ // Add the hook to the plugin
+ if (!Plugin->AddHookRef(HookType, a_ParamIdx + 1))
+ {
+ LOGWARNING("cPluginManager.AddHook(): Cannot add hook %d, unknown error.", HookType);
+ S.LogStackTrace();
+ return 0;
+ }
+ a_PluginManager->AddHook(Plugin, HookType);
+
+ // Success
+ return 0;
+}
+
+
+
+
+
+static int tolua_cPluginManager_AddHook_DefFn(cPluginManager * a_PluginManager, cLuaState & S, int a_ParamIdx)
+{
+ // Helper function for cPluginmanager:AddHook() binding
+ // Takes care of the old case (#121): args are cPluginLua and HOOK_TYPE
+ // The arg types have already been checked
+
+ // Retrieve and check the cPlugin parameter
+ cPluginLua * Plugin = (cPluginLua *)tolua_tousertype(S, a_ParamIdx, NULL);
+ if (Plugin == NULL)
+ {
+ LOGWARNING("cPluginManager.AddHook(): Invalid Plugin parameter, expected a valid cPlugin object. Hook not added");
+ S.LogStackTrace();
+ return 0;
+ }
+ if (Plugin != GetLuaPlugin(S))
+ {
+ // The plugin parameter passed to us is not our stored plugin. Disallow this!
+ LOGWARNING("cPluginManager.AddHook(): Invalid Plugin parameter, cannot add hook to foreign plugins. Hook not added.");
+ S.LogStackTrace();
+ return 0;
+ }
+
+ // Retrieve and check the hook type
+ int HookType = (int)tolua_tonumber(S, a_ParamIdx + 1, -1);
+ if (!a_PluginManager->IsValidHookType(HookType))
+ {
+ LOGWARNING("cPluginManager.AddHook(): Invalid HOOK_TYPE parameter: %d", HookType);
+ S.LogStackTrace();
+ return 0;
+ }
+
+ // Get the standard name for the callback function:
+ const char * FnName = cPluginLua::GetHookFnName(HookType);
+ if (FnName == NULL)
+ {
+ LOGWARNING("cPluginManager.AddHook(): Unknown hook type (%d). Hook not added.", HookType);
+ S.LogStackTrace();
+ return 0;
+ }
+
+ // Retrieve the function to call and add it to the plugin:
+ lua_pushstring(S, FnName);
+ bool res = Plugin->AddHookRef(HookType, 1);
+ lua_pop(S, 1); // Pop the function off the stack
+ if (!res)
+ {
+ LOGWARNING("cPluginManager.AddHook(): Function %s not found. Hook not added.", FnName);
+ S.LogStackTrace();
+ return 0;
+ }
+ a_PluginManager->AddHook(Plugin, HookType);
+
+ // Success
+ return 0;
+}
+
+
+
+
+
+static int tolua_cPluginManager_AddHook(lua_State * tolua_S)
+{
+ /*
+ Function signatures:
+ cPluginManager.AddHook(HOOK_TYPE, CallbackFunction) -- (1) recommended
+ cPluginManager:Get():AddHook(HOOK_TYPE, CallbackFunction) -- (2) accepted silently
+ cPluginManager:Get():AddHook(Plugin, HOOK_TYPE) -- (3) old style (#121), accepted but complained about
+ cPluginManager.AddHook(Plugin, HOOK_TYPE) -- (4) old style (#121) mangled, accepted but complained about
+ */
+
+ cLuaState S(tolua_S);
+ cPluginManager * PlgMgr = cPluginManager::Get();
+
+ // If the first param is a cPluginManager, use it instead of the global one:
+ int ParamIdx = 1;
+ tolua_Error err;
+ if (tolua_isusertype(S, 1, "cPluginManager", 0, &err))
+ {
+ // Style 2 or 3, retrieve the PlgMgr instance
+ PlgMgr = (cPluginManager *)tolua_tousertype(S, 1, NULL);
+ if (PlgMgr == NULL)
+ {
+ LOGWARNING("Malformed plugin, use cPluginManager.AddHook(HOOK_TYPE, CallbackFunction). Fixing the call for you.");
+ S.LogStackTrace();
+ PlgMgr = cPluginManager::Get();
+ }
+ ParamIdx += 1;
+ }
+
+ if (lua_isnumber(S, ParamIdx) && lua_isfunction(S, ParamIdx + 1))
+ {
+ // The next params are a number and a function, assume style 1 or 2
+ return tolua_cPluginManager_AddHook_FnRef(PlgMgr, S, ParamIdx);
+ }
+ else if (tolua_isusertype(S, ParamIdx, "cPlugin", 0, &err) && lua_isnumber(S, ParamIdx + 1))
+ {
+ // The next params are a cPlugin and a number, assume style 3 or 4
+ LOGINFO("cPluginManager.AddHook(): Deprecated format used, use cPluginManager.AddHook(HOOK_TYPE, CallbackFunction) instead. Fixing the call for you.");
+ S.LogStackTrace();
+ return tolua_cPluginManager_AddHook_DefFn(PlgMgr, S, ParamIdx);
+ }
+
+ AString ParamDesc;
+ Printf(ParamDesc, "%s, %s, %s", S.GetTypeText(1).c_str(), S.GetTypeText(2).c_str(), S.GetTypeText(3).c_str());
+ LOGWARNING("cPluginManager.AddHook(): bad parameters. Expected HOOK_TYPE and CallbackFunction, got %s. Hook not added.", ParamDesc.c_str());
+ S.LogStackTrace();
+ return 0;
+}
+
+
+
+
+
static int tolua_cPluginManager_ForEachCommand(lua_State * tolua_S)
{
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
@@ -1699,6 +1852,7 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "ForEachCommand", tolua_cPluginManager_ForEachCommand);
tolua_function(tolua_S, "ForEachConsoleCommand", tolua_cPluginManager_ForEachConsoleCommand);
tolua_function(tolua_S, "GetAllPlugins", tolua_cPluginManager_GetAllPlugins);
+ tolua_function(tolua_S, "AddHook", tolua_cPluginManager_AddHook);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cPlayer");
diff --git a/source/OSSupport/IsThread.cpp b/source/OSSupport/IsThread.cpp
index 45e329a68..1fadb3769 100644
--- a/source/OSSupport/IsThread.cpp
+++ b/source/OSSupport/IsThread.cpp
@@ -147,6 +147,7 @@ bool cIsThread::Wait(void)
int res = pthread_join(m_Handle, NULL);
m_Handle = NULL;
LOGD("Thread %s finished", m_ThreadName.c_str());
+ m_HasStarted = false;
return (res == 0);
#endif // else _WIN32
}
diff --git a/source/OSSupport/ListenThread.cpp b/source/OSSupport/ListenThread.cpp
index c586227df..0890aabc8 100644
--- a/source/OSSupport/ListenThread.cpp
+++ b/source/OSSupport/ListenThread.cpp
@@ -80,7 +80,7 @@ void cListenThread::Stop(void)
super::Wait();
// Close all the listening sockets:
- for (cSockets::iterator itr = m_Sockets.begin(), end = m_Sockets.end(); itr != end; ++itr)
+ for (cSockets::iterator itr = m_Sockets.begin() + 1, end = m_Sockets.end(); itr != end; ++itr)
{
itr->CloseSocket();
} // for itr - m_Sockets[]
diff --git a/source/OSSupport/Socket.cpp b/source/OSSupport/Socket.cpp
index f79bdbf47..48b5d704d 100644
--- a/source/OSSupport/Socket.cpp
+++ b/source/OSSupport/Socket.cpp
@@ -74,11 +74,11 @@ void cSocket::CloseSocket()
if (shutdown(m_Socket, SHUT_RDWR) != 0)//SD_BOTH);
{
- LOGWARN("Error on shutting down socket (%s): %s", m_IPString.c_str(), GetLastErrorString().c_str());
+ LOGWARN("Error on shutting down socket %d (%s): %s", m_Socket, m_IPString.c_str(), GetLastErrorString().c_str());
}
if (close(m_Socket) != 0)
{
- LOGWARN("Error closing socket (%s): %s", m_IPString.c_str(), GetLastErrorString().c_str());
+ LOGWARN("Error closing socket %d (%s): %s", m_Socket, m_IPString.c_str(), GetLastErrorString().c_str());
}
#endif // else _WIN32
diff --git a/source/Plugin.h b/source/Plugin.h
index 2595b9470..be803bab2 100644
--- a/source/Plugin.h
+++ b/source/Plugin.h
@@ -113,13 +113,6 @@ public:
/// All bound console commands are to be removed, do any language-dependent cleanup here
virtual void ClearConsoleCommands(void) {} ;
- /** Called from cPluginManager::AddHook() to check if the hook can be added.
- Plugin API providers may check if the plugin is written correctly (has the hook handler function)
- Returns true if the hook can be added (handler exists)
- Descendants should also log the specific error message as a warning if they return false.
- */
- virtual bool CanAddHook(cPluginManager::PluginHook a_Hook) = 0;
-
// tolua_begin
const AString & GetName(void) const { return m_Name; }
void SetName(const AString & a_Name) { m_Name = a_Name; }
diff --git a/source/PluginLua.cpp b/source/PluginLua.cpp
index 5128ef0b0..81a536838 100644
--- a/source/PluginLua.cpp
+++ b/source/PluginLua.cpp
@@ -36,7 +36,33 @@ cPluginLua::cPluginLua(const AString & a_PluginDirectory) :
cPluginLua::~cPluginLua()
{
cCSLock Lock(m_CriticalSection);
- m_LuaState.Close();
+ Close();
+}
+
+
+
+
+
+void cPluginLua::Close(void)
+{
+ if (m_LuaState.IsValid())
+ {
+ // Release all the references in the hook map:
+ for (cHookMap::iterator itrH = m_HookMap.begin(), endH = m_HookMap.end(); itrH != endH; ++itrH)
+ {
+ for (cLuaRefs::iterator itrR = itrH->second.begin(), endR = itrH->second.end(); itrR != endR; ++itrR)
+ {
+ delete *itrR;
+ } // for itrR - itrH->second[]
+ } // for itrH - m_HookMap[]
+ m_HookMap.clear();
+
+ m_LuaState.Close();
+ }
+ else
+ {
+ ASSERT(m_HookMap.empty());
+ }
}
@@ -70,7 +96,7 @@ bool cPluginLua::Initialize(void)
AString Path = PluginPath + *itr;
if (!m_LuaState.LoadFile(Path))
{
- m_LuaState.Close();
+ Close();
return false;
}
} // for itr - Files[]
@@ -80,14 +106,14 @@ bool cPluginLua::Initialize(void)
if (!m_LuaState.Call("Initialize", this, cLuaState::Return, res))
{
LOGWARNING("Error in plugin %s: Cannot call the Initialize() function. Plugin is temporarily disabled.", GetName().c_str());
- m_LuaState.Close();
+ Close();
return false;
}
if (!res)
{
LOGINFO("Plugin %s: Initialize() call failed, plugin is temporarily disabled.", GetName().c_str());
- m_LuaState.Close();
+ Close();
return false;
}
@@ -115,7 +141,11 @@ void cPluginLua::OnDisable(void)
void cPluginLua::Tick(float a_Dt)
{
cCSLock Lock(m_CriticalSection);
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_TICK), a_Dt);
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_TICK];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), a_Dt);
+ }
}
@@ -126,8 +156,16 @@ bool cPluginLua::OnBlockToPickups(cWorld * a_World, cEntity * a_Digger, int a_Bl
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_BLOCK_TO_PICKUPS), a_World, a_Digger, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, &a_Pickups, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_BLOCK_TO_PICKUPS];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), a_World, a_Digger, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, &a_Pickups, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -138,8 +176,16 @@ bool cPluginLua::OnChat(cPlayer * a_Player, AString & a_Message)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_CHAT), a_Player, a_Message, cLuaState::Return, res, a_Message);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CHAT];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), a_Player, a_Message, cLuaState::Return, res, a_Message);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -150,8 +196,16 @@ bool cPluginLua::OnChunkAvailable(cWorld * a_World, int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_CHUNK_AVAILABLE), a_World, a_ChunkX, a_ChunkZ, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CHUNK_AVAILABLE];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), a_World, a_ChunkX, a_ChunkZ, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -162,8 +216,16 @@ bool cPluginLua::OnChunkGenerated(cWorld * a_World, int a_ChunkX, int a_ChunkZ,
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_CHUNK_GENERATED), a_World, a_ChunkX, a_ChunkZ, a_ChunkDesc, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CHUNK_GENERATED];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), a_World, a_ChunkX, a_ChunkZ, a_ChunkDesc, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -174,8 +236,16 @@ bool cPluginLua::OnChunkGenerating(cWorld * a_World, int a_ChunkX, int a_ChunkZ,
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_CHUNK_GENERATING), a_World, a_ChunkX, a_ChunkZ, a_ChunkDesc, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CHUNK_GENERATING];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), a_World, a_ChunkX, a_ChunkZ, a_ChunkDesc, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -186,8 +256,16 @@ bool cPluginLua::OnChunkUnloaded(cWorld * a_World, int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_CHUNK_UNLOADED), a_World, a_ChunkX, a_ChunkZ, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CHUNK_UNLOADED];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), a_World, a_ChunkX, a_ChunkZ, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -198,8 +276,16 @@ bool cPluginLua::OnChunkUnloading(cWorld * a_World, int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_CHUNK_UNLOADING), a_World, a_ChunkX, a_ChunkZ, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CHUNK_UNLOADING];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), a_World, a_ChunkX, a_ChunkZ, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -210,8 +296,16 @@ bool cPluginLua::OnCollectingPickup(cPlayer * a_Player, cPickup * a_Pickup)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_COLLECTING_PICKUP), a_Player, a_Pickup, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_COLLECTING_PICKUP];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), a_Player, a_Pickup, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -222,8 +316,16 @@ bool cPluginLua::OnCraftingNoRecipe(const cPlayer * a_Player, const cCraftingGri
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_CRAFTING_NO_RECIPE), (cPlayer *)a_Player, a_Grid, a_Recipe, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CRAFTING_NO_RECIPE];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), (cPlayer *)a_Player, a_Grid, a_Recipe, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -234,8 +336,16 @@ bool cPluginLua::OnDisconnect(cPlayer * a_Player, const AString & a_Reason)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_DISCONNECT), a_Player, a_Reason, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_DISCONNECT];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), a_Player, a_Reason, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -246,8 +356,16 @@ bool cPluginLua::OnExecuteCommand(cPlayer * a_Player, const AStringVector & a_Sp
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_EXECUTE_COMMAND), a_Player, a_Split, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_EXECUTE_COMMAND];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), a_Player, a_Split, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -258,26 +376,33 @@ bool cPluginLua::OnExploded(cWorld & a_World, double a_ExplosionSize, bool a_Can
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- const char * FnName = GetHookFnName(cPluginManager::HOOK_EXPLODED);
- switch (a_Source)
- {
- case esOther: m_LuaState.Call(FnName, &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break;
- case esPrimedTNT: m_LuaState.Call(FnName, &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (cTNTEntity *)a_SourceData, cLuaState::Return, res); break;
- case esCreeper: m_LuaState.Call(FnName, &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (cCreeper *)a_SourceData, cLuaState::Return, res); break;
- case esBed: m_LuaState.Call(FnName, &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (Vector3i *)a_SourceData, cLuaState::Return, res); break;
- case esEnderCrystal: m_LuaState.Call(FnName, &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (Vector3i *)a_SourceData, cLuaState::Return, res); break;
- case esGhastFireball: m_LuaState.Call(FnName, &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break;
- case esWitherSkullBlack:
- case esWitherSkullBlue: m_LuaState.Call(FnName, &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break;
- case esWitherBirth: m_LuaState.Call(FnName, &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break;
- case esPlugin: m_LuaState.Call(FnName, &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break;
- default:
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_EXPLODED];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ switch (a_Source)
{
- ASSERT(!"Unhandled ExplosionSource");
- return false;
+ case esOther: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break;
+ case esPrimedTNT: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (cTNTEntity *)a_SourceData, cLuaState::Return, res); break;
+ case esCreeper: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (cCreeper *)a_SourceData, cLuaState::Return, res); break;
+ case esBed: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (Vector3i *)a_SourceData, cLuaState::Return, res); break;
+ case esEnderCrystal: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (Vector3i *)a_SourceData, cLuaState::Return, res); break;
+ case esGhastFireball: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break;
+ case esWitherSkullBlack:
+ case esWitherSkullBlue: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break;
+ case esWitherBirth: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break;
+ case esPlugin: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break;
+ default:
+ {
+ ASSERT(!"Unhandled ExplosionSource");
+ return false;
+ }
+ }
+ if (res)
+ {
+ return true;
}
}
- return res;
+ return false;
}
@@ -288,26 +413,33 @@ bool cPluginLua::OnExploding(cWorld & a_World, double & a_ExplosionSize, bool &
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- const char * FnName = GetHookFnName(cPluginManager::HOOK_EXPLODING);
- switch (a_Source)
- {
- case esOther: m_LuaState.Call(FnName, &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break;
- case esPrimedTNT: m_LuaState.Call(FnName, &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (cTNTEntity *)a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break;
- case esCreeper: m_LuaState.Call(FnName, &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (cCreeper *)a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break;
- case esBed: m_LuaState.Call(FnName, &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (Vector3i *)a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break;
- case esEnderCrystal: m_LuaState.Call(FnName, &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (Vector3i *)a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break;
- case esGhastFireball: m_LuaState.Call(FnName, &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break;
- case esWitherSkullBlack:
- case esWitherSkullBlue: m_LuaState.Call(FnName, &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break;
- case esWitherBirth: m_LuaState.Call(FnName, &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break;
- case esPlugin: m_LuaState.Call(FnName, &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break;
- default:
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_EXPLODING];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ switch (a_Source)
{
- ASSERT(!"Unhandled ExplosionSource");
- return false;
+ case esOther: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break;
+ case esPrimedTNT: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (cTNTEntity *)a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break;
+ case esCreeper: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (cCreeper *)a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break;
+ case esBed: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (Vector3i *)a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break;
+ case esEnderCrystal: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, (Vector3i *)a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break;
+ case esGhastFireball: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break;
+ case esWitherSkullBlack:
+ case esWitherSkullBlue: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break;
+ case esWitherBirth: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break;
+ case esPlugin: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break;
+ default:
+ {
+ ASSERT(!"Unhandled ExplosionSource");
+ return false;
+ }
+ }
+ if (res)
+ {
+ return true;
}
}
- return res;
+ return false;
}
@@ -318,8 +450,16 @@ bool cPluginLua::OnHandshake(cClientHandle * a_Client, const AString & a_Usernam
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_HANDSHAKE), a_Client, a_Username, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_HANDSHAKE];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), a_Client, a_Username, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -330,8 +470,17 @@ bool cPluginLua::OnHopperPullingItem(cWorld & a_World, cHopperEntity & a_Hopper,
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_HOPPER_PULLING_ITEM), &a_World, &a_Hopper, a_DstSlotNum, &a_SrcEntity, a_SrcSlotNum, cLuaState::Return, res);
- return res;
+
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_HOPPER_PULLING_ITEM];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_World, &a_Hopper, a_DstSlotNum, &a_SrcEntity, a_SrcSlotNum, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -342,8 +491,16 @@ bool cPluginLua::OnHopperPushingItem(cWorld & a_World, cHopperEntity & a_Hopper,
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_HOPPER_PUSHING_ITEM), &a_World, &a_Hopper, a_SrcSlotNum, &a_DstEntity, a_DstSlotNum, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_HOPPER_PUSHING_ITEM];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_World, &a_Hopper, a_SrcSlotNum, &a_DstEntity, a_DstSlotNum, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -354,8 +511,16 @@ bool cPluginLua::OnKilling(cEntity & a_Victim, cEntity * a_Killer)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_KILLING), &a_Victim, a_Killer, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_KILLING];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Victim, a_Killer, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -366,8 +531,16 @@ bool cPluginLua::OnLogin(cClientHandle * a_Client, int a_ProtocolVersion, const
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_LOGIN), a_Client, a_ProtocolVersion, a_Username, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_LOGIN];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), a_Client, a_ProtocolVersion, a_Username, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -378,8 +551,16 @@ bool cPluginLua::OnPlayerAnimation(cPlayer & a_Player, int a_Animation)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PLAYER_ANIMATION), &a_Player, a_Animation, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_ANIMATION];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, a_Animation, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -390,8 +571,16 @@ bool cPluginLua::OnPlayerBreakingBlock(cPlayer & a_Player, int a_BlockX, int a_B
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PLAYER_BREAKING_BLOCK), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_BlockType, a_BlockMeta, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_BREAKING_BLOCK];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_BlockType, a_BlockMeta, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -402,8 +591,16 @@ bool cPluginLua::OnPlayerBrokenBlock(cPlayer & a_Player, int a_BlockX, int a_Blo
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PLAYER_BROKEN_BLOCK), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_BlockType, a_BlockMeta, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_BROKEN_BLOCK];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_BlockType, a_BlockMeta, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -414,8 +611,16 @@ bool cPluginLua::OnPlayerEating(cPlayer & a_Player)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PLAYER_EATING), &a_Player, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_EATING];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -426,8 +631,16 @@ bool cPluginLua::OnPlayerJoined(cPlayer & a_Player)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PLAYER_JOINED), &a_Player, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_JOINED];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -438,8 +651,16 @@ bool cPluginLua::OnPlayerLeftClick(cPlayer & a_Player, int a_BlockX, int a_Block
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PLAYER_LEFT_CLICK), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_Status, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_LEFT_CLICK];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_Status, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -450,8 +671,16 @@ bool cPluginLua::OnPlayerMoved(cPlayer & a_Player)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PLAYER_MOVING), &a_Player, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_MOVING];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -462,8 +691,16 @@ bool cPluginLua::OnPlayerPlacedBlock(cPlayer & a_Player, int a_BlockX, int a_Blo
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PLAYER_PLACED_BLOCK), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_PLACED_BLOCK];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -474,8 +711,16 @@ bool cPluginLua::OnPlayerPlacingBlock(cPlayer & a_Player, int a_BlockX, int a_Bl
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PLAYER_PLACING_BLOCK), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_PLACING_BLOCK];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -486,8 +731,16 @@ bool cPluginLua::OnPlayerRightClick(cPlayer & a_Player, int a_BlockX, int a_Bloc
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PLAYER_RIGHT_CLICK), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_RIGHT_CLICK];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -498,8 +751,16 @@ bool cPluginLua::OnPlayerRightClickingEntity(cPlayer & a_Player, cEntity & a_Ent
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PLAYER_RIGHT_CLICKING_ENTITY), &a_Player, &a_Entity, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_RIGHT_CLICKING_ENTITY];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, &a_Entity, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -510,8 +771,16 @@ bool cPluginLua::OnPlayerShooting(cPlayer & a_Player)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PLAYER_SHOOTING), &a_Player, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_SHOOTING];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -522,8 +791,16 @@ bool cPluginLua::OnPlayerSpawned(cPlayer & a_Player)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PLAYER_SPAWNED), &a_Player, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_SPAWNED];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -534,8 +811,16 @@ bool cPluginLua::OnPlayerTossingItem(cPlayer & a_Player)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PLAYER_TOSSING_ITEM), &a_Player, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_TOSSING_ITEM];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -546,8 +831,16 @@ bool cPluginLua::OnPlayerUsedBlock(cPlayer & a_Player, int a_BlockX, int a_Block
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PLAYER_USED_BLOCK), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_USED_BLOCK];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -558,8 +851,16 @@ bool cPluginLua::OnPlayerUsedItem(cPlayer & a_Player, int a_BlockX, int a_BlockY
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PLAYER_USED_ITEM), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_USED_ITEM];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -570,8 +871,16 @@ bool cPluginLua::OnPlayerUsingBlock(cPlayer & a_Player, int a_BlockX, int a_Bloc
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PLAYER_USING_BLOCK), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_USING_BLOCK];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -582,8 +891,16 @@ bool cPluginLua::OnPlayerUsingItem(cPlayer & a_Player, int a_BlockX, int a_Block
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PLAYER_USING_ITEM), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_USING_ITEM];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -594,8 +911,16 @@ bool cPluginLua::OnPostCrafting(const cPlayer * a_Player, const cCraftingGrid *
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_POST_CRAFTING), a_Player, a_Grid, a_Recipe, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_POST_CRAFTING];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), a_Player, a_Grid, a_Recipe, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -606,8 +931,16 @@ bool cPluginLua::OnPreCrafting(const cPlayer * a_Player, const cCraftingGrid * a
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_PRE_CRAFTING), a_Player, a_Grid, a_Recipe, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PRE_CRAFTING];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), a_Player, a_Grid, a_Recipe, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -618,8 +951,16 @@ bool cPluginLua::OnSpawnedEntity(cWorld & a_World, cEntity & a_Entity)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_SPAWNED_ENTITY), &a_World, &a_Entity, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_SPAWNED_ENTITY];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_World, &a_Entity, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -630,8 +971,16 @@ bool cPluginLua::OnSpawnedMonster(cWorld & a_World, cMonster & a_Monster)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_SPAWNED_MONSTER), &a_World, &a_Monster, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_SPAWNED_MONSTER];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_World, &a_Monster, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -642,8 +991,16 @@ bool cPluginLua::OnSpawningEntity(cWorld & a_World, cEntity & a_Entity)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_SPAWNING_ENTITY), &a_World, &a_Entity, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_SPAWNING_ENTITY];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_World, &a_Entity, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -654,8 +1011,16 @@ bool cPluginLua::OnSpawningMonster(cWorld & a_World, cMonster & a_Monster)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_SPAWNING_MONSTER), &a_World, &a_Monster, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_SPAWNING_MONSTER];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_World, &a_Monster, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -666,8 +1031,16 @@ bool cPluginLua::OnTakeDamage(cEntity & a_Receiver, TakeDamageInfo & a_TDI)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_TAKE_DAMAGE), &a_Receiver, &a_TDI, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_TAKE_DAMAGE];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Receiver, &a_TDI, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -683,8 +1056,16 @@ bool cPluginLua::OnUpdatedSign(
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_UPDATED_SIGN), a_World, a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4, a_Player, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_UPDATED_SIGN];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), a_World, a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4, a_Player, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -700,8 +1081,16 @@ bool cPluginLua::OnUpdatingSign(
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_UPDATING_SIGN), a_World, a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4, a_Player, cLuaState::Return, res, a_Line1, a_Line2, a_Line3, a_Line4);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_UPDATING_SIGN];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), a_World, a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4, a_Player, cLuaState::Return, res, a_Line1, a_Line2, a_Line3, a_Line4);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -712,8 +1101,16 @@ bool cPluginLua::OnWeatherChanged(cWorld & a_World)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_WEATHER_CHANGED), &a_World, cLuaState::Return, res);
- return res;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_WEATHER_CHANGED];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_World, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -725,9 +1122,18 @@ bool cPluginLua::OnWeatherChanging(cWorld & a_World, eWeather & a_NewWeather)
cCSLock Lock(m_CriticalSection);
bool res = false;
int NewWeather = a_NewWeather;
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_WEATHER_CHANGING), &a_World, a_NewWeather, cLuaState::Return, res, NewWeather);
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_WEATHER_CHANGING];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_World, NewWeather, cLuaState::Return, res, NewWeather);
+ if (res)
+ {
+ a_NewWeather = (eWeather)NewWeather;
+ return true;
+ }
+ }
a_NewWeather = (eWeather)NewWeather;
- return res;
+ return false;
}
@@ -737,7 +1143,11 @@ bool cPluginLua::OnWeatherChanging(cWorld & a_World, eWeather & a_NewWeather)
bool cPluginLua::OnWorldTick(cWorld & a_World, float a_Dt)
{
cCSLock Lock(m_CriticalSection);
- m_LuaState.Call(GetHookFnName(cPluginManager::HOOK_WORLD_TICK), &a_World, a_Dt);
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_WORLD_TICK];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_World, a_Dt);
+ }
return false;
}
@@ -830,13 +1240,16 @@ void cPluginLua::ClearConsoleCommands(void)
-bool cPluginLua::CanAddHook(cPluginManager::PluginHook a_Hook)
+bool cPluginLua::CanAddOldStyleHook(int a_HookType)
{
- const char * FnName = GetHookFnName(a_Hook);
+ const char * FnName = GetHookFnName(a_HookType);
if (FnName == NULL)
{
// Unknown hook ID
- LOGWARNING("Plugin %s wants to add an unknown hook ID (%d). The plugin need not work properly.", GetName().c_str(), a_Hook);
+ LOGWARNING("Plugin %s wants to add an unknown hook ID (%d). The plugin need not work properly.",
+ GetName().c_str(), a_HookType
+ );
+ m_LuaState.LogStackTrace();
return false;
}
@@ -847,23 +1260,9 @@ bool cPluginLua::CanAddHook(cPluginManager::PluginHook a_Hook)
}
LOGWARNING("Plugin %s wants to add a hook (%d), but it doesn't provide the callback function \"%s\" for it. The plugin need not work properly.",
- GetName().c_str(), a_Hook, FnName
+ GetName().c_str(), a_HookType, FnName
);
-
- // Lua stacktrace:
- LOGWARNING("Stack trace:");
- lua_Debug entry;
- int depth = 0;
- while (lua_getstack(m_LuaState, depth, &entry))
- {
- int status = lua_getinfo(m_LuaState, "Sln", &entry);
- assert(status);
-
- LOGWARNING(" %s(%d): %s", entry.short_src, entry.currentline, entry.name ? entry.name : "?");
- depth++;
- }
- LOGWARNING("Stack trace end");
-
+ m_LuaState.LogStackTrace();
return false;
}
@@ -871,9 +1270,9 @@ bool cPluginLua::CanAddHook(cPluginManager::PluginHook a_Hook)
-const char * cPluginLua::GetHookFnName(cPluginManager::PluginHook a_Hook)
+const char * cPluginLua::GetHookFnName(int a_HookType)
{
- switch (a_Hook)
+ switch (a_HookType)
{
case cPluginManager::HOOK_BLOCK_TO_PICKUPS: return "OnBlockToPickups";
case cPluginManager::HOOK_CHAT: return "OnChat";
@@ -928,6 +1327,28 @@ const char * cPluginLua::GetHookFnName(cPluginManager::PluginHook a_Hook)
+bool cPluginLua::AddHookRef(int a_HookType, int a_FnRefIdx)
+{
+ ASSERT(m_CriticalSection.IsLockedByCurrentThread()); // It probably has to be, how else would we have a LuaState?
+
+ // Check if the function reference is valid:
+ cLuaState::cRef * Ref = new cLuaState::cRef(m_LuaState, a_FnRefIdx);
+ if ((Ref == NULL) || !Ref->IsValid())
+ {
+ LOGWARNING("Plugin %s tried to add a hook %d with bad handler function.", GetName().c_str(), a_HookType);
+ m_LuaState.LogStackTrace();
+ delete Ref;
+ return false;
+ }
+
+ m_HookMap[a_HookType].push_back(Ref);
+ return true;
+}
+
+
+
+
+
AString cPluginLua::HandleWebRequest(const HTTPRequest * a_Request )
{
cCSLock Lock(m_CriticalSection);
diff --git a/source/PluginLua.h b/source/PluginLua.h
index 300fadc8b..fee9c4986 100644
--- a/source/PluginLua.h
+++ b/source/PluginLua.h
@@ -100,7 +100,8 @@ public:
virtual void ClearConsoleCommands(void) override;
- virtual bool CanAddHook(cPluginManager::PluginHook a_Hook) override;
+ /// Returns true if the plugin contains the function for the specified hook type, using the old-style registration (#121)
+ bool CanAddOldStyleHook(int a_HookType);
// cWebPlugin override
virtual const AString GetWebTitle(void) const {return GetName(); }
@@ -128,18 +129,35 @@ public:
/// Calls the plugin-specified "cLuaWindow slot changed" callback.
void CallbackWindowSlotChanged(int a_FnRef, cWindow & a_Window, int a_SlotNum);
-protected:
- cCriticalSection m_CriticalSection;
- cLuaState m_LuaState;
+ /// Returns the name of Lua function that should handle the specified hook type in the older (#121) API
+ static const char * GetHookFnName(int a_HookType);
+ /** Adds a Lua function to be called for the specified hook.
+ The function has to be on the Lua stack at the specified index a_FnRefIdx
+ Returns true if the hook was added successfully.
+ */
+ bool AddHookRef(int a_HookType, int a_FnRefIdx);
+
+protected:
/// Maps command name into Lua function reference
typedef std::map<AString, int> CommandMap;
+ /// Provides an array of Lua function references
+ typedef std::vector<cLuaState::cRef *> cLuaRefs;
+
+ /// Maps hook types into arrays of Lua function references to call for each hook type
+ typedef std::map<int, cLuaRefs> cHookMap;
+
+ cCriticalSection m_CriticalSection;
+ cLuaState m_LuaState;
+
CommandMap m_Commands;
CommandMap m_ConsoleCommands;
-
- /// Returns the name of Lua function that should handle the specified hook
- const char * GetHookFnName(cPluginManager::PluginHook a_Hook);
+
+ cHookMap m_HookMap;
+
+ /// Releases all Lua references and closes the LuaState
+ void Close(void);
} ; // tolua_export
diff --git a/source/PluginManager.cpp b/source/PluginManager.cpp
index e6ff3e6e2..93ee71926 100644
--- a/source/PluginManager.cpp
+++ b/source/PluginManager.cpp
@@ -61,7 +61,7 @@ void cPluginManager::FindPlugins(void)
// First get a clean list of only the currently running plugins, we don't want to mess those up
for (PluginMap::iterator itr = m_Plugins.begin(); itr != m_Plugins.end();)
{
- if( itr->second == NULL )
+ if (itr->second == NULL)
{
PluginMap::iterator thiz = itr;
++thiz;
@@ -1585,6 +1585,15 @@ void cPluginManager::TabCompleteCommand(const AString & a_Text, AStringVector &
+bool cPluginManager::IsValidHookType(int a_HookType)
+{
+ return ((a_HookType >= 0) && (a_HookType <= HOOK_MAX));
+}
+
+
+
+
+
bool cPluginManager::AddPlugin(cPlugin * a_Plugin)
{
m_Plugins[a_Plugin->GetDirectory()] = a_Plugin;
@@ -1603,17 +1612,13 @@ bool cPluginManager::AddPlugin(cPlugin * a_Plugin)
-void cPluginManager::AddHook(cPlugin * a_Plugin, PluginHook a_Hook)
+void cPluginManager::AddHook(cPlugin * a_Plugin, int a_Hook)
{
if (!a_Plugin)
{
LOGWARN("Called cPluginManager::AddHook() with a_Plugin == NULL");
return;
}
- if (!a_Plugin->CanAddHook(a_Hook))
- {
- return;
- }
PluginList & Plugins = m_Hooks[a_Hook];
Plugins.remove(a_Plugin);
Plugins.push_back(a_Plugin);
diff --git a/source/PluginManager.h b/source/PluginManager.h
index 0933d389f..816e4a40c 100644
--- a/source/PluginManager.h
+++ b/source/PluginManager.h
@@ -110,6 +110,10 @@ public: // tolua_export
// Note that if a hook type is added, it may need processing in cPlugin::CanAddHook() descendants,
// and it definitely needs adding in cPluginLua::GetHookFnName() !
+
+ // Keep these two as the last items, they are used for validity checking and get their values automagically
+ HOOK_NUM_HOOKS,
+ HOOK_MAX = HOOK_NUM_HOOKS - 1,
} ;
// tolua_end
@@ -133,7 +137,9 @@ public: // tolua_export
void FindPlugins(); // tolua_export
void ReloadPlugins(); // tolua_export
- void AddHook( cPlugin* a_Plugin, PluginHook a_Hook ); // tolua_export
+
+ /// Adds the plugin to the list of plugins called for the specified hook type. Handles multiple adds as a single add
+ void AddHook(cPlugin * a_Plugin, int a_HookType);
unsigned int GetNumPlugins() const; // tolua_export
@@ -237,6 +243,9 @@ public: // tolua_export
*/
void TabCompleteCommand(const AString & a_Text, AStringVector & a_Results, cPlayer * a_Player);
+ /// Returns true if the specified hook type is within the allowed range
+ static bool IsValidHookType(int a_HookType);
+
private:
friend class cRoot;
@@ -248,7 +257,7 @@ private:
AString m_HelpString;
} ;
- typedef std::map< cPluginManager::PluginHook, cPluginManager::PluginList > HookMap;
+ typedef std::map<int, cPluginManager::PluginList> HookMap;
typedef std::map<AString, cCommandReg> CommandMap;
PluginList m_DisablePluginList;
diff --git a/source/Protocol/Protocol132.cpp b/source/Protocol/Protocol132.cpp
index 2e5c305cc..26a1a9fad 100644
--- a/source/Protocol/Protocol132.cpp
+++ b/source/Protocol/Protocol132.cpp
@@ -340,9 +340,6 @@ void cProtocol132::SendLogin(const cPlayer & a_Player, const cWorld & a_World)
Flush();
SendCompass(a_World);
-
- // Send the initial position (so that confirmation works, FS #245):
- SendPlayerMoveLook();
}
diff --git a/source/StringUtils.cpp b/source/StringUtils.cpp
index 403b10a7c..cb91a4da7 100644
--- a/source/StringUtils.cpp
+++ b/source/StringUtils.cpp
@@ -350,6 +350,33 @@ AString & RawBEToUTF8(short * a_RawData, int a_NumShorts, AString & a_UTF8)
// UTF-8 conversion code adapted from:
// http://stackoverflow.com/questions/2867123/convert-utf-16-to-utf-8-under-windows-and-linux-in-c
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Begin of Unicode, Inc.'s code / information
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+Notice from the original file:
+* Copyright 2001-2004 Unicode, Inc.
+*
+* Disclaimer
+*
+* This source code is provided as is by Unicode, Inc. No claims are
+* made as to fitness for any particular purpose. No warranties of any
+* kind are expressed or implied. The recipient agrees to determine
+* applicability of information provided. If this file has been
+* purchased on magnetic or optical media from Unicode, Inc., the
+* sole remedy for any claim will be exchange of defective media
+* within 90 days of receipt.
+*
+* Limitations on Rights to Redistribute This Code
+*
+* Unicode, Inc. hereby grants the right to freely use the information
+* supplied in this file in the creation of products supporting the
+* Unicode Standard, and to make copies of this file in any form
+* for internal or external distribution as long as this notice
+* remains attached.
+*/
+
#define UNI_MAX_BMP 0x0000FFFF
#define UNI_MAX_UTF16 0x0010FFFF
#define UNI_MAX_UTF32 0x7FFFFFFF
@@ -505,18 +532,24 @@ AString & UTF8ToRawBEUTF16(const char * a_UTF8, size_t a_UTF8Length, AString & a
} while (tmpBytesToRead > 0);
}
- --------------------------------------------------------------------- */
-
+ ---------------------------------------------------------------------
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// End of Unicode, Inc.'s code / information
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-/*
+
+
+
+#define HEX(x) ((x) > 9 ? (x) + 'A' - 10 : (x) + '0')
+
+/**
format binary data this way:
00001234: 31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 1234567890abcdef
*/
-#define HEX(x) ((x) > 9 ? (x) + 'A' - 10 : (x) + '0')
-
AString & CreateHexDump(AString & a_Out, const void * a_Data, int a_Size, int a_LineLength)
{
ASSERT(a_LineLength <= 120); // Due to using a fixed size line buffer; increase line[]'s size to lift this max
diff --git a/source/Tracer.cpp b/source/Tracer.cpp
index 6d37f2ed8..42f1ae5dd 100644
--- a/source/Tracer.cpp
+++ b/source/Tracer.cpp
@@ -133,9 +133,9 @@ void cTracer::SetValues(const Vector3f & a_Start, const Vector3f & a_Direction)
int cTracer::Trace( const Vector3f & a_Start, const Vector3f & a_Direction, int a_Distance)
{
- if (a_Start.y < 0)
+ if ((a_Start.y < 0) || (a_Start.y >= cChunkDef::Height))
{
- LOGD("%s: Start is below the world", __FUNCTION__);
+ LOGD("%s: Start Y is outside the world (%.2f), not tracing.", __FUNCTION__, a_Start.y);
return 0;
}
diff --git a/source/World.cpp b/source/World.cpp
index 053eaedc7..1985f01ec 100644
--- a/source/World.cpp
+++ b/source/World.cpp
@@ -2202,15 +2202,12 @@ cPlayer * cWorld::FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit)
Vector3f Pos = (*itr)->GetPosition();
float Distance = (Pos - a_Pos).Length();
- if (Distance <= a_SightLimit)
+ if (Distance < ClosestDistance)
{
if (!LineOfSight.Trace(a_Pos,(Pos - a_Pos),(int)(Pos - a_Pos).Length()))
{
- if (Distance < ClosestDistance)
- {
- ClosestDistance = Distance;
- ClosestPlayer = *itr;
- }
+ ClosestDistance = Distance;
+ ClosestPlayer = *itr;
}
}
}
diff --git a/source/World.h b/source/World.h
index 8c90b08c4..bcda169bd 100644
--- a/source/World.h
+++ b/source/World.h
@@ -451,22 +451,30 @@ public:
void GrowTreeImage(const sSetBlockVector & a_Blocks);
+ // tolua_begin
+
/// Grows the plant at the specified block to its ripe stage (bonemeal used); returns false if the block is not growable. If a_IsBonemeal is true, block is not grown if not allowed in world.ini
- bool GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsByBonemeal = false); // tolua_export
+ bool GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsByBonemeal = false);
/// Grows a cactus present at the block specified by the amount of blocks specified, up to the max height specified in the config
- void GrowCactus(int a_BlockX, int a_BlockY, int a_BlockZ, int a_NumBlocksToGrow); // tolua_export
+ void GrowCactus(int a_BlockX, int a_BlockY, int a_BlockZ, int a_NumBlocksToGrow);
/// Grows a melon or a pumpkin next to the block specified (assumed to be the stem)
- void GrowMelonPumpkin(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockType); // tolua_export
+ void GrowMelonPumpkin(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockType);
/// Grows a sugarcane present at the block specified by the amount of blocks specified, up to the max height specified in the config
- void GrowSugarcane(int a_BlockX, int a_BlockY, int a_BlockZ, int a_NumBlocksToGrow); // tolua_export
+ void GrowSugarcane(int a_BlockX, int a_BlockY, int a_BlockZ, int a_NumBlocksToGrow);
- int GetBiomeAt (int a_BlockX, int a_BlockZ); // tolua_export
+ /// Returns the biome at the specified coords. Reads the biome from the chunk, if loaded, otherwise uses the world generator to provide the biome value
+ int GetBiomeAt(int a_BlockX, int a_BlockZ);
- const AString & GetName(void) const { return m_WorldName; } // tolua_export
+ /// Returns the name of the world
+ const AString & GetName(void) const { return m_WorldName; }
+
+ /// Returns the name of the world.ini file used by this world
const AString & GetIniFileName(void) const {return m_IniFileName; }
+
+ // tolua_end
inline static void AbsoluteToRelative( int & a_X, int & a_Y, int & a_Z, int & a_ChunkX, int & a_ChunkY, int & a_ChunkZ )
{