aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/Common/Network
diff options
context:
space:
mode:
Diffstat (limited to 'Minecraft.Client/Common/Network')
-rw-r--r--Minecraft.Client/Common/Network/GameNetworkManager.cpp53
-rw-r--r--Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp50
2 files changed, 80 insertions, 23 deletions
diff --git a/Minecraft.Client/Common/Network/GameNetworkManager.cpp b/Minecraft.Client/Common/Network/GameNetworkManager.cpp
index a502dbfb..50aeae68 100644
--- a/Minecraft.Client/Common/Network/GameNetworkManager.cpp
+++ b/Minecraft.Client/Common/Network/GameNetworkManager.cpp
@@ -200,10 +200,12 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft *minecraft, LPVOID lpParame
#endif
int64_t seed = 0;
+ bool dedicatedNoLocalHostPlayer = false;
if (lpParameter != nullptr)
{
NetworkGameInitData *param = static_cast<NetworkGameInitData *>(lpParameter);
seed = param->seed;
+ dedicatedNoLocalHostPlayer = param->dedicatedNoLocalHostPlayer;
app.setLevelGenerationOptions(param->levelGen);
if(param->levelGen != nullptr)
@@ -359,9 +361,19 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft *minecraft, LPVOID lpParame
// PRIMARY PLAYER
vector<ClientConnection *> createdConnections;
- ClientConnection *connection;
+ ClientConnection *connection = nullptr;
- if( g_NetworkManager.IsHost() )
+ if( g_NetworkManager.IsHost() && dedicatedNoLocalHostPlayer )
+ {
+ app.DebugPrintf("Dedicated server mode: skipping local host client connection\n");
+
+ // Keep telemetry behavior consistent with the host path.
+ INT multiplayerInstanceId = TelemetryManager->GenerateMultiplayerInstanceId();
+ TelemetryManager->SetMultiplayerInstanceId(multiplayerInstanceId);
+
+ app.SetGameMode( eMode_Multiplayer );
+ }
+ else if( g_NetworkManager.IsHost() )
{
connection = new ClientConnection(minecraft, nullptr);
}
@@ -390,16 +402,18 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft *minecraft, LPVOID lpParame
connection = new ClientConnection(minecraft, socket);
}
- if( !connection->createdOk )
+ if (connection != nullptr)
{
- assert(false);
- delete connection;
- connection = nullptr;
- MinecraftServer::HaltServer();
- return false;
- }
+ if( !connection->createdOk )
+ {
+ assert(false);
+ delete connection;
+ connection = nullptr;
+ MinecraftServer::HaltServer();
+ return false;
+ }
- connection->send(std::make_shared<PreLoginPacket>(minecraft->user->name));
+ connection->send(std::make_shared<PreLoginPacket>(minecraft->user->name));
// Tick connection until we're ready to go. The stages involved in this are:
// (1) Creating the ClientConnection sends a prelogin packet to the server
@@ -434,9 +448,9 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft *minecraft, LPVOID lpParame
connection->close();
}
- if( connection->isStarted() && !connection->isClosed() )
- {
- createdConnections.push_back( connection );
+ if( connection->isStarted() && !connection->isClosed() )
+ {
+ createdConnections.push_back( connection );
int primaryPad = ProfileManager.GetPrimaryPad();
app.SetRichPresenceContext(primaryPad,CONTEXT_GAME_STATE_BLANK);
@@ -533,13 +547,14 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft *minecraft, LPVOID lpParame
}
}
- app.SetGameMode( eMode_Multiplayer );
- }
- else if ( connection->isClosed() || !IsInSession())
- {
+ app.SetGameMode( eMode_Multiplayer );
+ }
+ else if ( connection->isClosed() || !IsInSession())
+ {
// assert(false);
- MinecraftServer::HaltServer();
- return false;
+ MinecraftServer::HaltServer();
+ return false;
+ }
}
diff --git a/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp b/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp
index 7340a7e0..1e625098 100644
--- a/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp
+++ b/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp
@@ -240,7 +240,13 @@ void CPlatformNetworkManagerStub::DoWork()
qnetPlayer->m_resolvedXuid = INVALID_XUID;
qnetPlayer->m_gamertag[0] = 0;
qnetPlayer->SetCustomDataValue(0);
- while (IQNet::s_playerCount > 1 && IQNet::m_player[IQNet::s_playerCount - 1].GetCustomDataValue() == 0)
+ // Recalculate s_playerCount as the highest active slot + 1.
+ // A blind decrement would hide players at higher-indexed slots when a
+ // lower-indexed player disconnects first: GetPlayerBySmallId scans
+ // [0, s_playerCount) so any slot at or above the decremented count
+ // becomes invisible, causing its disconnect to be missed (ghost player).
+ while (IQNet::s_playerCount > 1 &&
+ IQNet::m_player[IQNet::s_playerCount - 1].GetCustomDataValue() == 0)
IQNet::s_playerCount--;
}
// NOTE: Do NOT call PushFreeSmallId here. The old PlayerConnection's
@@ -257,6 +263,25 @@ void CPlatformNetworkManagerStub::DoWork()
SystemFlagRemoveBySmallId(disconnectedSmallId);
}
}
+
+ // Client-side host disconnect detection:
+ // if TCP is gone, propagate through normal network-disconnect flow so UI returns to menus.
+ // The processing from the Xbox version will be reused.
+ if (_iQNetStubState == QNET_STATE_GAME_PLAY && !m_pIQNet->IsHost() && !m_bLeavingGame)
+ {
+ if (!WinsockNetLayer::IsConnected())
+ {
+ if (!m_bLeaveGameOnTick)
+ {
+ m_bLeaveGameOnTick = true;
+ g_NetworkManager.HandleDisconnect(false);
+ }
+ }
+ else
+ {
+ m_bLeaveGameOnTick = false;
+ }
+ }
#endif
}
@@ -356,6 +381,7 @@ bool CPlatformNetworkManagerStub::LeaveGame(bool bMigrateHost)
if( m_bLeavingGame ) return true;
m_bLeavingGame = true;
+ m_bLeaveGameOnTick = false;
#ifdef _WINDOWS64
WinsockNetLayer::StopAdvertising();
@@ -404,6 +430,7 @@ void CPlatformNetworkManagerStub::HostGame(int localUsersMask, bool bOnlineGame,
localUsersMask |= GetLocalPlayerMask( g_NetworkManager.GetPrimaryPad() );
m_bLeavingGame = false;
+ m_bLeaveGameOnTick = false;
m_pIQNet->HostGame();
@@ -433,9 +460,23 @@ void CPlatformNetworkManagerStub::HostGame(int localUsersMask, bool bOnlineGame,
if (WinsockNetLayer::IsActive())
{
- const wchar_t* hostName = IQNet::m_player[0].m_gamertag;
- unsigned int settings = app.GetGameHostOption(eGameHostOption_All);
- WinsockNetLayer::StartAdvertising(port, hostName, settings, 0, 0, MINECRAFT_NET_VERSION);
+ // For Dedicated Server, refer to `lan-advertise` in `server.properties`
+ bool enableLanAdvertising = true;
+ if (g_Win64DedicatedServer)
+ {
+ enableLanAdvertising = g_Win64DedicatedServerLanAdvertise;
+ }
+
+ if (enableLanAdvertising)
+ {
+ const wchar_t* hostName = IQNet::m_player[0].m_gamertag;
+ unsigned int settings = app.GetGameHostOption(eGameHostOption_All);
+ WinsockNetLayer::StartAdvertising(port, hostName, settings, 0, 0, MINECRAFT_NET_VERSION);
+ }
+ else
+ {
+ WinsockNetLayer::StopAdvertising();
+ }
}
#endif
//#endif
@@ -463,6 +504,7 @@ int CPlatformNetworkManagerStub::JoinGame(FriendSessionInfo* searchResult, int l
return CGameNetworkManager::JOINGAME_FAIL_GENERAL;
m_bLeavingGame = false;
+ m_bLeaveGameOnTick = false;
IQNet::s_isHosting = false;
m_pIQNet->ClientJoinGame();