diff --git a/source/BlockEntities/BlockEntity.h b/source/BlockEntities/BlockEntity.h index a2de3160a..0d358b556 100644 --- a/source/BlockEntities/BlockEntity.h +++ b/source/BlockEntities/BlockEntity.h @@ -52,6 +52,11 @@ public: /// Returns NULL for unknown block types static cBlockEntity * CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World = NULL); + static const char * GetClassStatic(void) // Needed for ManualBindings's ForEach templates + { + return "cBlockEntity"; + } + // tolua_begin // Position, in absolute block coordinates: diff --git a/source/Chunk.cpp b/source/Chunk.cpp index 6e83d32ea..7e71e9ea7 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -1840,6 +1840,24 @@ bool cChunk::DoWithEntityByID(int a_EntityID, cEntityCallback & a_Callback, bool +bool cChunk::ForEachBlockEntity(cBlockEntityCallback & a_Callback) +{ + // The blockentity list is locked by the parent chunkmap's CS + for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2) + { + ++itr2; + if (a_Callback.Item(*itr)) + { + return false; + } + } // for itr - m_BlockEntitites[] + return true; +} + + + + + bool cChunk::ForEachChest(cChestCallback & a_Callback) { // The blockentity list is locked by the parent chunkmap's CS @@ -1958,6 +1976,32 @@ bool cChunk::ForEachFurnace(cFurnaceCallback & a_Callback) +bool cChunk::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback) +{ + // The blockentity list is locked by the parent chunkmap's CS + for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2) + { + ++itr2; + if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ)) + { + continue; + } + + if (a_Callback.Item(*itr)) + { + return false; + } + return true; + } // for itr - m_BlockEntitites[] + + // Not found: + return false; +} + + + + + bool cChunk::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback) { // The blockentity list is locked by the parent chunkmap's CS diff --git a/source/Chunk.h b/source/Chunk.h index 0d7479347..895b407a3 100644 --- a/source/Chunk.h +++ b/source/Chunk.h @@ -207,6 +207,9 @@ public: /// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found. bool DoWithEntityByID(int a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackResult); // Lua-accessible + /// Calls the callback for each block entity; returns true if all block entities processed, false if the callback aborted by returning true + bool ForEachBlockEntity(cBlockEntityCallback & a_Callback); // Lua-accessible + /// Calls the callback for each chest; returns true if all chests processed, false if the callback aborted by returning true bool ForEachChest(cChestCallback & a_Callback); // Lua-accessible @@ -222,6 +225,9 @@ public: /// Calls the callback for each furnace; returns true if all furnaces processed, false if the callback aborted by returning true bool ForEachFurnace(cFurnaceCallback & a_Callback); // Lua-accessible + /// Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found + bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback); // Lua-acessible + /// Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Lua-acessible diff --git a/source/ChunkMap.cpp b/source/ChunkMap.cpp index 73a16dbb4..9d55917e5 100644 --- a/source/ChunkMap.cpp +++ b/source/ChunkMap.cpp @@ -1702,6 +1702,21 @@ bool cChunkMap::DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback) +bool cChunkMap::ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback & a_Callback) +{ + cCSLock Lock(m_CSLayers); + cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ); + if ((Chunk == NULL) && !Chunk->IsValid()) + { + return false; + } + return Chunk->ForEachBlockEntity(a_Callback); +} + + + + + bool cChunkMap::ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback & a_Callback) { cCSLock Lock(m_CSLayers); @@ -1777,6 +1792,24 @@ bool cChunkMap::ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallba +bool cChunkMap::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback) +{ + int ChunkX, ChunkZ; + int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ; + cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ); + cCSLock Lock(m_CSLayers); + cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ); + if ((Chunk == NULL) && !Chunk->IsValid()) + { + return false; + } + return Chunk->DoWithBlockEntityAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback); +} + + + + + bool cChunkMap::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback) { int ChunkX, ChunkZ; diff --git a/source/ChunkMap.h b/source/ChunkMap.h index f68cb6472..2a1d78ff8 100644 --- a/source/ChunkMap.h +++ b/source/ChunkMap.h @@ -32,6 +32,7 @@ class cMobSpawner; typedef std::list cClientHandleList; typedef cChunk * cChunkPtr; typedef cItemCallback cEntityCallback; +typedef cItemCallback cBlockEntityCallback; typedef cItemCallback cChestCallback; typedef cItemCallback cDispenserCallback; typedef cItemCallback cDropperCallback; @@ -191,8 +192,11 @@ public: /// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found and callback returned false. bool DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback); // Lua-accessible + /// Calls the callback for each block entity in the specified chunk; returns true if all block entities processed, false if the callback aborted by returning true + bool ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback & a_Callback); // Lua-accessible + /// Calls the callback for each chest in the specified chunk; returns true if all chests processed, false if the callback aborted by returning true - bool ForEachChestInChunk (int a_ChunkX, int a_ChunkZ, cChestCallback & a_Callback); // Lua-accessible + bool ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback & a_Callback); // Lua-accessible /// Calls the callback for each dispenser in the specified chunk; returns true if all dispensers processed, false if the callback aborted by returning true bool ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, cDispenserCallback & a_Callback); @@ -206,8 +210,11 @@ public: /// Calls the callback for each furnace in the specified chunk; returns true if all furnaces processed, false if the callback aborted by returning true bool ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback & a_Callback); // Lua-accessible + /// Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found + bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback); // Lua-acessible + /// Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found - bool DoWithChestAt (int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Lua-acessible + bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Lua-acessible /// Calls the callback for the dispenser at the specified coords; returns false if there's no dispenser at those coords or callback returns true, returns true if found bool DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback & a_Callback); // Lua-accessible diff --git a/source/ManualBindings.cpp b/source/ManualBindings.cpp index f98e25880..59bd0657c 100644 --- a/source/ManualBindings.cpp +++ b/source/ManualBindings.cpp @@ -2128,26 +2128,28 @@ void ManualBindings::Bind(lua_State * tolua_S) tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cWorld"); - tolua_function(tolua_S, "DoWithChestAt", tolua_DoWithXYZ); - tolua_function(tolua_S, "DoWithDispenserAt", tolua_DoWithXYZ); - tolua_function(tolua_S, "DoWithDropSpenserAt", tolua_DoWithXYZ); - tolua_function(tolua_S, "DoWithDropperAt", tolua_DoWithXYZ); - tolua_function(tolua_S, "DoWithEntityByID", tolua_DoWithID< cWorld, cEntity, &cWorld::DoWithEntityByID>); - tolua_function(tolua_S, "DoWithFurnaceAt", tolua_DoWithXYZ); - tolua_function(tolua_S, "DoWithPlayer", tolua_DoWith< cWorld, cPlayer, &cWorld::DoWithPlayer>); - tolua_function(tolua_S, "FindAndDoWithPlayer", tolua_DoWith< cWorld, cPlayer, &cWorld::FindAndDoWithPlayer>); - tolua_function(tolua_S, "ForEachChestInChunk", tolua_ForEachInChunk); - tolua_function(tolua_S, "ForEachEntity", tolua_ForEach< cWorld, cEntity, &cWorld::ForEachEntity>); - tolua_function(tolua_S, "ForEachEntityInChunk", tolua_ForEachInChunk); - tolua_function(tolua_S, "ForEachFurnaceInChunk", tolua_ForEachInChunk); - tolua_function(tolua_S, "ForEachPlayer", tolua_ForEach< cWorld, cPlayer, &cWorld::ForEachPlayer>); - tolua_function(tolua_S, "GetBlockInfo", tolua_cWorld_GetBlockInfo); - tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cWorld_GetBlockTypeMeta); - tolua_function(tolua_S, "GetSignLines", tolua_cWorld_GetSignLines); - tolua_function(tolua_S, "QueueTask", tolua_cWorld_QueueTask); - tolua_function(tolua_S, "SetSignLines", tolua_cWorld_SetSignLines); - tolua_function(tolua_S, "TryGetHeight", tolua_cWorld_TryGetHeight); - tolua_function(tolua_S, "UpdateSign", tolua_cWorld_SetSignLines); + tolua_function(tolua_S, "DoWithBlockEntityAt", tolua_DoWithXYZ); + tolua_function(tolua_S, "DoWithChestAt", tolua_DoWithXYZ); + tolua_function(tolua_S, "DoWithDispenserAt", tolua_DoWithXYZ); + tolua_function(tolua_S, "DoWithDropSpenserAt", tolua_DoWithXYZ); + tolua_function(tolua_S, "DoWithDropperAt", tolua_DoWithXYZ); + tolua_function(tolua_S, "DoWithEntityByID", tolua_DoWithID< cWorld, cEntity, &cWorld::DoWithEntityByID>); + tolua_function(tolua_S, "DoWithFurnaceAt", tolua_DoWithXYZ); + tolua_function(tolua_S, "DoWithPlayer", tolua_DoWith< cWorld, cPlayer, &cWorld::DoWithPlayer>); + tolua_function(tolua_S, "FindAndDoWithPlayer", tolua_DoWith< cWorld, cPlayer, &cWorld::FindAndDoWithPlayer>); + tolua_function(tolua_S, "ForEachBlockEntityInChunk", tolua_ForEachInChunk); + tolua_function(tolua_S, "ForEachChestInChunk", tolua_ForEachInChunk); + tolua_function(tolua_S, "ForEachEntity", tolua_ForEach< cWorld, cEntity, &cWorld::ForEachEntity>); + tolua_function(tolua_S, "ForEachEntityInChunk", tolua_ForEachInChunk); + tolua_function(tolua_S, "ForEachFurnaceInChunk", tolua_ForEachInChunk); + tolua_function(tolua_S, "ForEachPlayer", tolua_ForEach< cWorld, cPlayer, &cWorld::ForEachPlayer>); + tolua_function(tolua_S, "GetBlockInfo", tolua_cWorld_GetBlockInfo); + tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cWorld_GetBlockTypeMeta); + tolua_function(tolua_S, "GetSignLines", tolua_cWorld_GetSignLines); + tolua_function(tolua_S, "QueueTask", tolua_cWorld_QueueTask); + tolua_function(tolua_S, "SetSignLines", tolua_cWorld_SetSignLines); + tolua_function(tolua_S, "TryGetHeight", tolua_cWorld_TryGetHeight); + tolua_function(tolua_S, "UpdateSign", tolua_cWorld_SetSignLines); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cPlugin"); diff --git a/source/World.cpp b/source/World.cpp index 0f9df8a62..531952e37 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -922,6 +922,15 @@ void cWorld::WakeUpSimulatorsInArea(int a_MinBlockX, int a_MaxBlockX, int a_MinB +bool cWorld::ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback & a_Callback) +{ + return m_ChunkMap->ForEachBlockEntityInChunk(a_ChunkX, a_ChunkZ, a_Callback); +} + + + + + bool cWorld::ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback & a_Callback) { return m_ChunkMap->ForEachChestInChunk(a_ChunkX, a_ChunkZ, a_Callback); @@ -1010,6 +1019,15 @@ void cWorld::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_Blo +bool cWorld::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback) +{ + return m_ChunkMap->DoWithBlockEntityAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback); +} + + + + + bool cWorld::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback) { return m_ChunkMap->DoWithChestAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback); diff --git a/source/World.h b/source/World.h index ee4a23b14..d10aa3b78 100644 --- a/source/World.h +++ b/source/World.h @@ -385,8 +385,11 @@ public: inline cFluidSimulator * GetWaterSimulator(void) { return m_WaterSimulator; } inline cFluidSimulator * GetLavaSimulator (void) { return m_LavaSimulator; } + /// Calls the callback for each block entity in the specified chunk; returns true if all block entities processed, false if the callback aborted by returning true + bool ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback & a_Callback); // Exported in ManualBindings.cpp + /// Calls the callback for each chest in the specified chunk; returns true if all chests processed, false if the callback aborted by returning true - bool ForEachChestInChunk (int a_ChunkX, int a_ChunkZ, cChestCallback & a_Callback); // Exported in ManualBindings.cpp + bool ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback & a_Callback); // Exported in ManualBindings.cpp /// Calls the callback for each dispenser in the specified chunk; returns true if all dispensers processed, false if the callback aborted by returning true bool ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, cDispenserCallback & a_Callback); @@ -415,8 +418,11 @@ public: */ void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData); // tolua_export + /// Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found + bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback); // Exported in ManualBindings.cpp + /// Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found - bool DoWithChestAt (int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Exported in ManualBindings.cpp + bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Exported in ManualBindings.cpp /// Calls the callback for the dispenser at the specified coords; returns false if there's no dispenser at those coords or callback returns true, returns true if found bool DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback & a_Callback); // Exported in ManualBindings.cpp