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\Socket.h"
3#include "..\..\..\Minecraft.World\StringHelpers.h"
4#include "PlatformNetworkManagerDurango.h"
5#include "NetworkPlayerDurango.h"
6
7CPlatformNetworkManagerDurango *g_pPlatformNetworkManager;
8
9void CPlatformNetworkManagerDurango::HandleStateChange(DQRNetworkManager::eDQRNetworkManagerState oldState, DQRNetworkManager::eDQRNetworkManagerState newState)
10{
11 static const char * c_apszStateNames[] =
12 {
13 "DNM_STATE_INITIALISING",
14 "DNM_STATE_INITIALISE_FAILED",
15 "DNM_STATE_IDLE",
16 "DNM_STATE_HOSTING",
17 "DNM_STATE_JOINING",
18 "DNM_STATE_STARTING",
19 "DNM_STATE_PLAYING",
20 "DNM_STATE_LEAVING",
21 "DNM_STATE_ENDING",
22 };
23
24 app.DebugPrintf( "Network State: %s ==> %s\n",
25 c_apszStateNames[ oldState ],
26 c_apszStateNames[ newState ] );
27
28 if( newState == DQRNetworkManager::DNM_STATE_HOSTING )
29 {
30 m_bLeavingGame = false;
31 m_bLeaveGameOnTick = false;
32 m_bHostChanged = false;
33 g_NetworkManager.StateChange_AnyToHosting();
34 }
35 else if( newState == DQRNetworkManager::DNM_STATE_JOINING )
36 {
37 m_bLeavingGame = false;
38 m_bLeaveGameOnTick = false;
39 m_bHostChanged = false;
40 g_NetworkManager.StateChange_AnyToJoining();
41 }
42 else if( newState == DQRNetworkManager::DNM_STATE_IDLE && oldState == DQRNetworkManager::DNM_STATE_JOINING )
43 {
44 g_NetworkManager.StateChange_JoiningToIdle(JOIN_FAILED_NONSPECIFIC);
45 }
46 else if( newState == DQRNetworkManager::DNM_STATE_IDLE && oldState == DQRNetworkManager::DNM_STATE_HOSTING )
47 {
48 m_bLeavingGame = true;
49 }
50 else if( newState == DQRNetworkManager::DNM_STATE_STARTING )
51 {
52 m_lastPlayerEventTimeStart = app.getAppTime();
53
54 g_NetworkManager.StateChange_AnyToStarting();
55 }
56 // Fix for #93148 - TCR 001: BAS Game Stability: Title will crash for the multiplayer client if host of the game will exit during the clients loading to created world.
57 // 4J Stu - If the client joins just as the host is exiting, then they can skip to leaving without passing through ending
58 else if( newState == DQRNetworkManager::DNM_STATE_ENDING )
59 {
60 g_NetworkManager.StateChange_AnyToEnding( oldState == DQRNetworkManager::DNM_STATE_PLAYING );
61
62 if( m_pDQRNet->IsHost() )
63 {
64 m_bLeavingGame = true;
65 }
66 }
67
68 if( newState == DQRNetworkManager::DNM_STATE_IDLE )
69 {
70 g_NetworkManager.StateChange_AnyToIdle();
71 }
72}
73
74void CPlatformNetworkManagerDurango::HandlePlayerJoined(DQRNetworkPlayer *pDQRPlayer)
75{
76 const char * pszDescription;
77
78 // If this is a local player, we need to inform the chat system that it has joined
79 if( pDQRPlayer->IsLocal() )
80 {
81 m_pDQRNet->ChatPlayerJoined(pDQRPlayer->GetLocalPlayerIndex());
82 }
83
84 // 4J Stu - We create a fake socket for every where that we need an INBOUND queue of game data. Outbound
85 // is all handled by QNet so we don't need that. Therefore each client player has one, and the host has one
86 // for each client player.
87 bool createFakeSocket = false;
88 bool localPlayer = false;
89
90 NetworkPlayerDurango *networkPlayer = (NetworkPlayerDurango *)addNetworkPlayer(pDQRPlayer);
91
92 // Request full display name for this player
93 m_pDQRNet->RequestDisplayName(pDQRPlayer);
94
95 if( pDQRPlayer->IsLocal() )
96 {
97 localPlayer = true;
98 if( pDQRPlayer->IsHost() )
99 {
100 pszDescription = "local host";
101 // 4J Stu - No socket for the localhost as it uses a special loopback queue
102
103 m_machineDQRPrimaryPlayers.push_back( pDQRPlayer );
104 }
105 else
106 {
107 pszDescription = "local";
108
109 // We need an inbound queue on all local players to receive data from the host
110 createFakeSocket = true;
111 }
112 }
113 else
114 {
115 if( pDQRPlayer->IsHost() )
116 {
117 pszDescription = "remote host";
118 }
119 else
120 {
121 pszDescription = "remote";
122
123 // If we are the host, then create a fake socket for every remote player
124 if( m_pDQRNet->IsHost() )
125 {
126 createFakeSocket = true;
127 }
128 }
129
130 if( m_pDQRNet->IsHost() && !m_bHostChanged )
131 {
132 // Do we already have a primary player for this system?
133 bool systemHasPrimaryPlayer = false;
134 for(AUTO_VAR(it, m_machineDQRPrimaryPlayers.begin()); it < m_machineDQRPrimaryPlayers.end(); ++it)
135 {
136 DQRNetworkPlayer *pQNetPrimaryPlayer = *it;
137 if( pDQRPlayer->IsSameSystem(pQNetPrimaryPlayer) )
138 {
139 systemHasPrimaryPlayer = true;
140 break;
141 }
142 }
143 if( !systemHasPrimaryPlayer )
144 m_machineDQRPrimaryPlayers.push_back( pDQRPlayer );
145 }
146 }
147 g_NetworkManager.PlayerJoining( networkPlayer );
148
149 if( createFakeSocket == true && !m_bHostChanged )
150 {
151 g_NetworkManager.CreateSocket( networkPlayer, localPlayer );
152 }
153
154 app.DebugPrintf( "Player 0x%p \"%ls\" joined; %s; voice %i; camera %i.\n",
155 pDQRPlayer,
156 pDQRPlayer->GetGamertag(),
157 pszDescription,
158 (int) pDQRPlayer->HasVoice(),
159 (int) pDQRPlayer->HasCamera() );
160
161
162 if( m_pDQRNet->IsHost() )
163 {
164 g_NetworkManager.UpdateAndSetGameSessionData();
165 SystemFlagAddPlayer( networkPlayer );
166 }
167
168 for( int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
169 {
170 if(playerChangedCallback[idx] != NULL)
171 playerChangedCallback[idx]( playerChangedCallbackParam[idx], networkPlayer, false );
172 }
173
174 if(m_pDQRNet->GetState() == QNET_STATE_GAME_PLAY)
175 {
176 int localPlayerCount = 0;
177 for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
178 {
179 if( m_pDQRNet->GetLocalPlayerByUserIndex(idx) != NULL ) ++localPlayerCount;
180 }
181
182 float appTime = app.getAppTime();
183
184 // Only record stats for the primary player here
185 m_lastPlayerEventTimeStart = appTime;
186 }
187}
188
189void CPlatformNetworkManagerDurango::HandlePlayerLeaving(DQRNetworkPlayer *pDQRPlayer)
190{
191 //__debugbreak();
192
193 app.DebugPrintf( "Player 0x%p leaving.\n",
194 pDQRPlayer );
195
196 INetworkPlayer *networkPlayer = getNetworkPlayer(pDQRPlayer);
197
198 if( networkPlayer )
199 {
200 // Get our wrapper object associated with this player.
201 Socket *socket = networkPlayer->GetSocket();
202 if( socket != NULL )
203 {
204 // If we are in game then remove this player from the game as well.
205 // We may get here either from the player requesting to exit the game,
206 // in which case we they will already have left the game server, or from a disconnection
207 // where we then have to remove them from the game server
208 if( m_pDQRNet->IsHost() && !m_bHostChanged )
209 {
210 g_NetworkManager.CloseConnection(networkPlayer);
211 }
212
213 // Free the wrapper object memory.
214 // TODO 4J Stu - We may still be using this at the point that the player leaves the session.
215 // We need this as long as the game server still needs to communicate with the player
216 //delete socket;
217
218 networkPlayer->SetSocket( NULL );
219 }
220
221 if( m_pDQRNet->IsHost() && !m_bHostChanged )
222 {
223 if( isSystemPrimaryPlayer(pDQRPlayer) )
224 {
225 DQRNetworkPlayer *pNewDQRPrimaryPlayer = NULL;
226 for(unsigned int i = 0; i < m_pDQRNet->GetPlayerCount(); ++i )
227 {
228 DQRNetworkPlayer *pDQRPlayer2 = m_pDQRNet->GetPlayerByIndex( i );
229
230 if( pDQRPlayer2 != pDQRPlayer && pDQRPlayer2->IsSameSystem( pDQRPlayer ) )
231 {
232 pNewDQRPrimaryPlayer = pDQRPlayer2;
233 break;
234 }
235 }
236 AUTO_VAR(it, find( m_machineDQRPrimaryPlayers.begin(), m_machineDQRPrimaryPlayers.end(), pDQRPlayer));
237 if( it != m_machineDQRPrimaryPlayers.end() )
238 {
239 m_machineDQRPrimaryPlayers.erase( it );
240 }
241
242 if( pNewDQRPrimaryPlayer != NULL )
243 m_machineDQRPrimaryPlayers.push_back( pNewDQRPrimaryPlayer );
244 }
245
246 g_NetworkManager.UpdateAndSetGameSessionData( networkPlayer );
247 SystemFlagRemovePlayer( networkPlayer );
248
249 }
250
251 g_NetworkManager.PlayerLeaving( networkPlayer );
252
253 for( int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
254 {
255 if(playerChangedCallback[idx] != NULL)
256 playerChangedCallback[idx]( playerChangedCallbackParam[idx], networkPlayer, true );
257 }
258
259 if(m_pDQRNet->GetState() == DQRNetworkManager::DNM_STATE_PLAYING)
260 {
261 int localPlayerCount = 0;
262 for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
263 {
264 if( m_pDQRNet->GetLocalPlayerByUserIndex(idx) != NULL ) ++localPlayerCount;
265 }
266
267 float appTime = app.getAppTime();
268 m_lastPlayerEventTimeStart = appTime;
269 }
270
271 removeNetworkPlayer(pDQRPlayer);
272 }
273}
274
275void CPlatformNetworkManagerDurango::HandleDataReceived(DQRNetworkPlayer *playerFrom, DQRNetworkPlayer *playerTo, unsigned char *data, unsigned int dataSize)
276{
277#if 0
278 // TODO - put this back in
279 if(m_pSQRNet->GetState() == SQRNetworkManager::SNM_STATE_ENDING)
280 {
281 return;
282 }
283#endif
284
285 if( playerTo->IsHost() )
286 {
287 // If we are the host we care who this came from
288 //app.DebugPrintf( "Pushing data into host read queue for user \"%ls\"\n", pPlayerFrom->GetGamertag());
289 // Push this data into the read queue for the player that sent it
290 INetworkPlayer *pPlayerFrom = getNetworkPlayer(playerFrom);
291 Socket *socket = pPlayerFrom->GetSocket();
292
293 if(socket != NULL)
294 socket->pushDataToQueue(data, dataSize, false);
295 }
296 else
297 {
298 // If we are not the host the message must have come from the host, so we care more about who it is addressed to
299 INetworkPlayer *pPlayerTo = getNetworkPlayer(playerTo);
300 Socket *socket = pPlayerTo->GetSocket();
301 //app.DebugPrintf( "Pushing data into read queue for user \"%ls\"\n", apPlayersTo[dwPlayer]->GetGamertag());
302 if(socket != NULL)
303 socket->pushDataToQueue(data, dataSize);
304 }
305}
306
307void CPlatformNetworkManagerDurango::HandleInviteReceived(int playerIndex, DQRNetworkManager::SessionInfo *pInviteInfo)
308{
309 g_NetworkManager.GameInviteReceived(playerIndex, pInviteInfo);
310}
311
312bool CPlatformNetworkManagerDurango::Initialise(CGameNetworkManager *pGameNetworkManager, int flagIndexSize)
313{
314 m_pDQRNet = new DQRNetworkManager(this);
315 m_pDQRNet->Initialise();
316
317 m_hostGameSessionIsJoinable = false;
318 m_pGameNetworkManager = pGameNetworkManager;
319 m_flagIndexSize = flagIndexSize;
320 g_pPlatformNetworkManager = this;
321 for( int i = 0; i < XUSER_MAX_COUNT; i++ )
322 {
323 playerChangedCallback[ i ] = NULL;
324 }
325
326 m_bLeavingGame = false;
327 m_bLeaveGameOnTick = false;
328 m_bHostChanged = false;
329
330 m_bSearchResultsReady = false;
331 m_bSearchPending = false;
332
333 m_bIsOfflineGame = false;
334 m_pSearchParam = NULL;
335 m_SessionsUpdatedCallback = NULL;
336
337 m_searchResultsCount = 0;
338 m_lastSearchStartTime = 0;
339
340 // The results that will be filled in with the current search
341 m_pSearchResults = NULL;
342
343 Windows::Networking::Connectivity::NetworkInformation::NetworkStatusChanged += ref new Windows::Networking::Connectivity::NetworkStatusChangedEventHandler( []( Platform::Object^ pxObject )
344 {
345 app.DebugPrintf("NetworkStatusChanged callback\n" );
346 auto internetProfile = Windows::Networking::Connectivity::NetworkInformation::GetInternetConnectionProfile();
347 if (internetProfile != nullptr)
348 {
349 auto connectionLevel = internetProfile->GetNetworkConnectivityLevel();
350 app.DebugPrintf("Connection level has changed to (%d)\n", connectionLevel);
351
352 //int iPrimaryPlayer = g_NetworkManager.GetPrimaryPad();
353 //bool bConnected = (connectionLevel == Windows::Networking::Connectivity::NetworkConnectivityLevel::XboxLiveAccess)?true:false;
354 //if((g_NetworkManager.GetLockedProfile()!=-1) && iPrimaryPlayer!=-1 && bConnected == false && g_NetworkManager.IsInSession() )
355 //{
356 // app.SetAction(iPrimaryPlayer,eAppAction_EthernetDisconnected);
357 //}
358 }
359 });
360
361 // Success!
362 return true;
363}
364
365void CPlatformNetworkManagerDurango::Terminate()
366{
367}
368
369int CPlatformNetworkManagerDurango::GetJoiningReadyPercentage()
370{
371 return 100;
372}
373
374int CPlatformNetworkManagerDurango::CorrectErrorIDS(int IDS)
375{
376 return IDS;
377}
378
379bool CPlatformNetworkManagerDurango::isSystemPrimaryPlayer(DQRNetworkPlayer *pDQRPlayer)
380{
381 bool playerIsSystemPrimary = false;
382 for(auto it = m_machineDQRPrimaryPlayers.begin(); it < m_machineDQRPrimaryPlayers.end(); ++it)
383 {
384 DQRNetworkPlayer *pDQRPrimaryPlayer = *it;
385 if( pDQRPrimaryPlayer == pDQRPlayer )
386 {
387 playerIsSystemPrimary = true;
388 break;
389 }
390 }
391 return playerIsSystemPrimary;
392}
393
394// We call this twice a frame, either side of the render call so is a good place to "tick" things
395void CPlatformNetworkManagerDurango::DoWork()
396{
397 m_pDQRNet->Tick();
398
399 TickSearch();
400
401 if( m_bLeaveGameOnTick )
402 {
403 m_pDQRNet->LeaveRoom();
404 m_bLeaveGameOnTick = false;
405 }
406}
407
408int CPlatformNetworkManagerDurango::GetPlayerCount()
409{
410 return m_pDQRNet->GetPlayerCount();
411}
412
413bool CPlatformNetworkManagerDurango::ShouldMessageForFullSession()
414{
415 return m_pDQRNet->ShouldMessageForFullSession();
416}
417
418int CPlatformNetworkManagerDurango::GetOnlinePlayerCount()
419{
420 return m_pDQRNet->GetOnlinePlayerCount();
421}
422
423int CPlatformNetworkManagerDurango::GetLocalPlayerMask(int playerIndex)
424{
425 return 1 << playerIndex;
426}
427
428bool CPlatformNetworkManagerDurango::AddLocalPlayerByUserIndex( int userIndex )
429{
430 return m_pDQRNet->AddLocalPlayerByUserIndex( userIndex );
431}
432
433bool CPlatformNetworkManagerDurango::RemoveLocalPlayerByUserIndex( int userIndex )
434{
435 return m_pDQRNet->RemoveLocalPlayerByUserIndex( userIndex );
436}
437
438bool CPlatformNetworkManagerDurango::IsInStatsEnabledSession()
439{
440 return true;
441}
442
443bool CPlatformNetworkManagerDurango::SessionHasSpace(unsigned int spaceRequired /*= 1*/)
444{
445 return true;
446}
447
448void CPlatformNetworkManagerDurango::SendInviteGUI(int quadrant)
449{
450 m_pDQRNet->SendInviteGUI(quadrant);
451}
452
453bool CPlatformNetworkManagerDurango::IsAddingPlayer()
454{
455 return m_pDQRNet->IsAddingPlayer();
456}
457
458bool CPlatformNetworkManagerDurango::LeaveGame(bool bMigrateHost)
459{
460 if( m_bLeavingGame ) return true;
461
462 m_bLeavingGame = true;
463
464 // If we are the host wait for the game server to end
465 if(m_pDQRNet->IsHost() && g_NetworkManager.ServerStoppedValid())
466 {
467// m_pDQRNet->EndGame();
468 g_NetworkManager.ServerStoppedWait();
469 g_NetworkManager.ServerStoppedDestroy();
470 }
471 return _LeaveGame(bMigrateHost, true);;
472}
473
474bool CPlatformNetworkManagerDurango::_LeaveGame(bool bMigrateHost, bool bLeaveRoom)
475{
476 m_bLeavingGame = true;
477 m_bLeaveGameOnTick = true;
478 m_migrateHostOnLeave = bMigrateHost;
479 return true;
480}
481
482void CPlatformNetworkManagerDurango::HostGame(int localUsersMask, bool bOnlineGame, bool bIsPrivate, unsigned char publicSlots /*= MINECRAFT_NET_MAX_PLAYERS*/, unsigned char privateSlots /*= 0*/)
483{
484// #ifdef _XBOX
485 // 4J Stu - We probably did this earlier as well, but just to be sure!
486 SetLocalGame( !bOnlineGame );
487 SetPrivateGame( bIsPrivate );
488 SystemFlagReset();
489
490 // Make sure that the Primary Pad is in by default
491 localUsersMask |= GetLocalPlayerMask( g_NetworkManager.GetPrimaryPad() );
492
493 m_bLeavingGame = false;
494
495 _HostGame( localUsersMask, publicSlots, privateSlots );
496//#endif
497}
498
499void CPlatformNetworkManagerDurango::_HostGame(int usersMask, unsigned char publicSlots /*= MINECRAFT_NET_MAX_PLAYERS*/, unsigned char privateSlots /*= 0*/)
500{
501 memset(&m_hostGameSessionData,0,sizeof(m_hostGameSessionData));
502 m_hostGameSessionData.netVersion = MINECRAFT_NET_VERSION;
503 m_hostGameSessionData.isReadyToJoin = false;
504 m_hostGameSessionData.m_uiGameHostSettings = app.GetGameHostOption(eGameHostOption_All);
505 m_hostGameSessionIsJoinable = !IsPrivateGame();
506
507 m_pDQRNet->CreateAndJoinSession(usersMask, (unsigned char *)&m_hostGameSessionData, sizeof(m_hostGameSessionData), IsLocalGame() );
508}
509
510bool CPlatformNetworkManagerDurango::_StartGame()
511{
512 return true;
513}
514
515int CPlatformNetworkManagerDurango::JoinGame(FriendSessionInfo *searchResult, int localUsersMask, int primaryUserIndex)
516{
517 app.DebugPrintf("Joining game party from search result\n");
518
519 int joinPlayerCount = 0;
520 for( int i = 0; i < DQRNetworkManager::MAX_LOCAL_PLAYER_COUNT; i++ )
521 {
522 if( localUsersMask & ( 1 << i ) )
523 {
524 // Check if this joining user is already in the session, in which case we don't need to count it
525 bool isJoiningUser = false;
526 for( int j = 0; j < searchResult->searchResult.m_usedSlotCount; j++ )
527 {
528 Platform::String^ xuid = ref new Platform::String(searchResult->searchResult.m_sessionXuids[j].c_str());
529 if( xuid == ProfileManager.GetUser(i)->XboxUserId )
530 {
531 app.DebugPrintf("Joining user found to be already in session, so won't be counting to our total\n");
532 isJoiningUser = true;
533 break;
534 }
535 }
536 if( !isJoiningUser )
537 {
538 joinPlayerCount++;
539 }
540 }
541 }
542 app.DebugPrintf("Used slots: %d, fully playing players: %d, trying to join %d\n", searchResult->searchResult.m_usedSlotCount, searchResult->searchResult.m_playerCount, joinPlayerCount);
543 GameSessionData *gameSession = (GameSessionData *)(&searchResult->data);
544 if( ( searchResult->searchResult.m_usedSlotCount + joinPlayerCount ) > DQRNetworkManager::MAX_ONLINE_PLAYER_COUNT )
545 {
546 return CGameNetworkManager::JOINGAME_FAIL_SERVER_FULL;
547 }
548
549 if(m_pDQRNet->JoinPartyFromSearchResult(&searchResult->searchResult, localUsersMask))
550 {
551 app.DebugPrintf("Join success\n");
552 return CGameNetworkManager::JOINGAME_SUCCESS;
553 }
554 else
555 {
556 app.DebugPrintf("Join fail\n");
557 return CGameNetworkManager::JOINGAME_FAIL_GENERAL;
558 }
559}
560
561void CPlatformNetworkManagerDurango::CancelJoinGame()
562{
563 m_pDQRNet->CancelJoinPartyFromSearchResult();
564}
565
566bool CPlatformNetworkManagerDurango::SetLocalGame(bool isLocal)
567{
568 m_bIsOfflineGame = isLocal;
569
570 return true;
571}
572
573void CPlatformNetworkManagerDurango::SetPrivateGame(bool isPrivate)
574{
575 app.DebugPrintf("Setting as private game: %s\n", isPrivate ? "yes" : "no" );
576 m_bIsPrivateGame = isPrivate;
577}
578
579void CPlatformNetworkManagerDurango::RegisterPlayerChangedCallback(int iPad, void (*callback)(void *callbackParam, INetworkPlayer *pPlayer, bool leaving), void *callbackParam)
580{
581 playerChangedCallback[iPad] = callback;
582 playerChangedCallbackParam[iPad] = callbackParam;
583}
584
585void CPlatformNetworkManagerDurango::UnRegisterPlayerChangedCallback(int iPad, void (*callback)(void *callbackParam, INetworkPlayer *pPlayer, bool leaving), void *callbackParam)
586{
587 if(playerChangedCallbackParam[iPad] == callbackParam)
588 {
589 playerChangedCallback[iPad] = NULL;
590 playerChangedCallbackParam[iPad] = NULL;
591 }
592}
593
594void CPlatformNetworkManagerDurango::HandleSignInChange()
595{
596 return;
597}
598
599void CPlatformNetworkManagerDurango::HandleAddLocalPlayerFailed(int idx, bool serverFull)
600{
601 g_NetworkManager.AddLocalPlayerFailed(idx, serverFull);
602}
603
604void CPlatformNetworkManagerDurango::HandleDisconnect(bool bLostRoomOnly)
605{
606 g_NetworkManager.HandleDisconnect(bLostRoomOnly);
607}
608
609bool CPlatformNetworkManagerDurango::_RunNetworkGame()
610{
611 m_pDQRNet->StartGame();
612 m_hostGameSessionData.isReadyToJoin = true;
613 m_pDQRNet->UpdateCustomSessionData();
614 return true;
615}
616
617void CPlatformNetworkManagerDurango::UpdateAndSetGameSessionData(INetworkPlayer *pNetworkPlayerLeaving /*= NULL*/)
618{
619 if( this->m_bLeavingGame )
620 return;
621
622 if( GetHostPlayer() == NULL )
623 return;
624
625 m_hostGameSessionData.m_uiGameHostSettings = app.GetGameHostOption(eGameHostOption_All);
626
627 m_pDQRNet->UpdateCustomSessionData();
628}
629
630int CPlatformNetworkManagerDurango::RemovePlayerOnSocketClosedThreadProc( void* lpParam )
631{
632 INetworkPlayer *pNetworkPlayer = (INetworkPlayer *)lpParam;
633
634 Socket *socket = pNetworkPlayer->GetSocket();
635
636 if( socket != NULL )
637 {
638 //printf("Waiting for socket closed event\n");
639 socket->m_socketClosedEvent->WaitForSignal(INFINITE);
640
641 //printf("Socket closed event has fired\n");
642 // 4J Stu - Clear our reference to this socket
643 pNetworkPlayer->SetSocket( NULL );
644 delete socket;
645 }
646
647 return g_pPlatformNetworkManager->RemoveLocalPlayer( pNetworkPlayer );
648}
649
650bool CPlatformNetworkManagerDurango::RemoveLocalPlayer( INetworkPlayer *pNetworkPlayer )
651{
652 return true;
653}
654
655CPlatformNetworkManagerDurango::PlayerFlags::PlayerFlags(INetworkPlayer *pNetworkPlayer, unsigned int count)
656{
657 // 4J Stu - Don't assert, just make it a multiple of 8! This count is calculated from a load of separate values,
658 // and makes tweaking world/render sizes a pain if we hit an assert here
659 count = (count + 8 - 1) & ~(8 - 1);
660 //assert( ( count % 8 ) == 0 );
661 this->m_pNetworkPlayer = pNetworkPlayer;
662 this->flags = new unsigned char [ count / 8 ];
663 memset( this->flags, 0, count / 8 );
664 this->count = count;
665}
666
667CPlatformNetworkManagerDurango::PlayerFlags::~PlayerFlags()
668{
669 delete [] flags;
670}
671
672// Add a player to the per system flag storage - if we've already got a player from that system, copy its flags over
673void CPlatformNetworkManagerDurango::SystemFlagAddPlayer(INetworkPlayer *pNetworkPlayer)
674{
675 PlayerFlags *newPlayerFlags = new PlayerFlags( pNetworkPlayer, m_flagIndexSize);
676 // If any of our existing players are on the same system, then copy over flags from that one
677 for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
678 {
679 if( pNetworkPlayer->IsSameSystem(m_playerFlags[i]->m_pNetworkPlayer) )
680 {
681 memcpy( newPlayerFlags->flags, m_playerFlags[i]->flags, m_playerFlags[i]->count / 8 );
682 break;
683 }
684 }
685 m_playerFlags.push_back(newPlayerFlags);
686}
687
688// Remove a player from the per system flag storage - just maintains the m_playerFlags vector without any gaps in it
689void CPlatformNetworkManagerDurango::SystemFlagRemovePlayer(INetworkPlayer *pNetworkPlayer)
690{
691 for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
692 {
693 if( m_playerFlags[i]->m_pNetworkPlayer == pNetworkPlayer )
694 {
695 delete m_playerFlags[i];
696 m_playerFlags[i] = m_playerFlags.back();
697 m_playerFlags.pop_back();
698 return;
699 }
700 }
701}
702
703void CPlatformNetworkManagerDurango::SystemFlagReset()
704{
705 for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
706 {
707 delete m_playerFlags[i];
708 }
709 m_playerFlags.clear();
710}
711
712// Set a per system flag - this is done by setting the flag on every player that shares that system
713void CPlatformNetworkManagerDurango::SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index)
714{
715 if( ( index < 0 ) || ( index >= m_flagIndexSize ) ) return;
716 if( pNetworkPlayer == NULL ) return;
717
718 for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
719 {
720 if( pNetworkPlayer->IsSameSystem(m_playerFlags[i]->m_pNetworkPlayer) )
721 {
722 m_playerFlags[i]->flags[ index / 8 ] |= ( 128 >> ( index % 8 ) );
723 }
724 }
725}
726
727// Get value of a per system flag - can be read from the flags of the passed in player as anything else sent to that
728// system should also have been duplicated here
729bool CPlatformNetworkManagerDurango::SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index)
730{
731 if( ( index < 0 ) || ( index >= m_flagIndexSize ) ) return false;
732 if( pNetworkPlayer == NULL )
733 {
734 return false;
735 }
736
737 for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
738 {
739 if( m_playerFlags[i]->m_pNetworkPlayer == pNetworkPlayer )
740 {
741 return ( ( m_playerFlags[i]->flags[ index / 8 ] & ( 128 >> ( index % 8 ) ) ) != 0 );
742 }
743 }
744 return false;
745}
746
747wstring CPlatformNetworkManagerDurango::GatherStats()
748{
749 return L"";
750}
751
752wstring CPlatformNetworkManagerDurango::GatherRTTStats()
753{
754 return L"";
755}
756
757void CPlatformNetworkManagerDurango::TickSearch()
758{
759 if( m_bSearchPending )
760 {
761 if( !m_pDQRNet->FriendPartyManagerIsBusy() )
762 {
763 m_searchResultsCount = m_pDQRNet->FriendPartyManagerGetCount();
764 delete [] m_pSearchResults;
765 m_pSearchResults = new DQRNetworkManager::SessionSearchResult[m_searchResultsCount];
766
767 for( int i = 0; i < m_searchResultsCount; i++ )
768 {
769 m_pDQRNet->FriendPartyManagerGetSessionInfo(i, &m_pSearchResults[i] );
770 }
771 m_bSearchPending = false;
772
773 if( m_SessionsUpdatedCallback != NULL ) m_SessionsUpdatedCallback(m_pSearchParam);
774 }
775 }
776 else
777 {
778 if( !m_pDQRNet->FriendPartyManagerIsBusy() )
779 {
780 // Don't start searches unless we have registered a callback
781 if( m_SessionsUpdatedCallback != NULL && (m_lastSearchStartTime + MINECRAFT_DURANGO_PARTY_SEARCH_DELAY_MILLISECONDS) < GetTickCount() )
782 {
783 if( m_pDQRNet->FriendPartyManagerSearch() );
784 {
785 m_bSearchPending = true;
786 m_lastSearchStartTime = GetTickCount();
787 }
788 }
789 }
790 }
791}
792
793vector<FriendSessionInfo *> *CPlatformNetworkManagerDurango::GetSessionList(int iPad, int localPlayers, bool partyOnly)
794{
795 vector<FriendSessionInfo *> *filteredList = new vector<FriendSessionInfo *>();
796 for( int i = 0; i < m_searchResultsCount; i++ )
797 {
798 GameSessionData *gameSessionData = (GameSessionData *)m_pSearchResults[i].m_extData;
799 if( ( gameSessionData->netVersion == MINECRAFT_NET_VERSION ) &&
800 ( gameSessionData->isReadyToJoin ) )
801 {
802 FriendSessionInfo *session = new FriendSessionInfo();
803 session->searchResult = m_pSearchResults[i];
804 session->searchResult.m_extData = NULL; // We have another copy of the GameSessionData, so don't need to make another copy of this here
805 session->displayLabelLength = session->searchResult.m_playerNames[0].size();
806 session->displayLabel = new wchar_t[ session->displayLabelLength + 1 ];
807 memcpy(&session->data, gameSessionData, sizeof(GameSessionData));
808 wcscpy_s(session->displayLabel, session->displayLabelLength + 1, session->searchResult.m_playerNames[0].c_str() );
809 filteredList->push_back(session);
810 }
811 }
812 return filteredList;
813}
814
815bool CPlatformNetworkManagerDurango::GetGameSessionInfo(int iPad, SessionID sessionId, FriendSessionInfo *foundSessionInfo)
816{
817 return false;
818}
819
820void CPlatformNetworkManagerDurango::SetSessionsUpdatedCallback( void (*SessionsUpdatedCallback)(LPVOID pParam), LPVOID pSearchParam )
821{
822 m_SessionsUpdatedCallback = SessionsUpdatedCallback; m_pSearchParam = pSearchParam;
823}
824
825void CPlatformNetworkManagerDurango::GetFullFriendSessionInfo( FriendSessionInfo *foundSession, void (* FriendSessionUpdatedFn)(bool success, void *pParam), void *pParam )
826{
827 FriendSessionUpdatedFn(true, pParam);
828}
829
830void CPlatformNetworkManagerDurango::ForceFriendsSessionRefresh()
831{
832 app.DebugPrintf("Resetting friends session search data\n");
833 m_lastSearchStartTime = 0;
834 m_searchResultsCount = 0;
835 delete [] m_pSearchResults;
836 m_pSearchResults = NULL;
837}
838
839INetworkPlayer *CPlatformNetworkManagerDurango::addNetworkPlayer(DQRNetworkPlayer *pDQRPlayer)
840{
841 NetworkPlayerDurango *pNetworkPlayer = new NetworkPlayerDurango(pDQRPlayer);
842 pDQRPlayer->SetCustomDataValue((ULONG_PTR)pNetworkPlayer);
843 currentNetworkPlayers.push_back( pNetworkPlayer );
844 return pNetworkPlayer;
845}
846
847void CPlatformNetworkManagerDurango::removeNetworkPlayer(DQRNetworkPlayer *pDQRPlayer)
848{
849 INetworkPlayer *pNetworkPlayer = getNetworkPlayer(pDQRPlayer);
850 for( AUTO_VAR(it, currentNetworkPlayers.begin()); it != currentNetworkPlayers.end(); it++ )
851 {
852 if( *it == pNetworkPlayer )
853 {
854 currentNetworkPlayers.erase(it);
855 return;
856 }
857 }
858}
859
860INetworkPlayer *CPlatformNetworkManagerDurango::getNetworkPlayer(DQRNetworkPlayer *pDQRPlayer)
861{
862 return pDQRPlayer ? (INetworkPlayer *)(pDQRPlayer->GetCustomDataValue()) : NULL;
863}
864
865
866INetworkPlayer *CPlatformNetworkManagerDurango::GetLocalPlayerByUserIndex(int userIndex )
867{
868 return getNetworkPlayer(m_pDQRNet->GetLocalPlayerByUserIndex(userIndex));
869}
870
871INetworkPlayer *CPlatformNetworkManagerDurango::GetPlayerByIndex(int playerIndex)
872{
873 return getNetworkPlayer(m_pDQRNet->GetPlayerByIndex(playerIndex));
874}
875
876INetworkPlayer * CPlatformNetworkManagerDurango::GetPlayerByXuid(PlayerUID xuid)
877{
878 return getNetworkPlayer(m_pDQRNet->GetPlayerByXuid(xuid)) ;
879}
880
881INetworkPlayer * CPlatformNetworkManagerDurango::GetPlayerBySmallId(unsigned char smallId)
882{
883 return getNetworkPlayer(m_pDQRNet->GetPlayerBySmallId(smallId));
884}
885
886wstring CPlatformNetworkManagerDurango::GetDisplayNameByGamertag(wstring gamertag)
887{
888 return m_pDQRNet->GetDisplayNameByGamertag(gamertag);
889}
890
891INetworkPlayer *CPlatformNetworkManagerDurango::GetHostPlayer()
892{
893 return getNetworkPlayer(m_pDQRNet->GetHostPlayer());
894}
895
896bool CPlatformNetworkManagerDurango::IsHost()
897{
898 return m_pDQRNet->IsHost() && !m_bHostChanged;
899}
900
901bool CPlatformNetworkManagerDurango::JoinGameFromInviteInfo( int userIndex, int userMask, const INVITE_INFO *pInviteInfo)
902{
903 m_pDQRNet->m_currentUserMask = userMask;
904 m_pDQRNet->JoinSessionFromInviteInfo(userMask);
905 return true;
906}
907
908void CPlatformNetworkManagerDurango::SetSessionTexturePackParentId( int id )
909{
910 m_hostGameSessionData.texturePackParentId = id;
911}
912
913void CPlatformNetworkManagerDurango::SetSessionSubTexturePackId( int id )
914{
915 m_hostGameSessionData.subTexturePackId = id;
916}
917
918void CPlatformNetworkManagerDurango::Notify(int ID, ULONG_PTR Param)
919{
920}
921
922bool CPlatformNetworkManagerDurango::IsInSession()
923{
924 return m_pDQRNet->IsInSession();
925}
926
927bool CPlatformNetworkManagerDurango::IsInGameplay()
928{
929 return m_pDQRNet->GetState() == DQRNetworkManager::DNM_STATE_PLAYING;
930}
931
932bool CPlatformNetworkManagerDurango::IsReadyToPlayOrIdle()
933{
934 return m_pDQRNet->IsReadyToPlayOrIdle();
935}
936
937bool CPlatformNetworkManagerDurango::IsSessionJoinable()
938{
939 return m_hostGameSessionIsJoinable;
940}