// LuaChunkStay.cpp // 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" cLuaChunkStay::cLuaChunkStay() { } bool cLuaChunkStay::AddChunks(const cLuaState::cStackTable & a_ChunkCoordsTable) { // This function is expected to be called just once, with all the coords in a table ASSERT(m_Chunks.empty()); // Add each set of coords: a_ChunkCoordsTable.ForEachArrayElement([=](cLuaState & a_LuaState, int a_Index) { if (!lua_istable(a_LuaState, -1)) { LOGWARNING("%s: Element #%d is not a table (got %s). Ignoring the element.", __FUNCTION__, a_Index, lua_typename(a_LuaState, -1) ); a_LuaState.LogStackTrace(); lua_pop(a_LuaState, 1); return false; } AddChunkCoord(a_LuaState, a_Index); return false; } ); // If there are no chunks, log a warning and return failure: if (m_Chunks.empty()) { LOGWARNING("%s: No valid chunk coords.", __FUNCTION__); a_ChunkCoordsTable.GetLuaState().LogStackTrace(); return false; } // All ok return true; } void cLuaChunkStay::AddChunkCoord(cLuaState & L, int a_Index) { // 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; } // 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.emplace_back(ChunkX, ChunkZ); } void cLuaChunkStay::Enable(cChunkMap & a_ChunkMap, cLuaState::cCallbackPtr a_OnChunkAvailable, cLuaState::cCallbackPtr a_OnAllChunksAvailable) { m_OnChunkAvailable = std::move(a_OnChunkAvailable); m_OnAllChunksAvailable = std::move(a_OnAllChunksAvailable); // Enable the ChunkStay: Super::Enable(a_ChunkMap); } void cLuaChunkStay::OnChunkAvailable(int a_ChunkX, int a_ChunkZ) { if (m_OnChunkAvailable != nullptr) { m_OnChunkAvailable->Call(a_ChunkX, a_ChunkZ); } } bool cLuaChunkStay::OnAllChunksAvailable(void) { if (m_OnAllChunksAvailable != nullptr) { // Call the callback: m_OnAllChunksAvailable->Call(); // Remove the callback references - they won't be needed anymore m_OnChunkAvailable.reset(); m_OnAllChunksAvailable.reset(); } // Disable the ChunkStay by returning true return true; } void cLuaChunkStay::OnDisabled(void) { // This object is no longer needed, delete it delete this; }