From 9eb07f483a237f3fba21a761e7a19053032d2282 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 3 Sep 2014 16:56:59 +0200 Subject: cBoundingBox: Added accessors. --- src/BoundingBox.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src') diff --git a/src/BoundingBox.h b/src/BoundingBox.h index 793466302..928e62afa 100644 --- a/src/BoundingBox.h +++ b/src/BoundingBox.h @@ -80,6 +80,17 @@ public: /// Calculates the intersection of the two bounding boxes; returns true if nonempty bool Intersect(const cBoundingBox & a_Other, cBoundingBox & a_Intersection); + double GetMinX(void) const { return m_Min.x; } + double GetMinY(void) const { return m_Min.y; } + double GetMinZ(void) const { return m_Min.z; } + + double GetMaxX(void) const { return m_Max.x; } + double GetMaxY(void) const { return m_Max.y; } + double GetMaxZ(void) const { return m_Max.z; } + + const Vector3d & GetMin(void) const { return m_Min; } + const Vector3d & GetMax(void) const { return m_Max; } + protected: Vector3d m_Min; Vector3d m_Max; -- cgit v1.2.3 From a51c1e0b73a83cddcce865671ca30240393e458f Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 3 Sep 2014 17:00:26 +0200 Subject: Added cWorld::ForEachEntityInBox() --- src/Bindings/LuaState.cpp | 26 ++++++++++++++++++++++++++ src/Bindings/LuaState.h | 10 ++++++++++ src/Chunk.cpp | 25 +++++++++++++++++++++++++ src/Chunk.h | 4 ++++ src/ChunkMap.cpp | 32 ++++++++++++++++++++++++++++++++ src/ChunkMap.h | 6 ++++++ src/World.cpp | 9 +++++++++ src/World.h | 5 +++++ 8 files changed, 117 insertions(+) (limited to 'src') diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp index 9fe93ccc2..4ebb1e92f 100644 --- a/src/Bindings/LuaState.cpp +++ b/src/Bindings/LuaState.cpp @@ -859,6 +859,32 @@ void cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal) +void cLuaState::GetStackValue(int a_StackPos, pBoundingBox & a_ReturnedVal) +{ + tolua_Error err; + if (tolua_isusertable(m_LuaState, a_StackPos, "cBoundingBox", false, &err)) + { + a_ReturnedVal = (cBoundingBox *)lua_touserdata(m_LuaState, a_StackPos); + } +} + + + + + +void cLuaState::GetStackValue(int a_StackPos, pWorld & a_ReturnedVal) +{ + tolua_Error err; + if (tolua_isusertable(m_LuaState, a_StackPos, "cWorld", false, &err)) + { + a_ReturnedVal = (cWorld *)lua_touserdata(m_LuaState, a_StackPos); + } +} + + + + + bool cLuaState::CallFunction(int a_NumResults) { ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h index eeb93fd4d..fd506b10e 100644 --- a/src/Bindings/LuaState.h +++ b/src/Bindings/LuaState.h @@ -59,6 +59,10 @@ class cTNTEntity; class cCreeper; class cHopperEntity; class cBlockEntity; +class cBoundingBox; + +typedef cBoundingBox * pBoundingBox; +typedef cWorld * pWorld; @@ -230,6 +234,12 @@ public: /** Retrieve value at a_StackPos, if it is a valid number, converting and clamping it to eWeather. If not, a_Value is unchanged. */ void GetStackValue(int a_StackPos, eWeather & a_Value); + + /** Retrieve value at a_StackPos, if it is a valid cBoundingBox class. If not, a_Value is unchanged */ + void GetStackValue(int a_StackPos, pBoundingBox & a_Value); + + /** Retrieve value at a_StackPos, if it is a valid cWorld class. If not, a_Value is unchanged */ + void GetStackValue(int a_StackPos, pWorld & a_Value); // Include the cLuaState::Call() overload implementation that is generated by the gen_LuaState_Call.lua script: diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 40ffff834..20e943d9a 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -37,6 +37,7 @@ #include "MobSpawner.h" #include "BlockInServerPluginInterface.h" #include "SetChunkData.h" +#include "BoundingBox.h" #include "json/json.h" @@ -1960,6 +1961,30 @@ bool cChunk::ForEachEntity(cEntityCallback & a_Callback) +bool cChunk::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback) +{ + // The entity list is locked by the parent chunkmap's CS + for (cEntityList::iterator itr = m_Entities.begin(), itr2 = itr; itr != m_Entities.end(); itr = itr2) + { + ++itr2; + cBoundingBox EntBox((*itr)->GetPosition(), (*itr)->GetWidth() / 2, (*itr)->GetHeight()); + if (!EntBox.DoesIntersect(a_Box)) + { + // The entity is not in the specified box + continue; + } + if (a_Callback.Item(*itr)) + { + return false; + } + } // for itr - m_Entitites[] + return true; +} + + + + + bool cChunk::DoWithEntityByID(int a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackResult) { // The entity list is locked by the parent chunkmap's CS diff --git a/src/Chunk.h b/src/Chunk.h index e5de22e3b..008a351db 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -216,6 +216,10 @@ public: /** Calls the callback for each entity; returns true if all entities processed, false if the callback aborted by returning true */ bool ForEachEntity(cEntityCallback & a_Callback); // Lua-accessible + /** Calls the callback for each entity that has a nonempty intersection with the specified boundingbox. + Returns true if all entities processed, false if the callback aborted by returning true. */ + bool ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback); // Lua-accessible + /** 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 diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp index a3692ef11..ffc5e3d3f 100644 --- a/src/ChunkMap.cpp +++ b/src/ChunkMap.cpp @@ -1775,6 +1775,38 @@ bool cChunkMap::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback +bool cChunkMap::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback) +{ + // Calculate the chunk range for the box: + int MinChunkX = (int)floor(a_Box.GetMinX() / cChunkDef::Width); + int MinChunkZ = (int)floor(a_Box.GetMinZ() / cChunkDef::Width); + int MaxChunkX = (int)floor((a_Box.GetMaxX() + cChunkDef::Width) / cChunkDef::Width); + int MaxChunkZ = (int)floor((a_Box.GetMaxZ() + cChunkDef::Width) / cChunkDef::Width); + + // Iterate over each chunk in the range: + cCSLock Lock(m_CSLayers); + for (int z = MinChunkZ; z <= MaxChunkZ; z++) + { + for (int x = MinChunkX; x <= MaxChunkX; x++) + { + cChunkPtr Chunk = GetChunkNoGen(x, ZERO_CHUNK_Y, z); + if ((Chunk == NULL) || !Chunk->IsValid()) + { + continue; + } + if (!Chunk->ForEachEntityInBox(a_Box, a_Callback)) + { + return false; + } + } // for x + } // for z + return true; +} + + + + + void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, cVector3iArray & a_BlocksAffected) { // Don't explode if outside of Y range (prevents the following test running into unallocated memory): diff --git a/src/ChunkMap.h b/src/ChunkMap.h index 1e9a0f982..24a91dcd1 100644 --- a/src/ChunkMap.h +++ b/src/ChunkMap.h @@ -36,6 +36,7 @@ class cBlockArea; class cMobCensus; class cMobSpawner; class cSetChunkData; +class cBoundingBox; typedef std::list cClientHandleList; typedef cChunk * cChunkPtr; @@ -209,6 +210,11 @@ public: /** Calls the callback for each entity in the specified chunk; returns true if all entities processed, false if the callback aborted by returning true */ bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback); // Lua-accessible + /** Calls the callback for each entity that has a nonempty intersection with the specified boundingbox. + Returns true if all entities processed, false if the callback aborted by returning true. + If any chunk in the box is missing, ignores the entities in that chunk silently. */ + bool ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback); // Lua-accessible + /** Destroys and returns a list of blocks destroyed in the explosion at the specified coordinates */ void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, cVector3iArray & a_BlockAffected); diff --git a/src/World.cpp b/src/World.cpp index 99e09c658..d3751364f 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -2696,6 +2696,15 @@ bool cWorld::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & +bool cWorld::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback) +{ + return m_ChunkMap->ForEachEntityInBox(a_Box, a_Callback); +} + + + + + bool cWorld::DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback) { return m_ChunkMap->DoWithEntityByID(a_UniqueID, a_Callback); diff --git a/src/World.h b/src/World.h index 578c9682b..d4acb52d4 100644 --- a/src/World.h +++ b/src/World.h @@ -324,6 +324,11 @@ public: /** Calls the callback for each entity in the specified chunk; returns true if all entities processed, false if the callback aborted by returning true */ bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback); // Exported in ManualBindings.cpp + /** Calls the callback for each entity that has a nonempty intersection with the specified boundingbox. + Returns true if all entities processed, false if the callback aborted by returning true. + If any chunk in the box is missing, ignores the entities in that chunk silently. */ + bool ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback); // Exported in ManualBindings.cpp + /** 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); // Exported in ManualBindings.cpp -- cgit v1.2.3 From a9ed5baba35b012f577ca6c6cca970042fc4edf0 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 3 Sep 2014 17:01:23 +0200 Subject: Exported ForEachEntityInBox() to Lua API. --- src/Bindings/ManualBindings.cpp | 70 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'src') diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index adf10a72f..b7ea65759 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -676,6 +676,75 @@ static int tolua_ForEachInChunk(lua_State * tolua_S) +template < + class Ty1, + class Ty2, + bool (Ty1::*Func1)(const cBoundingBox &, cItemCallback &) +> +static int tolua_ForEachInBox(lua_State * tolua_S) +{ + // Check params: + cLuaState L(tolua_S); + if ( + !L.CheckParamUserType(1, "cWorld") || + !L.CheckParamUserType(2, "cBoundingBox") || + !L.CheckParamFunction(3) || + !L.CheckParamEnd(4) + ) + { + return 0; + } + + // Get the params: + Ty1 * Self = NULL; + cBoundingBox * Box = NULL; + L.GetStackValues(1, Self, Box); + ASSERT(Self != NULL); // We have verified the type at the top, so we should get valid objects here + ASSERT(Box != NULL); + + // Create a reference for the function: + cLuaState::cRef FnRef(L, 3); + + // Callback wrapper for the Lua function: + class cLuaCallback : public cItemCallback + { + public: + cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FuncRef) : + m_LuaState(a_LuaState), + m_FnRef(a_FuncRef) + {} + + private: + // cItemCallback overrides: + virtual bool Item(Ty2 * a_Item) override + { + bool res = false; + if (!m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, res)) + { + LOGWARNING("Failed to call Lua callback"); + m_LuaState.LogStackTrace(); + return true; // Abort enumeration + } + + return res; + } + cLuaState & m_LuaState; + cLuaState::cRef & m_FnRef; + } Callback(L, FnRef); + + bool bRetVal = (Self->*Func1)(*Box, Callback); + + FnRef.UnRef(); + + /* Push return value on stack */ + tolua_pushboolean(tolua_S, bRetVal); + return 1; +} + + + + + template < class Ty1, class Ty2, @@ -3327,6 +3396,7 @@ void ManualBindings::Bind(lua_State * tolua_S) 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, "ForEachEntityInBox", tolua_ForEachInBox< cWorld, cEntity, &cWorld::ForEachEntityInBox>); 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>); -- cgit v1.2.3 From 06c66a08cdbfbbac56d79a175bcc6142d690cc94 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 3 Sep 2014 23:05:03 +0200 Subject: LuaState: Fixed referenced function pushing. The references are no longer destroyed by the call. --- src/Bindings/LuaState.h | 8 ++++++++ src/Bindings/gen_LuaState_Call.lua | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h index fd506b10e..44f187701 100644 --- a/src/Bindings/LuaState.h +++ b/src/Bindings/LuaState.h @@ -338,6 +338,14 @@ protected: */ bool PushFunction(int a_FnRef); + /** Pushes a function that has been saved as a reference. + Returns true if successful. Logs a warning on failure + */ + bool PushFunction(const cRef & a_FnRef) + { + return PushFunction((int)a_FnRef); + } + /** Pushes a function that is stored in a referenced table by name Returns true if successful. Logs a warning on failure */ diff --git a/src/Bindings/gen_LuaState_Call.lua b/src/Bindings/gen_LuaState_Call.lua index 2d8630d12..7f62573c7 100644 --- a/src/Bindings/gen_LuaState_Call.lua +++ b/src/Bindings/gen_LuaState_Call.lua @@ -109,7 +109,7 @@ local function WriteOverload(f, a_NumParams, a_NumReturns) -- Write the function signature: f:write("bool Call(") - f:write("FnT a_Function") + f:write("const FnT & a_Function") for i = 1, a_NumParams do f:write(", ParamT", i, " a_Param", i) end -- cgit v1.2.3 From 014a55a15ac77d274538236228ec990be9269080 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 3 Sep 2014 23:05:22 +0200 Subject: LuaState: Fixed class value-getting off the stack. --- src/Bindings/LuaState.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp index 4ebb1e92f..ba2f3c5e0 100644 --- a/src/Bindings/LuaState.cpp +++ b/src/Bindings/LuaState.cpp @@ -862,9 +862,9 @@ void cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal) void cLuaState::GetStackValue(int a_StackPos, pBoundingBox & a_ReturnedVal) { tolua_Error err; - if (tolua_isusertable(m_LuaState, a_StackPos, "cBoundingBox", false, &err)) + if (tolua_isusertype(m_LuaState, a_StackPos, "cBoundingBox", false, &err)) { - a_ReturnedVal = (cBoundingBox *)lua_touserdata(m_LuaState, a_StackPos); + a_ReturnedVal = *((cBoundingBox **)lua_touserdata(m_LuaState, a_StackPos)); } } @@ -875,9 +875,9 @@ void cLuaState::GetStackValue(int a_StackPos, pBoundingBox & a_ReturnedVal) void cLuaState::GetStackValue(int a_StackPos, pWorld & a_ReturnedVal) { tolua_Error err; - if (tolua_isusertable(m_LuaState, a_StackPos, "cWorld", false, &err)) + if (tolua_isusertype(m_LuaState, a_StackPos, "cWorld", false, &err)) { - a_ReturnedVal = (cWorld *)lua_touserdata(m_LuaState, a_StackPos); + a_ReturnedVal = *((cWorld **)lua_touserdata(m_LuaState, a_StackPos)); } } -- cgit v1.2.3 From 7ab4c078b873433a9b353b742a9a39540dd5219b Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 4 Sep 2014 14:05:42 +0200 Subject: Fixed compilation after chunk Y removal. --- src/ChunkMap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp index 557434fbb..8c765c8c9 100644 --- a/src/ChunkMap.cpp +++ b/src/ChunkMap.cpp @@ -1789,7 +1789,7 @@ bool cChunkMap::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & { for (int x = MinChunkX; x <= MaxChunkX; x++) { - cChunkPtr Chunk = GetChunkNoGen(x, ZERO_CHUNK_Y, z); + cChunkPtr Chunk = GetChunkNoGen(x, z); if ((Chunk == NULL) || !Chunk->IsValid()) { continue; -- cgit v1.2.3