mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-08-20 09:57:09 +00:00
Merge branch 'main' of https://github.com/smartcmd/MinecraftConsoles
This commit is contained in:
commit
cb6106b490
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -433,3 +433,6 @@ build/*
|
|||
|
||||
# Local saves
|
||||
Minecraft.Client/Saves/
|
||||
|
||||
# Visual Studio Per-User Config
|
||||
*.user
|
||||
|
|
|
|||
|
|
@ -759,6 +759,18 @@ void ClientConnection::handleAddPlayer(shared_ptr<AddPlayerPacket> packet)
|
|||
return;
|
||||
}
|
||||
}
|
||||
#ifdef _WINDOWS64
|
||||
// Win64 keeps local-player identity separate from network smallId; also guard against creating
|
||||
// a duplicate remote player for a local slot by checking the username directly.
|
||||
for (unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
|
||||
{
|
||||
if (minecraft->localplayers[idx] != NULL && minecraft->localplayers[idx]->name == packet->name)
|
||||
{
|
||||
app.DebugPrintf("AddPlayerPacket received for local player name %ls\n", packet->name.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*#ifdef _WINDOWS64
|
||||
// On Windows64 all XUIDs are INVALID_XUID so the XUID check above never fires.
|
||||
// packet->m_playerIndex is the server-assigned sequential index (set via LoginPacket),
|
||||
|
|
@ -800,22 +812,50 @@ void ClientConnection::handleAddPlayer(shared_ptr<AddPlayerPacket> packet)
|
|||
|
||||
#ifdef _WINDOWS64
|
||||
{
|
||||
IQNetPlayer* matchedQNetPlayer = NULL;
|
||||
PlayerUID pktXuid = player->getXuid();
|
||||
const PlayerUID WIN64_XUID_BASE = (PlayerUID)0xe000d45248242f2e;
|
||||
// Legacy compatibility path for peers still using embedded smallId XUIDs.
|
||||
if (pktXuid >= WIN64_XUID_BASE && pktXuid < WIN64_XUID_BASE + MINECRAFT_NET_MAX_PLAYERS)
|
||||
{
|
||||
BYTE smallId = (BYTE)(pktXuid - WIN64_XUID_BASE);
|
||||
INetworkPlayer* np = g_NetworkManager.GetPlayerBySmallId(smallId);
|
||||
if (np != NULL)
|
||||
{
|
||||
NetworkPlayerXbox* npx = (NetworkPlayerXbox*)np;
|
||||
matchedQNetPlayer = npx->GetQNetPlayer();
|
||||
}
|
||||
}
|
||||
|
||||
// Current Win64 path: identify QNet player by name and attach packet XUID.
|
||||
if (matchedQNetPlayer == NULL)
|
||||
{
|
||||
for (BYTE smallId = 0; smallId < MINECRAFT_NET_MAX_PLAYERS; ++smallId)
|
||||
{
|
||||
INetworkPlayer* np = g_NetworkManager.GetPlayerBySmallId(smallId);
|
||||
if (np == NULL)
|
||||
continue;
|
||||
|
||||
NetworkPlayerXbox* npx = (NetworkPlayerXbox*)np;
|
||||
IQNetPlayer* qp = npx->GetQNetPlayer();
|
||||
if (qp != NULL && qp->m_gamertag[0] == 0)
|
||||
if (qp != NULL && _wcsicmp(qp->m_gamertag, packet->name.c_str()) == 0)
|
||||
{
|
||||
wcsncpy_s(qp->m_gamertag, 32, packet->name.c_str(), _TRUNCATE);
|
||||
matchedQNetPlayer = qp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matchedQNetPlayer != NULL)
|
||||
{
|
||||
// Store packet-authoritative XUID on this network slot so later lookups by XUID
|
||||
// (e.g. remove player, display mapping) work for both legacy and uid.dat clients.
|
||||
matchedQNetPlayer->m_resolvedXuid = pktXuid;
|
||||
if (matchedQNetPlayer->m_gamertag[0] == 0)
|
||||
{
|
||||
wcsncpy_s(matchedQNetPlayer->m_gamertag, 32, packet->name.c_str(), _TRUNCATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -985,6 +1025,8 @@ void ClientConnection::handleRemoveEntity(shared_ptr<RemoveEntitiesPacket> packe
|
|||
qp->m_smallId = 0;
|
||||
qp->m_isRemote = false;
|
||||
qp->m_isHostPlayer = false;
|
||||
// Clear resolved id to avoid stale XUID -> player matches after disconnect.
|
||||
qp->m_resolvedXuid = INVALID_XUID;
|
||||
qp->m_gamertag[0] = 0;
|
||||
qp->SetCustomDataValue(0);
|
||||
}
|
||||
|
|
@ -3956,4 +3998,4 @@ ClientConnection::DeferredEntityLinkPacket::DeferredEntityLinkPacket(shared_ptr<
|
|||
{
|
||||
m_recievedTick = GetTickCount();
|
||||
m_packet = packet;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -260,16 +260,13 @@ void SoundEngine::updateMiniAudio()
|
|||
continue;
|
||||
}
|
||||
|
||||
float finalVolume = s->info.volume;
|
||||
float finalVolume = s->info.volume * m_MasterEffectsVolume;
|
||||
if (finalVolume > 1.0f)
|
||||
finalVolume = 1.0f;
|
||||
|
||||
ma_sound_set_volume(&s->sound, finalVolume);
|
||||
|
||||
if (!s->info.bUseSoundsPitchVal)
|
||||
{
|
||||
ma_sound_set_pitch(&s->sound, s->info.pitch);
|
||||
}
|
||||
ma_sound_set_pitch(&s->sound, s->info.pitch);
|
||||
|
||||
if (s->info.bIs3D)
|
||||
{
|
||||
|
|
@ -967,14 +964,8 @@ void SoundEngine::playMusicTick()
|
|||
// AP - moved to a separate function so it can be called from the mixer callback on Vita
|
||||
void SoundEngine::playMusicUpdate()
|
||||
{
|
||||
//return;
|
||||
static bool firstCall = true;
|
||||
static float fMusicVol = 0.0f;
|
||||
if( firstCall )
|
||||
{
|
||||
fMusicVol = getMasterMusicVolume();
|
||||
firstCall = false;
|
||||
}
|
||||
fMusicVol = getMasterMusicVolume();
|
||||
|
||||
switch(m_StreamState)
|
||||
{
|
||||
|
|
@ -1242,7 +1233,7 @@ void SoundEngine::playMusicUpdate()
|
|||
|
||||
ma_sound_set_pitch(&m_musicStream, m_StreamingAudioInfo.pitch);
|
||||
|
||||
float finalVolume = m_StreamingAudioInfo.volume * m_MasterMusicVolume;
|
||||
float finalVolume = m_StreamingAudioInfo.volume * getMasterMusicVolume();
|
||||
|
||||
ma_sound_set_volume(&m_musicStream, finalVolume);
|
||||
ma_result startResult = ma_sound_start(&m_musicStream);
|
||||
|
|
@ -1370,14 +1361,11 @@ void SoundEngine::playMusicUpdate()
|
|||
}
|
||||
|
||||
// volume change required?
|
||||
if (fMusicVol != getMasterMusicVolume())
|
||||
if (m_musicStreamActive)
|
||||
{
|
||||
if (m_musicStreamActive)
|
||||
{
|
||||
float finalVolume = m_StreamingAudioInfo.volume * fMusicVol;
|
||||
float finalVolume = m_StreamingAudioInfo.volume * fMusicVol;
|
||||
|
||||
ma_sound_set_volume(&m_musicStream, finalVolume);
|
||||
}
|
||||
ma_sound_set_volume(&m_musicStream, finalVolume);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2441,10 +2441,10 @@ void CMinecraftApp::ClearGameSettingsChangedFlag(int iPad)
|
|||
|
||||
///////////////////////////
|
||||
//
|
||||
// Remove the debug settings in the content package build
|
||||
// Remove the debug settings in the release build
|
||||
//
|
||||
////////////////////////////
|
||||
#ifndef _DEBUG_MENUS_ENABLED
|
||||
#ifndef _DEBUG
|
||||
unsigned int CMinecraftApp::GetGameSettingsDebugMask(int iPad,bool bOverridePlayer) //bOverridePlayer is to force the send for the server to get the read options
|
||||
{
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "..\..\Xbox\Network\NetworkPlayerXbox.h"
|
||||
#ifdef _WINDOWS64
|
||||
#include "..\..\Windows64\Network\WinsockNetLayer.h"
|
||||
#include "..\..\Windows64\Windows64_Xuid.h"
|
||||
#include "..\..\Minecraft.h"
|
||||
#include "..\..\User.h"
|
||||
#include <iostream>
|
||||
|
|
@ -234,6 +235,7 @@ void CPlatformNetworkManagerStub::DoWork()
|
|||
qnetPlayer->m_smallId = 0;
|
||||
qnetPlayer->m_isRemote = false;
|
||||
qnetPlayer->m_isHostPlayer = false;
|
||||
qnetPlayer->m_resolvedXuid = INVALID_XUID;
|
||||
qnetPlayer->m_gamertag[0] = 0;
|
||||
qnetPlayer->SetCustomDataValue(0);
|
||||
WinsockNetLayer::PushFreeSmallId(disconnectedSmallId);
|
||||
|
|
@ -354,7 +356,9 @@ void CPlatformNetworkManagerStub::HostGame(int localUsersMask, bool bOnlineGame,
|
|||
#ifdef _WINDOWS64
|
||||
IQNet::m_player[0].m_smallId = 0;
|
||||
IQNet::m_player[0].m_isRemote = false;
|
||||
// world host is pinned to legacy host XUID to keep old player data compatibility.
|
||||
IQNet::m_player[0].m_isHostPlayer = true;
|
||||
IQNet::m_player[0].m_resolvedXuid = Win64Xuid::GetLegacyEmbeddedHostXuid();
|
||||
IQNet::s_playerCount = 1;
|
||||
#endif
|
||||
|
||||
|
|
@ -411,6 +415,8 @@ int CPlatformNetworkManagerStub::JoinGame(FriendSessionInfo* searchResult, int l
|
|||
IQNet::m_player[0].m_smallId = 0;
|
||||
IQNet::m_player[0].m_isRemote = true;
|
||||
IQNet::m_player[0].m_isHostPlayer = true;
|
||||
// Remote host still maps to legacy host XUID in mixed old/new sessions.
|
||||
IQNet::m_player[0].m_resolvedXuid = Win64Xuid::GetLegacyEmbeddedHostXuid();
|
||||
wcsncpy_s(IQNet::m_player[0].m_gamertag, 32, searchResult->data.hostName, _TRUNCATE);
|
||||
|
||||
WinsockNetLayer::StopDiscovery();
|
||||
|
|
@ -426,6 +432,8 @@ int CPlatformNetworkManagerStub::JoinGame(FriendSessionInfo* searchResult, int l
|
|||
IQNet::m_player[localSmallId].m_smallId = localSmallId;
|
||||
IQNet::m_player[localSmallId].m_isRemote = false;
|
||||
IQNet::m_player[localSmallId].m_isHostPlayer = false;
|
||||
// Local non-host identity is the persistent uid.dat XUID.
|
||||
IQNet::m_player[localSmallId].m_resolvedXuid = Win64Xuid::ResolvePersistentXuid();
|
||||
|
||||
Minecraft* pMinecraft = Minecraft::GetInstance();
|
||||
wcscpy_s(IQNet::m_player[localSmallId].m_gamertag, 32, pMinecraft->user->name.c_str());
|
||||
|
|
|
|||
|
|
@ -2342,7 +2342,13 @@ void UIController::PlayUISFX(ESoundEffect eSound)
|
|||
if (time - m_lastUiSfx < 10) { return; }
|
||||
m_lastUiSfx = time;
|
||||
|
||||
Minecraft::GetInstance()->soundEngine->playUI(eSound,1.0f,1.0f);
|
||||
float pitch = 1.0f;
|
||||
if (eSound == eSFX_Focus)
|
||||
{
|
||||
pitch += (m_randomDistribution(m_randomGenerator) - 0.5f) / 10;
|
||||
}
|
||||
|
||||
Minecraft::GetInstance()->soundEngine->playUI(eSound,1.0f,pitch);
|
||||
}
|
||||
|
||||
void UIController::DisplayGamertag(unsigned int iPad, bool show)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using namespace std;
|
|||
#include "IUIController.h"
|
||||
#include "UIEnums.h"
|
||||
#include "UIGroup.h"
|
||||
#include <random>
|
||||
|
||||
class UIAbstractBitmapFont;
|
||||
class UIBitmapFont;
|
||||
|
|
@ -63,6 +64,9 @@ private:
|
|||
UITTFFont *m_mcTTFFont;
|
||||
UIBitmapFont *m_moj7, *m_moj11;
|
||||
|
||||
std::mt19937 m_randomGenerator;
|
||||
std::uniform_real_distribution<float> m_randomDistribution;
|
||||
|
||||
public:
|
||||
void setCleanupOnReload();
|
||||
void updateCurrentFont();
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ UIScene_HelpAndOptionsMenu::UIScene_HelpAndOptionsMenu(int iPad, void *initData,
|
|||
// We don't have a reinstall content, so remove the button
|
||||
removeControl( &m_buttons[BUTTON_HAO_REINSTALL], false );
|
||||
|
||||
#ifdef _FINAL_BUILD
|
||||
#ifndef _DEBUG
|
||||
removeControl( &m_buttons[BUTTON_HAO_DEBUG], false);
|
||||
#else
|
||||
if(!app.DebugSettingsOn()) removeControl( &m_buttons[BUTTON_HAO_DEBUG], false);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "Windows64\Social\SocialManager.h"
|
||||
#include "Windows64\Sentient\DynamicConfigurations.h"
|
||||
#include "Windows64\Network\WinsockNetLayer.h"
|
||||
#include "Windows64\Windows64_Xuid.h"
|
||||
#elif defined __PSVITA__
|
||||
#include "PSVita\Sentient\SentientManager.h"
|
||||
#include "StatsCounter.h"
|
||||
|
|
@ -200,7 +201,15 @@ DWORD IQNetPlayer::GetCurrentRtt() { return 0; }
|
|||
bool IQNetPlayer::IsHost() { return m_isHostPlayer; }
|
||||
bool IQNetPlayer::IsGuest() { return false; }
|
||||
bool IQNetPlayer::IsLocal() { return !m_isRemote; }
|
||||
PlayerUID IQNetPlayer::GetXuid() { return (PlayerUID)(0xe000d45248242f2e + m_smallId); } // todo: restore to INVALID_XUID once saves support this
|
||||
PlayerUID IQNetPlayer::GetXuid()
|
||||
{
|
||||
// Compatibility model:
|
||||
// - Preferred path: use per-player resolved XUID populated from login/add-player flow.
|
||||
// - Fallback path: keep legacy base+smallId behavior for peers/saves still on old scheme.
|
||||
if (m_resolvedXuid != INVALID_XUID)
|
||||
return m_resolvedXuid;
|
||||
return (PlayerUID)(0xe000d45248242f2e + m_smallId);
|
||||
}
|
||||
LPCWSTR IQNetPlayer::GetGamertag() { return m_gamertag; }
|
||||
int IQNetPlayer::GetSessionIndex() { return m_smallId; }
|
||||
bool IQNetPlayer::IsTalking() { return false; }
|
||||
|
|
@ -226,6 +235,7 @@ void Win64_SetupRemoteQNetPlayer(IQNetPlayer * player, BYTE smallId, bool isHost
|
|||
player->m_smallId = smallId;
|
||||
player->m_isRemote = !isLocal;
|
||||
player->m_isHostPlayer = isHost;
|
||||
player->m_resolvedXuid = INVALID_XUID;
|
||||
swprintf_s(player->m_gamertag, 32, L"Player%d", smallId);
|
||||
if (smallId >= IQNet::s_playerCount)
|
||||
IQNet::s_playerCount = smallId + 1;
|
||||
|
|
@ -285,8 +295,13 @@ IQNetPlayer* IQNet::GetPlayerByXuid(PlayerUID xuid)
|
|||
{
|
||||
for (DWORD i = 0; i < s_playerCount; i++)
|
||||
{
|
||||
if (Win64_IsActivePlayer(&m_player[i], i) && m_player[i].GetXuid() == xuid) return &m_player[i];
|
||||
if (!Win64_IsActivePlayer(&m_player[i], i))
|
||||
continue;
|
||||
|
||||
if (m_player[i].GetXuid() == xuid)
|
||||
return &m_player[i];
|
||||
}
|
||||
// Keep existing stub behavior: return host slot instead of NULL on miss.
|
||||
return &m_player[0];
|
||||
}
|
||||
DWORD IQNet::GetPlayerCount()
|
||||
|
|
@ -301,7 +316,13 @@ DWORD IQNet::GetPlayerCount()
|
|||
QNET_STATE IQNet::GetState() { return _iQNetStubState; }
|
||||
bool IQNet::IsHost() { return s_isHosting; }
|
||||
HRESULT IQNet::JoinGameFromInviteInfo(DWORD dwUserIndex, DWORD dwUserMask, const INVITE_INFO * pInviteInfo) { return S_OK; }
|
||||
void IQNet::HostGame() { _iQNetStubState = QNET_STATE_SESSION_STARTING; s_isHosting = true; }
|
||||
void IQNet::HostGame()
|
||||
{
|
||||
_iQNetStubState = QNET_STATE_SESSION_STARTING;
|
||||
s_isHosting = true;
|
||||
// Host slot keeps legacy XUID so old host player data remains addressable.
|
||||
m_player[0].m_resolvedXuid = Win64Xuid::GetLegacyEmbeddedHostXuid();
|
||||
}
|
||||
void IQNet::ClientJoinGame()
|
||||
{
|
||||
_iQNetStubState = QNET_STATE_SESSION_STARTING;
|
||||
|
|
@ -312,6 +333,7 @@ void IQNet::ClientJoinGame()
|
|||
m_player[i].m_smallId = (BYTE)i;
|
||||
m_player[i].m_isRemote = true;
|
||||
m_player[i].m_isHostPlayer = false;
|
||||
m_player[i].m_resolvedXuid = INVALID_XUID;
|
||||
m_player[i].m_gamertag[0] = 0;
|
||||
m_player[i].SetCustomDataValue(0);
|
||||
}
|
||||
|
|
@ -326,6 +348,7 @@ void IQNet::EndGame()
|
|||
m_player[i].m_smallId = (BYTE)i;
|
||||
m_player[i].m_isRemote = false;
|
||||
m_player[i].m_isHostPlayer = false;
|
||||
m_player[i].m_resolvedXuid = INVALID_XUID;
|
||||
m_player[i].m_gamertag[0] = 0;
|
||||
m_player[i].SetCustomDataValue(0);
|
||||
}
|
||||
|
|
@ -575,10 +598,13 @@ void C_4JProfile::GetXUID(int iPad, PlayerUID * pXuid, bool bOnlineXuid)
|
|||
*pXuid = INVALID_XUID;
|
||||
return;
|
||||
}
|
||||
// LoginPacket reads this value as client identity:
|
||||
// - host keeps legacy host XUID for world compatibility
|
||||
// - non-host uses persistent uid.dat-backed XUID
|
||||
if (IQNet::s_isHosting)
|
||||
*pXuid = 0xe000d45248242f2e;
|
||||
*pXuid = Win64Xuid::GetLegacyEmbeddedHostXuid();
|
||||
else
|
||||
*pXuid = 0xe000d45248242f2e + WinsockNetLayer::GetLocalSmallId();
|
||||
*pXuid = Win64Xuid::ResolvePersistentXuid();
|
||||
#else
|
||||
* pXuid = 0xe000d45248242f2e + iPad;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<LastConfigDeployed>Debug</LastConfigDeployed>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)$(Platform)\$(Configuration)\</LocalDebuggerWorkingDirectory>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64EC'">
|
||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)$(Platform)\$(Configuration)\</LocalDebuggerWorkingDirectory>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)$(Platform)\$(Configuration)\</LocalDebuggerWorkingDirectory>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64EC'">
|
||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)$(Platform)\$(Configuration)\</LocalDebuggerWorkingDirectory>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -52,6 +52,7 @@
|
|||
#include "..\Minecraft.World\net.minecraft.world.level.dimension.h"
|
||||
#include "..\Minecraft.World\net.minecraft.world.item.h"
|
||||
#include "..\Minecraft.World\Minecraft.World.h"
|
||||
#include "Windows64\Windows64_Xuid.h"
|
||||
#include "ClientConnection.h"
|
||||
#include "..\Minecraft.World\HellRandomLevelSource.h"
|
||||
#include "..\Minecraft.World\net.minecraft.world.entity.animal.h"
|
||||
|
|
@ -1038,6 +1039,19 @@ shared_ptr<MultiplayerLocalPlayer> Minecraft::createExtraLocalPlayer(int idx, co
|
|||
PlayerUID playerXUIDOnline = INVALID_XUID;
|
||||
ProfileManager.GetXUID(idx,&playerXUIDOffline,false);
|
||||
ProfileManager.GetXUID(idx,&playerXUIDOnline,true);
|
||||
#ifdef _WINDOWS64
|
||||
// Compatibility rule for Win64 id migration
|
||||
// host keeps legacy host XUID, non-host uses persistent uid.dat XUID.
|
||||
INetworkPlayer *localNetworkPlayer = g_NetworkManager.GetLocalPlayerByUserIndex(idx);
|
||||
if(localNetworkPlayer != NULL && localNetworkPlayer->IsHost())
|
||||
{
|
||||
playerXUIDOffline = Win64Xuid::GetLegacyEmbeddedHostXuid();
|
||||
}
|
||||
else
|
||||
{
|
||||
playerXUIDOffline = Win64Xuid::ResolvePersistentXuid();
|
||||
}
|
||||
#endif
|
||||
localplayers[idx]->setXuid(playerXUIDOffline);
|
||||
localplayers[idx]->setOnlineXuid(playerXUIDOnline);
|
||||
localplayers[idx]->setIsGuest(ProfileManager.IsGuest(idx));
|
||||
|
|
@ -4298,6 +4312,19 @@ void Minecraft::setLevel(MultiPlayerLevel *level, int message /*=-1*/, shared_pt
|
|||
// player doesn't have an online UID, set it from the player name
|
||||
playerXUIDOnline.setForAdhoc();
|
||||
}
|
||||
#endif
|
||||
#ifdef _WINDOWS64
|
||||
// On Windows, the implementation has been changed to use a per-client pseudo XUID based on `uid.dat`.
|
||||
// To maintain player data compatibility with existing worlds, the world host (the first player) will use the previous embedded pseudo XUID.
|
||||
INetworkPlayer *localNetworkPlayer = g_NetworkManager.GetLocalPlayerByUserIndex(iPrimaryPlayer);
|
||||
if(localNetworkPlayer != NULL && localNetworkPlayer->IsHost())
|
||||
{
|
||||
playerXUIDOffline = Win64Xuid::GetLegacyEmbeddedHostXuid();
|
||||
}
|
||||
else
|
||||
{
|
||||
playerXUIDOffline = Win64Xuid::ResolvePersistentXuid();
|
||||
}
|
||||
#endif
|
||||
player->setXuid(playerXUIDOffline);
|
||||
player->setOnlineXuid(playerXUIDOnline);
|
||||
|
|
@ -4481,6 +4508,18 @@ void Minecraft::respawnPlayer(int iPad, int dimension, int newEntityId)
|
|||
PlayerUID playerXUIDOnline = INVALID_XUID;
|
||||
ProfileManager.GetXUID(iTempPad,&playerXUIDOffline,false);
|
||||
ProfileManager.GetXUID(iTempPad,&playerXUIDOnline,true);
|
||||
#ifdef _WINDOWS64
|
||||
// Same compatibility rule as create/init paths.
|
||||
INetworkPlayer *localNetworkPlayer = g_NetworkManager.GetLocalPlayerByUserIndex(iTempPad);
|
||||
if(localNetworkPlayer != NULL && localNetworkPlayer->IsHost())
|
||||
{
|
||||
playerXUIDOffline = Win64Xuid::GetLegacyEmbeddedHostXuid();
|
||||
}
|
||||
else
|
||||
{
|
||||
playerXUIDOffline = Win64Xuid::ResolvePersistentXuid();
|
||||
}
|
||||
#endif
|
||||
player->setXuid(playerXUIDOffline);
|
||||
player->setOnlineXuid(playerXUIDOnline);
|
||||
player->setIsGuest( ProfileManager.IsGuest(iTempPad) );
|
||||
|
|
|
|||
|
|
@ -161,6 +161,23 @@ void PendingConnection::handleLogin(shared_ptr<LoginPacket> packet)
|
|||
//if (true)// 4J removed !server->onlineMode)
|
||||
bool sentDisconnect = false;
|
||||
|
||||
// Use the same Xuid choice as handleAcceptedLogin (offline first, online fallback).
|
||||
//
|
||||
PlayerUID loginXuid = packet->m_offlineXuid;
|
||||
if (loginXuid == INVALID_XUID) loginXuid = packet->m_onlineXuid;
|
||||
|
||||
bool duplicateXuid = false;
|
||||
if (loginXuid != INVALID_XUID && server->getPlayers()->getPlayer(loginXuid) != nullptr)
|
||||
{
|
||||
duplicateXuid = true;
|
||||
}
|
||||
else if (packet->m_onlineXuid != INVALID_XUID &&
|
||||
packet->m_onlineXuid != loginXuid &&
|
||||
server->getPlayers()->getPlayer(packet->m_onlineXuid) != nullptr)
|
||||
{
|
||||
duplicateXuid = true;
|
||||
}
|
||||
|
||||
if( sentDisconnect )
|
||||
{
|
||||
// Do nothing
|
||||
|
|
@ -169,6 +186,12 @@ void PendingConnection::handleLogin(shared_ptr<LoginPacket> packet)
|
|||
{
|
||||
disconnect(DisconnectPacket::eDisconnect_Banned);
|
||||
}
|
||||
else if (duplicateXuid)
|
||||
{
|
||||
// if same XUID already in use by another player so disconnect this one.
|
||||
app.DebugPrintf("Rejecting duplicate xuid for name: %ls\n", name.c_str());
|
||||
disconnect(DisconnectPacket::eDisconnect_Banned);
|
||||
}
|
||||
#ifdef _WINDOWS64
|
||||
else if (g_bRejectDuplicateNames)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1093,6 +1093,10 @@ void PlayerConnection::handleContainerClose(shared_ptr<ContainerClosePacket> pac
|
|||
#ifndef _CONTENT_PACKAGE
|
||||
void PlayerConnection::handleContainerSetSlot(shared_ptr<ContainerSetSlotPacket> packet)
|
||||
{
|
||||
if(player->gameMode->isSurvival()){ // Still allow creative players to change slots manually with packets(?) -- might want this different.
|
||||
server->warn(L"Player " + player->getName() + L" just tried to set a slot in a container in survival mode");
|
||||
return;
|
||||
}
|
||||
if (packet->containerId == AbstractContainerMenu::CONTAINER_ID_CARRIED )
|
||||
{
|
||||
player->inventory->setCarried(packet->item);
|
||||
|
|
@ -1589,6 +1593,10 @@ void PlayerConnection::handleCraftItem(shared_ptr<CraftItemPacket> packet)
|
|||
Recipy::INGREDIENTS_REQUIRED *pRecipeIngredientsRequired=Recipes::getInstance()->getRecipeIngredientsArray();
|
||||
shared_ptr<ItemInstance> pTempItemInst=pRecipeIngredientsRequired[iRecipe].pRecipy->assemble(nullptr);
|
||||
|
||||
size_t recipeCount = Recipes::getInstance()->getRecipies()->size();
|
||||
if (iRecipe < 0 || iRecipe >= (int)recipeCount)
|
||||
return;
|
||||
|
||||
if(app.DebugSettingsOn() && (player->GetDebugOptions()&(1L<<eDebugSetting_CraftAnything)))
|
||||
{
|
||||
pTempItemInst->onCraftedBy(player->level, dynamic_pointer_cast<Player>( player->shared_from_this() ), pTempItemInst->count );
|
||||
|
|
@ -1607,9 +1615,21 @@ void PlayerConnection::handleCraftItem(shared_ptr<CraftItemPacket> packet)
|
|||
{
|
||||
|
||||
|
||||
// TODO 4J Stu - Assume at the moment that the client can work this out for us...
|
||||
//if(pRecipeIngredientsRequired[iRecipe].bCanMake)
|
||||
//{
|
||||
Recipy::INGREDIENTS_REQUIRED &req = pRecipeIngredientsRequired[iRecipe];
|
||||
if (req.iType == RECIPE_TYPE_3x3 && dynamic_cast<CraftingMenu *>(player->containerMenu) == NULL)
|
||||
{
|
||||
server->warn(L"Player " + player->getName() + L" tried to craft a 3x3 recipe without a crafting bench");
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < req.iIngC; i++){
|
||||
int need = req.iIngValA[i];
|
||||
int have = player->inventory->countResource(req.iIngIDA[i], req.iIngAuxValA[i]);
|
||||
if (have < need){
|
||||
server->warn(L"Player " + player->getName() + L" just tried to craft item " + to_wstring(pTempItemInst->id) + L" with insufficient ingredients");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pTempItemInst->onCraftedBy(player->level, dynamic_pointer_cast<Player>( player->shared_from_this() ), pTempItemInst->count );
|
||||
|
||||
// and remove those resources from your inventory
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "..\Minecraft.World\ArrayWithLength.h"
|
||||
#include "..\Minecraft.World\net.minecraft.network.packet.h"
|
||||
#include "..\Minecraft.World\net.minecraft.network.h"
|
||||
#include "Windows64\Windows64_Xuid.h"
|
||||
#include "..\Minecraft.World\Pos.h"
|
||||
#include "..\Minecraft.World\ProgressListener.h"
|
||||
#include "..\Minecraft.World\HellRandomLevelSource.h"
|
||||
|
|
@ -106,11 +107,18 @@ void PlayerList::placeNewPlayer(Connection *connection, shared_ptr<ServerPlayer>
|
|||
}
|
||||
#endif
|
||||
#ifdef _WINDOWS64
|
||||
if (networkPlayer != NULL && !networkPlayer->IsLocal())
|
||||
if (networkPlayer != NULL)
|
||||
{
|
||||
NetworkPlayerXbox* nxp = (NetworkPlayerXbox*)networkPlayer;
|
||||
IQNetPlayer* qnp = nxp->GetQNetPlayer();
|
||||
wcsncpy_s(qnp->m_gamertag, 32, player->name.c_str(), _TRUNCATE);
|
||||
if (qnp != NULL)
|
||||
{
|
||||
if (!networkPlayer->IsLocal())
|
||||
{
|
||||
wcsncpy_s(qnp->m_gamertag, 32, player->name.c_str(), _TRUNCATE);
|
||||
}
|
||||
qnp->m_resolvedXuid = player->getXuid();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// 4J Stu - TU-1 hotfix
|
||||
|
|
@ -520,12 +528,20 @@ shared_ptr<ServerPlayer> PlayerList::getPlayerForLogin(PendingConnection *pendin
|
|||
player->setOnlineXuid( onlineXuid ); // 4J Added
|
||||
#ifdef _WINDOWS64
|
||||
{
|
||||
// Use packet-supplied identity from LoginPacket.
|
||||
// Do not recompute from name here: mixed-version clients must stay compatible.
|
||||
INetworkPlayer* np = pendingConnection->connection->getSocket()->getPlayer();
|
||||
if (np != NULL)
|
||||
{
|
||||
PlayerUID realXuid = np->GetUID();
|
||||
player->setXuid(realXuid);
|
||||
player->setOnlineXuid(realXuid);
|
||||
player->setOnlineXuid(np->GetUID());
|
||||
|
||||
// Backward compatibility: when Minecraft.Client is hosting, keep the first
|
||||
// host player on the legacy embedded host XUID (base + 0).
|
||||
// This preserves pre-migration host playerdata in existing worlds.
|
||||
if (np->IsHost())
|
||||
{
|
||||
player->setXuid(Win64Xuid::GetLegacyEmbeddedHostXuid());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "..\..\Minecraft.World\OldChunkStorage.h"
|
||||
#include "Common/PostProcesser.h"
|
||||
#include "Network\WinsockNetLayer.h"
|
||||
#include "Windows64_Xuid.h"
|
||||
|
||||
#include "Xbox/resource.h"
|
||||
|
||||
|
|
@ -110,6 +111,7 @@ struct Win64LaunchOptions
|
|||
{
|
||||
int screenMode;
|
||||
bool serverMode;
|
||||
bool fullscreen;
|
||||
};
|
||||
|
||||
static void CopyWideArgToAnsi(LPCWSTR source, char* dest, size_t destSize)
|
||||
|
|
@ -256,6 +258,8 @@ static Win64LaunchOptions ParseLaunchOptions()
|
|||
g_Win64MultiplayerPort = (int)port;
|
||||
}
|
||||
}
|
||||
else if (_wcsicmp(argv[i], L"-fullscreen") == 0)
|
||||
options.fullscreen = true;
|
||||
}
|
||||
|
||||
LocalFree(argv);
|
||||
|
|
@ -1218,6 +1222,12 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
|
|||
Win64LaunchOptions launchOptions = ParseLaunchOptions();
|
||||
ApplyScreenMode(launchOptions.screenMode);
|
||||
|
||||
// Ensure uid.dat exists from startup in client mode (before any multiplayer/login path).
|
||||
if (!launchOptions.serverMode)
|
||||
{
|
||||
Win64Xuid::ResolvePersistentXuid();
|
||||
}
|
||||
|
||||
// If no username, let's fall back
|
||||
if (g_Win64Username[0] == 0)
|
||||
{
|
||||
|
|
@ -1245,7 +1255,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
|
|||
}
|
||||
|
||||
// Restore fullscreen state from previous session
|
||||
if (LoadFullscreenOption() && !g_isFullscreen)
|
||||
if (LoadFullscreenOption() && !g_isFullscreen || launchOptions.fullscreen)
|
||||
{
|
||||
ToggleFullscreen();
|
||||
}
|
||||
|
|
|
|||
214
Minecraft.Client/Windows64/Windows64_Xuid.h
Normal file
214
Minecraft.Client/Windows64/Windows64_Xuid.h
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <Windows.h>
|
||||
|
||||
namespace Win64Xuid
|
||||
{
|
||||
inline PlayerUID GetLegacyEmbeddedBaseXuid()
|
||||
{
|
||||
return (PlayerUID)0xe000d45248242f2eULL;
|
||||
}
|
||||
|
||||
inline PlayerUID GetLegacyEmbeddedHostXuid()
|
||||
{
|
||||
// Legacy behavior used "embedded base + smallId"; host was always smallId 0.
|
||||
// We intentionally keep this value for host/self compatibility with pre-migration worlds.
|
||||
return GetLegacyEmbeddedBaseXuid();
|
||||
}
|
||||
|
||||
inline bool IsLegacyEmbeddedRange(PlayerUID xuid)
|
||||
{
|
||||
// Old Win64 XUIDs were not persistent and always lived in this narrow base+smallId range.
|
||||
// Treat them as legacy/non-persistent so uid.dat values never collide with old slot IDs.
|
||||
const PlayerUID base = GetLegacyEmbeddedBaseXuid();
|
||||
return xuid >= base && xuid < (base + MINECRAFT_NET_MAX_PLAYERS);
|
||||
}
|
||||
|
||||
inline bool IsPersistedUidValid(PlayerUID xuid)
|
||||
{
|
||||
return xuid != INVALID_XUID && !IsLegacyEmbeddedRange(xuid);
|
||||
}
|
||||
|
||||
|
||||
// ./uid.dat
|
||||
inline bool BuildUidFilePath(char* outPath, size_t outPathSize)
|
||||
{
|
||||
if (outPath == NULL || outPathSize == 0)
|
||||
return false;
|
||||
|
||||
outPath[0] = 0;
|
||||
|
||||
char exePath[MAX_PATH] = {};
|
||||
DWORD len = GetModuleFileNameA(NULL, exePath, MAX_PATH);
|
||||
if (len == 0 || len >= MAX_PATH)
|
||||
return false;
|
||||
|
||||
char* lastSlash = strrchr(exePath, '\\');
|
||||
if (lastSlash != NULL)
|
||||
{
|
||||
*(lastSlash + 1) = 0;
|
||||
}
|
||||
|
||||
if (strcpy_s(outPath, outPathSize, exePath) != 0)
|
||||
return false;
|
||||
if (strcat_s(outPath, outPathSize, "uid.dat") != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool ReadUid(PlayerUID* outXuid)
|
||||
{
|
||||
if (outXuid == NULL)
|
||||
return false;
|
||||
|
||||
char path[MAX_PATH] = {};
|
||||
if (!BuildUidFilePath(path, MAX_PATH))
|
||||
return false;
|
||||
|
||||
FILE* f = NULL;
|
||||
if (fopen_s(&f, path, "rb") != 0 || f == NULL)
|
||||
return false;
|
||||
|
||||
char buffer[128] = {};
|
||||
size_t readBytes = fread(buffer, 1, sizeof(buffer) - 1, f);
|
||||
fclose(f);
|
||||
|
||||
if (readBytes == 0)
|
||||
return false;
|
||||
|
||||
// Compatibility: earlier experiments may have written raw 8-byte uid.dat.
|
||||
if (readBytes == sizeof(unsigned __int64))
|
||||
{
|
||||
unsigned __int64 raw = 0;
|
||||
memcpy(&raw, buffer, sizeof(raw));
|
||||
PlayerUID parsed = (PlayerUID)raw;
|
||||
if (IsPersistedUidValid(parsed))
|
||||
{
|
||||
*outXuid = parsed;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
buffer[readBytes] = 0;
|
||||
char* begin = buffer;
|
||||
while (*begin == ' ' || *begin == '\t' || *begin == '\r' || *begin == '\n')
|
||||
{
|
||||
++begin;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
char* end = NULL;
|
||||
unsigned __int64 raw = _strtoui64(begin, &end, 0);
|
||||
if (begin == end || errno != 0)
|
||||
return false;
|
||||
|
||||
while (*end == ' ' || *end == '\t' || *end == '\r' || *end == '\n')
|
||||
{
|
||||
++end;
|
||||
}
|
||||
if (*end != 0)
|
||||
return false;
|
||||
|
||||
PlayerUID parsed = (PlayerUID)raw;
|
||||
if (!IsPersistedUidValid(parsed))
|
||||
return false;
|
||||
|
||||
*outXuid = parsed;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool WriteUid(PlayerUID xuid)
|
||||
{
|
||||
char path[MAX_PATH] = {};
|
||||
if (!BuildUidFilePath(path, MAX_PATH))
|
||||
return false;
|
||||
|
||||
FILE* f = NULL;
|
||||
if (fopen_s(&f, path, "wb") != 0 || f == NULL)
|
||||
return false;
|
||||
|
||||
int written = fprintf_s(f, "0x%016llX\n", (unsigned long long)xuid);
|
||||
fclose(f);
|
||||
return written > 0;
|
||||
}
|
||||
|
||||
inline unsigned __int64 Mix64(unsigned __int64 x)
|
||||
{
|
||||
x += 0x9E3779B97F4A7C15ULL;
|
||||
x = (x ^ (x >> 30)) * 0xBF58476D1CE4E5B9ULL;
|
||||
x = (x ^ (x >> 27)) * 0x94D049BB133111EBULL;
|
||||
return x ^ (x >> 31);
|
||||
}
|
||||
|
||||
inline PlayerUID GeneratePersistentUid()
|
||||
{
|
||||
// Avoid rand_s dependency: mix several Win64 runtime values into a 64-bit seed.
|
||||
FILETIME ft = {};
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
unsigned __int64 t = (((unsigned __int64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
|
||||
|
||||
LARGE_INTEGER qpc = {};
|
||||
QueryPerformanceCounter(&qpc);
|
||||
|
||||
unsigned __int64 seed = t;
|
||||
seed ^= (unsigned __int64)qpc.QuadPart;
|
||||
seed ^= ((unsigned __int64)GetCurrentProcessId() << 32);
|
||||
seed ^= (unsigned __int64)GetCurrentThreadId();
|
||||
seed ^= (unsigned __int64)GetTickCount();
|
||||
seed ^= (unsigned __int64)(size_t)&qpc;
|
||||
seed ^= (unsigned __int64)(size_t)GetModuleHandleA(NULL);
|
||||
|
||||
unsigned __int64 raw = Mix64(seed) ^ Mix64(seed + 0xA0761D6478BD642FULL);
|
||||
raw ^= 0x8F4B2D6C1A93E705ULL;
|
||||
raw |= 0x8000000000000000ULL;
|
||||
|
||||
PlayerUID xuid = (PlayerUID)raw;
|
||||
if (!IsPersistedUidValid(xuid))
|
||||
{
|
||||
raw ^= 0x0100000000000001ULL;
|
||||
xuid = (PlayerUID)raw;
|
||||
}
|
||||
|
||||
if (!IsPersistedUidValid(xuid))
|
||||
{
|
||||
// Last-resort deterministic fallback for pathological cases.
|
||||
xuid = (PlayerUID)0xD15EA5E000000001ULL;
|
||||
}
|
||||
|
||||
return xuid;
|
||||
}
|
||||
|
||||
inline PlayerUID ResolvePersistentXuid()
|
||||
{
|
||||
// Process-local cache: uid.dat is immutable during runtime and this path is hot.
|
||||
static bool s_cached = false;
|
||||
static PlayerUID s_xuid = INVALID_XUID;
|
||||
|
||||
if (s_cached)
|
||||
return s_xuid;
|
||||
|
||||
PlayerUID fileXuid = INVALID_XUID;
|
||||
if (ReadUid(&fileXuid))
|
||||
{
|
||||
s_xuid = fileXuid;
|
||||
s_cached = true;
|
||||
return s_xuid;
|
||||
}
|
||||
|
||||
// First launch on this client: generate once and persist to uid.dat.
|
||||
s_xuid = GeneratePersistentUid();
|
||||
WriteUid(s_xuid);
|
||||
s_cached = true;
|
||||
return s_xuid;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue