about summary refs log tree commit diff
path: root/src/game/server/gameworld.cpp
diff options
context:
space:
mode:
authoroy <Tom_Adams@web.de>2011-01-19 15:31:42 +0100
committeroy <Tom_Adams@web.de>2011-01-19 15:31:42 +0100
commit1359db54763739d65895d9fe48c13de95570bbe5 (patch)
tree6e7729259c39439cdf1af83fba8ce4bad77327ca /src/game/server/gameworld.cpp
parent68faba809c9c0be9c63a462f91d5dac3c540a8b6 (diff)
downloadzcatch-1359db54763739d65895d9fe48c13de95570bbe5.tar.gz
zcatch-1359db54763739d65895d9fe48c13de95570bbe5.zip
prevent that removing an entity aborts traversing the entity list in gameworld
Diffstat (limited to 'src/game/server/gameworld.cpp')
-rw-r--r--src/game/server/gameworld.cpp32
1 files changed, 26 insertions, 6 deletions
diff --git a/src/game/server/gameworld.cpp b/src/game/server/gameworld.cpp
index e2d08ed6..8fc9fec8 100644
--- a/src/game/server/gameworld.cpp
+++ b/src/game/server/gameworld.cpp
@@ -107,6 +107,10 @@ void CGameWorld::RemoveEntity(CEntity *pEnt)
 	if(pEnt->m_pNextTypeEntity)
 		pEnt->m_pNextTypeEntity->m_pPrevTypeEntity = pEnt->m_pPrevTypeEntity;
 
+	// keep list traversing valid
+	if(m_pNextTraverseEntity == pEnt)
+		m_pNextTraverseEntity = pEnt->m_pNextEntity;
+
 	pEnt->m_pNextEntity = 0;
 	pEnt->m_pPrevEntity = 0;
 	pEnt->m_pNextTypeEntity = 0;
@@ -116,15 +120,23 @@ void CGameWorld::RemoveEntity(CEntity *pEnt)
 //
 void CGameWorld::Snap(int SnappingClient)
 {
-	for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity)
+	for(CEntity *pEnt = m_pFirstEntity; pEnt; )
+	{
+		m_pNextTraverseEntity = pEnt->m_pNextEntity;
 		pEnt->Snap(SnappingClient);
+		pEnt = m_pNextTraverseEntity;
+	}
 }
 
 void CGameWorld::Reset()
 {
 	// reset all entities
-	for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity)
+	for(CEntity *pEnt = m_pFirstEntity; pEnt; )
+	{
+		m_pNextTraverseEntity = pEnt->m_pNextEntity;
 		pEnt->Reset();
+		pEnt = m_pNextTraverseEntity;
+	}
 	RemoveEntities();
 
 	GameServer()->m_pController->PostReset();
@@ -139,13 +151,13 @@ void CGameWorld::RemoveEntities()
 	CEntity *pEnt = m_pFirstEntity;
 	while(pEnt)
 	{
-		CEntity *pNext = pEnt->m_pNextEntity;
+		m_pNextTraverseEntity = pEnt->m_pNextEntity;
 		if(pEnt->m_MarkedForDestroy)
 		{
 			RemoveEntity(pEnt);
 			pEnt->Destroy();
 		}
-		pEnt = pNext;
+		pEnt = m_pNextTraverseEntity;
 	}
 }
 
@@ -159,11 +171,19 @@ void CGameWorld::Tick()
 		if(GameServer()->m_pController->IsForceBalanced())
 			GameServer()->SendChat(-1, CGameContext::CHAT_ALL, "Teams have been balanced");
 		// update all objects
-		for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity)
+		for(CEntity *pEnt = m_pFirstEntity; pEnt; )
+		{
+			m_pNextTraverseEntity = pEnt->m_pNextEntity;
 			pEnt->Tick();
+			pEnt = m_pNextTraverseEntity;
+		}
 		
-		for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity)
+		for(CEntity *pEnt = m_pFirstEntity; pEnt; )
+		{
+			m_pNextTraverseEntity = pEnt->m_pNextEntity;
 			pEnt->TickDefered();
+			pEnt = m_pNextTraverseEntity;
+		}
 	}
 
 	RemoveEntities();