summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Chunk.cpp50
-rw-r--r--src/World.cpp46
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);
}