Merge upstream/main into main
Brings in dedicated server software, README updates, and .vscode cleanup while preserving hardcore mode, screenshot, and watermark toggle features.
This commit is contained in:
@@ -1,21 +1,32 @@
|
||||
#include "stdafx.h"
|
||||
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
|
||||
#include "..\..\Minecraft.Server\ServerLogManager.h"
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Name: DebugSpewV()
|
||||
// Desc: Internal helper function
|
||||
//--------------------------------------------------------------------------------------
|
||||
#ifndef _CONTENT_PACKAGE
|
||||
static VOID DebugSpewV( const CHAR* strFormat, const va_list pArgList )
|
||||
static VOID DebugSpewV( const CHAR* strFormat, va_list pArgList )
|
||||
{
|
||||
#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__
|
||||
assert(0);
|
||||
assert(0);
|
||||
#else
|
||||
CHAR str[2048];
|
||||
// Use the secure CRT to avoid buffer overruns. Specify a count of
|
||||
// _TRUNCATE so that too long strings will be silently truncated
|
||||
// rather than triggering an error.
|
||||
_vsnprintf_s( str, _TRUNCATE, strFormat, pArgList );
|
||||
OutputDebugStringA( str );
|
||||
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
|
||||
// Dedicated server routes legacy debug spew through ServerLogger to preserve CLI prompt handling.
|
||||
if (ServerRuntime::ServerLogManager::ShouldForwardClientDebugLogs())
|
||||
{
|
||||
ServerRuntime::ServerLogManager::ForwardClientDebugSpewLogV(strFormat, pArgList);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
CHAR str[2048];
|
||||
// Use the secure CRT to avoid buffer overruns. Specify a count of
|
||||
// _TRUNCATE so that too long strings will be silently truncated
|
||||
// rather than triggering an error.
|
||||
_vsnprintf_s( str, _TRUNCATE, strFormat, pArgList );
|
||||
OutputDebugStringA( str );
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -31,10 +42,9 @@ VOID CDECL DebugPrintf( const CHAR* strFormat, ... )
|
||||
#endif
|
||||
{
|
||||
#ifndef _CONTENT_PACKAGE
|
||||
va_list pArgList;
|
||||
va_start( pArgList, strFormat );
|
||||
DebugSpewV( strFormat, pArgList );
|
||||
va_end( pArgList );
|
||||
va_list pArgList;
|
||||
va_start( pArgList, strFormat );
|
||||
DebugSpewV( strFormat, pArgList );
|
||||
va_end( pArgList );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
#include "GameRules\ConsoleSchematicFile.h"
|
||||
#include "..\User.h"
|
||||
#include "..\..\Minecraft.World\LevelData.h"
|
||||
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
|
||||
#include "..\..\Minecraft.Server\ServerLogManager.h"
|
||||
#endif
|
||||
#include "..\..\Minecraft.World\net.minecraft.world.entity.player.h"
|
||||
#include "..\EntityRenderDispatcher.h"
|
||||
#include "..\..\Minecraft.World\compression.h"
|
||||
@@ -240,12 +243,21 @@ void CMinecraftApp::DebugPrintf(const char *szFormat, ...)
|
||||
{
|
||||
|
||||
#ifndef _FINAL_BUILD
|
||||
char buf[1024];
|
||||
va_list ap;
|
||||
va_start(ap, szFormat);
|
||||
vsnprintf(buf, sizeof(buf), szFormat, ap);
|
||||
va_end(ap);
|
||||
OutputDebugStringA(buf);
|
||||
va_list ap;
|
||||
va_start(ap, szFormat);
|
||||
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
|
||||
// Dedicated server routes client debug spew through ServerLogger so CLI output stays prompt-safe.
|
||||
if (ServerRuntime::ServerLogManager::ShouldForwardClientDebugLogs())
|
||||
{
|
||||
ServerRuntime::ServerLogManager::ForwardClientAppDebugLogV(szFormat, ap);
|
||||
va_end(ap);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
char buf[1024];
|
||||
vsnprintf(buf, sizeof(buf), szFormat, ap);
|
||||
va_end(ap);
|
||||
OutputDebugStringA(buf);
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -253,53 +265,62 @@ void CMinecraftApp::DebugPrintf(const char *szFormat, ...)
|
||||
void CMinecraftApp::DebugPrintf(int user, const char *szFormat, ...)
|
||||
{
|
||||
#ifndef _FINAL_BUILD
|
||||
if(user == USER_NONE)
|
||||
return;
|
||||
char buf[1024];
|
||||
va_list ap;
|
||||
va_start(ap, szFormat);
|
||||
vsnprintf(buf, sizeof(buf), szFormat, ap);
|
||||
va_end(ap);
|
||||
if(user == USER_NONE)
|
||||
return;
|
||||
va_list ap;
|
||||
va_start(ap, szFormat);
|
||||
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
|
||||
// Dedicated server routes client debug spew through ServerLogger so CLI output stays prompt-safe.
|
||||
if (ServerRuntime::ServerLogManager::ShouldForwardClientDebugLogs())
|
||||
{
|
||||
ServerRuntime::ServerLogManager::ForwardClientUserDebugLogV(user, szFormat, ap);
|
||||
va_end(ap);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
char buf[1024];
|
||||
vsnprintf(buf, sizeof(buf), szFormat, ap);
|
||||
va_end(ap);
|
||||
#ifdef __PS3__
|
||||
unsigned int writelen;
|
||||
sys_tty_write(SYS_TTYP_USER1 + ( user - 1 ), buf, strlen(buf), &writelen );
|
||||
unsigned int writelen;
|
||||
sys_tty_write(SYS_TTYP_USER1 + ( user - 1 ), buf, strlen(buf), &writelen );
|
||||
#elif defined __PSVITA__
|
||||
switch(user)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
SceUID tty2 = sceIoOpen("tty2:", SCE_O_WRONLY, 0);
|
||||
if(tty2>=0)
|
||||
{
|
||||
std::string string1(buf);
|
||||
sceIoWrite(tty2, string1.c_str(), string1.length());
|
||||
sceIoClose(tty2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
SceUID tty3 = sceIoOpen("tty3:", SCE_O_WRONLY, 0);
|
||||
if(tty3>=0)
|
||||
{
|
||||
std::string string1(buf);
|
||||
sceIoWrite(tty3, string1.c_str(), string1.length());
|
||||
sceIoClose(tty3);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
OutputDebugStringA(buf);
|
||||
break;
|
||||
}
|
||||
switch(user)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
SceUID tty2 = sceIoOpen("tty2:", SCE_O_WRONLY, 0);
|
||||
if(tty2>=0)
|
||||
{
|
||||
std::string string1(buf);
|
||||
sceIoWrite(tty2, string1.c_str(), string1.length());
|
||||
sceIoClose(tty2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
SceUID tty3 = sceIoOpen("tty3:", SCE_O_WRONLY, 0);
|
||||
if(tty3>=0)
|
||||
{
|
||||
std::string string1(buf);
|
||||
sceIoWrite(tty3, string1.c_str(), string1.length());
|
||||
sceIoClose(tty3);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
OutputDebugStringA(buf);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
OutputDebugStringA(buf);
|
||||
OutputDebugStringA(buf);
|
||||
#endif
|
||||
#ifndef _XBOX
|
||||
if(user == USER_UI)
|
||||
{
|
||||
ui.logDebugString(buf);
|
||||
}
|
||||
if(user == USER_UI)
|
||||
{
|
||||
ui.logDebugString(buf);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user