Fixed invalid iterators
This commit is contained in:
parent
1296c5dce7
commit
6e681269d9
@ -71,7 +71,6 @@ cChunk::cChunk(
|
|||||||
m_IsDirty(false),
|
m_IsDirty(false),
|
||||||
m_IsSaving(false),
|
m_IsSaving(false),
|
||||||
m_HasLoadFailed(false),
|
m_HasLoadFailed(false),
|
||||||
m_EntityTickIteratorData(std::make_pair(false, m_Entities.end())),
|
|
||||||
m_StayCount(0),
|
m_StayCount(0),
|
||||||
m_PosX(a_ChunkX),
|
m_PosX(a_ChunkX),
|
||||||
m_PosY(a_ChunkY),
|
m_PosY(a_ChunkY),
|
||||||
@ -577,44 +576,39 @@ void cChunk::Tick(float a_Dt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Tick all entities in this chunk (except mobs):
|
// Tick all entities in this chunk (except mobs):
|
||||||
m_EntityTickIteratorData.first = true;
|
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
|
||||||
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
|
|
||||||
{
|
{
|
||||||
// Mobs are ticked inside cWorld::TickMobs() (as we don't have to tick them if they are far away from players)
|
// Mobs are ticked inside cWorld::TickMobs() (as we don't have to tick them if they are far away from players)
|
||||||
// Don't tick things queued to be removed
|
// Don't tick things queued to be removed
|
||||||
if (!((*itr)->IsMob()))
|
if (!((*itr)->IsMob()))
|
||||||
{
|
{
|
||||||
m_EntityTickIteratorData.second = itr;
|
|
||||||
(*itr)->Tick(a_Dt, *this);
|
(*itr)->Tick(a_Dt, *this);
|
||||||
|
|
||||||
if (itr != m_EntityTickIteratorData.second)
|
|
||||||
{
|
|
||||||
itr = m_EntityTickIteratorData.second;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
++itr;
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
++itr;
|
|
||||||
} // for itr - m_Entitites[]
|
} // for itr - m_Entitites[]
|
||||||
m_EntityTickIteratorData.first = false;
|
|
||||||
|
|
||||||
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
|
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
|
||||||
{
|
{
|
||||||
if ((*itr)->IsDestroyed()) // Remove all entities that were scheduled for removal:
|
if ((*itr)->IsDestroyed()) // Remove all entities that were scheduled for removal:
|
||||||
{
|
{
|
||||||
LOGD("Destroying entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass());
|
LOGD("Destroying entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass());
|
||||||
|
MarkDirty();
|
||||||
cEntity * ToDelete = *itr;
|
cEntity * ToDelete = *itr;
|
||||||
itr = m_Entities.erase(itr);
|
itr = m_Entities.erase(itr);
|
||||||
delete ToDelete;
|
delete ToDelete;
|
||||||
}
|
}
|
||||||
|
else if ((*itr)->IsTravellingThroughPortal())
|
||||||
|
{
|
||||||
|
MarkDirty();
|
||||||
|
(*itr)->SetIsTravellingThroughPortal(false);
|
||||||
|
itr = m_Entities.erase(itr);
|
||||||
|
}
|
||||||
else if ( // If any entity moved out of the chunk, move it to the neighbor:
|
else if ( // If any entity moved out of the chunk, move it to the neighbor:
|
||||||
((*itr)->GetChunkX() != m_PosX) ||
|
((*itr)->GetChunkX() != m_PosX) ||
|
||||||
((*itr)->GetChunkZ() != m_PosZ)
|
((*itr)->GetChunkZ() != m_PosZ)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
MarkDirty();
|
||||||
MoveEntityToNewChunk(*itr);
|
MoveEntityToNewChunk(*itr);
|
||||||
itr = m_Entities.erase(itr);
|
itr = m_Entities.erase(itr);
|
||||||
}
|
}
|
||||||
@ -1874,14 +1868,7 @@ void cChunk::AddEntity(cEntity * a_Entity)
|
|||||||
|
|
||||||
void cChunk::RemoveEntity(cEntity * a_Entity)
|
void cChunk::RemoveEntity(cEntity * a_Entity)
|
||||||
{
|
{
|
||||||
if (m_EntityTickIteratorData.first)
|
m_Entities.remove(a_Entity);
|
||||||
{
|
|
||||||
m_EntityTickIteratorData.second = m_Entities.erase(m_EntityTickIteratorData.second);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_Entities.remove(a_Entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark as dirty if it was a server-generated entity:
|
// Mark as dirty if it was a server-generated entity:
|
||||||
if (!a_Entity->IsPlayer())
|
if (!a_Entity->IsPlayer())
|
||||||
|
@ -425,7 +425,6 @@ private:
|
|||||||
// A critical section is not needed, because all chunk access is protected by its parent ChunkMap's csLayers
|
// A critical section is not needed, because all chunk access is protected by its parent ChunkMap's csLayers
|
||||||
cClientHandleList m_LoadedByClient;
|
cClientHandleList m_LoadedByClient;
|
||||||
cEntityList m_Entities;
|
cEntityList m_Entities;
|
||||||
std::pair<bool, cEntityList::iterator> m_EntityTickIteratorData;
|
|
||||||
cBlockEntityList m_BlockEntities;
|
cBlockEntityList m_BlockEntities;
|
||||||
|
|
||||||
/** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */
|
/** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */
|
||||||
|
@ -57,6 +57,7 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d
|
|||||||
, m_Width(a_Width)
|
, m_Width(a_Width)
|
||||||
, m_Height(a_Height)
|
, m_Height(a_Height)
|
||||||
, m_InvulnerableTicks(0)
|
, m_InvulnerableTicks(0)
|
||||||
|
, m_IsTravellingThroughPortal(false)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSCount);
|
cCSLock Lock(m_CSCount);
|
||||||
m_EntityCount++;
|
m_EntityCount++;
|
||||||
@ -1183,7 +1184,7 @@ bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove all links to the old world
|
// Remove all links to the old world
|
||||||
GetWorld()->RemoveEntity(this);
|
SetIsTravellingThroughPortal(true); // cChunk handles entity removal
|
||||||
GetWorld()->BroadcastDestroyEntity(*this);
|
GetWorld()->BroadcastDestroyEntity(*this);
|
||||||
|
|
||||||
// Queue add to new world
|
// Queue add to new world
|
||||||
|
@ -374,6 +374,12 @@ public:
|
|||||||
virtual bool MoveToWorld(const AString & a_WorldName, cWorld * a_World = NULL, bool a_ShouldSendRespawn = true);
|
virtual bool MoveToWorld(const AString & a_WorldName, cWorld * a_World = NULL, bool a_ShouldSendRespawn = true);
|
||||||
|
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
|
/** Returns if the entity is travelling through a portal. Set to true by MoveToWorld and to false when the entity is removed by the old chunk */
|
||||||
|
bool IsTravellingThroughPortal(void) const { return m_IsTravellingThroughPortal; }
|
||||||
|
|
||||||
|
/** Sets if the entity has begun travelling through a portal or not */
|
||||||
|
void SetIsTravellingThroughPortal(bool a_Flag) { m_IsTravellingThroughPortal = a_Flag; }
|
||||||
|
|
||||||
/// Updates clients of changes in the entity.
|
/// Updates clients of changes in the entity.
|
||||||
virtual void BroadcastMovementUpdate(const cClientHandle * a_Exclude = NULL);
|
virtual void BroadcastMovementUpdate(const cClientHandle * a_Exclude = NULL);
|
||||||
@ -470,6 +476,9 @@ protected:
|
|||||||
/** True when entity is initialised (Initialize()) and false when destroyed pending deletion (Destroy()) */
|
/** True when entity is initialised (Initialize()) and false when destroyed pending deletion (Destroy()) */
|
||||||
bool m_IsInitialized;
|
bool m_IsInitialized;
|
||||||
|
|
||||||
|
/** True when entity is being moved across worlds, false anytime else */
|
||||||
|
bool m_IsTravellingThroughPortal;
|
||||||
|
|
||||||
eEntityType m_EntityType;
|
eEntityType m_EntityType;
|
||||||
|
|
||||||
cWorld * m_World;
|
cWorld * m_World;
|
||||||
@ -492,7 +501,6 @@ protected:
|
|||||||
/// Time, in ticks, since the last damage dealt by the void. Reset to zero when moving out of the void.
|
/// Time, in ticks, since the last damage dealt by the void. Reset to zero when moving out of the void.
|
||||||
int m_TicksSinceLastVoidDamage;
|
int m_TicksSinceLastVoidDamage;
|
||||||
|
|
||||||
|
|
||||||
virtual void Destroyed(void) {} // Called after the entity has been destroyed
|
virtual void Destroyed(void) {} // Called after the entity has been destroyed
|
||||||
|
|
||||||
/** Called in each tick to handle air-related processing i.e. drowning */
|
/** Called in each tick to handle air-related processing i.e. drowning */
|
||||||
|
@ -1600,6 +1600,7 @@ bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove player from the old world
|
// Remove player from the old world
|
||||||
|
SetIsTravellingThroughPortal(true); // cChunk handles entity removal
|
||||||
m_World->RemovePlayer(this);
|
m_World->RemovePlayer(this);
|
||||||
|
|
||||||
// Queue adding player to the new world, including all the necessary adjustments to the object
|
// Queue adding player to the new world, including all the necessary adjustments to the object
|
||||||
|
@ -2417,7 +2417,10 @@ void cWorld::AddPlayer(cPlayer * a_Player)
|
|||||||
|
|
||||||
void cWorld::RemovePlayer(cPlayer * a_Player)
|
void cWorld::RemovePlayer(cPlayer * a_Player)
|
||||||
{
|
{
|
||||||
m_ChunkMap->RemoveEntity(a_Player);
|
if (!a_Player->IsTravellingThroughPortal())
|
||||||
|
{
|
||||||
|
m_ChunkMap->RemoveEntity(a_Player);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSPlayersToAdd);
|
cCSLock Lock(m_CSPlayersToAdd);
|
||||||
m_PlayersToAdd.remove(a_Player);
|
m_PlayersToAdd.remove(a_Player);
|
||||||
@ -2919,15 +2922,6 @@ bool cWorld::HasEntity(int a_UniqueID)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cWorld::RemoveEntity(cEntity * a_Entity)
|
|
||||||
{
|
|
||||||
m_ChunkMap->RemoveEntity(a_Entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
unsigned int cWorld::GetNumPlayers(void)
|
unsigned int cWorld::GetNumPlayers(void)
|
||||||
{
|
{
|
||||||
|
@ -313,9 +313,6 @@ public:
|
|||||||
|
|
||||||
bool HasEntity(int a_UniqueID);
|
bool HasEntity(int a_UniqueID);
|
||||||
|
|
||||||
/** Removes the entity, the entity ptr ownership is assumed taken by the caller */
|
|
||||||
void RemoveEntity(cEntity * a_Entity);
|
|
||||||
|
|
||||||
/** Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true */
|
/** Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true */
|
||||||
bool ForEachEntity(cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
|
bool ForEachEntity(cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user