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 <xuiresource.h>
3#include <xuiapp.h>
4#include <assert.h>
5#include "..\..\..\Minecraft.World\StringHelpers.h"
6#include "..\..\Common\Tutorial\TutorialMode.h"
7#include "..\..\..\Minecraft.World\ConsoleSaveFileIO.h"
8#include "..\..\LocalPlayer.h"
9#include "..\..\Minecraft.h"
10#include "..\..\ProgressRenderer.h"
11#include "..\..\..\Minecraft.World\AABB.h"
12#include "..\..\..\Minecraft.World\Vec3.h"
13#include "..\..\..\Minecraft.World\ArrayWithLength.h"
14#include "..\..\..\Minecraft.World\File.h"
15#include "..\..\..\Minecraft.World\InputOutputStream.h"
16#include "XUI_Ctrl_4JList.h"
17#include "XUI_Ctrl_4JIcon.h"
18#include "XUI_LoadSettings.h"
19#include "XUI_MultiGameInfo.h"
20#include "XUI_MultiGameJoinLoad.h"
21#include "XUI_MultiGameCreate.h"
22#include "..\..\MinecraftServer.h"
23#include "..\..\Options.h"
24
25#include "..\GameRules\LevelGenerationOptions.h"
26#include "..\..\TexturePackRepository.h"
27#include "..\..\TexturePack.h"
28#include "..\..\..\Minecraft.World\LevelSettings.h"
29
30#define CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID 3
31#define CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME 100
32
33//----------------------------------------------------------------------------------
34// Performs initialization tasks - retrieves controls.
35//----------------------------------------------------------------------------------
36HRESULT CScene_MultiGameJoinLoad::OnInit( XUIMessageInit* pInitData, BOOL& bHandled )
37{
38
39 m_iPad=*(int *)pInitData->pvInitData;
40 m_bReady=false;
41 MapChildControls();
42
43 m_iTexturePacksNotInstalled=0;
44 m_iConfigA=NULL;
45
46 XuiControlSetText(m_LabelNoGames,app.GetString(IDS_NO_GAMES_FOUND));
47 XuiControlSetText(m_GamesList,app.GetString(IDS_JOIN_GAME));
48 XuiControlSetText(m_SavesList,app.GetString(IDS_START_GAME));
49
50
51 const DWORD LOCATOR_SIZE = 256; // Use this to allocate space to hold a ResourceLocator string
52 WCHAR szResourceLocator[ LOCATOR_SIZE ];
53
54 const ULONG_PTR c_ModuleHandle = (ULONG_PTR)GetModuleHandle(NULL);
55 swprintf(szResourceLocator, LOCATOR_SIZE ,L"section://%X,%ls#%ls",c_ModuleHandle,L"media", L"media/Graphics/TexturePackIcon.png");
56
57 m_DefaultMinecraftIconSize = 0;
58 HRESULT hr = XuiResourceLoadAllNoLoc(szResourceLocator, &m_DefaultMinecraftIconData, &m_DefaultMinecraftIconSize);
59
60 m_localPlayers = 1;
61 m_bKillSaveInfoEnumerate=false;
62
63 m_bShowingPartyGamesOnly = false;
64
65 m_bRetrievingSaveInfo=false;
66 m_bSaveTransferInProgress=false;
67
68 // check for a default custom cloak in the global storage
69 // 4J-PB - changed to a config file
70// if(ProfileManager.IsSignedInLive( m_iPad ))
71// {
72// app.InstallDefaultCape();
73// }
74
75 m_initData= new JoinMenuInitData();
76 m_bMultiplayerAllowed = ProfileManager.IsSignedInLive( m_iPad ) && ProfileManager.AllowedToPlayMultiplayer(m_iPad);
77
78 XPARTY_USER_LIST partyList;
79
80 if((XPartyGetUserList( &partyList ) != XPARTY_E_NOT_IN_PARTY ) && (partyList.dwUserCount>1))
81 {
82 m_bInParty=true;
83 }
84 else
85 {
86 m_bInParty=false;
87 }
88
89 int iLB = -1;
90 if(m_bInParty) iLB = IDS_TOOLTIPS_PARTY_GAMES;
91
92 XuiSetTimer(m_hObj,JOIN_LOAD_ONLINE_TIMER_ID,JOIN_LOAD_ONLINE_TIMER_TIME);
93
94 m_iSaveInfoC=0;
95
96 VOID *pObj;
97 XuiObjectFromHandle( m_SavesList, &pObj );
98 m_pSavesList = (CXuiCtrl4JList *)pObj;
99
100 XuiObjectFromHandle( m_GamesList, &pObj );
101 m_pGamesList = (CXuiCtrl4JList *)pObj;
102
103 // block input if we're waiting for DLC to install, and wipe the saves list. The end of dlc mounting custom message will fill the list again
104 if(app.StartInstallDLCProcess(m_iPad)==true)
105 {
106 // not doing a mount, so enable input
107 m_bIgnoreInput=true;
108 }
109 else
110 {
111 // if we're waiting for DLC to mount, don't fill the save list. The custom message on end of dlc mounting will do that
112 m_bIgnoreInput=false;
113
114
115
116 m_iChangingSaveGameInfoIndex = 0;
117
118 m_generators = app.getLevelGenerators();
119 m_iDefaultButtonsC = 0;
120 m_iMashUpButtonsC=0;
121
122 // check if we're in the trial version
123 if(ProfileManager.IsFullVersion()==false)
124 {
125 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK, -1, -1, -1, -1,iLB);
126
127 AddDefaultButtons();
128
129 m_pSavesList->SetCurSelVisible(0);
130 }
131 else if(StorageManager.GetSaveDisabled())
132 {
133 if(StorageManager.GetSaveDeviceSelected(m_iPad))
134 {
135 // saving is disabled, but we should still be able to load from a selected save device
136
137 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_CHANGEDEVICE,-1,-1,-1,iLB,IDS_TOOLTIPS_DELETESAVE);
138
139 GetSaveInfo();
140 }
141 else
142 {
143 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE,-1,-1,-1,iLB);
144
145 AddDefaultButtons();
146 m_SavesListTimer.SetShow( FALSE );
147
148 m_pSavesList->SetCurSelVisible(0);
149 }
150 }
151 else
152 {
153 // 4J-PB - we need to check that there is enough space left to create a copy of the save (for a rename)
154 bool bCanRename = StorageManager.EnoughSpaceForAMinSaveGame();
155 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_CHANGEDEVICE,-1,-1,-1,-1,bCanRename?IDS_TOOLTIPS_SAVEOPTIONS:IDS_TOOLTIPS_DELETESAVE);
156
157 GetSaveInfo();
158 }
159 }
160 //XuiElementSetDisableFocusRecursion( m_pGamesList->m_hObj, TRUE);
161
162 UpdateGamesList();
163
164 g_NetworkManager.SetSessionsUpdatedCallback( &CScene_MultiGameJoinLoad::UpdateGamesListCallback, this );
165
166 // 4J Stu - Fix for #12530 -TCR 001 BAS Game Stability: Title will crash if the player disconnects while starting a new world and then opts to play the tutorial once they have been returned to the Main Menu.
167 MinecraftServer::resetFlags();
168
169 // If we're not ignoring input, then we aren't still waiting for the DLC to mount, and can now check for corrupt dlc. Otherwise this will happen when the dlc has finished mounting.
170 if( !m_bIgnoreInput)
171 {
172 app.m_dlcManager.checkForCorruptDLCAndAlert();
173 }
174
175
176 // 4J-PB - Load up any texture pack data we have locally in the XZP
177 for(int i=0;i<TMS_COUNT;i++)
178 {
179 if(app.TMSFileA[i].eTMSType==eTMSFileType_TexturePack)
180 {
181 app.LoadLocalTMSFile(app.TMSFileA[i].wchFilename,app.TMSFileA[i].eEXT);
182 app.AddMemoryTPDFile(app.TMSFileA[i].iConfig, app.TMSFileA[i].pbData,app.TMSFileA[i].uiSize);
183 }
184 }
185
186 // 4J-PB - there may be texture packs we don't have, so use the info from TMS for this
187
188 DLC_INFO *pDLCInfo=NULL;
189
190 // first pass - look to see if there are any that are not in the list
191 bool bTexturePackAlreadyListed;
192 bool bNeedToGetTPD=false;
193 Minecraft *pMinecraft = Minecraft::GetInstance();
194 int texturePacksCount = pMinecraft->skins->getTexturePackCount();
195 //CXuiCtrl4JList::LIST_ITEM_INFO ListInfo;
196 //HRESULT hr;
197
198
199 for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i)
200 {
201 bTexturePackAlreadyListed=false;
202 ULONGLONG ull=app.GetDLCInfoTexturesFullOffer(i);
203 pDLCInfo=app.GetDLCInfoForFullOfferID(ull);
204 for(unsigned int i = 0; i < texturePacksCount; ++i)
205 {
206 TexturePack *tp = pMinecraft->skins->getTexturePackByIndex(i);
207 if(pDLCInfo->iConfig==tp->getDLCParentPackId())
208 {
209 bTexturePackAlreadyListed=true;
210 }
211 }
212 if(bTexturePackAlreadyListed==false)
213 {
214 // some missing
215 bNeedToGetTPD=true;
216
217 m_iTexturePacksNotInstalled++;
218 }
219 }
220
221 if(bNeedToGetTPD==true)
222 {
223 // add a TMS request for them
224 app.DebugPrintf("+++ Adding TMSPP request for texture pack data\n");
225 app.AddTMSPPFileTypeRequest(e_DLC_TexturePackData);
226 m_iConfigA= new int [m_iTexturePacksNotInstalled];
227 m_iTexturePacksNotInstalled=0;
228
229 for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i)
230 {
231 bTexturePackAlreadyListed=false;
232 ULONGLONG ull=app.GetDLCInfoTexturesFullOffer(i);
233 pDLCInfo=app.GetDLCInfoForFullOfferID(ull);
234 for(unsigned int i = 0; i < texturePacksCount; ++i)
235 {
236 TexturePack *tp = pMinecraft->skins->getTexturePackByIndex(i);
237 if(pDLCInfo->iConfig==tp->getDLCParentPackId())
238 {
239 bTexturePackAlreadyListed=true;
240 }
241 }
242 if(bTexturePackAlreadyListed==false)
243 {
244 m_iConfigA[m_iTexturePacksNotInstalled++]=pDLCInfo->iConfig;
245 }
246 }
247 }
248
249 XuiSetTimer(m_hObj,CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID,CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME);
250
251 return S_OK;
252}
253
254void CScene_MultiGameJoinLoad::AddDefaultButtons()
255{
256 CXuiCtrl4JList::LIST_ITEM_INFO ListInfo;
257
258 // Add two for New Game and Tutorial
259 ZeroMemory(&ListInfo,sizeof(CXuiCtrl4JList::LIST_ITEM_INFO));
260
261 ListInfo.pwszText = app.GetString(IDS_CREATE_NEW_WORLD);
262 ListInfo.fEnabled = TRUE;
263 ListInfo.iData = -1;
264 m_pSavesList->AddData(ListInfo);
265
266 int iSavesListIndex = 0;
267 int iGeneratorIndex = 0;
268 m_iMashUpButtonsC=0;
269
270 for(AUTO_VAR(it, m_generators->begin()); it != m_generators->end(); ++it)
271 {
272 LevelGenerationOptions *levelGen = *it;
273 ListInfo.pwszText = levelGen->getWorldName();
274 ListInfo.fEnabled = TRUE;
275 ListInfo.iData = iGeneratorIndex++; // used to index into the list of generators
276
277 // need to check if the user has disabled this pack in the save display list
278 unsigned int uiTexturePackID=levelGen->getRequiredTexturePackId();
279
280 if(uiTexturePackID!=0)
281 {
282 unsigned int uiMashUpWorldsBitmask=app.GetMashupPackWorlds(m_iPad);
283
284 if((uiMashUpWorldsBitmask & (1<<(uiTexturePackID-1024)))==0)
285 {
286 // this world is hidden, so skip
287 continue;
288 }
289 }
290 m_pSavesList->AddData(ListInfo);
291
292 // retrieve the save icon from the texture pack, if there is one
293 if(uiTexturePackID!=0)
294 {
295 // increment the count of the mash-up pack worlds in the save list
296 m_iMashUpButtonsC++;
297 TexturePack *tp = Minecraft::GetInstance()->skins->getTexturePackById(levelGen->getRequiredTexturePackId());
298 DWORD dwImageBytes;
299 PBYTE pbImageData = tp->getPackIcon(dwImageBytes);
300 HXUIBRUSH hXuiBrush;
301
302 if(dwImageBytes > 0 && pbImageData)
303 {
304 XuiCreateTextureBrushFromMemory(pbImageData,dwImageBytes,&hXuiBrush);
305 // the index inside the list item for this will be i+1 because they start at m_vListData.size(), so the first etry (tutorial) is 1
306 m_pSavesList->UpdateGraphic(iSavesListIndex+1,hXuiBrush);
307 }
308 }
309
310 ++iSavesListIndex;
311 }
312
313 m_iDefaultButtonsC = iSavesListIndex + 1;
314}
315
316
317HRESULT CScene_MultiGameJoinLoad::GetSaveInfo( )
318{
319 unsigned int uiSaveC=0;
320
321 // This will return with the number retrieved in uiSaveC
322
323 if(app.DebugSettingsOn() && app.GetLoadSavesFromFolderEnabled())
324 {
325 uiSaveC = 0;
326 File savesDir(L"GAME:\\Saves");
327 if( savesDir.exists() )
328 {
329 m_saves = savesDir.listFiles();
330 uiSaveC = (unsigned int)m_saves->size();
331 }
332 // add the New Game and Tutorial after the saves list is retrieved, if there are any saves
333
334 // Add two for New Game and Tutorial
335 unsigned int listItems = uiSaveC;
336
337 CXuiCtrl4JList::LIST_ITEM_INFO ListInfo;
338 ZeroMemory(&ListInfo,sizeof(CXuiCtrl4JList::LIST_ITEM_INFO));
339
340 AddDefaultButtons();
341
342 for(unsigned int i=0;i<listItems;i++)
343 {
344
345 wstring wName = m_saves->at(i)->getName();
346 wchar_t *name = new wchar_t[wName.size()+1];
347 for(unsigned int j = 0; j < wName.size(); ++j)
348 {
349 name[j] = wName[j];
350 }
351 name[wName.size()] = 0;
352 ListInfo.pwszText = name;
353 ListInfo.fEnabled=TRUE;
354 ListInfo.iData = -1;
355 m_pSavesList->AddData(ListInfo);
356 }
357 m_pSavesList->SetCurSelVisible(0);
358 }
359 else
360 {
361 m_bRetrievingSaveInfo=true; // we're blocking the exit from this scene until complete
362
363 // clear the saves list
364 m_pSavesList->RemoveAllData();
365
366 m_iSaveInfoC=0;
367#ifdef _XBOX
368 C4JStorage::ESGIStatus eSGIStatus=StorageManager.GetSavesInfo(ProfileManager.GetPrimaryPad(),&CScene_MultiGameJoinLoad::GetSavesInfoCallback,this,"savegame.dat");
369
370 if(eSGIStatus==C4JStorage::ESGIStatus_NoSaves)
371 {
372 uiSaveC=0;
373 m_SavesListTimer.SetShow( FALSE );
374 m_SavesList.SetEnable(TRUE);
375 }
376#else
377
378 //C4JStorage::ESaveGameState eStatus=StorageManager.GetSavesInfo(ProfileManager.GetPrimaryPad(),&CScene_MultiGameJoinLoad::GetSavesInfoCallback,this,"savegame.dat");
379
380#endif
381 }
382
383 return S_OK;
384}
385
386HRESULT CScene_MultiGameJoinLoad::OnDestroy()
387{
388 g_NetworkManager.SetSessionsUpdatedCallback( NULL, NULL );
389
390 for(AUTO_VAR(it, currentSessions.begin()); it < currentSessions.end(); ++it)
391 {
392 delete (*it);
393 }
394
395 if(m_bSaveTransferInProgress)
396 {
397 CancelSaveUploadCallback(this);
398 }
399
400 // Reset the background downloading, in case we changed it by attempting to download a texture pack
401 XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_AUTO);
402
403 // clear out the texture pack data
404 for(int i=0;i<TMS_COUNT;i++)
405 {
406 if(app.TMSFileA[i].eTMSType==eTMSFileType_TexturePack)
407 {
408 app.RemoveMemoryTPDFile(app.TMSFileA[i].iConfig);
409 }
410 }
411 app.FreeLocalTMSFiles(eTMSFileType_TexturePack);
412
413 return S_OK;
414}
415
416
417int CScene_MultiGameJoinLoad::DeviceRemovedDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
418{
419 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
420
421 // results switched for this dialog
422 if(result==C4JStorage::EMessage_ResultDecline)
423 {
424 StorageManager.SetSaveDisabled(true);
425 StorageManager.SetSaveDeviceSelected(ProfileManager.GetPrimaryPad(),false);
426 // use the device select returned function to wipe the saves list and change the tooltip
427 CScene_MultiGameJoinLoad::DeviceSelectReturned(pClass,true);
428 }
429 else // continue without saving
430 {
431 // Change device
432 StorageManager.SetSaveDevice(&CScene_MultiGameJoinLoad::DeviceSelectReturned,pClass,true);
433 }
434
435 pClass->m_bIgnoreInput=false;
436 return 0;
437}
438//----------------------------------------------------------------------------------
439// Handler for the button press message.
440//----------------------------------------------------------------------------------
441HRESULT CScene_MultiGameJoinLoad::OnNotifyPressEx(HXUIOBJ hObjPressed, XUINotifyPress* pNotifyPressData, BOOL& rfHandled)
442{
443 if(m_bIgnoreInput) return S_OK;
444
445 // if we're retrieving save info, ignore key presses
446 if(m_bRetrievingSaveInfo)
447 {
448 return S_OK;
449 }
450
451 // This assumes all buttons can only be pressed with the A button
452 ui.AnimateKeyPress(pNotifyPressData->UserIndex, VK_PAD_A);
453
454 if ( hObjPressed == m_GamesList )
455 {
456 m_bIgnoreInput=true;
457
458 DWORD nIndex = m_pGamesList->GetCurSel();
459
460 if( m_pGamesList->GetItemCount() > 0 && nIndex < currentSessions.size() )
461 {
462 //CScene_MultiGameInfo::JoinMenuInitData *initData = new CScene_MultiGameInfo::JoinMenuInitData();
463 m_initData->iPad = m_iPad;
464 m_initData->selectedSession = currentSessions.at( nIndex );
465
466 // check that we have the texture pack available
467 // If it's not the default texture pack
468 if(m_initData->selectedSession->data.texturePackParentId!=0)
469 {
470 int texturePacksCount = Minecraft::GetInstance()->skins->getTexturePackCount();
471 bool bHasTexturePackInstalled=false;
472
473 for(int i=0;i<texturePacksCount;i++)
474 {
475 TexturePack *tp = Minecraft::GetInstance()->skins->getTexturePackByIndex(i);
476 if(tp->getDLCParentPackId()==m_initData->selectedSession->data.texturePackParentId)
477 {
478 bHasTexturePackInstalled=true;
479 break;
480 }
481 }
482
483 if(bHasTexturePackInstalled==false)
484 {
485 // upsell the texture pack
486 // tell sentient about the upsell of the full version of the skin pack
487 ULONGLONG ullOfferID_Full;
488 app.GetDLCFullOfferIDForPackID(m_initData->selectedSession->data.texturePackParentId,&ullOfferID_Full);
489
490 TelemetryManager->RecordUpsellPresented(pNotifyPressData->UserIndex, eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF);
491
492 UINT uiIDA[3];
493
494 // Need to check if the texture pack has both Full and Trial versions - we may do some as free ones, so only Full
495 DLC_INFO *pDLCInfo=app.GetDLCInfoForFullOfferID(ullOfferID_Full);
496
497 if(pDLCInfo->ullOfferID_Trial!=0LL)
498 {
499 uiIDA[0]=IDS_TEXTUREPACK_FULLVERSION;
500 uiIDA[1]=IDS_TEXTURE_PACK_TRIALVERSION;
501 uiIDA[2]=IDS_CONFIRM_CANCEL;
502 // Give the player a warning about the texture pack missing
503 StorageManager.RequestMessageBox(IDS_DLC_TEXTUREPACK_NOT_PRESENT_TITLE, IDS_DLC_TEXTUREPACK_NOT_PRESENT, uiIDA, 3, ProfileManager.GetPrimaryPad(),&CScene_MultiGameJoinLoad::TexturePackDialogReturned,this,app.GetStringTable());
504 }
505 else
506 {
507 uiIDA[0]=IDS_TEXTUREPACK_FULLVERSION;
508 uiIDA[1]=IDS_CONFIRM_CANCEL;
509 // Give the player a warning about the texture pack missing
510 StorageManager.RequestMessageBox(IDS_DLC_TEXTUREPACK_NOT_PRESENT_TITLE, IDS_DLC_TEXTUREPACK_NOT_PRESENT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CScene_MultiGameJoinLoad::TexturePackDialogReturned,this,app.GetStringTable());
511 }
512
513 return S_OK;
514 }
515 }
516
517 m_NetGamesListTimer.SetShow( FALSE );
518
519 // Reset the background downloading, in case we changed it by attempting to download a texture pack
520 XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_AUTO);
521
522 // kill the texture pack check timer
523 XuiKillTimer(m_hObj,CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID);
524 app.NavigateToScene(pNotifyPressData->UserIndex,eUIScene_JoinMenu,m_initData);
525 }
526 }
527 else if(hObjPressed==m_SavesList)
528 {
529 m_bIgnoreInput=true;
530
531 CXuiControl pItem;
532 int iIndex;
533 // get the selected item
534 iIndex=m_SavesList.GetCurSel(&pItem);
535
536 CXuiCtrl4JList::LIST_ITEM_INFO info = m_pSavesList->GetData(iIndex);
537
538 if(iIndex == JOIN_LOAD_CREATE_BUTTON_INDEX)
539 {
540 app.SetTutorialMode( false );
541 m_NetGamesListTimer.SetShow( FALSE );
542
543 app.SetCorruptSaveDeleted(false);
544
545 CreateWorldMenuInitData *params = new CreateWorldMenuInitData();
546 params->iPad = m_iPad;
547 app.NavigateToScene(pNotifyPressData->UserIndex,eUIScene_CreateWorldMenu,(void *)params);
548 }
549 else if(info.iData >= 0)
550 {
551 LevelGenerationOptions *levelGen = m_generators->at(info.iData);
552 app.SetTutorialMode( levelGen->isTutorial() );
553 // Reset the autosave time
554 app.SetAutosaveTimerTime();
555
556 if(levelGen->isTutorial())
557 {
558 LoadLevelGen(levelGen);
559 }
560 else
561 {
562 LoadMenuInitData *params = new LoadMenuInitData();
563 params->iPad = m_iPad;
564 // need to get the iIndex from the list item, since the position in the list doesn't correspond to the GetSaveGameInfo list because of sorting
565 params->iSaveGameInfoIndex=-1;
566 //params->pbSaveRenamed=&m_bSaveRenamed;
567 params->levelGen = levelGen;
568
569 // navigate to the settings scene
570 app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_LoadMenu, params);
571 }
572 }
573 else
574 {
575 // check if this is a damaged save
576 if(m_pSavesList->GetData(iIndex).bIsDamaged)
577 {
578 // give the option to delete the save
579 UINT uiIDA[2];
580 uiIDA[0]=IDS_CONFIRM_CANCEL;
581 uiIDA[1]=IDS_CONFIRM_OK;
582 StorageManager.RequestMessageBox(IDS_CORRUPT_OR_DAMAGED_SAVE_TITLE, IDS_CORRUPT_OR_DAMAGED_SAVE_TEXT, uiIDA, 2, pNotifyPressData->UserIndex,&CScene_MultiGameJoinLoad::DeleteSaveDialogReturned,this, app.GetStringTable());
583 }
584 else
585 {
586 app.SetTutorialMode( false );
587 if(app.DebugSettingsOn() && app.GetLoadSavesFromFolderEnabled())
588 {
589 LoadSaveFromDisk(m_saves->at(iIndex-m_iDefaultButtonsC));
590 }
591 else
592 {
593 LoadMenuInitData *params = new LoadMenuInitData();
594 params->iPad = m_iPad;
595 // need to get the iIndex from the list item, since the position in the list doesn't correspond to the GetSaveGameInfo list because of sorting
596 params->iSaveGameInfoIndex=m_pSavesList->GetData(iIndex).iIndex-m_iDefaultButtonsC;
597 //params->pbSaveRenamed=&m_bSaveRenamed;
598 params->levelGen = NULL;
599
600 // kill the texture pack timer
601 XuiKillTimer(m_hObj,CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID);
602 // navigate to the settings scene
603 app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_LoadMenu, params);
604 }
605 }
606 }
607 }
608
609 return S_OK;
610}
611
612HRESULT CScene_MultiGameJoinLoad::OnKeyDown(XUIMessageInput* pInputData, BOOL& rfHandled)
613{
614 if(m_bIgnoreInput) return S_OK;
615
616 // if we're retrieving save info, ignore key presses
617 if(m_bRetrievingSaveInfo)
618 {
619 return S_OK;
620 }
621
622 ui.AnimateKeyPress(pInputData->UserIndex, pInputData->dwKeyCode);
623
624 HRESULT hr = S_OK;
625
626 // Explicitly handle B button presses
627 switch(pInputData->dwKeyCode)
628 {
629 case VK_PAD_B:
630 case VK_ESCAPE:
631 m_NetGamesListTimer.SetShow( FALSE );
632
633 app.NavigateBack(XUSER_INDEX_ANY);
634 rfHandled = TRUE;
635 break;
636 case VK_PAD_X:
637
638 // Change device
639 // Fix for #12531 - TCR 001: BAS Game Stability: When a player selects to change a storage
640 // device, and repeatedly backs out of the SD screen, disconnects from LIVE, and then selects a SD, the title crashes.
641 m_bIgnoreInput=true;
642 StorageManager.SetSaveDevice(&CScene_MultiGameJoinLoad::DeviceSelectReturned,this,true);
643 CXuiSceneBase::PlayUISFX(eSFX_Press);
644 break;
645 case VK_PAD_Y:
646 if(m_pGamesList->TreeHasFocus() && m_pGamesList->GetItemCount() > 0)
647 {
648 DWORD nIndex = m_pGamesList->GetCurSel();
649 FriendSessionInfo *pSelectedSession = currentSessions.at( nIndex );
650
651 PlayerUID xuid = pSelectedSession->data.hostPlayerUID;
652 if( xuid != INVALID_XUID )
653 hr = XShowGamerCardUI(ProfileManager.GetLockedProfile(), xuid);
654 CXuiSceneBase::PlayUISFX(eSFX_Press);
655 }
656 else if(DoesSavesListHaveFocus())
657 {
658 // save transfer - make sure they want to overwrite a save that is up there
659 if(ProfileManager.IsSignedInLive( m_iPad ))
660 {
661 // 4J-PB - required for a delete of the save if it's found to be a corrupted save
662 DWORD nIndex = m_pSavesList->GetCurSel();
663 m_iChangingSaveGameInfoIndex=m_pSavesList->GetData(nIndex).iIndex;
664
665 UINT uiIDA[2];
666 uiIDA[0]=IDS_UPLOAD_SAVE;
667 uiIDA[1]=IDS_CONFIRM_CANCEL;
668
669 ui.RequestMessageBox(IDS_SAVE_TRANSFER_TITLE, IDS_SAVE_TRANSFER_TEXT, uiIDA, 2, pInputData->UserIndex,&CScene_MultiGameJoinLoad::SaveTransferDialogReturned,this, app.GetStringTable());
670 }
671 }
672 break;
673 case VK_PAD_RSHOULDER:
674 if(DoesSavesListHaveFocus())
675 {
676 m_bIgnoreInput = true;
677
678 int iIndex=m_SavesList.GetCurSel();
679 m_iChangingSaveGameInfoIndex=m_pSavesList->GetData(iIndex).iIndex;
680
681 // Could be delete save or Save Options
682 if(StorageManager.GetSaveDisabled())
683 {
684 // delete the save game
685 // Have to ask the player if they are sure they want to delete this game
686 UINT uiIDA[2];
687 uiIDA[0]=IDS_CONFIRM_CANCEL;
688 uiIDA[1]=IDS_CONFIRM_OK;
689 StorageManager.RequestMessageBox(IDS_TOOLTIPS_DELETESAVE, IDS_TEXT_DELETE_SAVE, uiIDA, 2, pInputData->UserIndex,&CScene_MultiGameJoinLoad::DeleteSaveDialogReturned,this, app.GetStringTable());
690 }
691 else
692 {
693 if(StorageManager.EnoughSpaceForAMinSaveGame())
694 {
695 UINT uiIDA[3];
696 uiIDA[0]=IDS_CONFIRM_CANCEL;
697 uiIDA[1]=IDS_TITLE_RENAMESAVE;
698 uiIDA[2]=IDS_TOOLTIPS_DELETESAVE;
699 StorageManager.RequestMessageBox(IDS_TOOLTIPS_SAVEOPTIONS, IDS_TEXT_SAVEOPTIONS, uiIDA, 3, pInputData->UserIndex,&CScene_MultiGameJoinLoad::SaveOptionsDialogReturned,this, app.GetStringTable());
700 }
701 else
702 {
703 // delete the save game
704 // Have to ask the player if they are sure they want to delete this game
705 UINT uiIDA[2];
706 uiIDA[0]=IDS_CONFIRM_CANCEL;
707 uiIDA[1]=IDS_CONFIRM_OK;
708 StorageManager.RequestMessageBox(IDS_TOOLTIPS_DELETESAVE, IDS_TEXT_DELETE_SAVE, uiIDA, 2, pInputData->UserIndex,&CScene_MultiGameJoinLoad::DeleteSaveDialogReturned,this, app.GetStringTable());
709 }
710 }
711 CXuiSceneBase::PlayUISFX(eSFX_Press);
712
713 }
714 else if(DoesMashUpWorldHaveFocus())
715 {
716 // hiding a mash-up world
717 // get the mash-up pack id
718 CXuiControl pItem;
719 int iIndex;
720 iIndex=m_SavesList.GetCurSel(&pItem);
721
722 CXuiCtrl4JList::LIST_ITEM_INFO info = m_pSavesList->GetData(iIndex);
723 if((iIndex != JOIN_LOAD_CREATE_BUTTON_INDEX) && (info.iData >= 0))
724 {
725 LevelGenerationOptions *levelGen = m_generators->at(info.iData);
726
727 if(!levelGen->isTutorial())
728 {
729 if(levelGen->requiresTexturePack())
730 {
731 unsigned int uiPackID=levelGen->getRequiredTexturePackId();
732
733 m_bIgnoreInput = true;
734 app.HideMashupPackWorld(m_iPad,uiPackID);
735
736 // update the saves list
737 m_pSavesList->RemoveAllData();
738 m_iSaveInfoC=0;
739 GetSaveInfo();
740 m_bIgnoreInput = false;
741 }
742 }
743 }
744
745 CXuiSceneBase::PlayUISFX(eSFX_Press);
746
747 }
748 break;
749 case VK_PAD_LSHOULDER:
750 if( m_bInParty )
751 {
752 m_bShowingPartyGamesOnly = !m_bShowingPartyGamesOnly;
753 UpdateGamesList();
754 CXuiSceneBase::PlayUISFX(eSFX_Press);
755 }
756 break;
757 }
758
759 return hr;
760}
761
762HRESULT CScene_MultiGameJoinLoad::OnNavReturn(HXUIOBJ hSceneFrom,BOOL& rfHandled)
763{
764
765 CXuiSceneBase::ShowLogo( DEFAULT_XUI_MENU_USER, TRUE );
766 // start the texture pack timer again
767 XuiSetTimer(m_hObj,CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID,CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME);
768
769 m_bMultiplayerAllowed = ProfileManager.IsSignedInLive( m_iPad ) && ProfileManager.AllowedToPlayMultiplayer(m_iPad);
770
771 // re-enable button presses
772 m_bIgnoreInput=false;
773
774 if( m_bMultiplayerAllowed )
775 {
776 HXUICLASS hClassFullscreenProgress = XuiFindClass( L"CScene_FullscreenProgress" );
777 HXUICLASS hClassConnectingProgress = XuiFindClass( L"CScene_ConnectingProgress" );
778
779 // If we are navigating back from a full screen progress scene, then that means a connection attempt failed
780 if( XuiIsInstanceOf( hSceneFrom, hClassFullscreenProgress ) || XuiIsInstanceOf( hSceneFrom, hClassConnectingProgress ) )
781 {
782 UpdateGamesList();
783 }
784 }
785 else
786 {
787 m_pGamesList->RemoveAllData();
788 //m_GamesList.DeleteItems(0, m_GamesList.GetItemCount() );
789 m_pGamesList->SetEnable(FALSE);
790 //XuiElementSetDisableFocusRecursion( m_pGamesList->m_hObj, TRUE);
791 m_NetGamesListTimer.SetShow( TRUE );
792 m_LabelNoGames.SetShow( FALSE );
793 m_SavesList.InitFocus(m_iPad);
794 }
795
796 // are we back here because of a delete of a corrupt save?
797
798 if(app.GetCorruptSaveDeleted())
799 {
800 // need to re-get the saves list and update the display
801 // clear the saves list
802 m_pSavesList->RemoveAllData();
803 m_iSaveInfoC=0;
804 GetSaveInfo();
805 app.SetCorruptSaveDeleted(false);
806 }
807
808 int iY = -1;
809 int iRB=-1;
810 if( DoesGamesListHaveFocus() )
811 {
812 iY = IDS_TOOLTIPS_VIEW_GAMERCARD;
813 }
814 else if(DoesSavesListHaveFocus())
815 {
816 if(ProfileManager.IsSignedInLive( m_iPad ))
817 {
818 iY=IDS_TOOLTIPS_UPLOAD_SAVE_FOR_XBOXONE;
819 }
820
821 if(StorageManager.GetSaveDisabled())
822 {
823 iRB=IDS_TOOLTIPS_DELETESAVE;
824 }
825 else
826 {
827 // 4J-PB - we need to check that there is enough space left to create a copy of the save (for a rename)
828
829 if(StorageManager.EnoughSpaceForAMinSaveGame())
830 {
831 iRB=IDS_TOOLTIPS_SAVEOPTIONS;
832 }
833 else
834 {
835 iRB=IDS_TOOLTIPS_DELETESAVE;
836
837 }
838 }
839 }
840 else if(DoesMashUpWorldHaveFocus())
841 {
842 // If it's a mash-up pack world, give the Hide option
843 iRB=IDS_TOOLTIPS_HIDE;
844 }
845
846 int iLB = -1;
847 if(m_bInParty)
848 {
849 if( m_bShowingPartyGamesOnly ) iLB = IDS_TOOLTIPS_ALL_GAMES;
850 else iLB = IDS_TOOLTIPS_PARTY_GAMES;
851 }
852
853 if(ProfileManager.IsFullVersion()==false )
854 {
855 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, -1, -1,-1,-1,iLB);
856 }
857 else if(StorageManager.GetSaveDisabled())
858 {
859 // clear out the saves list, since the disable save may have happened in the load screen because of a device removal
860
861 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE,iY,-1,-1,iLB,iRB);
862 }
863 else
864 {
865 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, IDS_TOOLTIPS_CHANGEDEVICE, iY,-1,-1,iLB,iRB);
866 }
867
868 return S_OK;
869}
870
871HRESULT CScene_MultiGameJoinLoad::OnNotifySelChanged(HXUIOBJ hObjSource, XUINotifySelChanged *pNotifySelChangedData, BOOL& bHandled)
872{
873
874 if(m_bReady)
875 {
876 CXuiSceneBase::PlayUISFX(eSFX_Focus);
877 }
878
879 return S_OK;
880}
881
882
883HRESULT CScene_MultiGameJoinLoad::OnTransitionStart( XUIMessageTransition *pTransition, BOOL& bHandled )
884{
885 //if(pTransition->dwTransAction==XUI_TRANSITION_ACTION_DESTROY ) return S_OK;
886
887 if(pTransition->dwTransAction==XUI_TRANSITION_ACTION_DESTROY ||
888 pTransition->dwTransType == XUI_TRANSITION_FROM || pTransition->dwTransType == XUI_TRANSITION_BACKFROM)
889 {
890 // 4J Stu - We may have had to unload our font renderer in this scene if one of the save files
891 // uses characters not in our font (eg asian chars) so restore our font renderer
892 // This will not do anything if our font renderer is already loaded
893 app.OverrideFontRenderer(true,true);
894
895 KillTimer(JOIN_LOAD_ONLINE_TIMER_ID);
896 }
897 else if(pTransition->dwTransType == XUI_TRANSITION_TO || pTransition->dwTransType == XUI_TRANSITION_BACKTO)
898 {
899 SetTimer(JOIN_LOAD_ONLINE_TIMER_ID,JOIN_LOAD_ONLINE_TIMER_TIME);
900 // 4J-PB - Need to check for installed DLC, which might have happened while you were on the info scene
901 if(pTransition->dwTransType == XUI_TRANSITION_BACKTO)
902 {
903 // Can't call this here because if you back out of the load info screen and then go back in and load a game, it will attempt to use the dlc as it's running a mount of the dlc
904
905 // block input if we're waiting for DLC to install, and wipe the saves list. The end of dlc mounting custom message will fill the list again
906 if(app.StartInstallDLCProcess(m_iPad)==false)
907 {
908 // not doing a mount, so re-enable input
909 m_bIgnoreInput=false;
910 }
911 else
912 {
913 m_bIgnoreInput=true;
914 m_pSavesList->RemoveAllData();
915 m_SavesListTimer.SetShow( TRUE );
916 }
917 }
918 }
919
920 return S_OK;
921}
922
923HRESULT CScene_MultiGameJoinLoad::OnFontRendererChange()
924{
925 // update the tooltips
926 // if the saves list has focus, then we should show the Delete Save tooltip
927 // if the games list has focus, then we should the the View Gamercard tooltip
928 int iRB=-1;
929 int iY = -1;
930 if( DoesGamesListHaveFocus() )
931 {
932 iY = IDS_TOOLTIPS_VIEW_GAMERCARD;
933 }
934 else if(DoesSavesListHaveFocus())
935 {
936 if(ProfileManager.IsSignedInLive( m_iPad ))
937 {
938 iY=IDS_TOOLTIPS_UPLOAD_SAVE_FOR_XBOXONE;
939 }
940 if(StorageManager.GetSaveDisabled())
941 {
942 iRB=IDS_TOOLTIPS_DELETESAVE;
943 }
944 else
945 {
946 if(StorageManager.EnoughSpaceForAMinSaveGame())
947 {
948 iRB=IDS_TOOLTIPS_SAVEOPTIONS;
949 }
950 else
951 {
952 iRB=IDS_TOOLTIPS_DELETESAVE;
953 }
954 }
955 }
956 else if(DoesMashUpWorldHaveFocus())
957 {
958 // If it's a mash-up pack world, give the Hide option
959 iRB=IDS_TOOLTIPS_HIDE;
960 }
961
962 int iLB = -1;
963 if(m_bInParty)
964 {
965 if( m_bShowingPartyGamesOnly ) iLB = IDS_TOOLTIPS_ALL_GAMES;
966 else iLB = IDS_TOOLTIPS_PARTY_GAMES;
967 }
968
969 if(ProfileManager.IsFullVersion()==false )
970 {
971 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, -1, iY,-1,-1,iLB,-1,-1,true);
972 }
973 else if(StorageManager.GetSaveDisabled())
974 {
975 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE,iY,-1,-1,iLB,iRB,-1,true);
976 }
977 else
978 {
979 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, IDS_TOOLTIPS_CHANGEDEVICE, iY,-1,-1,iLB,iRB,-1,true);
980 }
981 return S_OK;
982}
983
984HRESULT CScene_MultiGameJoinLoad::OnNotifySetFocus(HXUIOBJ hObjSource, XUINotifyFocus *pNotifyFocusData, BOOL& bHandled)
985{
986 // update the tooltips
987 // if the saves list has focus, then we should show the Delete Save tooltip
988 // if the games list has focus, then we should the the View Gamercard tooltip
989 int iRB=-1;
990 int iY = -1;
991 if( DoesGamesListHaveFocus() )
992 {
993 iY = IDS_TOOLTIPS_VIEW_GAMERCARD;
994 }
995 else if(DoesSavesListHaveFocus())
996 {
997 if(ProfileManager.IsSignedInLive( m_iPad ))
998 {
999 iY=IDS_TOOLTIPS_UPLOAD_SAVE_FOR_XBOXONE;
1000 }
1001 if(StorageManager.GetSaveDisabled())
1002 {
1003 iRB=IDS_TOOLTIPS_DELETESAVE;
1004 }
1005 else
1006 {
1007 if(StorageManager.EnoughSpaceForAMinSaveGame())
1008 {
1009 iRB=IDS_TOOLTIPS_SAVEOPTIONS;
1010 }
1011 else
1012 {
1013 iRB=IDS_TOOLTIPS_DELETESAVE;
1014 }
1015 }
1016 }
1017 else if(DoesMashUpWorldHaveFocus())
1018 {
1019 // If it's a mash-up pack world, give the Hide option
1020 iRB=IDS_TOOLTIPS_HIDE;
1021 }
1022
1023 int iLB = -1;
1024 if(m_bInParty)
1025 {
1026 if( m_bShowingPartyGamesOnly ) iLB = IDS_TOOLTIPS_ALL_GAMES;
1027 else iLB = IDS_TOOLTIPS_PARTY_GAMES;
1028 }
1029
1030 if(ProfileManager.IsFullVersion()==false )
1031 {
1032 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, -1, iY,-1,-1,iLB,-1);
1033 }
1034 else if(StorageManager.GetSaveDisabled())
1035 {
1036 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE,iY,-1,-1,iLB,iRB);
1037 }
1038 else
1039 {
1040 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, IDS_TOOLTIPS_CHANGEDEVICE, iY,-1,-1,iLB,iRB);
1041 }
1042 return S_OK;
1043}
1044
1045HRESULT CScene_MultiGameJoinLoad::OnNotifyKillFocus(HXUIOBJ hObjSource, XUINotifyFocus *pNotifyFocusData, BOOL& bHandled)
1046{
1047 return S_OK;
1048}
1049
1050bool CScene_MultiGameJoinLoad::DoesSavesListHaveFocus()
1051{
1052 HXUIOBJ hParentObj,hObj=TreeGetFocus();
1053
1054 if(hObj!=NULL)
1055 {
1056 // get the parent and see if it's the saves list
1057 XuiElementGetParent(hObj,&hParentObj);
1058 if(hParentObj==m_SavesList.m_hObj)
1059 {
1060 // check it's not the first or second element (new world or tutorial)
1061 if(m_SavesList.GetCurSel()>(m_iDefaultButtonsC-1))
1062 {
1063 return true;
1064 }
1065 }
1066 }
1067 return false;
1068}
1069
1070bool CScene_MultiGameJoinLoad::DoesMashUpWorldHaveFocus()
1071{
1072 HXUIOBJ hParentObj,hObj=TreeGetFocus();
1073
1074 if(hObj!=NULL)
1075 {
1076 // get the parent and see if it's the saves list
1077 XuiElementGetParent(hObj,&hParentObj);
1078 if(hParentObj==m_SavesList.m_hObj)
1079 {
1080 // check it's not the first or second element (new world or tutorial)
1081 if(m_SavesList.GetCurSel()>(m_iDefaultButtonsC-1))
1082 {
1083 return false;
1084 }
1085
1086 if(m_SavesList.GetCurSel()>(m_iDefaultButtonsC - 1 - m_iMashUpButtonsC))
1087 {
1088 return true;
1089 }
1090 else return false;
1091 }
1092 else return false;
1093 }
1094 return false;
1095}
1096
1097bool CScene_MultiGameJoinLoad::DoesGamesListHaveFocus()
1098{
1099 HXUIOBJ hParentObj,hObj=TreeGetFocus();
1100
1101 if(hObj!=NULL)
1102 {
1103 // get the parent and see if it's the saves list
1104 XuiElementGetParent(hObj,&hParentObj);
1105 if(hParentObj==m_pGamesList->m_hObj)
1106 {
1107 return true;
1108 }
1109 }
1110 return false;
1111}
1112
1113void CScene_MultiGameJoinLoad::UpdateGamesListCallback(LPVOID lpParam)
1114{
1115 if(lpParam != NULL)
1116 {
1117 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad *) lpParam;
1118 // check this there's no save transfer in progress
1119 if(!pClass->m_bSaveTransferInProgress)
1120 {
1121 pClass->UpdateGamesList();
1122 }
1123 }
1124}
1125
1126void CScene_MultiGameJoinLoad::UpdateGamesList()
1127{
1128 if( m_bIgnoreInput ) return;
1129
1130 // if we're retrieving save info, don't show the list yet as we will be ignoring press events
1131 if(m_bRetrievingSaveInfo)
1132 {
1133 return;
1134 }
1135
1136 DWORD nIndex = -1;
1137 FriendSessionInfo *pSelectedSession = NULL;
1138 if(m_pGamesList->TreeHasFocus() && m_pGamesList->GetItemCount() > 0)
1139 {
1140 nIndex = m_pGamesList->GetCurSel();
1141 pSelectedSession = currentSessions.at( nIndex );
1142 }
1143
1144 SessionID selectedSessionId;
1145 if( pSelectedSession != NULL )selectedSessionId = pSelectedSession->sessionId;
1146 pSelectedSession = NULL;
1147
1148 for(AUTO_VAR(it, currentSessions.begin()); it < currentSessions.end(); ++it)
1149 {
1150 delete (*it);
1151 }
1152 currentSessions.clear();
1153
1154 m_NetGamesListTimer.SetShow( FALSE );
1155
1156 // if the saves list has focus, then we should show the Delete Save tooltip
1157 // if the games list has focus, then we should show the View Gamercard tooltip
1158 int iRB=-1;
1159 int iY = -1;
1160
1161 if( DoesGamesListHaveFocus() )
1162 {
1163 iY = IDS_TOOLTIPS_VIEW_GAMERCARD;
1164 }
1165 else if(DoesSavesListHaveFocus())
1166 {
1167 if(ProfileManager.IsSignedInLive( m_iPad ))
1168 {
1169 iY=IDS_TOOLTIPS_UPLOAD_SAVE_FOR_XBOXONE;
1170 }
1171 if(StorageManager.GetSaveDisabled())
1172 {
1173 iRB=IDS_TOOLTIPS_DELETESAVE;
1174 }
1175 else
1176 {
1177 if(StorageManager.EnoughSpaceForAMinSaveGame())
1178 {
1179 iRB=IDS_TOOLTIPS_SAVEOPTIONS;
1180 }
1181 else
1182 {
1183 iRB=IDS_TOOLTIPS_DELETESAVE;
1184 }
1185 }
1186 }
1187 else if(DoesMashUpWorldHaveFocus())
1188 {
1189 // If it's a mash-up pack world, give the Hide option
1190 iRB=IDS_TOOLTIPS_HIDE;
1191 }
1192
1193 int iLB = -1;
1194 if(m_bInParty)
1195 {
1196 if( m_bShowingPartyGamesOnly ) iLB = IDS_TOOLTIPS_ALL_GAMES;
1197 else iLB = IDS_TOOLTIPS_PARTY_GAMES;
1198 }
1199
1200 if(ProfileManager.IsFullVersion()==false )
1201 {
1202 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, -1, iY,-1,-1,iLB,-1);
1203 }
1204 else if(StorageManager.GetSaveDisabled())
1205 {
1206 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE,iY,-1,-1,iLB,iRB);
1207 }
1208 else
1209 {
1210 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, IDS_TOOLTIPS_CHANGEDEVICE, iY,-1,-1,iLB,iRB);
1211 }
1212
1213 currentSessions = *g_NetworkManager.GetSessionList( m_iPad, m_localPlayers, m_bShowingPartyGamesOnly );
1214
1215 // Update the xui list displayed
1216 unsigned int xuiListSize = m_pGamesList->GetItemCount();
1217 unsigned int filteredListSize = (unsigned int)currentSessions.size();
1218
1219 BOOL gamesListHasFocus = m_pGamesList->TreeHasFocus();
1220
1221 if(filteredListSize > 0)
1222 {
1223 if( !m_pGamesList->IsEnabled() )
1224 {
1225 m_pGamesList->SetEnable(TRUE);
1226 //XuiElementSetDisableFocusRecursion( m_pGamesList->m_hObj, FALSE);
1227 m_pGamesList->SetCurSel( 0 );
1228 }
1229 m_LabelNoGames.SetShow( FALSE );
1230 m_NetGamesListTimer.SetShow( FALSE );
1231 }
1232 else
1233 {
1234 m_pGamesList->SetEnable(FALSE);
1235 //XuiElementSetDisableFocusRecursion(m_pGamesList->m_hObj, TRUE);
1236 m_NetGamesListTimer.SetShow( FALSE );
1237 m_LabelNoGames.SetShow( TRUE );
1238
1239 if( gamesListHasFocus ) m_pGamesList->InitFocus(m_iPad);
1240 }
1241
1242 // clear out the games list and re-fill
1243 m_pGamesList->RemoveAllData();
1244
1245 if( filteredListSize > 0 )
1246 {
1247 // Reset the focus to the selected session if it still exists
1248 unsigned int sessionIndex = 0;
1249 m_pGamesList->SetCurSel(0);
1250
1251 for( AUTO_VAR(it, currentSessions.begin()); it < currentSessions.end(); ++it)
1252 {
1253 FriendSessionInfo *sessionInfo = *it;
1254 HXUIBRUSH hXuiBrush;
1255 CXuiCtrl4JList::LIST_ITEM_INFO ListInfo;
1256
1257 ZeroMemory(&ListInfo,sizeof(CXuiCtrl4JList::LIST_ITEM_INFO));
1258
1259 ListInfo.pwszText = sessionInfo->displayLabel;
1260 ListInfo.fEnabled = TRUE;
1261 ListInfo.iData = sessionIndex;
1262 m_pGamesList->AddData(ListInfo);
1263 // display an icon too
1264
1265 // Is this a default game or a texture pack game?
1266 if(sessionInfo->data.texturePackParentId!=0)
1267 {
1268 // Do we have the texture pack
1269 Minecraft *pMinecraft = Minecraft::GetInstance();
1270 TexturePack *tp = pMinecraft->skins->getTexturePackById(sessionInfo->data.texturePackParentId);
1271 HRESULT hr;
1272
1273 DWORD dwImageBytes=0;
1274 PBYTE pbImageData=NULL;
1275
1276 if(tp==NULL)
1277 {
1278 DWORD dwBytes=0;
1279 PBYTE pbData=NULL;
1280 app.GetTPD(sessionInfo->data.texturePackParentId,&pbData,&dwBytes);
1281
1282 // is it in the tpd data ?
1283 app.GetFileFromTPD(eTPDFileType_Icon,pbData,dwBytes,&pbImageData,&dwImageBytes );
1284 if(dwImageBytes > 0 && pbImageData)
1285 {
1286 hr=XuiCreateTextureBrushFromMemory(pbImageData,dwImageBytes,&hXuiBrush);
1287 m_pGamesList->UpdateGraphic(sessionIndex,hXuiBrush);
1288 }
1289 }
1290 else
1291 {
1292 pbImageData = tp->getPackIcon(dwImageBytes);
1293 if(dwImageBytes > 0 && pbImageData)
1294 {
1295 hr=XuiCreateTextureBrushFromMemory(pbImageData,dwImageBytes,&hXuiBrush);
1296 m_pGamesList->UpdateGraphic(sessionIndex,hXuiBrush);
1297 }
1298 }
1299 }
1300 else
1301 {
1302 // default texture pack
1303 XuiCreateTextureBrushFromMemory(m_DefaultMinecraftIconData,m_DefaultMinecraftIconSize,&hXuiBrush);
1304 m_pGamesList->UpdateGraphic(sessionIndex,hXuiBrush);
1305 }
1306
1307
1308 if(memcmp( &selectedSessionId, &sessionInfo->sessionId, sizeof(SessionID) ) == 0)
1309 {
1310 m_pGamesList->SetCurSel(sessionIndex);
1311 break;
1312 }
1313 ++sessionIndex;
1314 }
1315 }
1316}
1317
1318void CScene_MultiGameJoinLoad::UpdateGamesList(DWORD dwNumResults, IQNetGameSearch *pGameSearch)
1319{
1320 // We don't use the QNet callback, but could resurrect this if we ever do normal matchmaking, but updated to work as the function above
1321#if 0
1322 const XSESSION_SEARCHRESULT *pSearchResult;
1323 const XNQOSINFO * pxnqi;
1324
1325 if(m_searches>0)
1326 --m_searches;
1327
1328 if(m_searches==0)
1329 {
1330 m_NetGamesListTimer.SetShow( FALSE );
1331
1332 // if the saves list has focus, then we should show the Delete Save tooltip
1333 // if the games list has focus, then we should show the View Gamercard tooltip
1334 int iRB=-1;
1335 int iY = -1;
1336
1337 if( DoesGamesListHaveFocus() )
1338 {
1339 iY = IDS_TOOLTIPS_VIEW_GAMERCARD;
1340 }
1341 else if(DoesSavesListHaveFocus())
1342 {
1343 iRB=IDS_TOOLTIPS_DELETESAVE;
1344 }
1345
1346 int iLB = -1;
1347 if(m_bInParty)
1348 {
1349 if( m_bShowingPartyGamesOnly ) iLB = IDS_TOOLTIPS_ALL_GAMES
1350 else iLB = IDS_TOOLTIPS_PARTY_GAMES;
1351 }
1352
1353 if(ProfileManager.IsFullVersion()==false )
1354 {
1355 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, -1, iY,-1,-1,iLB,iRB);
1356 }
1357 else if(StorageManager.GetSaveDisabled())
1358 {
1359 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE,iY,-1,-1,iLB,iRB);
1360 }
1361 else
1362 {
1363 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, IDS_TOOLTIPS_CHANGEDEVICE, iY,-1,-1,iLB,iRB);
1364 }
1365 }
1366
1367 if( dwNumResults == 0 )
1368 {
1369 if(m_searches==0 && m_GamesList.GetItemCount() == 0)
1370 {
1371 m_LabelNoGames.SetShow( TRUE );
1372 }
1373 return;
1374 }
1375
1376 unsigned int startOffset = m_GamesList.GetItemCount();
1377 //m_GamesList.InsertItems(startOffset,dwNumResults);
1378 //m_GamesList.SetEnable(TRUE);
1379 //XuiElementSetDisableFocusRecursion( m_GamesList.m_hObj, FALSE);
1380
1381 // Loop through all the results.
1382 for( DWORD dwResult = 0; dwResult < pGameSearch->GetNumResults(); dwResult++ )
1383 {
1384
1385 pSearchResult = pGameSearch->GetSearchResultAtIndex( dwResult );
1386
1387 // No room for us, so ignore it
1388 if(pSearchResult->dwOpenPublicSlots < m_localPlayers)
1389 continue;
1390
1391 FriendSessionInfo *sessionInfo = NULL;
1392 bool foundSession = false;
1393 for(AUTO_VAR(it, friendsSessions.begin()); it < friendsSessions.end(); ++it)
1394 {
1395 sessionInfo = *it;
1396 if(memcmp( &pSearchResult->info.sessionID, &sessionInfo->sessionId, sizeof(SessionID) ) == 0)
1397 {
1398 sessionInfo->searchResult = *pSearchResult;
1399 sessionInfo->displayLabel = new wchar_t[100];
1400 foundSession = true;
1401 break;
1402 }
1403 }
1404
1405 // We received a search result for a session no longer in our list of friends sessions
1406 if(!foundSession)
1407 continue;
1408
1409 // Print some info about this result.
1410 //printf( "Search result %u:\n", dwResult );
1411 //printf( " public slots open = %u, filled = %u\n", pSearchResult->dwOpenPublicSlots, pSearchResult->dwFilledPublicSlots );
1412 //printf( " private slots open = %u, filled = %u\n", pSearchResult->dwOpenPrivateSlots, pSearchResult->dwFilledPrivateSlots );
1413
1414 // See if this result was contacted successfully via QoS probes.
1415 pxnqi = pGameSearch->GetQosInfoAtIndex( dwResult );
1416 if( pxnqi->bFlags & XNET_XNQOSINFO_TARGET_CONTACTED )
1417 {
1418 // Print the round trip time and the rough estimation of
1419 // bandwidth.
1420 app.DebugPrintf( " RTT min = %u, med = %u\n", pxnqi->wRttMinInMsecs, pxnqi->wRttMedInMsecs );
1421 app.DebugPrintf( " bps up = %u, down = %u\n", pxnqi->dwUpBitsPerSec, pxnqi->dwDnBitsPerSec );
1422
1423 if(pxnqi->cbData > 0)
1424 {
1425 sessionInfo->data = *(GameSessionData *)pxnqi->pbData;
1426
1427 wstring gamerName = convStringToWstring(sessionInfo->data.hostName);
1428 swprintf(sessionInfo->displayLabel,L"%ls's Game", gamerName.c_str() );
1429 }
1430 else
1431 {
1432 swprintf(sessionInfo->displayLabel,L"Unknown host Game");
1433 }
1434
1435 // If this host wasn't disabled use this one.
1436 if( !( pxnqi->bFlags & XNET_XNQOSINFO_TARGET_DISABLED ) && sessionInfo->data.netVersion == MINECRAFT_NET_VERSION )
1437 {
1438 //printf("This game is valid\n");
1439 filteredResults.push_back(sessionInfo);
1440 m_GamesList.InsertItems(startOffset,1);
1441 m_GamesList.SetText(startOffset,sessionInfo->displayLabel);
1442 startOffset++;
1443 }
1444#ifndef _CONTENT_PACKAGE
1445 if( sessionInfo->data.netVersion != MINECRAFT_NET_VERSION )
1446 {
1447 wprintf(L"%ls version of %d does not match our version of %d\n", sessionInfo->displayLabel, sessionInfo->data.netVersion, MINECRAFT_NET_VERSION);
1448 }
1449#endif
1450 }
1451 }
1452
1453 if( m_GamesList.GetItemCount() == 0)
1454 {
1455 m_LabelNoGames.SetShow( TRUE );
1456 }
1457 else
1458 {
1459 m_GamesList.SetEnable(TRUE);
1460 XuiElementSetDisableFocusRecursion( m_GamesList.m_hObj, FALSE);
1461 if( DoesGamesListHaveFocus() )
1462 {
1463 m_GamesList.SetCurSel(0);
1464 }
1465 }
1466#endif
1467}
1468
1469/*void CScene_MultiGameJoinLoad::UpdateGamesListLabels()
1470{
1471 for( unsigned int i = 0; i < currentSessions.size(); ++i )
1472 {
1473 FriendSessionInfo *sessionInfo = currentSessions.at(i);
1474 m_GamesList.SetText(i,sessionInfo->displayLabel);
1475 HXUIBRUSH hBrush;
1476 CXuiCtrl4JList::LIST_ITEM_INFO info = m_pGamesList->GetData(i);
1477
1478 // display an icon too
1479 XuiCreateTextureBrushFromMemory(m_DefaultMinecraftIconData,m_DefaultMinecraftIconSize,&hBrush);
1480 m_pGamesList->UpdateGraphic(i,hBrush);
1481 }
1482#if 0
1483 XUIRect xuiRect;
1484 HXUIOBJ item = XuiListGetItemControl(m_GamesList,0);
1485
1486 HXUIOBJ hObj=NULL;
1487 HXUIOBJ hTextPres=NULL;
1488 HRESULT hr=XuiControlGetVisual(item,&hObj);
1489 hr=XuiElementGetChildById(hObj,L"text_Label",&hTextPres);
1490
1491 unsigned char displayLabelViewableStartIndex = 0;
1492 for( unsigned int i = 0; i < currentSessions.size(); ++i )
1493 {
1494 FriendSessionInfo *sessionInfo = currentSessions.at(i);
1495
1496 if(hTextPres != NULL )
1497 {
1498 hr=XuiTextPresenterMeasureText(hTextPres, sessionInfo->displayLabel, &xuiRect);
1499
1500 float fWidth, fHeight;
1501 XuiElementGetBounds(hTextPres,&fWidth,&fHeight);
1502 int characters = (fWidth/xuiRect.right) * sessionInfo->displayLabelLength;
1503
1504 if( characters < sessionInfo->displayLabelLength )
1505 {
1506 static wchar_t temp[100];
1507 ZeroMemory(temp, (100)*sizeof(wchar_t));
1508 wcsncpy_s( temp, sessionInfo->displayLabel+sessionInfo->displayLabelViewableStartIndex, characters );
1509 m_GamesList.SetText(i,temp);
1510 sessionInfo->displayLabelViewableStartIndex++;
1511 if( sessionInfo->displayLabelViewableStartIndex >= sessionInfo->displayLabelLength ) sessionInfo->displayLabelViewableStartIndex = 0;
1512 }
1513 }
1514 }
1515#endif
1516}*/
1517
1518void CScene_MultiGameJoinLoad::SearchForGameCallback(void *param, DWORD dwNumResults, IQNetGameSearch *pGameSearch)
1519{
1520#if 0
1521 HXUIOBJ hObj = (HXUIOBJ)param;
1522
1523 void *pObj;
1524 XuiObjectFromHandle( hObj, &pObj);
1525 CScene_MultiGameJoinLoad *MultiGameJoinLoad = (CScene_MultiGameJoinLoad *)pObj;
1526
1527 MultiGameJoinLoad->UpdateGamesList(dwNumResults, pGameSearch);
1528#endif
1529}
1530
1531int CScene_MultiGameJoinLoad::DeviceSelectReturned(void *pParam,bool bContinue)
1532{
1533 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
1534 //HRESULT hr;
1535
1536 if(bContinue==true)
1537 {
1538 // if the saves list has focus, then we should show the Delete Save tooltip
1539 // if the games list has focus, then we should show the View Gamercard tooltip
1540 int iRB=-1;
1541 int iY = -1;
1542 if( pClass->DoesGamesListHaveFocus() )
1543 {
1544 iY = IDS_TOOLTIPS_VIEW_GAMERCARD;
1545 }
1546 else if(pClass->DoesSavesListHaveFocus())
1547 {
1548 if(ProfileManager.IsSignedInLive( pClass->m_iPad ))
1549 {
1550 iY=IDS_TOOLTIPS_UPLOAD_SAVE_FOR_XBOXONE;
1551 }
1552 if(StorageManager.GetSaveDisabled())
1553 {
1554 iRB=IDS_TOOLTIPS_DELETESAVE;
1555 }
1556 else
1557 {
1558 if(StorageManager.EnoughSpaceForAMinSaveGame())
1559 {
1560 iRB=IDS_TOOLTIPS_SAVEOPTIONS;
1561 }
1562 else
1563 {
1564 iRB=IDS_TOOLTIPS_DELETESAVE;
1565 }
1566 }
1567 }
1568 else if(pClass->DoesMashUpWorldHaveFocus())
1569 {
1570 // If it's a mash-up pack world, give the Hide option
1571 iRB=IDS_TOOLTIPS_HIDE;
1572 }
1573
1574 int iLB = -1;
1575 if(pClass->m_bInParty)
1576 {
1577 if( pClass->m_bShowingPartyGamesOnly ) iLB = IDS_TOOLTIPS_ALL_GAMES;
1578 else iLB = IDS_TOOLTIPS_PARTY_GAMES;
1579 }
1580
1581 //BOOL bOnlineGame=pClass->m_CheckboxOnline.IsChecked();
1582
1583 // refresh the saves list (if there is a device selected)
1584
1585 // clear out the list first
1586
1587 if(StorageManager.GetSaveDisabled())
1588 {
1589 if(StorageManager.GetSaveDeviceSelected(pClass->m_iPad))
1590 {
1591 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_CHANGEDEVICE,iY,-1,-1,iLB,iRB);
1592 // saving is disabled, but we should still be able to load from a selected save device
1593 pClass->GetSaveInfo();
1594 }
1595 else
1596 {
1597 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE,iY,-1,-1,iLB,iRB);
1598 // clear the saves list
1599 pClass->m_pSavesList->RemoveAllData();
1600
1601 pClass->m_iSaveInfoC=0;
1602 //pClass->m_iThumbnailsLoadedC=0;
1603
1604 pClass->AddDefaultButtons();
1605
1606 pClass->m_SavesListTimer.SetShow( FALSE );
1607
1608 pClass->m_pSavesList->SetCurSelVisible(0);
1609 }
1610 }
1611 else
1612 {
1613 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_CHANGEDEVICE,iY,-1,-1,iLB,iRB);
1614 pClass->GetSaveInfo();
1615 }
1616 }
1617
1618 // enable input again
1619 pClass->m_bIgnoreInput=false;
1620
1621 return 0;
1622}
1623
1624HRESULT CScene_MultiGameJoinLoad::OnTimer( XUIMessageTimer *pTimer, BOOL& bHandled )
1625{
1626 // 4J-PB - TODO - Don't think we can do this - if a 2nd player signs in here with an offline profile, the signed in LIVE player gets re-logged in, and bMultiplayerAllowed is false briefly
1627 switch(pTimer->nId)
1628 {
1629
1630
1631 case JOIN_LOAD_ONLINE_TIMER_ID:
1632 {
1633 XPARTY_USER_LIST partyList;
1634
1635 if((XPartyGetUserList( &partyList ) != XPARTY_E_NOT_IN_PARTY ) && (partyList.dwUserCount>1))
1636 {
1637 m_bInParty=true;
1638 }
1639 else
1640 {
1641 m_bInParty=false;
1642 }
1643
1644 bool bMultiplayerAllowed = ProfileManager.IsSignedInLive( m_iPad ) && ProfileManager.AllowedToPlayMultiplayer(m_iPad);
1645 if(bMultiplayerAllowed != m_bMultiplayerAllowed)
1646 {
1647 if( bMultiplayerAllowed )
1648 {
1649// m_CheckboxOnline.SetEnable(TRUE);
1650// m_CheckboxPrivate.SetEnable(TRUE);
1651 }
1652 else
1653 {
1654 m_bInParty = false;
1655 m_pGamesList->RemoveAllData();
1656 //m_GamesList.DeleteItems(0, m_GamesList.GetItemCount() );
1657 m_pGamesList->SetEnable(FALSE);
1658 //XuiElementSetDisableFocusRecursion( m_pGamesList->m_hObj, TRUE);
1659 m_NetGamesListTimer.SetShow( TRUE );
1660 m_LabelNoGames.SetShow( FALSE );
1661 }
1662
1663 int iLB = -1;
1664 if(m_bInParty)
1665 {
1666 if( m_bShowingPartyGamesOnly ) iLB = IDS_TOOLTIPS_ALL_GAMES;
1667 else iLB = IDS_TOOLTIPS_PARTY_GAMES;
1668 }
1669 int iRB=-1;
1670 int iY=-1;
1671
1672 if( DoesGamesListHaveFocus() )
1673 {
1674 }
1675 else if(DoesSavesListHaveFocus())
1676 {
1677 if(ProfileManager.IsSignedInLive( m_iPad ))
1678 {
1679 iY=IDS_TOOLTIPS_UPLOAD_SAVE_FOR_XBOXONE;
1680 }
1681
1682 if(StorageManager.GetSaveDisabled())
1683 {
1684 iRB=IDS_TOOLTIPS_DELETESAVE;
1685 }
1686 else
1687 {
1688 if(StorageManager.EnoughSpaceForAMinSaveGame())
1689 {
1690 iRB=IDS_TOOLTIPS_SAVEOPTIONS;
1691 }
1692 else
1693 {
1694 iRB=IDS_TOOLTIPS_DELETESAVE;
1695 }
1696 }
1697 }
1698 else if(DoesMashUpWorldHaveFocus())
1699 {
1700 // If it's a mash-up pack world, give the Hide option
1701 iRB=IDS_TOOLTIPS_HIDE;
1702 }
1703
1704 if(ProfileManager.IsFullVersion()==false )
1705 {
1706 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, -1, -1,-1,-1,iLB);
1707 }
1708 else if(StorageManager.GetSaveDisabled())
1709 {
1710 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE,-1,-1,-1,iLB,iRB);
1711 }
1712 else
1713 {
1714 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, IDS_TOOLTIPS_CHANGEDEVICE,iY,-1,-1,iLB,iRB);
1715 }
1716 m_bMultiplayerAllowed = bMultiplayerAllowed;
1717 }
1718 }
1719 break;
1720 case JOIN_LOAD_SEARCH_MINIMUM_TIMER_ID:
1721 {
1722 XuiKillTimer( m_hObj, JOIN_LOAD_SEARCH_MINIMUM_TIMER_ID );
1723 m_NetGamesListTimer.SetShow( FALSE );
1724 m_LabelNoGames.SetShow( TRUE );
1725 }
1726 break;
1727 case JOIN_LOAD_SCROLL_GAME_NAMES_TIMER_ID:
1728 {
1729 // This is called by the gameslist callback function, so isn't needed on a timer
1730 //UpdateGamesListLabels();
1731 }
1732 break;
1733 case CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID:
1734 {
1735 // also check for any new texture packs info being available
1736 // for each item in the mem list, check it's in the data list
1737
1738 //CXuiCtrl4JList::LIST_ITEM_INFO ListInfo;
1739 // for each iConfig, check if the data is available, and add it to the List, then remove it from the viConfig
1740
1741 for(int i=0;i<m_iTexturePacksNotInstalled;i++)
1742 {
1743 if(m_iConfigA[i]!=-1)
1744 {
1745 DWORD dwBytes=0;
1746 PBYTE pbData=NULL;
1747 //app.DebugPrintf("Retrieving iConfig %d from TPD\n",m_iConfigA[i]);
1748
1749 app.GetTPD(m_iConfigA[i],&pbData,&dwBytes);
1750
1751 if(dwBytes > 0 && pbData)
1752 {
1753 //update the games list
1754 UpdateGamesList();
1755
1756 m_iConfigA[i]=-1;
1757 }
1758 }
1759 }
1760 bool bAllDone=true;
1761 for(int i=0;i<m_iTexturePacksNotInstalled;i++)
1762 {
1763 if(m_iConfigA[i]!=-1)
1764 {
1765 bAllDone = false;
1766 }
1767 }
1768
1769 if(bAllDone)
1770 {
1771 // kill this timer
1772 XuiKillTimer(m_hObj,CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID);
1773 }
1774 }
1775 break;
1776 }
1777
1778 return S_OK;
1779}
1780
1781/*
1782int CScene_MultiGameJoinLoad::LoadSaveDataReturned(void *pParam,bool bContinue)
1783{
1784 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
1785
1786 if(bContinue==true)
1787 {
1788 bool isClientSide = ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad());
1789
1790 // 4J Stu - If we only have one controller connected, then don't show the sign-in UI again
1791 DWORD connectedControllers = 0;
1792 for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
1793 {
1794 if( InputManager.IsPadConnected(i) || ProfileManager.IsSignedIn(i) ) ++connectedControllers;
1795 }
1796
1797 if(!isClientSide || connectedControllers == 1 || !RenderManager.IsHiDef())
1798 {
1799 DWORD dwLocalUsersMask = CGameNetworkManager::GetLocalPlayerMask(ProfileManager.GetPrimaryPad());
1800
1801 // No guest problems so we don't need to force a sign-in of players here
1802 StartGameFromSave(pClass, dwLocalUsersMask);
1803 }
1804 else
1805 {
1806 ProfileManager.RequestSignInUI(false, false, false, true, false,&CScene_MultiGameJoinLoad::StartGame_SignInReturned, pParam,ProfileManager.GetPrimaryPad());
1807 }
1808 }
1809 else
1810 {
1811 pClass->m_bIgnoreInput=false;
1812 }
1813 return 0;
1814}
1815*/
1816
1817int CScene_MultiGameJoinLoad::StartGame_SignInReturned(void *pParam,bool bContinue, int iPad)
1818{
1819 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
1820
1821 if(bContinue==true)
1822 {
1823 // It's possible that the player has not signed in - they can back out
1824 if(ProfileManager.IsSignedIn(iPad))
1825 {
1826 DWORD dwLocalUsersMask = 0;
1827
1828 for(unsigned int index = 0; index < XUSER_MAX_COUNT; ++index)
1829 {
1830 if(ProfileManager.IsSignedIn(index) )
1831 {
1832 dwLocalUsersMask |= CGameNetworkManager::GetLocalPlayerMask(index);
1833 }
1834 }
1835 StartGameFromSave(pClass, dwLocalUsersMask);
1836 }
1837 }
1838 else
1839 {
1840 pClass->m_bIgnoreInput=false;
1841 }
1842 return 0;
1843}
1844
1845// 4J Stu - Shared functionality that is the same whether we needed a quadrant sign-in or not
1846void CScene_MultiGameJoinLoad::StartGameFromSave(CScene_MultiGameJoinLoad* pClass, DWORD dwLocalUsersMask)
1847{
1848 /*bool isClientSide = ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()) && pClass->m_CheckboxOnline.IsChecked() == TRUE;
1849 //bool isPrivate = pClass->m_CheckboxPrivate.IsChecked() == TRUE;
1850
1851 SenStatGameEvent(ProfileManager.GetPrimaryPad(),eTelemetryGameEvent_Load,Minecraft::GetInstance()->options->difficulty, isClientSide, ProfileManager.IsFullVersion(), 1,0 );
1852
1853 g_NetworkManager.HostGame(dwLocalUsersMask,isClientSide,isPrivate,MINECRAFT_NET_MAX_PLAYERS,0);
1854
1855 LoadingInputParams *loadingParams = new LoadingInputParams();
1856 loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc;
1857 loadingParams->lpParam = NULL;
1858
1859 UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
1860 completionData->bShowBackground=TRUE;
1861 completionData->bShowLogo=TRUE;
1862 completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes;
1863 completionData->iPad = DEFAULT_XUI_MENU_USER;
1864 loadingParams->completionData = completionData;
1865
1866 app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);*/
1867}
1868
1869int CScene_MultiGameJoinLoad::DeleteSaveDataReturned(void *pParam,bool bSuccess)
1870{
1871 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
1872
1873 if(bSuccess==true)
1874 {
1875 // need to re-get the saves list and update the display
1876 // clear the saves list
1877 pClass->m_pSavesList->RemoveAllData();
1878 pClass->m_iSaveInfoC=0;
1879 pClass->GetSaveInfo();
1880 }
1881
1882 pClass->m_bIgnoreInput=false;
1883
1884 return 0;
1885}
1886
1887void CScene_MultiGameJoinLoad::LoadLevelGen(LevelGenerationOptions *levelGen)
1888{
1889 // Load data from disc
1890 //File saveFile( L"Tutorial\\Tutorial" );
1891 //LoadSaveFromDisk(&saveFile);
1892
1893 // clear out the app's terrain features list
1894 app.ClearTerrainFeaturePosition();
1895
1896 StorageManager.ResetSaveData();
1897 // Make our next save default to the name of the level
1898 StorageManager.SetSaveTitle(levelGen->getDefaultSaveName().c_str());
1899
1900 bool isClientSide = false;
1901 bool isPrivate = false;
1902 int maxPlayers = MINECRAFT_NET_MAX_PLAYERS;
1903
1904 if( app.GetTutorialMode() )
1905 {
1906 isClientSide = false;
1907 maxPlayers = 4;
1908 }
1909
1910 g_NetworkManager.HostGame(0,isClientSide,isPrivate,maxPlayers,0);
1911
1912 NetworkGameInitData *param = new NetworkGameInitData();
1913 param->seed = 0;
1914 param->saveData = NULL;
1915 param->settings = app.GetGameHostOption( eGameHostOption_Tutorial );
1916 param->levelGen = levelGen;
1917
1918 if(levelGen->requiresTexturePack())
1919 {
1920 param->texturePackId = levelGen->getRequiredTexturePackId();
1921
1922 Minecraft *pMinecraft = Minecraft::GetInstance();
1923 pMinecraft->skins->selectTexturePackById(param->texturePackId);
1924 //pMinecraft->skins->updateUI();
1925 }
1926
1927 LoadingInputParams *loadingParams = new LoadingInputParams();
1928 loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc;
1929 loadingParams->lpParam = (LPVOID)param;
1930
1931 UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
1932 completionData->bShowBackground=TRUE;
1933 completionData->bShowLogo=TRUE;
1934 completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes;
1935 completionData->iPad = DEFAULT_XUI_MENU_USER;
1936 loadingParams->completionData = completionData;
1937
1938 app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);
1939}
1940
1941void CScene_MultiGameJoinLoad::LoadSaveFromDisk(File *saveFile)
1942{
1943 // we'll only be coming in here when the tutorial is loaded now
1944
1945 StorageManager.ResetSaveData();
1946
1947 // Make our next save default to the name of the level
1948 StorageManager.SetSaveTitle(saveFile->getName().c_str());
1949
1950 __int64 fileSize = saveFile->length();
1951 FileInputStream fis(*saveFile);
1952 byteArray ba(fileSize);
1953 fis.read(ba);
1954 fis.close();
1955
1956 bool isClientSide = false;
1957 bool isPrivate = false;
1958 int maxPlayers = MINECRAFT_NET_MAX_PLAYERS;
1959
1960 if( app.GetTutorialMode() )
1961 {
1962 isClientSide = false;
1963 maxPlayers = 4;
1964 }
1965
1966 app.SetGameHostOption(eGameHostOption_GameType,GameType::CREATIVE->getId());
1967
1968 g_NetworkManager.HostGame(0,isClientSide,isPrivate,maxPlayers,0);
1969
1970 LoadSaveDataThreadParam *saveData = new LoadSaveDataThreadParam(ba.data, ba.length, saveFile->getName());
1971
1972 NetworkGameInitData *param = new NetworkGameInitData();
1973 param->seed = 0;
1974 param->saveData = saveData;
1975 param->settings = app.GetGameHostOption( eGameHostOption_All );
1976
1977 LoadingInputParams *loadingParams = new LoadingInputParams();
1978 loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc;
1979 loadingParams->lpParam = (LPVOID)param;
1980
1981 UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
1982 completionData->bShowBackground=TRUE;
1983 completionData->bShowLogo=TRUE;
1984 completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes;
1985 completionData->iPad = DEFAULT_XUI_MENU_USER;
1986 loadingParams->completionData = completionData;
1987
1988 app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);
1989}
1990
1991int CScene_MultiGameJoinLoad::DeleteSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
1992{
1993 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
1994 // results switched for this dialog
1995 if(result==C4JStorage::EMessage_ResultDecline)
1996 {
1997 if(app.DebugSettingsOn() && app.GetLoadSavesFromFolderEnabled())
1998 {
1999 pClass->m_bIgnoreInput=false;
2000 }
2001 else
2002 {
2003 XCONTENT_DATA XContentData;
2004 StorageManager.GetSaveCacheFileInfo(pClass->m_iChangingSaveGameInfoIndex-pClass->m_iDefaultButtonsC,XContentData);
2005 StorageManager.DeleteSaveData(&XContentData,CScene_MultiGameJoinLoad::DeleteSaveDataReturned,pClass);
2006 pClass->m_SavesListTimer.SetShow( TRUE );
2007 }
2008 }
2009 else
2010 {
2011 pClass->m_bIgnoreInput=false;
2012 }
2013 return 0;
2014}
2015
2016int CScene_MultiGameJoinLoad::SaveTransferDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
2017{
2018 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
2019 // results switched for this dialog
2020 if(result==C4JStorage::EMessage_ResultAccept)
2021 {
2022 // upload the save
2023
2024 // first load the save
2025 int iIndex=pClass->m_pSavesList->GetData(pClass->m_pSavesList->GetCurSel()).iIndex-pClass->m_iDefaultButtonsC;
2026 XCONTENT_DATA ContentData;
2027
2028 // 4J-PB - ensure we've switched to the right title group id for uploading to
2029 app.TMSPP_SetTitleGroupID(SAVETRANSFER_GROUP_ID);
2030 StorageManager.GetSaveCacheFileInfo(iIndex,ContentData);
2031 C4JStorage::ELoadGameStatus eLoadStatus=StorageManager.LoadSaveData(&ContentData,CScene_MultiGameJoinLoad::LoadSaveDataReturned,pClass);
2032
2033 pClass->m_bIgnoreInput=false;
2034 }
2035 else
2036 {
2037 pClass->m_bIgnoreInput=false;
2038 }
2039 return 0;
2040}
2041
2042int CScene_MultiGameJoinLoad::UploadSaveForXboxOneThreadProc( LPVOID lpParameter )
2043{
2044 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad *) lpParameter;
2045 Minecraft *pMinecraft = Minecraft::GetInstance();
2046
2047 pMinecraft->progressRenderer->progressStart(IDS_SAVE_TRANSFER_TITLE);
2048 pMinecraft->progressRenderer->progressStage( IDS_SAVE_TRANSFER_UPLOADING );
2049
2050 // Delete the marker file
2051 DeleteFile(pClass, "completemarker");
2052 if(!WaitForTransferComplete(pClass)) return 0;
2053
2054 // Upload the save data
2055 {
2056 unsigned int uiSaveBytes;
2057 uiSaveBytes=StorageManager.GetSaveSize();
2058 pClass->m_pbSaveTransferData=new BYTE [uiSaveBytes];
2059
2060 StorageManager.GetSaveData(pClass->m_pbSaveTransferData,&uiSaveBytes);
2061
2062 app.DebugPrintf("Uploading save data (%d bytes)\n", uiSaveBytes);
2063 UploadFile(pClass, "savedata", pClass->m_pbSaveTransferData, uiSaveBytes);
2064 }
2065
2066 if(!WaitForTransferComplete(pClass)) return 0;
2067 if(pClass->m_bTransferFail)
2068 {
2069 // something went wrong, user has been informed
2070 pMinecraft->progressRenderer->progressStage( IDS_SAVE_TRANSFER_UPLOADFAILED );
2071 return 0;
2072 }
2073
2074 // Upload the metadata and thumbnail
2075 {
2076 ByteArrayOutputStream baos;
2077 DataOutputStream dos(&baos);
2078
2079 LPCWSTR title = StorageManager.GetSaveTitle();
2080 dos.writeUTF(title);
2081
2082 char szUniqueMapName[14];
2083 StorageManager.GetSaveUniqueFilename(szUniqueMapName);
2084 dos.writeUTF(convStringToWstring(szUniqueMapName));
2085
2086 {
2087 // set the save icon
2088 PBYTE pbImageData=NULL;
2089 DWORD dwImageBytes=0;
2090 XCONTENT_DATA XContentData;
2091 int iIndex=pClass->m_pSavesList->GetData(pClass->m_pSavesList->GetCurSel()).iIndex-pClass->m_iDefaultButtonsC;
2092 StorageManager.GetSaveCacheFileInfo(iIndex,XContentData);
2093 StorageManager.GetSaveCacheFileInfo(iIndex,&pbImageData,&dwImageBytes);
2094
2095 // if there is no thumbnail, retrieve the default one from the file.
2096 // Don't delete the image data after creating the xuibrush, since we'll use it in the rename of the save
2097 if(pbImageData==NULL)
2098 {
2099 DWORD dwResult=XContentGetThumbnail(ProfileManager.GetPrimaryPad(),&XContentData,NULL,&dwImageBytes,NULL);
2100 if(dwResult==ERROR_SUCCESS)
2101 {
2102 pClass->m_pbSaveTransferData = new BYTE[dwImageBytes];
2103 pbImageData = pClass->m_pbSaveTransferData; // Copy pointer so that we can use the same name as the library owned one, but m_pbSaveTransferData will get deleted when done
2104 XContentGetThumbnail(ProfileManager.GetPrimaryPad(),&XContentData,pbImageData,&dwImageBytes,NULL);
2105 }
2106 }
2107
2108 dos.writeInt(dwImageBytes);
2109
2110 byteArray ba(pbImageData, dwImageBytes);
2111 dos.write(ba);
2112 }
2113
2114 pClass->m_pbSaveTransferData=new BYTE [baos.size()];
2115 memcpy(pClass->m_pbSaveTransferData,baos.buf.data,baos.size());
2116
2117 app.DebugPrintf("Uploading meta data (%d bytes)\n", baos.size());
2118 UploadFile(pClass, "metadata", pClass->m_pbSaveTransferData, baos.size());
2119 }
2120
2121 // Wait for metadata and thumbnail
2122 if(!WaitForTransferComplete(pClass)) return 0;
2123 if(pClass->m_bTransferFail)
2124 {
2125 // something went wrong, user has been informed
2126 pMinecraft->progressRenderer->progressStage( IDS_SAVE_TRANSFER_UPLOADFAILED );
2127 return 0;
2128 }
2129
2130 // Upload the marker file
2131 {
2132 char singleByteData[1] = {1};
2133 app.DebugPrintf("Uploading marker (%d bytes)\n", 1);
2134 UploadFile(pClass, "completemarker", &singleByteData, 1);
2135 }
2136
2137 // Wait for marker
2138 if(!WaitForTransferComplete(pClass)) return 0;
2139 if(pClass->m_bTransferFail)
2140 {
2141 // something went wrong, user has been informed
2142 pMinecraft->progressRenderer->progressStage( IDS_SAVE_TRANSFER_UPLOADFAILED );
2143
2144 return 0;
2145 }
2146 // change text for completion confirmation
2147 pMinecraft->progressRenderer->progressStage( IDS_SAVE_TRANSFER_UPLOADCOMPLETE );
2148
2149 // done
2150 return 0;
2151}
2152
2153void CScene_MultiGameJoinLoad::DeleteFile(CScene_MultiGameJoinLoad *pClass, char *filename)
2154{
2155 pClass->m_fProgress=0.0f;
2156 pClass->m_bTransferComplete=false;
2157
2158 C4JStorage::ETMSStatus result = StorageManager.TMSPP_DeleteFile(
2159 ProfileManager.GetPrimaryPad(),
2160 filename,
2161 C4JStorage::TMS_FILETYPE_BINARY,
2162 &CScene_MultiGameJoinLoad::DeleteComplete,
2163 pClass,
2164 NULL);
2165
2166 if(result != C4JStorage::ETMSStatus_DeleteInProgress)
2167 {
2168 DeleteComplete(pClass,ProfileManager.GetPrimaryPad(), -1);
2169 }
2170}
2171
2172void CScene_MultiGameJoinLoad::UploadFile(CScene_MultiGameJoinLoad *pClass, char *filename, LPVOID data, DWORD size)
2173{
2174 pClass->m_fProgress=0.0f;
2175 pClass->m_bTransferComplete=false;
2176
2177 C4JStorage::ETMSStatus result = StorageManager.TMSPP_WriteFileWithProgress(
2178 ProfileManager.GetPrimaryPad(),
2179 C4JStorage::eGlobalStorage_TitleUser,
2180 C4JStorage::TMS_FILETYPE_BINARY,
2181 C4JStorage::TMS_UGCTYPE_NONE,
2182 filename,
2183 (CHAR *)data,
2184 size,
2185 &CScene_MultiGameJoinLoad::TransferComplete,pClass, 0,
2186 &CScene_MultiGameJoinLoad::Progress,pClass);
2187
2188#ifdef _DEBUG_MENUS_ENABLED
2189 if(app.GetWriteSavesToFolderEnabled())
2190 {
2191 File targetFileDir(L"GAME:\\FakeTMSPP");
2192 if(!targetFileDir.exists()) targetFileDir.mkdir();
2193 string path = string( wstringtofilename( targetFileDir.getPath() ) ).append("\\").append(filename);
2194 HANDLE hSaveFile = CreateFile( path.c_str(), GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, NULL);
2195
2196 DWORD numberOfBytesWritten = 0;
2197 WriteFile( hSaveFile,data,size,&numberOfBytesWritten,NULL);
2198 assert(numberOfBytesWritten == size);
2199
2200 CloseHandle(hSaveFile);
2201 }
2202#endif
2203
2204 if(result != C4JStorage::ETMSStatus_WriteInProgress)
2205 {
2206 TransferComplete(pClass,ProfileManager.GetPrimaryPad(), -1);
2207 }
2208}
2209
2210bool CScene_MultiGameJoinLoad::WaitForTransferComplete( CScene_MultiGameJoinLoad *pClass )
2211{
2212 Minecraft *pMinecraft = Minecraft::GetInstance();
2213 // loop until complete
2214 while(pClass->m_bTransferComplete==false)
2215 {
2216 // check for a cancel
2217 if(pClass->m_bSaveTransferInProgress==false)
2218 {
2219 // cancelled
2220 return false;
2221 }
2222 Sleep(50);
2223 // update the progress
2224 pMinecraft->progressRenderer->progressStagePercentage((unsigned int)(pClass->m_fProgress*100.0f));
2225 }
2226
2227 // was there a transfer error?
2228
2229 return true;
2230}
2231
2232int CScene_MultiGameJoinLoad::SaveOptionsDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
2233{
2234 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
2235
2236 // results switched for this dialog
2237 // EMessage_ResultAccept means cancel
2238 if(result==C4JStorage::EMessage_ResultDecline || result==C4JStorage::EMessage_ResultThirdOption)
2239 {
2240 if(result==C4JStorage::EMessage_ResultDecline) // rename
2241 {
2242 ZeroMemory(pClass->m_wchNewName,sizeof(WCHAR)*XCONTENT_MAX_DISPLAYNAME_LENGTH);
2243 // bring up a keyboard
2244 InputManager.RequestKeyboard(IDS_RENAME_WORLD_TITLE,L"",IDS_RENAME_WORLD_TEXT,iPad,pClass->m_wchNewName,XCONTENT_MAX_DISPLAYNAME_LENGTH,&CScene_MultiGameJoinLoad::KeyboardReturned,pClass,C_4JInput::EKeyboardMode_Default,app.GetStringTable());
2245 }
2246 else // delete
2247 {
2248 // delete the save game
2249 // Have to ask the player if they are sure they want to delete this game
2250 UINT uiIDA[2];
2251 uiIDA[0]=IDS_CONFIRM_CANCEL;
2252 uiIDA[1]=IDS_CONFIRM_OK;
2253 StorageManager.RequestMessageBox(IDS_TOOLTIPS_DELETESAVE, IDS_TEXT_DELETE_SAVE, uiIDA, 2, iPad,&CScene_MultiGameJoinLoad::DeleteSaveDialogReturned,pClass, app.GetStringTable());
2254 //pClass->m_bIgnoreInput=false;
2255 }
2256 }
2257 else
2258 {
2259 pClass->m_bIgnoreInput=false;
2260 }
2261 return 0;
2262}
2263
2264int CScene_MultiGameJoinLoad::LoadSaveDataReturned(void *pParam,bool bContinue)
2265{
2266 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
2267
2268 if(bContinue==true)
2269 {
2270 pClass->m_bSaveTransferInProgress=true;
2271 LoadingInputParams *loadingParams = new LoadingInputParams();
2272 loadingParams->func = &CScene_MultiGameJoinLoad::UploadSaveForXboxOneThreadProc;
2273 loadingParams->lpParam = (LPVOID)pParam;
2274
2275 UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
2276 completionData->bShowBackground=TRUE;
2277 completionData->bShowLogo=TRUE;
2278 completionData->type = e_ProgressCompletion_NavigateBack;
2279 completionData->iPad = DEFAULT_XUI_MENU_USER;
2280 completionData->bRequiresUserAction=TRUE;
2281 loadingParams->completionData = completionData;
2282
2283 loadingParams->cancelFunc=&CScene_MultiGameJoinLoad::CancelSaveUploadCallback;
2284 loadingParams->completeFunc=&CScene_MultiGameJoinLoad::SaveUploadCompleteCallback;
2285 loadingParams->m_cancelFuncParam=pClass;
2286 loadingParams->m_completeFuncParam=pClass;
2287 loadingParams->cancelText=IDS_TOOLTIPS_CANCEL;
2288
2289 app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);
2290 }
2291 else
2292 {
2293 // switch back to the normal title group id
2294 app.TMSPP_SetTitleGroupID(GROUP_ID);
2295
2296 // the save is corrupt!
2297
2298 pClass->SetShow( TRUE );
2299 pClass->m_bIgnoreInput=false;
2300
2301 // give the option to delete the save
2302 UINT uiIDA[2];
2303 uiIDA[0]=IDS_CONFIRM_CANCEL;
2304 uiIDA[1]=IDS_CONFIRM_OK;
2305 StorageManager.RequestMessageBox(IDS_CORRUPT_OR_DAMAGED_SAVE_TITLE, IDS_CORRUPT_OR_DAMAGED_SAVE_TEXT, uiIDA, 2,
2306 pClass->m_iPad,&CScene_MultiGameJoinLoad::DeleteSaveDialogReturned,pClass, app.GetStringTable());
2307
2308 }
2309
2310 return 0;
2311}
2312
2313int CScene_MultiGameJoinLoad::Progress(void *pParam,float fProgress)
2314{
2315 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
2316
2317 app.DebugPrintf("Progress - %f\n",fProgress);
2318 pClass->m_fProgress=fProgress;
2319 return 0;
2320}
2321
2322int CScene_MultiGameJoinLoad::TransferComplete(void *pParam,int iPad, int iResult)
2323{
2324 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
2325
2326 delete [] pClass->m_pbSaveTransferData;
2327 pClass->m_pbSaveTransferData = NULL;
2328 if(iResult!=0)
2329 {
2330 // There was a transfer fail
2331 // Display a dialog
2332 UINT uiIDA[1];
2333 uiIDA[0]=IDS_CONFIRM_OK;
2334 StorageManager.RequestMessageBox(IDS_SAVE_TRANSFER_TITLE, IDS_SAVE_TRANSFER_UPLOADFAILED, uiIDA, 1, ProfileManager.GetPrimaryPad(),NULL,NULL,app.GetStringTable());
2335 pClass->m_bTransferFail=true;
2336 }
2337 else
2338 {
2339 pClass->m_bTransferFail=false;
2340 }
2341 pClass->m_bTransferComplete=true;
2342 //pClass->m_bSaveTransferInProgress=false;
2343 return 0;
2344}
2345
2346int CScene_MultiGameJoinLoad::DeleteComplete(void *pParam,int iPad, int iResult)
2347{
2348 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
2349 pClass->m_bTransferComplete=true;
2350 return 0;
2351}
2352
2353int CScene_MultiGameJoinLoad::KeyboardReturned(void *pParam,bool bSet)
2354{
2355 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
2356 HRESULT hr = S_OK;
2357
2358 // if the user has left the name empty, treat this as backing out
2359 if((pClass->m_wchNewName[0]!=0) && bSet)
2360 {
2361#ifdef _XBOX
2362 XCONTENT_DATA XContentData;
2363 StorageManager.GetSaveCacheFileInfo(pClass->m_iChangingSaveGameInfoIndex-pClass->m_iDefaultButtonsC,XContentData);
2364
2365 C4JStorage::ELoadGameStatus eLoadStatus=StorageManager.LoadSaveData(&XContentData,CScene_MultiGameJoinLoad::LoadSaveDataForRenameReturned,pClass);
2366
2367 if(eLoadStatus==C4JStorage::ELoadGame_DeviceRemoved)
2368 {
2369 // disable saving
2370 StorageManager.SetSaveDisabled(true);
2371 StorageManager.SetSaveDeviceSelected(ProfileManager.GetPrimaryPad(),false);
2372 UINT uiIDA[1];
2373 uiIDA[0]=IDS_OK;
2374 StorageManager.RequestMessageBox(IDS_STORAGEDEVICEPROBLEM_TITLE, IDS_FAILED_TO_LOADSAVE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(),&CScene_MultiGameJoinLoad::DeviceRemovedDialogReturned,pClass);
2375 }
2376#else
2377 // rename the save
2378
2379#endif
2380 }
2381 else
2382 {
2383 pClass->m_bIgnoreInput=false;
2384 }
2385
2386 return hr;
2387}
2388
2389int CScene_MultiGameJoinLoad::LoadSaveDataForRenameReturned(void *pParam,bool bContinue)
2390{
2391 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
2392#ifdef _XBOX
2393 if(bContinue==true)
2394 {
2395 // set the save icon
2396 PBYTE pbImageData=NULL;
2397 DWORD dwImageBytes=0;
2398 HXUIBRUSH hXuiBrush;
2399 XCONTENT_DATA XContentData;
2400 StorageManager.GetSaveCacheFileInfo(pClass->m_iChangingSaveGameInfoIndex-pClass->m_iDefaultButtonsC,XContentData);
2401 StorageManager.GetSaveCacheFileInfo(pClass->m_iChangingSaveGameInfoIndex-pClass->m_iDefaultButtonsC,&pbImageData,&dwImageBytes);
2402
2403 // if there is no thumbnail, retrieve the default one from the file.
2404 // Don't delete the image data after creating the xuibrush, since we'll use it in the rename of the save
2405 if(pbImageData==NULL)
2406 {
2407 DWORD dwResult=XContentGetThumbnail(ProfileManager.GetPrimaryPad(),&XContentData,NULL,&dwImageBytes,NULL);
2408 if(dwResult==ERROR_SUCCESS)
2409 {
2410 pbImageData = new BYTE[dwImageBytes];
2411 XContentGetThumbnail(ProfileManager.GetPrimaryPad(),&XContentData,pbImageData,&dwImageBytes,NULL);
2412 XuiCreateTextureBrushFromMemory(pbImageData,dwImageBytes,&hXuiBrush);
2413 }
2414 }
2415 else
2416 {
2417 XuiCreateTextureBrushFromMemory(pbImageData,dwImageBytes,&hXuiBrush);
2418 }
2419 // save the data with this icon
2420 StorageManager.CopySaveDataToNewSave( pbImageData,dwImageBytes,pClass->m_wchNewName,&CScene_MultiGameJoinLoad::CopySaveReturned,pClass);
2421 }
2422 else
2423#endif
2424 {
2425 //pClass->SetShow( TRUE );
2426 pClass->m_bIgnoreInput=false;
2427 }
2428 return 0;
2429}
2430
2431int CScene_MultiGameJoinLoad::CopySaveReturned(void *pParam,bool bResult)
2432{
2433 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
2434#ifdef _XBOX
2435 if(bResult)
2436 {
2437 // and delete the old save
2438 XCONTENT_DATA XContentData;
2439 StorageManager.GetSaveCacheFileInfo(pClass->m_iChangingSaveGameInfoIndex-pClass->m_iDefaultButtonsC,XContentData);
2440 StorageManager.DeleteSaveData(&XContentData,CScene_MultiGameJoinLoad::DeleteSaveDataReturned,pClass);
2441 pClass->m_SavesListTimer.SetShow( TRUE );
2442 }
2443 else
2444#endif
2445 {
2446 //pClass->SetShow( TRUE );
2447 pClass->m_bIgnoreInput=false;
2448 }
2449
2450 return 0;
2451}
2452
2453int CScene_MultiGameJoinLoad::TexturePackDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
2454{
2455 CScene_MultiGameJoinLoad *pClass = (CScene_MultiGameJoinLoad *)pParam;
2456
2457 // Exit with or without saving
2458 // Decline means install full version of the texture pack in this dialog
2459 if(result==C4JStorage::EMessage_ResultDecline || result==C4JStorage::EMessage_ResultAccept)
2460 {
2461 // we need to enable background downloading for the DLC
2462 XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW);
2463
2464 ULONGLONG ullOfferID_Full;
2465 ULONGLONG ullIndexA[1];
2466 app.GetDLCFullOfferIDForPackID(pClass->m_initData->selectedSession->data.texturePackParentId,&ullOfferID_Full);
2467
2468 if( result==C4JStorage::EMessage_ResultAccept ) // Full version
2469 {
2470 ullIndexA[0]=ullOfferID_Full;
2471 StorageManager.InstallOffer(1,ullIndexA,NULL,NULL);
2472
2473 }
2474 else // trial version
2475 {
2476 // if there is no trial version, this is a Cancel
2477 DLC_INFO *pDLCInfo=app.GetDLCInfoForFullOfferID(ullOfferID_Full);
2478 if(pDLCInfo->ullOfferID_Trial!=0LL)
2479 {
2480 ullIndexA[0]=pDLCInfo->ullOfferID_Trial;
2481 StorageManager.InstallOffer(1,ullIndexA,NULL,NULL);
2482 }
2483 }
2484 }
2485 pClass->m_bIgnoreInput=false;
2486 return 0;
2487}
2488
2489HRESULT CScene_MultiGameJoinLoad::OnCustomMessage_DLCInstalled()
2490{
2491 // mounted DLC may have changed
2492
2493 if(app.StartInstallDLCProcess(m_iPad)==false)
2494 {
2495 // not doing a mount, so re-enable input
2496 m_bIgnoreInput=false;
2497 }
2498 else
2499 {
2500 m_bIgnoreInput=true;
2501 // clear out the saves list and re-fill
2502
2503 m_pSavesList->RemoveAllData();
2504 m_SavesListTimer.SetShow( TRUE );
2505 }
2506 // this will send a CustomMessage_DLCMountingComplete when done
2507 return S_OK;
2508}
2509
2510HRESULT CScene_MultiGameJoinLoad::OnCustomMessage_DLCMountingComplete()
2511{
2512
2513 VOID *pObj;
2514 XuiObjectFromHandle( m_SavesList, &pObj );
2515 m_pSavesList = (CXuiCtrl4JList *)pObj;
2516
2517 m_iChangingSaveGameInfoIndex = 0;
2518
2519 m_generators = app.getLevelGenerators();
2520 m_iDefaultButtonsC = 0;
2521 m_iMashUpButtonsC = 0;
2522 XPARTY_USER_LIST partyList;
2523
2524 if((XPartyGetUserList( &partyList ) != XPARTY_E_NOT_IN_PARTY ) && (partyList.dwUserCount>1))
2525 {
2526 m_bInParty=true;
2527 }
2528 else
2529 {
2530 m_bInParty=false;
2531 }
2532
2533 int iLB = -1;
2534
2535 int iY=-1;
2536 if(DoesSavesListHaveFocus())
2537 {
2538 if(ProfileManager.IsSignedInLive( m_iPad ))
2539 {
2540 iY=IDS_TOOLTIPS_UPLOAD_SAVE_FOR_XBOXONE;
2541 }
2542 }
2543 if(m_bInParty) iLB = IDS_TOOLTIPS_PARTY_GAMES;
2544 // check if we're in the trial version
2545 if(ProfileManager.IsFullVersion()==false)
2546 {
2547 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK, -1, -1, -1, -1,iLB);
2548
2549 AddDefaultButtons();
2550
2551 m_pSavesList->SetCurSelVisible(0);
2552 }
2553 else if(StorageManager.GetSaveDisabled())
2554 {
2555 if(StorageManager.GetSaveDeviceSelected(m_iPad))
2556 {
2557 // saving is disabled, but we should still be able to load from a selected save device
2558
2559 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_CHANGEDEVICE,iY,-1,-1,iLB,IDS_TOOLTIPS_DELETESAVE);
2560
2561 GetSaveInfo();
2562 }
2563 else
2564 {
2565 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE,iY,-1,-1,iLB);
2566
2567 AddDefaultButtons();
2568 m_SavesListTimer.SetShow( FALSE );
2569
2570 m_pSavesList->SetCurSelVisible(0);
2571 }
2572 }
2573 else
2574 {
2575 // 4J-PB - we need to check that there is enough space left to create a copy of the save (for a rename)
2576 bool bCanRename = StorageManager.EnoughSpaceForAMinSaveGame();
2577 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_CHANGEDEVICE,iY,-1,-1,-1,bCanRename?IDS_TOOLTIPS_SAVEOPTIONS:IDS_TOOLTIPS_DELETESAVE);
2578
2579 GetSaveInfo();
2580 }
2581
2582 m_bIgnoreInput=false;
2583 app.m_dlcManager.checkForCorruptDLCAndAlert();
2584 return S_OK;
2585}
2586
2587/*
2588void CScene_MultiGameJoinLoad::UpdateTooltips()
2589{
2590 int iA=IDS_TOOLTIPS_SELECT;
2591 int iB=IDS_TOOLTIPS_BACK;
2592 int iX=-1;
2593 int iY=-1
2594 int iLB = -1;
2595 XPARTY_USER_LIST partyList;
2596
2597 if((XPartyGetUserList( &partyList ) != XPARTY_E_NOT_IN_PARTY ) && (partyList.dwUserCount>1))
2598 {
2599 m_bInParty=true;
2600 }
2601 else
2602 {
2603 m_bInParty=false;
2604 }
2605
2606 if(m_bInParty) iLB = IDS_TOOLTIPS_PARTY_GAMES;
2607
2608 if(ProfileManager.IsFullVersion()==false)
2609 {
2610 ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK, -1, -1, -1, -1,iLB);
2611 }
2612 else if(StorageManager.GetSaveDisabled())
2613 {
2614 if(StorageManager.GetSaveDeviceSelected(m_iPad))
2615 {
2616 // saving is disabled, but we should still be able to load from a selected save device
2617 iX=IDS_TOOLTIPS_CHANGEDEVICE;
2618 iRB=IDS_TOOLTIPS_DELETESAVE;
2619 }
2620 else
2621 {
2622 iX=IDS_TOOLTIPS_SELECTDEVICE;
2623 }
2624 }
2625 else
2626 {
2627 // 4J-PB - we need to check that there is enough space left to create a copy of the save (for a rename)
2628 bool bCanRename = StorageManager.EnoughSpaceForAMinSaveGame();
2629
2630 if(bCanRename)
2631 {
2632 iRB=IDS_TOOLTIPS_SAVEOPTIONS;
2633 }
2634 else
2635 {
2636 iRB=IDS_TOOLTIPS_DELETESAVE;
2637 }
2638 }
2639
2640 ui.SetTooltips( DEFAULT_XUI_MENU_USER, iA,iB, iX, iY, iLT, iRT,iLB, iRB);
2641}
2642*/
2643
2644
2645
2646#ifdef _XBOX
2647bool CScene_MultiGameJoinLoad::GetSavesInfoCallback(LPVOID pParam,int iTotalSaveInfoC, C4JStorage::CACHEINFOSTRUCT *InfoA, int iPad, HRESULT hResult)
2648{
2649 CScene_MultiGameJoinLoad *pClass=(CScene_MultiGameJoinLoad *)pParam;
2650 CXuiCtrl4JList::LIST_ITEM_INFO ListInfo;
2651 PBYTE pbImageData=(PBYTE)InfoA;
2652 PBYTE pbCurrentImagePtr;
2653 HXUIBRUSH hXuiBrush;
2654 HRESULT hr;
2655
2656 // move the image data pointer to the right place
2657 if(iTotalSaveInfoC!=0)
2658 {
2659 pbImageData+=sizeof(C4JStorage::CACHEINFOSTRUCT)*iTotalSaveInfoC;
2660 }
2661
2662 pClass->m_SavesListTimer.SetShow( FALSE );
2663 pClass->m_SavesList.SetEnable(TRUE);
2664
2665 pClass->AddDefaultButtons();
2666
2667 for(int i=0;i<iTotalSaveInfoC;i++)
2668 {
2669 ZeroMemory(&ListInfo,sizeof(CXuiCtrl4JList::LIST_ITEM_INFO));
2670 // Add these to the save list
2671 if(!(app.DebugSettingsOn() && app.GetLoadSavesFromFolderEnabled()))
2672 {
2673 // if the save is corrupt, display this instead of the title
2674 if(InfoA[i].dwImageBytes==0)
2675 {
2676 ListInfo.pwszText=app.GetString(IDS_CORRUPT_OR_DAMAGED_SAVE_TITLE);
2677 ListInfo.bIsDamaged=true;
2678 }
2679 else
2680 {
2681 ListInfo.pwszText=InfoA[i].wchDisplayName;
2682 ListInfo.bIsDamaged=false;
2683 }
2684 ListInfo.fEnabled=TRUE;
2685 ListInfo.iData = -1;
2686
2687 pClass->m_pSavesList->AddData(ListInfo,-1);
2688
2689 // update the graphic on the list item
2690
2691 // if there is no thumbnail, this is a corrupt file
2692 if(InfoA[i].dwImageBytes!=0)
2693 {
2694 pbCurrentImagePtr=pbImageData+InfoA[i].dwImageOffset;
2695 hr=XuiCreateTextureBrushFromMemory(pbCurrentImagePtr,InfoA[i].dwImageBytes,&hXuiBrush);
2696 pClass->m_pSavesList->UpdateGraphic(i+pClass->m_iDefaultButtonsC,hXuiBrush );
2697 }
2698 else
2699 {
2700 // we could put in a damaged save icon here
2701 const DWORD LOCATOR_SIZE = 256; // Use this to allocate space to hold a ResourceLocator string
2702 WCHAR szResourceLocator[ LOCATOR_SIZE ];
2703 const ULONG_PTR c_ModuleHandle = (ULONG_PTR)GetModuleHandle(NULL);
2704
2705 swprintf(szResourceLocator, LOCATOR_SIZE, L"section://%X,%ls#%ls",c_ModuleHandle,L"media", L"media/Graphics/MinecraftBrokenIcon.png");
2706
2707 XuiCreateTextureBrush(szResourceLocator,&hXuiBrush);
2708 pClass->m_pSavesList->UpdateGraphic(i+pClass->m_iDefaultButtonsC,hXuiBrush );
2709 }
2710 }
2711 }
2712
2713 pClass->m_iSaveInfoC=iTotalSaveInfoC;
2714
2715 // If there are some saves, then set the focus to be on the most recent one, which will be the first one after the create and tutorial
2716 if(iTotalSaveInfoC>0)
2717 {
2718 pClass->m_pSavesList->SetCurSelVisible(pClass->m_iDefaultButtonsC);
2719 pClass->m_bReady=true;
2720 }
2721
2722 pClass->m_bRetrievingSaveInfo=false;
2723
2724 // It's possible that the games list is updated but we haven't displayed it yet as we were still waiting on saves list to load
2725 // This is to fix a bug where joining a game before the saves list has loaded causes a crash when this callback is called
2726 // as the scene no longer exists
2727 pClass->UpdateGamesList();
2728
2729 // Fix for #45154 - Frontend: DLC: Content can only be downloaded from the frontend if you have not joined/exited multiplayer
2730 XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_AUTO);
2731
2732 return false;
2733}
2734#else
2735int CScene_MultiGameJoinLoad::GetSavesInfoCallback(LPVOID lpParam,const bool)
2736{
2737 return true;
2738}
2739#endif
2740
2741void CScene_MultiGameJoinLoad::CancelSaveUploadCallback(LPVOID lpParam)
2742{
2743 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad *) lpParam;
2744
2745 StorageManager.TMSPP_CancelWriteFileWithProgress(pClass->m_iPad);
2746
2747 pClass->m_bSaveTransferInProgress=false;
2748
2749 // change back to the normal title group id
2750 app.TMSPP_SetTitleGroupID(GROUP_ID);
2751// app.getRemoteStorage()->abort();
2752// pClass->m_eSaveUploadState = eSaveUpload_Idle;
2753
2754 UINT uiIDA[1] = { IDS_CONFIRM_OK };
2755 ui.RequestMessageBox(IDS_XBONE_CANCEL_UPLOAD_TITLE, IDS_XBONE_CANCEL_UPLOAD_TEXT, uiIDA, 1, pClass->m_iPad, NULL, NULL, app.GetStringTable());
2756}
2757
2758void CScene_MultiGameJoinLoad::SaveUploadCompleteCallback(LPVOID lpParam)
2759{
2760 CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad *) lpParam;
2761
2762 pClass->m_bSaveTransferInProgress=false;
2763 // change back to the normal title group id
2764 app.TMSPP_SetTitleGroupID(GROUP_ID);
2765 // app.getRemoteStorage()->abort();
2766 // pClass->m_eSaveUploadState = eSaveUpload_Idle;
2767}