diff --git a/Minecraft.Client/Common/Network/NetworkSocketLayer.cpp b/Minecraft.Client/Common/Network/NetworkSocketLayer.cpp index 22900158..abee0fd9 100644 --- a/Minecraft.Client/Common/Network/NetworkSocketLayer.cpp +++ b/Minecraft.Client/Common/Network/NetworkSocketLayer.cpp @@ -16,9 +16,11 @@ SOCKET NetworkSocketLayer::s_advertiseSock = -1; SOCKET NetworkSocketLayer::s_discoverySock = -1; #if defined __PS3__ +#define LCE_NET_ERRNO sys_net_errno int closesocket(int s) { return socketclose(s); }; void terminate_networking() { cellNetCtlTerm(); sys_net_finalize_network(); }; #elif defined __ORBIS__ +#define LCE_NET_ERRNO errno int closesocket(int s) { return sceNetSocketClose(s); }; int socketclose(int s) { return sceNetSocketClose(s); }; void terminate_networking() {}; @@ -60,10 +62,52 @@ std::vector NetworkSocketLayer::s_disconnectedSmallIds; CRITICAL_SECTION NetworkSocketLayer::s_freeSmallIdLock; std::vector NetworkSocketLayer::s_freeSmallIds; -bool g_MultiplayerHost = false; -bool g_MultiplayerJoin = true; -int g_MultiplayerPort = NETWORK_LAN_DEFAULT_PORT; -char g_MultiplayerIP[256] = "127.0.0.1"; +bool g_Win64MultiplayerHost = false; +#if defined __ORBIS__ +// Orbis has direct lan networking so it can bypass psn account checks +bool g_Win64MultiplayerJoin = true; +int g_Win64MultiplayerPort = WIN64_NET_DEFAULT_PORT; +char g_Win64MultiplayerIP[256] = ""; +#else +bool g_Win64MultiplayerJoin = false; +int g_Win64MultiplayerPort = WIN64_NET_DEFAULT_PORT; +char g_Win64MultiplayerIP[256] = "127.0.0.1"; +#endif + +#ifdef _WINDOWS64 +static int GetLocalIPv4Interfaces(SOCKET socketHandle, struct in_addr *localAddresses, + struct in_addr *broadcastAddresses, int capacity) +{ + INTERFACE_INFO interfaceList[32]; + DWORD bytesReturned = 0; + if(WSAIoctl(socketHandle, SIO_GET_INTERFACE_LIST, NULL, 0, interfaceList, + sizeof(interfaceList), &bytesReturned, NULL, NULL) == SOCKET_ERROR) + { + return 0; + } + + int interfaceCount = (int)(bytesReturned / sizeof(INTERFACE_INFO)); + int resultCount = 0; + for(int i = 0; i < interfaceCount && resultCount < capacity; ++i) + { + struct sockaddr_in *address = (struct sockaddr_in *)&interfaceList[i].iiAddress; + struct sockaddr_in *netmask = (struct sockaddr_in *)&interfaceList[i].iiNetmask; + if(address->sin_family != AF_INET) + continue; + + unsigned long hostAddress = ntohl(address->sin_addr.s_addr); + unsigned long hostNetmask = ntohl(netmask->sin_addr.s_addr); + if(hostAddress == 0 || (hostAddress & 0xff000000) == 0x7f000000 || hostNetmask == 0) + continue; + + localAddresses[resultCount] = address->sin_addr; + broadcastAddresses[resultCount].s_addr = htonl(hostAddress | ~hostNetmask); + ++resultCount; + } + + return resultCount; +} +#endif bool NetworkSocketLayer::Initialize() { @@ -555,6 +599,9 @@ bool NetworkSocketLayer::JoinGame(const char *ip, int port) struct sockaddr_in addr = {}; +#if defined(__ORBIS__) + addr.sin_len = sizeof(addr); +#endif addr.sin_family = AF_INET; addr.sin_port = htons((uint16_t)port); @@ -597,15 +644,16 @@ bool NetworkSocketLayer::JoinGame(const char *ip, int port) #endif iResult = connect(s_hostConnectionSocket, (struct sockaddr*)&addr, sizeof(addr)); + int connectError = iResult < 0 ? LCE_NET_ERRNO : 0; if (iResult < 0) { #if defined(__PS3__) - int err = sys_net_errno; + int err = connectError; if (err == SYS_NET_EINPROGRESS) { #elif defined(__ORBIS__) - int err = sce_net_errno; - if (err == SCE_NET_EINPROGRESS) + int err = connectError; + if (err == EINPROGRESS) { #endif fd_set writeFds, exceptFds; @@ -1205,8 +1253,31 @@ int NetworkSocketLayer::AdvertiseThreadProc(LPVOID param) data.gameHostSettings = htonl(data.gameHostSettings); data.texturePackParentId = htonl(data.texturePackParentId); - int sent = sendto(s_advertiseSock, (const char *)&data, sizeof(data), 0, + int sent = -1; + +#ifdef _WINDOWS64 + struct in_addr localAddresses[32]; + struct in_addr broadcastAddresses[32]; + int interfaceCount = GetLocalIPv4Interfaces(s_advertiseSock, localAddresses, broadcastAddresses, 32); + for(int i = 0; i < interfaceCount; ++i) + { + broadcastAddr.sin_addr = broadcastAddresses[i]; + int interfaceSent = sendto(s_advertiseSock, (const char *)&data, sizeof(data), 0, + (struct sockaddr *)&broadcastAddr, sizeof(broadcastAddr)); + if(interfaceSent != SOCKET_ERROR) + sent = interfaceSent; + } + + if(interfaceCount == 0) + { + broadcastAddr.sin_addr.s_addr = INADDR_BROADCAST; + sent = sendto(s_advertiseSock, (const char *)&data, sizeof(data), 0, + (struct sockaddr *)&broadcastAddr, sizeof(broadcastAddr)); + } +#else + sent = sendto(s_advertiseSock, (const char *)&data, sizeof(data), 0, (struct sockaddr *)&broadcastAddr, sizeof(broadcastAddr)); +#endif #if defined _WINDOWS64 || defined _XBOX if (sent == SOCKET_ERROR && s_advertising) diff --git a/Minecraft.Client/Common/Network/PlatformNetworkManager.cpp b/Minecraft.Client/Common/Network/PlatformNetworkManager.cpp index 59ce1a0b..f0ff0dd0 100644 --- a/Minecraft.Client/Common/Network/PlatformNetworkManager.cpp +++ b/Minecraft.Client/Common/Network/PlatformNetworkManager.cpp @@ -1,947 +1,947 @@ -#include "stdafx.h" -#include "..\..\..\Minecraft.World\Socket.h" -#include "..\..\..\Minecraft.World\StringHelpers.h" -#include "PlatformNetworkManager.h" -#include "..\..\Xbox\Network\NetworkPlayerXbox.h" // TODO - stub version of this? -#include "..\..\Minecraft.h" -#include "..\..\User.h" -#include "..\..\Common\Network\NetworkSocketLayer.h" - -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; - } -} - -void CPlatformNetworkManagerStub::NotifyPlayerLeaving(IQNetPlayer *pQNetPlayer) -{ - app.DebugPrintf("Player 0x%p \"%ls\" leaving.\n", pQNetPlayer, pQNetPlayer->GetGamertag()); - - INetworkPlayer *networkPlayer = getNetworkPlayer(pQNetPlayer); - if (networkPlayer == NULL) - return; - - Socket *socket = networkPlayer->GetSocket(); - if (socket != NULL) - { - if (m_pIQNet->IsHost()) - g_NetworkManager.CloseConnection(networkPlayer); - } - - if (m_pIQNet->IsHost()) - { - SystemFlagRemovePlayer(networkPlayer); - } - - g_NetworkManager.PlayerLeaving(networkPlayer); - - if (m_pIQNet->IsHost()) - { - g_NetworkManager.UpdateAndSetGameSessionData(networkPlayer); - } - - for (int idx = 0; idx < XUSER_MAX_COUNT; ++idx) - { - if (playerChangedCallback[idx] != NULL) - playerChangedCallback[idx](playerChangedCallbackParam[idx], networkPlayer, true); - } - - removeNetworkPlayer(pQNetPlayer); -} - -bool CPlatformNetworkManagerStub::Initialise(CGameNetworkManager *pGameNetworkManager, int flagIndexSize) -{ - m_pGameNetworkManager = pGameNetworkManager; - m_flagIndexSize = flagIndexSize; - m_pIQNet = new IQNet(); - 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() -{ - extern QNET_STATE _iQNetStubState; - if (_iQNetStubState == QNET_STATE_SESSION_STARTING && app.GetGameStarted()) - { - _iQNetStubState = QNET_STATE_GAME_PLAY; - if (m_pIQNet->IsHost()) - NetworkSocketLayer::UpdateAdvertiseJoinable(true); - } - if (_iQNetStubState == QNET_STATE_IDLE) - TickSearch(); - if (_iQNetStubState == QNET_STATE_GAME_PLAY && m_pIQNet->IsHost()) - { - BYTE disconnectedSmallId; - while (NetworkSocketLayer::PopDisconnectedSmallId(&disconnectedSmallId)) - { - IQNetPlayer *qnetPlayer = m_pIQNet->GetPlayerBySmallId(disconnectedSmallId); - if (qnetPlayer != NULL && qnetPlayer->m_smallId == disconnectedSmallId) - { - NotifyPlayerLeaving(qnetPlayer); - qnetPlayer->m_smallId = 0; - qnetPlayer->m_isRemote = false; - qnetPlayer->m_isHostPlayer = false; - qnetPlayer->m_gamertag[0] = 0; - qnetPlayer->SetCustomDataValue(0); - NetworkSocketLayer::PushFreeSmallId(disconnectedSmallId); - if (IQNet::s_playerCount > 1) - IQNet::s_playerCount--; - } - } - - for (int i = 1; i < MINECRAFT_NET_MAX_PLAYERS; i++) - { - IQNetPlayer *qp = &IQNet::m_player[i]; - if (qp->GetCustomDataValue() == 0) - continue; - INetworkPlayer *np = (INetworkPlayer *)qp->GetCustomDataValue(); - Socket *sock = np->GetSocket(); - if (sock != NULL && sock->isClosing()) - { - NetworkSocketLayer::CloseConnectionBySmallId((BYTE)i); - } - } - } - if (_iQNetStubState == QNET_STATE_GAME_PLAY && !m_pIQNet->IsHost()) - { - if (!NetworkSocketLayer::IsConnected() && !g_NetworkManager.IsLeavingGame()) - { - if (app.GetDisconnectReason() == DisconnectPacket::eDisconnect_None) - app.SetDisconnectReason(DisconnectPacket::eDisconnect_Quitting); - app.SetAction(ProfileManager.GetPrimaryPad(), eAppAction_ExitWorld, (void *)TRUE); - } - } -} - -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; - NetworkSocketLayer::StopAdvertising(); - - // 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(); - } - else - { - m_pIQNet->EndGame(); - } - - for (AUTO_VAR(it, currentNetworkPlayers.begin()); it != currentNetworkPlayers.end(); it++) - delete *it; - currentNetworkPlayers.clear(); - m_machineQNetPrimaryPlayers.clear(); - SystemFlagReset(); - - NetworkSocketLayer::Shutdown(); - NetworkSocketLayer::Initialize(); - - 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(); - - IQNet::m_player[0].m_smallId = 0; - IQNet::m_player[0].m_isRemote = false; - IQNet::m_player[0].m_isHostPlayer = true; - IQNet::s_playerCount = 1; - - _HostGame( localUsersMask, publicSlots, privateSlots ); - - int port = NETWORK_LAN_DEFAULT_PORT; - if (!NetworkSocketLayer::IsActive()) - NetworkSocketLayer::HostGame(port); - - const wchar_t *hostName = IQNet::m_player[0].m_gamertag; - unsigned int settings = app.GetGameHostOption(eGameHostOption_All); - NetworkSocketLayer::StartAdvertising(port, hostName, settings, 0, 0, MINECRAFT_NET_VERSION); -//#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) -{ - if (searchResult == NULL) - return CGameNetworkManager::JOINGAME_FAIL_GENERAL; - - const char *hostIP = searchResult->data.hostIP; - int hostPort = searchResult->data.hostPort; - - if (hostPort <= 0 || hostIP[0] == 0) - return CGameNetworkManager::JOINGAME_FAIL_GENERAL; - - m_bLeavingGame = false; - IQNet::s_isHosting = false; - m_pIQNet->ClientJoinGame(); - - IQNet::m_player[0].m_smallId = 0; - IQNet::m_player[0].m_isRemote = true; - IQNet::m_player[0].m_isHostPlayer = true; - wcsncpy(IQNet::m_player[0].m_gamertag, searchResult->data.hostName, 31); - - NetworkSocketLayer::StopDiscovery(); - - if (!NetworkSocketLayer::JoinGame(hostIP, hostPort)) - { - app.DebugPrintf("Win64 LAN: Failed to connect to %s:%d\n", hostIP, hostPort); - return CGameNetworkManager::JOINGAME_FAIL_GENERAL; - } - - BYTE localSmallId = NetworkSocketLayer::GetLocalSmallId(); - - IQNet::m_player[localSmallId].m_smallId = localSmallId; - IQNet::m_player[localSmallId].m_isRemote = false; - IQNet::m_player[localSmallId].m_isHostPlayer = false; - - Minecraft *pMinecraft = Minecraft::GetInstance(); - wcsncpy(IQNet::m_player[localSmallId].m_gamertag, pMinecraft->user->name.c_str(), 32); - IQNet::s_playerCount = localSmallId + 1; - - NotifyPlayerJoined(&IQNet::m_player[0]); - NotifyPlayerJoined(&IQNet::m_player[localSmallId]); - - m_pGameNetworkManager->StateChange_AnyToStarting(); - - 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() -{ - extern QNET_STATE _iQNetStubState; - _iQNetStubState = QNET_STATE_GAME_PLAY; - - for (DWORD i = 0; i < IQNet::s_playerCount; i++) - { - if (IQNet::m_player[i].m_isRemote) - { - INetworkPlayer *pNetworkPlayer = getNetworkPlayer(&IQNet::m_player[i]); - if (pNetworkPlayer != NULL && pNetworkPlayer->GetSocket() != NULL) - { - Socket::addIncomingSocket(pNetworkPlayer->GetSocket()); - } - } - } - - return true; -} - -void CPlatformNetworkManagerStub::UpdateAndSetGameSessionData(INetworkPlayer *pNetworkPlayerLeaving /*= NULL*/) -{ - if (this->m_bLeavingGame) - return; - - if (!m_pIQNet->IsHost()) - return; - - DWORD playerCount = m_pIQNet->GetPlayerCount(); - - m_hostGameSessionData.m_uiGameHostSettings = app.GetGameHostOption(eGameHostOption_All); - m_hostGameSessionData.playerCount = (unsigned char)playerCount; - - for (unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) - { - if (i < playerCount) - { - INetworkPlayer *pNetworkPlayer = GetPlayerByIndex(i); - - if (pNetworkPlayer != NULL && pNetworkPlayer != pNetworkPlayerLeaving) - { - m_hostGameSessionData.players[i] = (GameSessionUID)(i + 1); - - const wchar_t *name = pNetworkPlayer->GetOnlineName(); - char nameBuf[XUSER_NAME_SIZE]; - memset(nameBuf, 0, sizeof(nameBuf)); - wcstombs(nameBuf, name, XUSER_NAME_SIZE - 1); - memcpy(m_hostGameSessionData.szPlayers[i], nameBuf, XUSER_NAME_SIZE); - } - else - { - m_hostGameSessionData.players[i] = 0; - memset(m_hostGameSessionData.szPlayers[i], 0, XUSER_NAME_SIZE); - } - } - else - { - m_hostGameSessionData.players[i] = 0; - memset(m_hostGameSessionData.szPlayers[i], 0, XUSER_NAME_SIZE); - } - } - - // update the LAN advertiser with current player names and count - NetworkSocketLayer::UpdateAdvertisePlayerNames(m_hostGameSessionData.playerCount, m_hostGameSessionData.szPlayers); -} - -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() -{ - if (m_SessionsUpdatedCallback == NULL) - return; - - static DWORD lastSearchTime = 0; - DWORD now = GetTickCount(); - if (now - lastSearchTime < 2000) - return; - lastSearchTime = now; - - SearchForGames(); -} - -void CPlatformNetworkManagerStub::SearchForGames() -{ - std::vector lanSessions = NetworkSocketLayer::GetDiscoveredSessions(); - - if (g_MultiplayerJoin) - { - bool alreadyPresent = false; - for (size_t i = 0; i < lanSessions.size(); i++) - { - if (strcmp(lanSessions[i].hostIP, g_MultiplayerIP) == 0 && - lanSessions[i].hostPort == g_MultiplayerPort) - { - alreadyPresent = true; - break; - } - } - if (!alreadyPresent) - { - LANSession manual; - memset(&manual, 0, sizeof(manual)); - strncpy(manual.hostIP, g_MultiplayerIP, sizeof(manual.hostIP) - 1); - manual.hostIP[sizeof(manual.hostIP) - 1] = '\0'; - - manual.hostPort = g_MultiplayerPort; - - swprintf(manual.hostName, 32, L"%hs:%d", g_MultiplayerIP, g_MultiplayerPort); - manual.hostName[31] = L'\0'; - manual.playerCount = 0; - manual.maxPlayers = MINECRAFT_NET_MAX_PLAYERS; - manual.isJoinable = true; - manual.lastSeenTick = GetTickCount(); - lanSessions.push_back(manual); - } - } - - for (size_t i = 0; i < friendsSessions[0].size(); i++) - delete friendsSessions[0][i]; - friendsSessions[0].clear(); - - for (size_t i = 0; i < lanSessions.size(); i++) - { - FriendSessionInfo *info = new FriendSessionInfo(); - size_t nameLen = wcslen(lanSessions[i].hostName); - info->displayLabel = new wchar_t[nameLen + 1]; - wcsncpy(info->displayLabel, lanSessions[i].hostName, nameLen); - info->displayLabel[nameLen] = L'\0'; - info->displayLabelLength = (unsigned char)nameLen; - info->displayLabelViewableStartIndex = 0; - - info->data.netVersion = lanSessions[i].netVersion; - info->data.m_uiGameHostSettings = lanSessions[i].gameHostSettings; - info->data.texturePackParentId = lanSessions[i].texturePackParentId; - info->data.subTexturePackId = lanSessions[i].subTexturePackId; - info->data.isReadyToJoin = lanSessions[i].isJoinable; - info->data.isJoinable = lanSessions[i].isJoinable; - strncpy(info->data.hostIP, lanSessions[i].hostIP, sizeof(info->data.hostIP) - 1); - info->data.hostIP[sizeof(info->data.hostIP) - 1] = '\0'; - info->data.hostPort = lanSessions[i].hostPort; - wcsncpy(info->data.hostName, lanSessions[i].hostName, XUSER_NAME_SIZE - 1); - info->data.hostName[XUSER_NAME_SIZE - 1] = L'\0'; - info->data.playerCount = lanSessions[i].playerCount; - info->data.maxPlayers = lanSessions[i].maxPlayers; - - memset(info->data.players, 0, sizeof(info->data.players)); - memset(info->data.szPlayers, 0, sizeof(info->data.szPlayers)); - for (int p = 0; p < MINECRAFT_NET_MAX_PLAYERS && p < lanSessions[i].playerCount; p++) - { - if (lanSessions[i].playerNames[p][0] != 0) - { - info->data.players[p] = (GameSessionUID)(p + 1); - memcpy(info->data.szPlayers[p], lanSessions[i].playerNames[p], XUSER_NAME_SIZE); - } - } - -#ifdef __ORBIS__ - SceNetInAddr ip_addr = {}; - sceNetInetPton(SCE_NET_AF_INET, lanSessions[i].hostIP, &ip_addr); - info->sessionId = (ULONGLONG)((uint64_t)ip_addr.s_addr | ((uint64_t)lanSessions[i].hostPort << 32)); -#else - info->sessionId = (ULONGLONG)((unsigned __int64)inet_addr(lanSessions[i].hostIP) | ((unsigned __int64)lanSessions[i].hostPort << 32)); -#endif - friendsSessions[0].push_back(info); - } - - m_searchResultsCount[0] = (int)friendsSessions[0].size(); - - if (m_SessionsUpdatedCallback != NULL) - m_SessionsUpdatedCallback(m_pSearchParam); -} - -int CPlatformNetworkManagerStub::SearchForGamesThreadProc( void* lpParameter ) -{ - return 0; -} - -void CPlatformNetworkManagerStub::SetSearchResultsReady(int resultCount) -{ - m_bSearchResultsReady = true; - m_searchResultsCount[m_lastSearchPad] = resultCount; -} - -vector *CPlatformNetworkManagerStub::GetSessionList(int iPad, int localPlayers, bool partyOnly) -{ - vector *filteredList = new vector(); - for (size_t i = 0; i < friendsSessions[0].size(); i++) - filteredList->push_back(friendsSessions[0][i]); - return filteredList; -} - -bool CPlatformNetworkManagerStub::GetGameSessionInfo(int iPad, SessionID sessionId, FriendSessionInfo *foundSessionInfo) -{ - for (size_t i = 0; i < friendsSessions[0].size(); i++) - { - if (friendsSessions[0][i]->sessionId == sessionId) - { - if (foundSessionInfo != NULL) - { - foundSessionInfo->sessionId = friendsSessions[0][i]->sessionId; - foundSessionInfo->data = friendsSessions[0][i]->data; - foundSessionInfo->hasPartyMember = friendsSessions[0][i]->hasPartyMember; - } - return true; - } - } -} - -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) -{ - IQNetPlayer *qnetPlayer = m_pIQNet->GetPlayerBySmallId(smallId); - if (qnetPlayer == NULL) - return NULL; - - INetworkPlayer *networkPlayer = getNetworkPlayer(qnetPlayer); - if (networkPlayer == NULL && smallId != 0 && !m_pIQNet->IsHost()) - { - qnetPlayer->m_isRemote = true; - qnetPlayer->m_isHostPlayer = false; - NotifyPlayerJoined(qnetPlayer); - networkPlayer = getNetworkPlayer(qnetPlayer); - } - return networkPlayer; -} - -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; -} +#include "stdafx.h" +#include "..\..\..\Minecraft.World\Socket.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" +#include "PlatformNetworkManager.h" +#include "..\..\Xbox\Network\NetworkPlayerXbox.h" // TODO - stub version of this? +#include "..\..\Minecraft.h" +#include "..\..\User.h" +#include "..\..\Common\Network\NetworkSocketLayer.h" + +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; + } +} + +void CPlatformNetworkManagerStub::NotifyPlayerLeaving(IQNetPlayer *pQNetPlayer) +{ + app.DebugPrintf("Player 0x%p \"%ls\" leaving.\n", pQNetPlayer, pQNetPlayer->GetGamertag()); + + INetworkPlayer *networkPlayer = getNetworkPlayer(pQNetPlayer); + if (networkPlayer == NULL) + return; + + Socket *socket = networkPlayer->GetSocket(); + if (socket != NULL) + { + if (m_pIQNet->IsHost()) + g_NetworkManager.CloseConnection(networkPlayer); + } + + if (m_pIQNet->IsHost()) + { + SystemFlagRemovePlayer(networkPlayer); + } + + g_NetworkManager.PlayerLeaving(networkPlayer); + + if (m_pIQNet->IsHost()) + { + g_NetworkManager.UpdateAndSetGameSessionData(networkPlayer); + } + + for (int idx = 0; idx < XUSER_MAX_COUNT; ++idx) + { + if (playerChangedCallback[idx] != NULL) + playerChangedCallback[idx](playerChangedCallbackParam[idx], networkPlayer, true); + } + + removeNetworkPlayer(pQNetPlayer); +} + +bool CPlatformNetworkManagerStub::Initialise(CGameNetworkManager *pGameNetworkManager, int flagIndexSize) +{ + m_pGameNetworkManager = pGameNetworkManager; + m_flagIndexSize = flagIndexSize; + m_pIQNet = new IQNet(); + 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() +{ + extern QNET_STATE _iQNetStubState; + if (_iQNetStubState == QNET_STATE_SESSION_STARTING && app.GetGameStarted()) + { + _iQNetStubState = QNET_STATE_GAME_PLAY; + if (m_pIQNet->IsHost()) + NetworkSocketLayer::UpdateAdvertiseJoinable(true); + } + if (_iQNetStubState == QNET_STATE_IDLE) + TickSearch(); + if (_iQNetStubState == QNET_STATE_GAME_PLAY && m_pIQNet->IsHost()) + { + BYTE disconnectedSmallId; + while (NetworkSocketLayer::PopDisconnectedSmallId(&disconnectedSmallId)) + { + IQNetPlayer *qnetPlayer = m_pIQNet->GetPlayerBySmallId(disconnectedSmallId); + if (qnetPlayer != NULL && qnetPlayer->m_smallId == disconnectedSmallId) + { + NotifyPlayerLeaving(qnetPlayer); + qnetPlayer->m_smallId = 0; + qnetPlayer->m_isRemote = false; + qnetPlayer->m_isHostPlayer = false; + qnetPlayer->m_gamertag[0] = 0; + qnetPlayer->SetCustomDataValue(0); + NetworkSocketLayer::PushFreeSmallId(disconnectedSmallId); + if (IQNet::s_playerCount > 1) + IQNet::s_playerCount--; + } + } + + for (int i = 1; i < MINECRAFT_NET_MAX_PLAYERS; i++) + { + IQNetPlayer *qp = &IQNet::m_player[i]; + if (qp->GetCustomDataValue() == 0) + continue; + INetworkPlayer *np = (INetworkPlayer *)qp->GetCustomDataValue(); + Socket *sock = np->GetSocket(); + if (sock != NULL && sock->isClosing()) + { + NetworkSocketLayer::CloseConnectionBySmallId((BYTE)i); + } + } + } + if (_iQNetStubState == QNET_STATE_GAME_PLAY && !m_pIQNet->IsHost()) + { + if (!NetworkSocketLayer::IsConnected() && !g_NetworkManager.IsLeavingGame()) + { + if (app.GetDisconnectReason() == DisconnectPacket::eDisconnect_None) + app.SetDisconnectReason(DisconnectPacket::eDisconnect_Quitting); + app.SetAction(ProfileManager.GetPrimaryPad(), eAppAction_ExitWorld, (void *)TRUE); + } + } +} + +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; + NetworkSocketLayer::StopAdvertising(); + + // 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(); + } + else + { + m_pIQNet->EndGame(); + } + + for (AUTO_VAR(it, currentNetworkPlayers.begin()); it != currentNetworkPlayers.end(); it++) + delete *it; + currentNetworkPlayers.clear(); + m_machineQNetPrimaryPlayers.clear(); + SystemFlagReset(); + + NetworkSocketLayer::Shutdown(); + NetworkSocketLayer::Initialize(); + + 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(); + + IQNet::m_player[0].m_smallId = 0; + IQNet::m_player[0].m_isRemote = false; + IQNet::m_player[0].m_isHostPlayer = true; + IQNet::s_playerCount = 1; + + _HostGame( localUsersMask, publicSlots, privateSlots ); + + int port = NETWORK_LAN_DEFAULT_PORT; + if (!NetworkSocketLayer::IsActive()) + NetworkSocketLayer::HostGame(port); + + const wchar_t *hostName = IQNet::m_player[0].m_gamertag; + unsigned int settings = app.GetGameHostOption(eGameHostOption_All); + NetworkSocketLayer::StartAdvertising(port, hostName, settings, 0, 0, MINECRAFT_NET_VERSION); +//#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) +{ + if (searchResult == NULL) + return CGameNetworkManager::JOINGAME_FAIL_GENERAL; + + const char *hostIP = searchResult->data.hostIP; + int hostPort = searchResult->data.hostPort; + + if (hostPort <= 0 || hostIP[0] == 0) + return CGameNetworkManager::JOINGAME_FAIL_GENERAL; + + m_bLeavingGame = false; + IQNet::s_isHosting = false; + m_pIQNet->ClientJoinGame(); + + IQNet::m_player[0].m_smallId = 0; + IQNet::m_player[0].m_isRemote = true; + IQNet::m_player[0].m_isHostPlayer = true; + wcsncpy(IQNet::m_player[0].m_gamertag, searchResult->data.hostName, 31); + + NetworkSocketLayer::StopDiscovery(); + + if (!NetworkSocketLayer::JoinGame(hostIP, hostPort)) + { + app.DebugPrintf("Win64 LAN: Failed to connect to %s:%d\n", hostIP, hostPort); + return CGameNetworkManager::JOINGAME_FAIL_GENERAL; + } + + BYTE localSmallId = NetworkSocketLayer::GetLocalSmallId(); + + IQNet::m_player[localSmallId].m_smallId = localSmallId; + IQNet::m_player[localSmallId].m_isRemote = false; + IQNet::m_player[localSmallId].m_isHostPlayer = false; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + wcsncpy(IQNet::m_player[localSmallId].m_gamertag, pMinecraft->user->name.c_str(), 32); + IQNet::s_playerCount = localSmallId + 1; + + NotifyPlayerJoined(&IQNet::m_player[0]); + NotifyPlayerJoined(&IQNet::m_player[localSmallId]); + + m_pGameNetworkManager->StateChange_AnyToStarting(); + + 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() +{ + extern QNET_STATE _iQNetStubState; + _iQNetStubState = QNET_STATE_GAME_PLAY; + + for (DWORD i = 0; i < IQNet::s_playerCount; i++) + { + if (IQNet::m_player[i].m_isRemote) + { + INetworkPlayer *pNetworkPlayer = getNetworkPlayer(&IQNet::m_player[i]); + if (pNetworkPlayer != NULL && pNetworkPlayer->GetSocket() != NULL) + { + Socket::addIncomingSocket(pNetworkPlayer->GetSocket()); + } + } + } + + return true; +} + +void CPlatformNetworkManagerStub::UpdateAndSetGameSessionData(INetworkPlayer *pNetworkPlayerLeaving /*= NULL*/) +{ + if (this->m_bLeavingGame) + return; + + if (!m_pIQNet->IsHost()) + return; + + DWORD playerCount = m_pIQNet->GetPlayerCount(); + + m_hostGameSessionData.m_uiGameHostSettings = app.GetGameHostOption(eGameHostOption_All); + m_hostGameSessionData.playerCount = (unsigned char)playerCount; + + for (unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) + { + if (i < playerCount) + { + INetworkPlayer *pNetworkPlayer = GetPlayerByIndex(i); + + if (pNetworkPlayer != NULL && pNetworkPlayer != pNetworkPlayerLeaving) + { + m_hostGameSessionData.players[i] = (GameSessionUID)(i + 1); + + const wchar_t *name = pNetworkPlayer->GetOnlineName(); + char nameBuf[XUSER_NAME_SIZE]; + memset(nameBuf, 0, sizeof(nameBuf)); + wcstombs(nameBuf, name, XUSER_NAME_SIZE - 1); + memcpy(m_hostGameSessionData.szPlayers[i], nameBuf, XUSER_NAME_SIZE); + } + else + { + m_hostGameSessionData.players[i] = 0; + memset(m_hostGameSessionData.szPlayers[i], 0, XUSER_NAME_SIZE); + } + } + else + { + m_hostGameSessionData.players[i] = 0; + memset(m_hostGameSessionData.szPlayers[i], 0, XUSER_NAME_SIZE); + } + } + + // update the LAN advertiser with current player names and count + NetworkSocketLayer::UpdateAdvertisePlayerNames(m_hostGameSessionData.playerCount, m_hostGameSessionData.szPlayers); +} + +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() +{ + if (m_SessionsUpdatedCallback == NULL) + return; + + static DWORD lastSearchTime = 0; + DWORD now = GetTickCount(); + if (now - lastSearchTime < 2000) + return; + lastSearchTime = now; + + SearchForGames(); +} + +void CPlatformNetworkManagerStub::SearchForGames() +{ + std::vector lanSessions = NetworkSocketLayer::GetDiscoveredSessions(); + + if (g_MultiplayerJoin) + { + bool alreadyPresent = false; + for (size_t i = 0; i < lanSessions.size(); i++) + { + if (strcmp(lanSessions[i].hostIP, g_MultiplayerIP) == 0 && + lanSessions[i].hostPort == g_MultiplayerPort) + { + alreadyPresent = true; + break; + } + } + if (!alreadyPresent) + { + LANSession manual; + memset(&manual, 0, sizeof(manual)); + strncpy(manual.hostIP, g_MultiplayerIP, sizeof(manual.hostIP) - 1); + manual.hostIP[sizeof(manual.hostIP) - 1] = '\0'; + + manual.hostPort = g_MultiplayerPort; + + swprintf(manual.hostName, 32, L"%hs:%d", g_MultiplayerIP, g_MultiplayerPort); + manual.hostName[31] = L'\0'; + manual.playerCount = 0; + manual.maxPlayers = MINECRAFT_NET_MAX_PLAYERS; + manual.isJoinable = true; + manual.lastSeenTick = GetTickCount(); + lanSessions.push_back(manual); + } + } + + for (size_t i = 0; i < friendsSessions[0].size(); i++) + delete friendsSessions[0][i]; + friendsSessions[0].clear(); + + for (size_t i = 0; i < lanSessions.size(); i++) + { + FriendSessionInfo *info = new FriendSessionInfo(); + size_t nameLen = wcslen(lanSessions[i].hostName); + info->displayLabel = new wchar_t[nameLen + 1]; + wcsncpy(info->displayLabel, lanSessions[i].hostName, nameLen); + info->displayLabel[nameLen] = L'\0'; + info->displayLabelLength = (unsigned char)nameLen; + info->displayLabelViewableStartIndex = 0; + + info->data.netVersion = lanSessions[i].netVersion; + info->data.m_uiGameHostSettings = lanSessions[i].gameHostSettings; + info->data.texturePackParentId = lanSessions[i].texturePackParentId; + info->data.subTexturePackId = lanSessions[i].subTexturePackId; + info->data.isReadyToJoin = lanSessions[i].isJoinable; + info->data.isJoinable = lanSessions[i].isJoinable; + strncpy(info->data.hostIP, lanSessions[i].hostIP, sizeof(info->data.hostIP) - 1); + info->data.hostIP[sizeof(info->data.hostIP) - 1] = '\0'; + info->data.hostPort = lanSessions[i].hostPort; + wcsncpy(info->data.hostName, lanSessions[i].hostName, XUSER_NAME_SIZE - 1); + info->data.hostName[XUSER_NAME_SIZE - 1] = L'\0'; + info->data.playerCount = lanSessions[i].playerCount; + info->data.maxPlayers = lanSessions[i].maxPlayers; + + memset(info->data.players, 0, sizeof(info->data.players)); + memset(info->data.szPlayers, 0, sizeof(info->data.szPlayers)); + for (int p = 0; p < MINECRAFT_NET_MAX_PLAYERS && p < lanSessions[i].playerCount; p++) + { + if (lanSessions[i].playerNames[p][0] != 0) + { + info->data.players[p] = (GameSessionUID)(p + 1); + memcpy(info->data.szPlayers[p], lanSessions[i].playerNames[p], XUSER_NAME_SIZE); + } + } + +#ifdef __ORBIS__ + SceNetInAddr ip_addr = {}; + sceNetInetPton(SCE_NET_AF_INET, lanSessions[i].hostIP, &ip_addr); + info->sessionId = (ULONGLONG)((uint64_t)ip_addr.s_addr | ((uint64_t)lanSessions[i].hostPort << 32)); +#else + info->sessionId = (ULONGLONG)((unsigned __int64)inet_addr(lanSessions[i].hostIP) | ((unsigned __int64)lanSessions[i].hostPort << 32)); +#endif + friendsSessions[0].push_back(info); + } + + m_searchResultsCount[0] = (int)friendsSessions[0].size(); + + if (m_SessionsUpdatedCallback != NULL) + m_SessionsUpdatedCallback(m_pSearchParam); +} + +int CPlatformNetworkManagerStub::SearchForGamesThreadProc( void* lpParameter ) +{ + return 0; +} + +void CPlatformNetworkManagerStub::SetSearchResultsReady(int resultCount) +{ + m_bSearchResultsReady = true; + m_searchResultsCount[m_lastSearchPad] = resultCount; +} + +vector *CPlatformNetworkManagerStub::GetSessionList(int iPad, int localPlayers, bool partyOnly) +{ + vector *filteredList = new vector(); + for (size_t i = 0; i < friendsSessions[0].size(); i++) + filteredList->push_back(friendsSessions[0][i]); + return filteredList; +} + +bool CPlatformNetworkManagerStub::GetGameSessionInfo(int iPad, SessionID sessionId, FriendSessionInfo *foundSessionInfo) +{ + for (size_t i = 0; i < friendsSessions[0].size(); i++) + { + if (friendsSessions[0][i]->sessionId == sessionId) + { + if (foundSessionInfo != NULL) + { + foundSessionInfo->sessionId = friendsSessions[0][i]->sessionId; + foundSessionInfo->data = friendsSessions[0][i]->data; + foundSessionInfo->hasPartyMember = friendsSessions[0][i]->hasPartyMember; + } + return true; + } + } +} + +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) +{ + IQNetPlayer *qnetPlayer = m_pIQNet->GetPlayerBySmallId(smallId); + if (qnetPlayer == NULL) + return NULL; + + INetworkPlayer *networkPlayer = getNetworkPlayer(qnetPlayer); + if (networkPlayer == NULL && smallId != 0 && !m_pIQNet->IsHost()) + { + qnetPlayer->m_isRemote = true; + qnetPlayer->m_isHostPlayer = false; + NotifyPlayerJoined(qnetPlayer); + networkPlayer = getNetworkPlayer(qnetPlayer); + } + return networkPlayer; +} + +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; +} diff --git a/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp b/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp index 86b3806b..7d19b290 100644 --- a/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp @@ -7,6 +7,7 @@ #include "..\..\MinecraftServer.h" #include "..\..\..\Minecraft.World\net.minecraft.world.level.h" #include "..\..\..\Minecraft.World\net.minecraft.world.h" +#include "..\..\Common\Network\WinsockNetLayer.h" #define UPDATE_PLAYERS_TIMER_ID 0 #define UPDATE_PLAYERS_TIMER_TIME 30000 @@ -50,7 +51,6 @@ void UIScene_JoinMenu::tick() g_NetworkManager.GetFullFriendSessionInfo(m_selectedSession, &friendSessionUpdated, this); m_friendInfoRequestIssued = true; } - if( m_friendInfoUpdatedOK ) { m_friendInfoUpdatedOK = false; @@ -368,6 +368,12 @@ void UIScene_JoinMenu::checkPrivilegeCallback(LPVOID lpParam, bool hasPrivilege, void UIScene_JoinMenu::StartSharedLaunchFlow() { + const bool bManualJoin = (g_Win64MultiplayerJoin == true); + if (bManualJoin) + { + JoinGame(this); + return; + } #if defined DISABLE_PSN JoinGame(this); #else @@ -421,6 +427,12 @@ int UIScene_JoinMenu::StartGame_SignInReturned(void *pParam,bool bContinue, int // Shared function to join the game that is the same whether we used the sign-in UI or not void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) { + if (pClass == NULL) + { + return; + } + const bool bManualJoin = (g_Win64MultiplayerJoin == true); + DWORD dwSignedInUsers = 0; bool noPrivileges = false; DWORD dwLocalUsersMask = 0; @@ -428,10 +440,14 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) int iPadNotSignedInLive = -1; ProfileManager.SetLockedProfile(0); // TEMP! + if (bManualJoin) + { + isSignedInLive = true; + } // If we're in SD mode, then only the primary player gets to play if (app.IsLocalMultiplayerAvailable()) - { + { for(unsigned int index = 0; index < XUSER_MAX_COUNT; ++index) { if(ProfileManager.IsSignedIn(index)) @@ -442,7 +458,7 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) iPadNotSignedInLive = index; } - if( !ProfileManager.AllowedToPlayMultiplayer(index) ) noPrivileges = true; + if( !bManualJoin && !ProfileManager.AllowedToPlayMultiplayer(index) ) noPrivileges = true; dwLocalUsersMask |= CGameNetworkManager::GetLocalPlayerMask(index); isSignedInLive = isSignedInLive && ProfileManager.IsSignedInLive(index); } @@ -452,7 +468,7 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) { if(ProfileManager.IsSignedIn(ProfileManager.GetPrimaryPad())) { - if( !ProfileManager.AllowedToPlayMultiplayer(ProfileManager.GetPrimaryPad()) ) noPrivileges = true; + if( !bManualJoin && !ProfileManager.AllowedToPlayMultiplayer(ProfileManager.GetPrimaryPad()) ) noPrivileges = true; dwLocalUsersMask |= CGameNetworkManager::GetLocalPlayerMask(ProfileManager.GetPrimaryPad()); #ifndef DISABLE_PSN @@ -467,7 +483,7 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) } // If this is an online game but not all players are signed in to Live, stop! - if (!isSignedInLive) + if (!bManualJoin && !isSignedInLive) { #ifdef __ORBIS__ // Check if PSN is unavailable because of age restriction @@ -497,14 +513,22 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) BOOL pccFriendsAllowed = TRUE; #if !defined(DISABLE_PSN) && (defined(__PS3__) || defined(__PSVITA__)) - if(isSignedInLive) + if(!bManualJoin && isSignedInLive) { ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),false,&noUGC,NULL,NULL); } #else - ProfileManager.AllowedPlayerCreatedContent(ProfileManager.GetPrimaryPad(),false,&pccAllowed,&pccFriendsAllowed); - if(!pccAllowed && !pccFriendsAllowed) noUGC = true; + if(!bManualJoin) + { + ProfileManager.AllowedPlayerCreatedContent(ProfileManager.GetPrimaryPad(),false,&pccAllowed,&pccFriendsAllowed); + if(!pccAllowed && !pccFriendsAllowed) noUGC = true; + } #endif + if (bManualJoin) + { + noUGC = false; + noPrivileges = false; + } #ifdef __PSVITA__ @@ -534,13 +558,16 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) ui.RequestErrorMessage( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad()); } else - { -#if defined(__ORBIS__) || defined(__PSVITA__) - bool chatRestricted = false; - ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),false,&chatRestricted,NULL,NULL); - if(chatRestricted) { - ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION, ProfileManager.GetPrimaryPad() ); +#if defined(__ORBIS__) || defined(__PSVITA__) + if(!bManualJoin) + { + bool chatRestricted = false; + ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),false,&chatRestricted,NULL,NULL); + if(chatRestricted) + { + ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION, ProfileManager.GetPrimaryPad() ); + } } #endif CGameNetworkManager::eJoinGameResult result = g_NetworkManager.JoinGame( pClass->m_selectedSession, dwLocalUsersMask ); @@ -550,6 +577,7 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) if( result != CGameNetworkManager::JOINGAME_SUCCESS ) { + pClass->m_bIgnoreInput = false; int exitReasonStringId = -1; switch(result) { @@ -643,4 +671,4 @@ void UIScene_JoinMenu::handleTimerComplete(int id) } break; }; -} \ No newline at end of file +} diff --git a/Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.cpp b/Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.cpp index 39bba779..f977ff91 100644 --- a/Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.cpp @@ -14,6 +14,7 @@ #include "..\..\TexturePackRepository.h" #include "..\..\TexturePack.h" #include "..\Network\SessionInfo.h" +#include "..\..\Common\Network\WinsockNetLayer.h" #if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) #include "Common\Network\Sony\SonyHttp.h" #include "Common\Network\Sony\SonyRemoteStorage.h" @@ -1385,20 +1386,24 @@ void UIScene_LoadOrJoinMenu::CheckAndJoinGame(int gameIndex) if( m_buttonListGames.getItemCount() > 0 && gameIndex < m_currentSessions->size() ) { #if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + const bool bManualJoin = (g_Win64MultiplayerJoin == true); // 4J-PB - is the player allowed to join games? bool noUGC=false; bool bContentRestricted=false; - // we're online, since we are joining a game - ProfileManager.GetChatAndContentRestrictions(m_iPad,true,&noUGC,&bContentRestricted,NULL); + // A direct LAN join should probnot use PSN matchmaking or account privileges (nansess) + if(!bManualJoin) + { + ProfileManager.GetChatAndContentRestrictions(m_iPad,true,&noUGC,&bContentRestricted,NULL); + } #ifdef __ORBIS__ // 4J Stu - On PS4 we don't restrict playing multiplayer based on chat restriction, so remove this check noUGC = false; bool bPlayStationPlus=true; - int iPadWithNoPlaystationPlus=0; - bool isSignedInLive = true; + int iPadWithNoPlaystationPlus=-1; + bool isSignedInLive = true; int iPadNotSignedInLive = -1; for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) { @@ -1414,6 +1419,7 @@ void UIScene_LoadOrJoinMenu::CheckAndJoinGame(int gameIndex) if(ProfileManager.HasPlayStationPlus(i)==false) { bPlayStationPlus=false; + iPadWithNoPlaystationPlus = (int)i; break; } } @@ -1427,7 +1433,7 @@ void UIScene_LoadOrJoinMenu::CheckAndJoinGame(int gameIndex) } #endif - if(noUGC) + if(!bManualJoin && noUGC) { // not allowed to join #ifndef __PSVITA__ @@ -1443,7 +1449,7 @@ void UIScene_LoadOrJoinMenu::CheckAndJoinGame(int gameIndex) m_bIgnoreInput=false; return; } - else if(bContentRestricted) + else if(!bManualJoin && bContentRestricted) { ui.RequestContentRestrictedMessageBox(); @@ -1452,7 +1458,7 @@ void UIScene_LoadOrJoinMenu::CheckAndJoinGame(int gameIndex) } #ifdef __ORBIS__ // If this is an online game but not all players are signed in to Live, stop! - else if (!isSignedInLive) + else if (!bManualJoin && !isSignedInLive) { UINT uiIDA[1]; uiIDA[0]=IDS_CONFIRM_OK; @@ -1471,7 +1477,7 @@ void UIScene_LoadOrJoinMenu::CheckAndJoinGame(int gameIndex) } return; } - else if(bPlayStationPlus==false) + else if(!bManualJoin && bPlayStationPlus==false) { if(ProfileManager.RequestingPlaystationPlus(iPadWithNoPlaystationPlus)) @@ -1480,6 +1486,7 @@ void UIScene_LoadOrJoinMenu::CheckAndJoinGame(int gameIndex) UINT uiIDA[1]; uiIDA[0]=IDS_OK; ui.RequestAlertMessage(IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, ProfileManager.GetPrimaryPad(), NULL, NULL); + m_bIgnoreInput=false; return; } diff --git a/Minecraft.Client/Common/UI/UIScene_MainMenu.cpp b/Minecraft.Client/Common/UI/UIScene_MainMenu.cpp index c9251291..2dff8e47 100644 --- a/Minecraft.Client/Common/UI/UIScene_MainMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_MainMenu.cpp @@ -8,6 +8,7 @@ #include "UIScene_MainMenu.h" #ifdef __ORBIS__ #include +#include "..\..\Common\Network\WinsockNetLayer.h" #endif Random *UIScene_MainMenu::random = new Random(); @@ -318,7 +319,17 @@ void UIScene_MainMenu::handlePress(F64 controlId, F64 childId) //CD - Added for audio ui.PlayUISFX(eSFX_Press); - ProfileManager.RefreshChatAndContentRestrictions(RefreshChatAndContentRestrictionsReturned_PlayGame, this); + if(g_Win64MultiplayerJoin) + { + // The LAN backend does not use PSN privileges. Do this before + // starting the asynchronous restriction refresh: while offline that + // request only completes after the platform network timeout. + CreateLoad_SignInReturned(this, true, primaryPad); + } + else + { + ProfileManager.RefreshChatAndContentRestrictions(RefreshChatAndContentRestrictionsReturned_PlayGame, this); + } } #else m_eAction=eAction_RunGame; @@ -1098,6 +1109,12 @@ void UIScene_MainMenu::RefreshChatAndContentRestrictionsReturned_PlayGame(void * int primaryPad = ProfileManager.GetPrimaryPad(); UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; + const bool bManualJoin = (g_Win64MultiplayerJoin == true); + if (bManualJoin) + { + CreateLoad_SignInReturned(pClass, true, primaryPad); + return; + } int (*signInReturnedFunc) (LPVOID,const bool, const int iPad) = NULL; diff --git a/Minecraft.Client/Minecraft.Client.vcxproj b/Minecraft.Client/Minecraft.Client.vcxproj index 50472670..0124434b 100644 --- a/Minecraft.Client/Minecraft.Client.vcxproj +++ b/Minecraft.Client/Minecraft.Client.vcxproj @@ -1015,7 +1015,8 @@ xcopy /q /y /i /s /e $(ProjectDir)DurangoMedia\CU $(LayoutDir)Image\Loose\CUfalse $(OutDir)$(ProjectName).pch MultiThreaded - _FINAL_BUILD;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64;%(PreprocessorDefinitions) + + _LARGE_WORLDS;_EXTENDED_ACHIEVEMENTS;_FINAL_BUILD;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64;%(PreprocessorDefinitions) Disabled Windows64\Iggy\include;$(ProjectDir);%(AdditionalIncludeDirectories) true @@ -36126,4 +36127,4 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU - \ No newline at end of file + diff --git a/Minecraft.Client/Orbis/OrbisExtras/OrbisStubs.cpp b/Minecraft.Client/Orbis/OrbisExtras/OrbisStubs.cpp index 1cc40be5..37924651 100644 --- a/Minecraft.Client/Orbis/OrbisExtras/OrbisStubs.cpp +++ b/Minecraft.Client/Orbis/OrbisExtras/OrbisStubs.cpp @@ -619,7 +619,6 @@ DWORD GetFileAttributesA(LPCSTR lpFileName) SceFiosStat statData; if(sceFiosStatSync(NULL, filePath, &statData) != SCE_FIOS_OK) { - app.DebugPrintf("*** sceFiosStatSync Failed\n"); return -1; } if(statData.statFlags & SCE_FIOS_STATUS_DIRECTORY ) @@ -671,19 +670,25 @@ BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount) #ifndef _FINAL_BUILD -VOID OutputDebugStringW(LPCWSTR lpOutputString) -{ - wprintf(lpOutputString); +VOID OutputDebugStringW(LPCWSTR lpOutputString) +{ + if (lpOutputString != NULL) + wprintf(L"%ls", lpOutputString); + fflush(stdout); } -VOID OutputDebugStringA(LPCSTR lpOutputString) -{ - printf(lpOutputString); +VOID OutputDebugStringA(LPCSTR lpOutputString) +{ + if (lpOutputString != NULL) + printf("%s", lpOutputString); + fflush(stdout); } -VOID OutputDebugString(LPCSTR lpOutputString) -{ - printf(lpOutputString); +VOID OutputDebugString(LPCSTR lpOutputString) +{ + if (lpOutputString != NULL) + printf("%s", lpOutputString); + fflush(stdout); } #endif // _CONTENT_PACKAGE @@ -787,4 +792,4 @@ DWORD XGetLocale() DWORD XEnableGuestSignin(BOOL fEnable) { return 0; -} \ No newline at end of file +} diff --git a/Minecraft.World/Minecraft.World.vcxproj b/Minecraft.World/Minecraft.World.vcxproj index f9105bc4..4d02015f 100644 --- a/Minecraft.World/Minecraft.World.vcxproj +++ b/Minecraft.World/Minecraft.World.vcxproj @@ -858,7 +858,7 @@ false $(OutDir)$(ProjectName).pch MultiThreaded - _FINAL_BUILD;_LIB;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64;%(PreprocessorDefinitions) + _LARGE_WORLDS;_EXTENDED_ACHIEVEMENTS;_FINAL_BUILD;_LIB;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64;%(PreprocessorDefinitions) Disabled true false