Files
MinecraftConsoles/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp
2026-03-01 12:16:08 +08:00

647 lines
17 KiB
C++

#include "stdafx.h"
#include "..\..\..\Minecraft.World\Socket.h"
#include "..\..\..\Minecraft.World\StringHelpers.h"
#include "PlatformNetworkManagerStub.h"
#include "..\..\Xbox\Network\NetworkPlayerXbox.h" // TODO - stub version of this?
CPlatformNetworkManagerStub *g_pPlatformNetworkManager;
void CPlatformNetworkManagerStub::NotifyPlayerJoined(IQNetPlayer *pQNetPlayer )
{
const char * pszDescription;
// 4J Stu - We create a fake socket for every where that we need an INBOUND queue of game data. Outbound
// is all handled by QNet so we don't need that. Therefore each client player has one, and the host has one
// for each client player.
bool createFakeSocket = false;
bool localPlayer = false;
NetworkPlayerXbox *networkPlayer = (NetworkPlayerXbox *)addNetworkPlayer(pQNetPlayer);
if( pQNetPlayer->IsLocal() )
{
localPlayer = true;
if( pQNetPlayer->IsHost() )
{
pszDescription = "local host";
// 4J Stu - No socket for the localhost as it uses a special loopback queue
m_machineQNetPrimaryPlayers.push_back( pQNetPlayer );
}
else
{
pszDescription = "local";
// We need an inbound queue on all local players to receive data from the host
createFakeSocket = true;
}
}
else
{
if( pQNetPlayer->IsHost() )
{
pszDescription = "remote host";
}
else
{
pszDescription = "remote";
// If we are the host, then create a fake socket for every remote player
if( m_pIQNet->IsHost() )
{
createFakeSocket = true;
}
}
if( m_pIQNet->IsHost() && !m_bHostChanged )
{
// Do we already have a primary player for this system?
bool systemHasPrimaryPlayer = false;
for(AUTO_VAR(it, m_machineQNetPrimaryPlayers.begin()); it < m_machineQNetPrimaryPlayers.end(); ++it)
{
IQNetPlayer *pQNetPrimaryPlayer = *it;
if( pQNetPlayer->IsSameSystem(pQNetPrimaryPlayer) )
{
systemHasPrimaryPlayer = true;
break;
}
}
if( !systemHasPrimaryPlayer )
m_machineQNetPrimaryPlayers.push_back( pQNetPlayer );
}
}
g_NetworkManager.PlayerJoining( networkPlayer );
if( createFakeSocket == true && !m_bHostChanged )
{
g_NetworkManager.CreateSocket( networkPlayer, localPlayer );
}
app.DebugPrintf( "Player 0x%p \"%ls\" joined; %s; voice %i; camera %i.\n",
pQNetPlayer,
pQNetPlayer->GetGamertag(),
pszDescription,
(int) pQNetPlayer->HasVoice(),
(int) pQNetPlayer->HasCamera() );
if( m_pIQNet->IsHost() )
{
// 4J-PB - only the host should do this
// g_NetworkManager.UpdateAndSetGameSessionData();
SystemFlagAddPlayer( networkPlayer );
}
for( int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
{
if(playerChangedCallback[idx] != NULL)
playerChangedCallback[idx]( playerChangedCallbackParam[idx], networkPlayer, false );
}
if(m_pIQNet->GetState() == QNET_STATE_GAME_PLAY)
{
int localPlayerCount = 0;
for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
{
if( m_pIQNet->GetLocalPlayerByUserIndex(idx) != NULL ) ++localPlayerCount;
}
float appTime = app.getAppTime();
// Only record stats for the primary player here
m_lastPlayerEventTimeStart = appTime;
}
}
bool CPlatformNetworkManagerStub::Initialise(CGameNetworkManager *pGameNetworkManager, int flagIndexSize)
{
m_pGameNetworkManager = pGameNetworkManager;
m_flagIndexSize = flagIndexSize;
g_pPlatformNetworkManager = this;
for( int i = 0; i < XUSER_MAX_COUNT; i++ )
{
playerChangedCallback[ i ] = NULL;
}
m_bLeavingGame = false;
m_bLeaveGameOnTick = false;
m_bHostChanged = false;
m_bSearchResultsReady = false;
m_bSearchPending = false;
m_bIsOfflineGame = false;
m_pSearchParam = NULL;
m_SessionsUpdatedCallback = NULL;
for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
{
m_searchResultsCount[i] = 0;
m_lastSearchStartTime[i] = 0;
// The results that will be filled in with the current search
m_pSearchResults[i] = NULL;
m_pQoSResult[i] = NULL;
m_pCurrentSearchResults[i] = NULL;
m_pCurrentQoSResult[i] = NULL;
m_currentSearchResultsCount[i] = 0;
}
// Success!
return true;
}
void CPlatformNetworkManagerStub::Terminate()
{
}
int CPlatformNetworkManagerStub::GetJoiningReadyPercentage()
{
return 100;
}
int CPlatformNetworkManagerStub::CorrectErrorIDS(int IDS)
{
return IDS;
}
bool CPlatformNetworkManagerStub::isSystemPrimaryPlayer(IQNetPlayer *pQNetPlayer)
{
return true;
}
// We call this twice a frame, either side of the render call so is a good place to "tick" things
void CPlatformNetworkManagerStub::DoWork()
{
}
int CPlatformNetworkManagerStub::GetPlayerCount()
{
return m_pIQNet->GetPlayerCount();
}
bool CPlatformNetworkManagerStub::ShouldMessageForFullSession()
{
return false;
}
int CPlatformNetworkManagerStub::GetOnlinePlayerCount()
{
return 1;
}
int CPlatformNetworkManagerStub::GetLocalPlayerMask(int playerIndex)
{
return 1 << playerIndex;
}
bool CPlatformNetworkManagerStub::AddLocalPlayerByUserIndex( int userIndex )
{
NotifyPlayerJoined(m_pIQNet->GetLocalPlayerByUserIndex(userIndex));
return ( m_pIQNet->AddLocalPlayerByUserIndex(userIndex) == S_OK );
}
bool CPlatformNetworkManagerStub::RemoveLocalPlayerByUserIndex( int userIndex )
{
return true;
}
bool CPlatformNetworkManagerStub::IsInStatsEnabledSession()
{
return true;
}
bool CPlatformNetworkManagerStub::SessionHasSpace(unsigned int spaceRequired /*= 1*/)
{
return true;
}
void CPlatformNetworkManagerStub::SendInviteGUI(int quadrant)
{
}
bool CPlatformNetworkManagerStub::IsAddingPlayer()
{
return false;
}
bool CPlatformNetworkManagerStub::LeaveGame(bool bMigrateHost)
{
if( m_bLeavingGame ) return true;
m_bLeavingGame = true;
// If we are the host wait for the game server to end
if(m_pIQNet->IsHost() && g_NetworkManager.ServerStoppedValid())
{
m_pIQNet->EndGame();
g_NetworkManager.ServerStoppedWait();
g_NetworkManager.ServerStoppedDestroy();
}
return true;
}
bool CPlatformNetworkManagerStub::_LeaveGame(bool bMigrateHost, bool bLeaveRoom)
{
return true;
}
void CPlatformNetworkManagerStub::HostGame(int localUsersMask, bool bOnlineGame, bool bIsPrivate, unsigned char publicSlots /*= MINECRAFT_NET_MAX_PLAYERS*/, unsigned char privateSlots /*= 0*/)
{
// #ifdef _XBOX
// 4J Stu - We probably did this earlier as well, but just to be sure!
SetLocalGame( !bOnlineGame );
SetPrivateGame( bIsPrivate );
SystemFlagReset();
// Make sure that the Primary Pad is in by default
localUsersMask |= GetLocalPlayerMask( g_NetworkManager.GetPrimaryPad() );
m_bLeavingGame = false;
m_pIQNet->HostGame();
_HostGame( localUsersMask, publicSlots, privateSlots );
//#endif
}
void CPlatformNetworkManagerStub::_HostGame(int usersMask, unsigned char publicSlots /*= MINECRAFT_NET_MAX_PLAYERS*/, unsigned char privateSlots /*= 0*/)
{
}
bool CPlatformNetworkManagerStub::_StartGame()
{
return true;
}
int CPlatformNetworkManagerStub::JoinGame(FriendSessionInfo *searchResult, int localUsersMask, int primaryUserIndex)
{
return CGameNetworkManager::JOINGAME_SUCCESS;
}
bool CPlatformNetworkManagerStub::SetLocalGame(bool isLocal)
{
m_bIsOfflineGame = isLocal;
return true;
}
void CPlatformNetworkManagerStub::SetPrivateGame(bool isPrivate)
{
app.DebugPrintf("Setting as private game: %s\n", isPrivate ? "yes" : "no" );
m_bIsPrivateGame = isPrivate;
}
void CPlatformNetworkManagerStub::RegisterPlayerChangedCallback(int iPad, void (*callback)(void *callbackParam, INetworkPlayer *pPlayer, bool leaving), void *callbackParam)
{
playerChangedCallback[iPad] = callback;
playerChangedCallbackParam[iPad] = callbackParam;
}
void CPlatformNetworkManagerStub::UnRegisterPlayerChangedCallback(int iPad, void (*callback)(void *callbackParam, INetworkPlayer *pPlayer, bool leaving), void *callbackParam)
{
if(playerChangedCallbackParam[iPad] == callbackParam)
{
playerChangedCallback[iPad] = NULL;
playerChangedCallbackParam[iPad] = NULL;
}
}
void CPlatformNetworkManagerStub::HandleSignInChange()
{
return;
}
bool CPlatformNetworkManagerStub::_RunNetworkGame()
{
return true;
}
void CPlatformNetworkManagerStub::UpdateAndSetGameSessionData(INetworkPlayer *pNetworkPlayerLeaving /*= NULL*/)
{
// DWORD playerCount = m_pIQNet->GetPlayerCount();
//
// if( this->m_bLeavingGame )
// return;
//
// if( GetHostPlayer() == NULL )
// return;
//
// for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i)
// {
// if( i < playerCount )
// {
// INetworkPlayer *pNetworkPlayer = GetPlayerByIndex(i);
//
// // We can call this from NotifyPlayerLeaving but at that point the player is still considered in the session
// if( pNetworkPlayer != pNetworkPlayerLeaving )
// {
// m_hostGameSessionData.players[i] = ((NetworkPlayerXbox *)pNetworkPlayer)->GetUID();
//
// char *temp;
// temp = (char *)wstringtofilename( pNetworkPlayer->GetOnlineName() );
// memcpy(m_hostGameSessionData.szPlayers[i],temp,XUSER_NAME_SIZE);
// }
// else
// {
// m_hostGameSessionData.players[i] = NULL;
// memset(m_hostGameSessionData.szPlayers[i],0,XUSER_NAME_SIZE);
// }
// }
// else
// {
// m_hostGameSessionData.players[i] = NULL;
// memset(m_hostGameSessionData.szPlayers[i],0,XUSER_NAME_SIZE);
// }
// }
//
// m_hostGameSessionData.hostPlayerUID = ((NetworkPlayerXbox *)GetHostPlayer())->GetQNetPlayer()->GetXuid();
// m_hostGameSessionData.m_uiGameHostSettings = app.GetGameHostOption(eGameHostOption_All);
}
int CPlatformNetworkManagerStub::RemovePlayerOnSocketClosedThreadProc( void* lpParam )
{
INetworkPlayer *pNetworkPlayer = (INetworkPlayer *)lpParam;
Socket *socket = pNetworkPlayer->GetSocket();
if( socket != NULL )
{
//printf("Waiting for socket closed event\n");
socket->m_socketClosedEvent->WaitForSignal(INFINITE);
//printf("Socket closed event has fired\n");
// 4J Stu - Clear our reference to this socket
pNetworkPlayer->SetSocket( NULL );
delete socket;
}
return g_pPlatformNetworkManager->RemoveLocalPlayer( pNetworkPlayer );
}
bool CPlatformNetworkManagerStub::RemoveLocalPlayer( INetworkPlayer *pNetworkPlayer )
{
return true;
}
CPlatformNetworkManagerStub::PlayerFlags::PlayerFlags(INetworkPlayer *pNetworkPlayer, unsigned int count)
{
// 4J Stu - Don't assert, just make it a multiple of 8! This count is calculated from a load of separate values,
// and makes tweaking world/render sizes a pain if we hit an assert here
count = (count + 8 - 1) & ~(8 - 1);
//assert( ( count % 8 ) == 0 );
this->m_pNetworkPlayer = pNetworkPlayer;
this->flags = new unsigned char [ count / 8 ];
memset( this->flags, 0, count / 8 );
this->count = count;
}
CPlatformNetworkManagerStub::PlayerFlags::~PlayerFlags()
{
delete [] flags;
}
// Add a player to the per system flag storage - if we've already got a player from that system, copy its flags over
void CPlatformNetworkManagerStub::SystemFlagAddPlayer(INetworkPlayer *pNetworkPlayer)
{
PlayerFlags *newPlayerFlags = new PlayerFlags( pNetworkPlayer, m_flagIndexSize);
// If any of our existing players are on the same system, then copy over flags from that one
for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
{
if( pNetworkPlayer->IsSameSystem(m_playerFlags[i]->m_pNetworkPlayer) )
{
memcpy( newPlayerFlags->flags, m_playerFlags[i]->flags, m_playerFlags[i]->count / 8 );
break;
}
}
m_playerFlags.push_back(newPlayerFlags);
}
// Remove a player from the per system flag storage - just maintains the m_playerFlags vector without any gaps in it
void CPlatformNetworkManagerStub::SystemFlagRemovePlayer(INetworkPlayer *pNetworkPlayer)
{
for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
{
if( m_playerFlags[i]->m_pNetworkPlayer == pNetworkPlayer )
{
delete m_playerFlags[i];
m_playerFlags[i] = m_playerFlags.back();
m_playerFlags.pop_back();
return;
}
}
}
void CPlatformNetworkManagerStub::SystemFlagReset()
{
for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
{
delete m_playerFlags[i];
}
m_playerFlags.clear();
}
// Set a per system flag - this is done by setting the flag on every player that shares that system
void CPlatformNetworkManagerStub::SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index)
{
if( ( index < 0 ) || ( index >= m_flagIndexSize ) ) return;
if( pNetworkPlayer == NULL ) return;
for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
{
if( pNetworkPlayer->IsSameSystem(m_playerFlags[i]->m_pNetworkPlayer) )
{
m_playerFlags[i]->flags[ index / 8 ] |= ( 128 >> ( index % 8 ) );
}
}
}
// Get value of a per system flag - can be read from the flags of the passed in player as anything else sent to that
// system should also have been duplicated here
bool CPlatformNetworkManagerStub::SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index)
{
if( ( index < 0 ) || ( index >= m_flagIndexSize ) ) return false;
if( pNetworkPlayer == NULL )
{
return false;
}
for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
{
if( m_playerFlags[i]->m_pNetworkPlayer == pNetworkPlayer )
{
return ( ( m_playerFlags[i]->flags[ index / 8 ] & ( 128 >> ( index % 8 ) ) ) != 0 );
}
}
return false;
}
wstring CPlatformNetworkManagerStub::GatherStats()
{
return L"";
}
wstring CPlatformNetworkManagerStub::GatherRTTStats()
{
wstring stats(L"Rtt: ");
wchar_t stat[32];
for(unsigned int i = 0; i < GetPlayerCount(); ++i)
{
IQNetPlayer *pQNetPlayer = ((NetworkPlayerXbox *)GetPlayerByIndex( i ))->GetQNetPlayer();
if(!pQNetPlayer->IsLocal())
{
ZeroMemory(stat,32*sizeof(WCHAR));
swprintf(stat, 32, L"%d: %d/", i, pQNetPlayer->GetCurrentRtt() );
stats.append(stat);
}
}
return stats;
}
void CPlatformNetworkManagerStub::TickSearch()
{
}
void CPlatformNetworkManagerStub::SearchForGames()
{
}
int CPlatformNetworkManagerStub::SearchForGamesThreadProc( void* lpParameter )
{
return 0;
}
void CPlatformNetworkManagerStub::SetSearchResultsReady(int resultCount)
{
m_bSearchResultsReady = true;
m_searchResultsCount[m_lastSearchPad] = resultCount;
}
vector<FriendSessionInfo *> *CPlatformNetworkManagerStub::GetSessionList(int iPad, int localPlayers, bool partyOnly)
{
vector<FriendSessionInfo *> *filteredList = new vector<FriendSessionInfo *>();;
return filteredList;
}
bool CPlatformNetworkManagerStub::GetGameSessionInfo(int iPad, SessionID sessionId, FriendSessionInfo *foundSessionInfo)
{
return false;
}
void CPlatformNetworkManagerStub::SetSessionsUpdatedCallback( void (*SessionsUpdatedCallback)(LPVOID pParam), LPVOID pSearchParam )
{
m_SessionsUpdatedCallback = SessionsUpdatedCallback; m_pSearchParam = pSearchParam;
}
void CPlatformNetworkManagerStub::GetFullFriendSessionInfo( FriendSessionInfo *foundSession, void (* FriendSessionUpdatedFn)(bool success, void *pParam), void *pParam )
{
FriendSessionUpdatedFn(true, pParam);
}
void CPlatformNetworkManagerStub::ForceFriendsSessionRefresh()
{
app.DebugPrintf("Resetting friends session search data\n");
for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
{
m_searchResultsCount[i] = 0;
m_lastSearchStartTime[i] = 0;
delete m_pSearchResults[i];
m_pSearchResults[i] = NULL;
}
}
INetworkPlayer *CPlatformNetworkManagerStub::addNetworkPlayer(IQNetPlayer *pQNetPlayer)
{
NetworkPlayerXbox *pNetworkPlayer = new NetworkPlayerXbox(pQNetPlayer);
pQNetPlayer->SetCustomDataValue((ULONG_PTR)pNetworkPlayer);
currentNetworkPlayers.push_back( pNetworkPlayer );
return pNetworkPlayer;
}
void CPlatformNetworkManagerStub::removeNetworkPlayer(IQNetPlayer *pQNetPlayer)
{
INetworkPlayer *pNetworkPlayer = getNetworkPlayer(pQNetPlayer);
for( AUTO_VAR(it, currentNetworkPlayers.begin()); it != currentNetworkPlayers.end(); it++ )
{
if( *it == pNetworkPlayer )
{
currentNetworkPlayers.erase(it);
return;
}
}
}
INetworkPlayer *CPlatformNetworkManagerStub::getNetworkPlayer(IQNetPlayer *pQNetPlayer)
{
return pQNetPlayer ? (INetworkPlayer *)(pQNetPlayer->GetCustomDataValue()) : NULL;
}
INetworkPlayer *CPlatformNetworkManagerStub::GetLocalPlayerByUserIndex(int userIndex )
{
return getNetworkPlayer(m_pIQNet->GetLocalPlayerByUserIndex(userIndex));
}
INetworkPlayer *CPlatformNetworkManagerStub::GetPlayerByIndex(int playerIndex)
{
return getNetworkPlayer(m_pIQNet->GetPlayerByIndex(playerIndex));
}
INetworkPlayer * CPlatformNetworkManagerStub::GetPlayerByXuid(PlayerUID xuid)
{
return getNetworkPlayer( m_pIQNet->GetPlayerByXuid(xuid)) ;
}
INetworkPlayer * CPlatformNetworkManagerStub::GetPlayerBySmallId(unsigned char smallId)
{
return getNetworkPlayer(m_pIQNet->GetPlayerBySmallId(smallId));
}
INetworkPlayer *CPlatformNetworkManagerStub::GetHostPlayer()
{
return getNetworkPlayer(m_pIQNet->GetHostPlayer());
}
bool CPlatformNetworkManagerStub::IsHost()
{
return m_pIQNet->IsHost() && !m_bHostChanged;
}
bool CPlatformNetworkManagerStub::JoinGameFromInviteInfo( int userIndex, int userMask, const INVITE_INFO *pInviteInfo)
{
return ( m_pIQNet->JoinGameFromInviteInfo( userIndex, userMask, pInviteInfo ) == S_OK);
}
void CPlatformNetworkManagerStub::SetSessionTexturePackParentId( int id )
{
m_hostGameSessionData.texturePackParentId = id;
}
void CPlatformNetworkManagerStub::SetSessionSubTexturePackId( int id )
{
m_hostGameSessionData.subTexturePackId = id;
}
void CPlatformNetworkManagerStub::Notify(int ID, ULONG_PTR Param)
{
}
bool CPlatformNetworkManagerStub::IsInSession()
{
return m_pIQNet->GetState() != QNET_STATE_IDLE;
}
bool CPlatformNetworkManagerStub::IsInGameplay()
{
return m_pIQNet->GetState() == QNET_STATE_GAME_PLAY;
}
bool CPlatformNetworkManagerStub::IsReadyToPlayOrIdle()
{
return true;
}