summaryrefslogtreecommitdiffstats
path: root/src/Chunk.cpp
diff options
context:
space:
mode:
authorLogicParrot <LogicParrot@users.noreply.github.com>2016-02-19 09:58:35 +0100
committerLogicParrot <LogicParrot@users.noreply.github.com>2016-02-19 09:58:35 +0100
commita776337e5ecc4ba9fe54a46069f3423fbad56ec4 (patch)
tree637e5302c5c5affc5f3c52d4c195cba5607aac30 /src/Chunk.cpp
parentMerge pull request #3020 from cuberite/ice_block (diff)
parentProper entity destruction in non-ticking chunks (diff)
downloadcuberite-a776337e5ecc4ba9fe54a46069f3423fbad56ec4.tar
cuberite-a776337e5ecc4ba9fe54a46069f3423fbad56ec4.tar.gz
cuberite-a776337e5ecc4ba9fe54a46069f3423fbad56ec4.tar.bz2
cuberite-a776337e5ecc4ba9fe54a46069f3423fbad56ec4.tar.lz
cuberite-a776337e5ecc4ba9fe54a46069f3423fbad56ec4.tar.xz
cuberite-a776337e5ecc4ba9fe54a46069f3423fbad56ec4.tar.zst
cuberite-a776337e5ecc4ba9fe54a46069f3423fbad56ec4.zip
Diffstat (limited to 'src/Chunk.cpp')
-rw-r--r--src/Chunk.cpp82
1 files changed, 34 insertions, 48 deletions
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index f5d447c45..237bf62c0 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -139,7 +139,8 @@ cChunk::~cChunk()
{
if (!(*itr)->IsPlayer())
{
- (*itr)->Destroy(false);
+ // Scheduling a normal destruction is neither possible (Since this chunk will be gone till the schedule occurs) nor necessary.
+ (*itr)->DestroyNoScheduling(false); // No point in broadcasting in an unloading chunk. Chunks unload when no one is nearby.
delete *itr;
}
}
@@ -621,37 +622,44 @@ void cChunk::Tick(std::chrono::milliseconds a_Dt)
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
{
+ // Do not tick mobs that are detached from the world. They're either scheduled for teleportation or for removal.
+ if (!(*itr)->IsTicking())
+ {
+ ++itr;
+ 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);
}
- if ((*itr)->IsDestroyed()) // Remove all entities that were scheduled for removal:
+ // Do not move mobs that are detached from the world to neighbors. They're either scheduled for teleportation or for removal.
+ if (!(*itr)->IsTicking())
{
- LOGD("Destroying entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass());
- MarkDirty();
- cEntity * ToDelete = *itr;
- itr = m_Entities.erase(itr);
- delete ToDelete;
- }
- 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. (Scheduled)", m_PosX, m_PosZ);
- MarkDirty();
- (*itr)->SetWorldTravellingFrom(nullptr);
- itr = m_Entities.erase(itr);
+ ++itr;
+ continue;
}
- else if (
- ((*itr)->GetChunkX() != m_PosX) ||
- ((*itr)->GetChunkZ() != m_PosZ)
+
+ // Because the schedulded destruction is going to look for them in this chunk. See cEntity::destroy.
+ if ((((*itr)->GetChunkX() != m_PosX) ||
+ ((*itr)->GetChunkZ() != m_PosZ))
)
{
+ // This block is very similar to RemoveEntity, except it uses an iterator to avoid scanning the whole m_Entities
// The entity moved out of the chunk, move it to the neighbor
- MarkDirty();
+
+ (*itr)->SetParentChunk(nullptr);
MoveEntityToNewChunk(*itr);
itr = m_Entities.erase(itr);
+ // Mark as dirty if it was a server-generated entity:
+ if (!(*itr)->IsPlayer())
+ {
+ MarkDirty();
+ }
}
else
{
@@ -1891,6 +1899,8 @@ void cChunk::AddEntity(cEntity * a_Entity)
ASSERT(std::find(m_Entities.begin(), m_Entities.end(), a_Entity) == m_Entities.end()); // Not there already
m_Entities.push_back(a_Entity);
+ ASSERT(a_Entity->GetParentChunk() == nullptr);
+ a_Entity->SetParentChunk(this);
}
@@ -1899,33 +1909,9 @@ void cChunk::AddEntity(cEntity * a_Entity)
void cChunk::RemoveEntity(cEntity * a_Entity)
{
+ ASSERT(a_Entity->GetParentChunk() == this);
+ a_Entity->SetParentChunk(nullptr);
m_Entities.remove(a_Entity);
-
- // Mark as dirty if it was a server-generated entity:
- if (!a_Entity->IsPlayer())
- {
- MarkDirty();
- }
-}
-
-
-
-
-
-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())
{
@@ -1959,7 +1945,7 @@ 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())
+ if (!(*itr)->IsTicking())
{
continue;
}
@@ -1981,7 +1967,7 @@ 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())
+ if (!(*itr)->IsTicking())
{
continue;
}
@@ -2008,7 +1994,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) && (!(*itr)->IsDestroyed()))
+ if (((*itr)->GetUniqueID() == a_EntityID) && ((*itr)->IsTicking()))
{
a_CallbackResult = a_Callback.Item(*itr);
return true;