From b688ba9be8da66c2df428f0842be4b73092baa81 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 3 Aug 2013 20:05:07 +0200 Subject: [PATCH 01/19] Removed the unused BlockY parameter from cChunkDef::BlockToChunk() --- source/BlockEntities/ChestEntity.cpp | 2 +- source/BlockEntities/HopperEntity.cpp | 2 +- source/ChunkDef.h | 5 ++--- source/ChunkMap.cpp | 26 +++++++++++++------------- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/source/BlockEntities/ChestEntity.cpp b/source/BlockEntities/ChestEntity.cpp index 24d2aef11..d5cd076be 100644 --- a/source/BlockEntities/ChestEntity.cpp +++ b/source/BlockEntities/ChestEntity.cpp @@ -123,7 +123,7 @@ void cChestEntity::UsedBy(cPlayer * a_Player) // We cannot properly detect contents change, but such a change doesn't happen without a player opening the chest first. // The few false positives aren't much to worry about int ChunkX, ChunkZ; - cChunkDef::BlockToChunk(m_PosX, m_PosY, m_PosZ, ChunkX, ChunkZ); + cChunkDef::BlockToChunk(m_PosX, m_PosZ, ChunkX, ChunkZ); m_World->MarkChunkDirty(ChunkX, ChunkZ); } diff --git a/source/BlockEntities/HopperEntity.cpp b/source/BlockEntities/HopperEntity.cpp index 23e4b8096..591db7b4d 100644 --- a/source/BlockEntities/HopperEntity.cpp +++ b/source/BlockEntities/HopperEntity.cpp @@ -125,7 +125,7 @@ void cHopperEntity::UsedBy(cPlayer * a_Player) // We cannot properly detect contents change, but such a change doesn't happen without a player opening the chest first. // The few false positives aren't much to worry about int ChunkX, ChunkZ; - cChunkDef::BlockToChunk(m_PosX, m_PosY, m_PosZ, ChunkX, ChunkZ); + cChunkDef::BlockToChunk(m_PosX, m_PosZ, ChunkX, ChunkZ); m_World->MarkChunkDirty(ChunkX, ChunkZ); } diff --git a/source/ChunkDef.h b/source/ChunkDef.h index 7f9c0ca98..3e78b59b1 100644 --- a/source/ChunkDef.h +++ b/source/ChunkDef.h @@ -137,7 +137,7 @@ public: /// Converts absolute block coords into relative (chunk + block) coords: inline static void AbsoluteToRelative(/* in-out */ int & a_X, int & a_Y, int & a_Z, /* out */ int & a_ChunkX, int & a_ChunkZ ) { - BlockToChunk(a_X, a_Y, a_Z, a_ChunkX, a_ChunkZ); + BlockToChunk(a_X, a_Z, a_ChunkX, a_ChunkZ); a_X = a_X - a_ChunkX * Width; a_Z = a_Z - a_ChunkZ * Width; @@ -145,9 +145,8 @@ public: /// Converts absolute block coords to chunk coords: - inline static void BlockToChunk( int a_X, int a_Y, int a_Z, int & a_ChunkX, int & a_ChunkZ ) + inline static void BlockToChunk(int a_X, int a_Z, int & a_ChunkX, int & a_ChunkZ) { - (void)a_Y; a_ChunkX = a_X / Width; if ((a_X < 0) && (a_X % Width != 0)) { diff --git a/source/ChunkMap.cpp b/source/ChunkMap.cpp index 0db4b898a..9a9e0dcf6 100644 --- a/source/ChunkMap.cpp +++ b/source/ChunkMap.cpp @@ -345,7 +345,7 @@ void cChunkMap::BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, c x = a_BlockX; y = a_BlockY; z = a_BlockZ; - cChunkDef::BlockToChunk(x, y, z, ChunkX, ChunkZ); + cChunkDef::BlockToChunk(x, z, ChunkX, ChunkZ); cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ); if (Chunk == NULL) { @@ -364,7 +364,7 @@ void cChunkMap::BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a cCSLock Lock(m_CSLayers); int ChunkX, ChunkZ; - cChunkDef::BlockToChunk(a_blockX, a_blockY, a_blockZ, ChunkX, ChunkZ); + cChunkDef::BlockToChunk(a_blockX, a_blockZ, ChunkX, ChunkZ); cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ); if (Chunk == NULL) { @@ -382,7 +382,7 @@ void cChunkMap::BroadcastBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, c { cCSLock Lock(m_CSLayers); int ChunkX, ChunkZ; - cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ); + cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ); cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ); if ((Chunk == NULL) || !Chunk->IsValid()) { @@ -592,7 +592,7 @@ void cChunkMap::BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, in cCSLock Lock(m_CSLayers); int ChunkX, ChunkZ; - cChunkDef::BlockToChunk(a_SrcX / 8, a_SrcY / 8, a_SrcZ / 8, ChunkX, ChunkZ); + cChunkDef::BlockToChunk(a_SrcX / 8, a_SrcZ / 8, ChunkX, ChunkZ); cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ); if (Chunk == NULL) { @@ -611,7 +611,7 @@ void cChunkMap::BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_S cCSLock Lock(m_CSLayers); int ChunkX, ChunkZ; - cChunkDef::BlockToChunk(a_SrcX / 8, a_SrcY / 8, a_SrcZ / 8, ChunkX, ChunkZ); + cChunkDef::BlockToChunk(a_SrcX / 8, a_SrcZ / 8, ChunkX, ChunkZ); cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ); if (Chunk == NULL) { @@ -645,7 +645,7 @@ void cChunkMap::BroadcastThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ, c { cCSLock Lock(m_CSLayers); int ChunkX, ChunkZ; - cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ); + cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ); cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ); if (Chunk == NULL) { @@ -664,7 +664,7 @@ void cChunkMap::BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_Bl cCSLock Lock(m_CSLayers); int ChunkX, ChunkZ; - cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ); + cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ); cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ); if (Chunk == NULL) { @@ -682,7 +682,7 @@ void cChunkMap::SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClien { cCSLock Lock(m_CSLayers); int ChunkX, ChunkZ; - cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ); + cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ); cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ); if ((Chunk == NULL) || !Chunk->IsValid()) { @@ -700,7 +700,7 @@ void cChunkMap::UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, i // a_Player rclked block entity at the coords specified, handle it cCSLock Lock(m_CSLayers); int ChunkX, ChunkZ; - cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ); + cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ); cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ); if ((Chunk == NULL) || !Chunk->IsValid()) { @@ -717,7 +717,7 @@ void cChunkMap::WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ) { cCSLock Lock(m_CSLayers); int ChunkX, ChunkZ; - cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ); + cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ); cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ); if ((Chunk == NULL) || !Chunk->IsValid()) { @@ -735,8 +735,8 @@ void cChunkMap::WakeUpSimulatorsInArea(int a_MinBlockX, int a_MaxBlockX, int a_M { cSimulatorManager * SimMgr = m_World->GetSimulatorManager(); int MinChunkX, MinChunkZ, MaxChunkX, MaxChunkZ; - cChunkDef::BlockToChunk(a_MinBlockX, ZERO_CHUNK_Y, a_MinBlockZ, MinChunkX, MinChunkZ); - cChunkDef::BlockToChunk(a_MaxBlockX, ZERO_CHUNK_Y, a_MaxBlockZ, MaxChunkX, MaxChunkZ); + cChunkDef::BlockToChunk(a_MinBlockX, a_MinBlockZ, MinChunkX, MinChunkZ); + cChunkDef::BlockToChunk(a_MaxBlockX, a_MaxBlockZ, MaxChunkX, MaxChunkZ); for (int z = MinChunkZ; z <= MaxChunkZ; z++) { int MinZ = std::max(a_MinBlockZ, z * cChunkDef::Width); @@ -1903,7 +1903,7 @@ bool cChunkMap::SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const ASt { cCSLock Lock(m_CSLayers); int ChunkX, ChunkZ; - cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ); + cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ); cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ); if ((Chunk == NULL) || !Chunk->IsValid()) { From 4f26f11dc77ab032feec8c746fc6ddaa1ea44057 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 3 Aug 2013 20:26:50 +0200 Subject: [PATCH 02/19] Added cWorld::DoWithChunk() function. This will be used by the blocktracers to gain direct access to chunk data. --- source/ChunkMap.cpp | 15 +++++++++++++++ source/ChunkMap.h | 4 ++++ source/World.cpp | 9 +++++++++ source/World.h | 3 +++ 4 files changed, 31 insertions(+) diff --git a/source/ChunkMap.cpp b/source/ChunkMap.cpp index 9a9e0dcf6..0d49ce9c4 100644 --- a/source/ChunkMap.cpp +++ b/source/ChunkMap.cpp @@ -713,6 +713,21 @@ void cChunkMap::UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, i +bool cChunkMap::DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback) +{ + cCSLock Lock(m_CSLayers); + cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ); + if (Chunk == NULL) + { + return false; + } + return a_Callback.Item(Chunk); +} + + + + + void cChunkMap::WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ) { cCSLock Lock(m_CSLayers); diff --git a/source/ChunkMap.h b/source/ChunkMap.h index 899f290c5..183031808 100644 --- a/source/ChunkMap.h +++ b/source/ChunkMap.h @@ -35,6 +35,7 @@ typedef cItemCallback cDispenserCallback; typedef cItemCallback cDropperCallback; typedef cItemCallback cDropSpenserCallback; typedef cItemCallback cFurnaceCallback; +typedef cItemCallback cChunkCallback; @@ -79,6 +80,9 @@ public: /// a_Player rclked block entity at the coords specified, handle it void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z); + /// Calls the callback for the chunk specified, with ChunkMapCS locked; returns false if the chunk doesn't exist, otherwise returns the same value as the callback + bool DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback); + /// Wakes up simulators for the specified block void WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ); diff --git a/source/World.cpp b/source/World.cpp index 880f6e5b2..03e086148 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -832,6 +832,15 @@ bool cWorld::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_ +bool cWorld::DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback) +{ + return m_ChunkMap->DoWithChunk(a_ChunkX, a_ChunkZ, a_Callback); +} + + + + + void cWorld::GrowTree(int a_X, int a_Y, int a_Z) { if (GetBlock(a_X, a_Y, a_Z) == E_BLOCK_SAPLING) diff --git a/source/World.h b/source/World.h index 9de00ceec..52d634769 100644 --- a/source/World.h +++ b/source/World.h @@ -404,6 +404,9 @@ public: /// a_Player is using block entity at [x, y, z], handle that: void UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) {m_ChunkMap->UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ); } + + /// Calls the callback for the chunk specified, with ChunkMapCS locked; returns false if the chunk doesn't exist, otherwise returns the same value as the callback + bool DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback); void GrowTree (int a_BlockX, int a_BlockY, int a_BlockZ); // tolua_export void GrowTreeFromSapling(int a_BlockX, int a_BlockY, int a_BlockZ, char a_SaplingMeta); // tolua_export From 5fe7008966f70de2af53cce7fc13014c220ab721 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 4 Aug 2013 13:25:48 +0200 Subject: [PATCH 03/19] First attempt at implementing a cLineBlockTracer class Not yet tested, will probably have lots of bugs, if it is at all usable. --- VC2008/MCServer.vcproj | 14 +- source/BlockTracer.h | 104 +++++++++++++++ source/LineBlockTracer.cpp | 258 +++++++++++++++++++++++++++++++++++++ source/LineBlockTracer.h | 84 ++++++++++++ 4 files changed, 459 insertions(+), 1 deletion(-) create mode 100644 source/BlockTracer.h create mode 100644 source/LineBlockTracer.cpp create mode 100644 source/LineBlockTracer.h diff --git a/VC2008/MCServer.vcproj b/VC2008/MCServer.vcproj index 6fcd55388..54a694f19 100644 --- a/VC2008/MCServer.vcproj +++ b/VC2008/MCServer.vcproj @@ -1,4 +1,4 @@ - + + + @@ -545,6 +549,14 @@ RelativePath="..\source\LinearUpscale.h" > + + + + diff --git a/source/BlockTracer.h b/source/BlockTracer.h new file mode 100644 index 000000000..4adc61f00 --- /dev/null +++ b/source/BlockTracer.h @@ -0,0 +1,104 @@ + +// BlockTracer.h + +// Declares the classes common for all blocktracers + + + + + +#pragma once + + + + + +// fwd: World.h +class cWorld; + + + + + +class cBlockTracer abstract +{ +public: + /** The callback class is used to notify the caller of individual events that are being traced. + */ + class cCallbacks abstract + { + public: + /** Called on each block encountered along the path, including the first block (path start) + When this callback returns true, the tracing is aborted. + */ + virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0; + + /** Called on each block encountered along the path, including the first block (path start), if chunk data is not loaded + When this callback returns true, the tracing is aborted. + */ + virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ) {} + + /** Called when the path goes out of world, either below (a_BlockY < 0) or above (a_BlockY >= cChunkDef::Height) + The coords specify the exact point at which the path exited the world. + If this callback returns true, the tracing is aborted. + Note that some paths can go out of the world and come back again (parabola), + in such a case this callback is followed by OnIntoWorld() and further OnNextBlock() calls + */ + virtual bool OnOutOfWorld(double a_BlockX, double a_BlockY, double a_BlockZ) {} + + /** Called when the path goes into the world, from either below (a_BlockY < 0) or above (a_BlockY >= cChunkDef::Height) + The coords specify the exact point at which the path entered the world. + If this callback returns true, the tracing is aborted. + Note that some paths can go out of the world and come back again (parabola), + in such a case this callback is followed by further OnNextBlock() calls + */ + virtual bool OnIntoWorld(double a_BlockX, double a_BlockY, double a_BlockZ) {} + + /** Called when the path is sure not to hit any more blocks. + Note that for some shapes this might never happen (line with constant Y) + */ + virtual void OnNoMoreHits(void) {} + + /** Called when the block tracing walks into a chunk that is not allocated. + This usually means that the tracing is aborted. + */ + virtual void OnNoChunk(void) {} + } ; + + + /// Creates the BlockTracer parent with the specified callbacks + cBlockTracer(cWorld & a_World, cCallbacks & a_Callbacks) : + m_World(&a_World), + m_Callbacks(&a_Callbacks) + { + } + + + /// Sets new world, returns the old one. Note that both need to be valid + cWorld & SetWorld(cWorld & a_World) + { + cWorld & Old = *m_World; + m_World = &a_World; + return Old; + } + + + /// Sets new callbacks, returns the old ones. Note that both need to be valid + cCallbacks & SetCallbacks(cCallbacks & a_NewCallbacks) + { + cCallbacks & Old = *m_Callbacks; + m_Callbacks = &a_NewCallbacks; + return Old; + } + +protected: + /// The world upon which to operate + cWorld * m_World; + + /// The callback to use for reporting + cCallbacks * m_Callbacks; +} ; + + + + diff --git a/source/LineBlockTracer.cpp b/source/LineBlockTracer.cpp new file mode 100644 index 000000000..c5939cb78 --- /dev/null +++ b/source/LineBlockTracer.cpp @@ -0,0 +1,258 @@ + +// LineBlockTracer.cpp + +// Implements the cLineBlockTracer class representing a cBlockTracer that traces along a straight line between two points + +#include "Globals.h" +#include "LineBlockTracer.h" +#include "Vector3d.h" +#include "World.h" +#include "Chunk.h" + + + + + + +cLineBlockTracer::cLineBlockTracer(cWorld & a_World, cCallbacks & a_Callbacks) : + super(a_World, a_Callbacks) +{ +} + + + + + +bool cLineBlockTracer::Trace(cWorld & a_World, cBlockTracer::cCallbacks & a_Callbacks, const Vector3d & a_Start, const Vector3d & a_End) +{ + cLineBlockTracer Tracer(a_World, a_Callbacks); + return Tracer.Trace(a_Start.x, a_Start.y, a_Start.z, a_End.x, a_End.y, a_End.z); +} + + + + + +bool cLineBlockTracer::Trace(cWorld & a_World, cBlockTracer::cCallbacks &a_Callbacks, double a_StartX, double a_StartY, double a_StartZ, double a_EndX, double a_EndY, double a_EndZ) +{ + cLineBlockTracer Tracer(a_World, a_Callbacks); + return Tracer.Trace(a_StartX, a_StartY, a_StartZ, a_EndX, a_EndY, a_EndZ); +} + + + + + +bool cLineBlockTracer::Trace(double a_StartX, double a_StartY, double a_StartZ, double a_EndX, double a_EndY, double a_EndZ) +{ + // Initialize the member veriables: + m_StartX = a_StartX; + m_StartY = a_StartY; + m_StartZ = a_StartZ; + m_EndX = a_EndX; + m_EndY = a_EndY; + m_EndZ = a_EndZ; + m_DirX = (m_StartX < m_EndX) ? 1 : -1; + m_DirY = (m_StartY < m_EndY) ? 1 : -1; + m_DirZ = (m_StartZ < m_EndZ) ? 1 : -1; + + // Check the start coords, adjust into the world: + if (m_StartY < 0) + { + if (m_EndY < 0) + { + // Nothing to trace + m_Callbacks->OnNoMoreHits(); + return true; + } + FixStartBelowWorld(); + m_Callbacks->OnIntoWorld(m_StartX, m_StartY, m_StartZ); + } + else if (m_StartY >= cChunkDef::Height) + { + if (m_EndY >= cChunkDef::Height) + { + m_Callbacks->OnNoMoreHits(); + return true; + } + FixStartAboveWorld(); + m_Callbacks->OnIntoWorld(m_StartX, m_StartY, m_StartZ); + } + + m_CurrentX = (int)floor(m_StartX); + m_CurrentY = (int)floor(m_StartY); + m_CurrentZ = (int)floor(m_StartZ); + + m_DiffX = m_EndX - m_StartX; + m_DiffY = m_EndY - m_StartY; + m_DiffZ = m_EndZ - m_StartZ; + + // The actual trace is handled with ChunkMapCS locked by calling our Item() for the specified chunk + int BlockX = (int)floor(m_StartX); + int BlockZ = (int)floor(m_StartZ); + int ChunkX, ChunkZ; + cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ); + return m_World->DoWithChunk(ChunkX, ChunkZ, *this); +} + + + + + +void cLineBlockTracer::FixStartAboveWorld(void) +{ + // We must set the start Y to less than cChunkDef::Height so that it is considered inside the world later on + // Therefore we use an EPS-offset from the height, as small as reasonably possible. + const double Height = (double)cChunkDef::Height - 0.00001; + CalcXZIntersection(Height, m_StartX, m_StartZ); + m_StartY = Height; +} + + + + + +void cLineBlockTracer::FixStartBelowWorld(void) +{ + CalcXZIntersection(0, m_StartX, m_StartZ); + m_StartY = 0; +} + + + + + +void cLineBlockTracer::CalcXZIntersection(double a_Y, double & a_IntersectX, double & a_IntersectZ) +{ + double Ratio = (m_StartY - a_Y) / (m_StartY - m_EndY); + a_IntersectX = m_StartX + (m_EndX - m_StartX) * Ratio; + a_IntersectZ = m_StartZ + (m_EndZ - m_StartZ) * Ratio; +} + + + + + +bool cLineBlockTracer::MoveToNextBlock(void) +{ + // Find out which of the current block's walls gets hit by the path: + static const double EPS = 0.00001; + double Coeff = 1; + enum eDirection + { + dirNONE, + dirX, + dirY, + dirZ, + } Direction = dirNONE; + if (abs(m_DiffX) > EPS) + { + double DestX = (m_DirX > 0) ? (m_CurrentX + 1) : m_CurrentX; + Coeff = (m_EndX - DestX) / m_DiffX; + Direction = dirX; + } + if (abs(m_DiffY) > EPS) + { + double DestY = (m_DirY > 0) ? (m_CurrentY + 1) : m_CurrentY; + double CoeffY = (DestY - m_StartY) / m_DiffY; + if (CoeffY < Coeff) + { + Coeff = CoeffY; + Direction = dirY; + } + } + if (abs(m_DiffZ) > EPS) + { + double DestZ = (m_DirZ > 0) ? (m_CurrentZ + 1) : m_CurrentZ; + double CoeffZ = (DestZ - m_StartZ) / m_DiffZ; + if (CoeffZ < Coeff) + { + Coeff = CoeffZ; + Direction = dirZ; + } + } + + // Based on the wall hit, adjust the current coords + switch (Direction) + { + case dirX: m_CurrentX += m_DirX; break; + case dirY: m_CurrentY += m_DirY; break; + case dirZ: m_CurrentZ += m_DirZ; break; + case dirNONE: return false; + } + return true; +} + + + + + +bool cLineBlockTracer::Item(cChunk * a_Chunk) +{ + ASSERT((m_CurrentY >= 0) && (m_CurrentY < cChunkDef::Height)); // This should be provided by FixStartAboveWorld() / FixStartBelowWorld() + + // This is the actual line tracing loop. + bool Finished = false; + while (true) + { + // Report the current block through the callbacks: + if (a_Chunk == NULL) + { + m_Callbacks->OnNoChunk(); + return false; + } + if (a_Chunk->IsValid()) + { + BLOCKTYPE BlockType; + NIBBLETYPE BlockMeta; + int RelX = FAST_FLOOR_DIV(m_CurrentX, cChunkDef::Width); + int RelZ = FAST_FLOOR_DIV(m_CurrentZ, cChunkDef::Width); + a_Chunk->GetBlockTypeMeta(RelX, m_CurrentY, RelZ, BlockType, BlockMeta); + if (m_Callbacks->OnNextBlock(m_CurrentX, m_CurrentY, m_CurrentZ, BlockType, BlockMeta)) + { + // The callback terminated the trace + return false; + } + } + else + { + if (m_Callbacks->OnNextBlockNoData(m_CurrentX, m_CurrentY, m_CurrentZ)) + { + // The callback terminated the trace + return false; + } + } + + // Move to next block + if (!MoveToNextBlock()) + { + // We've reached the end + m_Callbacks->OnNoMoreHits(); + return true; + } + + // Update the current chunk + if (a_Chunk != NULL) + { + a_Chunk = a_Chunk->GetNeighborChunk(m_CurrentX, m_CurrentZ); + } + + if ((m_CurrentY < 0) || (m_CurrentY >= cChunkDef::Height)) + { + // We've gone out of the world, that's the end of this trace + double IntersectX, IntersectZ; + CalcXZIntersection(m_CurrentY, IntersectX, IntersectZ); + if (m_Callbacks->OnOutOfWorld(IntersectX, m_CurrentY, IntersectZ)) + { + // The callback terminated the trace + return false; + } + m_Callbacks->OnNoMoreHits(); + return true; + } + } +} + + + + diff --git a/source/LineBlockTracer.h b/source/LineBlockTracer.h new file mode 100644 index 000000000..4616cb191 --- /dev/null +++ b/source/LineBlockTracer.h @@ -0,0 +1,84 @@ + +// LineBlockTracer.h + +// Declares the cLineBlockTracer class representing a cBlockTracer that traces along a straight line between two points + + + + + +#pragma once + +#include "BlockTracer.h" + + + + + +// fwd: Chunk.h +class cChunk; + +// fwd: cChunkMap.h +typedef cItemCallback cChunkCallback; + + + + + + +class cLineBlockTracer : + public cBlockTracer, + public cChunkCallback +{ + typedef cBlockTracer super; + +public: + cLineBlockTracer(cWorld & a_World, cCallbacks & a_Callbacks); + + /// Traces one line between Start and End; returns true if the entire line was traced (until OnNoMoreHits()) + bool Trace(double a_StartX, double a_StartY, double a_StartZ, double a_EndX, double a_EndY, double a_EndZ); + + // Utility functions for simple one-line usage: + /// Traces one line between Start and End; returns true if the entire line was traced (until OnNoMoreHits()) + static bool Trace(cWorld & a_World, cCallbacks & a_Callbacks, double a_StartX, double a_StartY, double a_StartZ, double a_EndX, double a_EndY, double a_EndZ); + + /// Traces one line between Start and End; returns true if the entire line was traced (until OnNoMoreHits()) + static bool Trace(cWorld & a_World, cCallbacks & a_Callbacks, const Vector3d & a_Start, const Vector3d & a_End); + +protected: + // The start point of the trace + double m_StartX, m_StartY, m_StartZ; + + // The end point of the trace + double m_EndX, m_EndY, m_EndZ; + + // The difference in coords, End - Start + double m_DiffX, m_DiffY, m_DiffZ; + + // The increment at which the block coords are going from Start to End; either +1 or -1 + int m_DirX, m_DirY, m_DirZ; + + // The current block + int m_CurrentX, m_CurrentY, m_CurrentZ; + + + /// Adjusts the start point above the world to just at the world's top + void FixStartAboveWorld(void); + + /// Adjusts the start point below the world to just at the world's bottom + void FixStartBelowWorld(void); + + /// Calculates the XZ coords of an intersection with the specified Yconst plane; assumes that such an intersection exists + void CalcXZIntersection(double a_Y, double & a_IntersectX, double & a_IntersectZ); + + /// Moves m_Current to the next block on the line; returns false if no move is possible (reached the end) + bool MoveToNextBlock(void); + + // cChunkCallback overrides: + virtual bool Item(cChunk * a_Chunk) override; +} ; + + + + + From b522a9b2621e0e585446065412785b8145e21b49 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 4 Aug 2013 16:05:45 +0200 Subject: [PATCH 04/19] Ignoring all .ini files in the MCServer folder. Only the .example.ini files are supposed to be in the repository and they must be added specifically by name (git add -f ). All the other .ini files are considered instance-specific and are not to be put into the repo. --- MCServer/.gitignore | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/MCServer/.gitignore b/MCServer/.gitignore index 62225e137..ca10d90e8 100644 --- a/MCServer/.gitignore +++ b/MCServer/.gitignore @@ -1,11 +1,8 @@ *.exe -ChunkWorx.ini -ChunkWorxSave.ini +*.ini MCServer -banned.ini logs players -whitelist.ini world* API.txt *.dat @@ -15,9 +12,6 @@ schematics *.pdb memdump.xml *.grab -ProtectionAreas.ini ProtectionAreas.sqlite helgrind.log -settings.ini -webadmin.ini motd.txt From 6af81c66e9aea6ecc5913266815e7e468872dee4 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 4 Aug 2013 16:06:28 +0200 Subject: [PATCH 05/19] cItem: Removed a warning emitted when creating an item from air --- source/Item.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/Item.h b/source/Item.h index fc54da51d..fee861050 100644 --- a/source/Item.h +++ b/source/Item.h @@ -55,7 +55,10 @@ public: { if (!IsValidItem(m_ItemType)) { - LOGWARNING("%s: creating an invalid item type (%d), resetting to empty.", __FUNCTION__, a_ItemType); + if (m_ItemType != E_BLOCK_AIR) + { + LOGWARNING("%s: creating an invalid item type (%d), resetting to empty.", __FUNCTION__, a_ItemType); + } Empty(); } } From 654714e7bc34b61d01202e3f87adc2fa60baeeab Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 4 Aug 2013 16:07:15 +0200 Subject: [PATCH 06/19] LineBlockTracer: Fixed initial errors --- source/BlockTracer.h | 6 +++--- source/LineBlockTracer.cpp | 11 +++++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/source/BlockTracer.h b/source/BlockTracer.h index 4adc61f00..6d67f1052 100644 --- a/source/BlockTracer.h +++ b/source/BlockTracer.h @@ -36,7 +36,7 @@ public: /** Called on each block encountered along the path, including the first block (path start), if chunk data is not loaded When this callback returns true, the tracing is aborted. */ - virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ) {} + virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ) { return false; } /** Called when the path goes out of world, either below (a_BlockY < 0) or above (a_BlockY >= cChunkDef::Height) The coords specify the exact point at which the path exited the world. @@ -44,7 +44,7 @@ public: Note that some paths can go out of the world and come back again (parabola), in such a case this callback is followed by OnIntoWorld() and further OnNextBlock() calls */ - virtual bool OnOutOfWorld(double a_BlockX, double a_BlockY, double a_BlockZ) {} + virtual bool OnOutOfWorld(double a_BlockX, double a_BlockY, double a_BlockZ) { return false; } /** Called when the path goes into the world, from either below (a_BlockY < 0) or above (a_BlockY >= cChunkDef::Height) The coords specify the exact point at which the path entered the world. @@ -52,7 +52,7 @@ public: Note that some paths can go out of the world and come back again (parabola), in such a case this callback is followed by further OnNextBlock() calls */ - virtual bool OnIntoWorld(double a_BlockX, double a_BlockY, double a_BlockZ) {} + virtual bool OnIntoWorld(double a_BlockX, double a_BlockY, double a_BlockZ) { return false; } /** Called when the path is sure not to hit any more blocks. Note that for some shapes this might never happen (line with constant Y) diff --git a/source/LineBlockTracer.cpp b/source/LineBlockTracer.cpp index c5939cb78..03464314a 100644 --- a/source/LineBlockTracer.cpp +++ b/source/LineBlockTracer.cpp @@ -148,8 +148,11 @@ bool cLineBlockTracer::MoveToNextBlock(void) if (abs(m_DiffX) > EPS) { double DestX = (m_DirX > 0) ? (m_CurrentX + 1) : m_CurrentX; - Coeff = (m_EndX - DestX) / m_DiffX; - Direction = dirX; + Coeff = (DestX - m_StartX) / m_DiffX; + if (Coeff <= 1) + { + Direction = dirX; + } } if (abs(m_DiffY) > EPS) { @@ -205,8 +208,8 @@ bool cLineBlockTracer::Item(cChunk * a_Chunk) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; - int RelX = FAST_FLOOR_DIV(m_CurrentX, cChunkDef::Width); - int RelZ = FAST_FLOOR_DIV(m_CurrentZ, cChunkDef::Width); + int RelX = m_CurrentX - a_Chunk->GetPosX() * cChunkDef::Width; + int RelZ = m_CurrentZ - a_Chunk->GetPosZ() * cChunkDef::Width; a_Chunk->GetBlockTypeMeta(RelX, m_CurrentY, RelZ, BlockType, BlockMeta); if (m_Callbacks->OnNextBlock(m_CurrentX, m_CurrentY, m_CurrentZ, BlockType, BlockMeta)) { From e21ed58d5fbf901e10cf829bba0fb3d1c9952f7b Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 4 Aug 2013 16:08:09 +0200 Subject: [PATCH 07/19] cWorld: Added a self-test for LineBlockTracer, disabled by an #ifdef. --- source/World.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/source/World.cpp b/source/World.cpp index 03e086148..1ff5a5970 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -59,6 +59,9 @@ #include "tolua++.h" +// DEBUG: Test out the cLineBlockTracer class by tracing a few lines: +#include "LineBlockTracer.h" + #ifndef _WIN32 #include #endif @@ -442,6 +445,60 @@ void cWorld::InitializeSpawn(void) // TODO: Better spawn detection - move spawn out of the water if it isn't set in the INI already m_SpawnY = (double)GetHeight((int)m_SpawnX, (int)m_SpawnZ) + 1.6f; // +1.6f eye height + + + #ifdef TEST_LINEBLOCKTRACER + // DEBUG: Test out the cLineBlockTracer class by tracing a few lines: + class cTracerCallbacks : + public cBlockTracer::cCallbacks + { + virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override + { + LOGD("Block {%d, %d, %d}: %d:%d (%s)", + a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, + ItemToString(cItem(a_BlockType, 1, a_BlockMeta)).c_str() + ); + return false; + } + + virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ) override + { + LOGD("Block {%d, %d, %d}: no data available", + a_BlockX, a_BlockY, a_BlockZ + ); + return false; + } + + virtual bool OnOutOfWorld(double a_BlockX, double a_BlockY, double a_BlockZ) override + { + LOGD("Out of world at {%f, %f, %f}", a_BlockX, a_BlockY, a_BlockZ); + return false; + } + + virtual bool OnIntoWorld(double a_BlockX, double a_BlockY, double a_BlockZ) override + { + LOGD("Into world at {%f, %f, %f}", a_BlockX, a_BlockY, a_BlockZ); + return false; + } + + virtual void OnNoMoreHits(void) override + { + LOGD("No more hits"); + } + } Callbacks; + LOGD("Spawn is at {%f, %f, %f}", m_SpawnX, m_SpawnY, m_SpawnZ); + LOGD("Tracing a line along +X:"); + cLineBlockTracer::Trace(*this, Callbacks, m_SpawnX - 10, m_SpawnY, m_SpawnZ, m_SpawnX + 10, m_SpawnY, m_SpawnZ); + LOGD("Tracing a line along -Z:"); + cLineBlockTracer::Trace(*this, Callbacks, m_SpawnX, m_SpawnY, m_SpawnZ + 10, m_SpawnX, m_SpawnY, m_SpawnZ - 10); + LOGD("Tracing a line along -Y, out of world:"); + cLineBlockTracer::Trace(*this, Callbacks, m_SpawnX, 260, m_SpawnZ, m_SpawnX, -5, m_SpawnZ); + LOGD("Tracing a line along XY:"); + cLineBlockTracer::Trace(*this, Callbacks, m_SpawnX - 10, m_SpawnY - 10, m_SpawnZ, m_SpawnX + 10, m_SpawnY + 10, m_SpawnZ); + LOGD("Tracing a line in generic direction:"); + cLineBlockTracer::Trace(*this, Callbacks, m_SpawnX - 15, m_SpawnY - 5, m_SpawnZ + 7.5, m_SpawnX + 13, m_SpawnY - 10, m_SpawnZ + 8.5); + LOGD("Tracing tests done"); + #endif // TEST_LINEBLOCKTRACER } From 71bb41ee86e262103909d8007dbc2ef876cd0b24 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 4 Aug 2013 23:11:25 +0200 Subject: [PATCH 08/19] LuaState refactoring: initial part. The cLuaState class is a wrapper for the lua_State * and for the common functions on it. The cPlugin_NewLua has been rewritten to use it instead of the raw pointer. Part of #33 --- VC2008/MCServer.vcproj | 8 + source/LuaState.cpp | 218 ++++++++++++++++++++++++ source/LuaState.h | 90 ++++++++++ source/ManualBindings.cpp | 19 ++- source/Plugin_NewLua.cpp | 350 +++++++++++++------------------------- source/Plugin_NewLua.h | 11 +- 6 files changed, 447 insertions(+), 249 deletions(-) create mode 100644 source/LuaState.cpp create mode 100644 source/LuaState.h diff --git a/VC2008/MCServer.vcproj b/VC2008/MCServer.vcproj index 54a694f19..8755fb2e8 100644 --- a/VC2008/MCServer.vcproj +++ b/VC2008/MCServer.vcproj @@ -1497,6 +1497,14 @@ RelativePath="..\source\LuaScript.h" > + + + + diff --git a/source/LuaState.cpp b/source/LuaState.cpp new file mode 100644 index 000000000..da86a4b20 --- /dev/null +++ b/source/LuaState.cpp @@ -0,0 +1,218 @@ + +// LuaState.cpp + +// Implements the cLuaState class representing the wrapper over lua_State *, provides associated helper functions + +#include "Globals.h" +#include "LuaState.h" + +extern "C" +{ + #include "lualib.h" +} + +#include "tolua++.h" +#include "Bindings.h" +#include "ManualBindings.h" + +// fwd: SQLite/lsqlite3.c +extern "C" +{ + LUALIB_API int luaopen_lsqlite3(lua_State * L); +} + +// fwd: LuaExpat/lxplib.c: +extern "C" +{ + int luaopen_lxp(lua_State * L); +} + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cLuaState: + +cLuaState::cLuaState(const AString & a_SubsystemName) : + m_LuaState(NULL), + m_SubsystemName(a_SubsystemName) +{ +} + + + + + +cLuaState::~cLuaState() +{ + if (IsValid()) + { + Close(); + } +} + + + + + +void cLuaState::Create(void) +{ + if (m_LuaState != NULL) + { + LOGWARNING("%s: Trying to create an already-existing LuaState, ignoring.", __FUNCTION__); + return; + } + m_LuaState = lua_open(); + luaL_openlibs(m_LuaState); + tolua_AllToLua_open(m_LuaState); + ManualBindings::Bind(m_LuaState); + luaopen_lsqlite3(m_LuaState); + luaopen_lxp(m_LuaState); +} + + + + + +void cLuaState::Close(void) +{ + if (m_LuaState == NULL) + { + LOGWARNING("%s: Trying to close an invalid LuaState, ignoring.", __FUNCTION__); + return; + } + lua_close(m_LuaState); + m_LuaState = NULL; +} + + + + + +bool cLuaState::LoadFile(const AString & a_FileName) +{ + ASSERT(IsValid()); + + // Load the file: + int s = luaL_loadfile(m_LuaState, a_FileName.c_str()); + if (ReportErrors(s)) + { + LOGWARNING("Can't load %s because of an error in file %s", m_SubsystemName.c_str(), a_FileName.c_str()); + return false; + } + + // Execute the globals: + s = lua_pcall(m_LuaState, 0, LUA_MULTRET, 0); + if (ReportErrors(s)) + { + LOGWARNING("Error in %s in file %s", m_SubsystemName.c_str(), a_FileName.c_str()); + return false; + } + + return true; +} + + + + + +bool cLuaState::PushFunction(const char * a_FunctionName, bool a_ShouldLogFailure /* = true */) +{ + if (!IsValid()) + { + // This happens if cPlugin::Initialize() fails with an error + return false; + } + + lua_getglobal(m_LuaState, a_FunctionName); + if (!lua_isfunction(m_LuaState, -1)) + { + if (a_ShouldLogFailure) + { + LOGWARNING("Error in %s: Could not find function %s()", m_SubsystemName.c_str(), a_FunctionName); + } + lua_pop(m_LuaState, 1); + return false; + } + return true; +} + + + + + +bool cLuaState::PushFunctionFromRegistry(int a_FnRef) +{ + lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_FnRef); // same as lua_getref() + if (!lua_isfunction(m_LuaState, -1)) + { + lua_pop(m_LuaState, 1); + return false; + } + return true; +} + + + + + +void cLuaState::PushStringVector(const AStringVector & a_Vector) +{ + lua_createtable(m_LuaState, a_Vector.size(), 0); + int newTable = lua_gettop(m_LuaState); + int index = 1; + for (AStringVector::const_iterator itr = a_Vector.begin(), end = a_Vector.end(); itr != end; ++itr, ++index) + { + tolua_pushstring(m_LuaState, itr->c_str()); + lua_rawseti(m_LuaState, newTable, index); + } +} + + + + + +bool cLuaState::CallFunction(int a_NumArgs, int a_NumResults, const char * a_FunctionName) +{ + ASSERT(lua_isfunction(m_LuaState, -a_NumArgs - 1)); + + int s = lua_pcall(m_LuaState, a_NumArgs, a_NumResults, 0); + if (ReportErrors(s)) + { + LOGWARNING("Error in %s calling function %s()", m_SubsystemName.c_str(), a_FunctionName); + return false; + } + return true; +} + + + + + +bool cLuaState::ReportErrors(int a_Status) +{ + return ReportErrors(m_LuaState, a_Status); +} + + + + + +bool cLuaState::ReportErrors(lua_State * a_LuaState, int a_Status) +{ + if (a_Status == 0) + { + // No error to report + return false; + } + + LOGWARNING("LUA: %d - %s", a_Status, lua_tostring(a_LuaState, -1)); + lua_pop(a_LuaState, 1); + return true; +} + + + + diff --git a/source/LuaState.h b/source/LuaState.h new file mode 100644 index 000000000..10ff53911 --- /dev/null +++ b/source/LuaState.h @@ -0,0 +1,90 @@ + +// LuaState.h + +// Declares the cLuaState class representing the wrapper over lua_State *, provides associated helper functions + + + + + +#pragma once + + + + + +// fwd: lua.h +struct lua_State; + + + + + +class cLuaState +{ +public: + /** Creates a new instance. The LuaState is not initialized. + a_SubsystemName is used for reporting problems in the console, it is "plugin %s" for plugins, + or "LuaScript" for the cLuaScript template + */ + cLuaState(const AString & a_SubsystemName); + + ~cLuaState(); + + operator lua_State * (void) { return m_LuaState; } + + /// Creates the m_LuaState, if not closed already + void Create(void); + + /// Closes the m_LuaState, if not closed already + void Close(void); + + /// Returns true if the m_LuaState is valid + bool IsValid(void) const { return (m_LuaState != NULL); } + + /** Loads the specified file + Returns false and logs a warning to the console if not successful (but the LuaState is kept open). + m_SubsystemName is displayed in the warning log message. + */ + bool LoadFile(const AString & a_FileName); + + /** Pushes the function of the specified name onto the stack. + Returns true if successful. + If a_ShouldLogFail is true, logs a warning on failure (incl. m_SubsystemName) + */ + bool PushFunction(const char * a_FunctionName, bool a_ShouldLogFailure = true); + + /** Pushes a function that has been saved into the global registry, identified by a_FnRef. + Returns true if successful. Logs a warning on failure + */ + bool PushFunctionFromRegistry(int a_FnRef); + + /// Pushes a string vector, as a table, onto the stack + void PushStringVector(const AStringVector & a_Vector); + + /** + Calls the function that has been pushed onto the stack by PushFunction. + Returns true if successful, logs a warning on failure. + a_FunctionName is used only for the warning log message, the function + to be called must be pushed by PushFunction() beforehand. + */ + bool CallFunction(int a_NumArgs, int a_NumResults, const char * a_FunctionName); + + /// If the status is nonzero, prints the text on the top of Lua stack and returns true + bool ReportErrors(int status); + + /// 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); + +protected: + lua_State * m_LuaState; + + /** The subsystem name is used for reporting errors to the console, it is either "plugin %s" or "LuaScript" + whatever is given to the constructor + */ + AString m_SubsystemName; +} ; + + + + diff --git a/source/ManualBindings.cpp b/source/ManualBindings.cpp index 7a13d94c0..403ad21d5 100644 --- a/source/ManualBindings.cpp +++ b/source/ManualBindings.cpp @@ -19,13 +19,14 @@ #include "BlockEntities/FurnaceEntity.h" #include "md5/md5.h" #include "LuaWindow.h" +#include "LuaState.h" // fwd: LuaCommandBinder.cpp -bool report_errors(lua_State* lua, int status); +// bool cLuaState::ReportErrors(lua_State* lua, int status); @@ -233,7 +234,7 @@ static int tolua_DoWith(lua_State* tolua_S) } int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0); - if (report_errors(LuaState, s)) + if (cLuaState::ReportErrors(LuaState, s)) { return true; // Abort enumeration } @@ -328,7 +329,7 @@ static int tolua_DoWithXYZ(lua_State* tolua_S) } int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0); - if (report_errors(LuaState, s)) + if (cLuaState::ReportErrors(LuaState, s)) { return true; // Abort enumeration } @@ -421,7 +422,7 @@ static int tolua_ForEachInChunk(lua_State* tolua_S) } int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0); - if (report_errors(LuaState, s)) + if (cLuaState::ReportErrors(LuaState, s)) { return true; /* Abort enumeration */ } @@ -512,7 +513,7 @@ static int tolua_ForEach(lua_State * tolua_S) } int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0); - if (report_errors(LuaState, s)) + if (cLuaState::ReportErrors(LuaState, s)) { return true; /* Abort enumeration */ } @@ -677,7 +678,7 @@ static int tolua_cPluginManager_ForEachCommand(lua_State * tolua_S) tolua_pushcppstring(LuaState, a_HelpString); int s = lua_pcall(LuaState, 3, 1, 0); - if (report_errors(LuaState, s)) + if (cLuaState::ReportErrors(LuaState, s)) { return true; /* Abort enumeration */ } @@ -751,7 +752,7 @@ static int tolua_cPluginManager_ForEachConsoleCommand(lua_State * tolua_S) tolua_pushcppstring(LuaState, a_HelpString); int s = lua_pcall(LuaState, 2, 1, 0); - if (report_errors(LuaState, s)) + if (cLuaState::ReportErrors(LuaState, s)) { return true; /* Abort enumeration */ } @@ -1171,8 +1172,8 @@ static int tolua_cPlugin_Call(lua_State* tolua_S) return 0; } - int s = lua_pcall(targetState, top-2, LUA_MULTRET, 0); - if( report_errors( targetState, s ) ) + int s = lua_pcall(targetState, top - 2, LUA_MULTRET, 0); + if (cLuaState::ReportErrors(targetState, s)) { LOGWARN("Error while calling function '%s' in plugin '%s'", funcName.c_str(), self->GetName().c_str() ); return 0; diff --git a/source/Plugin_NewLua.cpp b/source/Plugin_NewLua.cpp index 8b0f047cd..51d16c839 100644 --- a/source/Plugin_NewLua.cpp +++ b/source/Plugin_NewLua.cpp @@ -7,45 +7,10 @@ extern "C" { -#include "lualib.h" + #include "lualib.h" } #include "tolua++.h" -#include "Bindings.h" -#include "ManualBindings.h" - - - - - -// fwd: SQLite/lsqlite3.c -extern "C" -{ - LUALIB_API int luaopen_lsqlite3(lua_State * L); -} - -// fwd: LuaExpat/lxplib.c: -extern "C" -{ - int luaopen_lxp(lua_State * L); -} - - - - - -bool report_errors(lua_State * lua, int status) -{ - if (status == 0) - { - // No error to report - return false; - } - - LOGERROR("LUA: %s", lua_tostring(lua, -1)); - lua_pop(lua, 1); - return true; -} @@ -54,10 +19,9 @@ bool report_errors(lua_State * lua, int status) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cPlugin_NewLua: -cPlugin_NewLua::cPlugin_NewLua(const AString & a_PluginDirectory) - : m_LuaState( 0 ) - , cWebPlugin() - , cPlugin(a_PluginDirectory) +cPlugin_NewLua::cPlugin_NewLua(const AString & a_PluginDirectory) : + cPlugin(a_PluginDirectory), + m_LuaState(Printf("plugin %s", GetName().c_str())) { } @@ -68,12 +32,7 @@ cPlugin_NewLua::cPlugin_NewLua(const AString & a_PluginDirectory) cPlugin_NewLua::~cPlugin_NewLua() { cCSLock Lock(m_CriticalSection); - - if( m_LuaState ) - { - lua_close( m_LuaState ); - m_LuaState = 0; - } + m_LuaState.Close(); } @@ -83,14 +42,9 @@ cPlugin_NewLua::~cPlugin_NewLua() bool cPlugin_NewLua::Initialize(void) { cCSLock Lock(m_CriticalSection); - if (m_LuaState == NULL) + if (!m_LuaState.IsValid()) { - m_LuaState = lua_open(); - luaL_openlibs(m_LuaState); - tolua_AllToLua_open(m_LuaState); - ManualBindings::Bind(m_LuaState); - luaopen_lsqlite3(m_LuaState); - luaopen_lxp(m_LuaState); + m_LuaState.Create(); // Inject the identification global variables into the state: lua_pushlightuserdata(m_LuaState, this); @@ -110,47 +64,32 @@ bool cPlugin_NewLua::Initialize(void) continue; } AString Path = PluginPath + *itr; - int s = luaL_loadfile(m_LuaState, Path.c_str() ); - if( report_errors( m_LuaState, s ) ) + if (!m_LuaState.LoadFile(Path)) { - LOGERROR("Can't load plugin %s because of an error in file %s", GetLocalDirectory().c_str(), Path.c_str() ); - lua_close( m_LuaState ); - m_LuaState = 0; - return false; - } - - s = lua_pcall(m_LuaState, 0, LUA_MULTRET, 0); - if( report_errors( m_LuaState, s ) ) - { - LOGERROR("Error in plugin %s in file %s", GetLocalDirectory().c_str(), Path.c_str() ); - lua_close( m_LuaState ); - m_LuaState = 0; + m_LuaState.Close(); return false; } } // for itr - Files[] // Call intialize function - if (!PushFunction("Initialize")) + if (!m_LuaState.PushFunction("Initialize")) { - lua_close( m_LuaState ); - m_LuaState = 0; + m_LuaState.Close(); return false; } tolua_pushusertype(m_LuaState, this, "cPlugin_NewLua"); - if (!CallFunction(1, 1, "Initialize")) + if (!m_LuaState.CallFunction(1, 1, "Initialize")) { - lua_close( m_LuaState ); - m_LuaState = 0; + m_LuaState.Close(); return false; } - if( !lua_isboolean( m_LuaState, -1 ) ) + if (!lua_isboolean(m_LuaState, -1)) { - LOGWARN("Error in plugin %s Initialize() must return a boolean value!", GetLocalDirectory().c_str() ); - lua_close( m_LuaState ); - m_LuaState = 0; + LOGWARNING("Error in plugin %s: Initialize() must return a boolean value!", GetName().c_str()); + m_LuaState.Close(); return false; } @@ -165,12 +104,12 @@ bool cPlugin_NewLua::Initialize(void) void cPlugin_NewLua::OnDisable() { cCSLock Lock(m_CriticalSection); - if (!PushFunction("OnDisable", false)) // false = don't log error if not found + if (!m_LuaState.PushFunction("OnDisable", false)) // false = don't log error if not found { return; } - CallFunction(0, 0, "OnDisable"); + m_LuaState.CallFunction(0, 0, "OnDisable"); } @@ -181,14 +120,14 @@ void cPlugin_NewLua::Tick(float a_Dt) { cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_TICK); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return; } tolua_pushnumber( m_LuaState, a_Dt ); - CallFunction(1, 0, FnName); + m_LuaState.CallFunction(1, 0, FnName); } @@ -200,7 +139,7 @@ bool cPlugin_NewLua::OnBlockToPickups(cWorld * a_World, cEntity * a_Digger, int cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_BLOCK_TO_PICKUPS); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -214,7 +153,7 @@ bool cPlugin_NewLua::OnBlockToPickups(cWorld * a_World, cEntity * a_Digger, int tolua_pushnumber (m_LuaState, a_BlockMeta); tolua_pushusertype(m_LuaState, &a_Pickups, "cItems"); - if (!CallFunction(8, 1, FnName)) + if (!m_LuaState.CallFunction(8, 1, FnName)) { return false; } @@ -233,7 +172,7 @@ bool cPlugin_NewLua::OnChat(cPlayer * a_Player, AString & a_Message) cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_CHAT); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -241,7 +180,7 @@ bool cPlugin_NewLua::OnChat(cPlayer * a_Player, AString & a_Message) tolua_pushusertype(m_LuaState, a_Player, "cPlayer"); tolua_pushstring (m_LuaState, a_Message.c_str()); - if (!CallFunction(2, 2, FnName)) + if (!m_LuaState.CallFunction(2, 2, FnName)) { return false; } @@ -264,7 +203,7 @@ bool cPlugin_NewLua::OnChunkAvailable(cWorld * a_World, int a_ChunkX, int a_Chun cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_CHUNK_AVAILABLE); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -273,7 +212,7 @@ bool cPlugin_NewLua::OnChunkAvailable(cWorld * a_World, int a_ChunkX, int a_Chun tolua_pushnumber (m_LuaState, a_ChunkX); tolua_pushnumber (m_LuaState, a_ChunkZ); - if (!CallFunction(3, 1, FnName)) + if (!m_LuaState.CallFunction(3, 1, FnName)) { return false; } @@ -292,7 +231,7 @@ bool cPlugin_NewLua::OnChunkGenerated(cWorld * a_World, int a_ChunkX, int a_Chun cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_CHUNK_GENERATED); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -302,7 +241,7 @@ bool cPlugin_NewLua::OnChunkGenerated(cWorld * a_World, int a_ChunkX, int a_Chun tolua_pushnumber (m_LuaState, a_ChunkZ); tolua_pushusertype(m_LuaState, a_ChunkDesc, "cChunkDesc"); - if (!CallFunction(4, 1, FnName)) + if (!m_LuaState.CallFunction(4, 1, FnName)) { return false; } @@ -321,7 +260,7 @@ bool cPlugin_NewLua::OnChunkGenerating(cWorld * a_World, int a_ChunkX, int a_Chu cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_CHUNK_GENERATING); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -331,7 +270,7 @@ bool cPlugin_NewLua::OnChunkGenerating(cWorld * a_World, int a_ChunkX, int a_Chu tolua_pushnumber (m_LuaState, a_ChunkZ); tolua_pushusertype(m_LuaState, a_pLuaChunk, "cChunkDesc"); - if (!CallFunction(4, 1, FnName)) + if (!m_LuaState.CallFunction(4, 1, FnName)) { return false; } @@ -350,7 +289,7 @@ bool cPlugin_NewLua::OnChunkUnloaded(cWorld * a_World, int a_ChunkX, int a_Chunk cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_CHUNK_UNLOADED); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -359,7 +298,7 @@ bool cPlugin_NewLua::OnChunkUnloaded(cWorld * a_World, int a_ChunkX, int a_Chunk tolua_pushnumber (m_LuaState, a_ChunkX); tolua_pushnumber (m_LuaState, a_ChunkZ); - if (!CallFunction(3, 1, FnName)) + if (!m_LuaState.CallFunction(3, 1, FnName)) { return false; } @@ -378,7 +317,7 @@ bool cPlugin_NewLua::OnChunkUnloading(cWorld * a_World, int a_ChunkX, int a_Chun cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_CHUNK_UNLOADING); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -387,7 +326,7 @@ bool cPlugin_NewLua::OnChunkUnloading(cWorld * a_World, int a_ChunkX, int a_Chun tolua_pushnumber (m_LuaState, a_ChunkX); tolua_pushnumber (m_LuaState, a_ChunkZ); - if (!CallFunction(3, 1, FnName)) + if (!m_LuaState.CallFunction(3, 1, FnName)) { return false; } @@ -406,7 +345,7 @@ bool cPlugin_NewLua::OnCollectingPickup(cPlayer * a_Player, cPickup * a_Pickup) cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_COLLECTING_PICKUP); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -414,7 +353,7 @@ bool cPlugin_NewLua::OnCollectingPickup(cPlayer * a_Player, cPickup * a_Pickup) tolua_pushusertype(m_LuaState, a_Player, "cPlayer"); tolua_pushusertype(m_LuaState, a_Pickup, "cPickup"); - if (!CallFunction(2, 1, FnName)) + if (!m_LuaState.CallFunction(2, 1, FnName)) { return false; } @@ -433,7 +372,7 @@ bool cPlugin_NewLua::OnCraftingNoRecipe(const cPlayer * a_Player, const cCraftin cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_CRAFTING_NO_RECIPE); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -442,7 +381,7 @@ bool cPlugin_NewLua::OnCraftingNoRecipe(const cPlayer * a_Player, const cCraftin tolua_pushusertype(m_LuaState, (void *)a_Grid, "cCraftingGrid"); tolua_pushusertype(m_LuaState, (void *)a_Recipe, "cCraftingRecipe"); - if (!CallFunction(3, 1, FnName)) + if (!m_LuaState.CallFunction(3, 1, FnName)) { return false; } @@ -461,7 +400,7 @@ bool cPlugin_NewLua::OnDisconnect(cPlayer * a_Player, const AString & a_Reason) cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_DISCONNECT); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -469,7 +408,7 @@ bool cPlugin_NewLua::OnDisconnect(cPlayer * a_Player, const AString & a_Reason) tolua_pushusertype(m_LuaState, a_Player, "cPlayer"); tolua_pushstring (m_LuaState, a_Reason.c_str()); - if (!CallFunction(2, 1, FnName)) + if (!m_LuaState.CallFunction(2, 1, FnName)) { return false; } @@ -488,7 +427,7 @@ bool cPlugin_NewLua::OnExecuteCommand(cPlayer * a_Player, const AStringVector & cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_EXECUTE_COMMAND); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -508,7 +447,7 @@ bool cPlugin_NewLua::OnExecuteCommand(cPlayer * a_Player, const AStringVector & ++index; } - if (!CallFunction(2, 1, FnName)) + if (!m_LuaState.CallFunction(2, 1, FnName)) { return false; } @@ -527,7 +466,7 @@ bool cPlugin_NewLua::OnHandshake(cClientHandle * a_Client, const AString & a_Use cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_HANDSHAKE); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -535,7 +474,7 @@ bool cPlugin_NewLua::OnHandshake(cClientHandle * a_Client, const AString & a_Use tolua_pushusertype(m_LuaState, a_Client, "cClientHandle"); tolua_pushstring (m_LuaState, a_Username.c_str()); - if (!CallFunction(2, 1, FnName)) + if (!m_LuaState.CallFunction(2, 1, FnName)) { return false; } @@ -554,7 +493,7 @@ bool cPlugin_NewLua::OnKilling(cEntity & a_Victim, cEntity * a_Killer) cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_KILLING); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -562,7 +501,7 @@ bool cPlugin_NewLua::OnKilling(cEntity & a_Victim, cEntity * a_Killer) tolua_pushusertype(m_LuaState, &a_Victim, "cEntity"); tolua_pushusertype(m_LuaState, a_Killer, "cEntity"); - if (!CallFunction(2, 1, FnName)) + if (!m_LuaState.CallFunction(2, 1, FnName)) { return false; } @@ -581,7 +520,7 @@ bool cPlugin_NewLua::OnLogin(cClientHandle * a_Client, int a_ProtocolVersion, co cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_LOGIN); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -590,7 +529,7 @@ bool cPlugin_NewLua::OnLogin(cClientHandle * a_Client, int a_ProtocolVersion, co tolua_pushnumber (m_LuaState, a_ProtocolVersion); tolua_pushcppstring(m_LuaState, a_Username); - if (!CallFunction(3, 1, FnName)) + if (!m_LuaState.CallFunction(3, 1, FnName)) { return false; } @@ -609,7 +548,7 @@ bool cPlugin_NewLua::OnPlayerBreakingBlock(cPlayer & a_Player, int a_BlockX, int cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_BREAKING_BLOCK); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -622,7 +561,7 @@ bool cPlugin_NewLua::OnPlayerBreakingBlock(cPlayer & a_Player, int a_BlockX, int tolua_pushnumber (m_LuaState, a_BlockType); tolua_pushnumber (m_LuaState, a_BlockMeta); - if (!CallFunction(7, 1, FnName)) + if (!m_LuaState.CallFunction(7, 1, FnName)) { return false; } @@ -641,7 +580,7 @@ bool cPlugin_NewLua::OnPlayerBrokenBlock(cPlayer & a_Player, int a_BlockX, int a cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_BROKEN_BLOCK); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -654,7 +593,7 @@ bool cPlugin_NewLua::OnPlayerBrokenBlock(cPlayer & a_Player, int a_BlockX, int a tolua_pushnumber (m_LuaState, a_BlockType); tolua_pushnumber (m_LuaState, a_BlockMeta); - if (!CallFunction(7, 1, FnName)) + if (!m_LuaState.CallFunction(7, 1, FnName)) { return false; } @@ -673,14 +612,14 @@ bool cPlugin_NewLua::OnPlayerEating(cPlayer & a_Player) cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_EATING); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); - if (!CallFunction(1, 1, FnName)) + if (!m_LuaState.CallFunction(1, 1, FnName)) { return false; } @@ -699,14 +638,14 @@ bool cPlugin_NewLua::OnPlayerJoined(cPlayer & a_Player) cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_JOINED); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); - if (!CallFunction(1, 1, FnName)) + if (!m_LuaState.CallFunction(1, 1, FnName)) { return false; } @@ -725,7 +664,7 @@ bool cPlugin_NewLua::OnPlayerLeftClick(cPlayer & a_Player, int a_BlockX, int a_B cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_LEFT_CLICK); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -737,7 +676,7 @@ bool cPlugin_NewLua::OnPlayerLeftClick(cPlayer & a_Player, int a_BlockX, int a_B tolua_pushnumber (m_LuaState, a_BlockFace); tolua_pushnumber (m_LuaState, a_Status); - if (!CallFunction(6, 1, FnName)) + if (!m_LuaState.CallFunction(6, 1, FnName)) { return false; } @@ -756,14 +695,14 @@ bool cPlugin_NewLua::OnPlayerMoved(cPlayer & a_Player) cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_MOVING); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); - if (!CallFunction(1, 1, FnName)) + if (!m_LuaState.CallFunction(1, 1, FnName)) { return false; } @@ -782,7 +721,7 @@ bool cPlugin_NewLua::OnPlayerPlacedBlock(cPlayer & a_Player, int a_BlockX, int a cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_PLACED_BLOCK); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -798,7 +737,7 @@ bool cPlugin_NewLua::OnPlayerPlacedBlock(cPlayer & a_Player, int a_BlockX, int a tolua_pushnumber (m_LuaState, a_BlockType); tolua_pushnumber (m_LuaState, a_BlockMeta); - if (!CallFunction(10, 1, FnName)) + if (!m_LuaState.CallFunction(10, 1, FnName)) { return false; } @@ -817,7 +756,7 @@ bool cPlugin_NewLua::OnPlayerPlacingBlock(cPlayer & a_Player, int a_BlockX, int cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_PLACING_BLOCK); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -833,7 +772,7 @@ bool cPlugin_NewLua::OnPlayerPlacingBlock(cPlayer & a_Player, int a_BlockX, int tolua_pushnumber (m_LuaState, a_BlockType); tolua_pushnumber (m_LuaState, a_BlockMeta); - if (!CallFunction(10, 1, FnName)) + if (!m_LuaState.CallFunction(10, 1, FnName)) { return false; } @@ -852,7 +791,7 @@ bool cPlugin_NewLua::OnPlayerRightClick(cPlayer & a_Player, int a_BlockX, int a_ cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_RIGHT_CLICK); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -866,7 +805,7 @@ bool cPlugin_NewLua::OnPlayerRightClick(cPlayer & a_Player, int a_BlockX, int a_ tolua_pushnumber (m_LuaState, a_CursorY); tolua_pushnumber (m_LuaState, a_CursorZ); - if (!CallFunction(8, 1, FnName)) + if (!m_LuaState.CallFunction(8, 1, FnName)) { return false; } @@ -885,7 +824,7 @@ bool cPlugin_NewLua::OnPlayerRightClickingEntity(cPlayer & a_Player, cEntity & a cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_RIGHT_CLICKING_ENTITY); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -893,7 +832,7 @@ bool cPlugin_NewLua::OnPlayerRightClickingEntity(cPlayer & a_Player, cEntity & a tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); tolua_pushusertype(m_LuaState, &a_Entity, "cEntity"); - if (!CallFunction(2, 1, FnName)) + if (!m_LuaState.CallFunction(2, 1, FnName)) { return false; } @@ -912,14 +851,14 @@ bool cPlugin_NewLua::OnPlayerShooting(cPlayer & a_Player) cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_SHOOTING); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); - if (!CallFunction(1, 1, FnName)) + if (!m_LuaState.CallFunction(1, 1, FnName)) { return false; } @@ -938,14 +877,14 @@ bool cPlugin_NewLua::OnPlayerSpawned(cPlayer & a_Player) cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_SPAWNED); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); - if (!CallFunction(1, 1, FnName)) + if (!m_LuaState.CallFunction(1, 1, FnName)) { return false; } @@ -964,14 +903,14 @@ bool cPlugin_NewLua::OnPlayerTossingItem(cPlayer & a_Player) cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_TOSSING_ITEM); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); - if (!CallFunction(1, 1, FnName)) + if (!m_LuaState.CallFunction(1, 1, FnName)) { return false; } @@ -990,7 +929,7 @@ bool cPlugin_NewLua::OnPlayerUsedBlock(cPlayer & a_Player, int a_BlockX, int a_B cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_USED_BLOCK); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -1006,7 +945,7 @@ bool cPlugin_NewLua::OnPlayerUsedBlock(cPlayer & a_Player, int a_BlockX, int a_B tolua_pushnumber (m_LuaState, a_BlockType); tolua_pushnumber (m_LuaState, a_BlockMeta); - if (!CallFunction(10, 1, FnName)) + if (!m_LuaState.CallFunction(10, 1, FnName)) { return false; } @@ -1025,7 +964,7 @@ bool cPlugin_NewLua::OnPlayerUsedItem(cPlayer & a_Player, int a_BlockX, int a_Bl cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_USED_ITEM); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -1039,7 +978,7 @@ bool cPlugin_NewLua::OnPlayerUsedItem(cPlayer & a_Player, int a_BlockX, int a_Bl tolua_pushnumber (m_LuaState, a_CursorY); tolua_pushnumber (m_LuaState, a_CursorZ); - if (!CallFunction(8, 1, FnName)) + if (!m_LuaState.CallFunction(8, 1, FnName)) { return false; } @@ -1058,7 +997,7 @@ bool cPlugin_NewLua::OnPlayerUsingBlock(cPlayer & a_Player, int a_BlockX, int a_ cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_USING_BLOCK); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -1074,7 +1013,7 @@ bool cPlugin_NewLua::OnPlayerUsingBlock(cPlayer & a_Player, int a_BlockX, int a_ tolua_pushnumber (m_LuaState, a_BlockType); tolua_pushnumber (m_LuaState, a_BlockMeta); - if (!CallFunction(10, 1, FnName)) + if (!m_LuaState.CallFunction(10, 1, FnName)) { return false; } @@ -1093,7 +1032,7 @@ bool cPlugin_NewLua::OnPlayerUsingItem(cPlayer & a_Player, int a_BlockX, int a_B cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_USING_ITEM); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -1107,7 +1046,7 @@ bool cPlugin_NewLua::OnPlayerUsingItem(cPlayer & a_Player, int a_BlockX, int a_B tolua_pushnumber (m_LuaState, a_CursorY); tolua_pushnumber (m_LuaState, a_CursorZ); - if (!CallFunction(8, 1, FnName)) + if (!m_LuaState.CallFunction(8, 1, FnName)) { return false; } @@ -1126,7 +1065,7 @@ bool cPlugin_NewLua::OnPostCrafting(const cPlayer * a_Player, const cCraftingGri cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_POST_CRAFTING); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -1135,7 +1074,7 @@ bool cPlugin_NewLua::OnPostCrafting(const cPlayer * a_Player, const cCraftingGri tolua_pushusertype(m_LuaState, (void *)a_Grid, "cCraftingGrid"); tolua_pushusertype(m_LuaState, (void *)a_Recipe, "cCraftingRecipe"); - if (!CallFunction(3, 1, FnName)) + if (!m_LuaState.CallFunction(3, 1, FnName)) { return false; } @@ -1154,7 +1093,7 @@ bool cPlugin_NewLua::OnPreCrafting(const cPlayer * a_Player, const cCraftingGrid cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_PRE_CRAFTING); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -1163,7 +1102,7 @@ bool cPlugin_NewLua::OnPreCrafting(const cPlayer * a_Player, const cCraftingGrid tolua_pushusertype(m_LuaState, (void *)a_Grid, "cCraftingGrid"); tolua_pushusertype(m_LuaState, (void *)a_Recipe, "cCraftingRecipe"); - if (!CallFunction(3, 1, FnName)) + if (!m_LuaState.CallFunction(3, 1, FnName)) { return false; } @@ -1182,7 +1121,7 @@ bool cPlugin_NewLua::OnTakeDamage(cEntity & a_Receiver, TakeDamageInfo & a_TDI) cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_TAKE_DAMAGE); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -1190,7 +1129,7 @@ bool cPlugin_NewLua::OnTakeDamage(cEntity & a_Receiver, TakeDamageInfo & a_TDI) tolua_pushusertype(m_LuaState, &a_Receiver, "cEntity"); tolua_pushusertype(m_LuaState, &a_TDI, "TakeDamageInfo"); - if (!CallFunction(2, 1, FnName)) + if (!m_LuaState.CallFunction(2, 1, FnName)) { return false; } @@ -1214,7 +1153,7 @@ bool cPlugin_NewLua::OnUpdatedSign( cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_UPDATED_SIGN); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -1229,7 +1168,7 @@ bool cPlugin_NewLua::OnUpdatedSign( tolua_pushstring (m_LuaState, a_Line4.c_str()); tolua_pushusertype(m_LuaState, (void *)a_Player, "cPlayer"); - if (!CallFunction(9, 1, FnName)) + if (!m_LuaState.CallFunction(9, 1, FnName)) { return false; } @@ -1253,7 +1192,7 @@ bool cPlugin_NewLua::OnUpdatingSign( cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_UPDATING_SIGN); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -1268,7 +1207,7 @@ bool cPlugin_NewLua::OnUpdatingSign( tolua_pushstring (m_LuaState, a_Line4.c_str()); tolua_pushusertype(m_LuaState, (void *)a_Player, "cPlayer"); - if (!CallFunction(9, 5, "OnUpdatingSign")) + if (!m_LuaState.CallFunction(9, 5, "OnUpdatingSign")) { return false; } @@ -1303,14 +1242,14 @@ bool cPlugin_NewLua::OnWeatherChanged(cWorld & a_World) cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_WEATHER_CHANGED); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } tolua_pushusertype(m_LuaState, &a_World, "cWorld"); - if (!CallFunction(1, 1, FnName)) + if (!m_LuaState.CallFunction(1, 1, FnName)) { return false; } @@ -1329,7 +1268,7 @@ bool cPlugin_NewLua::OnWeatherChanging(cWorld & a_World, eWeather & a_NewWeather cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_WEATHER_CHANGED); ASSERT(FnName != NULL); - if (!PushFunction(FnName)) + if (!m_LuaState.PushFunction(FnName)) { return false; } @@ -1337,7 +1276,7 @@ bool cPlugin_NewLua::OnWeatherChanging(cWorld & a_World, eWeather & a_NewWeather tolua_pushusertype(m_LuaState, &a_World, "cWorld"); tolua_pushnumber (m_LuaState, a_NewWeather); - if (!CallFunction(2, 2, FnName)) + if (!m_LuaState.CallFunction(2, 2, FnName)) { return false; } @@ -1368,29 +1307,22 @@ bool cPlugin_NewLua::HandleCommand(const AStringVector & a_Split, cPlayer * a_Pl cCSLock Lock(m_CriticalSection); // Push the function to be called: - lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, cmd->second); // same as lua_getref() + if (!m_LuaState.PushFunctionFromRegistry(cmd->second)) + { + LOGWARNING("Command handler function for \"%s\" is invalid", cmd->first.c_str()); + return false; + } // Push the split: - lua_createtable(m_LuaState, a_Split.size(), 0); - int newTable = lua_gettop(m_LuaState); - int index = 1; - std::vector::const_iterator iter = a_Split.begin(), end = a_Split.end(); - while(iter != end) - { - tolua_pushstring(m_LuaState, (*iter).c_str()); - lua_rawseti(m_LuaState, newTable, index); - ++iter; - ++index; - } + m_LuaState.PushStringVector(a_Split); // Push player: tolua_pushusertype(m_LuaState, a_Player, "cPlayer"); // Call function: - int s = lua_pcall(m_LuaState, 2, 1, 0); - if (report_errors(m_LuaState, s)) + if (!m_LuaState.CallFunction(2, 1, __FUNCTION__)) { - LOGERROR("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState)); + LOGWARNING("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState)); return false; } @@ -1436,10 +1368,9 @@ bool cPlugin_NewLua::HandleConsoleCommand(const AStringVector & a_Split, cComman } // Call function: - int s = lua_pcall(m_LuaState, 1, 2, 0); - if (report_errors(m_LuaState, s)) + if (!m_LuaState.CallFunction(1, 2, __FUNCTION__)) { - LOGERROR("Lua error. Stack size: %i", lua_gettop(m_LuaState)); + LOGWARNING("Lua error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState)); return false; } @@ -1604,9 +1535,9 @@ AString cPlugin_NewLua::HandleWebRequest(const HTTPRequest * a_Request ) return ""; sWebPluginTab* Tab = 0; - for( TabList::iterator itr = GetTabs().begin(); itr != GetTabs().end(); ++itr ) + for (TabList::iterator itr = GetTabs().begin(); itr != GetTabs().end(); ++itr) { - if( (*itr)->SafeTitle.compare( SafeTabName ) == 0 ) // This is the one! Rawr + if ((*itr)->SafeTitle.compare(SafeTabName) == 0) // This is the one! Rawr { Tab = *itr; break; @@ -1615,13 +1546,13 @@ AString cPlugin_NewLua::HandleWebRequest(const HTTPRequest * a_Request ) if( Tab ) { - //LOGINFO("1. Stack size: %i", lua_gettop(m_LuaState) ); + // LOGINFO("1. Stack size: %i", lua_gettop(m_LuaState) ); lua_rawgeti( m_LuaState, LUA_REGISTRYINDEX, Tab->UserData); // same as lua_getref() - //LOGINFO("2. Stack size: %i", lua_gettop(m_LuaState) ); + // LOGINFO("2. Stack size: %i", lua_gettop(m_LuaState) ); // Push HTTPRequest tolua_pushusertype( m_LuaState, (void*)a_Request, "const HTTPRequest" ); - //LOGINFO("Calling bound function! :D"); + // LOGINFO("Calling bound function! :D"); int s = lua_pcall( m_LuaState, 1, 1, 0); if ( s != 0 ) @@ -1642,7 +1573,7 @@ AString cPlugin_NewLua::HandleWebRequest(const HTTPRequest * a_Request ) RetVal += tolua_tostring(m_LuaState, -1, 0); lua_pop(m_LuaState, 1); // Pop return value - //LOGINFO("ok. Stack size: %i", lua_gettop(m_LuaState) ); + // LOGINFO("ok. Stack size: %i", lua_gettop(m_LuaState) ); } return RetVal; @@ -1652,7 +1583,7 @@ AString cPlugin_NewLua::HandleWebRequest(const HTTPRequest * a_Request ) -bool cPlugin_NewLua::AddWebTab( const AString & a_Title, lua_State * a_LuaState, int a_FunctionReference ) +bool cPlugin_NewLua::AddWebTab(const AString & a_Title, lua_State * a_LuaState, int a_FunctionReference) { cCSLock Lock(m_CriticalSection); if (a_LuaState != m_LuaState) @@ -1666,7 +1597,7 @@ bool cPlugin_NewLua::AddWebTab( const AString & a_Title, lua_State * a_LuaState, Tab->UserData = a_FunctionReference; - GetTabs().push_back( Tab ); + GetTabs().push_back(Tab); return true; } @@ -1715,10 +1646,9 @@ bool cPlugin_NewLua::CallbackWindowClosing(int a_FnRef, cWindow & a_Window, cPla tolua_pushboolean (m_LuaState, a_CanRefuse ? 1 : 0); // Call function: - int s = lua_pcall(m_LuaState, 3, 1, 0); - if (report_errors(m_LuaState, s)) + if (!m_LuaState.CallFunction(3, 1, __FUNCTION__)) { - LOGERROR("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState)); + LOGWARNING("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState)); return false; } @@ -1741,56 +1671,12 @@ void cPlugin_NewLua::CallbackWindowSlotChanged(int a_FnRef, cWindow & a_Window, tolua_pushnumber (m_LuaState, a_SlotNum); // Call function: - int s = lua_pcall(m_LuaState, 2, 0, 0); - if (report_errors(m_LuaState, s)) + if (!m_LuaState.CallFunction(2, 0, __FUNCTION__)) { - LOGERROR("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState)); + LOGWARNING("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState)); } } - -// Helper functions -bool cPlugin_NewLua::PushFunction(const char * a_FunctionName, bool a_bLogError /* = true */) -{ - if (m_LuaState == NULL) - { - // This happens if Initialize() fails with an error - return false; - } - - lua_getglobal(m_LuaState, a_FunctionName); - if (!lua_isfunction(m_LuaState, -1)) - { - if (a_bLogError) - { - LOGWARN("Error in plugin %s: Could not find function %s()", GetName().c_str(), a_FunctionName); - } - lua_pop(m_LuaState, 1); - return false; - } - return true; -} - - - - - -bool cPlugin_NewLua::CallFunction( int a_NumArgs, int a_NumResults, const char * a_FunctionName) -{ - ASSERT(lua_isfunction(m_LuaState, -a_NumArgs - 1)); - - int s = lua_pcall(m_LuaState, a_NumArgs, a_NumResults, 0); - if (report_errors(m_LuaState, s)) - { - LOGWARN("Error in plugin %s calling function %s()", GetName().c_str(), a_FunctionName); - return false; - } - return true; -} - - - - diff --git a/source/Plugin_NewLua.h b/source/Plugin_NewLua.h index a79affd5d..d31a62601 100644 --- a/source/Plugin_NewLua.h +++ b/source/Plugin_NewLua.h @@ -3,6 +3,7 @@ #include "Plugin.h" #include "WebPlugin.h" +#include "LuaState.h" // Names for the global variables through which the plugin is identified in its LuaState #define LUA_PLUGIN_NAME_VAR_NAME "_MCServerInternal_PluginName" @@ -11,9 +12,6 @@ -// fwd: Lua -typedef struct lua_State lua_State; - // fwd: UI/Window.h class cWindow; @@ -99,7 +97,7 @@ public: /// Binds the console command to call the function specified by a Lua function reference. Simply adds to CommandMap. void BindConsoleCommand(const AString & a_Command, int a_FnRef); - lua_State * GetLuaState(void) { return m_LuaState; } + cLuaState & GetLuaState(void) { return m_LuaState; } cCriticalSection & GetCriticalSection(void) { return m_CriticalSection; } @@ -114,7 +112,7 @@ public: protected: cCriticalSection m_CriticalSection; - lua_State * m_LuaState; + cLuaState m_LuaState; /// Maps command name into Lua function reference typedef std::map CommandMap; @@ -122,9 +120,6 @@ protected: CommandMap m_Commands; CommandMap m_ConsoleCommands; - bool PushFunction(const char * a_FunctionName, bool a_bLogError = true); - bool CallFunction(int a_NumArgs, int a_NumResults, const char * a_FunctionName ); // a_FunctionName is only used for error messages, nothing else - /// Returns the name of Lua function that should handle the specified hook const char * GetHookFnName(cPluginManager::PluginHook a_Hook); } ; // tolua_export From 2151bb8f5bad91975010ab1022177fdb94cc2a3e Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 6 Aug 2013 08:01:00 +0200 Subject: [PATCH 09/19] cLuaState can now contain a detached LuaState, too. This will be useful for cases when we get a lua_State * from the outside and are asked to perform operations on it. --- source/LuaState.cpp | 67 +++++++++++++++++++++++++++++++++++++++++++++ source/LuaState.h | 23 +++++++++++++++- 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/source/LuaState.cpp b/source/LuaState.cpp index da86a4b20..117023755 100644 --- a/source/LuaState.cpp +++ b/source/LuaState.cpp @@ -37,6 +37,7 @@ extern "C" cLuaState::cLuaState(const AString & a_SubsystemName) : m_LuaState(NULL), + m_IsOwned(false), m_SubsystemName(a_SubsystemName) { } @@ -45,6 +46,17 @@ cLuaState::cLuaState(const AString & a_SubsystemName) : +cLuaState::cLuaState(lua_State * a_AttachState) : + m_LuaState(a_AttachState), + m_IsOwned(false), + m_SubsystemName("") +{ +} + + + + + cLuaState::~cLuaState() { if (IsValid()) @@ -70,6 +82,7 @@ void cLuaState::Create(void) ManualBindings::Bind(m_LuaState); luaopen_lsqlite3(m_LuaState); luaopen_lxp(m_LuaState); + m_IsOwned = true; } @@ -83,8 +96,62 @@ void cLuaState::Close(void) LOGWARNING("%s: Trying to close an invalid LuaState, ignoring.", __FUNCTION__); return; } + if (!m_IsOwned) + { + LOGWARNING( + "%s: Detected mis-use, calling Close() on an attached state (0x%p). Detaching instead.", + __FUNCTION__, m_LuaState + ); + Detach(); + return; + } lua_close(m_LuaState); m_LuaState = NULL; + m_IsOwned = false; +} + + + + + +void cLuaState::Attach(lua_State * a_State) +{ + if (m_LuaState != NULL) + { + LOGINFO("%s: Already contains a LuaState (0x%p), will be closed / detached.", __FUNCTION__, m_LuaState); + if (m_IsOwned) + { + Close(); + } + else + { + Detach(); + } + } + m_LuaState = a_State; + m_IsOwned = false; +} + + + + + +void cLuaState::Detach(void) +{ + if (m_LuaState == NULL) + { + return; + } + if (m_IsOwned) + { + LOGWARNING( + "%s: Detected a mis-use, calling Detach() when the state is owned. Closing the owned state (0x%p).", + __FUNCTION__, m_LuaState + ); + Close(); + return; + } + m_LuaState = NULL; } diff --git a/source/LuaState.h b/source/LuaState.h index 10ff53911..fca532d89 100644 --- a/source/LuaState.h +++ b/source/LuaState.h @@ -3,6 +3,12 @@ // Declares the cLuaState class representing the wrapper over lua_State *, provides associated helper functions +/* +The contained lua_State can be either owned or attached. +Owned lua_State is created by calling Create() and the cLuaState automatically closes the state +Or, lua_State can be attached by calling Attach(), the cLuaState doesn't close such a state +Attaching a state will automatically close an owned state. +*/ @@ -29,16 +35,28 @@ public: */ cLuaState(const AString & a_SubsystemName); + /** Creates a new instance. The a_AttachState is attached. + Subsystem name is set to "". + */ + explicit cLuaState(lua_State * a_AttachState); + ~cLuaState(); + /// Allows this object to be used in the same way as a lua_State *, for example in the LuaLib functions operator lua_State * (void) { return m_LuaState; } - /// Creates the m_LuaState, if not closed already + /// Creates the m_LuaState, if not closed already. This state will be automatically closed in the destructor void Create(void); /// Closes the m_LuaState, if not closed already void Close(void); + /// Attaches the specified state. Operations will be carried out on this state, but it will not be closed in the destructor + void Attach(lua_State * a_State); + + /// Detaches a previously attached state. + void Detach(void); + /// Returns true if the m_LuaState is valid bool IsValid(void) const { return (m_LuaState != NULL); } @@ -79,6 +97,9 @@ public: protected: lua_State * m_LuaState; + /// If true, the state is owned by this object and will be auto-Closed. False => attached state + bool m_IsOwned; + /** The subsystem name is used for reporting errors to the console, it is either "plugin %s" or "LuaScript" whatever is given to the constructor */ From 2030bd47c823b47606e9567a1974761f80cf0d55 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 6 Aug 2013 08:59:54 +0200 Subject: [PATCH 10/19] cLuaState now tracks the function name and number of args --- source/LuaState.cpp | 188 ++++++++++++++- source/LuaState.h | 50 +++- source/Plugin_NewLua.cpp | 498 ++++++++++++++++++--------------------- 3 files changed, 459 insertions(+), 277 deletions(-) diff --git a/source/LuaState.cpp b/source/LuaState.cpp index 117023755..e60a0f80c 100644 --- a/source/LuaState.cpp +++ b/source/LuaState.cpp @@ -38,7 +38,8 @@ extern "C" cLuaState::cLuaState(const AString & a_SubsystemName) : m_LuaState(NULL), m_IsOwned(false), - m_SubsystemName(a_SubsystemName) + m_SubsystemName(a_SubsystemName), + m_NumCurrentFunctionArgs(-1) { } @@ -49,7 +50,8 @@ cLuaState::cLuaState(const AString & a_SubsystemName) : cLuaState::cLuaState(lua_State * a_AttachState) : m_LuaState(a_AttachState), m_IsOwned(false), - m_SubsystemName("") + m_SubsystemName(""), + m_NumCurrentFunctionArgs(-1) { } @@ -187,6 +189,8 @@ bool cLuaState::LoadFile(const AString & a_FileName) bool cLuaState::PushFunction(const char * a_FunctionName, bool a_ShouldLogFailure /* = true */) { + ASSERT(m_NumCurrentFunctionArgs == -1); // If not, there's already something pushed onto the stack + if (!IsValid()) { // This happens if cPlugin::Initialize() fails with an error @@ -203,6 +207,8 @@ bool cLuaState::PushFunction(const char * a_FunctionName, bool a_ShouldLogFailur lua_pop(m_LuaState, 1); return false; } + m_CurrentFunctionName.assign(a_FunctionName); + m_NumCurrentFunctionArgs = 0; return true; } @@ -212,12 +218,17 @@ bool cLuaState::PushFunction(const char * a_FunctionName, bool a_ShouldLogFailur bool cLuaState::PushFunctionFromRegistry(int a_FnRef) { + ASSERT(IsValid()); + ASSERT(m_NumCurrentFunctionArgs == -1); // If not, there's already something pushed onto the stack + lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_FnRef); // same as lua_getref() if (!lua_isfunction(m_LuaState, -1)) { lua_pop(m_LuaState, 1); return false; } + m_CurrentFunctionName = ""; + m_NumCurrentFunctionArgs = 0; return true; } @@ -227,6 +238,9 @@ bool cLuaState::PushFunctionFromRegistry(int a_FnRef) void cLuaState::PushStringVector(const AStringVector & a_Vector) { + ASSERT(IsValid()); + ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first + lua_createtable(m_LuaState, a_Vector.size(), 0); int newTable = lua_gettop(m_LuaState); int index = 1; @@ -235,22 +249,184 @@ void cLuaState::PushStringVector(const AStringVector & a_Vector) tolua_pushstring(m_LuaState, itr->c_str()); lua_rawseti(m_LuaState, newTable, index); } + m_NumCurrentFunctionArgs += 1; } -bool cLuaState::CallFunction(int a_NumArgs, int a_NumResults, const char * a_FunctionName) +void cLuaState::PushUserType(void * a_Object, const char * a_Type) { - ASSERT(lua_isfunction(m_LuaState, -a_NumArgs - 1)); + ASSERT(IsValid()); + ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first + + tolua_pushusertype(m_LuaState, a_Object, a_Type); + m_NumCurrentFunctionArgs += 1; +} + + + + + +void cLuaState::PushNumber(int a_Value) +{ + ASSERT(IsValid()); + ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first + + tolua_pushnumber(m_LuaState, a_Value); + m_NumCurrentFunctionArgs += 1; +} + + + + + +void cLuaState::PushNumber(double a_Value) +{ + ASSERT(IsValid()); + ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first + + tolua_pushnumber(m_LuaState, a_Value); + m_NumCurrentFunctionArgs += 1; +} + + + + + +void cLuaState::PushString(const char * a_Value) +{ + ASSERT(IsValid()); + ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first + + tolua_pushstring(m_LuaState, a_Value); + m_NumCurrentFunctionArgs += 1; +} + + + + + +void cLuaState::PushBool(bool a_Value) +{ + ASSERT(IsValid()); + ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first + + tolua_pushboolean(m_LuaState, a_Value ? 1 : 0); + m_NumCurrentFunctionArgs += 1; +} + + + + + +void cLuaState::PushObject(cWorld * a_World) +{ + ASSERT(IsValid()); + ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first + + tolua_pushusertype(m_LuaState, a_World, "cWorld"); + m_NumCurrentFunctionArgs += 1; +} + + + + + +void cLuaState::PushObject(cPlayer * a_Player) +{ + ASSERT(IsValid()); + ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first + + tolua_pushusertype(m_LuaState, a_Player, "cPlayer"); + m_NumCurrentFunctionArgs += 1; +} + + + + + +void cLuaState::PushObject(cEntity * a_Entity) +{ + ASSERT(IsValid()); + ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first + + tolua_pushusertype(m_LuaState, a_Entity, "cEntity"); + m_NumCurrentFunctionArgs += 1; +} + + + + + +void cLuaState::PushObject(cItem * a_Item) +{ + ASSERT(IsValid()); + ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first + + tolua_pushusertype(m_LuaState, a_Item, "cItem"); + m_NumCurrentFunctionArgs += 1; +} + + + + + +void cLuaState::PushObject(cItems * a_Items) +{ + ASSERT(IsValid()); + ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first + + tolua_pushusertype(m_LuaState, a_Items, "cItems"); + m_NumCurrentFunctionArgs += 1; +} + + + + + +void cLuaState::PushObject(cClientHandle * a_Client) +{ + ASSERT(IsValid()); + ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first + + tolua_pushusertype(m_LuaState, a_Client, "cClientHandle"); + m_NumCurrentFunctionArgs += 1; +} + + + + + +void cLuaState::PushObject(cPickup * a_Pickup) +{ + ASSERT(IsValid()); + ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first + + tolua_pushusertype(m_LuaState, a_Pickup, "cPickup"); + m_NumCurrentFunctionArgs += 1; +} + + + + + +bool cLuaState::CallFunction(int a_NumResults) +{ + ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first + ASSERT(lua_isfunction(m_LuaState, -m_NumCurrentFunctionArgs - 1)); - int s = lua_pcall(m_LuaState, a_NumArgs, a_NumResults, 0); + int s = lua_pcall(m_LuaState, m_NumCurrentFunctionArgs, a_NumResults, 0); if (ReportErrors(s)) { - LOGWARNING("Error in %s calling function %s()", m_SubsystemName.c_str(), a_FunctionName); + LOGWARNING("Error in %s calling function %s()", m_SubsystemName.c_str(), m_CurrentFunctionName); + m_NumCurrentFunctionArgs = -1; + m_CurrentFunctionName.clear(); return false; } + m_NumCurrentFunctionArgs = -1; + m_CurrentFunctionName.clear(); return true; } diff --git a/source/LuaState.h b/source/LuaState.h index fca532d89..18c7c1354 100644 --- a/source/LuaState.h +++ b/source/LuaState.h @@ -8,6 +8,11 @@ The contained lua_State can be either owned or attached. Owned lua_State is created by calling Create() and the cLuaState automatically closes the state Or, lua_State can be attached by calling Attach(), the cLuaState doesn't close such a state Attaching a state will automatically close an owned state. + +Calling a Lua function is done by pushing the function, either by PushFunction() or PushFunctionFromRegistry(), +then pushing the arguments (PushString(), PushNumber(), PushUserData() etc.) and finally +executing CallFunction(). cLuaState automatically keeps track of the number of arguments and the name of the +function (for logging purposes), which makes the call less error-prone. */ @@ -22,6 +27,14 @@ Attaching a state will automatically close an owned state. // fwd: lua.h struct lua_State; +class cWorld; +class cPlayer; +class cEntity; +class cItem; +class cItems; +class cClientHandle; +class cPickup; + @@ -80,13 +93,36 @@ public: /// Pushes a string vector, as a table, onto the stack void PushStringVector(const AStringVector & a_Vector); + /// Pushes a usertype of the specified class type onto the stack + void PushUserType(void * a_Object, const char * a_Type); + + /// Pushes an integer onto the stack + void PushNumber(int a_Value); + + /// Pushes a double onto the stack + void PushNumber(double a_Value); + + /// Pushes a string onto the stack + void PushString(const char * a_Value); + + /// Pushes a bool onto the stack + void PushBool(bool a_Value); + + // Special family of functions that do PushUserType internally, but require one less parameter + void PushObject(cWorld * a_World); + void PushObject(cPlayer * a_Player); + void PushObject(cEntity * a_Entity); + void PushObject(cItem * a_Item); + void PushObject(cItems * a_Items); + void PushObject(cClientHandle * a_ClientHandle); + void PushObject(cPickup * a_Pickup); + /** - Calls the function that has been pushed onto the stack by PushFunction. + Calls the function that has been pushed onto the stack by PushFunction(), + with arguments pushed by PushXXX(). Returns true if successful, logs a warning on failure. - a_FunctionName is used only for the warning log message, the function - to be called must be pushed by PushFunction() beforehand. */ - bool CallFunction(int a_NumArgs, int a_NumResults, const char * a_FunctionName); + bool CallFunction(int a_NumReturnValues); /// If the status is nonzero, prints the text on the top of Lua stack and returns true bool ReportErrors(int status); @@ -104,6 +140,12 @@ protected: whatever is given to the constructor */ AString m_SubsystemName; + + /// Name of the currently pushed function (for the Push / Call chain) + AString m_CurrentFunctionName; + + /// Number of arguments currently pushed (for the Push / Call chain) + int m_NumCurrentFunctionArgs; } ; diff --git a/source/Plugin_NewLua.cpp b/source/Plugin_NewLua.cpp index 51d16c839..b3dac7912 100644 --- a/source/Plugin_NewLua.cpp +++ b/source/Plugin_NewLua.cpp @@ -78,9 +78,9 @@ bool cPlugin_NewLua::Initialize(void) return false; } - tolua_pushusertype(m_LuaState, this, "cPlugin_NewLua"); + m_LuaState.PushUserType(this, "cPlugin_NewLua"); - if (!m_LuaState.CallFunction(1, 1, "Initialize")) + if (!m_LuaState.CallFunction(1)) { m_LuaState.Close(); return false; @@ -109,7 +109,7 @@ void cPlugin_NewLua::OnDisable() return; } - m_LuaState.CallFunction(0, 0, "OnDisable"); + m_LuaState.CallFunction(0); } @@ -124,10 +124,8 @@ void cPlugin_NewLua::Tick(float a_Dt) { return; } - - tolua_pushnumber( m_LuaState, a_Dt ); - - m_LuaState.CallFunction(1, 0, FnName); + m_LuaState.PushNumber(a_Dt); + m_LuaState.CallFunction(0); } @@ -144,16 +142,16 @@ bool cPlugin_NewLua::OnBlockToPickups(cWorld * a_World, cEntity * a_Digger, int return false; } - tolua_pushusertype(m_LuaState, a_World, "cWorld"); - tolua_pushusertype(m_LuaState, a_Digger, "cEntity"); - tolua_pushnumber (m_LuaState, a_BlockX); - tolua_pushnumber (m_LuaState, a_BlockY); - tolua_pushnumber (m_LuaState, a_BlockZ); - tolua_pushnumber (m_LuaState, a_BlockType); - tolua_pushnumber (m_LuaState, a_BlockMeta); - tolua_pushusertype(m_LuaState, &a_Pickups, "cItems"); + m_LuaState.PushObject(a_World); + m_LuaState.PushObject(a_Digger); + m_LuaState.PushNumber(a_BlockX); + m_LuaState.PushNumber(a_BlockY); + m_LuaState.PushNumber(a_BlockZ); + m_LuaState.PushNumber(a_BlockType); + m_LuaState.PushNumber(a_BlockMeta); + m_LuaState.PushObject(&a_Pickups); - if (!m_LuaState.CallFunction(8, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -177,10 +175,10 @@ bool cPlugin_NewLua::OnChat(cPlayer * a_Player, AString & a_Message) return false; } - tolua_pushusertype(m_LuaState, a_Player, "cPlayer"); - tolua_pushstring (m_LuaState, a_Message.c_str()); + m_LuaState.PushObject(a_Player); + m_LuaState.PushString(a_Message.c_str()); - if (!m_LuaState.CallFunction(2, 2, FnName)) + if (!m_LuaState.CallFunction(2)) { return false; } @@ -208,11 +206,11 @@ bool cPlugin_NewLua::OnChunkAvailable(cWorld * a_World, int a_ChunkX, int a_Chun return false; } - tolua_pushusertype(m_LuaState, a_World, "cWorld"); - tolua_pushnumber (m_LuaState, a_ChunkX); - tolua_pushnumber (m_LuaState, a_ChunkZ); + m_LuaState.PushObject(a_World); + m_LuaState.PushNumber(a_ChunkX); + m_LuaState.PushNumber(a_ChunkZ); - if (!m_LuaState.CallFunction(3, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -236,12 +234,12 @@ bool cPlugin_NewLua::OnChunkGenerated(cWorld * a_World, int a_ChunkX, int a_Chun return false; } - tolua_pushusertype(m_LuaState, a_World, "cWorld"); - tolua_pushnumber (m_LuaState, a_ChunkX); - tolua_pushnumber (m_LuaState, a_ChunkZ); - tolua_pushusertype(m_LuaState, a_ChunkDesc, "cChunkDesc"); + m_LuaState.PushObject(a_World); + m_LuaState.PushNumber(a_ChunkX); + m_LuaState.PushNumber(a_ChunkZ); + m_LuaState.PushUserType(a_ChunkDesc, "cChunkDesc"); - if (!m_LuaState.CallFunction(4, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -255,7 +253,7 @@ bool cPlugin_NewLua::OnChunkGenerated(cWorld * a_World, int a_ChunkX, int a_Chun -bool cPlugin_NewLua::OnChunkGenerating(cWorld * a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_pLuaChunk) +bool cPlugin_NewLua::OnChunkGenerating(cWorld * a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc) { cCSLock Lock(m_CriticalSection); const char * FnName = GetHookFnName(cPluginManager::HOOK_CHUNK_GENERATING); @@ -265,12 +263,12 @@ bool cPlugin_NewLua::OnChunkGenerating(cWorld * a_World, int a_ChunkX, int a_Chu return false; } - tolua_pushusertype(m_LuaState, a_World, "cWorld"); - tolua_pushnumber (m_LuaState, a_ChunkX); - tolua_pushnumber (m_LuaState, a_ChunkZ); - tolua_pushusertype(m_LuaState, a_pLuaChunk, "cChunkDesc"); + m_LuaState.PushObject(a_World); + m_LuaState.PushNumber(a_ChunkX); + m_LuaState.PushNumber(a_ChunkZ); + m_LuaState.PushUserType(a_ChunkDesc, "cChunkDesc"); - if (!m_LuaState.CallFunction(4, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -294,11 +292,11 @@ bool cPlugin_NewLua::OnChunkUnloaded(cWorld * a_World, int a_ChunkX, int a_Chunk return false; } - tolua_pushusertype(m_LuaState, a_World, "cWorld"); - tolua_pushnumber (m_LuaState, a_ChunkX); - tolua_pushnumber (m_LuaState, a_ChunkZ); + m_LuaState.PushObject(a_World); + m_LuaState.PushNumber(a_ChunkX); + m_LuaState.PushNumber(a_ChunkZ); - if (!m_LuaState.CallFunction(3, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -322,11 +320,11 @@ bool cPlugin_NewLua::OnChunkUnloading(cWorld * a_World, int a_ChunkX, int a_Chun return false; } - tolua_pushusertype(m_LuaState, a_World, "cWorld"); - tolua_pushnumber (m_LuaState, a_ChunkX); - tolua_pushnumber (m_LuaState, a_ChunkZ); + m_LuaState.PushObject(a_World); + m_LuaState.PushNumber(a_ChunkX); + m_LuaState.PushNumber(a_ChunkZ); - if (!m_LuaState.CallFunction(3, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -350,10 +348,10 @@ bool cPlugin_NewLua::OnCollectingPickup(cPlayer * a_Player, cPickup * a_Pickup) return false; } - tolua_pushusertype(m_LuaState, a_Player, "cPlayer"); - tolua_pushusertype(m_LuaState, a_Pickup, "cPickup"); + m_LuaState.PushObject(a_Player); + m_LuaState.PushObject(a_Pickup); - if (!m_LuaState.CallFunction(2, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -377,11 +375,11 @@ bool cPlugin_NewLua::OnCraftingNoRecipe(const cPlayer * a_Player, const cCraftin return false; } - tolua_pushusertype(m_LuaState, (void *)a_Player, "cPlayer"); - tolua_pushusertype(m_LuaState, (void *)a_Grid, "cCraftingGrid"); - tolua_pushusertype(m_LuaState, (void *)a_Recipe, "cCraftingRecipe"); + m_LuaState.PushUserType((void *)a_Player, "cPlayer"); + m_LuaState.PushUserType((void *)a_Grid, "cCraftingGrid"); + m_LuaState.PushUserType((void *)a_Recipe, "cCraftingRecipe"); - if (!m_LuaState.CallFunction(3, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -405,10 +403,10 @@ bool cPlugin_NewLua::OnDisconnect(cPlayer * a_Player, const AString & a_Reason) return false; } - tolua_pushusertype(m_LuaState, a_Player, "cPlayer"); - tolua_pushstring (m_LuaState, a_Reason.c_str()); + m_LuaState.PushObject(a_Player); + m_LuaState.PushString(a_Reason.c_str()); - if (!m_LuaState.CallFunction(2, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -432,22 +430,10 @@ bool cPlugin_NewLua::OnExecuteCommand(cPlayer * a_Player, const AStringVector & return false; } - tolua_pushusertype(m_LuaState, a_Player, "cPlayer"); + m_LuaState.PushObject(a_Player); + m_LuaState.PushStringVector(a_Split); - // Push the split: - lua_createtable(m_LuaState, a_Split.size(), 0); - int newTable = lua_gettop(m_LuaState); - int index = 1; - std::vector::const_iterator iter = a_Split.begin(), end = a_Split.end(); - while(iter != end) - { - tolua_pushstring(m_LuaState, (*iter).c_str()); - lua_rawseti(m_LuaState, newTable, index); - ++iter; - ++index; - } - - if (!m_LuaState.CallFunction(2, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -471,10 +457,10 @@ bool cPlugin_NewLua::OnHandshake(cClientHandle * a_Client, const AString & a_Use return false; } - tolua_pushusertype(m_LuaState, a_Client, "cClientHandle"); - tolua_pushstring (m_LuaState, a_Username.c_str()); + m_LuaState.PushUserType(a_Client, "cClientHandle"); + m_LuaState.PushString (a_Username.c_str()); - if (!m_LuaState.CallFunction(2, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -498,10 +484,10 @@ bool cPlugin_NewLua::OnKilling(cEntity & a_Victim, cEntity * a_Killer) return false; } - tolua_pushusertype(m_LuaState, &a_Victim, "cEntity"); - tolua_pushusertype(m_LuaState, a_Killer, "cEntity"); + m_LuaState.PushObject(&a_Victim); + m_LuaState.PushObject(a_Killer); - if (!m_LuaState.CallFunction(2, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -525,11 +511,11 @@ bool cPlugin_NewLua::OnLogin(cClientHandle * a_Client, int a_ProtocolVersion, co return false; } - tolua_pushusertype (m_LuaState, a_Client, "cClientHandle"); - tolua_pushnumber (m_LuaState, a_ProtocolVersion); - tolua_pushcppstring(m_LuaState, a_Username); + m_LuaState.PushObject(a_Client); + m_LuaState.PushNumber(a_ProtocolVersion); + m_LuaState.PushString(a_Username.c_str()); - if (!m_LuaState.CallFunction(3, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -553,15 +539,15 @@ bool cPlugin_NewLua::OnPlayerBreakingBlock(cPlayer & a_Player, int a_BlockX, int return false; } - tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); - tolua_pushnumber (m_LuaState, a_BlockX); - tolua_pushnumber (m_LuaState, a_BlockY); - tolua_pushnumber (m_LuaState, a_BlockZ); - tolua_pushnumber (m_LuaState, a_BlockFace); - tolua_pushnumber (m_LuaState, a_BlockType); - tolua_pushnumber (m_LuaState, a_BlockMeta); + m_LuaState.PushObject(&a_Player); + m_LuaState.PushNumber(a_BlockX); + m_LuaState.PushNumber(a_BlockY); + m_LuaState.PushNumber(a_BlockZ); + m_LuaState.PushNumber(a_BlockFace); + m_LuaState.PushNumber(a_BlockType); + m_LuaState.PushNumber(a_BlockMeta); - if (!m_LuaState.CallFunction(7, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -585,15 +571,15 @@ bool cPlugin_NewLua::OnPlayerBrokenBlock(cPlayer & a_Player, int a_BlockX, int a return false; } - tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); - tolua_pushnumber (m_LuaState, a_BlockX); - tolua_pushnumber (m_LuaState, a_BlockY); - tolua_pushnumber (m_LuaState, a_BlockZ); - tolua_pushnumber (m_LuaState, a_BlockFace); - tolua_pushnumber (m_LuaState, a_BlockType); - tolua_pushnumber (m_LuaState, a_BlockMeta); + m_LuaState.PushObject(&a_Player); + m_LuaState.PushNumber(a_BlockX); + m_LuaState.PushNumber(a_BlockY); + m_LuaState.PushNumber(a_BlockZ); + m_LuaState.PushNumber(a_BlockFace); + m_LuaState.PushNumber(a_BlockType); + m_LuaState.PushNumber(a_BlockMeta); - if (!m_LuaState.CallFunction(7, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -617,9 +603,9 @@ bool cPlugin_NewLua::OnPlayerEating(cPlayer & a_Player) return false; } - tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); + m_LuaState.PushObject(&a_Player); - if (!m_LuaState.CallFunction(1, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -643,9 +629,9 @@ bool cPlugin_NewLua::OnPlayerJoined(cPlayer & a_Player) return false; } - tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); + m_LuaState.PushObject(&a_Player); - if (!m_LuaState.CallFunction(1, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -669,14 +655,14 @@ bool cPlugin_NewLua::OnPlayerLeftClick(cPlayer & a_Player, int a_BlockX, int a_B return false; } - tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); - tolua_pushnumber (m_LuaState, a_BlockX); - tolua_pushnumber (m_LuaState, a_BlockY); - tolua_pushnumber (m_LuaState, a_BlockZ); - tolua_pushnumber (m_LuaState, a_BlockFace); - tolua_pushnumber (m_LuaState, a_Status); + m_LuaState.PushObject(&a_Player); + m_LuaState.PushNumber(a_BlockX); + m_LuaState.PushNumber(a_BlockY); + m_LuaState.PushNumber(a_BlockZ); + m_LuaState.PushNumber(a_BlockFace); + m_LuaState.PushNumber(a_Status); - if (!m_LuaState.CallFunction(6, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -700,9 +686,9 @@ bool cPlugin_NewLua::OnPlayerMoved(cPlayer & a_Player) return false; } - tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); + m_LuaState.PushObject(&a_Player); - if (!m_LuaState.CallFunction(1, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -726,18 +712,18 @@ bool cPlugin_NewLua::OnPlayerPlacedBlock(cPlayer & a_Player, int a_BlockX, int a return false; } - tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); - tolua_pushnumber (m_LuaState, a_BlockX); - tolua_pushnumber (m_LuaState, a_BlockY); - tolua_pushnumber (m_LuaState, a_BlockZ); - tolua_pushnumber (m_LuaState, a_BlockFace); - tolua_pushnumber (m_LuaState, a_CursorX); - tolua_pushnumber (m_LuaState, a_CursorY); - tolua_pushnumber (m_LuaState, a_CursorZ); - tolua_pushnumber (m_LuaState, a_BlockType); - tolua_pushnumber (m_LuaState, a_BlockMeta); + m_LuaState.PushObject(&a_Player); + m_LuaState.PushNumber(a_BlockX); + m_LuaState.PushNumber(a_BlockY); + m_LuaState.PushNumber(a_BlockZ); + m_LuaState.PushNumber(a_BlockFace); + m_LuaState.PushNumber(a_CursorX); + m_LuaState.PushNumber(a_CursorY); + m_LuaState.PushNumber(a_CursorZ); + m_LuaState.PushNumber(a_BlockType); + m_LuaState.PushNumber(a_BlockMeta); - if (!m_LuaState.CallFunction(10, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -761,18 +747,18 @@ bool cPlugin_NewLua::OnPlayerPlacingBlock(cPlayer & a_Player, int a_BlockX, int return false; } - tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); - tolua_pushnumber (m_LuaState, a_BlockX); - tolua_pushnumber (m_LuaState, a_BlockY); - tolua_pushnumber (m_LuaState, a_BlockZ); - tolua_pushnumber (m_LuaState, a_BlockFace); - tolua_pushnumber (m_LuaState, a_CursorX); - tolua_pushnumber (m_LuaState, a_CursorY); - tolua_pushnumber (m_LuaState, a_CursorZ); - tolua_pushnumber (m_LuaState, a_BlockType); - tolua_pushnumber (m_LuaState, a_BlockMeta); + m_LuaState.PushObject(&a_Player); + m_LuaState.PushNumber(a_BlockX); + m_LuaState.PushNumber(a_BlockY); + m_LuaState.PushNumber(a_BlockZ); + m_LuaState.PushNumber(a_BlockFace); + m_LuaState.PushNumber(a_CursorX); + m_LuaState.PushNumber(a_CursorY); + m_LuaState.PushNumber(a_CursorZ); + m_LuaState.PushNumber(a_BlockType); + m_LuaState.PushNumber(a_BlockMeta); - if (!m_LuaState.CallFunction(10, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -796,16 +782,16 @@ bool cPlugin_NewLua::OnPlayerRightClick(cPlayer & a_Player, int a_BlockX, int a_ return false; } - tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); - tolua_pushnumber (m_LuaState, a_BlockX); - tolua_pushnumber (m_LuaState, a_BlockY); - tolua_pushnumber (m_LuaState, a_BlockZ); - tolua_pushnumber (m_LuaState, a_BlockFace); - tolua_pushnumber (m_LuaState, a_CursorX); - tolua_pushnumber (m_LuaState, a_CursorY); - tolua_pushnumber (m_LuaState, a_CursorZ); + m_LuaState.PushObject(&a_Player); + m_LuaState.PushNumber(a_BlockX); + m_LuaState.PushNumber(a_BlockY); + m_LuaState.PushNumber(a_BlockZ); + m_LuaState.PushNumber(a_BlockFace); + m_LuaState.PushNumber(a_CursorX); + m_LuaState.PushNumber(a_CursorY); + m_LuaState.PushNumber(a_CursorZ); - if (!m_LuaState.CallFunction(8, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -829,10 +815,10 @@ bool cPlugin_NewLua::OnPlayerRightClickingEntity(cPlayer & a_Player, cEntity & a return false; } - tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); - tolua_pushusertype(m_LuaState, &a_Entity, "cEntity"); + m_LuaState.PushObject(&a_Player); + m_LuaState.PushObject(&a_Entity); - if (!m_LuaState.CallFunction(2, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -856,9 +842,9 @@ bool cPlugin_NewLua::OnPlayerShooting(cPlayer & a_Player) return false; } - tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); + m_LuaState.PushObject(&a_Player); - if (!m_LuaState.CallFunction(1, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -882,9 +868,9 @@ bool cPlugin_NewLua::OnPlayerSpawned(cPlayer & a_Player) return false; } - tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); + m_LuaState.PushObject(&a_Player); - if (!m_LuaState.CallFunction(1, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -908,9 +894,9 @@ bool cPlugin_NewLua::OnPlayerTossingItem(cPlayer & a_Player) return false; } - tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); + m_LuaState.PushObject(&a_Player); - if (!m_LuaState.CallFunction(1, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -934,18 +920,18 @@ bool cPlugin_NewLua::OnPlayerUsedBlock(cPlayer & a_Player, int a_BlockX, int a_B return false; } - tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); - tolua_pushnumber (m_LuaState, a_BlockX); - tolua_pushnumber (m_LuaState, a_BlockY); - tolua_pushnumber (m_LuaState, a_BlockZ); - tolua_pushnumber (m_LuaState, a_BlockFace); - tolua_pushnumber (m_LuaState, a_CursorX); - tolua_pushnumber (m_LuaState, a_CursorY); - tolua_pushnumber (m_LuaState, a_CursorZ); - tolua_pushnumber (m_LuaState, a_BlockType); - tolua_pushnumber (m_LuaState, a_BlockMeta); + m_LuaState.PushObject(&a_Player); + m_LuaState.PushNumber(a_BlockX); + m_LuaState.PushNumber(a_BlockY); + m_LuaState.PushNumber(a_BlockZ); + m_LuaState.PushNumber(a_BlockFace); + m_LuaState.PushNumber(a_CursorX); + m_LuaState.PushNumber(a_CursorY); + m_LuaState.PushNumber(a_CursorZ); + m_LuaState.PushNumber(a_BlockType); + m_LuaState.PushNumber(a_BlockMeta); - if (!m_LuaState.CallFunction(10, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -969,16 +955,16 @@ bool cPlugin_NewLua::OnPlayerUsedItem(cPlayer & a_Player, int a_BlockX, int a_Bl return false; } - tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); - tolua_pushnumber (m_LuaState, a_BlockX); - tolua_pushnumber (m_LuaState, a_BlockY); - tolua_pushnumber (m_LuaState, a_BlockZ); - tolua_pushnumber (m_LuaState, a_BlockFace); - tolua_pushnumber (m_LuaState, a_CursorX); - tolua_pushnumber (m_LuaState, a_CursorY); - tolua_pushnumber (m_LuaState, a_CursorZ); + m_LuaState.PushObject(&a_Player); + m_LuaState.PushNumber(a_BlockX); + m_LuaState.PushNumber(a_BlockY); + m_LuaState.PushNumber(a_BlockZ); + m_LuaState.PushNumber(a_BlockFace); + m_LuaState.PushNumber(a_CursorX); + m_LuaState.PushNumber(a_CursorY); + m_LuaState.PushNumber(a_CursorZ); - if (!m_LuaState.CallFunction(8, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -1002,18 +988,18 @@ bool cPlugin_NewLua::OnPlayerUsingBlock(cPlayer & a_Player, int a_BlockX, int a_ return false; } - tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); - tolua_pushnumber (m_LuaState, a_BlockX); - tolua_pushnumber (m_LuaState, a_BlockY); - tolua_pushnumber (m_LuaState, a_BlockZ); - tolua_pushnumber (m_LuaState, a_BlockFace); - tolua_pushnumber (m_LuaState, a_CursorX); - tolua_pushnumber (m_LuaState, a_CursorY); - tolua_pushnumber (m_LuaState, a_CursorZ); - tolua_pushnumber (m_LuaState, a_BlockType); - tolua_pushnumber (m_LuaState, a_BlockMeta); + m_LuaState.PushObject(&a_Player); + m_LuaState.PushNumber(a_BlockX); + m_LuaState.PushNumber(a_BlockY); + m_LuaState.PushNumber(a_BlockZ); + m_LuaState.PushNumber(a_BlockFace); + m_LuaState.PushNumber(a_CursorX); + m_LuaState.PushNumber(a_CursorY); + m_LuaState.PushNumber(a_CursorZ); + m_LuaState.PushNumber(a_BlockType); + m_LuaState.PushNumber(a_BlockMeta); - if (!m_LuaState.CallFunction(10, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -1037,16 +1023,16 @@ bool cPlugin_NewLua::OnPlayerUsingItem(cPlayer & a_Player, int a_BlockX, int a_B return false; } - tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); - tolua_pushnumber (m_LuaState, a_BlockX); - tolua_pushnumber (m_LuaState, a_BlockY); - tolua_pushnumber (m_LuaState, a_BlockZ); - tolua_pushnumber (m_LuaState, a_BlockFace); - tolua_pushnumber (m_LuaState, a_CursorX); - tolua_pushnumber (m_LuaState, a_CursorY); - tolua_pushnumber (m_LuaState, a_CursorZ); + m_LuaState.PushObject(&a_Player); + m_LuaState.PushNumber(a_BlockX); + m_LuaState.PushNumber(a_BlockY); + m_LuaState.PushNumber(a_BlockZ); + m_LuaState.PushNumber(a_BlockFace); + m_LuaState.PushNumber(a_CursorX); + m_LuaState.PushNumber(a_CursorY); + m_LuaState.PushNumber(a_CursorZ); - if (!m_LuaState.CallFunction(8, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -1070,11 +1056,11 @@ bool cPlugin_NewLua::OnPostCrafting(const cPlayer * a_Player, const cCraftingGri return false; } - tolua_pushusertype(m_LuaState, (void *)a_Player, "cPlayer"); - tolua_pushusertype(m_LuaState, (void *)a_Grid, "cCraftingGrid"); - tolua_pushusertype(m_LuaState, (void *)a_Recipe, "cCraftingRecipe"); + m_LuaState.PushUserType((void *)a_Player, "cPlayer"); + m_LuaState.PushUserType((void *)a_Grid, "cCraftingGrid"); + m_LuaState.PushUserType((void *)a_Recipe, "cCraftingRecipe"); - if (!m_LuaState.CallFunction(3, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -1098,11 +1084,11 @@ bool cPlugin_NewLua::OnPreCrafting(const cPlayer * a_Player, const cCraftingGrid return false; } - tolua_pushusertype(m_LuaState, (void *)a_Player, "cPlayer"); - tolua_pushusertype(m_LuaState, (void *)a_Grid, "cCraftingGrid"); - tolua_pushusertype(m_LuaState, (void *)a_Recipe, "cCraftingRecipe"); + m_LuaState.PushUserType((void *)a_Player, "cPlayer"); + m_LuaState.PushUserType((void *)a_Grid, "cCraftingGrid"); + m_LuaState.PushUserType((void *)a_Recipe, "cCraftingRecipe"); - if (!m_LuaState.CallFunction(3, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -1126,10 +1112,10 @@ bool cPlugin_NewLua::OnTakeDamage(cEntity & a_Receiver, TakeDamageInfo & a_TDI) return false; } - tolua_pushusertype(m_LuaState, &a_Receiver, "cEntity"); - tolua_pushusertype(m_LuaState, &a_TDI, "TakeDamageInfo"); + m_LuaState.PushObject(&a_Receiver); + m_LuaState.PushUserType(&a_TDI, "TakeDamageInfo"); - if (!m_LuaState.CallFunction(2, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -1158,17 +1144,17 @@ bool cPlugin_NewLua::OnUpdatedSign( return false; } - tolua_pushusertype(m_LuaState, (void *)a_World, "cWorld"); - tolua_pushnumber (m_LuaState, a_BlockX); - tolua_pushnumber (m_LuaState, a_BlockY); - tolua_pushnumber (m_LuaState, a_BlockZ); - tolua_pushstring (m_LuaState, a_Line1.c_str()); - tolua_pushstring (m_LuaState, a_Line2.c_str()); - tolua_pushstring (m_LuaState, a_Line3.c_str()); - tolua_pushstring (m_LuaState, a_Line4.c_str()); - tolua_pushusertype(m_LuaState, (void *)a_Player, "cPlayer"); + m_LuaState.PushObject(a_World); + m_LuaState.PushNumber(a_BlockX); + m_LuaState.PushNumber(a_BlockY); + m_LuaState.PushNumber(a_BlockZ); + m_LuaState.PushString(a_Line1.c_str()); + m_LuaState.PushString(a_Line2.c_str()); + m_LuaState.PushString(a_Line3.c_str()); + m_LuaState.PushString(a_Line4.c_str()); + m_LuaState.PushObject(a_Player); - if (!m_LuaState.CallFunction(9, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -1197,17 +1183,17 @@ bool cPlugin_NewLua::OnUpdatingSign( return false; } - tolua_pushusertype(m_LuaState, (void *)a_World, "cWorld"); - tolua_pushnumber (m_LuaState, a_BlockX); - tolua_pushnumber (m_LuaState, a_BlockY); - tolua_pushnumber (m_LuaState, a_BlockZ); - tolua_pushstring (m_LuaState, a_Line1.c_str()); - tolua_pushstring (m_LuaState, a_Line2.c_str()); - tolua_pushstring (m_LuaState, a_Line3.c_str()); - tolua_pushstring (m_LuaState, a_Line4.c_str()); - tolua_pushusertype(m_LuaState, (void *)a_Player, "cPlayer"); + m_LuaState.PushObject(a_World); + m_LuaState.PushNumber(a_BlockX); + m_LuaState.PushNumber(a_BlockY); + m_LuaState.PushNumber(a_BlockZ); + m_LuaState.PushString(a_Line1.c_str()); + m_LuaState.PushString(a_Line2.c_str()); + m_LuaState.PushString(a_Line3.c_str()); + m_LuaState.PushString(a_Line4.c_str()); + m_LuaState.PushObject(a_Player); - if (!m_LuaState.CallFunction(9, 5, "OnUpdatingSign")) + if (!m_LuaState.CallFunction(5)) { return false; } @@ -1247,9 +1233,9 @@ bool cPlugin_NewLua::OnWeatherChanged(cWorld & a_World) return false; } - tolua_pushusertype(m_LuaState, &a_World, "cWorld"); + m_LuaState.PushObject(&a_World); - if (!m_LuaState.CallFunction(1, 1, FnName)) + if (!m_LuaState.CallFunction(1)) { return false; } @@ -1273,10 +1259,10 @@ bool cPlugin_NewLua::OnWeatherChanging(cWorld & a_World, eWeather & a_NewWeather return false; } - tolua_pushusertype(m_LuaState, &a_World, "cWorld"); - tolua_pushnumber (m_LuaState, a_NewWeather); + m_LuaState.PushObject(&a_World); + m_LuaState.PushNumber(a_NewWeather); - if (!m_LuaState.CallFunction(2, 2, FnName)) + if (!m_LuaState.CallFunction(2)) { return false; } @@ -1313,14 +1299,11 @@ bool cPlugin_NewLua::HandleCommand(const AStringVector & a_Split, cPlayer * a_Pl return false; } - // Push the split: m_LuaState.PushStringVector(a_Split); - - // Push player: - tolua_pushusertype(m_LuaState, a_Player, "cPlayer"); + m_LuaState.PushObject(a_Player); // Call function: - if (!m_LuaState.CallFunction(2, 1, __FUNCTION__)) + if (!m_LuaState.CallFunction(1)) { LOGWARNING("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState)); return false; @@ -1352,23 +1335,12 @@ bool cPlugin_NewLua::HandleConsoleCommand(const AStringVector & a_Split, cComman cCSLock Lock(m_CriticalSection); // Push the function to be called: - lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, cmd->second); // same as lua_getref() + m_LuaState.PushFunctionFromRegistry(cmd->second); - // Push the split: - lua_createtable(m_LuaState, a_Split.size(), 0); - int newTable = lua_gettop(m_LuaState); - int index = 1; - std::vector::const_iterator iter = a_Split.begin(), end = a_Split.end(); - while(iter != end) - { - tolua_pushstring(m_LuaState, (*iter).c_str()); - lua_rawseti(m_LuaState, newTable, index); - ++iter; - ++index; - } + m_LuaState.PushStringVector(a_Split); // Call function: - if (!m_LuaState.CallFunction(1, 2, __FUNCTION__)) + if (!m_LuaState.CallFunction(2)) { LOGWARNING("Lua error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState)); return false; @@ -1546,29 +1518,21 @@ AString cPlugin_NewLua::HandleWebRequest(const HTTPRequest * a_Request ) if( Tab ) { - // LOGINFO("1. Stack size: %i", lua_gettop(m_LuaState) ); - lua_rawgeti( m_LuaState, LUA_REGISTRYINDEX, Tab->UserData); // same as lua_getref() + m_LuaState.PushFunctionFromRegistry(Tab->UserData); - // LOGINFO("2. Stack size: %i", lua_gettop(m_LuaState) ); // Push HTTPRequest - tolua_pushusertype( m_LuaState, (void*)a_Request, "const HTTPRequest" ); - // LOGINFO("Calling bound function! :D"); - int s = lua_pcall( m_LuaState, 1, 1, 0); - - if ( s != 0 ) + m_LuaState.PushUserType((void*)a_Request, "const HTTPRequest"); + + if (!m_LuaState.CallFunction(1)) { - std::string err = lua_tostring(m_LuaState, -1); - LOGERROR("-- %s", err.c_str() ); - lua_pop(m_LuaState, 1); - LOGINFO("error. Stack size: %i", lua_gettop(m_LuaState) ); - return err; // Show the error message in the web page, looks cool + return "Lua encountered error while processing the page request"; } - if( !lua_isstring( m_LuaState, -1 ) ) + if (!lua_isstring(m_LuaState, -1)) { - LOGWARN("WARNING: WebPlugin tab '%s' did not return a string!", Tab->Title.c_str() ); - lua_pop(m_LuaState, 1); // Pop return value - return std::string("WARNING: WebPlugin tab '") + Tab->Title + std::string("' did not return a string!"); + LOGWARNING("WebPlugin tab '%s' did not return a string!", Tab->Title.c_str()); + lua_pop(m_LuaState, 1); // Pop return value + return Printf("WARNING: WebPlugin tab '%s' did not return a string!", Tab->Title.c_str()); } RetVal += tolua_tostring(m_LuaState, -1, 0); @@ -1640,13 +1604,13 @@ bool cPlugin_NewLua::CallbackWindowClosing(int a_FnRef, cWindow & a_Window, cPla ASSERT(a_FnRef != LUA_REFNIL); cCSLock Lock(m_CriticalSection); - lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_FnRef); // Push the function to be called - tolua_pushusertype(m_LuaState, &a_Window, "cWindow"); - tolua_pushusertype(m_LuaState, &a_Player, "cPlayer"); - tolua_pushboolean (m_LuaState, a_CanRefuse ? 1 : 0); + m_LuaState.PushFunctionFromRegistry(a_FnRef); + m_LuaState.PushUserType(&a_Window, "cWindow"); + m_LuaState.PushObject(&a_Player); + m_LuaState.PushBool(a_CanRefuse); // Call function: - if (!m_LuaState.CallFunction(3, 1, __FUNCTION__)) + if (!m_LuaState.CallFunction(1)) { LOGWARNING("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState)); return false; @@ -1666,12 +1630,12 @@ void cPlugin_NewLua::CallbackWindowSlotChanged(int a_FnRef, cWindow & a_Window, ASSERT(a_FnRef != LUA_REFNIL); cCSLock Lock(m_CriticalSection); - lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_FnRef); // Push the function to be called - tolua_pushusertype(m_LuaState, &a_Window, "cWindow"); - tolua_pushnumber (m_LuaState, a_SlotNum); + m_LuaState.PushFunctionFromRegistry(a_FnRef); + m_LuaState.PushUserType(&a_Window, "cWindow"); + m_LuaState.PushNumber(a_SlotNum); // Call function: - if (!m_LuaState.CallFunction(2, 0, __FUNCTION__)) + if (!m_LuaState.CallFunction(0)) { LOGWARNING("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState)); } From 4034136922a5b47450fa25c6be4bc35411a8d1ba Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 6 Aug 2013 17:17:26 +0200 Subject: [PATCH 11/19] cLuaState is used for pushing splits in ManualBindings --- source/ManualBindings.cpp | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/source/ManualBindings.cpp b/source/ManualBindings.cpp index 141335602..292b33726 100644 --- a/source/ManualBindings.cpp +++ b/source/ManualBindings.cpp @@ -25,13 +25,6 @@ -// fwd: LuaCommandBinder.cpp -// bool cLuaState::ReportErrors(lua_State* lua, int status); - - - - - /**************************** * Better error reporting for Lua **/ @@ -84,23 +77,14 @@ int lua_do_error(lua_State* L, const char * a_pFormat, ...) * Lua bound functions with special return types **/ -static int tolua_StringSplit(lua_State* tolua_S) +static int tolua_StringSplit(lua_State * tolua_S) { - std::string str = ((std::string) tolua_tocppstring(tolua_S,1,0)); - std::string delim = ((std::string) tolua_tocppstring(tolua_S,2,0)); + cLuaState LuaState(tolua_S); + std::string str = (std::string)tolua_tocppstring(LuaState, 1, 0); + std::string delim = (std::string)tolua_tocppstring(LuaState, 2, 0); - AStringVector Split = StringSplit( str, delim ); - - lua_createtable(tolua_S, Split.size(), 0); - int newTable = lua_gettop(tolua_S); - int index = 1; - std::vector::const_iterator iter = Split.begin(); - while(iter != Split.end()) { - tolua_pushstring( tolua_S, (*iter).c_str() ); - lua_rawseti(tolua_S, newTable, index); - ++iter; - ++index; - } + AStringVector Split = StringSplit(str, delim); + LuaState.PushStringVector(Split); return 1; } @@ -158,7 +142,8 @@ cPlugin_NewLua * GetLuaPlugin(lua_State * L) lua_getglobal(L, LUA_PLUGIN_INSTANCE_VAR_NAME); if (!lua_islightuserdata(L, -1)) { - LOGERROR("%s: cannot get plugin instance, what have you done to my Lua state?", __FUNCTION__); + LOGWARNING("%s: cannot get plugin instance, what have you done to my Lua state?", __FUNCTION__); + lua_pop(L); return NULL; } cPlugin_NewLua * Plugin = (cPlugin_NewLua *)lua_topointer(L, -1); From 0281b1db6e862af628bd9ea6712ce7e2f66cc4d8 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 6 Aug 2013 19:27:48 +0200 Subject: [PATCH 12/19] Fixed compilation in ManualBindings --- source/ManualBindings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/ManualBindings.cpp b/source/ManualBindings.cpp index 292b33726..f428b0905 100644 --- a/source/ManualBindings.cpp +++ b/source/ManualBindings.cpp @@ -143,7 +143,7 @@ cPlugin_NewLua * GetLuaPlugin(lua_State * L) if (!lua_islightuserdata(L, -1)) { LOGWARNING("%s: cannot get plugin instance, what have you done to my Lua state?", __FUNCTION__); - lua_pop(L); + lua_pop(L, 1); return NULL; } cPlugin_NewLua * Plugin = (cPlugin_NewLua *)lua_topointer(L, -1); From c55fabb5ad34ec57760b90ea11960f7f426990db Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 6 Aug 2013 19:28:09 +0200 Subject: [PATCH 13/19] cLuaScript now uses cLuaState --- MCServer/webadmin/template.lua | 16 ++- source/LuaScript.cpp | 232 +++------------------------------ source/LuaScript.h | 36 +++-- source/LuaState.cpp | 2 +- source/WebAdmin.cpp | 8 +- 5 files changed, 51 insertions(+), 243 deletions(-) diff --git a/MCServer/webadmin/template.lua b/MCServer/webadmin/template.lua index f508ad5aa..1ab1aab88 100644 --- a/MCServer/webadmin/template.lua +++ b/MCServer/webadmin/template.lua @@ -4,6 +4,10 @@ function Output(String) table.insert(SiteContent, String) end + + + + function GetTableSize(Table) local Size = 0 for key,value in pairs(Table) do @@ -12,6 +16,10 @@ function GetTableSize(Table) return Size end + + + + function GetDefaultPage() local PM = cRoot:Get():GetPluginManager() @@ -42,11 +50,15 @@ function GetDefaultPage() return Content, SubTitle end + + + + function ShowPage(WebAdmin, TemplateRequest) SiteContent = {} local BaseURL = WebAdmin:GetBaseURL(TemplateRequest.Request.Path) local Title = "MCServer" - local MemoryUsage = WebAdmin:GetMemoryUsage() + local MemoryUsage = cWebAdmin:GetMemoryUsage() local NumChunks = cRoot:Get():GetTotalChunkCount() local PluginPage = WebAdmin:GetPage(TemplateRequest.Request) local PageContent = PluginPage.Content @@ -408,6 +420,7 @@ function ShowPage(WebAdmin, TemplateRequest)