diff options
Diffstat (limited to 'src/Chunk.cpp')
-rw-r--r-- | src/Chunk.cpp | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/src/Chunk.cpp b/src/Chunk.cpp index da13e3b10..f5d447c45 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -603,6 +603,7 @@ void cChunk::SpawnMobs(cMobSpawner & a_MobSpawner) void cChunk::Tick(std::chrono::milliseconds a_Dt) { + m_IsInTick = true; BroadcastPendingBlockChanges(); CheckBlocks(); @@ -637,7 +638,7 @@ void cChunk::Tick(std::chrono::milliseconds a_Dt) else if ((*itr)->IsWorldTravellingFrom(m_World)) { // Remove all entities that are travelling to another world - LOGD("Removing entity from [%d, %d] that's travelling between worlds.", m_PosX, m_PosZ); + LOGD("Removing entity from [%d, %d] that's travelling between worlds. (Scheduled)", m_PosX, m_PosZ); MarkDirty(); (*itr)->SetWorldTravellingFrom(nullptr); itr = m_Entities.erase(itr); @@ -659,6 +660,7 @@ void cChunk::Tick(std::chrono::milliseconds a_Dt) } // for itr - m_Entitites[] ApplyWeatherToTop(); + m_IsInTick = false; } @@ -1910,6 +1912,31 @@ void cChunk::RemoveEntity(cEntity * a_Entity) +void cChunk::SafeRemoveEntity(cEntity * a_Entity) +{ + if (!m_IsInTick) + { + LOGD("Removing entity from [%d, %d] that's travelling between worlds. (immediate)", m_PosX, m_PosZ); + // If we're not in a tick, just remove it. + m_Entities.remove(a_Entity); + } + else + { + // If we are in a tick, we don't want to invalidate the iterator, so we schedule the removal. Removal will be done in cChunk::tick() + a_Entity->SetWorldTravellingFrom(GetWorld()); + } + + // Mark as dirty if it was a server-generated entity: + if (!a_Entity->IsPlayer()) + { + MarkDirty(); + } +} + + + + + bool cChunk::HasEntity(UInt32 a_EntityID) { for (cEntityList::const_iterator itr = m_Entities.begin(), end = m_Entities.end(); itr != end; ++itr) @@ -1932,6 +1959,10 @@ bool cChunk::ForEachEntity(cEntityCallback & a_Callback) for (cEntityList::iterator itr = m_Entities.begin(), itr2 = itr; itr != m_Entities.end(); itr = itr2) { ++itr2; + if ((*itr)->IsDestroyed()) + { + continue; + } if (a_Callback.Item(*itr)) { return false; @@ -1950,6 +1981,10 @@ bool cChunk::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_ for (cEntityList::iterator itr = m_Entities.begin(), itr2 = itr; itr != m_Entities.end(); itr = itr2) { ++itr2; + if ((*itr)->IsDestroyed()) + { + continue; + } cBoundingBox EntBox((*itr)->GetPosition(), (*itr)->GetWidth() / 2, (*itr)->GetHeight()); if (!EntBox.DoesIntersect(a_Box)) { @@ -1973,7 +2008,7 @@ bool cChunk::DoWithEntityByID(UInt32 a_EntityID, cEntityCallback & a_Callback, b // The entity list is locked by the parent chunkmap's CS for (cEntityList::iterator itr = m_Entities.begin(), end = m_Entities.end(); itr != end; ++itr) { - if ((*itr)->GetUniqueID() == a_EntityID) + if (((*itr)->GetUniqueID() == a_EntityID) && (!(*itr)->IsDestroyed())) { a_CallbackResult = a_Callback.Item(*itr); return true; |