diff options
Diffstat (limited to '')
-rw-r--r-- | src/Chunk.cpp | 50 | ||||
-rw-r--r-- | src/World.cpp | 46 |
2 files changed, 40 insertions, 56 deletions
diff --git a/src/Chunk.cpp b/src/Chunk.cpp index bc0de0516..837e169c2 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -40,6 +40,7 @@ #include "SetChunkData.h" #include "BoundingBox.h" #include "Blocks/ChunkInterface.h" +#include "Mobs/Wolf.h" #include "json/json.h" @@ -641,13 +642,11 @@ void cChunk::Tick(std::chrono::milliseconds a_Dt) continue; } - 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); - } + // 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); // 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. @@ -1853,11 +1852,11 @@ bool cChunk::AddClient(cClientHandle * a_Client) void cChunk::RemoveClient(cClientHandle * a_Client) { - auto itr = std::remove(m_LoadedByClient.begin(), m_LoadedByClient.end(), a_Client); + auto ClientItr = std::remove(m_LoadedByClient.begin(), m_LoadedByClient.end(), a_Client); // We should always remove at most one client. - ASSERT(std::distance(itr, m_LoadedByClient.end()) <= 1); + ASSERT(std::distance(ClientItr, m_LoadedByClient.end()) <= 1); // Note: itr can equal m_LoadedByClient.end() - m_LoadedByClient.erase(itr, m_LoadedByClient.end()); + m_LoadedByClient.erase(ClientItr, m_LoadedByClient.end()); if (!a_Client->IsDestroyed()) { @@ -1874,6 +1873,37 @@ 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 d8b77647a..dcf02f02a 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1131,52 +1131,6 @@ 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); } |