From 6e86d20f730aa46e0fa6b13b26a3b2586d21e513 Mon Sep 17 00:00:00 2001 From: tycho Date: Thu, 24 Sep 2015 15:43:31 +0100 Subject: Add new "ForEach" function: ForEachLoadedChunk. --- CONTRIBUTORS | 1 + src/Bindings/ManualBindings_World.cpp | 54 +++++++++++++++++++++++++++++++++++ src/ChunkMap.cpp | 28 ++++++++++++++++++ src/ChunkMap.h | 3 ++ src/World.cpp | 9 ++++++ src/World.h | 5 +++- 6 files changed, 99 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index f4b527000..153611eba 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -40,6 +40,7 @@ Taugeshtu tigerw (Tiger Wang) tonibm19 UltraCoderRU +Warmist WebFreak001 worktycho xoft (Mattes Dolak/madmaxoft on GH) diff --git a/src/Bindings/ManualBindings_World.cpp b/src/Bindings/ManualBindings_World.cpp index e2902b81a..e007a9689 100644 --- a/src/Bindings/ManualBindings_World.cpp +++ b/src/Bindings/ManualBindings_World.cpp @@ -110,6 +110,59 @@ static int tolua_cWorld_ChunkStay(lua_State * tolua_S) +static int tolua_cWorld_ForEachLoadedChunk(lua_State * tolua_S) +{ + // Exported manually, because tolua doesn't support converting functions to functor types. + // Function signature: ForEachLoadedChunk(callback) -> bool + + cLuaState L(tolua_S); + if ( + !L.CheckParamUserType(1, "cWorld") || + !L.CheckParamFunction(2) + ) + { + return 0; + } + + cPluginLua * Plugin = cManualBindings::GetLuaPlugin(tolua_S); + if (Plugin == nullptr) + { + return 0; + } + + // Read the params: + cWorld * World = (cWorld *)tolua_tousertype(tolua_S, 1, nullptr); + if (World == nullptr) + { + LOGWARNING("World:ForEachLoadedChunk(): invalid world parameter"); + L.LogStackTrace(); + return 0; + } + cLuaState::cRef FnRef; + L.GetStackValues(2, FnRef); + if (!FnRef.IsValid()) + { + return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #2"); + } + + // Call the enumeration: + bool ret = World->ForEachLoadedChunk( + [&L, &FnRef](int a_ChunkX, int a_ChunkZ) -> bool + { + bool res = false; // By default continue the enumeration + L.Call(FnRef, a_ChunkX, a_ChunkZ, cLuaState::Return, res); + return res; + } + ); + + // Push the return value: + L.Push(ret); + return 1; +} + + + + static int tolua_cWorld_GetBlockInfo(lua_State * tolua_S) { @@ -580,6 +633,7 @@ void cManualBindings::BindWorld(lua_State * tolua_S) tolua_function(tolua_S, "ForEachEntityInChunk", ForEachInChunk); tolua_function(tolua_S, "ForEachFurnaceInChunk", ForEachInChunk); tolua_function(tolua_S, "ForEachPlayer", ForEach< cWorld, cPlayer, &cWorld::ForEachPlayer>); + tolua_function(tolua_S, "ForEachLoadedChunk", tolua_cWorld_ForEachLoadedChunk); tolua_function(tolua_S, "GetBlockInfo", tolua_cWorld_GetBlockInfo); tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cWorld_GetBlockTypeMeta); tolua_function(tolua_S, "GetSignLines", tolua_cWorld_GetSignLines); diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp index aeae8f350..a11ceb060 100644 --- a/src/ChunkMap.cpp +++ b/src/ChunkMap.cpp @@ -2576,6 +2576,34 @@ bool cChunkMap::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinCh +bool cChunkMap::ForEachLoadedChunk(std::function a_Callback) +{ + cCSLock Lock(m_CSLayers); + for (cChunkLayerList::const_iterator itr = m_Layers.begin(); itr != m_Layers.end(); ++itr) // iterate over ALL loaded layers + { + cChunkLayer * layer = *itr; + for (int x = 0; x < LAYER_SIZE; x++) + { + for (int z = 0; z < LAYER_SIZE; z++) + { + cChunkPtr p = layer->FindChunk(layer->GetX() * LAYER_SIZE + x, layer->GetZ() * LAYER_SIZE + z); + if ((p != nullptr) && p->IsValid()) // if chunk is loaded + { + if (a_Callback(p->GetPosX(), p->GetPosZ())) + { + return false; + } + } + } + } + } + return true; +} + + + + + bool cChunkMap::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) { // Convert block coords to chunks coords: diff --git a/src/ChunkMap.h b/src/ChunkMap.h index 4974671da..e9309dbd8 100644 --- a/src/ChunkMap.h +++ b/src/ChunkMap.h @@ -344,6 +344,9 @@ public: /** Calls the callback for each chunk in the coords specified (all cords are inclusive). Returns true if all chunks have been processed successfully */ bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback); + + /** Calls the callback for each loaded chunk. Returns true if all chunks have been processed successfully */ + bool ForEachLoadedChunk(std::function a_Callback); /** Writes the block area into the specified coords. Returns true if all chunks have been processed. Prefer cBlockArea::Write() instead. */ bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes); diff --git a/src/World.cpp b/src/World.cpp index eb96eb57a..5920b83fe 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -3140,6 +3140,15 @@ bool cWorld::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunk +bool cWorld::ForEachLoadedChunk(std::function a_Callback) +{ + return m_ChunkMap->ForEachLoadedChunk(a_Callback); +} + + + + + void cWorld::SaveAllChunks(void) { m_LastSave = std::chrono::duration_cast(m_WorldAge); diff --git a/src/World.h b/src/World.h index 1ee473970..1902296be 100644 --- a/src/World.h +++ b/src/World.h @@ -27,7 +27,7 @@ #include "Blocks/BroadcastInterface.h" #include "FastRandom.h" #include "ClientHandle.h" - +#include @@ -434,6 +434,9 @@ public: /** Calls the callback for each chunk in the coords specified (all cords are inclusive). Returns true if all chunks have been processed successfully */ virtual bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback) override; + /** Calls the callback for each loaded chunk. Returns true if all chunks have been processed successfully */ + bool ForEachLoadedChunk(std::function a_Callback); + // tolua_begin /** Sets the block at the specified coords to the specified value. -- cgit v1.2.3