the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
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