mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-08-20 09:57:09 +00:00
fix: Fix reconnect failure after leaving host session
This commit is contained in:
parent
7bea3a33fd
commit
66ffc689d1
|
|
@ -1396,7 +1396,19 @@ void CGameNetworkManager::CreateSocket( INetworkPlayer *pNetworkPlayer, bool loc
|
|||
Minecraft *pMinecraft = Minecraft::GetInstance();
|
||||
|
||||
Socket *socket = NULL;
|
||||
shared_ptr<MultiplayerLocalPlayer> mpPlayer = pMinecraft->localplayers[pNetworkPlayer->GetUserIndex()];
|
||||
int localUserIndex = -1;
|
||||
shared_ptr<MultiplayerLocalPlayer> mpPlayer;
|
||||
if (localPlayer)
|
||||
{
|
||||
localUserIndex = pNetworkPlayer->GetUserIndex();
|
||||
#ifdef _WINDOWS64
|
||||
// Win64 client local user is always the primary pad, not the network small-id slot.
|
||||
if (!g_NetworkManager.IsHost())
|
||||
localUserIndex = ProfileManager.GetPrimaryPad();
|
||||
#endif
|
||||
if (localUserIndex >= 0 && localUserIndex < XUSER_MAX_COUNT)
|
||||
mpPlayer = pMinecraft->localplayers[localUserIndex];
|
||||
}
|
||||
if( localPlayer && mpPlayer != NULL && mpPlayer->connection != NULL)
|
||||
{
|
||||
// If we already have a MultiplayerLocalPlayer here then we are doing a session type change
|
||||
|
|
@ -1425,7 +1437,14 @@ void CGameNetworkManager::CreateSocket( INetworkPlayer *pNetworkPlayer, bool loc
|
|||
// the player in to the game server
|
||||
if( localPlayer && g_NetworkManager.IsInGameplay() )
|
||||
{
|
||||
int idx = pNetworkPlayer->GetUserIndex();
|
||||
int idx = localUserIndex;
|
||||
if (idx < 0 || idx >= XUSER_MAX_COUNT)
|
||||
idx = ProfileManager.GetPrimaryPad();
|
||||
if (idx < 0 || idx >= XUSER_MAX_COUNT)
|
||||
{
|
||||
app.DebugPrintf("CreateSocket: invalid local user index %d\n", idx);
|
||||
return;
|
||||
}
|
||||
app.DebugPrintf("Creating new client connection for idx: %d\n", idx);
|
||||
|
||||
ClientConnection *connection;
|
||||
|
|
|
|||
|
|
@ -270,25 +270,44 @@ void CPlatformNetworkManagerStub::DoWork()
|
|||
// Keep LAN search ticking whenever the join menu callback is active, even if QNet state
|
||||
// is not idle due to prior connection attempts.
|
||||
TickSearch();
|
||||
if (_iQNetStubState == QNET_STATE_GAME_PLAY && m_pIQNet->IsHost())
|
||||
if (m_pIQNet->IsHost())
|
||||
{
|
||||
BYTE disconnectedSmallId;
|
||||
while (WinsockNetLayer::PopDisconnectedSmallId(&disconnectedSmallId))
|
||||
{
|
||||
IQNetPlayer *qnetPlayer = m_pIQNet->GetPlayerBySmallId(disconnectedSmallId);
|
||||
if (qnetPlayer != NULL && qnetPlayer->m_smallId == disconnectedSmallId)
|
||||
if (disconnectedSmallId == 0 || disconnectedSmallId >= MINECRAFT_NET_MAX_PLAYERS)
|
||||
continue;
|
||||
|
||||
app.DebugPrintf("Win64 LAN: Processing disconnected smallId=%d\n", disconnectedSmallId);
|
||||
|
||||
IQNetPlayer *qnetPlayer = &IQNet::m_player[disconnectedSmallId];
|
||||
if (qnetPlayer->m_smallId == disconnectedSmallId)
|
||||
{
|
||||
NotifyPlayerLeaving(qnetPlayer);
|
||||
if (qnetPlayer->GetCustomDataValue() != 0)
|
||||
{
|
||||
NotifyPlayerLeaving(qnetPlayer);
|
||||
}
|
||||
else
|
||||
{
|
||||
app.DebugPrintf("Win64 LAN: smallId=%d had no active network player object\n", disconnectedSmallId);
|
||||
}
|
||||
qnetPlayer->m_smallId = 0;
|
||||
qnetPlayer->m_isRemote = false;
|
||||
qnetPlayer->m_isHostPlayer = false;
|
||||
qnetPlayer->m_gamertag[0] = 0;
|
||||
qnetPlayer->SetCustomDataValue(0);
|
||||
WinsockNetLayer::PushFreeSmallId(disconnectedSmallId);
|
||||
if (IQNet::s_playerCount > 1)
|
||||
IQNet::s_playerCount--;
|
||||
}
|
||||
WinsockNetLayer::PushFreeSmallId(disconnectedSmallId);
|
||||
}
|
||||
|
||||
// Keep player-count in sync with active remote slots.
|
||||
DWORD highestUsedIndex = 0;
|
||||
for (DWORD i = 1; i < MINECRAFT_NET_MAX_PLAYERS; i++)
|
||||
{
|
||||
if (IQNet::m_player[i].GetCustomDataValue() != 0)
|
||||
highestUsedIndex = i;
|
||||
}
|
||||
IQNet::s_playerCount = highestUsedIndex + 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -397,11 +397,12 @@ bool WinsockNetLayer::SendToSmallId(BYTE targetSmallId, const void *data, int da
|
|||
SOCKET WinsockNetLayer::GetSocketForSmallId(BYTE smallId)
|
||||
{
|
||||
EnterCriticalSection(&s_connectionsLock);
|
||||
for (size_t i = 0; i < s_connections.size(); i++)
|
||||
for (size_t i = s_connections.size(); i > 0; i--)
|
||||
{
|
||||
if (s_connections[i].smallId == smallId && s_connections[i].active)
|
||||
Win64RemoteConnection &conn = s_connections[i - 1];
|
||||
if (conn.smallId == smallId && conn.active && conn.tcpSocket != INVALID_SOCKET)
|
||||
{
|
||||
SOCKET sock = s_connections[i].tcpSocket;
|
||||
SOCKET sock = conn.tcpSocket;
|
||||
LeaveCriticalSection(&s_connectionsLock);
|
||||
return sock;
|
||||
}
|
||||
|
|
@ -492,9 +493,26 @@ DWORD WINAPI WinsockNetLayer::AcceptThreadProc(LPVOID param)
|
|||
{
|
||||
app.DebugPrintf("Failed to send small ID to client\n");
|
||||
closesocket(clientSocket);
|
||||
PushFreeSmallId(assignedSmallId);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If an old slot for this smallId somehow remains, retire it before reusing the id.
|
||||
EnterCriticalSection(&s_connectionsLock);
|
||||
for (size_t i = 0; i < s_connections.size(); i++)
|
||||
{
|
||||
if (s_connections[i].smallId == assignedSmallId)
|
||||
{
|
||||
s_connections[i].active = false;
|
||||
if (s_connections[i].tcpSocket != INVALID_SOCKET)
|
||||
{
|
||||
closesocket(s_connections[i].tcpSocket);
|
||||
s_connections[i].tcpSocket = INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&s_connectionsLock);
|
||||
|
||||
Win64RemoteConnection conn;
|
||||
conn.tcpSocket = clientSocket;
|
||||
conn.smallId = assignedSmallId;
|
||||
|
|
@ -574,18 +592,21 @@ DWORD WINAPI WinsockNetLayer::RecvThreadProc(LPVOID param)
|
|||
delete[] recvBuf;
|
||||
|
||||
EnterCriticalSection(&s_connectionsLock);
|
||||
for (size_t i = 0; i < s_connections.size(); i++)
|
||||
if (connIdx < (DWORD)s_connections.size())
|
||||
{
|
||||
if (s_connections[i].smallId == clientSmallId)
|
||||
s_connections[connIdx].active = false;
|
||||
if (s_connections[connIdx].tcpSocket != INVALID_SOCKET)
|
||||
{
|
||||
s_connections[i].active = false;
|
||||
closesocket(s_connections[i].tcpSocket);
|
||||
s_connections[i].tcpSocket = INVALID_SOCKET;
|
||||
break;
|
||||
closesocket(s_connections[connIdx].tcpSocket);
|
||||
s_connections[connIdx].tcpSocket = INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&s_connectionsLock);
|
||||
|
||||
// Return this id immediately so rapid reconnect attempts don't exhaust the id pool
|
||||
// while the game thread catches up with disconnect processing.
|
||||
PushFreeSmallId(clientSmallId);
|
||||
|
||||
EnterCriticalSection(&s_disconnectLock);
|
||||
s_disconnectedSmallIds.push_back(clientSmallId);
|
||||
LeaveCriticalSection(&s_disconnectLock);
|
||||
|
|
@ -609,8 +630,21 @@ bool WinsockNetLayer::PopDisconnectedSmallId(BYTE *outSmallId)
|
|||
|
||||
void WinsockNetLayer::PushFreeSmallId(BYTE smallId)
|
||||
{
|
||||
if (smallId == 0 || smallId >= MINECRAFT_NET_MAX_PLAYERS)
|
||||
return;
|
||||
|
||||
EnterCriticalSection(&s_freeSmallIdLock);
|
||||
s_freeSmallIds.push_back(smallId);
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < s_freeSmallIds.size(); i++)
|
||||
{
|
||||
if (s_freeSmallIds[i] == smallId)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
s_freeSmallIds.push_back(smallId);
|
||||
LeaveCriticalSection(&s_freeSmallIdLock);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue