summaryrefslogtreecommitdiffstats
path: root/src/Bindings/LuaChunkStay.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Bindings/LuaChunkStay.cpp')
-rw-r--r--src/Bindings/LuaChunkStay.cpp146
1 files changed, 120 insertions, 26 deletions
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;
+}
+
+
+
+