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 );
}
void CGameNetworkManager::SystemFlagClearForSystem(INetworkPlayer *pNetworkPlayer)
{
s_pPlatformNetworkManager->SystemFlagClearForSystem( pNetworkPlayer );
}
wstring CGameNetworkManager::GatherStats()
{
return s_pPlatformNetworkManager->GatherStats();

View file

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

View file

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

View file

@ -707,6 +707,19 @@ bool CPlatformNetworkManagerStub::SystemFlagGet(INetworkPlayer *pNetworkPlayer,
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()
{
return L"";

View file

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

View file

@ -1064,6 +1064,19 @@ bool CPlatformNetworkManagerSony::SystemFlagGet(INetworkPlayer *pNetworkPlayer,
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()
{
#if 0

View file

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

View file

@ -744,6 +744,19 @@ bool CPlatformNetworkManagerDurango::SystemFlagGet(INetworkPlayer *pNetworkPlaye
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()
{
return L"";
@ -937,4 +950,4 @@ bool CPlatformNetworkManagerDurango::IsReadyToPlayOrIdle()
bool CPlatformNetworkManagerDurango::IsSessionJoinable()
{
return m_hostGameSessionIsJoinable;
}
}

View file

@ -114,6 +114,7 @@ private:
public:
virtual void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index);
virtual bool SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index);
virtual void SystemFlagClearForSystem(INetworkPlayer *pNetworkPlayer);
// For telemetry
private:
@ -165,4 +166,4 @@ public:
virtual void HandleDisconnect(bool bLostRoomOnly);
virtual void HandleInviteReceived(int playerIndex, DQRNetworkManager::SessionInfo *pInviteInfo);
virtual bool IsSessionJoinable();
};
};

View file

@ -86,6 +86,32 @@ void PlayerList::placeNewPlayer(Connection *connection, shared_ptr<ServerPlayer>
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__)
// 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() )

View file

@ -1097,6 +1097,19 @@ bool CPlatformNetworkManagerXbox::SystemFlagGet(INetworkPlayer *pNetworkPlayer,
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()
{
return L"Queue messages: " + _toString(((NetworkPlayerXbox *)GetHostPlayer())->GetQNetPlayer()->GetSendQueueSize( NULL, QNET_GETSENDQUEUESIZE_MESSAGES ) )

View file

@ -115,6 +115,7 @@ private:
public:
virtual void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index);
virtual bool SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index);
virtual void SystemFlagClearForSystem(INetworkPlayer *pNetworkPlayer);
// For telemetry
private:
@ -181,4 +182,4 @@ public:
VOID NotifyGameInvite( __in DWORD dwUserIndex, __in const INVITE_INFO * pInviteInfo );
VOID NotifyContextChanged( __in const XUSER_CONTEXT * pContext);
VOID NotifyPropertyChanged( __in const XUSER_PROPERTY * pProperty);
};
};