From 13960a93b2a7c114446c109de059db305db4555d Mon Sep 17 00:00:00 2001 From: Kevin <115616336+lag@users.noreply.github.com> Date: Fri, 6 Mar 2026 19:23:32 -0600 Subject: Max players from 8 -> 255 + small connection optimizations (#722) * Multiplayer 8 to max byte increase. Made-with: Cursor * Server chunk optimizations for large player counts, server full notification fix, added to server.properties. --- .../Common/Network/PlatformNetworkManagerStub.cpp | 40 ++++++++++++++++++++- .../Common/Network/PlatformNetworkManagerStub.h | 5 +++ Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp | 42 ++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) (limited to 'Minecraft.Client/Common') 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 #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 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 @@ -532,6 +532,48 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) break; } + 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); -- cgit v1.2.3