From 9455f59b1100f3db2c5b1e88bb9d1f6a01664721 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 9 Feb 2014 18:56:16 +0100 Subject: Initial Lua cChunkStay export. --- src/Bindings/LuaChunkStay.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/Bindings/LuaChunkStay.cpp (limited to 'src/Bindings/LuaChunkStay.cpp') diff --git a/src/Bindings/LuaChunkStay.cpp b/src/Bindings/LuaChunkStay.cpp new file mode 100644 index 000000000..606f7694f --- /dev/null +++ b/src/Bindings/LuaChunkStay.cpp @@ -0,0 +1,52 @@ + +// LuaChunkStay.cpp + +// Implements the cLuaChunkStay class representing a cChunkStay binding for plugins + +#include "Globals.h" +#include "LuaChunkStay.h" +#include "../World.h" + + + + + +void cLuaChunkStay::Enable( + cWorld & a_World, cLuaState & a_LuaState, + const cLuaState::cRef & a_OnChunkAvailable, const cLuaState::cRef & a_OnAllChunksAvailable +) +{ + if (m_LuaState != NULL) + { + LOGWARNING("LuaChunkStay: Already enabled. Ignoring this call."); + a_LuaState.LogStackTrace(); + return; + } + m_LuaState = &a_LuaState; + m_OnChunkAvailable = a_OnAllChunksAvailable; + m_OnAllChunksAvailable = a_OnAllChunksAvailable; + super::Enable(*a_World.GetChunkMap()); +} + + + + + +void cLuaChunkStay::OnChunkAvailable(int a_ChunkX, int a_ChunkZ) +{ + m_LuaState->Call(m_OnChunkAvailable, a_ChunkX, a_ChunkZ); +} + + + + + +void cLuaChunkStay::OnAllChunksAvailable(void) +{ + m_LuaState->Call(m_OnAllChunksAvailable); +} + + + + + -- cgit v1.2.3 From 47a497fa895fa5f353ba593d4bb232ea514e66c9 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 9 Feb 2014 20:39:45 +0100 Subject: First working version of cLuaChunkStay. It works, but has random failures, probably due to threading issues. --- src/Bindings/LuaChunkStay.cpp | 45 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) (limited to 'src/Bindings/LuaChunkStay.cpp') diff --git a/src/Bindings/LuaChunkStay.cpp b/src/Bindings/LuaChunkStay.cpp index 606f7694f..f84964f56 100644 --- a/src/Bindings/LuaChunkStay.cpp +++ b/src/Bindings/LuaChunkStay.cpp @@ -11,20 +11,29 @@ +cLuaChunkStay::cLuaChunkStay(void) : + m_LuaState((lua_State *)NULL) // Want a detached Lua state by default +{ +} + + + + + void cLuaChunkStay::Enable( - cWorld & a_World, cLuaState & a_LuaState, - const cLuaState::cRef & a_OnChunkAvailable, const cLuaState::cRef & a_OnAllChunksAvailable + cWorld & a_World, lua_State * a_LuaState, + int a_OnChunkAvailableStackPos, int a_OnAllChunksAvailableStackPos ) { - if (m_LuaState != NULL) + if (m_LuaState.IsValid()) { LOGWARNING("LuaChunkStay: Already enabled. Ignoring this call."); - a_LuaState.LogStackTrace(); + cLuaState::LogStackTrace(a_LuaState); return; } - m_LuaState = &a_LuaState; - m_OnChunkAvailable = a_OnAllChunksAvailable; - m_OnAllChunksAvailable = a_OnAllChunksAvailable; + m_LuaState.Attach(a_LuaState); + m_OnChunkAvailable.RefStack(m_LuaState, a_OnChunkAvailableStackPos); + m_OnAllChunksAvailable.RefStack(m_LuaState, a_OnAllChunksAvailableStackPos); super::Enable(*a_World.GetChunkMap()); } @@ -32,9 +41,27 @@ void cLuaChunkStay::Enable( +void cLuaChunkStay::Disable(void) +{ + super::Disable(); + + // If the state was valid (bound to Lua functions), unbind those functions: + if (!m_LuaState.IsValid()) + { + return; + } + m_OnAllChunksAvailable.UnRef(); + m_OnChunkAvailable.UnRef(); + m_LuaState.Detach(); +} + + + + + void cLuaChunkStay::OnChunkAvailable(int a_ChunkX, int a_ChunkZ) { - m_LuaState->Call(m_OnChunkAvailable, a_ChunkX, a_ChunkZ); + m_LuaState.Call(m_OnChunkAvailable, a_ChunkX, a_ChunkZ); } @@ -43,7 +70,7 @@ void cLuaChunkStay::OnChunkAvailable(int a_ChunkX, int a_ChunkZ) void cLuaChunkStay::OnAllChunksAvailable(void) { - m_LuaState->Call(m_OnAllChunksAvailable); + m_LuaState.Call(m_OnAllChunksAvailable); } -- cgit v1.2.3 From 9cebc9157cf43ba639227b9d79b980b3613dda1e Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 10 Feb 2014 22:47:10 +0100 Subject: Rewritten Lua ChunkStay API into a single function, cWorld:ChunkStay(). This fixes problems with indeterminate class object lifespan (Lua-GC) and forgetting to disable it or keep it until ready. --- src/Bindings/LuaChunkStay.cpp | 146 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 120 insertions(+), 26 deletions(-) (limited to 'src/Bindings/LuaChunkStay.cpp') diff --git a/src/Bindings/LuaChunkStay.cpp b/src/Bindings/LuaChunkStay.cpp index f84964f56..0e982637f 100644 --- a/src/Bindings/LuaChunkStay.cpp +++ b/src/Bindings/LuaChunkStay.cpp @@ -1,18 +1,20 @@ // LuaChunkStay.cpp -// Implements the cLuaChunkStay class representing a cChunkStay binding for plugins +// Implements the cLuaChunkStay class representing a cChunkStay binding for plugins, used by cWorld:ChunkStay() Lua API #include "Globals.h" #include "LuaChunkStay.h" +#include "PluginLua.h" #include "../World.h" -cLuaChunkStay::cLuaChunkStay(void) : - m_LuaState((lua_State *)NULL) // Want a detached Lua state by default +cLuaChunkStay::cLuaChunkStay(cPluginLua & a_Plugin) : + m_Plugin(a_Plugin), + m_LuaState(NULL) { } @@ -20,39 +22,107 @@ cLuaChunkStay::cLuaChunkStay(void) : -void cLuaChunkStay::Enable( - cWorld & a_World, lua_State * a_LuaState, - int a_OnChunkAvailableStackPos, int a_OnAllChunksAvailableStackPos -) +bool cLuaChunkStay::AddChunks(int a_ChunkCoordTableStackPos) { - if (m_LuaState.IsValid()) + // This function is expected to be called just once, with all the coords in a table + ASSERT(m_Chunks.empty()); + + cPluginLua::cOperation Op(m_Plugin); + cLuaState & L = Op(); + + // Check that we got a table: + if (!lua_istable(L, a_ChunkCoordTableStackPos)) { - LOGWARNING("LuaChunkStay: Already enabled. Ignoring this call."); - cLuaState::LogStackTrace(a_LuaState); - return; + LOGWARNING("%s: The parameter is not a table of coords (got %s). Ignoring the call.", + __FUNCTION__, lua_typename(L, lua_type(L, a_ChunkCoordTableStackPos)) + ); + L.LogStackTrace(); + return false; + } + + // Add each set of coords: + int NumChunks = luaL_getn(L, a_ChunkCoordTableStackPos); + m_Chunks.reserve(NumChunks); + for (int idx = 1; idx <= NumChunks; idx++) + { + // Push the idx-th element of the array onto stack top, check that it's a table: + lua_rawgeti(L, a_ChunkCoordTableStackPos, idx); + if (!lua_istable(L, -1)) + { + LOGWARNING("%s: Element #%d is not a table (got %s). Ignoring the element.", + __FUNCTION__, idx, lua_typename(L, -1) + ); + L.LogStackTrace(); + lua_pop(L, 1); + continue; + } + AddChunkCoord(L, idx); + lua_pop(L, 1); } - m_LuaState.Attach(a_LuaState); - m_OnChunkAvailable.RefStack(m_LuaState, a_OnChunkAvailableStackPos); - m_OnAllChunksAvailable.RefStack(m_LuaState, a_OnAllChunksAvailableStackPos); - super::Enable(*a_World.GetChunkMap()); + + // If there are no chunks, log a warning and return failure: + if (m_Chunks.empty()) + { + LOGWARNING("%s: Zero chunks to stay.", __FUNCTION__); + L.LogStackTrace(); + return false; + } + + // All ok + return true; } -void cLuaChunkStay::Disable(void) +void cLuaChunkStay::AddChunkCoord(cLuaState & L, int a_Index) { - super::Disable(); - - // If the state was valid (bound to Lua functions), unbind those functions: - if (!m_LuaState.IsValid()) + // Check that the element has 2 coords: + int NumCoords = luaL_getn(L, -1); + if (NumCoords != 2) { + LOGWARNING("%s: Element #%d doesn't contain 2 coords (got %d). Ignoring the element.", + __FUNCTION__, a_Index, NumCoords + ); return; } - m_OnAllChunksAvailable.UnRef(); - m_OnChunkAvailable.UnRef(); - m_LuaState.Detach(); + + // Read the two coords from the element: + lua_rawgeti(L, -1, 1); + lua_rawgeti(L, -2, 2); + int ChunkX = luaL_checkint(L, -2); + int ChunkZ = luaL_checkint(L, -1); + lua_pop(L, 2); + + // Check that a coord is not yet present: + for (cChunkCoordsVector::iterator itr = m_Chunks.begin(), end = m_Chunks.end(); itr != end; ++itr) + { + if ((itr->m_ChunkX == ChunkX) && (itr->m_ChunkZ == ChunkZ)) + { + LOGWARNING("%s: Element #%d is a duplicate, ignoring it.", + __FUNCTION__, a_Index + ); + return; + } + } // for itr - m_Chunks[] + + m_Chunks.push_back(cChunkCoords(ChunkX, ZERO_CHUNK_Y, ChunkZ)); +} + + + + + +void cLuaChunkStay::Enable(cChunkMap & a_ChunkMap, int a_OnChunkAvailableStackPos, int a_OnAllChunksAvailableStackPos) +{ + // Get the references to the callback functions: + m_LuaState = &m_Plugin.GetLuaState(); + m_OnChunkAvailable.RefStack(*m_LuaState, a_OnChunkAvailableStackPos); + m_OnAllChunksAvailable.RefStack(*m_LuaState, a_OnAllChunksAvailableStackPos); + + // Enable the ChunkStay: + super::Enable(a_ChunkMap); } @@ -61,19 +131,43 @@ void cLuaChunkStay::Disable(void) void cLuaChunkStay::OnChunkAvailable(int a_ChunkX, int a_ChunkZ) { - m_LuaState.Call(m_OnChunkAvailable, a_ChunkX, a_ChunkZ); + // DEBUG: + LOGD("LuaChunkStay: Chunk [%d, %d] is now available, calling the callback...", a_ChunkX, a_ChunkZ); + + cPluginLua::cOperation Op(m_Plugin); + Op().Call((int)m_OnChunkAvailable, a_ChunkX, a_ChunkZ); } -void cLuaChunkStay::OnAllChunksAvailable(void) +bool cLuaChunkStay::OnAllChunksAvailable(void) { - m_LuaState.Call(m_OnAllChunksAvailable); + { + // Call the callback: + cPluginLua::cOperation Op(m_Plugin); + Op().Call((int)m_OnAllChunksAvailable); + + // Remove the callback references - they won't be needed anymore + m_OnChunkAvailable.UnRef(); + m_OnAllChunksAvailable.UnRef(); + } + + // Disable the ChunkStay by returning true + return true; } +void cLuaChunkStay::OnDisabled(void) +{ + // This object is no longer needed, delete it + delete this; +} + + + + -- cgit v1.2.3