fix: clear stale per-system chunk-sent flags on reconnect to restore terrain load speed

- Add SystemFlagClearForSystem (PlatformNetworkManagerInterface / GameNetworkManager)
- In PlayerList::placeNewPlayer, clear flags when no active player exists on the same system
- Prevent initial chunk transmission from being incorrectly skipped after disconnect/reconnect
This commit is contained in:
kuwacom 2026-03-03 04:43:21 +09:00
parent 66ffc689d1
commit 33080d195f
12 changed files with 92 additions and 3 deletions

View file

@ -1264,6 +1264,11 @@ bool CGameNetworkManager::SystemFlagGet(INetworkPlayer *pNetworkPlayer, int inde
return s_pPlatformNetworkManager->SystemFlagGet( pNetworkPlayer, index ); return s_pPlatformNetworkManager->SystemFlagGet( pNetworkPlayer, index );
} }
void CGameNetworkManager::SystemFlagClearForSystem(INetworkPlayer *pNetworkPlayer)
{
s_pPlatformNetworkManager->SystemFlagClearForSystem( pNetworkPlayer );
}
wstring CGameNetworkManager::GatherStats() wstring CGameNetworkManager::GatherStats()
{ {
return s_pPlatformNetworkManager->GatherStats(); return s_pPlatformNetworkManager->GatherStats();

View file

@ -133,6 +133,7 @@ public:
void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index); void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index);
bool SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index); bool SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index);
void SystemFlagClearForSystem(INetworkPlayer *pNetworkPlayer);
// Events // Events

View file

@ -101,6 +101,7 @@ private:
public: public:
virtual void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index) = 0; virtual void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index) = 0;
virtual bool SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index) = 0; virtual bool SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index) = 0;
virtual void SystemFlagClearForSystem(INetworkPlayer *pNetworkPlayer) {}
virtual wstring GatherStats() = 0; virtual wstring GatherStats() = 0;
virtual wstring GatherRTTStats() = 0; virtual wstring GatherRTTStats() = 0;

View file

@ -707,6 +707,19 @@ bool CPlatformNetworkManagerStub::SystemFlagGet(INetworkPlayer *pNetworkPlayer,
return false; return false;
} }
void CPlatformNetworkManagerStub::SystemFlagClearForSystem(INetworkPlayer *pNetworkPlayer)
{
if( pNetworkPlayer == NULL ) return;
for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
{
if( pNetworkPlayer->IsSameSystem(m_playerFlags[i]->m_pNetworkPlayer) )
{
memset(m_playerFlags[i]->flags, 0, m_playerFlags[i]->count / 8);
}
}
}
wstring CPlatformNetworkManagerStub::GatherStats() wstring CPlatformNetworkManagerStub::GatherStats()
{ {
return L""; return L"";

View file

@ -108,6 +108,7 @@ private:
public: public:
virtual void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index); virtual void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index);
virtual bool SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index); virtual bool SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index);
virtual void SystemFlagClearForSystem(INetworkPlayer *pNetworkPlayer);
// For telemetry // For telemetry
private: private:

View file

@ -1064,6 +1064,19 @@ bool CPlatformNetworkManagerSony::SystemFlagGet(INetworkPlayer *pNetworkPlayer,
return false; return false;
} }
void CPlatformNetworkManagerSony::SystemFlagClearForSystem(INetworkPlayer *pNetworkPlayer)
{
if( pNetworkPlayer == NULL ) return;
for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
{
if( pNetworkPlayer->IsSameSystem(m_playerFlags[i]->m_pNetworkPlayer) )
{
memset(m_playerFlags[i]->flags, 0, m_playerFlags[i]->count / 8);
}
}
}
wstring CPlatformNetworkManagerSony::GatherStats() wstring CPlatformNetworkManagerSony::GatherStats()
{ {
#if 0 #if 0

View file

@ -129,6 +129,7 @@ private:
public: public:
virtual void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index); virtual void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index);
virtual bool SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index); virtual bool SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index);
virtual void SystemFlagClearForSystem(INetworkPlayer *pNetworkPlayer);
// For telemetry // For telemetry
private: private:

View file

@ -744,6 +744,19 @@ bool CPlatformNetworkManagerDurango::SystemFlagGet(INetworkPlayer *pNetworkPlaye
return false; return false;
} }
void CPlatformNetworkManagerDurango::SystemFlagClearForSystem(INetworkPlayer *pNetworkPlayer)
{
if( pNetworkPlayer == NULL ) return;
for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
{
if( pNetworkPlayer->IsSameSystem(m_playerFlags[i]->m_pNetworkPlayer) )
{
memset(m_playerFlags[i]->flags, 0, m_playerFlags[i]->count / 8);
}
}
}
wstring CPlatformNetworkManagerDurango::GatherStats() wstring CPlatformNetworkManagerDurango::GatherStats()
{ {
return L""; return L"";

View file

@ -114,6 +114,7 @@ private:
public: public:
virtual void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index); virtual void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index);
virtual bool SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index); virtual bool SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index);
virtual void SystemFlagClearForSystem(INetworkPlayer *pNetworkPlayer);
// For telemetry // For telemetry
private: private:

View file

@ -86,6 +86,32 @@ void PlayerList::placeNewPlayer(Connection *connection, shared_ptr<ServerPlayer>
player->setPlayerGamePrivilege(Player::ePlayerGamePrivilege_HOST,1); player->setPlayerGamePrivilege(Player::ePlayerGamePrivilege_HOST,1);
} }
// A reconnect from the same machine can race with platform-level leave notifications.
// If this is the first active player we can currently see for this system, clear the per-system
// chunk-sent flags so initial terrain is always resent for this login.
if( networkPlayer != NULL )
{
bool hasActiveSameSystemPlayer = false;
for(AUTO_VAR(it, players.begin()); it < players.end(); ++it)
{
shared_ptr<ServerPlayer> existingPlayer = *it;
if( existingPlayer == NULL || existingPlayer->connection == NULL ) continue;
INetworkPlayer *existingNetworkPlayer = existingPlayer->connection->getNetworkPlayer();
if( existingNetworkPlayer == NULL ) continue;
if( networkPlayer->IsSameSystem(existingNetworkPlayer) )
{
hasActiveSameSystemPlayer = true;
break;
}
}
if( !hasActiveSameSystemPlayer )
{
g_NetworkManager.SystemFlagClearForSystem(networkPlayer);
}
}
#if defined(__PS3__) || defined(__ORBIS__) #if defined(__PS3__) || defined(__ORBIS__)
// PS3 networking library doesn't automatically assign PlayerUIDs to the network players for anything remote, so need to tell it what to set from the data in this packet now // PS3 networking library doesn't automatically assign PlayerUIDs to the network players for anything remote, so need to tell it what to set from the data in this packet now
if( !g_NetworkManager.IsLocalGame() ) if( !g_NetworkManager.IsLocalGame() )

View file

@ -1097,6 +1097,19 @@ bool CPlatformNetworkManagerXbox::SystemFlagGet(INetworkPlayer *pNetworkPlayer,
return false; return false;
} }
void CPlatformNetworkManagerXbox::SystemFlagClearForSystem(INetworkPlayer *pNetworkPlayer)
{
if( pNetworkPlayer == NULL ) return;
for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
{
if( pNetworkPlayer->IsSameSystem(m_playerFlags[i]->m_pNetworkPlayer) )
{
memset(m_playerFlags[i]->flags, 0, m_playerFlags[i]->count / 8);
}
}
}
wstring CPlatformNetworkManagerXbox::GatherStats() wstring CPlatformNetworkManagerXbox::GatherStats()
{ {
return L"Queue messages: " + _toString(((NetworkPlayerXbox *)GetHostPlayer())->GetQNetPlayer()->GetSendQueueSize( NULL, QNET_GETSENDQUEUESIZE_MESSAGES ) ) return L"Queue messages: " + _toString(((NetworkPlayerXbox *)GetHostPlayer())->GetQNetPlayer()->GetSendQueueSize( NULL, QNET_GETSENDQUEUESIZE_MESSAGES ) )

View file

@ -115,6 +115,7 @@ private:
public: public:
virtual void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index); virtual void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index);
virtual bool SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index); virtual bool SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index);
virtual void SystemFlagClearForSystem(INetworkPlayer *pNetworkPlayer);
// For telemetry // For telemetry
private: private: