the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 2091 lines 70 kB view raw
1#include "stdafx.h" 2#include "..\..\..\Minecraft.World\StringHelpers.h" 3#include "..\..\..\Minecraft.World\AABB.h" 4#include "..\..\..\Minecraft.World\Vec3.h" 5#include "..\..\..\Minecraft.World\Socket.h" 6#include "..\..\..\Minecraft.World\ThreadName.h" 7#include "..\..\..\Minecraft.World\Entity.h" 8#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.h" 9#include "..\..\..\Minecraft.World\FireworksRecipe.h" 10#include "..\..\ClientConnection.h" 11#include "..\..\Minecraft.h" 12#include "..\..\User.h" 13#include "..\..\MinecraftServer.h" 14#include "..\..\PlayerList.h" 15#include "..\..\ServerPlayer.h" 16#include "..\..\PlayerConnection.h" 17#include "..\..\MultiPlayerLevel.h" 18#include "..\..\ProgressRenderer.h" 19#include "..\..\MultiPlayerLocalPlayer.h" 20#include "..\..\..\Minecraft.World\DisconnectPacket.h" 21#include "..\..\..\Minecraft.World\compression.h" 22#include "..\..\..\Minecraft.World\OldChunkStorage.h" 23#include "..\..\TexturePackRepository.h" 24#include "..\..\TexturePack.h" 25 26#include "..\..\Gui.h" 27#include "..\..\LevelRenderer.h" 28#include "..\..\..\Minecraft.World\IntCache.h" 29#include "..\GameRules\ConsoleGameRules.h" 30#include "GameNetworkManager.h" 31 32#ifdef _XBOX 33#include "Common\XUI\XUI_PauseMenu.h" 34#else 35#include "Common\UI\UI.h" 36#include "Common\UI\UIScene_PauseMenu.h" 37#include "..\..\Xbox\Network\NetworkPlayerXbox.h" 38#endif 39 40#ifdef _DURANGO 41#include "..\Minecraft.World\DurangoStats.h" 42#endif 43 44// Global instance 45CGameNetworkManager g_NetworkManager; 46CPlatformNetworkManager *CGameNetworkManager::s_pPlatformNetworkManager; 47 48__int64 CGameNetworkManager::messageQueue[512]; 49__int64 CGameNetworkManager::byteQueue[512]; 50int CGameNetworkManager::messageQueuePos = 0; 51 52CGameNetworkManager::CGameNetworkManager() 53{ 54 m_bInitialised = false; 55 m_bLastDisconnectWasLostRoomOnly = false; 56 m_bFullSessionMessageOnNextSessionChange = false; 57 58#ifdef __ORBIS__ 59 m_pUpsell = NULL; 60 m_pInviteInfo = NULL; 61#endif 62} 63 64void CGameNetworkManager::Initialise() 65{ 66 ServerStoppedCreate( false ); 67 ServerReadyCreate( false ); 68 int flagIndexSize = LevelRenderer::getGlobalChunkCount() / (Level::maxBuildHeight / 16); // dividing here by number of renderer chunks in one column 69#ifdef _XBOX 70 s_pPlatformNetworkManager = new CPlatformNetworkManagerXbox(); 71#elif defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ 72 s_pPlatformNetworkManager = new CPlatformNetworkManagerSony(); 73#elif defined _DURANGO 74 s_pPlatformNetworkManager = new CPlatformNetworkManagerDurango(); 75#else 76 s_pPlatformNetworkManager = new CPlatformNetworkManagerStub(); 77#endif 78 s_pPlatformNetworkManager->Initialise( this, flagIndexSize ); 79 m_bNetworkThreadRunning = false; 80 m_bInitialised = true; 81} 82 83void CGameNetworkManager::Terminate() 84{ 85 if( m_bInitialised ) 86 { 87 s_pPlatformNetworkManager->Terminate(); 88 } 89} 90 91void CGameNetworkManager::DoWork() 92{ 93#ifdef _XBOX 94 // did we get any notifications from the game listener? 95 if(app.GetNotifications()->size()!=0) 96 { 97 PNOTIFICATION pNotification=app.GetNotifications()->back(); 98 99 switch(pNotification->dwNotification) 100 { 101 case XN_LIVE_LINK_STATE_CHANGED: 102 { 103 int iPrimaryPlayer = g_NetworkManager.GetPrimaryPad(); 104 bool bConnected = (pNotification->uiParam!=0)?true:false; 105 if((g_NetworkManager.GetLockedProfile()!=-1) && iPrimaryPlayer!=-1 && bConnected == false && g_NetworkManager.IsInSession() ) 106 { 107 app.SetAction(iPrimaryPlayer,eAppAction_EthernetDisconnected); 108 } 109 } 110 break; 111 case XN_LIVE_INVITE_ACCEPTED: 112 s_pPlatformNetworkManager->Notify(pNotification->dwNotification,pNotification->uiParam); 113 break; 114 } 115 116 app.GetNotifications()->pop_back(); 117 delete pNotification; 118 } 119#endif 120 s_pPlatformNetworkManager->DoWork(); 121 122#ifdef __ORBIS__ 123 if (m_pUpsell != NULL && m_pUpsell->hasResponse()) 124 { 125 int iPad_invited = m_iPlayerInvited, iPad_checking = m_pUpsell->m_userIndex; 126 127 m_iPlayerInvited = -1; 128 129 delete m_pUpsell; 130 m_pUpsell = NULL; 131 132 if (ProfileManager.HasPlayStationPlus(iPad_checking)) 133 { 134 this->GameInviteReceived(iPad_invited, m_pInviteInfo); 135 136 // m_pInviteInfo deleted by GameInviteReceived. 137 m_pInviteInfo = NULL; 138 } 139 else 140 { 141 delete m_pInviteInfo; 142 m_pInviteInfo = NULL; 143 } 144 } 145#endif 146} 147 148bool CGameNetworkManager::_RunNetworkGame(LPVOID lpParameter) 149{ 150 bool success = true; 151 152 bool isHost = g_NetworkManager.IsHost(); 153 // Start the network game 154 Minecraft *pMinecraft=Minecraft::GetInstance(); 155 success = StartNetworkGame(pMinecraft,lpParameter); 156 157 if(!success) return false; 158 159 if( isHost ) 160 { 161 // We do not have a lobby, so the only players in the game at this point are local ones. 162 163 success = s_pPlatformNetworkManager->_RunNetworkGame(); 164 if(!success) 165 { 166 app.SetAction(ProfileManager.GetPrimaryPad(),eAppAction_ExitWorld,(void *)TRUE); 167 return true; 168 } 169 } 170 else 171 { 172 // Client needs QNET_STATE_GAME_PLAY so that IsInGameplay() returns true 173 s_pPlatformNetworkManager->SetGamePlayState(); 174 } 175 176 if( g_NetworkManager.IsLeavingGame() ) return false; 177 178 app.SetGameStarted(true); 179 180 // 4J-PB - if this is the trial game, start the trial timer 181 if(!ProfileManager.IsFullVersion()) 182 { 183 ui.SetTrialTimerLimitSecs(MinecraftDynamicConfigurations::GetTrialTime()); 184 app.SetTrialTimerStart(); 185 } 186 //app.CloseXuiScenes(ProfileManager.GetPrimaryPad()); 187 188 return success; 189} 190 191bool CGameNetworkManager::StartNetworkGame(Minecraft *minecraft, LPVOID lpParameter) 192{ 193#ifdef _DURANGO 194 ProfileManager.SetDeferredSignoutEnabled(true); 195#endif 196 197 __int64 seed = 0; 198 if(lpParameter != NULL) 199 { 200 NetworkGameInitData *param = (NetworkGameInitData *)lpParameter; 201 seed = param->seed; 202 203 app.setLevelGenerationOptions(param->levelGen); 204 if(param->levelGen != NULL) 205 { 206 if(app.getLevelGenerationOptions() == NULL) 207 { 208 app.DebugPrintf("Game rule was not loaded, and seed is required. Exiting.\n"); 209 return false; 210 } 211 else 212 { 213 param->seed = seed = app.getLevelGenerationOptions()->getLevelSeed(); 214 215 if(param->levelGen->isTutorial()) 216 { 217 // Load the tutorial save data here 218 if(param->levelGen->requiresBaseSave() && !param->levelGen->getBaseSavePath().empty() ) 219 { 220#ifdef _XBOX 221#ifdef _TU_BUILD 222 wstring fileRoot = L"UPDATE:\\res\\GameRules\\" + param->levelGen->getBaseSavePath(); 223#else 224 wstring fileRoot = L"GAME:\\res\\TitleUpdate\\GameRules\\" + param->levelGen->getBaseSavePath(); 225#endif 226#else 227#ifdef _WINDOWS64 228 wstring fileRoot = L"Windows64Media\\Tutorial\\" + param->levelGen->getBaseSavePath(); 229 File root(fileRoot); 230 if(!root.exists()) fileRoot = L"Windows64\\Tutorial\\" + param->levelGen->getBaseSavePath(); 231#elif defined(__ORBIS__) 232 wstring fileRoot = L"/app0/orbis/Tutorial/" + param->levelGen->getBaseSavePath(); 233#elif defined(__PSVITA__) 234 wstring fileRoot = L"PSVita/Tutorial/" + param->levelGen->getBaseSavePath(); 235#elif defined(__PS3__) 236 wstring fileRoot = L"PS3/Tutorial/" + param->levelGen->getBaseSavePath(); 237#else 238 wstring fileRoot = L"Tutorial\\" + param->levelGen->getBaseSavePath(); 239#endif 240#endif 241 File grf(fileRoot); 242 if (grf.exists()) 243 { 244#ifdef _UNICODE 245 wstring path = grf.getPath(); 246 const WCHAR *pchFilename=path.c_str(); 247 HANDLE fileHandle = CreateFile( 248 pchFilename, // file name 249 GENERIC_READ, // access mode 250 0, // share mode // TODO 4J Stu - Will we need to share file? Probably not but... 251 NULL, // Unused 252 OPEN_EXISTING , // how to create // TODO 4J Stu - Assuming that the file already exists if we are opening to read from it 253 FILE_FLAG_SEQUENTIAL_SCAN, // file attributes 254 NULL // Unsupported 255 ); 256#else 257 const char *pchFilename=wstringtofilename(grf.getPath()); 258 HANDLE fileHandle = CreateFile( 259 pchFilename, // file name 260 GENERIC_READ, // access mode 261 0, // share mode // TODO 4J Stu - Will we need to share file? Probably not but... 262 NULL, // Unused 263 OPEN_EXISTING , // how to create // TODO 4J Stu - Assuming that the file already exists if we are opening to read from it 264 FILE_FLAG_SEQUENTIAL_SCAN, // file attributes 265 NULL // Unsupported 266 ); 267#endif 268 269 if( fileHandle != INVALID_HANDLE_VALUE ) 270 { 271 DWORD bytesRead,dwFileSize = GetFileSize(fileHandle,NULL); 272 PBYTE pbData = (PBYTE) new BYTE[dwFileSize]; 273 BOOL bSuccess = ReadFile(fileHandle,pbData,dwFileSize,&bytesRead,NULL); 274 if(bSuccess==FALSE) 275 { 276 app.FatalLoadError(); 277 } 278 CloseHandle(fileHandle); 279 280 // 4J-PB - is it possible that we can get here after a read fail and it's not an error? 281 param->levelGen->setBaseSaveData(pbData, dwFileSize); 282 } 283 } 284 } 285 } 286 } 287 } 288 } 289 290 static __int64 sseed = seed; // Create static version so this will be valid until next call to this function & whilst thread is running 291 ServerStoppedCreate(false); 292 if( g_NetworkManager.IsHost() ) 293 { 294 ServerStoppedCreate(true); 295 ServerReadyCreate(true); 296 // Ready to go - create actual networking thread & start hosting 297 C4JThread* thread = new C4JThread(&CGameNetworkManager::ServerThreadProc, lpParameter, "Server", 256 * 1024); 298#if defined __PS3__ || defined __PSVITA__ 299 thread->SetPriority(THREAD_PRIORITY_BELOW_NORMAL); 300#endif //__PS3__ 301 302 thread->SetProcessor(CPU_CORE_SERVER); 303 thread->Run(); 304 305 ServerReadyWait(); 306 ServerReadyDestroy(); 307 308 if( MinecraftServer::serverHalted() ) 309 return false; 310 311// printf("Server ready to go!\n"); 312 } 313 else 314 { 315 Socket::Initialise(NULL); 316 } 317 318#ifndef _XBOX 319 Minecraft *pMinecraft = Minecraft::GetInstance(); 320 // Make sure that we have transitioned through any joining/creating stages and are actually playing the game, so that we know the players should be valid 321 bool changedMessage = false; 322 while(!IsReadyToPlayOrIdle()) 323 { 324 changedMessage = true; 325 pMinecraft->progressRenderer->progressStage( g_NetworkManager.CorrectErrorIDS(IDS_PROGRESS_SAVING_TO_DISC) ); // "Finalizing..." vaguest message I could find 326 pMinecraft->progressRenderer->progressStagePercentage( g_NetworkManager.GetJoiningReadyPercentage() ); 327 Sleep(10); 328 } 329 if( changedMessage ) 330 { 331 pMinecraft->progressRenderer->progressStagePercentage( 100 ); 332 } 333#endif 334 335 // If we aren't in session, then something bad must have happened - we aren't joining, creating or ready play 336 if(!IsInSession() ) 337 { 338 MinecraftServer::HaltServer(); 339 return false; 340 } 341 342 // 4J Stu - Wait a while to make sure that DLC is loaded. This is the last point before the network communication starts 343 // so the latest we can check this 344 while( !app.DLCInstallProcessCompleted() && app.DLCInstallPending() && !g_NetworkManager.IsLeavingGame() ) 345 { 346 Sleep( 10 ); 347 } 348 if( g_NetworkManager.IsLeavingGame() ) 349 { 350 MinecraftServer::HaltServer(); 351 return false; 352 } 353 354 // PRIMARY PLAYER 355 356 vector<ClientConnection *> createdConnections; 357 ClientConnection *connection; 358 359 if( g_NetworkManager.IsHost() ) 360 { 361 connection = new ClientConnection(minecraft, NULL); 362 } 363 else 364 { 365 INetworkPlayer *pNetworkPlayer = g_NetworkManager.GetLocalPlayerByUserIndex(ProfileManager.GetLockedProfile()); 366 if(pNetworkPlayer == NULL) 367 { 368 MinecraftServer::HaltServer(); 369 app.DebugPrintf("%d\n",ProfileManager.GetLockedProfile()); 370 // If the player is NULL here then something went wrong in the session setup, and continuing will end up in a crash 371 return false; 372 } 373 374 Socket *socket = pNetworkPlayer->GetSocket(); 375 376 // Fix for #13259 - CRASH: Gameplay: loading process is halted when player loads saved data 377 if(socket == NULL) 378 { 379 assert(false); 380 MinecraftServer::HaltServer(); 381 // If the socket is NULL here then something went wrong in the session setup, and continuing will end up in a crash 382 return false; 383 } 384 385 connection = new ClientConnection(minecraft, socket); 386 } 387 388 if( !connection->createdOk ) 389 { 390 assert(false); 391 delete connection; 392 connection = NULL; 393 MinecraftServer::HaltServer(); 394 return false; 395 } 396 397 connection->send( shared_ptr<PreLoginPacket>( new PreLoginPacket(minecraft->user->name) ) ); 398 399 // Tick connection until we're ready to go. The stages involved in this are: 400 // (1) Creating the ClientConnection sends a prelogin packet to the server 401 // (2) the server sends a prelogin back, which is handled by the clientConnection, and returns a login packet 402 // (3) the server sends a login back, which is handled by the client connection to start the game 403 if( !g_NetworkManager.IsHost() ) 404 { 405 Minecraft::GetInstance()->progressRenderer->progressStart(IDS_PROGRESS_CONNECTING); 406 } 407 else 408 { 409 // 4J Stu - Host needs to generate a unique multiplayer id for sentient telemetry reporting 410 INT multiplayerInstanceId = TelemetryManager->GenerateMultiplayerInstanceId(); 411 TelemetryManager->SetMultiplayerInstanceId(multiplayerInstanceId); 412 } 413 TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); 414 do 415 { 416 app.DebugPrintf("ticking connection A\n"); 417 connection->tick(); 418 419 // 4J Stu - We were ticking this way too fast which could cause the connection to time out 420 // The connections should tick at 20 per second 421 Sleep(50); 422 } while ( (IsInSession() && !connection->isStarted() && !connection->isClosed() && !g_NetworkManager.IsLeavingGame()) || tPack->isLoadingData() || (Minecraft::GetInstance()->skins->needsUIUpdate() || ui.IsReloadingSkin()) ); 423 ui.CleanUpSkinReload(); 424 425 // 4J Stu - Fix for #11279 - CRASH: TCR 001: BAS Game Stability: Signing out of game will cause title to crash 426 // We need to break out of the above loop if m_bLeavingGame is set, and close the connection 427 if( g_NetworkManager.IsLeavingGame() || !IsInSession() ) 428 { 429 connection->close(); 430 } 431 432 if( connection->isStarted() && !connection->isClosed() ) 433 { 434 createdConnections.push_back( connection ); 435 436 int primaryPad = ProfileManager.GetPrimaryPad(); 437 app.SetRichPresenceContext(primaryPad,CONTEXT_GAME_STATE_BLANK); 438 if (GetPlayerCount() > 1) // Are we offline or online, and how many players are there 439 { 440 if (IsLocalGame()) ProfileManager.SetCurrentGameActivity(primaryPad,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false); 441 else ProfileManager.SetCurrentGameActivity(primaryPad,CONTEXT_PRESENCE_MULTIPLAYER,false); 442 } 443 else 444 { 445 if(IsLocalGame()) ProfileManager.SetCurrentGameActivity(primaryPad,CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE,false); 446 else ProfileManager.SetCurrentGameActivity(primaryPad,CONTEXT_PRESENCE_MULTIPLAYER_1P,false); 447 } 448 449 450 // ALL OTHER LOCAL PLAYERS 451 for(int idx = 0; idx < XUSER_MAX_COUNT; ++idx) 452 { 453 // Already have setup the primary pad 454 if(idx == ProfileManager.GetPrimaryPad() ) continue; 455 456 if( GetLocalPlayerByUserIndex(idx) != NULL && !ProfileManager.IsSignedIn(idx) ) 457 { 458 INetworkPlayer *pNetworkPlayer = g_NetworkManager.GetLocalPlayerByUserIndex(idx); 459 Socket *socket = pNetworkPlayer->GetSocket(); 460 app.DebugPrintf("Closing socket due to player %d not being signed in any more\n"); 461 if( !socket->close(false) ) socket->close(true); 462 463 continue; 464 } 465 466 // By default when we host we only have the local player, but currently allow multiple local players to join 467 // when joining any other way, so just because they are signed in doesn't mean they are in the session 468 // 4J Stu - If they are in the session, then we should add them to the game. Otherwise we won't be able to add them later 469 INetworkPlayer *pNetworkPlayer = g_NetworkManager.GetLocalPlayerByUserIndex(idx); 470 if( pNetworkPlayer == NULL ) 471 continue; 472 473 ClientConnection *connection; 474 475 Socket *socket = pNetworkPlayer->GetSocket(); 476 connection = new ClientConnection(minecraft, socket, idx); 477 478 minecraft->addPendingLocalConnection(idx, connection); 479 //minecraft->createExtraLocalPlayer(idx, (convStringToWstring( ProfileManager.GetGamertag(idx) )).c_str(), idx, connection); 480 481 // Open the socket on the server end to accept incoming data 482 Socket::addIncomingSocket(socket); 483 484 connection->send( shared_ptr<PreLoginPacket>( new PreLoginPacket(convStringToWstring( ProfileManager.GetGamertag(idx) )) ) ); 485 486 createdConnections.push_back( connection ); 487 488 // Tick connection until we're ready to go. The stages involved in this are: 489 // (1) Creating the ClientConnection sends a prelogin packet to the server 490 // (2) the server sends a prelogin back, which is handled by the clientConnection, and returns a login packet 491 // (3) the server sends a login back, which is handled by the client connection to start the game 492 do 493 { 494 // We need to keep ticking the connections for players that already logged in 495 for(AUTO_VAR(it, createdConnections.begin()); it < createdConnections.end(); ++it) 496 { 497 (*it)->tick(); 498 } 499 500 // 4J Stu - We were ticking this way too fast which could cause the connection to time out 501 // The connections should tick at 20 per second 502 Sleep(50); 503 app.DebugPrintf("<***> %d %d %d %d %d\n",IsInSession(), !connection->isStarted(),!connection->isClosed(),ProfileManager.IsSignedIn(idx),!g_NetworkManager.IsLeavingGame()); 504#if defined _XBOX || __PS3__ 505 } while (IsInSession() && !connection->isStarted() && !connection->isClosed() && ProfileManager.IsSignedIn(idx) && !g_NetworkManager.IsLeavingGame() ); 506#else 507 // TODO - This SHOULD be something just like the code above but temporarily changing here so that we don't have to depend on the profilemanager behaviour 508 } while (IsInSession() && !connection->isStarted() && !connection->isClosed() && !g_NetworkManager.IsLeavingGame() ); 509#endif 510 511 // 4J Stu - Fix for #11279 - CRASH: TCR 001: BAS Game Stability: Signing out of game will cause title to crash 512 // We need to break out of the above loop if m_bLeavingGame is set, and stop creating new connections 513 // The connections in the createdConnections vector get closed at the end of the thread 514 if( g_NetworkManager.IsLeavingGame() || !IsInSession() ) break; 515 516 if( ProfileManager.IsSignedIn(idx) && !connection->isClosed() ) 517 { 518 app.SetRichPresenceContext(idx,CONTEXT_GAME_STATE_BLANK); 519 if (IsLocalGame()) ProfileManager.SetCurrentGameActivity(idx,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false); 520 else ProfileManager.SetCurrentGameActivity(idx,CONTEXT_PRESENCE_MULTIPLAYER,false); 521 } 522 else 523 { 524 connection->close(); 525 AUTO_VAR(it, find( createdConnections.begin(), createdConnections.end(), connection )); 526 if(it != createdConnections.end() ) createdConnections.erase( it ); 527 } 528 } 529 530 app.SetGameMode( eMode_Multiplayer ); 531 } 532 else if ( connection->isClosed() || !IsInSession()) 533 { 534// assert(false); 535 MinecraftServer::HaltServer(); 536 return false; 537 } 538 539 540 if(g_NetworkManager.IsLeavingGame() || !IsInSession() ) 541 { 542 for(AUTO_VAR(it, createdConnections.begin()); it < createdConnections.end(); ++it) 543 { 544 (*it)->close(); 545 } 546// assert(false); 547 MinecraftServer::HaltServer(); 548 return false; 549 } 550 551 // Catch in-case server has been halted (by a player signout). 552 if ( MinecraftServer::serverHalted() ) 553 return false; 554 555 return true; 556} 557 558int CGameNetworkManager::CorrectErrorIDS(int IDS) 559{ 560 return s_pPlatformNetworkManager->CorrectErrorIDS(IDS); 561} 562 563int CGameNetworkManager::GetLocalPlayerMask(int playerIndex) 564{ 565 return s_pPlatformNetworkManager->GetLocalPlayerMask( playerIndex ); 566} 567 568int CGameNetworkManager::GetPlayerCount() 569{ 570 return s_pPlatformNetworkManager->GetPlayerCount(); 571} 572 573int CGameNetworkManager::GetOnlinePlayerCount() 574{ 575 return s_pPlatformNetworkManager->GetOnlinePlayerCount(); 576} 577 578bool CGameNetworkManager::AddLocalPlayerByUserIndex( int userIndex ) 579{ 580 return s_pPlatformNetworkManager->AddLocalPlayerByUserIndex( userIndex ); 581} 582 583bool CGameNetworkManager::RemoveLocalPlayerByUserIndex( int userIndex ) 584{ 585 return s_pPlatformNetworkManager->RemoveLocalPlayerByUserIndex( userIndex ); 586} 587 588INetworkPlayer *CGameNetworkManager::GetLocalPlayerByUserIndex(int userIndex ) 589{ 590 return s_pPlatformNetworkManager->GetLocalPlayerByUserIndex( userIndex ); 591} 592 593INetworkPlayer *CGameNetworkManager::GetPlayerByIndex(int playerIndex) 594{ 595 return s_pPlatformNetworkManager->GetPlayerByIndex( playerIndex ); 596} 597 598INetworkPlayer *CGameNetworkManager::GetPlayerByXuid(PlayerUID xuid) 599{ 600 return s_pPlatformNetworkManager->GetPlayerByXuid( xuid ); 601} 602 603INetworkPlayer *CGameNetworkManager::GetPlayerBySmallId(unsigned char smallId) 604{ 605 return s_pPlatformNetworkManager->GetPlayerBySmallId( smallId ); 606} 607 608#ifdef _DURANGO 609wstring CGameNetworkManager::GetDisplayNameByGamertag(wstring gamertag) 610{ 611 return s_pPlatformNetworkManager->GetDisplayNameByGamertag(gamertag); 612} 613#endif 614 615INetworkPlayer *CGameNetworkManager::GetHostPlayer() 616{ 617 return s_pPlatformNetworkManager->GetHostPlayer(); 618} 619 620void CGameNetworkManager::RegisterPlayerChangedCallback(int iPad, void (*callback)(void *callbackParam, INetworkPlayer *pPlayer, bool leaving), void *callbackParam) 621{ 622 s_pPlatformNetworkManager->RegisterPlayerChangedCallback( iPad, callback, callbackParam ); 623} 624 625void CGameNetworkManager::UnRegisterPlayerChangedCallback(int iPad, void (*callback)(void *callbackParam, INetworkPlayer *pPlayer, bool leaving), void *callbackParam) 626{ 627 s_pPlatformNetworkManager->UnRegisterPlayerChangedCallback( iPad, callback, callbackParam ); 628} 629 630void CGameNetworkManager::HandleSignInChange() 631{ 632 s_pPlatformNetworkManager->HandleSignInChange(); 633} 634 635bool CGameNetworkManager::ShouldMessageForFullSession() 636{ 637 return s_pPlatformNetworkManager->ShouldMessageForFullSession(); 638} 639 640bool CGameNetworkManager::IsInSession() 641{ 642 return s_pPlatformNetworkManager->IsInSession(); 643} 644 645bool CGameNetworkManager::IsInGameplay() 646{ 647 return s_pPlatformNetworkManager->IsInGameplay(); 648} 649 650bool CGameNetworkManager::IsReadyToPlayOrIdle() 651{ 652 return s_pPlatformNetworkManager->IsReadyToPlayOrIdle(); 653} 654 655bool CGameNetworkManager::IsLeavingGame() 656{ 657 return s_pPlatformNetworkManager->IsLeavingGame(); 658} 659 660bool CGameNetworkManager::SetLocalGame(bool isLocal) 661{ 662 return s_pPlatformNetworkManager->SetLocalGame( isLocal ); 663} 664 665bool CGameNetworkManager::IsLocalGame() 666{ 667 return s_pPlatformNetworkManager->IsLocalGame(); 668} 669 670void CGameNetworkManager::SetPrivateGame(bool isPrivate) 671{ 672 s_pPlatformNetworkManager->SetPrivateGame( isPrivate ); 673} 674 675bool CGameNetworkManager::IsPrivateGame() 676{ 677 return s_pPlatformNetworkManager->IsPrivateGame(); 678} 679 680void CGameNetworkManager::HostGame(int localUsersMask, bool bOnlineGame, bool bIsPrivate, unsigned char publicSlots, unsigned char privateSlots) 681{ 682 // 4J Stu - clear any previous connection errors 683 Minecraft::GetInstance()->clearConnectionFailed(); 684 685 s_pPlatformNetworkManager->HostGame( localUsersMask, bOnlineGame, bIsPrivate, publicSlots, privateSlots ); 686} 687 688bool CGameNetworkManager::IsHost() 689{ 690 return (s_pPlatformNetworkManager->IsHost() == TRUE); 691} 692 693bool CGameNetworkManager::IsInStatsEnabledSession() 694{ 695 return s_pPlatformNetworkManager->IsInStatsEnabledSession(); 696} 697 698bool CGameNetworkManager::SessionHasSpace(unsigned int spaceRequired) 699{ 700 return s_pPlatformNetworkManager->SessionHasSpace( spaceRequired ); 701} 702 703vector<FriendSessionInfo *> *CGameNetworkManager::GetSessionList(int iPad, int localPlayers, bool partyOnly) 704{ 705 return s_pPlatformNetworkManager->GetSessionList( iPad, localPlayers, partyOnly ); 706} 707 708bool CGameNetworkManager::GetGameSessionInfo(int iPad, SessionID sessionId,FriendSessionInfo *foundSession) 709{ 710 return s_pPlatformNetworkManager->GetGameSessionInfo( iPad, sessionId, foundSession ); 711} 712 713void CGameNetworkManager::SetSessionsUpdatedCallback( void (*SessionsUpdatedCallback)(LPVOID pParam), LPVOID pSearchParam ) 714{ 715 s_pPlatformNetworkManager->SetSessionsUpdatedCallback( SessionsUpdatedCallback, pSearchParam ); 716} 717 718void CGameNetworkManager::GetFullFriendSessionInfo( FriendSessionInfo *foundSession, void (* FriendSessionUpdatedFn)(bool success, void *pParam), void *pParam ) 719{ 720 s_pPlatformNetworkManager->GetFullFriendSessionInfo(foundSession, FriendSessionUpdatedFn, pParam); 721} 722 723void CGameNetworkManager::ForceFriendsSessionRefresh() 724{ 725 s_pPlatformNetworkManager->ForceFriendsSessionRefresh(); 726} 727 728bool CGameNetworkManager::JoinGameFromInviteInfo( int userIndex, int userMask, const INVITE_INFO *pInviteInfo) 729{ 730 return s_pPlatformNetworkManager->JoinGameFromInviteInfo( userIndex, userMask, pInviteInfo ); 731} 732 733CGameNetworkManager::eJoinGameResult CGameNetworkManager::JoinGame(FriendSessionInfo *searchResult, int localUsersMask) 734{ 735 app.SetTutorialMode( false ); 736 g_NetworkManager.SetLocalGame(false); 737 738 int primaryUserIndex = ProfileManager.GetLockedProfile(); 739 740 // 4J-PB - clear any previous connection errors 741 Minecraft::GetInstance()->clearConnectionFailed(); 742 743 // Make sure that the Primary Pad is in by default 744 localUsersMask |= GetLocalPlayerMask( ProfileManager.GetPrimaryPad() ); 745 746 return (eJoinGameResult)(s_pPlatformNetworkManager->JoinGame( searchResult, localUsersMask, primaryUserIndex )); 747} 748 749void CGameNetworkManager::CancelJoinGame(LPVOID lpParam) 750{ 751#ifdef _XBOX_ONE 752 s_pPlatformNetworkManager->CancelJoinGame(); 753#endif 754} 755 756bool CGameNetworkManager::LeaveGame(bool bMigrateHost) 757{ 758 Minecraft::GetInstance()->gui->clearMessages(); 759 return s_pPlatformNetworkManager->LeaveGame( bMigrateHost ); 760} 761 762int CGameNetworkManager::JoinFromInvite_SignInReturned(void *pParam,bool bContinue, int iPad) 763{ 764 INVITE_INFO * pInviteInfo = (INVITE_INFO *)pParam; 765 766 if(bContinue==true) 767 { 768#ifdef __ORBIS__ 769 // Check if PSN is unavailable because of age restriction 770 int npAvailability = ProfileManager.getNPAvailability(iPad); 771 if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) 772 { 773 UINT uiIDA[1]; 774 uiIDA[0] = IDS_OK; 775 ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPad); 776 777 return 0; 778 } 779#endif 780 781 app.DebugPrintf("JoinFromInvite_SignInReturned, iPad %d\n",iPad); 782 // It's possible that the player has not signed in - they can back out 783 if(ProfileManager.IsSignedIn(iPad) && ProfileManager.IsSignedInLive(iPad) ) 784 { 785 app.DebugPrintf("JoinFromInvite_SignInReturned, passed sign-in tests\n"); 786 int localUsersMask = 0; 787 int joiningUsers = 0; 788 789 bool noPrivileges = false; 790 for(unsigned int index = 0; index < XUSER_MAX_COUNT; ++index) 791 { 792 if(ProfileManager.IsSignedIn(index) ) 793 { 794 ++joiningUsers; 795 if( !ProfileManager.AllowedToPlayMultiplayer(index) ) noPrivileges = true; 796 localUsersMask |= GetLocalPlayerMask( index ); 797 } 798 } 799 800 // Check if user-created content is allowed, as we cannot play multiplayer if it's not 801 bool noUGC = false; 802#if defined(__PS3__) || defined(__PSVITA__) 803 ProfileManager.GetChatAndContentRestrictions(iPad,false,&noUGC,NULL,NULL); 804#elif defined(__ORBIS__) 805 ProfileManager.GetChatAndContentRestrictions(iPad,false,NULL,&noUGC,NULL); 806#endif 807 808 if(noUGC) 809 { 810 int messageText = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL; 811 if(joiningUsers > 1) messageText = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL; 812 813 ui.RequestUGCMessageBox(IDS_CONNECTION_FAILED, messageText); 814 } 815 else if(noPrivileges) 816 { 817 UINT uiIDA[1]; 818 uiIDA[0]=IDS_CONFIRM_OK; 819 ui.RequestErrorMessage( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad()); 820 } 821 else 822 { 823#if defined(__ORBIS__) || defined(__PSVITA__) 824 bool chatRestricted = false; 825 ProfileManager.GetChatAndContentRestrictions(iPad,false,&chatRestricted,NULL,NULL); 826 if(chatRestricted) 827 { 828 ProfileManager.DisplaySystemMessage( 0, ProfileManager.GetPrimaryPad() ); 829 } 830#endif 831 ProfileManager.SetLockedProfile(iPad); 832 ProfileManager.SetPrimaryPad(iPad); 833 834 g_NetworkManager.SetLocalGame(false); 835 836 // If the player was signed in before selecting play, we'll not have read the profile yet, so query the sign-in status to get this to happen 837 ProfileManager.QuerySigninStatus(); 838 839 // 4J-PB - clear any previous connection errors 840 Minecraft::GetInstance()->clearConnectionFailed(); 841 842 // change the minecraft player name 843 Minecraft::GetInstance()->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); 844 845 bool success = g_NetworkManager.JoinGameFromInviteInfo( 846 iPad, // dwUserIndex 847 localUsersMask, // dwUserMask 848 pInviteInfo ); // pInviteInfo 849 if( !success ) 850 { 851 app.DebugPrintf( "Failed joining game from invite\n" ); 852 } 853 } 854 } 855 else 856 { 857 app.DebugPrintf("JoinFromInvite_SignInReturned, failed sign-in tests :%d %d\n",ProfileManager.IsSignedIn(iPad),ProfileManager.IsSignedInLive(iPad)); 858 } 859 } 860 return 0; 861 862} 863 864void CGameNetworkManager::UpdateAndSetGameSessionData(INetworkPlayer *pNetworkPlayerLeaving) 865{ 866 Minecraft *pMinecraft = Minecraft::GetInstance(); 867 TexturePack *tPack = pMinecraft->skins->getSelected(); 868 s_pPlatformNetworkManager->SetSessionTexturePackParentId( tPack->getDLCParentPackId() ); 869 s_pPlatformNetworkManager->SetSessionSubTexturePackId( tPack->getDLCSubPackId() ); 870 871 s_pPlatformNetworkManager->UpdateAndSetGameSessionData( pNetworkPlayerLeaving ); 872} 873 874void CGameNetworkManager::SendInviteGUI(int quadrant) 875{ 876 s_pPlatformNetworkManager->SendInviteGUI(quadrant); 877} 878 879void CGameNetworkManager::ResetLeavingGame() 880{ 881 s_pPlatformNetworkManager->ResetLeavingGame(); 882} 883 884bool CGameNetworkManager::IsNetworkThreadRunning() 885{ 886 return m_bNetworkThreadRunning;; 887} 888 889int CGameNetworkManager::RunNetworkGameThreadProc( void* lpParameter ) 890{ 891 // Share AABB & Vec3 pools with default (main thread) - should be ok as long as we don't tick the main thread whilst this thread is running 892 AABB::UseDefaultThreadStorage(); 893 Vec3::UseDefaultThreadStorage(); 894 Compression::UseDefaultThreadStorage(); 895 Tile::CreateNewThreadStorage(); 896 IntCache::CreateNewThreadStorage(); 897 898 g_NetworkManager.m_bNetworkThreadRunning = true; 899 bool success = g_NetworkManager._RunNetworkGame(lpParameter); 900 g_NetworkManager.m_bNetworkThreadRunning = false; 901 if( !success) 902 { 903 TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); 904 while ( tPack->isLoadingData() || (Minecraft::GetInstance()->skins->needsUIUpdate() || ui.IsReloadingSkin()) ) 905 { 906 Sleep(1); 907 } 908 ui.CleanUpSkinReload(); 909 if(app.GetDisconnectReason() == DisconnectPacket::eDisconnect_None) 910 { 911 app.SetDisconnectReason( DisconnectPacket::eDisconnect_ConnectionCreationFailed ); 912 } 913 // If we failed before the server started, clear the game rules. Otherwise the server will clear it up. 914 if(MinecraftServer::getInstance() == NULL) app.m_gameRules.unloadCurrentGameRules(); 915 Tile::ReleaseThreadStorage(); 916 return -1; 917 } 918 919#ifdef __PSVITA__ 920 // 4J-JEV: Wait for the loading/saving to finish. 921 while (StorageManager.GetSaveState() != C4JStorage::ESaveGame_Idle) Sleep(10); 922#endif 923 924 Tile::ReleaseThreadStorage(); 925 IntCache::ReleaseThreadStorage(); 926 return 0; 927} 928 929int CGameNetworkManager::ServerThreadProc( void* lpParameter ) 930{ 931 __int64 seed = 0; 932 if(lpParameter != NULL) 933 { 934 NetworkGameInitData *param = (NetworkGameInitData *)lpParameter; 935 seed = param->seed; 936 app.SetGameHostOption(eGameHostOption_All,param->settings); 937 938 // 4J Stu - If we are loading a DLC save that's separate from the texture pack, load 939 if( param->levelGen != NULL && (param->texturePackId == 0 || param->levelGen->getRequiredTexturePackId() != param->texturePackId) ) 940 { 941 while((Minecraft::GetInstance()->skins->needsUIUpdate() || ui.IsReloadingSkin())) 942 { 943 Sleep(1); 944 } 945 param->levelGen->loadBaseSaveData(); 946 } 947 } 948 949 SetThreadName(-1, "Minecraft Server thread"); 950 AABB::CreateNewThreadStorage(); 951 Vec3::CreateNewThreadStorage(); 952 IntCache::CreateNewThreadStorage(); 953 Compression::UseDefaultThreadStorage(); 954 OldChunkStorage::UseDefaultThreadStorage(); 955 Entity::useSmallIds(); 956 Level::enableLightingCache(); 957 Tile::CreateNewThreadStorage(); 958 FireworksRecipe::CreateNewThreadStorage(); 959 960 MinecraftServer::main(seed, lpParameter); //saveData, app.GetGameHostOption(eGameHostOption_All)); 961 962 Tile::ReleaseThreadStorage(); 963 AABB::ReleaseThreadStorage(); 964 Vec3::ReleaseThreadStorage(); 965 IntCache::ReleaseThreadStorage(); 966 Level::destroyLightingCache(); 967 968 if(lpParameter != NULL) delete lpParameter; 969 970 return S_OK; 971} 972 973int CGameNetworkManager::ExitAndJoinFromInviteThreadProc( void* lpParam ) 974{ 975 // Share AABB & Vec3 pools with default (main thread) - should be ok as long as we don't tick the main thread whilst this thread is running 976 AABB::UseDefaultThreadStorage(); 977 Vec3::UseDefaultThreadStorage(); 978 Compression::UseDefaultThreadStorage(); 979 980 //app.SetGameStarted(false); 981 UIScene_PauseMenu::_ExitWorld(NULL); 982 983 while( g_NetworkManager.IsInSession() ) 984 { 985 Sleep(1); 986 } 987 988 // Xbox should always be online when receiving invites - on PS3 we need to check & ask the user to sign in 989#if !defined(__PS3__) && !defined(__PSVITA__) 990 JoinFromInviteData *inviteData = (JoinFromInviteData *)lpParam; 991 app.SetAction(inviteData->dwUserIndex, eAppAction_JoinFromInvite, lpParam); 992#else 993 if(ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad())) 994 { 995 JoinFromInviteData *inviteData = (JoinFromInviteData *)lpParam; 996 app.SetAction(inviteData->dwUserIndex, eAppAction_JoinFromInvite, lpParam); 997 } 998 else 999 { 1000 UINT uiIDA[2]; 1001 uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; 1002 uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; 1003 ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CGameNetworkManager::MustSignInReturned_0,lpParam); 1004 } 1005#endif 1006 1007 return S_OK; 1008} 1009 1010#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__ 1011// This case happens when we have been returned from the game to the main menu after receiving an invite and are now trying to go back in to join the new game 1012// The pair of methods MustSignInReturned_0 & PSNSignInReturned_0 handle this 1013int CGameNetworkManager::MustSignInReturned_0(void *pParam,int iPad,C4JStorage::EMessageResult result) 1014{ 1015 if(result==C4JStorage::EMessage_ResultAccept) 1016 { 1017#ifdef __PS3__ 1018 SQRNetworkManager_PS3::AttemptPSNSignIn(&CGameNetworkManager::PSNSignInReturned_0, pParam,true); 1019#elif defined __PSVITA__ 1020 SQRNetworkManager_Vita::AttemptPSNSignIn(&CGameNetworkManager::PSNSignInReturned_0, pParam,true); 1021#elif defined __ORBIS__ 1022 SQRNetworkManager_Orbis::AttemptPSNSignIn(&CGameNetworkManager::PSNSignInReturned_0, pParam,true); 1023#endif 1024 } 1025 else 1026 { 1027 app.SetAction(0,eAppAction_Idle); 1028 ui.NavigateToHomeMenu(); 1029 ui.UpdatePlayerBasePositions(); 1030 } 1031 1032 return 0; 1033} 1034 1035int CGameNetworkManager::PSNSignInReturned_0(void* pParam, bool bContinue, int iPad) 1036{ 1037 JoinFromInviteData *inviteData = (JoinFromInviteData *)pParam; 1038 1039 // If the invite data isn't set up yet (indicated by it being all zeroes, easiest detected via the net version), then try and get it again... this can happen if we got 1040 // the invite whilst signed out 1041 1042 if( bContinue ) 1043 { 1044 if(inviteData->pInviteInfo->netVersion == 0) 1045 { 1046#if defined __PS3__ || defined __VITA__ 1047 if(!SQRNetworkManager_PS3::UpdateInviteData((SQRNetworkManager::PresenceSyncInfo *)inviteData->pInviteInfo)) 1048 { 1049 bContinue = false; 1050 } 1051#elif defined __ORBIS__ 1052 // TODO: No Orbis equivalent (should there be?) 1053#endif 1054 } 1055 } 1056 1057 if( bContinue ) 1058 { 1059 app.SetAction(inviteData->dwUserIndex, eAppAction_JoinFromInvite, pParam); 1060 } 1061 else 1062 { 1063 app.SetAction(inviteData->dwUserIndex,eAppAction_Idle); 1064 ui.NavigateToHomeMenu(); 1065 ui.UpdatePlayerBasePositions(); 1066 } 1067 1068 return 0; 1069} 1070 1071// This case happens when we were in the main menus when we got an invite, and weren't signed in... now can proceed with the normal flow of code for this situation 1072// The pair of methods MustSignInReturned_1 & PSNSignInReturned_1 handle this 1073int CGameNetworkManager::MustSignInReturned_1(void *pParam,int iPad,C4JStorage::EMessageResult result) 1074{ 1075 if(result==C4JStorage::EMessage_ResultAccept) 1076 { 1077#ifdef __PS3__ 1078 SQRNetworkManager_PS3::AttemptPSNSignIn(&CGameNetworkManager::PSNSignInReturned_1, pParam,true); 1079#elif defined __PSVITA__ 1080 SQRNetworkManager_Vita::AttemptPSNSignIn(&CGameNetworkManager::PSNSignInReturned_1, pParam,true); 1081#elif defined __ORBIS__ 1082 SQRNetworkManager_Orbis::AttemptPSNSignIn(&CGameNetworkManager::PSNSignInReturned_1, pParam,true); 1083#endif 1084 } 1085 return 0; 1086} 1087 1088int CGameNetworkManager::PSNSignInReturned_1(void* pParam, bool bContinue, int iPad) 1089{ 1090 INVITE_INFO *inviteInfo = (INVITE_INFO *)pParam; 1091 1092 // If the invite data isn't set up yet (indicated by it being all zeroes, easiest detected via the net version), then try and get it again... this can happen if we got 1093 // the invite whilst signed out 1094 1095 if( bContinue ) 1096 { 1097 if(inviteInfo->netVersion == 0) 1098 { 1099#if defined __PS3__ || defined __VITA__ 1100 if(!SQRNetworkManager_PS3::UpdateInviteData((SQRNetworkManager::PresenceSyncInfo *)inviteInfo)) 1101 { 1102 bContinue = false; 1103 } 1104#elif defined __ORBIS__ 1105 // TODO: No Orbis equivalent (should there be?) 1106#endif 1107 1108 } 1109 } 1110 1111 if( bContinue ) 1112 { 1113 g_NetworkManager.HandleInviteWhenInMenus(0, inviteInfo); 1114 } 1115 1116 return 0; 1117} 1118#endif 1119 1120void CGameNetworkManager::_LeaveGame() 1121{ 1122 s_pPlatformNetworkManager->_LeaveGame(false, true); 1123} 1124 1125int CGameNetworkManager::ChangeSessionTypeThreadProc( void* lpParam ) 1126{ 1127 // Share AABB & Vec3 pools with default (main thread) - should be ok as long as we don't tick the main thread whilst this thread is running 1128 AABB::UseDefaultThreadStorage(); 1129 Vec3::UseDefaultThreadStorage(); 1130 Compression::UseDefaultThreadStorage(); 1131 1132 Minecraft *pMinecraft = Minecraft::GetInstance(); 1133 MinecraftServer *pServer = MinecraftServer::getInstance(); 1134 1135#if defined(__PS3__) || defined(__ORBIS__) || defined __PSVITA__ 1136 UINT uiIDA[1]; 1137 uiIDA[0]=IDS_CONFIRM_OK; 1138 if( g_NetworkManager.m_bLastDisconnectWasLostRoomOnly ) 1139 { 1140 if(g_NetworkManager.m_bSignedOutofPSN) 1141 { 1142 C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME, IDS_ERROR_PSN_SIGN_OUT, uiIDA,1,ProfileManager.GetPrimaryPad()); 1143 } 1144 else 1145 { 1146 C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_ERROR_NETWORK_TITLE, IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME, uiIDA,1,ProfileManager.GetPrimaryPad()); 1147 } 1148 } 1149 else 1150 { 1151 C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_CONNECTION_LOST, g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT), uiIDA,1,ProfileManager.GetPrimaryPad()); 1152 } 1153 1154 // Swap these two messages around as one is too long to display at 480 1155 pMinecraft->progressRenderer->progressStartNoAbort( IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME ); 1156 pMinecraft->progressRenderer->progressStage( -1 ); //g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT) ); 1157#elif defined(_XBOX_ONE) 1158 if( g_NetworkManager.m_bFullSessionMessageOnNextSessionChange ) 1159 { 1160 UINT uiIDA[1]; 1161 uiIDA[0]=IDS_CONFIRM_OK; 1162 C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME, IDS_IN_PARTY_SESSION_FULL, uiIDA,1,ProfileManager.GetPrimaryPad()); 1163 pMinecraft->progressRenderer->progressStartNoAbort( IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME ); 1164 pMinecraft->progressRenderer->progressStage( -1 ); 1165 } 1166 else 1167 { 1168 pMinecraft->progressRenderer->progressStartNoAbort( g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT) ); 1169 pMinecraft->progressRenderer->progressStage( IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME ); 1170 } 1171 1172#else 1173 pMinecraft->progressRenderer->progressStartNoAbort( g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT) ); 1174 pMinecraft->progressRenderer->progressStage( IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME ); 1175#endif 1176 1177 while( app.GetXuiServerAction(ProfileManager.GetPrimaryPad() ) != eXuiServerAction_Idle && !MinecraftServer::serverHalted() ) 1178 { 1179 Sleep(10); 1180 } 1181 app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_PauseServer,(void *)TRUE); 1182 1183 // wait for the server to be in a non-ticking state 1184 pServer->m_serverPausedEvent->WaitForSignal(INFINITE); 1185 1186#if defined(__PS3__) || defined(__ORBIS__) || defined __PSVITA__ 1187 // Swap these two messages around as one is too long to display at 480 1188 pMinecraft->progressRenderer->progressStartNoAbort( IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME ); 1189 pMinecraft->progressRenderer->progressStage( -1 ); //g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT) ); 1190#elif defined(_XBOX_ONE) 1191 if( g_NetworkManager.m_bFullSessionMessageOnNextSessionChange ) 1192 { 1193 pMinecraft->progressRenderer->progressStartNoAbort( IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME ); 1194 pMinecraft->progressRenderer->progressStage( -1 ); 1195 } 1196 else 1197 { 1198 pMinecraft->progressRenderer->progressStartNoAbort( g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT) ); 1199 pMinecraft->progressRenderer->progressStage( IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME ); 1200 } 1201#else 1202 pMinecraft->progressRenderer->progressStartNoAbort( g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT) ); 1203 pMinecraft->progressRenderer->progressStage( IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME ); 1204#endif 1205 1206 pMinecraft->progressRenderer->progressStagePercentage(25); 1207 1208#ifdef _XBOX_ONE 1209 // wait for any players that were being added, to finish doing this. On XB1, if we don't do this then there's an async thread running doing this, 1210 // which could then finish at any inappropriate time later 1211 while( s_pPlatformNetworkManager->IsAddingPlayer() ) 1212 { 1213 Sleep(1); 1214 } 1215#endif 1216 1217 // Null the network player of all the server players that are local, to stop them being removed from the server when removed from the session 1218 if( pServer != NULL ) 1219 { 1220 PlayerList *players = pServer->getPlayers(); 1221 for(AUTO_VAR(it, players->players.begin()); it < players->players.end(); ++it) 1222 { 1223 shared_ptr<ServerPlayer> servPlayer = *it; 1224 if( servPlayer->connection->isLocal() && !servPlayer->connection->isGuest() ) 1225 { 1226 servPlayer->connection->connection->getSocket()->setPlayer(NULL); 1227 } 1228 } 1229 } 1230 1231 // delete the current session - if we weren't actually disconnected fully from the network but have just lost our room, then pass a bLeaveRoom flag of false 1232 // here as by definition we don't need to leave the room (again). This is currently only an issue for sony platforms. 1233 if( g_NetworkManager.m_bLastDisconnectWasLostRoomOnly ) 1234 { 1235 s_pPlatformNetworkManager->_LeaveGame(false, false); 1236 } 1237 else 1238 { 1239 s_pPlatformNetworkManager->_LeaveGame(false, true); 1240 } 1241 1242 // wait for the current session to end 1243 while( g_NetworkManager.IsInSession() ) 1244 { 1245 Sleep(1); 1246 } 1247 1248 // Reset this flag as the we don't need to know that we only lost the room only from this point onwards, the behaviour is exactly the same 1249 g_NetworkManager.m_bLastDisconnectWasLostRoomOnly = false; 1250 g_NetworkManager.m_bFullSessionMessageOnNextSessionChange = false; 1251 1252 pMinecraft->progressRenderer->progressStagePercentage(50); 1253 1254 // Defaulting to making this a local game 1255 g_NetworkManager.SetLocalGame(true); 1256 1257 // Create a new session with all the players that were in the old one 1258 int localUsersMask = 0; 1259 char numLocalPlayers = 0; 1260 for(unsigned int index = 0; index < XUSER_MAX_COUNT; ++index) 1261 { 1262 if(ProfileManager.IsSignedIn(index) && pMinecraft->localplayers[index] != NULL ) 1263 { 1264 numLocalPlayers++; 1265 localUsersMask |= GetLocalPlayerMask(index); 1266 } 1267 } 1268 1269 s_pPlatformNetworkManager->_HostGame( localUsersMask ); 1270 1271 pMinecraft->progressRenderer->progressStagePercentage(75); 1272 1273 // Wait for all the local players to rejoin the session 1274 while( g_NetworkManager.GetPlayerCount() < numLocalPlayers ) 1275 { 1276 Sleep(1); 1277 } 1278 1279 // Restore the network player of all the server players that are local 1280 if( pServer != NULL ) 1281 { 1282 for(unsigned int index = 0; index < XUSER_MAX_COUNT; ++index) 1283 { 1284 if(ProfileManager.IsSignedIn(index) && pMinecraft->localplayers[index] != NULL ) 1285 { 1286 PlayerUID localPlayerXuid = pMinecraft->localplayers[index]->getXuid(); 1287 1288 PlayerList *players = pServer->getPlayers(); 1289 for(AUTO_VAR(it, players->players.begin()); it < players->players.end(); ++it) 1290 { 1291 shared_ptr<ServerPlayer> servPlayer = *it; 1292 if( servPlayer->getXuid() == localPlayerXuid ) 1293 { 1294 servPlayer->connection->connection->getSocket()->setPlayer( g_NetworkManager.GetLocalPlayerByUserIndex(index) ); 1295 } 1296 } 1297 1298 // Player might have a pending connection 1299 if (pMinecraft->m_pendingLocalConnections[index] != NULL) 1300 { 1301 // Update the network player 1302 pMinecraft->m_pendingLocalConnections[index]->getConnection()->getSocket()->setPlayer(g_NetworkManager.GetLocalPlayerByUserIndex(index)); 1303 } 1304 else if ( pMinecraft->m_connectionFailed[index] && (pMinecraft->m_connectionFailedReason[index] == DisconnectPacket::eDisconnect_ConnectionCreationFailed) ) 1305 { 1306 pMinecraft->removeLocalPlayerIdx(index); 1307#ifdef _XBOX_ONE 1308 ProfileManager.RemoveGamepadFromGame(index); 1309#endif 1310 } 1311 } 1312 } 1313 } 1314 1315 pMinecraft->progressRenderer->progressStagePercentage(100); 1316 1317#ifndef _XBOX 1318 // Make sure that we have transitioned through any joining/creating stages so we're actually ready to set to play 1319 while(!s_pPlatformNetworkManager->IsReadyToPlayOrIdle()) 1320 { 1321 Sleep(10); 1322 } 1323#endif 1324 1325 s_pPlatformNetworkManager->_StartGame(); 1326 1327#ifndef _XBOX 1328 // Wait until the message box has been closed 1329 while(ui.IsSceneInStack(XUSER_INDEX_ANY, eUIScene_MessageBox)) 1330 { 1331 Sleep(10); 1332 } 1333#endif 1334 1335 // Start the game again 1336 app.SetGameStarted(true); 1337 app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_PauseServer,(void *)FALSE); 1338 app.SetChangingSessionType(false); 1339 app.SetReallyChangingSessionType(false); 1340 1341 return S_OK; 1342 1343} 1344 1345void CGameNetworkManager::SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index) 1346{ 1347 s_pPlatformNetworkManager->SystemFlagSet( pNetworkPlayer, index ); 1348} 1349 1350bool CGameNetworkManager::SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index) 1351{ 1352 return s_pPlatformNetworkManager->SystemFlagGet( pNetworkPlayer, index ); 1353} 1354 1355wstring CGameNetworkManager::GatherStats() 1356{ 1357 return s_pPlatformNetworkManager->GatherStats(); 1358} 1359 1360void CGameNetworkManager::renderQueueMeter() 1361{ 1362#ifdef _XBOX 1363 int height = 720; 1364 1365 CGameNetworkManager::byteQueue[(CGameNetworkManager::messageQueuePos) & (CGameNetworkManager::messageQueue_length - 1)] = GetHostPlayer()->GetSendQueueSizeBytes(NULL, false); 1366 CGameNetworkManager::messageQueue[(CGameNetworkManager::messageQueuePos++) & (CGameNetworkManager::messageQueue_length - 1)] = GetHostPlayer()->GetSendQueueSizeMessages(NULL, false); 1367 1368 Minecraft *pMinecraft = Minecraft::GetInstance(); 1369 pMinecraft->gui->renderGraph(CGameNetworkManager::messageQueue_length, CGameNetworkManager::messageQueuePos, CGameNetworkManager::messageQueue, 10, 1000, CGameNetworkManager::byteQueue, 100, 25000); 1370#endif 1371} 1372 1373wstring CGameNetworkManager::GatherRTTStats() 1374{ 1375 return s_pPlatformNetworkManager->GatherRTTStats(); 1376} 1377 1378void CGameNetworkManager::StateChange_AnyToHosting() 1379{ 1380 app.DebugPrintf("Disabling Guest Signin\n"); 1381 XEnableGuestSignin(FALSE); 1382 Minecraft::GetInstance()->clearPendingClientTextureRequests(); 1383} 1384 1385void CGameNetworkManager::StateChange_AnyToJoining() 1386{ 1387 app.DebugPrintf("Disabling Guest Signin\n"); 1388 XEnableGuestSignin(FALSE); 1389 Minecraft::GetInstance()->clearPendingClientTextureRequests(); 1390 1391 ConnectionProgressParams *param = new ConnectionProgressParams(); 1392 param->iPad = ProfileManager.GetPrimaryPad(); 1393 param->stringId = -1; 1394 param->showTooltips = false; 1395 param->setFailTimer = true; 1396 param->timerTime = CONNECTING_PROGRESS_CHECK_TIME; 1397 1398 ui.NavigateToScene(ProfileManager.GetPrimaryPad(), eUIScene_ConnectingProgress, param); 1399} 1400 1401void CGameNetworkManager::StateChange_JoiningToIdle(CPlatformNetworkManager::eJoinFailedReason reason) 1402{ 1403 DisconnectPacket::eDisconnectReason disconnectReason; 1404 switch(reason) 1405 { 1406 case CPlatformNetworkManager::JOIN_FAILED_SERVER_FULL: 1407 disconnectReason = DisconnectPacket::eDisconnect_ServerFull; 1408 break; 1409 case CPlatformNetworkManager::JOIN_FAILED_INSUFFICIENT_PRIVILEGES: 1410 disconnectReason = DisconnectPacket::eDisconnect_NoMultiplayerPrivilegesJoin; 1411 app.SetAction(ProfileManager.GetPrimaryPad(),eAppAction_FailedToJoinNoPrivileges); 1412 break; 1413 default: 1414 disconnectReason = DisconnectPacket::eDisconnect_ConnectionCreationFailed; 1415 break; 1416 }; 1417 Minecraft::GetInstance()->connectionDisconnected(ProfileManager.GetPrimaryPad(), disconnectReason); 1418} 1419 1420void CGameNetworkManager::StateChange_AnyToStarting() 1421{ 1422#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ 1423 app.getRemoteStorage()->shutdown(); // shut the remote storage lib down and hopefully get our 7mb back 1424#endif 1425 1426 if(!g_NetworkManager.IsHost()) 1427 { 1428 LoadingInputParams *loadingParams = new LoadingInputParams(); 1429 loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc; 1430 loadingParams->lpParam = NULL; 1431 1432 UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); 1433 completionData->bShowBackground=TRUE; 1434 completionData->bShowLogo=TRUE; 1435 completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes; 1436 completionData->iPad = ProfileManager.GetPrimaryPad(); 1437 loadingParams->completionData = completionData; 1438 1439 ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); 1440 } 1441} 1442 1443void CGameNetworkManager::StateChange_AnyToEnding(bool bStateWasPlaying) 1444{ 1445 // Kick off a stats write for players that are signed into LIVE, if this is a local game 1446 if( bStateWasPlaying && g_NetworkManager.IsLocalGame() ) 1447 { 1448 for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) 1449 { 1450 INetworkPlayer *pNetworkPlayer = g_NetworkManager.GetLocalPlayerByUserIndex(i); 1451 if(pNetworkPlayer != NULL && ProfileManager.IsSignedIn( i ) ) 1452 { 1453 app.DebugPrintf("Stats save for an offline game for the player at index %d\n", i ); 1454 Minecraft::GetInstance()->forceStatsSave(pNetworkPlayer->GetUserIndex()); 1455 } 1456 } 1457 } 1458 1459 Minecraft::GetInstance()->gui->clearMessages(); 1460 1461 if(!g_NetworkManager.IsHost() && !g_NetworkManager.IsLeavingGame() ) 1462 { 1463 // 4J Stu - If the host is saving then it might take a while to quite the session, so do it ourself 1464 //m_bLeavingGame = true; 1465 1466 // The host has notified that the game is about to end 1467 if(app.GetDisconnectReason() == DisconnectPacket::eDisconnect_None) app.SetDisconnectReason( DisconnectPacket::eDisconnect_Quitting ); 1468 app.SetAction(ProfileManager.GetPrimaryPad(),eAppAction_ExitWorld,(void *)TRUE); 1469 } 1470} 1471 1472void CGameNetworkManager::StateChange_AnyToIdle() 1473{ 1474 app.DebugPrintf("Enabling Guest Signin\n"); 1475 XEnableGuestSignin(TRUE); 1476 // Reset this here so that we can search for games again 1477 // 4J Stu - If we are changing session type there is a race between that thread setting the game to local, and this setting it to not local 1478 if(!app.GetChangingSessionType()) g_NetworkManager.SetLocalGame( false ); 1479 1480} 1481 1482void CGameNetworkManager::CreateSocket( INetworkPlayer *pNetworkPlayer, bool localPlayer ) 1483{ 1484 Minecraft *pMinecraft = Minecraft::GetInstance(); 1485 1486 Socket *socket = NULL; 1487 shared_ptr<MultiplayerLocalPlayer> mpPlayer = nullptr; 1488 int userIdx = pNetworkPlayer->GetUserIndex(); 1489 if (userIdx >= 0 && userIdx < XUSER_MAX_COUNT) 1490 mpPlayer = pMinecraft->localplayers[userIdx]; 1491 if( localPlayer && mpPlayer != NULL && mpPlayer->connection != NULL) 1492 { 1493 // If we already have a MultiplayerLocalPlayer here then we are doing a session type change 1494 socket = mpPlayer->connection->getSocket(); 1495 1496 // Pair this socket and network player 1497 pNetworkPlayer->SetSocket( socket); 1498 if( socket ) 1499 { 1500 socket->setPlayer( pNetworkPlayer ); 1501 } 1502 } 1503 else 1504 { 1505 socket = new Socket( pNetworkPlayer, g_NetworkManager.IsHost(), g_NetworkManager.IsHost() && localPlayer ); 1506 pNetworkPlayer->SetSocket( socket ); 1507 1508 // 4J Stu - May be other states we want to accept aswell 1509 // Add this user to the game server if the game is started already 1510 if( g_NetworkManager.IsHost() && g_NetworkManager.IsInGameplay() ) 1511 { 1512 Socket::addIncomingSocket(socket); 1513 } 1514 1515 // If this is a local player and we are already in the game, we need to setup a local connection and log 1516 // the player in to the game server 1517 if( localPlayer && g_NetworkManager.IsInGameplay() ) 1518 { 1519 int idx = pNetworkPlayer->GetUserIndex(); 1520 app.DebugPrintf("Creating new client connection for idx: %d\n", idx); 1521 1522 ClientConnection *connection; 1523 connection = new ClientConnection(pMinecraft, socket, idx); 1524 1525 if( connection->createdOk ) 1526 { 1527 connection->send( shared_ptr<PreLoginPacket>( new PreLoginPacket( pNetworkPlayer->GetOnlineName() ) ) ); 1528 pMinecraft->addPendingLocalConnection(idx, connection); 1529 } 1530 else 1531 { 1532 pMinecraft->connectionDisconnected( idx , DisconnectPacket::eDisconnect_ConnectionCreationFailed ); 1533 delete connection; 1534 connection = NULL; 1535 } 1536 } 1537 } 1538 1539} 1540 1541void CGameNetworkManager::CloseConnection( INetworkPlayer *pNetworkPlayer ) 1542{ 1543 MinecraftServer *server = MinecraftServer::getInstance(); 1544 if( server != NULL ) 1545 { 1546 PlayerList *players = server->getPlayers(); 1547 if( players != NULL ) 1548 { 1549 players->closePlayerConnectionBySmallId(pNetworkPlayer->GetSmallId()); 1550 } 1551 } 1552} 1553 1554void CGameNetworkManager::PlayerJoining( INetworkPlayer *pNetworkPlayer ) 1555{ 1556 if (g_NetworkManager.IsInGameplay()) // 4J-JEV: Wait to do this at StartNetworkGame if not in-game yet. 1557 { 1558 // 4J-JEV: Update RichPresence when a player joins the game. 1559 bool multiplayer = g_NetworkManager.GetPlayerCount() > 1, localgame = g_NetworkManager.IsLocalGame(); 1560 for (int iPad=0; iPad<XUSER_MAX_COUNT; ++iPad) 1561 { 1562 INetworkPlayer *pNetworkPlayer = g_NetworkManager.GetLocalPlayerByUserIndex(iPad); 1563 if (pNetworkPlayer == NULL) continue; 1564 1565 app.SetRichPresenceContext(iPad,CONTEXT_GAME_STATE_BLANK); 1566 if (multiplayer) 1567 { 1568 if (localgame) ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MULTIPLAYEROFFLINE, false); 1569 else ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MULTIPLAYER, false); 1570 } 1571 else 1572 { 1573 if (localgame) ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE, false); 1574 else ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MULTIPLAYER_1P, false); 1575 } 1576 } 1577 } 1578 1579 if( pNetworkPlayer->IsLocal() ) 1580 { 1581 TelemetryManager->RecordPlayerSessionStart(pNetworkPlayer->GetUserIndex()); 1582 } 1583#ifdef _XBOX 1584 else 1585 { 1586 if( !pNetworkPlayer->IsHost() ) 1587 { 1588 for(int idx = 0; idx < XUSER_MAX_COUNT; ++idx) 1589 { 1590 if(Minecraft::GetInstance()->localplayers[idx] != NULL) 1591 { 1592 TelemetryManager->RecordLevelStart(idx, eSen_FriendOrMatch_Playing_With_Invited_Friends, eSen_CompeteOrCoop_Coop_and_Competitive, Minecraft::GetInstance()->level->difficulty, app.GetLocalPlayerCount(), g_NetworkManager.GetOnlinePlayerCount()); 1593 } 1594 } 1595 } 1596 } 1597#endif 1598} 1599 1600void CGameNetworkManager::PlayerLeaving( INetworkPlayer *pNetworkPlayer ) 1601{ 1602 if( pNetworkPlayer->IsLocal() ) 1603 { 1604 ProfileManager.SetCurrentGameActivity(pNetworkPlayer->GetUserIndex(),CONTEXT_PRESENCE_IDLE,false); 1605 1606 TelemetryManager->RecordPlayerSessionExit(pNetworkPlayer->GetUserIndex(), app.GetDisconnectReason()); 1607 } 1608#ifdef _XBOX 1609 else 1610 { 1611 for(int idx = 0; idx < XUSER_MAX_COUNT; ++idx) 1612 { 1613 if(Minecraft::GetInstance()->localplayers[idx] != NULL) 1614 { 1615 TelemetryManager->RecordLevelStart(idx, eSen_FriendOrMatch_Playing_With_Invited_Friends, eSen_CompeteOrCoop_Coop_and_Competitive, Minecraft::GetInstance()->level->difficulty, app.GetLocalPlayerCount(), g_NetworkManager.GetOnlinePlayerCount()); 1616 } 1617 } 1618 } 1619#endif 1620} 1621 1622void CGameNetworkManager::HostChanged() 1623{ 1624 // Disable host migration 1625 app.SetAction(ProfileManager.GetPrimaryPad(),eAppAction_ExitWorld,(void *)TRUE); 1626} 1627 1628void CGameNetworkManager::WriteStats( INetworkPlayer *pNetworkPlayer ) 1629{ 1630 Minecraft::GetInstance()->forceStatsSave( pNetworkPlayer->GetUserIndex() ); 1631} 1632 1633void CGameNetworkManager::GameInviteReceived( int userIndex, const INVITE_INFO *pInviteInfo) 1634{ 1635#ifdef __ORBIS__ 1636 if (m_pUpsell != NULL) 1637 { 1638 delete pInviteInfo; 1639 return; 1640 } 1641 1642 // Need to check we're signed in to PSN 1643 bool isSignedInLive = true; 1644 bool isLocalMultiplayerAvailable = app.IsLocalMultiplayerAvailable(); 1645 int iPadNotSignedInLive = -1; 1646 for(unsigned int i = 0; i < XUSER_MAX_COUNT; i++) 1647 { 1648 if (ProfileManager.IsSignedIn(i) && (i == ProfileManager.GetPrimaryPad() || isLocalMultiplayerAvailable)) 1649 { 1650 if (isSignedInLive && !ProfileManager.IsSignedInLive(i)) 1651 { 1652 // Record the first non signed in live pad 1653 iPadNotSignedInLive = i; 1654 } 1655 1656 isSignedInLive = isSignedInLive && ProfileManager.IsSignedInLive(i); 1657 } 1658 } 1659 1660 if (!isSignedInLive) 1661 { 1662 // Determine why they're not "signed in live" 1663 1664 // Check if PSN is unavailable because of age restriction 1665 int npAvailability = ProfileManager.getNPAvailability(iPadNotSignedInLive); 1666 if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) 1667 { 1668 // 4J Stu - This is a bit messy and is due to the library incorrectly returning false for IsSignedInLive if the npAvailability isn't SCE_OK 1669 UINT uiIDA[1]; 1670 uiIDA[0]=IDS_OK; 1671 ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPadNotSignedInLive); 1672 } 1673 else if (ProfileManager.isSignedInPSN(iPadNotSignedInLive)) 1674 { 1675 // Signed in to PSN but not connected (no internet access) 1676 assert(!ProfileManager.isConnectedToPSN(iPadNotSignedInLive)); 1677 1678 UINT uiIDA[1]; 1679 uiIDA[0] = IDS_OK; 1680 ui.RequestErrorMessage( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPadNotSignedInLive); 1681 } 1682 else 1683 { 1684 // Not signed in to PSN 1685 UINT uiIDA[1]; 1686 uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; 1687 ui.RequestAlertMessage( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, iPadNotSignedInLive, &CGameNetworkManager::MustSignInReturned_1, (void *)pInviteInfo); 1688 } 1689 return; 1690 } 1691 1692 // if this is the trial game, we'll check and send the user to unlock the game later, in HandleInviteWhenInMenus 1693 if(ProfileManager.IsFullVersion()) 1694 { 1695 // 4J-JEV: Check that all players are authorised for PsPlus, present upsell to players that aren't and try again. 1696 for (unsigned int index = 0; index < XUSER_MAX_COUNT; index++) 1697 { 1698 if ( ProfileManager.IsSignedIn(index) 1699 && !ProfileManager.HasPlayStationPlus(userIndex) ) 1700 { 1701 m_pInviteInfo = (INVITE_INFO *) pInviteInfo; 1702 m_iPlayerInvited = userIndex; 1703 1704 m_pUpsell = new PsPlusUpsellWrapper(index); 1705 m_pUpsell->displayUpsell(); 1706 1707 return; 1708 } 1709 } 1710 } 1711#endif 1712 1713 1714 int localUsersMask = 0; 1715 Minecraft *pMinecraft = Minecraft::GetInstance(); 1716 int joiningUsers = 0; 1717 1718 bool noPrivileges = false; 1719 for(unsigned int index = 0; index < XUSER_MAX_COUNT; ++index) 1720 { 1721 if(ProfileManager.IsSignedIn(index) ) 1722 { 1723 // 4J-PB we shouldn't bring any inactive players into the game, except for the invited player (who may be an inactive player) 1724 // 4J Stu - If we are not in a game, then bring in all players signed in 1725 if(index==userIndex || pMinecraft->localplayers[index]!=NULL ) 1726 { 1727 ++joiningUsers; 1728 if( !ProfileManager.AllowedToPlayMultiplayer(index) ) noPrivileges = true; 1729 localUsersMask |= GetLocalPlayerMask( index ); 1730 } 1731 } 1732 } 1733 1734 // Check if user-created content is allowed, as we cannot play multiplayer if it's not 1735 bool noUGC = false; 1736 bool bContentRestricted=false; 1737 BOOL pccAllowed = TRUE; 1738 BOOL pccFriendsAllowed = TRUE; 1739#if defined(__PS3__) || defined(__PSVITA__) 1740 ProfileManager.GetChatAndContentRestrictions(userIndex,false,&noUGC,&bContentRestricted,NULL); 1741#else 1742 ProfileManager.AllowedPlayerCreatedContent(ProfileManager.GetPrimaryPad(),false,&pccAllowed,&pccFriendsAllowed); 1743 if(!pccAllowed && !pccFriendsAllowed) noUGC = true; 1744#endif 1745 1746#if defined(_XBOX) || defined(__PS3__) 1747 if(joiningUsers > 1 && !RenderManager.IsHiDef() && userIndex != ProfileManager.GetPrimaryPad()) 1748 { 1749 UINT uiIDA[1]; 1750 uiIDA[0]=IDS_CONFIRM_OK; 1751 1752 // 4J-PB - it's possible there is no primary pad here, when accepting an invite from the dashboard 1753 ui.RequestErrorMessage( IDS_CONNECTION_FAILED, IDS_CONNECTION_FAILED_NO_SD_SPLITSCREEN, uiIDA,1,XUSER_INDEX_ANY); 1754 } 1755 else 1756#endif 1757 1758 if( noUGC ) 1759 { 1760#ifdef __PSVITA__ 1761 // showing the system message for chat restriction here instead now, to fix FQA bug report 1762 ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION, ProfileManager.GetPrimaryPad() ); 1763#else 1764 int messageText = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL; 1765 if(joiningUsers > 1) messageText = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL; 1766 1767 ui.RequestUGCMessageBox(IDS_CONNECTION_FAILED, messageText, XUSER_INDEX_ANY); 1768#endif 1769 } 1770#if defined(__PS3__) || defined __PSVITA__ 1771 else if(bContentRestricted) 1772 { 1773 int messageText = IDS_CONTENT_RESTRICTION; 1774 if(joiningUsers > 1) messageText = IDS_CONTENT_RESTRICTION_MULTIPLAYER; 1775 1776 ui.RequestContentRestrictedMessageBox(IDS_CONNECTION_FAILED, messageText, XUSER_INDEX_ANY); 1777 } 1778#endif 1779 else if(noPrivileges) 1780 { 1781 UINT uiIDA[1]; 1782 uiIDA[0]=IDS_CONFIRM_OK; 1783 1784 // 4J-PB - it's possible there is no primary pad here, when accepting an invite from the dashboard 1785 //StorageManager.RequestMessageBox( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable()); 1786 ui.RequestErrorMessage( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,XUSER_INDEX_ANY); 1787 } 1788 else 1789 { 1790#if defined(__ORBIS__) || defined(__PSVITA__) 1791 bool chatRestricted = false; 1792 ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),false,&chatRestricted,NULL,NULL); 1793 if(chatRestricted) 1794 { 1795 ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION, ProfileManager.GetPrimaryPad() ); 1796 } 1797#endif 1798 if( !g_NetworkManager.IsInSession() ) 1799 { 1800#if defined (__PS3__) || defined (__PSVITA__) 1801 // PS3 is more complicated here - we need to make sure that the player is online. If they are then we can do the same as the xbox, if not we need to try and get them online and then, if they do sign in, go down the same path 1802 1803 // Determine why they're not "signed in live" 1804 // MGH - On Vita we need to add a new message at some point for connecting when already signed in 1805 if(ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad())) 1806 { 1807 HandleInviteWhenInMenus(userIndex, pInviteInfo); 1808 } 1809 else 1810 { 1811 UINT uiIDA[2]; 1812 uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; 1813 uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; 1814 ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CGameNetworkManager::MustSignInReturned_1,(void *)pInviteInfo); 1815 } 1816 1817 1818#else 1819 HandleInviteWhenInMenus(userIndex, pInviteInfo); 1820#endif 1821 } 1822 else 1823 { 1824 app.DebugPrintf("We are already in a multiplayer game...need to leave it\n"); 1825 1826// JoinFromInviteData *joinData = new JoinFromInviteData(); 1827// joinData->dwUserIndex = dwUserIndex; 1828// joinData->dwLocalUsersMask = dwLocalUsersMask; 1829// joinData->pInviteInfo = pInviteInfo; 1830 1831 // tell the app to process this 1832#ifdef __PSVITA__ 1833 if(((CPlatformNetworkManagerSony*)s_pPlatformNetworkManager)->checkValidInviteData(pInviteInfo)) 1834#endif 1835 { 1836 app.ProcessInvite(userIndex,localUsersMask,pInviteInfo); 1837 } 1838 } 1839 } 1840} 1841 1842volatile bool waitHere = true; 1843 1844void CGameNetworkManager::HandleInviteWhenInMenus( int userIndex, const INVITE_INFO *pInviteInfo) 1845{ 1846 // We are in the root menus somewhere 1847 1848#if 0 1849 while( waitHere ) 1850 { 1851 Sleep(1); 1852 } 1853#endif 1854 1855 // if this is the trial game, then we need the user to unlock the full game 1856 if(!ProfileManager.IsFullVersion()) 1857 { 1858 // The marketplace will fail with the primary player set to -1 1859 ProfileManager.SetPrimaryPad(userIndex); 1860 1861 app.SetAction(userIndex,eAppAction_DashboardTrialJoinFromInvite); 1862 } 1863 else 1864 { 1865#ifndef _XBOX_ONE 1866 ProfileManager.SetPrimaryPad(userIndex); 1867#endif 1868 1869 // 4J Stu - If we accept an invite from the main menu before going to play game we need to load the DLC 1870 // These checks are done within the StartInstallDLCProcess - (!app.DLCInstallProcessCompleted() && !app.DLCInstallPending()) app.StartInstallDLCProcess(dwUserIndex); 1871 app.StartInstallDLCProcess(userIndex); 1872 1873 // 4J Stu - Fix for #10936 - MP Lab: TCR 001: Matchmaking: Player is stuck in a soft-locked state after selecting the guest account when prompted 1874 // The locked profile should not be changed if we are in menus as the main player might sign out in the sign-in ui 1875 //ProfileManager.SetLockedProfile(-1); 1876 1877#ifdef _XBOX_ONE 1878 if((!app.IsLocalMultiplayerAvailable())&&InputManager.IsPadLocked(userIndex)) 1879#else 1880 if(!app.IsLocalMultiplayerAvailable()) 1881#endif 1882 { 1883 bool noPrivileges=!ProfileManager.AllowedToPlayMultiplayer(userIndex); 1884 1885 if(noPrivileges) 1886 { 1887 UINT uiIDA[1]; 1888 uiIDA[0]=IDS_CONFIRM_OK; 1889 ui.RequestErrorMessage( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad()); 1890 } 1891 else 1892 { 1893 ProfileManager.SetLockedProfile(userIndex); 1894 ProfileManager.SetPrimaryPad(userIndex); 1895 1896 int localUsersMask=0; 1897 localUsersMask |= GetLocalPlayerMask( userIndex ); 1898 1899 // If the player was signed in before selecting play, we'll not have read the profile yet, so query the sign-in status to get this to happen 1900 ProfileManager.QuerySigninStatus(); 1901 1902 // 4J-PB - clear any previous connection errors 1903 Minecraft::GetInstance()->clearConnectionFailed(); 1904 1905 g_NetworkManager.SetLocalGame(false); 1906 1907 // change the minecraft player name 1908 Minecraft::GetInstance()->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); 1909 1910 bool success = g_NetworkManager.JoinGameFromInviteInfo( userIndex, localUsersMask, pInviteInfo ); 1911 if( !success ) 1912 { 1913 app.DebugPrintf( "Failed joining game from invite\n" ); 1914 } 1915 } 1916 } 1917 else 1918 { 1919 // the FromInvite will make the lib decide how many panes to display based on connected pads/signed in players 1920#ifdef _XBOX 1921 ProfileManager.RequestSignInUI(true, false, false, false, false,&CGameNetworkManager::JoinFromInvite_SignInReturned, (LPVOID)pInviteInfo,userIndex); 1922#else 1923 SignInInfo info; 1924 info.Func = &CGameNetworkManager::JoinFromInvite_SignInReturned; 1925 info.lpParam = (LPVOID)pInviteInfo; 1926 info.requireOnline = true; 1927 app.DebugPrintf("Using fullscreen layer\n"); 1928 ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_QuadrantSignin,&info,eUILayer_Alert,eUIGroup_Fullscreen); 1929#endif 1930 } 1931 } 1932} 1933 1934void CGameNetworkManager::AddLocalPlayerFailed(int idx, bool serverFull/* = false*/) 1935{ 1936 Minecraft::GetInstance()->connectionDisconnected(idx, serverFull ? DisconnectPacket::eDisconnect_ServerFull : DisconnectPacket::eDisconnect_ConnectionCreationFailed); 1937} 1938 1939#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__ 1940void CGameNetworkManager::HandleDisconnect(bool bLostRoomOnly,bool bPSNSignout) 1941#else 1942void CGameNetworkManager::HandleDisconnect(bool bLostRoomOnly) 1943#endif 1944{ 1945 int iPrimaryPlayer = g_NetworkManager.GetPrimaryPad(); 1946 1947 if((g_NetworkManager.GetLockedProfile()!=-1) && iPrimaryPlayer!=-1 && g_NetworkManager.IsInSession() ) 1948 { 1949 m_bLastDisconnectWasLostRoomOnly = bLostRoomOnly; 1950#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__ 1951 m_bSignedOutofPSN=bPSNSignout; 1952#endif 1953 app.SetAction(iPrimaryPlayer,eAppAction_EthernetDisconnected); 1954 } 1955 else 1956 { 1957 m_bLastDisconnectWasLostRoomOnly = false; 1958 } 1959} 1960 1961int CGameNetworkManager::GetPrimaryPad() 1962{ 1963 return ProfileManager.GetPrimaryPad(); 1964} 1965 1966int CGameNetworkManager::GetLockedProfile() 1967{ 1968 return ProfileManager.GetLockedProfile(); 1969} 1970 1971bool CGameNetworkManager::IsSignedInLive(int playerIdx) 1972{ 1973 return ProfileManager.IsSignedInLive(playerIdx); 1974} 1975 1976bool CGameNetworkManager::AllowedToPlayMultiplayer(int playerIdx) 1977{ 1978 return ProfileManager.AllowedToPlayMultiplayer(playerIdx); 1979} 1980 1981char *CGameNetworkManager::GetOnlineName(int playerIdx) 1982{ 1983 return ProfileManager.GetGamertag(playerIdx); 1984} 1985 1986void CGameNetworkManager::ServerReadyCreate(bool create) 1987{ 1988 m_hServerReadyEvent = ( create ? ( new C4JThread::Event ) : NULL ); 1989} 1990 1991void CGameNetworkManager::ServerReady() 1992{ 1993 m_hServerReadyEvent->Set(); 1994} 1995 1996void CGameNetworkManager::ServerReadyWait() 1997{ 1998 m_hServerReadyEvent->WaitForSignal(INFINITE); 1999} 2000 2001void CGameNetworkManager::ServerReadyDestroy() 2002{ 2003 delete m_hServerReadyEvent; 2004 m_hServerReadyEvent = NULL; 2005} 2006 2007bool CGameNetworkManager::ServerReadyValid() 2008{ 2009 return ( m_hServerReadyEvent != NULL ); 2010} 2011 2012void CGameNetworkManager::ServerStoppedCreate(bool create) 2013{ 2014 m_hServerStoppedEvent = ( create ? ( new C4JThread::Event ) : NULL ); 2015} 2016 2017void CGameNetworkManager::ServerStopped() 2018{ 2019 m_hServerStoppedEvent->Set(); 2020} 2021 2022void CGameNetworkManager::ServerStoppedWait() 2023{ 2024 // If this is called from the main thread, then this won't be ticking anything which can mean that the storage manager state can't progress. 2025 // This means that the server thread we are waiting on won't ever finish, as it might be locked waiting for this to complete itself. 2026 // Do some ticking here then if this is the case. 2027 if( C4JThread::isMainThread() ) 2028 { 2029 int result = WAIT_TIMEOUT; 2030 do 2031 { 2032#ifndef _XBOX 2033 RenderManager.StartFrame(); 2034#endif 2035 result = m_hServerStoppedEvent->WaitForSignal(20); 2036 // Tick some simple things 2037 ProfileManager.Tick(); 2038 StorageManager.Tick(); 2039 InputManager.Tick(); 2040 RenderManager.Tick(); 2041 ui.tick(); 2042 ui.render(); 2043 RenderManager.Present(); 2044 } while( result == WAIT_TIMEOUT ); 2045 } 2046 else 2047 { 2048 m_hServerStoppedEvent->WaitForSignal(INFINITE); 2049 } 2050} 2051 2052void CGameNetworkManager::ServerStoppedDestroy() 2053{ 2054 delete m_hServerStoppedEvent; 2055 m_hServerStoppedEvent = NULL; 2056} 2057 2058bool CGameNetworkManager::ServerStoppedValid() 2059{ 2060 return ( m_hServerStoppedEvent != NULL ); 2061} 2062 2063int CGameNetworkManager::GetJoiningReadyPercentage() 2064{ 2065 return s_pPlatformNetworkManager->GetJoiningReadyPercentage(); 2066} 2067 2068#ifndef _XBOX 2069void CGameNetworkManager::FakeLocalPlayerJoined() 2070{ 2071 s_pPlatformNetworkManager->FakeLocalPlayerJoined(); 2072} 2073#endif 2074 2075#ifdef __PSVITA__ 2076bool CGameNetworkManager::usingAdhocMode() 2077{ 2078 return ((CPlatformNetworkManagerSony*)s_pPlatformNetworkManager)->usingAdhocMode(); 2079} 2080 2081void CGameNetworkManager::setAdhocMode(bool bAdhoc) 2082{ 2083 ((CPlatformNetworkManagerSony*)s_pPlatformNetworkManager)->setAdhocMode(bAdhoc); 2084} 2085 2086void CGameNetworkManager::startAdhocMatching() 2087{ 2088 ((CPlatformNetworkManagerSony*)s_pPlatformNetworkManager)->startAdhocMatching(); 2089} 2090 2091#endif