Recreate all entities when restarting round

When restarting a round (i.e. with the `restart` command, with the `sv_warmup` option, and after a round ends) some entities where permanently destroyed and others were kept around.

This is changed so all entities are destroyed and then recreated, so rounds can be properly restarted.

Closes #6128.
This commit is contained in:
Robert Müller 2022-12-13 00:06:14 +01:00
parent 13b181c03a
commit 1fffd9f8c6
9 changed files with 38 additions and 25 deletions

View file

@ -40,6 +40,11 @@ void CDoor::ResetCollision()
}
}
void CDoor::Reset()
{
m_MarkedForDestroy = true;
}
void CDoor::Snap(int SnappingClient)
{
if(NetworkClipped(SnappingClient, m_Pos) && NetworkClipped(SnappingClient, m_To))

View file

@ -17,6 +17,7 @@ public:
CDoor(CGameWorld *pGameWorld, vec2 Pos, float Rotation, int Length,
int Number);
void Reset() override;
void Snap(int SnappingClient) override;
};

View file

@ -21,13 +21,12 @@ CPickup::CPickup(CGameWorld *pGameWorld, int Type, int SubType, int Layer, int N
m_Layer = Layer;
m_Number = Number;
Reset();
GameWorld()->InsertEntity(this);
}
void CPickup::Reset()
{
m_MarkedForDestroy = true;
}
void CPickup::Tick()

View file

@ -51,8 +51,7 @@ CProjectile::CProjectile(
void CProjectile::Reset()
{
if(m_LifeSpan > -2)
m_MarkedForDestroy = true;
m_MarkedForDestroy = true;
}
vec2 CProjectile::GetPos(float Time)

View file

@ -3432,11 +3432,29 @@ void CGameContext::OnInit()
}
// create all entities from the game layer
CreateAllEntities(true);
if(GIT_SHORTREV_HASH)
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "git-revision", GIT_SHORTREV_HASH);
#ifdef CONF_DEBUG
if(g_Config.m_DbgDummies)
{
for(int i = 0; i < g_Config.m_DbgDummies; i++)
{
OnClientConnected(MAX_CLIENTS - i - 1, 0);
}
}
#endif
}
void CGameContext::CreateAllEntities(bool Initial)
{
CMapItemLayerTilemap *pTileMap = m_Layers.GameLayer();
CTile *pTiles = (CTile *)Kernel()->RequestInterface<IMap>()->GetData(pTileMap->m_Data);
CTile *pFront = 0;
CSwitchTile *pSwitch = 0;
CTile *pFront = nullptr;
CSwitchTile *pSwitch = nullptr;
if(m_Layers.FrontLayer())
pFront = (CTile *)Kernel()->RequestInterface<IMap>()->GetData(m_Layers.FrontLayer()->m_Front);
if(m_Layers.SwitchLayer())
@ -3477,7 +3495,7 @@ void CGameContext::OnInit()
if(Index >= ENTITY_OFFSET)
{
vec2 Pos(x * 32.0f + 16.0f, y * 32.0f + 16.0f);
m_pController->OnEntity(Index - ENTITY_OFFSET, Pos, LAYER_GAME, pTiles[y * pTileMap->m_Width + x].m_Flags);
m_pController->OnEntity(Index - ENTITY_OFFSET, Pos, LAYER_GAME, pTiles[y * pTileMap->m_Width + x].m_Flags, Initial);
}
if(pFront)
@ -3511,7 +3529,7 @@ void CGameContext::OnInit()
if(Index >= ENTITY_OFFSET)
{
vec2 Pos(x * 32.0f + 16.0f, y * 32.0f + 16.0f);
m_pController->OnEntity(Index - ENTITY_OFFSET, Pos, LAYER_FRONT, pFront[y * pTileMap->m_Width + x].m_Flags);
m_pController->OnEntity(Index - ENTITY_OFFSET, Pos, LAYER_FRONT, pFront[y * pTileMap->m_Width + x].m_Flags, Initial);
}
}
if(pSwitch)
@ -3522,24 +3540,11 @@ void CGameContext::OnInit()
if(Index >= ENTITY_OFFSET)
{
vec2 Pos(x * 32.0f + 16.0f, y * 32.0f + 16.0f);
m_pController->OnEntity(Index - ENTITY_OFFSET, Pos, LAYER_SWITCH, pSwitch[y * pTileMap->m_Width + x].m_Flags, pSwitch[y * pTileMap->m_Width + x].m_Number);
m_pController->OnEntity(Index - ENTITY_OFFSET, Pos, LAYER_SWITCH, pSwitch[y * pTileMap->m_Width + x].m_Flags, Initial, pSwitch[y * pTileMap->m_Width + x].m_Number);
}
}
}
}
if(GIT_SHORTREV_HASH)
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "git-revision", GIT_SHORTREV_HASH);
#ifdef CONF_DEBUG
if(g_Config.m_DbgDummies)
{
for(int i = 0; i < g_Config.m_DbgDummies; i++)
{
OnClientConnected(MAX_CLIENTS - i - 1, 0);
}
}
#endif
}
void CGameContext::DeleteTempfile()

View file

@ -187,6 +187,8 @@ public:
char m_aaZoneEnterMsg[NUM_TUNEZONES][256]; // 0 is used for switching from or to area without tunings
char m_aaZoneLeaveMsg[NUM_TUNEZONES][256];
void CreateAllEntities(bool Initial);
char m_aDeleteTempfile[128];
void DeleteTempfile();

View file

@ -173,7 +173,7 @@ bool IGameController::CanSpawn(int Team, vec2 *pOutPos, int DDTeam)
return Eval.m_Got;
}
bool IGameController::OnEntity(int Index, vec2 Pos, int Layer, int Flags, int Number)
bool IGameController::OnEntity(int Index, vec2 Pos, int Layer, int Flags, bool Initial, int Number)
{
if(Index < 0)
return false;
@ -190,7 +190,7 @@ bool IGameController::OnEntity(int Index, vec2 Pos, int Layer, int Flags, int Nu
aSides[6] = GameServer()->Collision()->Entity(x - 1, y, Layer);
aSides[7] = GameServer()->Collision()->Entity(x - 1, y + 1, Layer);
if(Index >= ENTITY_SPAWN && Index <= ENTITY_SPAWN_BLUE)
if(Index >= ENTITY_SPAWN && Index <= ENTITY_SPAWN_BLUE && Initial)
{
const int Type = Index - ENTITY_SPAWN;
m_avSpawnPoints[Type].push_back(Pos);

View file

@ -104,7 +104,7 @@ public:
Returns:
bool?
*/
virtual bool OnEntity(int Index, vec2 Pos, int Layer, int Flags, int Number = 0);
virtual bool OnEntity(int Index, vec2 Pos, int Layer, int Flags, bool Initial, int Number = 0);
virtual void OnPlayerConnect(class CPlayer *pPlayer);
virtual void OnPlayerDisconnect(class CPlayer *pPlayer, const char *pReason);

View file

@ -146,6 +146,8 @@ void CGameWorld::Reset()
RemoveEntities();
m_ResetRequested = false;
GameServer()->CreateAllEntities(false);
}
void CGameWorld::RemoveEntities()