diff options
-rw-r--r-- | src/Chunk.cpp | 50 | ||||
-rw-r--r-- | src/World.cpp | 46 |
2 files changed, 56 insertions, 40 deletions
diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 837e169c2..bc0de0516 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -40,7 +40,6 @@ #include "SetChunkData.h" #include "BoundingBox.h" #include "Blocks/ChunkInterface.h" -#include "Mobs/Wolf.h" #include "json/json.h" @@ -642,11 +641,13 @@ void cChunk::Tick(std::chrono::milliseconds a_Dt) continue; } - // Tick all entities in this chunk - including mobs. - // In the past Cuberite ticked mobs in cWorld. This is no longer the case. - ASSERT((*itr)->GetParentChunk() == this); - (*itr)->Tick(a_Dt, *this); - ASSERT((*itr)->GetParentChunk() == this); + if (!((*itr)->IsMob())) // Mobs are ticked inside cWorld::TickMobs() (as we don't have to tick them if they are far away from players) + { + // Tick all entities in this chunk (except mobs): + ASSERT((*itr)->GetParentChunk() == this); + (*itr)->Tick(a_Dt, *this); + ASSERT((*itr)->GetParentChunk() == this); + } // Do not move mobs that are detached from the world to neighbors. They're either scheduled for teleportation or for removal. // Because the schedulded destruction is going to look for them in this chunk. See cEntity::destroy. @@ -1852,11 +1853,11 @@ bool cChunk::AddClient(cClientHandle * a_Client) void cChunk::RemoveClient(cClientHandle * a_Client) { - auto ClientItr = std::remove(m_LoadedByClient.begin(), m_LoadedByClient.end(), a_Client); + auto itr = std::remove(m_LoadedByClient.begin(), m_LoadedByClient.end(), a_Client); // We should always remove at most one client. - ASSERT(std::distance(ClientItr, m_LoadedByClient.end()) <= 1); + ASSERT(std::distance(itr, m_LoadedByClient.end()) <= 1); // Note: itr can equal m_LoadedByClient.end() - m_LoadedByClient.erase(ClientItr, m_LoadedByClient.end()); + m_LoadedByClient.erase(itr, m_LoadedByClient.end()); if (!a_Client->IsDestroyed()) { @@ -1873,37 +1874,6 @@ void cChunk::RemoveClient(cClientHandle * a_Client) } } - // All clients were removed. No one sees this chunk any more. - // Delete all hostiles inside it. - if (!HasAnyClients()) - { - for (auto Entity : m_Entities) - { - if (Entity->IsTicking() && Entity->IsMob()) - { - auto Monster = static_cast<cMonster *>(Entity); - if ( - (Monster->GetMobFamily() == cMonster::eFamily::mfHostile) && - (Monster->GetCustomName().empty()) // Monsters that have name tags are never removed - ) - { - // Non-hostile wolves should not be removed when player is too far - if (Monster->GetMobType() != eMonsterType::mtWolf) - { - Monster->Destroy(true); - } - else - { - auto Wolf = static_cast<cWolf *>(Monster); - if (Wolf->IsAngry()) - { - Monster->Destroy(true); - } - } - } - } - } - } return; } diff --git a/src/World.cpp b/src/World.cpp index dcf02f02a..d8b77647a 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1131,6 +1131,52 @@ void cWorld::TickMobs(std::chrono::milliseconds a_Dt) } } // for i - AllFamilies[] } // if (Spawning enabled) + + class cCallback : public cEntityCallback + { + virtual bool Item(cEntity * a_Entity) override + { + if (!a_Entity->IsMob()) + { + return false; + } + if (!a_Entity->IsTicking()) + { + return false; + } + + auto Monster = static_cast<cMonster *>(a_Entity); + ASSERT(Monster->GetParentChunk() != nullptr); // A ticking entity must have a valid parent chunk + + // Tick close mobs + if (Monster->GetParentChunk()->HasAnyClients()) + { + Monster->Tick(m_Dt, *(a_Entity->GetParentChunk())); + } + // Destroy far hostile mobs + else if ((Monster->GetMobFamily() == cMonster::eFamily::mfHostile)) + { + if (Monster->GetMobType() != eMonsterType::mtWolf) + { + Monster->Destroy(true); + } + else + { + auto Wolf = static_cast<cWolf *>(Monster); + if (Wolf->IsAngry()) + { + Monster->Destroy(true); + } + } + } + return false; + } + public: + std::chrono::milliseconds m_Dt; + } Callback; + + Callback.m_Dt = a_Dt; + ForEachEntity(Callback); } |