diff options
| author | qwasdrizzel <145519042+qwasdrizzel@users.noreply.github.com> | 2026-03-16 21:44:26 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-16 21:44:26 -0500 |
| commit | ce739f6045ec72127491286ea3f3f21e537c1b55 (patch) | |
| tree | f33bd42a47c1b4a7b2153a7fb77127ee3b407db9 /Minecraft.Client/Extrax64Stubs.cpp | |
| parent | 255a18fe8e9b57377975f82e2b227afe2a12eda0 (diff) | |
| parent | 5a59f5d146b43811dde6a5a0245ee9875d7b5cd1 (diff) | |
Merge branch 'smartcmd:main' into main
Diffstat (limited to 'Minecraft.Client/Extrax64Stubs.cpp')
| -rw-r--r-- | Minecraft.Client/Extrax64Stubs.cpp | 162 |
1 files changed, 119 insertions, 43 deletions
diff --git a/Minecraft.Client/Extrax64Stubs.cpp b/Minecraft.Client/Extrax64Stubs.cpp index 29865e40..0147896c 100644 --- a/Minecraft.Client/Extrax64Stubs.cpp +++ b/Minecraft.Client/Extrax64Stubs.cpp @@ -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" @@ -57,7 +58,7 @@ bool CSocialManager::IsTitleAllowedToPostImages() { return false; } bool CSocialManager::PostLinkToSocialNetwork(ESocialNetwork eSocialNetwork, DWORD dwUserIndex, bool bUsingKinect) { return false; } bool CSocialManager::PostImageToSocialNetwork(ESocialNetwork eSocialNetwork, DWORD dwUserIndex, bool bUsingKinect) { return false; } -CSocialManager* CSocialManager::Instance() { return NULL; } +CSocialManager* CSocialManager::Instance() { return nullptr; } void CSocialManager::SetSocialPostText(LPCWSTR Title, LPCWSTR Caption, LPCWSTR Desc) {}; DWORD XShowPartyUI(DWORD dwUserIndex) { return 0; } @@ -67,11 +68,11 @@ DWORD XContentGetThumbnail(DWORD dwUserIndex, const XCONTENT_DATA* pContentData, void XShowAchievementsUI(int i) {} DWORD XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE Mode) { return 0; } -#ifndef _DURANGO -void PIXAddNamedCounter(int a, char* b, ...) {} +#if !defined(_DURANGO) && !defined(_WIN64) +void PIXAddNamedCounter(int a, const char* b, ...) {} //#define PS3_USE_PIX_EVENTS //#define PS4_USE_PIX_EVENTS -void PIXBeginNamedEvent(int a, char* b, ...) +void PIXBeginNamedEvent(int a, const char* b, ...) { #ifdef PS4_USE_PIX_EVENTS char buf[512]; @@ -124,8 +125,10 @@ void PIXEndNamedEvent() PixDepth -= 1; #endif } -void PIXSetMarkerDeprecated(int a, char* b, ...) {} -#else +void PIXSetMarkerDeprecated(int a, const char* b, ...) {} +#endif + +#if 0//__PSVITA__ // 4J Stu - Removed this implementation in favour of a macro that will convert our string format // conversion at compile time rather than at runtime //void PIXBeginNamedEvent(int a, char *b, ...) @@ -158,7 +161,7 @@ void PIXSetMarkerDeprecated(int a, char* b, ...) {} //} #endif -// void *D3DXBUFFER::GetBufferPointer() { return NULL; } +// void *D3DXBUFFER::GetBufferPointer() { return nullptr; } // int D3DXBUFFER::GetBufferSize() { return 0; } // void D3DXBUFFER::Release() {} @@ -191,7 +194,16 @@ void IQNetPlayer::SendData(IQNetPlayer * player, const void* pvData, DWORD dwDat { if (WinsockNetLayer::IsActive()) { - WinsockNetLayer::SendToSmallId(player->m_smallId, pvData, dwDataSize); + if (!WinsockNetLayer::IsHosting() && !m_isRemote) + { + SOCKET sock = WinsockNetLayer::GetLocalSocket(m_smallId); + if (sock != INVALID_SOCKET) + WinsockNetLayer::SendOnSocket(sock, pvData, dwDataSize); + } + else + { + WinsockNetLayer::SendToSmallId(player->m_smallId, pvData, dwDataSize); + } } } bool IQNetPlayer::IsSameSystem(IQNetPlayer * player) { return (this == player) || (!m_isRemote && !player->m_isRemote); } @@ -200,7 +212,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 +246,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; @@ -233,7 +254,20 @@ void Win64_SetupRemoteQNetPlayer(IQNetPlayer * player, BYTE smallId, bool isHost static bool Win64_IsActivePlayer(IQNetPlayer* p, DWORD index); -HRESULT IQNet::AddLocalPlayerByUserIndex(DWORD dwUserIndex) { return S_OK; } +HRESULT IQNet::AddLocalPlayerByUserIndex(DWORD dwUserIndex) { + if (dwUserIndex >= MINECRAFT_NET_MAX_PLAYERS) return E_FAIL; + m_player[dwUserIndex].m_isRemote = false; + m_player[dwUserIndex].m_isHostPlayer = false; + // Give the joining player a distinct gamertag + extern wchar_t g_Win64UsernameW[17]; + if (dwUserIndex == 0) + wcscpy_s(m_player[0].m_gamertag, 32, g_Win64UsernameW); + else + swprintf_s(m_player[dwUserIndex].m_gamertag, 32, L"%s(%d)", g_Win64UsernameW, dwUserIndex + 1); + if (dwUserIndex >= s_playerCount) + s_playerCount = dwUserIndex + 1; + return S_OK; +} IQNetPlayer* IQNet::GetHostPlayer() { return &m_player[0]; } IQNetPlayer* IQNet::GetLocalPlayerByUserIndex(DWORD dwUserIndex) { @@ -243,16 +277,34 @@ IQNetPlayer* IQNet::GetLocalPlayerByUserIndex(DWORD dwUserIndex) !m_player[dwUserIndex].m_isRemote && Win64_IsActivePlayer(&m_player[dwUserIndex], dwUserIndex)) return &m_player[dwUserIndex]; - return NULL; + return nullptr; } - if (dwUserIndex != 0) - return NULL; - for (DWORD i = 0; i < s_playerCount; i++) + if (dwUserIndex == 0) { - if (!m_player[i].m_isRemote && Win64_IsActivePlayer(&m_player[i], i)) - return &m_player[i]; + // Primary pad: use direct index when networking is active (smallId may not be 0) + if (WinsockNetLayer::IsActive()) + { + DWORD idx = WinsockNetLayer::GetLocalSmallId(); + if (idx < MINECRAFT_NET_MAX_PLAYERS && + !m_player[idx].m_isRemote && + Win64_IsActivePlayer(&m_player[idx], idx)) + return &m_player[idx]; + return nullptr; + } + // Offline: scan for first local player + for (DWORD i = 0; i < s_playerCount; i++) + { + if (!m_player[i].m_isRemote && Win64_IsActivePlayer(&m_player[i], i)) + return &m_player[i]; + } + return nullptr; } - return NULL; + // Split-screen pads 1-3: the player is at m_player[dwUserIndex] with isRemote=false + if (dwUserIndex < MINECRAFT_NET_MAX_PLAYERS && + !m_player[dwUserIndex].m_isRemote && + Win64_IsActivePlayer(&m_player[dwUserIndex], dwUserIndex)) + return &m_player[dwUserIndex]; + return nullptr; } static bool Win64_IsActivePlayer(IQNetPlayer * p, DWORD index) { @@ -279,14 +331,19 @@ IQNetPlayer* IQNet::GetPlayerBySmallId(BYTE SmallId) { if (m_player[i].m_smallId == SmallId && Win64_IsActivePlayer(&m_player[i], i)) return &m_player[i]; } - return NULL; + return nullptr; } 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 nullptr on miss. return &m_player[0]; } DWORD IQNet::GetPlayerCount() @@ -301,7 +358,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; @@ -309,9 +372,10 @@ void IQNet::ClientJoinGame() for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++) { - m_player[i].m_smallId = (BYTE)i; + m_player[i].m_smallId = static_cast<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); } @@ -323,9 +387,10 @@ void IQNet::EndGame() s_playerCount = 1; for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++) { - m_player[i].m_smallId = (BYTE)i; + m_player[i].m_smallId = static_cast<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); } @@ -430,11 +495,11 @@ HRESULT XMemCreateCompressionContext( ) { /* - COMPRESSOR_HANDLE Compressor = NULL; + COMPRESSOR_HANDLE Compressor = nullptr; HRESULT hr = CreateCompressor( COMPRESS_ALGORITHM_XPRESS_HUFF, // Compression Algorithm - NULL, // Optional allocation routine + nullptr, // Optional allocation routine &Compressor); // Handle pContext = (XMEMDECOMPRESSION_CONTEXT *)Compressor; @@ -451,11 +516,11 @@ HRESULT XMemCreateDecompressionContext( ) { /* - DECOMPRESSOR_HANDLE Decompressor = NULL; + DECOMPRESSOR_HANDLE Decompressor = nullptr; HRESULT hr = CreateDecompressor( COMPRESS_ALGORITHM_XPRESS_HUFF, // Compression Algorithm - NULL, // Optional allocation routine + nullptr, // Optional allocation routine &Decompressor); // Handle pContext = (XMEMDECOMPRESSION_CONTEXT *)Decompressor; @@ -505,7 +570,7 @@ void C_4JProfile::Initialise(DWORD dwTitleID, ZeroMemory(profileData[i], sizeof(byte) * iGameDefinedDataSizeX4 / 4); // Set some sane initial values! - GAME_SETTINGS* pGameSettings = (GAME_SETTINGS*)profileData[i]; + GAME_SETTINGS* pGameSettings = static_cast<GAME_SETTINGS *>(profileData[i]); pGameSettings->ucMenuSensitivity = 100; //eGameSetting_Sensitivity_InMenu pGameSettings->ucInterfaceOpacity = 80; //eGameSetting_Sensitivity_InMenu pGameSettings->usBitmaskValues |= 0x0200; //eGameSetting_DisplaySplitscreenGamertags - on @@ -559,7 +624,7 @@ void C_4JProfile::SetTrialTextStringTable(CXuiStringTable * pStringTable, int void C_4JProfile::SetTrialAwardText(eAwardType AwardType, int iTitle, int iText) {} int C_4JProfile::GetLockedProfile() { return 0; } void C_4JProfile::SetLockedProfile(int iProf) {} -bool C_4JProfile::IsSignedIn(int iQuadrant) { return (iQuadrant == 0); } +bool C_4JProfile::IsSignedIn(int iQuadrant) { return (iQuadrant == 0) || InputManager.IsPadConnected(iQuadrant); } bool C_4JProfile::IsSignedInLive(int iProf) { return true; } bool C_4JProfile::IsGuest(int iQuadrant) { return false; } UINT C_4JProfile::RequestSignInUI(bool bFromInvite, bool bLocalGame, bool bNoGuestsAllowed, bool bMultiplayerSignIn, bool bAddUser, int(*Func)(LPVOID, const bool, const int iPad), LPVOID lpParam, int iQuadrant) { return 0; } @@ -570,15 +635,10 @@ bool C_4JProfile::QuerySigninStatus(void) { return true; } void C_4JProfile::GetXUID(int iPad, PlayerUID * pXuid, bool bOnlineXuid) { #ifdef _WINDOWS64 - if (iPad != 0) - { - *pXuid = INVALID_XUID; - return; - } - if (IQNet::s_isHosting) - *pXuid = 0xe000d45248242f2e; - else - *pXuid = 0xe000d45248242f2e + WinsockNetLayer::GetLocalSmallId(); + // Each pad gets a unique XUID derived from the persistent uid.dat value. + // Pad 0 uses the base XUID directly. Pads 1-3 get a deterministic hash + // of (base + pad) to produce fully independent IDs with no overlap risk. + *pXuid = Win64Xuid::DeriveXuidForPad(Win64Xuid::ResolvePersistentXuid(), iPad); #else * pXuid = 0xe000d45248242f2e + iPad; #endif @@ -608,8 +668,24 @@ void C_4JProfile::SetPrimaryPad(int iPad) {} char fakeGamerTag[32] = "PlayerName"; void SetFakeGamertag(char* name) { strcpy_s(fakeGamerTag, name); } #else -char* C_4JProfile::GetGamertag(int iPad) { extern char g_Win64Username[17]; return g_Win64Username; } -wstring C_4JProfile::GetDisplayName(int iPad) { extern wchar_t g_Win64UsernameW[17]; return g_Win64UsernameW; } +char* C_4JProfile::GetGamertag(int iPad) { + extern char g_Win64Username[17]; + if (iPad > 0 && iPad < XUSER_MAX_COUNT && IQNet::m_player[iPad].m_gamertag[0] != 0 && + !IQNet::m_player[iPad].m_isRemote) + { + static char s_padGamertag[XUSER_MAX_COUNT][17]; + WideCharToMultiByte(CP_ACP, 0, IQNet::m_player[iPad].m_gamertag, -1, s_padGamertag[iPad], 17, nullptr, nullptr); + return s_padGamertag[iPad]; + } + return g_Win64Username; +} +wstring C_4JProfile::GetDisplayName(int iPad) { + extern wchar_t g_Win64UsernameW[17]; + if (iPad > 0 && iPad < XUSER_MAX_COUNT && IQNet::m_player[iPad].m_gamertag[0] != 0 && + !IQNet::m_player[iPad].m_isRemote) + return IQNet::m_player[iPad].m_gamertag; + return g_Win64UsernameW; +} #endif bool C_4JProfile::IsFullVersion() { return s_bProfileIsFullVersion; } void C_4JProfile::SetSignInChangeCallback(void (*Func)(LPVOID, bool, unsigned int), LPVOID lpParam) {} @@ -619,8 +695,8 @@ bool C_4JProfile::LocaleIsUSorCanada(void) { return false; } HRESULT C_4JProfile::GetLiveConnectionStatus() { return S_OK; } bool C_4JProfile::IsSystemUIDisplayed() { return false; } void C_4JProfile::SetProfileReadErrorCallback(void (*Func)(LPVOID), LPVOID lpParam) {} -int(*defaultOptionsCallback)(LPVOID, C_4JProfile::PROFILESETTINGS*, const int iPad) = NULL; -LPVOID lpProfileParam = NULL; +int(*defaultOptionsCallback)(LPVOID, C_4JProfile::PROFILESETTINGS*, const int iPad) = nullptr; +LPVOID lpProfileParam = nullptr; int C_4JProfile::SetDefaultOptionsCallback(int(*Func)(LPVOID, PROFILESETTINGS*, const int iPad), LPVOID lpParam) { defaultOptionsCallback = Func; @@ -698,7 +774,7 @@ void C4JStorage::GetSaveCacheFileInfo(DWORD dwFile, XCONTENT_DATA & xCont void C4JStorage::GetSaveCacheFileInfo(DWORD dwFile, PBYTE * ppbImageData, DWORD * pdwImageBytes) {} C4JStorage::ESaveGameState C4JStorage::LoadSaveData(PSAVE_INFO pSaveInfo, int(*Func)(LPVOID lpParam, const bool, const bool), LPVOID lpParam) { return C4JStorage::ESaveGame_Idle; } C4JStorage::EDeleteGameStatus C4JStorage::DeleteSaveData(PSAVE_INFO pSaveInfo, int(*Func)(LPVOID lpParam, const bool), LPVOID lpParam) { return C4JStorage::EDeleteGame_Idle; } -PSAVE_DETAILS C4JStorage::ReturnSavesInfo() { return NULL; } +PSAVE_DETAILS C4JStorage::ReturnSavesInfo() { return nullptr; } void C4JStorage::RegisterMarketplaceCountsCallback(int (*Func)(LPVOID lpParam, C4JStorage::DLC_TMS_DETAILS*, int), LPVOID lpParam) {} void C4JStorage::SetDLCPackageRoot(char* pszDLCRoot) {} @@ -720,7 +796,7 @@ void C4JStorage::StoreTMSPathName(WCHAR * pwchName) {} unsigned int C4JStorage::CRC(unsigned char* buf, int len) { return 0; } struct PTMSPP_FILEDATA; -C4JStorage::ETMSStatus C4JStorage::TMSPP_ReadFile(int iPad, C4JStorage::eGlobalStorage eStorageFacility, C4JStorage::eTMS_FILETYPEVAL eFileTypeVal, LPCSTR szFilename, int(*Func)(LPVOID, int, int, PTMSPP_FILEDATA, LPCSTR)/*=NULL*/, LPVOID lpParam/*=NULL*/, int iUserData/*=0*/) { return C4JStorage::ETMSStatus_Idle; } +C4JStorage::ETMSStatus C4JStorage::TMSPP_ReadFile(int iPad, C4JStorage::eGlobalStorage eStorageFacility, C4JStorage::eTMS_FILETYPEVAL eFileTypeVal, LPCSTR szFilename, int(*Func)(LPVOID, int, int, PTMSPP_FILEDATA, LPCSTR)/*=nullptr*/, LPVOID lpParam/*=nullptr*/, int iUserData/*=0*/) { return C4JStorage::ETMSStatus_Idle; } #endif // _WINDOWS64 #endif // __PS3__ |
