splitscreen fix (LAN and Discord Game Invites) also have support for it!

This commit is contained in:
LazyByteDev
2026-03-06 03:36:32 -05:00
parent c5e3e62f67
commit 150efcb90b
3 changed files with 63 additions and 19 deletions

View File

@@ -293,8 +293,32 @@ int CPlatformNetworkManagerStub::GetLocalPlayerMask(int playerIndex)
bool CPlatformNetworkManagerStub::AddLocalPlayerByUserIndex( int userIndex )
{
NotifyPlayerJoined(m_pIQNet->GetLocalPlayerByUserIndex(userIndex));
return ( m_pIQNet->AddLocalPlayerByUserIndex(userIndex) == S_OK );
#ifdef _WINDOWS64
if (userIndex > 0 && m_pIQNet->GetState() == QNET_STATE_GAME_PLAY)
{
// Assign splitscreen pads from the TOP of the m_player array downward.
// WinsockNetLayer assigns remote client smallIds upward from 1, so
// using the top slots avoids the collision that causes the LAN client
// to receive the splitscreen player's packets as its own.
BYTE splitSmallId = (BYTE)(MINECRAFT_NET_MAX_PLAYERS - userIndex);
IQNetPlayer *qp = &IQNet::m_player[splitSmallId];
qp->m_smallId = splitSmallId;
qp->m_userIndex = userIndex; // preserve the real pad index for GetUserIndex()
qp->m_isRemote = false;
qp->m_isHostPlayer = false;
wchar_t name[32];
swprintf_s(name, 32, L"%S", ProfileManager.GetGamertag(userIndex));
wcsncpy_s(qp->m_gamertag, 32, name, _TRUNCATE);
if (splitSmallId >= IQNet::s_playerCount)
IQNet::s_playerCount = splitSmallId + 1;
NotifyPlayerJoined(qp);
return ( m_pIQNet->AddLocalPlayerByUserIndex(userIndex) == S_OK );
}
#endif
NotifyPlayerJoined(m_pIQNet->GetLocalPlayerByUserIndex(userIndex));
return ( m_pIQNet->AddLocalPlayerByUserIndex(userIndex) == S_OK );
}
bool CPlatformNetworkManagerStub::RemoveLocalPlayerByUserIndex( int userIndex )

View File

@@ -70,6 +70,8 @@ HRESULT ATG::XMLParser::ParseXMLBuffer( CONST CHAR* strBuffer, UINT uBufferSi
VOID ATG::XMLParser::RegisterSAXCallbackInterface( ISAXCallback *pISAXCallback ) {}
#endif
int m_userIndex = -1; // FOR SPLITSCREEN BULLSHIT
#ifdef _WINDOWS64
static char s_discordUsername[32] = "";
static ULONGLONG s_discordXuid = 0;
@@ -463,7 +465,11 @@ bool IQNetPlayer::IsTalking() { return false; }
bool IQNetPlayer::IsMutedByLocalUser(DWORD dwUserIndex) { return false; }
bool IQNetPlayer::HasVoice() { return false; }
bool IQNetPlayer::HasCamera() { return false; }
int IQNetPlayer::GetUserIndex() { return this - &IQNet::m_player[0]; }
int IQNetPlayer::GetUserIndex()
{
if (m_userIndex >= 0) return m_userIndex;
return (int)(this - &IQNet::m_player[0]);
}
void IQNetPlayer::SetCustomDataValue(ULONG_PTR ulpCustomDataValue) {
m_customData = ulpCustomDataValue;
}
@@ -567,6 +573,7 @@ void IQNet::ClientJoinGame()
m_player[i].m_isRemote = true;
m_player[i].m_isHostPlayer = false;
m_player[i].m_gamertag[0] = 0;
m_player[i].m_userIndex = -1;
m_player[i].SetCustomDataValue(0);
}
}
@@ -581,6 +588,7 @@ void IQNet::EndGame()
m_player[i].m_isRemote = false;
m_player[i].m_isHostPlayer = false;
m_player[i].m_gamertag[0] = 0;
m_player[i].m_userIndex = -1;
m_player[i].SetCustomDataValue(0);
}
}
@@ -827,7 +835,7 @@ void C_4JProfile::SetTrialTextStringTable(CXuiStringTable *pStringTable,int i
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 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; }
@@ -835,24 +843,35 @@ UINT C_4JProfile::DisplayOfflineProfile(int( *Func)(LPVOID,const bool, const
UINT C_4JProfile::RequestConvertOfflineToGuestUI(int( *Func)(LPVOID,const bool, const int iPad),LPVOID lpParam,int iQuadrant) { return 0; }
void C_4JProfile::SetPrimaryPlayerChanged(bool bVal) {}
bool C_4JProfile::QuerySigninStatus(void) { return true; }
void C_4JProfile::GetXUID(int iPad, PlayerUID *pXuid,bool bOnlineXuid)
void C_4JProfile::GetXUID(int iPad, PlayerUID *pXuid, bool bOnlineXuid)
{
if(pXuid == NULL)
{
return;
}
if(pXuid == NULL) return;
#ifdef _WINDOWS64
if (iPad != 0)
{
*pXuid = INVALID_XUID;
return;
}
if (IQNet::s_isHosting)
*pXuid = 0xe000d45248242f2e;
else
*pXuid = 0xe000d45248242f2e + WinsockNetLayer::GetLocalSmallId();
if (iPad == 0)
{
if (IQNet::s_isHosting)
*pXuid = 0xe000d45248242f2e;
else
*pXuid = 0xe000d45248242f2e + WinsockNetLayer::GetLocalSmallId();
return;
}
// Splitscreen pads (1-3): generate a random XUID once and cache it.
// Using a random value avoids any collision with LAN players whose
// XUIDs are derived from small IDs or process IDs.
static PlayerUID s_splitscreenXuids[XUSER_MAX_COUNT] = {0};
if (s_splitscreenXuids[iPad] == 0)
{
// Use two rand() calls to fill 64 bits, seeded uniquely per pad
srand((unsigned int)(GetTickCount() ^ (iPad * 0x9e3779b9)));
s_splitscreenXuids[iPad] = 0xE100000000000000ULL
| ((PlayerUID)(unsigned int)rand() << 32)
| ((PlayerUID)(unsigned int)rand());
}
*pXuid = s_splitscreenXuids[iPad];
#else
*pXuid = 0xe000d45248242f2e + iPad;
*pXuid = 0xe000d45248242f2e + iPad;
#endif
}
BOOL C_4JProfile::AreXUIDSEqual(PlayerUID xuid1,PlayerUID xuid2) { return xuid1 == xuid2; }

View File

@@ -220,6 +220,7 @@ public:
bool m_isRemote;
bool m_isHostPlayer;
wchar_t m_gamertag[32];
int m_userIndex;
private:
ULONG_PTR m_customData;
};