diff options
Diffstat (limited to 'Minecraft.Client/Common')
3 files changed, 86 insertions, 1 deletions
diff --git a/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp b/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp index a898c136..970dfd24 100644 --- a/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp +++ b/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp @@ -8,6 +8,8 @@ #include "..\..\Windows64\Windows64_Xuid.h" #include "..\..\Minecraft.h" #include "..\..\User.h" +#include "..\..\MinecraftServer.h" +#include "..\..\PlayerList.h" #include <iostream> #endif @@ -238,15 +240,33 @@ void CPlatformNetworkManagerStub::DoWork() qnetPlayer->m_resolvedXuid = INVALID_XUID; qnetPlayer->m_gamertag[0] = 0; qnetPlayer->SetCustomDataValue(0); - WinsockNetLayer::PushFreeSmallId(disconnectedSmallId); if (IQNet::s_playerCount > 1) IQNet::s_playerCount--; } + // Always return smallId to the free pool so it can be reused (game may have already cleared the slot). + WinsockNetLayer::PushFreeSmallId(disconnectedSmallId); + // Clear O(1) socket lookup so GetSocketForSmallId stays fast (s_connections never shrinks). + WinsockNetLayer::ClearSocketForSmallId(disconnectedSmallId); + // Clear chunk visibility flags for this system so rejoin gets fresh chunk state. + SystemFlagRemoveBySmallId((int)disconnectedSmallId); } } #endif } +bool CPlatformNetworkManagerStub::CanAcceptMoreConnections() +{ +#ifdef _WINDOWS64 + MinecraftServer* server = MinecraftServer::getInstance(); + if (server == NULL) return true; + PlayerList* list = server->getPlayerList(); + if (list == NULL) return true; + return (unsigned int)list->players.size() < (unsigned int)list->getMaxPlayers(); +#else + return true; +#endif +} + int CPlatformNetworkManagerStub::GetPlayerCount() { return m_pIQNet->GetPlayerCount(); @@ -581,6 +601,7 @@ CPlatformNetworkManagerStub::PlayerFlags::PlayerFlags(INetworkPlayer *pNetworkPl this->flags = new unsigned char [ count / 8 ]; memset( this->flags, 0, count / 8 ); this->count = count; + this->m_smallId = (pNetworkPlayer && pNetworkPlayer->IsLocal()) ? 256 : (pNetworkPlayer ? (int)pNetworkPlayer->GetSmallId() : -1); } CPlatformNetworkManagerStub::PlayerFlags::~PlayerFlags() { @@ -618,6 +639,23 @@ void CPlatformNetworkManagerStub::SystemFlagRemovePlayer(INetworkPlayer *pNetwor } } +// Clear chunk flags for a system when they disconnect (by smallId). Call even when we don't find the player, +// so we always clear and the smallId can be reused without stale "chunk seen" state. +void CPlatformNetworkManagerStub::SystemFlagRemoveBySmallId(int smallId) +{ + if (smallId < 0) return; + for (unsigned int i = 0; i < m_playerFlags.size(); i++) + { + if (m_playerFlags[i]->m_smallId == smallId) + { + delete m_playerFlags[i]; + m_playerFlags[i] = m_playerFlags.back(); + m_playerFlags.pop_back(); + return; + } + } +} + void CPlatformNetworkManagerStub::SystemFlagReset() { for( unsigned int i = 0; i < m_playerFlags.size(); i++ ) diff --git a/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.h b/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.h index 28953cec..261639f2 100644 --- a/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.h +++ b/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.h @@ -98,12 +98,14 @@ private: INetworkPlayer *m_pNetworkPlayer; unsigned char *flags; unsigned int count; + int m_smallId; PlayerFlags(INetworkPlayer *pNetworkPlayer, unsigned int count); ~PlayerFlags(); }; vector<PlayerFlags *> m_playerFlags; void SystemFlagAddPlayer(INetworkPlayer *pNetworkPlayer); void SystemFlagRemovePlayer(INetworkPlayer *pNetworkPlayer); + void SystemFlagRemoveBySmallId(int smallId); void SystemFlagReset(); public: virtual void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index); @@ -161,6 +163,9 @@ public: virtual void GetFullFriendSessionInfo( FriendSessionInfo *foundSession, void (* FriendSessionUpdatedFn)(bool success, void *pParam), void *pParam ); virtual void ForceFriendsSessionRefresh(); + // Win64: used by accept thread to reject connections when server is at max players (so we don't assign smallId > max). + bool CanAcceptMoreConnections(); + public: void NotifyPlayerJoined( IQNetPlayer *pQNetPlayer ); void NotifyPlayerLeaving(IQNetPlayer* pQNetPlayer); diff --git a/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp b/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp index c036f7bf..6e354922 100644 --- a/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp @@ -534,6 +534,48 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) if( exitReasonStringId == -1 ) { + Minecraft* pMinecraft = Minecraft::GetInstance(); + int primaryPad = ProfileManager.GetPrimaryPad(); + if( pMinecraft->m_connectionFailed[primaryPad] ) + { + switch( pMinecraft->m_connectionFailedReason[primaryPad] ) + { + case DisconnectPacket::eDisconnect_LoginTooLong: + exitReasonStringId = IDS_DISCONNECTED_LOGIN_TOO_LONG; + break; + case DisconnectPacket::eDisconnect_ServerFull: + exitReasonStringId = IDS_DISCONNECTED_SERVER_FULL; + break; + case DisconnectPacket::eDisconnect_Kicked: + exitReasonStringId = IDS_DISCONNECTED_KICKED; + break; + case DisconnectPacket::eDisconnect_NoUGC_AllLocal: + exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL; + break; + case DisconnectPacket::eDisconnect_NoUGC_Single_Local: + exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL; + break; + case DisconnectPacket::eDisconnect_NoFlying: + exitReasonStringId = IDS_DISCONNECTED_FLYING; + break; + case DisconnectPacket::eDisconnect_Quitting: + exitReasonStringId = IDS_DISCONNECTED_SERVER_QUIT; + break; + case DisconnectPacket::eDisconnect_OutdatedServer: + exitReasonStringId = IDS_DISCONNECTED_SERVER_OLD; + break; + case DisconnectPacket::eDisconnect_OutdatedClient: + exitReasonStringId = IDS_DISCONNECTED_CLIENT_OLD; + break; + default: + exitReasonStringId = IDS_CONNECTION_LOST_SERVER; + break; + } + } + } + + if( exitReasonStringId == -1 ) + { ui.NavigateBack(pClass->m_iPad); } else |
