aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/Common/XUI/XUI_MultiGameJoinLoad.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Minecraft.Client/Common/XUI/XUI_MultiGameJoinLoad.cpp')
-rw-r--r--Minecraft.Client/Common/XUI/XUI_MultiGameJoinLoad.cpp2767
1 files changed, 2767 insertions, 0 deletions
diff --git a/Minecraft.Client/Common/XUI/XUI_MultiGameJoinLoad.cpp b/Minecraft.Client/Common/XUI/XUI_MultiGameJoinLoad.cpp
new file mode 100644
index 00000000..73f25da5
--- /dev/null
+++ b/Minecraft.Client/Common/XUI/XUI_MultiGameJoinLoad.cpp
@@ -0,0 +1,2767 @@
+#include "stdafx.h"
+#include <xuiresource.h>
+#include <xuiapp.h>
+#include <assert.h>
+#include "..\..\..\Minecraft.World\StringHelpers.h"
+#include "..\..\Common\Tutorial\TutorialMode.h"
+#include "..\..\..\Minecraft.World\ConsoleSaveFileIO.h"
+#include "..\..\LocalPlayer.h"
+#include "..\..\Minecraft.h"
+#include "..\..\ProgressRenderer.h"
+#include "..\..\..\Minecraft.World\AABB.h"
+#include "..\..\..\Minecraft.World\Vec3.h"
+#include "..\..\..\Minecraft.World\ArrayWithLength.h"
+#include "..\..\..\Minecraft.World\File.h"
+#include "..\..\..\Minecraft.World\InputOutputStream.h"
+#include "XUI_Ctrl_4JList.h"
+#include "XUI_Ctrl_4JIcon.h"
+#include "XUI_LoadSettings.h"
+#include "XUI_MultiGameInfo.h"
+#include "XUI_MultiGameJoinLoad.h"
+#include "XUI_MultiGameCreate.h"
+#include "..\..\MinecraftServer.h"
+#include "..\..\Options.h"
+
+#include "..\GameRules\LevelGenerationOptions.h"
+#include "..\..\TexturePackRepository.h"
+#include "..\..\TexturePack.h"
+#include "..\..\..\Minecraft.World\LevelSettings.h"
+
+#define CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID 3
+#define CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME 100
+
+//----------------------------------------------------------------------------------
+// Performs initialization tasks - retrieves controls.
+//----------------------------------------------------------------------------------
+HRESULT CScene_MultiGameJoinLoad::OnInit( XUIMessageInit* pInitData, BOOL& bHandled )
+{
+
+ m_iPad=*(int *)pInitData->pvInitData;
+ m_bReady=false;
+ MapChildControls();
+
+ m_iTexturePacksNotInstalled=0;
+ m_iConfigA=NULL;
+
+ XuiControlSetText(m_LabelNoGames,app.GetString(IDS_NO_GAMES_FOUND));
+ XuiControlSetText(m_GamesList,app.GetString(IDS_JOIN_GAME));
+ XuiControlSetText(m_SavesList,app.GetString(IDS_START_GAME));
+
+
+ const DWORD LOCATOR_SIZE = 256; // Use this to allocate space to hold a ResourceLocator string
+ WCHAR szResourceLocator[ LOCATOR_SIZE ];
+
+ const ULONG_PTR c_ModuleHandle = (ULONG_PTR)GetModuleHandle(NULL);
+ swprintf(szResourceLocator, LOCATOR_SIZE ,L"section://%X,%ls#%ls",c_ModuleHandle,L"media", L"media/Graphics/TexturePackIcon.png");
+
+ m_DefaultMinecraftIconSize = 0;
+ HRESULT hr = XuiResourceLoadAllNoLoc(szResourceLocator, &m_DefaultMinecraftIconData, &m_DefaultMinecraftIconSize);
+
+ m_localPlayers = 1;
+ m_bKillSaveInfoEnumerate=false;
+
+ m_bShowingPartyGamesOnly = false;
+
+ m_bRetrievingSaveInfo=false;
+ m_bSaveTransferInProgress=false;
+
+ // check for a default custom cloak in the global storage
+ // 4J-PB - changed to a config file
+// if(ProfileManager.IsSignedInLive( m_iPad ))
+// {
+// app.InstallDefaultCape();
+// }
+
+ m_initData= new JoinMenuInitData();
+ m_bMultiplayerAllowed = ProfileManager.IsSignedInLive( m_iPad ) && ProfileManager.AllowedToPlayMultiplayer(m_iPad);
+
+ XPARTY_USER_LIST partyList;
+
+ if((XPartyGetUserList( &partyList ) != XPARTY_E_NOT_IN_PARTY ) && (partyList.dwUserCount>1))
+ {
+ m_bInParty=true;
+ }
+ else
+ {
+ m_bInParty=false;
+ }
+
+ int iLB = -1;
+ if(m_bInParty) iLB = IDS_TOOLTIPS_PARTY_GAMES;
+
+ XuiSetTimer(m_hObj,JOIN_LOAD_ONLINE_TIMER_ID,JOIN_LOAD_ONLINE_TIMER_TIME);
+
+ m_iSaveInfoC=0;
+
+ VOID *pObj;
+ XuiObjectFromHandle( m_SavesList, &pObj );
+ m_pSavesList = (CXuiCtrl4JList *)pObj;
+
+ XuiObjectFromHandle( m_GamesList, &pObj );
+ m_pGamesList = (CXuiCtrl4JList *)pObj;
+
+ // 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
+ if(app.StartInstallDLCProcess(m_iPad)==true)
+ {
+ // not doing a mount, so enable input
+ m_bIgnoreInput=true;
+ }
+ else
+ {
+ // 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
+ m_bIgnoreInput=false;
+
+
+
+ m_iChangingSaveGameInfoIndex = 0;
+
+ m_generators = app.getLevelGenerators();
+ m_iDefaultButtonsC = 0;
+ m_iMashUpButtonsC=0;
+
+ // check if we're in the trial version
+ if(ProfileManager.IsFullVersion()==false)
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK, -1, -1, -1, -1,iLB);
+
+ AddDefaultButtons();
+
+ m_pSavesList->SetCurSelVisible(0);
+ }
+ else if(StorageManager.GetSaveDisabled())
+ {
+ if(StorageManager.GetSaveDeviceSelected(m_iPad))
+ {
+ // saving is disabled, but we should still be able to load from a selected save device
+
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_CHANGEDEVICE,-1,-1,-1,iLB,IDS_TOOLTIPS_DELETESAVE);
+
+ GetSaveInfo();
+ }
+ else
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE,-1,-1,-1,iLB);
+
+ AddDefaultButtons();
+ m_SavesListTimer.SetShow( FALSE );
+
+ m_pSavesList->SetCurSelVisible(0);
+ }
+ }
+ else
+ {
+ // 4J-PB - we need to check that there is enough space left to create a copy of the save (for a rename)
+ bool bCanRename = StorageManager.EnoughSpaceForAMinSaveGame();
+ 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);
+
+ GetSaveInfo();
+ }
+ }
+ //XuiElementSetDisableFocusRecursion( m_pGamesList->m_hObj, TRUE);
+
+ UpdateGamesList();
+
+ g_NetworkManager.SetSessionsUpdatedCallback( &CScene_MultiGameJoinLoad::UpdateGamesListCallback, this );
+
+ // 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.
+ MinecraftServer::resetFlags();
+
+ // 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.
+ if( !m_bIgnoreInput)
+ {
+ app.m_dlcManager.checkForCorruptDLCAndAlert();
+ }
+
+
+ // 4J-PB - Load up any texture pack data we have locally in the XZP
+ for(int i=0;i<TMS_COUNT;i++)
+ {
+ if(app.TMSFileA[i].eTMSType==eTMSFileType_TexturePack)
+ {
+ app.LoadLocalTMSFile(app.TMSFileA[i].wchFilename,app.TMSFileA[i].eEXT);
+ app.AddMemoryTPDFile(app.TMSFileA[i].iConfig, app.TMSFileA[i].pbData,app.TMSFileA[i].uiSize);
+ }
+ }
+
+ // 4J-PB - there may be texture packs we don't have, so use the info from TMS for this
+
+ DLC_INFO *pDLCInfo=NULL;
+
+ // first pass - look to see if there are any that are not in the list
+ bool bTexturePackAlreadyListed;
+ bool bNeedToGetTPD=false;
+ Minecraft *pMinecraft = Minecraft::GetInstance();
+ int texturePacksCount = pMinecraft->skins->getTexturePackCount();
+ //CXuiCtrl4JList::LIST_ITEM_INFO ListInfo;
+ //HRESULT hr;
+
+
+ for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i)
+ {
+ bTexturePackAlreadyListed=false;
+ ULONGLONG ull=app.GetDLCInfoTexturesFullOffer(i);
+ pDLCInfo=app.GetDLCInfoForFullOfferID(ull);
+ for(unsigned int i = 0; i < texturePacksCount; ++i)
+ {
+ TexturePack *tp = pMinecraft->skins->getTexturePackByIndex(i);
+ if(pDLCInfo->iConfig==tp->getDLCParentPackId())
+ {
+ bTexturePackAlreadyListed=true;
+ }
+ }
+ if(bTexturePackAlreadyListed==false)
+ {
+ // some missing
+ bNeedToGetTPD=true;
+
+ m_iTexturePacksNotInstalled++;
+ }
+ }
+
+ if(bNeedToGetTPD==true)
+ {
+ // add a TMS request for them
+ app.DebugPrintf("+++ Adding TMSPP request for texture pack data\n");
+ app.AddTMSPPFileTypeRequest(e_DLC_TexturePackData);
+ m_iConfigA= new int [m_iTexturePacksNotInstalled];
+ m_iTexturePacksNotInstalled=0;
+
+ for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i)
+ {
+ bTexturePackAlreadyListed=false;
+ ULONGLONG ull=app.GetDLCInfoTexturesFullOffer(i);
+ pDLCInfo=app.GetDLCInfoForFullOfferID(ull);
+ for(unsigned int i = 0; i < texturePacksCount; ++i)
+ {
+ TexturePack *tp = pMinecraft->skins->getTexturePackByIndex(i);
+ if(pDLCInfo->iConfig==tp->getDLCParentPackId())
+ {
+ bTexturePackAlreadyListed=true;
+ }
+ }
+ if(bTexturePackAlreadyListed==false)
+ {
+ m_iConfigA[m_iTexturePacksNotInstalled++]=pDLCInfo->iConfig;
+ }
+ }
+ }
+
+ XuiSetTimer(m_hObj,CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID,CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME);
+
+ return S_OK;
+}
+
+void CScene_MultiGameJoinLoad::AddDefaultButtons()
+{
+ CXuiCtrl4JList::LIST_ITEM_INFO ListInfo;
+
+ // Add two for New Game and Tutorial
+ ZeroMemory(&ListInfo,sizeof(CXuiCtrl4JList::LIST_ITEM_INFO));
+
+ ListInfo.pwszText = app.GetString(IDS_CREATE_NEW_WORLD);
+ ListInfo.fEnabled = TRUE;
+ ListInfo.iData = -1;
+ m_pSavesList->AddData(ListInfo);
+
+ int iSavesListIndex = 0;
+ int iGeneratorIndex = 0;
+ m_iMashUpButtonsC=0;
+
+ for(AUTO_VAR(it, m_generators->begin()); it != m_generators->end(); ++it)
+ {
+ LevelGenerationOptions *levelGen = *it;
+ ListInfo.pwszText = levelGen->getWorldName();
+ ListInfo.fEnabled = TRUE;
+ ListInfo.iData = iGeneratorIndex++; // used to index into the list of generators
+
+ // need to check if the user has disabled this pack in the save display list
+ unsigned int uiTexturePackID=levelGen->getRequiredTexturePackId();
+
+ if(uiTexturePackID!=0)
+ {
+ unsigned int uiMashUpWorldsBitmask=app.GetMashupPackWorlds(m_iPad);
+
+ if((uiMashUpWorldsBitmask & (1<<(uiTexturePackID-1024)))==0)
+ {
+ // this world is hidden, so skip
+ continue;
+ }
+ }
+ m_pSavesList->AddData(ListInfo);
+
+ // retrieve the save icon from the texture pack, if there is one
+ if(uiTexturePackID!=0)
+ {
+ // increment the count of the mash-up pack worlds in the save list
+ m_iMashUpButtonsC++;
+ TexturePack *tp = Minecraft::GetInstance()->skins->getTexturePackById(levelGen->getRequiredTexturePackId());
+ DWORD dwImageBytes;
+ PBYTE pbImageData = tp->getPackIcon(dwImageBytes);
+ HXUIBRUSH hXuiBrush;
+
+ if(dwImageBytes > 0 && pbImageData)
+ {
+ XuiCreateTextureBrushFromMemory(pbImageData,dwImageBytes,&hXuiBrush);
+ // 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
+ m_pSavesList->UpdateGraphic(iSavesListIndex+1,hXuiBrush);
+ }
+ }
+
+ ++iSavesListIndex;
+ }
+
+ m_iDefaultButtonsC = iSavesListIndex + 1;
+}
+
+
+HRESULT CScene_MultiGameJoinLoad::GetSaveInfo( )
+{
+ unsigned int uiSaveC=0;
+
+ // This will return with the number retrieved in uiSaveC
+
+ if(app.DebugSettingsOn() && app.GetLoadSavesFromFolderEnabled())
+ {
+ uiSaveC = 0;
+ File savesDir(L"GAME:\\Saves");
+ if( savesDir.exists() )
+ {
+ m_saves = savesDir.listFiles();
+ uiSaveC = (unsigned int)m_saves->size();
+ }
+ // add the New Game and Tutorial after the saves list is retrieved, if there are any saves
+
+ // Add two for New Game and Tutorial
+ unsigned int listItems = uiSaveC;
+
+ CXuiCtrl4JList::LIST_ITEM_INFO ListInfo;
+ ZeroMemory(&ListInfo,sizeof(CXuiCtrl4JList::LIST_ITEM_INFO));
+
+ AddDefaultButtons();
+
+ for(unsigned int i=0;i<listItems;i++)
+ {
+
+ wstring wName = m_saves->at(i)->getName();
+ wchar_t *name = new wchar_t[wName.size()+1];
+ for(unsigned int j = 0; j < wName.size(); ++j)
+ {
+ name[j] = wName[j];
+ }
+ name[wName.size()] = 0;
+ ListInfo.pwszText = name;
+ ListInfo.fEnabled=TRUE;
+ ListInfo.iData = -1;
+ m_pSavesList->AddData(ListInfo);
+ }
+ m_pSavesList->SetCurSelVisible(0);
+ }
+ else
+ {
+ m_bRetrievingSaveInfo=true; // we're blocking the exit from this scene until complete
+
+ // clear the saves list
+ m_pSavesList->RemoveAllData();
+
+ m_iSaveInfoC=0;
+#ifdef _XBOX
+ C4JStorage::ESGIStatus eSGIStatus=StorageManager.GetSavesInfo(ProfileManager.GetPrimaryPad(),&CScene_MultiGameJoinLoad::GetSavesInfoCallback,this,"savegame.dat");
+
+ if(eSGIStatus==C4JStorage::ESGIStatus_NoSaves)
+ {
+ uiSaveC=0;
+ m_SavesListTimer.SetShow( FALSE );
+ m_SavesList.SetEnable(TRUE);
+ }
+#else
+
+ //C4JStorage::ESaveGameState eStatus=StorageManager.GetSavesInfo(ProfileManager.GetPrimaryPad(),&CScene_MultiGameJoinLoad::GetSavesInfoCallback,this,"savegame.dat");
+
+#endif
+ }
+
+ return S_OK;
+}
+
+HRESULT CScene_MultiGameJoinLoad::OnDestroy()
+{
+ g_NetworkManager.SetSessionsUpdatedCallback( NULL, NULL );
+
+ for(AUTO_VAR(it, currentSessions.begin()); it < currentSessions.end(); ++it)
+ {
+ delete (*it);
+ }
+
+ if(m_bSaveTransferInProgress)
+ {
+ CancelSaveUploadCallback(this);
+ }
+
+ // Reset the background downloading, in case we changed it by attempting to download a texture pack
+ XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_AUTO);
+
+ // clear out the texture pack data
+ for(int i=0;i<TMS_COUNT;i++)
+ {
+ if(app.TMSFileA[i].eTMSType==eTMSFileType_TexturePack)
+ {
+ app.RemoveMemoryTPDFile(app.TMSFileA[i].iConfig);
+ }
+ }
+ app.FreeLocalTMSFiles(eTMSFileType_TexturePack);
+
+ return S_OK;
+}
+
+
+int CScene_MultiGameJoinLoad::DeviceRemovedDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
+{
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
+
+ // results switched for this dialog
+ if(result==C4JStorage::EMessage_ResultDecline)
+ {
+ StorageManager.SetSaveDisabled(true);
+ StorageManager.SetSaveDeviceSelected(ProfileManager.GetPrimaryPad(),false);
+ // use the device select returned function to wipe the saves list and change the tooltip
+ CScene_MultiGameJoinLoad::DeviceSelectReturned(pClass,true);
+ }
+ else // continue without saving
+ {
+ // Change device
+ StorageManager.SetSaveDevice(&CScene_MultiGameJoinLoad::DeviceSelectReturned,pClass,true);
+ }
+
+ pClass->m_bIgnoreInput=false;
+ return 0;
+}
+//----------------------------------------------------------------------------------
+// Handler for the button press message.
+//----------------------------------------------------------------------------------
+HRESULT CScene_MultiGameJoinLoad::OnNotifyPressEx(HXUIOBJ hObjPressed, XUINotifyPress* pNotifyPressData, BOOL& rfHandled)
+{
+ if(m_bIgnoreInput) return S_OK;
+
+ // if we're retrieving save info, ignore key presses
+ if(m_bRetrievingSaveInfo)
+ {
+ return S_OK;
+ }
+
+ // This assumes all buttons can only be pressed with the A button
+ ui.AnimateKeyPress(pNotifyPressData->UserIndex, VK_PAD_A);
+
+ if ( hObjPressed == m_GamesList )
+ {
+ m_bIgnoreInput=true;
+
+ DWORD nIndex = m_pGamesList->GetCurSel();
+
+ if( m_pGamesList->GetItemCount() > 0 && nIndex < currentSessions.size() )
+ {
+ //CScene_MultiGameInfo::JoinMenuInitData *initData = new CScene_MultiGameInfo::JoinMenuInitData();
+ m_initData->iPad = m_iPad;
+ m_initData->selectedSession = currentSessions.at( nIndex );
+
+ // check that we have the texture pack available
+ // If it's not the default texture pack
+ if(m_initData->selectedSession->data.texturePackParentId!=0)
+ {
+ int texturePacksCount = Minecraft::GetInstance()->skins->getTexturePackCount();
+ bool bHasTexturePackInstalled=false;
+
+ for(int i=0;i<texturePacksCount;i++)
+ {
+ TexturePack *tp = Minecraft::GetInstance()->skins->getTexturePackByIndex(i);
+ if(tp->getDLCParentPackId()==m_initData->selectedSession->data.texturePackParentId)
+ {
+ bHasTexturePackInstalled=true;
+ break;
+ }
+ }
+
+ if(bHasTexturePackInstalled==false)
+ {
+ // upsell the texture pack
+ // tell sentient about the upsell of the full version of the skin pack
+ ULONGLONG ullOfferID_Full;
+ app.GetDLCFullOfferIDForPackID(m_initData->selectedSession->data.texturePackParentId,&ullOfferID_Full);
+
+ TelemetryManager->RecordUpsellPresented(pNotifyPressData->UserIndex, eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF);
+
+ UINT uiIDA[3];
+
+ // Need to check if the texture pack has both Full and Trial versions - we may do some as free ones, so only Full
+ DLC_INFO *pDLCInfo=app.GetDLCInfoForFullOfferID(ullOfferID_Full);
+
+ if(pDLCInfo->ullOfferID_Trial!=0LL)
+ {
+ uiIDA[0]=IDS_TEXTUREPACK_FULLVERSION;
+ uiIDA[1]=IDS_TEXTURE_PACK_TRIALVERSION;
+ uiIDA[2]=IDS_CONFIRM_CANCEL;
+ // Give the player a warning about the texture pack missing
+ StorageManager.RequestMessageBox(IDS_DLC_TEXTUREPACK_NOT_PRESENT_TITLE, IDS_DLC_TEXTUREPACK_NOT_PRESENT, uiIDA, 3, ProfileManager.GetPrimaryPad(),&CScene_MultiGameJoinLoad::TexturePackDialogReturned,this,app.GetStringTable());
+ }
+ else
+ {
+ uiIDA[0]=IDS_TEXTUREPACK_FULLVERSION;
+ uiIDA[1]=IDS_CONFIRM_CANCEL;
+ // Give the player a warning about the texture pack missing
+ StorageManager.RequestMessageBox(IDS_DLC_TEXTUREPACK_NOT_PRESENT_TITLE, IDS_DLC_TEXTUREPACK_NOT_PRESENT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CScene_MultiGameJoinLoad::TexturePackDialogReturned,this,app.GetStringTable());
+ }
+
+ return S_OK;
+ }
+ }
+
+ m_NetGamesListTimer.SetShow( FALSE );
+
+ // Reset the background downloading, in case we changed it by attempting to download a texture pack
+ XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_AUTO);
+
+ // kill the texture pack check timer
+ XuiKillTimer(m_hObj,CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID);
+ app.NavigateToScene(pNotifyPressData->UserIndex,eUIScene_JoinMenu,m_initData);
+ }
+ }
+ else if(hObjPressed==m_SavesList)
+ {
+ m_bIgnoreInput=true;
+
+ CXuiControl pItem;
+ int iIndex;
+ // get the selected item
+ iIndex=m_SavesList.GetCurSel(&pItem);
+
+ CXuiCtrl4JList::LIST_ITEM_INFO info = m_pSavesList->GetData(iIndex);
+
+ if(iIndex == JOIN_LOAD_CREATE_BUTTON_INDEX)
+ {
+ app.SetTutorialMode( false );
+ m_NetGamesListTimer.SetShow( FALSE );
+
+ app.SetCorruptSaveDeleted(false);
+
+ CreateWorldMenuInitData *params = new CreateWorldMenuInitData();
+ params->iPad = m_iPad;
+ app.NavigateToScene(pNotifyPressData->UserIndex,eUIScene_CreateWorldMenu,(void *)params);
+ }
+ else if(info.iData >= 0)
+ {
+ LevelGenerationOptions *levelGen = m_generators->at(info.iData);
+ app.SetTutorialMode( levelGen->isTutorial() );
+ // Reset the autosave time
+ app.SetAutosaveTimerTime();
+
+ if(levelGen->isTutorial())
+ {
+ LoadLevelGen(levelGen);
+ }
+ else
+ {
+ LoadMenuInitData *params = new LoadMenuInitData();
+ params->iPad = m_iPad;
+ // 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
+ params->iSaveGameInfoIndex=-1;
+ //params->pbSaveRenamed=&m_bSaveRenamed;
+ params->levelGen = levelGen;
+
+ // navigate to the settings scene
+ app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_LoadMenu, params);
+ }
+ }
+ else
+ {
+ // check if this is a damaged save
+ if(m_pSavesList->GetData(iIndex).bIsDamaged)
+ {
+ // give the option to delete the save
+ UINT uiIDA[2];
+ uiIDA[0]=IDS_CONFIRM_CANCEL;
+ uiIDA[1]=IDS_CONFIRM_OK;
+ StorageManager.RequestMessageBox(IDS_CORRUPT_OR_DAMAGED_SAVE_TITLE, IDS_CORRUPT_OR_DAMAGED_SAVE_TEXT, uiIDA, 2, pNotifyPressData->UserIndex,&CScene_MultiGameJoinLoad::DeleteSaveDialogReturned,this, app.GetStringTable());
+ }
+ else
+ {
+ app.SetTutorialMode( false );
+ if(app.DebugSettingsOn() && app.GetLoadSavesFromFolderEnabled())
+ {
+ LoadSaveFromDisk(m_saves->at(iIndex-m_iDefaultButtonsC));
+ }
+ else
+ {
+ LoadMenuInitData *params = new LoadMenuInitData();
+ params->iPad = m_iPad;
+ // 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
+ params->iSaveGameInfoIndex=m_pSavesList->GetData(iIndex).iIndex-m_iDefaultButtonsC;
+ //params->pbSaveRenamed=&m_bSaveRenamed;
+ params->levelGen = NULL;
+
+ // kill the texture pack timer
+ XuiKillTimer(m_hObj,CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID);
+ // navigate to the settings scene
+ app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_LoadMenu, params);
+ }
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+HRESULT CScene_MultiGameJoinLoad::OnKeyDown(XUIMessageInput* pInputData, BOOL& rfHandled)
+{
+ if(m_bIgnoreInput) return S_OK;
+
+ // if we're retrieving save info, ignore key presses
+ if(m_bRetrievingSaveInfo)
+ {
+ return S_OK;
+ }
+
+ ui.AnimateKeyPress(pInputData->UserIndex, pInputData->dwKeyCode);
+
+ HRESULT hr = S_OK;
+
+ // Explicitly handle B button presses
+ switch(pInputData->dwKeyCode)
+ {
+ case VK_PAD_B:
+ case VK_ESCAPE:
+ m_NetGamesListTimer.SetShow( FALSE );
+
+ app.NavigateBack(XUSER_INDEX_ANY);
+ rfHandled = TRUE;
+ break;
+ case VK_PAD_X:
+
+ // Change device
+ // Fix for #12531 - TCR 001: BAS Game Stability: When a player selects to change a storage
+ // device, and repeatedly backs out of the SD screen, disconnects from LIVE, and then selects a SD, the title crashes.
+ m_bIgnoreInput=true;
+ StorageManager.SetSaveDevice(&CScene_MultiGameJoinLoad::DeviceSelectReturned,this,true);
+ CXuiSceneBase::PlayUISFX(eSFX_Press);
+ break;
+ case VK_PAD_Y:
+ if(m_pGamesList->TreeHasFocus() && m_pGamesList->GetItemCount() > 0)
+ {
+ DWORD nIndex = m_pGamesList->GetCurSel();
+ FriendSessionInfo *pSelectedSession = currentSessions.at( nIndex );
+
+ PlayerUID xuid = pSelectedSession->data.hostPlayerUID;
+ if( xuid != INVALID_XUID )
+ hr = XShowGamerCardUI(ProfileManager.GetLockedProfile(), xuid);
+ CXuiSceneBase::PlayUISFX(eSFX_Press);
+ }
+ else if(DoesSavesListHaveFocus())
+ {
+ // save transfer - make sure they want to overwrite a save that is up there
+ if(ProfileManager.IsSignedInLive( m_iPad ))
+ {
+ // 4J-PB - required for a delete of the save if it's found to be a corrupted save
+ DWORD nIndex = m_pSavesList->GetCurSel();
+ m_iChangingSaveGameInfoIndex=m_pSavesList->GetData(nIndex).iIndex;
+
+ UINT uiIDA[2];
+ uiIDA[0]=IDS_UPLOAD_SAVE;
+ uiIDA[1]=IDS_CONFIRM_CANCEL;
+
+ ui.RequestMessageBox(IDS_SAVE_TRANSFER_TITLE, IDS_SAVE_TRANSFER_TEXT, uiIDA, 2, pInputData->UserIndex,&CScene_MultiGameJoinLoad::SaveTransferDialogReturned,this, app.GetStringTable());
+ }
+ }
+ break;
+ case VK_PAD_RSHOULDER:
+ if(DoesSavesListHaveFocus())
+ {
+ m_bIgnoreInput = true;
+
+ int iIndex=m_SavesList.GetCurSel();
+ m_iChangingSaveGameInfoIndex=m_pSavesList->GetData(iIndex).iIndex;
+
+ // Could be delete save or Save Options
+ if(StorageManager.GetSaveDisabled())
+ {
+ // delete the save game
+ // Have to ask the player if they are sure they want to delete this game
+ UINT uiIDA[2];
+ uiIDA[0]=IDS_CONFIRM_CANCEL;
+ uiIDA[1]=IDS_CONFIRM_OK;
+ StorageManager.RequestMessageBox(IDS_TOOLTIPS_DELETESAVE, IDS_TEXT_DELETE_SAVE, uiIDA, 2, pInputData->UserIndex,&CScene_MultiGameJoinLoad::DeleteSaveDialogReturned,this, app.GetStringTable());
+ }
+ else
+ {
+ if(StorageManager.EnoughSpaceForAMinSaveGame())
+ {
+ UINT uiIDA[3];
+ uiIDA[0]=IDS_CONFIRM_CANCEL;
+ uiIDA[1]=IDS_TITLE_RENAMESAVE;
+ uiIDA[2]=IDS_TOOLTIPS_DELETESAVE;
+ StorageManager.RequestMessageBox(IDS_TOOLTIPS_SAVEOPTIONS, IDS_TEXT_SAVEOPTIONS, uiIDA, 3, pInputData->UserIndex,&CScene_MultiGameJoinLoad::SaveOptionsDialogReturned,this, app.GetStringTable());
+ }
+ else
+ {
+ // delete the save game
+ // Have to ask the player if they are sure they want to delete this game
+ UINT uiIDA[2];
+ uiIDA[0]=IDS_CONFIRM_CANCEL;
+ uiIDA[1]=IDS_CONFIRM_OK;
+ StorageManager.RequestMessageBox(IDS_TOOLTIPS_DELETESAVE, IDS_TEXT_DELETE_SAVE, uiIDA, 2, pInputData->UserIndex,&CScene_MultiGameJoinLoad::DeleteSaveDialogReturned,this, app.GetStringTable());
+ }
+ }
+ CXuiSceneBase::PlayUISFX(eSFX_Press);
+
+ }
+ else if(DoesMashUpWorldHaveFocus())
+ {
+ // hiding a mash-up world
+ // get the mash-up pack id
+ CXuiControl pItem;
+ int iIndex;
+ iIndex=m_SavesList.GetCurSel(&pItem);
+
+ CXuiCtrl4JList::LIST_ITEM_INFO info = m_pSavesList->GetData(iIndex);
+ if((iIndex != JOIN_LOAD_CREATE_BUTTON_INDEX) && (info.iData >= 0))
+ {
+ LevelGenerationOptions *levelGen = m_generators->at(info.iData);
+
+ if(!levelGen->isTutorial())
+ {
+ if(levelGen->requiresTexturePack())
+ {
+ unsigned int uiPackID=levelGen->getRequiredTexturePackId();
+
+ m_bIgnoreInput = true;
+ app.HideMashupPackWorld(m_iPad,uiPackID);
+
+ // update the saves list
+ m_pSavesList->RemoveAllData();
+ m_iSaveInfoC=0;
+ GetSaveInfo();
+ m_bIgnoreInput = false;
+ }
+ }
+ }
+
+ CXuiSceneBase::PlayUISFX(eSFX_Press);
+
+ }
+ break;
+ case VK_PAD_LSHOULDER:
+ if( m_bInParty )
+ {
+ m_bShowingPartyGamesOnly = !m_bShowingPartyGamesOnly;
+ UpdateGamesList();
+ CXuiSceneBase::PlayUISFX(eSFX_Press);
+ }
+ break;
+ }
+
+ return hr;
+}
+
+HRESULT CScene_MultiGameJoinLoad::OnNavReturn(HXUIOBJ hSceneFrom,BOOL& rfHandled)
+{
+
+ CXuiSceneBase::ShowLogo( DEFAULT_XUI_MENU_USER, TRUE );
+ // start the texture pack timer again
+ XuiSetTimer(m_hObj,CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID,CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME);
+
+ m_bMultiplayerAllowed = ProfileManager.IsSignedInLive( m_iPad ) && ProfileManager.AllowedToPlayMultiplayer(m_iPad);
+
+ // re-enable button presses
+ m_bIgnoreInput=false;
+
+ if( m_bMultiplayerAllowed )
+ {
+ HXUICLASS hClassFullscreenProgress = XuiFindClass( L"CScene_FullscreenProgress" );
+ HXUICLASS hClassConnectingProgress = XuiFindClass( L"CScene_ConnectingProgress" );
+
+ // If we are navigating back from a full screen progress scene, then that means a connection attempt failed
+ if( XuiIsInstanceOf( hSceneFrom, hClassFullscreenProgress ) || XuiIsInstanceOf( hSceneFrom, hClassConnectingProgress ) )
+ {
+ UpdateGamesList();
+ }
+ }
+ else
+ {
+ m_pGamesList->RemoveAllData();
+ //m_GamesList.DeleteItems(0, m_GamesList.GetItemCount() );
+ m_pGamesList->SetEnable(FALSE);
+ //XuiElementSetDisableFocusRecursion( m_pGamesList->m_hObj, TRUE);
+ m_NetGamesListTimer.SetShow( TRUE );
+ m_LabelNoGames.SetShow( FALSE );
+ m_SavesList.InitFocus(m_iPad);
+ }
+
+ // are we back here because of a delete of a corrupt save?
+
+ if(app.GetCorruptSaveDeleted())
+ {
+ // need to re-get the saves list and update the display
+ // clear the saves list
+ m_pSavesList->RemoveAllData();
+ m_iSaveInfoC=0;
+ GetSaveInfo();
+ app.SetCorruptSaveDeleted(false);
+ }
+
+ int iY = -1;
+ int iRB=-1;
+ if( DoesGamesListHaveFocus() )
+ {
+ iY = IDS_TOOLTIPS_VIEW_GAMERCARD;
+ }
+ else if(DoesSavesListHaveFocus())
+ {
+ if(ProfileManager.IsSignedInLive( m_iPad ))
+ {
+ iY=IDS_TOOLTIPS_UPLOAD_SAVE_FOR_XBOXONE;
+ }
+
+ if(StorageManager.GetSaveDisabled())
+ {
+ iRB=IDS_TOOLTIPS_DELETESAVE;
+ }
+ else
+ {
+ // 4J-PB - we need to check that there is enough space left to create a copy of the save (for a rename)
+
+ if(StorageManager.EnoughSpaceForAMinSaveGame())
+ {
+ iRB=IDS_TOOLTIPS_SAVEOPTIONS;
+ }
+ else
+ {
+ iRB=IDS_TOOLTIPS_DELETESAVE;
+
+ }
+ }
+ }
+ else if(DoesMashUpWorldHaveFocus())
+ {
+ // If it's a mash-up pack world, give the Hide option
+ iRB=IDS_TOOLTIPS_HIDE;
+ }
+
+ int iLB = -1;
+ if(m_bInParty)
+ {
+ if( m_bShowingPartyGamesOnly ) iLB = IDS_TOOLTIPS_ALL_GAMES;
+ else iLB = IDS_TOOLTIPS_PARTY_GAMES;
+ }
+
+ if(ProfileManager.IsFullVersion()==false )
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, -1, -1,-1,-1,iLB);
+ }
+ else if(StorageManager.GetSaveDisabled())
+ {
+ // clear out the saves list, since the disable save may have happened in the load screen because of a device removal
+
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE,iY,-1,-1,iLB,iRB);
+ }
+ else
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, IDS_TOOLTIPS_CHANGEDEVICE, iY,-1,-1,iLB,iRB);
+ }
+
+ return S_OK;
+}
+
+HRESULT CScene_MultiGameJoinLoad::OnNotifySelChanged(HXUIOBJ hObjSource, XUINotifySelChanged *pNotifySelChangedData, BOOL& bHandled)
+{
+
+ if(m_bReady)
+ {
+ CXuiSceneBase::PlayUISFX(eSFX_Focus);
+ }
+
+ return S_OK;
+}
+
+
+HRESULT CScene_MultiGameJoinLoad::OnTransitionStart( XUIMessageTransition *pTransition, BOOL& bHandled )
+{
+ //if(pTransition->dwTransAction==XUI_TRANSITION_ACTION_DESTROY ) return S_OK;
+
+ if(pTransition->dwTransAction==XUI_TRANSITION_ACTION_DESTROY ||
+ pTransition->dwTransType == XUI_TRANSITION_FROM || pTransition->dwTransType == XUI_TRANSITION_BACKFROM)
+ {
+ // 4J Stu - We may have had to unload our font renderer in this scene if one of the save files
+ // uses characters not in our font (eg asian chars) so restore our font renderer
+ // This will not do anything if our font renderer is already loaded
+ app.OverrideFontRenderer(true,true);
+
+ KillTimer(JOIN_LOAD_ONLINE_TIMER_ID);
+ }
+ else if(pTransition->dwTransType == XUI_TRANSITION_TO || pTransition->dwTransType == XUI_TRANSITION_BACKTO)
+ {
+ SetTimer(JOIN_LOAD_ONLINE_TIMER_ID,JOIN_LOAD_ONLINE_TIMER_TIME);
+ // 4J-PB - Need to check for installed DLC, which might have happened while you were on the info scene
+ if(pTransition->dwTransType == XUI_TRANSITION_BACKTO)
+ {
+ // 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
+
+ // 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
+ if(app.StartInstallDLCProcess(m_iPad)==false)
+ {
+ // not doing a mount, so re-enable input
+ m_bIgnoreInput=false;
+ }
+ else
+ {
+ m_bIgnoreInput=true;
+ m_pSavesList->RemoveAllData();
+ m_SavesListTimer.SetShow( TRUE );
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+HRESULT CScene_MultiGameJoinLoad::OnFontRendererChange()
+{
+ // update the tooltips
+ // if the saves list has focus, then we should show the Delete Save tooltip
+ // if the games list has focus, then we should the the View Gamercard tooltip
+ int iRB=-1;
+ int iY = -1;
+ if( DoesGamesListHaveFocus() )
+ {
+ iY = IDS_TOOLTIPS_VIEW_GAMERCARD;
+ }
+ else if(DoesSavesListHaveFocus())
+ {
+ if(ProfileManager.IsSignedInLive( m_iPad ))
+ {
+ iY=IDS_TOOLTIPS_UPLOAD_SAVE_FOR_XBOXONE;
+ }
+ if(StorageManager.GetSaveDisabled())
+ {
+ iRB=IDS_TOOLTIPS_DELETESAVE;
+ }
+ else
+ {
+ if(StorageManager.EnoughSpaceForAMinSaveGame())
+ {
+ iRB=IDS_TOOLTIPS_SAVEOPTIONS;
+ }
+ else
+ {
+ iRB=IDS_TOOLTIPS_DELETESAVE;
+ }
+ }
+ }
+ else if(DoesMashUpWorldHaveFocus())
+ {
+ // If it's a mash-up pack world, give the Hide option
+ iRB=IDS_TOOLTIPS_HIDE;
+ }
+
+ int iLB = -1;
+ if(m_bInParty)
+ {
+ if( m_bShowingPartyGamesOnly ) iLB = IDS_TOOLTIPS_ALL_GAMES;
+ else iLB = IDS_TOOLTIPS_PARTY_GAMES;
+ }
+
+ if(ProfileManager.IsFullVersion()==false )
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, -1, iY,-1,-1,iLB,-1,-1,true);
+ }
+ else if(StorageManager.GetSaveDisabled())
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE,iY,-1,-1,iLB,iRB,-1,true);
+ }
+ else
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, IDS_TOOLTIPS_CHANGEDEVICE, iY,-1,-1,iLB,iRB,-1,true);
+ }
+ return S_OK;
+}
+
+HRESULT CScene_MultiGameJoinLoad::OnNotifySetFocus(HXUIOBJ hObjSource, XUINotifyFocus *pNotifyFocusData, BOOL& bHandled)
+{
+ // update the tooltips
+ // if the saves list has focus, then we should show the Delete Save tooltip
+ // if the games list has focus, then we should the the View Gamercard tooltip
+ int iRB=-1;
+ int iY = -1;
+ if( DoesGamesListHaveFocus() )
+ {
+ iY = IDS_TOOLTIPS_VIEW_GAMERCARD;
+ }
+ else if(DoesSavesListHaveFocus())
+ {
+ if(ProfileManager.IsSignedInLive( m_iPad ))
+ {
+ iY=IDS_TOOLTIPS_UPLOAD_SAVE_FOR_XBOXONE;
+ }
+ if(StorageManager.GetSaveDisabled())
+ {
+ iRB=IDS_TOOLTIPS_DELETESAVE;
+ }
+ else
+ {
+ if(StorageManager.EnoughSpaceForAMinSaveGame())
+ {
+ iRB=IDS_TOOLTIPS_SAVEOPTIONS;
+ }
+ else
+ {
+ iRB=IDS_TOOLTIPS_DELETESAVE;
+ }
+ }
+ }
+ else if(DoesMashUpWorldHaveFocus())
+ {
+ // If it's a mash-up pack world, give the Hide option
+ iRB=IDS_TOOLTIPS_HIDE;
+ }
+
+ int iLB = -1;
+ if(m_bInParty)
+ {
+ if( m_bShowingPartyGamesOnly ) iLB = IDS_TOOLTIPS_ALL_GAMES;
+ else iLB = IDS_TOOLTIPS_PARTY_GAMES;
+ }
+
+ if(ProfileManager.IsFullVersion()==false )
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, -1, iY,-1,-1,iLB,-1);
+ }
+ else if(StorageManager.GetSaveDisabled())
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE,iY,-1,-1,iLB,iRB);
+ }
+ else
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, IDS_TOOLTIPS_CHANGEDEVICE, iY,-1,-1,iLB,iRB);
+ }
+ return S_OK;
+}
+
+HRESULT CScene_MultiGameJoinLoad::OnNotifyKillFocus(HXUIOBJ hObjSource, XUINotifyFocus *pNotifyFocusData, BOOL& bHandled)
+{
+ return S_OK;
+}
+
+bool CScene_MultiGameJoinLoad::DoesSavesListHaveFocus()
+{
+ HXUIOBJ hParentObj,hObj=TreeGetFocus();
+
+ if(hObj!=NULL)
+ {
+ // get the parent and see if it's the saves list
+ XuiElementGetParent(hObj,&hParentObj);
+ if(hParentObj==m_SavesList.m_hObj)
+ {
+ // check it's not the first or second element (new world or tutorial)
+ if(m_SavesList.GetCurSel()>(m_iDefaultButtonsC-1))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool CScene_MultiGameJoinLoad::DoesMashUpWorldHaveFocus()
+{
+ HXUIOBJ hParentObj,hObj=TreeGetFocus();
+
+ if(hObj!=NULL)
+ {
+ // get the parent and see if it's the saves list
+ XuiElementGetParent(hObj,&hParentObj);
+ if(hParentObj==m_SavesList.m_hObj)
+ {
+ // check it's not the first or second element (new world or tutorial)
+ if(m_SavesList.GetCurSel()>(m_iDefaultButtonsC-1))
+ {
+ return false;
+ }
+
+ if(m_SavesList.GetCurSel()>(m_iDefaultButtonsC - 1 - m_iMashUpButtonsC))
+ {
+ return true;
+ }
+ else return false;
+ }
+ else return false;
+ }
+ return false;
+}
+
+bool CScene_MultiGameJoinLoad::DoesGamesListHaveFocus()
+{
+ HXUIOBJ hParentObj,hObj=TreeGetFocus();
+
+ if(hObj!=NULL)
+ {
+ // get the parent and see if it's the saves list
+ XuiElementGetParent(hObj,&hParentObj);
+ if(hParentObj==m_pGamesList->m_hObj)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void CScene_MultiGameJoinLoad::UpdateGamesListCallback(LPVOID lpParam)
+{
+ if(lpParam != NULL)
+ {
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad *) lpParam;
+ // check this there's no save transfer in progress
+ if(!pClass->m_bSaveTransferInProgress)
+ {
+ pClass->UpdateGamesList();
+ }
+ }
+}
+
+void CScene_MultiGameJoinLoad::UpdateGamesList()
+{
+ if( m_bIgnoreInput ) return;
+
+ // if we're retrieving save info, don't show the list yet as we will be ignoring press events
+ if(m_bRetrievingSaveInfo)
+ {
+ return;
+ }
+
+ DWORD nIndex = -1;
+ FriendSessionInfo *pSelectedSession = NULL;
+ if(m_pGamesList->TreeHasFocus() && m_pGamesList->GetItemCount() > 0)
+ {
+ nIndex = m_pGamesList->GetCurSel();
+ pSelectedSession = currentSessions.at( nIndex );
+ }
+
+ SessionID selectedSessionId;
+ if( pSelectedSession != NULL )selectedSessionId = pSelectedSession->sessionId;
+ pSelectedSession = NULL;
+
+ for(AUTO_VAR(it, currentSessions.begin()); it < currentSessions.end(); ++it)
+ {
+ delete (*it);
+ }
+ currentSessions.clear();
+
+ m_NetGamesListTimer.SetShow( FALSE );
+
+ // if the saves list has focus, then we should show the Delete Save tooltip
+ // if the games list has focus, then we should show the View Gamercard tooltip
+ int iRB=-1;
+ int iY = -1;
+
+ if( DoesGamesListHaveFocus() )
+ {
+ iY = IDS_TOOLTIPS_VIEW_GAMERCARD;
+ }
+ else if(DoesSavesListHaveFocus())
+ {
+ if(ProfileManager.IsSignedInLive( m_iPad ))
+ {
+ iY=IDS_TOOLTIPS_UPLOAD_SAVE_FOR_XBOXONE;
+ }
+ if(StorageManager.GetSaveDisabled())
+ {
+ iRB=IDS_TOOLTIPS_DELETESAVE;
+ }
+ else
+ {
+ if(StorageManager.EnoughSpaceForAMinSaveGame())
+ {
+ iRB=IDS_TOOLTIPS_SAVEOPTIONS;
+ }
+ else
+ {
+ iRB=IDS_TOOLTIPS_DELETESAVE;
+ }
+ }
+ }
+ else if(DoesMashUpWorldHaveFocus())
+ {
+ // If it's a mash-up pack world, give the Hide option
+ iRB=IDS_TOOLTIPS_HIDE;
+ }
+
+ int iLB = -1;
+ if(m_bInParty)
+ {
+ if( m_bShowingPartyGamesOnly ) iLB = IDS_TOOLTIPS_ALL_GAMES;
+ else iLB = IDS_TOOLTIPS_PARTY_GAMES;
+ }
+
+ if(ProfileManager.IsFullVersion()==false )
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, -1, iY,-1,-1,iLB,-1);
+ }
+ else if(StorageManager.GetSaveDisabled())
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE,iY,-1,-1,iLB,iRB);
+ }
+ else
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, IDS_TOOLTIPS_CHANGEDEVICE, iY,-1,-1,iLB,iRB);
+ }
+
+ currentSessions = *g_NetworkManager.GetSessionList( m_iPad, m_localPlayers, m_bShowingPartyGamesOnly );
+
+ // Update the xui list displayed
+ unsigned int xuiListSize = m_pGamesList->GetItemCount();
+ unsigned int filteredListSize = (unsigned int)currentSessions.size();
+
+ BOOL gamesListHasFocus = m_pGamesList->TreeHasFocus();
+
+ if(filteredListSize > 0)
+ {
+ if( !m_pGamesList->IsEnabled() )
+ {
+ m_pGamesList->SetEnable(TRUE);
+ //XuiElementSetDisableFocusRecursion( m_pGamesList->m_hObj, FALSE);
+ m_pGamesList->SetCurSel( 0 );
+ }
+ m_LabelNoGames.SetShow( FALSE );
+ m_NetGamesListTimer.SetShow( FALSE );
+ }
+ else
+ {
+ m_pGamesList->SetEnable(FALSE);
+ //XuiElementSetDisableFocusRecursion(m_pGamesList->m_hObj, TRUE);
+ m_NetGamesListTimer.SetShow( FALSE );
+ m_LabelNoGames.SetShow( TRUE );
+
+ if( gamesListHasFocus ) m_pGamesList->InitFocus(m_iPad);
+ }
+
+ // clear out the games list and re-fill
+ m_pGamesList->RemoveAllData();
+
+ if( filteredListSize > 0 )
+ {
+ // Reset the focus to the selected session if it still exists
+ unsigned int sessionIndex = 0;
+ m_pGamesList->SetCurSel(0);
+
+ for( AUTO_VAR(it, currentSessions.begin()); it < currentSessions.end(); ++it)
+ {
+ FriendSessionInfo *sessionInfo = *it;
+ HXUIBRUSH hXuiBrush;
+ CXuiCtrl4JList::LIST_ITEM_INFO ListInfo;
+
+ ZeroMemory(&ListInfo,sizeof(CXuiCtrl4JList::LIST_ITEM_INFO));
+
+ ListInfo.pwszText = sessionInfo->displayLabel;
+ ListInfo.fEnabled = TRUE;
+ ListInfo.iData = sessionIndex;
+ m_pGamesList->AddData(ListInfo);
+ // display an icon too
+
+ // Is this a default game or a texture pack game?
+ if(sessionInfo->data.texturePackParentId!=0)
+ {
+ // Do we have the texture pack
+ Minecraft *pMinecraft = Minecraft::GetInstance();
+ TexturePack *tp = pMinecraft->skins->getTexturePackById(sessionInfo->data.texturePackParentId);
+ HRESULT hr;
+
+ DWORD dwImageBytes=0;
+ PBYTE pbImageData=NULL;
+
+ if(tp==NULL)
+ {
+ DWORD dwBytes=0;
+ PBYTE pbData=NULL;
+ app.GetTPD(sessionInfo->data.texturePackParentId,&pbData,&dwBytes);
+
+ // is it in the tpd data ?
+ app.GetFileFromTPD(eTPDFileType_Icon,pbData,dwBytes,&pbImageData,&dwImageBytes );
+ if(dwImageBytes > 0 && pbImageData)
+ {
+ hr=XuiCreateTextureBrushFromMemory(pbImageData,dwImageBytes,&hXuiBrush);
+ m_pGamesList->UpdateGraphic(sessionIndex,hXuiBrush);
+ }
+ }
+ else
+ {
+ pbImageData = tp->getPackIcon(dwImageBytes);
+ if(dwImageBytes > 0 && pbImageData)
+ {
+ hr=XuiCreateTextureBrushFromMemory(pbImageData,dwImageBytes,&hXuiBrush);
+ m_pGamesList->UpdateGraphic(sessionIndex,hXuiBrush);
+ }
+ }
+ }
+ else
+ {
+ // default texture pack
+ XuiCreateTextureBrushFromMemory(m_DefaultMinecraftIconData,m_DefaultMinecraftIconSize,&hXuiBrush);
+ m_pGamesList->UpdateGraphic(sessionIndex,hXuiBrush);
+ }
+
+
+ if(memcmp( &selectedSessionId, &sessionInfo->sessionId, sizeof(SessionID) ) == 0)
+ {
+ m_pGamesList->SetCurSel(sessionIndex);
+ break;
+ }
+ ++sessionIndex;
+ }
+ }
+}
+
+void CScene_MultiGameJoinLoad::UpdateGamesList(DWORD dwNumResults, IQNetGameSearch *pGameSearch)
+{
+ // 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
+#if 0
+ const XSESSION_SEARCHRESULT *pSearchResult;
+ const XNQOSINFO * pxnqi;
+
+ if(m_searches>0)
+ --m_searches;
+
+ if(m_searches==0)
+ {
+ m_NetGamesListTimer.SetShow( FALSE );
+
+ // if the saves list has focus, then we should show the Delete Save tooltip
+ // if the games list has focus, then we should show the View Gamercard tooltip
+ int iRB=-1;
+ int iY = -1;
+
+ if( DoesGamesListHaveFocus() )
+ {
+ iY = IDS_TOOLTIPS_VIEW_GAMERCARD;
+ }
+ else if(DoesSavesListHaveFocus())
+ {
+ iRB=IDS_TOOLTIPS_DELETESAVE;
+ }
+
+ int iLB = -1;
+ if(m_bInParty)
+ {
+ if( m_bShowingPartyGamesOnly ) iLB = IDS_TOOLTIPS_ALL_GAMES
+ else iLB = IDS_TOOLTIPS_PARTY_GAMES;
+ }
+
+ if(ProfileManager.IsFullVersion()==false )
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, -1, iY,-1,-1,iLB,iRB);
+ }
+ else if(StorageManager.GetSaveDisabled())
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE,iY,-1,-1,iLB,iRB);
+ }
+ else
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, IDS_TOOLTIPS_CHANGEDEVICE, iY,-1,-1,iLB,iRB);
+ }
+ }
+
+ if( dwNumResults == 0 )
+ {
+ if(m_searches==0 && m_GamesList.GetItemCount() == 0)
+ {
+ m_LabelNoGames.SetShow( TRUE );
+ }
+ return;
+ }
+
+ unsigned int startOffset = m_GamesList.GetItemCount();
+ //m_GamesList.InsertItems(startOffset,dwNumResults);
+ //m_GamesList.SetEnable(TRUE);
+ //XuiElementSetDisableFocusRecursion( m_GamesList.m_hObj, FALSE);
+
+ // Loop through all the results.
+ for( DWORD dwResult = 0; dwResult < pGameSearch->GetNumResults(); dwResult++ )
+ {
+
+ pSearchResult = pGameSearch->GetSearchResultAtIndex( dwResult );
+
+ // No room for us, so ignore it
+ if(pSearchResult->dwOpenPublicSlots < m_localPlayers)
+ continue;
+
+ FriendSessionInfo *sessionInfo = NULL;
+ bool foundSession = false;
+ for(AUTO_VAR(it, friendsSessions.begin()); it < friendsSessions.end(); ++it)
+ {
+ sessionInfo = *it;
+ if(memcmp( &pSearchResult->info.sessionID, &sessionInfo->sessionId, sizeof(SessionID) ) == 0)
+ {
+ sessionInfo->searchResult = *pSearchResult;
+ sessionInfo->displayLabel = new wchar_t[100];
+ foundSession = true;
+ break;
+ }
+ }
+
+ // We received a search result for a session no longer in our list of friends sessions
+ if(!foundSession)
+ continue;
+
+ // Print some info about this result.
+ //printf( "Search result %u:\n", dwResult );
+ //printf( " public slots open = %u, filled = %u\n", pSearchResult->dwOpenPublicSlots, pSearchResult->dwFilledPublicSlots );
+ //printf( " private slots open = %u, filled = %u\n", pSearchResult->dwOpenPrivateSlots, pSearchResult->dwFilledPrivateSlots );
+
+ // See if this result was contacted successfully via QoS probes.
+ pxnqi = pGameSearch->GetQosInfoAtIndex( dwResult );
+ if( pxnqi->bFlags & XNET_XNQOSINFO_TARGET_CONTACTED )
+ {
+ // Print the round trip time and the rough estimation of
+ // bandwidth.
+ app.DebugPrintf( " RTT min = %u, med = %u\n", pxnqi->wRttMinInMsecs, pxnqi->wRttMedInMsecs );
+ app.DebugPrintf( " bps up = %u, down = %u\n", pxnqi->dwUpBitsPerSec, pxnqi->dwDnBitsPerSec );
+
+ if(pxnqi->cbData > 0)
+ {
+ sessionInfo->data = *(GameSessionData *)pxnqi->pbData;
+
+ wstring gamerName = convStringToWstring(sessionInfo->data.hostName);
+ swprintf(sessionInfo->displayLabel,L"%ls's Game", gamerName.c_str() );
+ }
+ else
+ {
+ swprintf(sessionInfo->displayLabel,L"Unknown host Game");
+ }
+
+ // If this host wasn't disabled use this one.
+ if( !( pxnqi->bFlags & XNET_XNQOSINFO_TARGET_DISABLED ) && sessionInfo->data.netVersion == MINECRAFT_NET_VERSION )
+ {
+ //printf("This game is valid\n");
+ filteredResults.push_back(sessionInfo);
+ m_GamesList.InsertItems(startOffset,1);
+ m_GamesList.SetText(startOffset,sessionInfo->displayLabel);
+ startOffset++;
+ }
+#ifndef _CONTENT_PACKAGE
+ if( sessionInfo->data.netVersion != MINECRAFT_NET_VERSION )
+ {
+ wprintf(L"%ls version of %d does not match our version of %d\n", sessionInfo->displayLabel, sessionInfo->data.netVersion, MINECRAFT_NET_VERSION);
+ }
+#endif
+ }
+ }
+
+ if( m_GamesList.GetItemCount() == 0)
+ {
+ m_LabelNoGames.SetShow( TRUE );
+ }
+ else
+ {
+ m_GamesList.SetEnable(TRUE);
+ XuiElementSetDisableFocusRecursion( m_GamesList.m_hObj, FALSE);
+ if( DoesGamesListHaveFocus() )
+ {
+ m_GamesList.SetCurSel(0);
+ }
+ }
+#endif
+}
+
+/*void CScene_MultiGameJoinLoad::UpdateGamesListLabels()
+{
+ for( unsigned int i = 0; i < currentSessions.size(); ++i )
+ {
+ FriendSessionInfo *sessionInfo = currentSessions.at(i);
+ m_GamesList.SetText(i,sessionInfo->displayLabel);
+ HXUIBRUSH hBrush;
+ CXuiCtrl4JList::LIST_ITEM_INFO info = m_pGamesList->GetData(i);
+
+ // display an icon too
+ XuiCreateTextureBrushFromMemory(m_DefaultMinecraftIconData,m_DefaultMinecraftIconSize,&hBrush);
+ m_pGamesList->UpdateGraphic(i,hBrush);
+ }
+#if 0
+ XUIRect xuiRect;
+ HXUIOBJ item = XuiListGetItemControl(m_GamesList,0);
+
+ HXUIOBJ hObj=NULL;
+ HXUIOBJ hTextPres=NULL;
+ HRESULT hr=XuiControlGetVisual(item,&hObj);
+ hr=XuiElementGetChildById(hObj,L"text_Label",&hTextPres);
+
+ unsigned char displayLabelViewableStartIndex = 0;
+ for( unsigned int i = 0; i < currentSessions.size(); ++i )
+ {
+ FriendSessionInfo *sessionInfo = currentSessions.at(i);
+
+ if(hTextPres != NULL )
+ {
+ hr=XuiTextPresenterMeasureText(hTextPres, sessionInfo->displayLabel, &xuiRect);
+
+ float fWidth, fHeight;
+ XuiElementGetBounds(hTextPres,&fWidth,&fHeight);
+ int characters = (fWidth/xuiRect.right) * sessionInfo->displayLabelLength;
+
+ if( characters < sessionInfo->displayLabelLength )
+ {
+ static wchar_t temp[100];
+ ZeroMemory(temp, (100)*sizeof(wchar_t));
+ wcsncpy_s( temp, sessionInfo->displayLabel+sessionInfo->displayLabelViewableStartIndex, characters );
+ m_GamesList.SetText(i,temp);
+ sessionInfo->displayLabelViewableStartIndex++;
+ if( sessionInfo->displayLabelViewableStartIndex >= sessionInfo->displayLabelLength ) sessionInfo->displayLabelViewableStartIndex = 0;
+ }
+ }
+ }
+#endif
+}*/
+
+void CScene_MultiGameJoinLoad::SearchForGameCallback(void *param, DWORD dwNumResults, IQNetGameSearch *pGameSearch)
+{
+#if 0
+ HXUIOBJ hObj = (HXUIOBJ)param;
+
+ void *pObj;
+ XuiObjectFromHandle( hObj, &pObj);
+ CScene_MultiGameJoinLoad *MultiGameJoinLoad = (CScene_MultiGameJoinLoad *)pObj;
+
+ MultiGameJoinLoad->UpdateGamesList(dwNumResults, pGameSearch);
+#endif
+}
+
+int CScene_MultiGameJoinLoad::DeviceSelectReturned(void *pParam,bool bContinue)
+{
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
+ //HRESULT hr;
+
+ if(bContinue==true)
+ {
+ // if the saves list has focus, then we should show the Delete Save tooltip
+ // if the games list has focus, then we should show the View Gamercard tooltip
+ int iRB=-1;
+ int iY = -1;
+ if( pClass->DoesGamesListHaveFocus() )
+ {
+ iY = IDS_TOOLTIPS_VIEW_GAMERCARD;
+ }
+ else if(pClass->DoesSavesListHaveFocus())
+ {
+ if(ProfileManager.IsSignedInLive( pClass->m_iPad ))
+ {
+ iY=IDS_TOOLTIPS_UPLOAD_SAVE_FOR_XBOXONE;
+ }
+ if(StorageManager.GetSaveDisabled())
+ {
+ iRB=IDS_TOOLTIPS_DELETESAVE;
+ }
+ else
+ {
+ if(StorageManager.EnoughSpaceForAMinSaveGame())
+ {
+ iRB=IDS_TOOLTIPS_SAVEOPTIONS;
+ }
+ else
+ {
+ iRB=IDS_TOOLTIPS_DELETESAVE;
+ }
+ }
+ }
+ else if(pClass->DoesMashUpWorldHaveFocus())
+ {
+ // If it's a mash-up pack world, give the Hide option
+ iRB=IDS_TOOLTIPS_HIDE;
+ }
+
+ int iLB = -1;
+ if(pClass->m_bInParty)
+ {
+ if( pClass->m_bShowingPartyGamesOnly ) iLB = IDS_TOOLTIPS_ALL_GAMES;
+ else iLB = IDS_TOOLTIPS_PARTY_GAMES;
+ }
+
+ //BOOL bOnlineGame=pClass->m_CheckboxOnline.IsChecked();
+
+ // refresh the saves list (if there is a device selected)
+
+ // clear out the list first
+
+ if(StorageManager.GetSaveDisabled())
+ {
+ if(StorageManager.GetSaveDeviceSelected(pClass->m_iPad))
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_CHANGEDEVICE,iY,-1,-1,iLB,iRB);
+ // saving is disabled, but we should still be able to load from a selected save device
+ pClass->GetSaveInfo();
+ }
+ else
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE,iY,-1,-1,iLB,iRB);
+ // clear the saves list
+ pClass->m_pSavesList->RemoveAllData();
+
+ pClass->m_iSaveInfoC=0;
+ //pClass->m_iThumbnailsLoadedC=0;
+
+ pClass->AddDefaultButtons();
+
+ pClass->m_SavesListTimer.SetShow( FALSE );
+
+ pClass->m_pSavesList->SetCurSelVisible(0);
+ }
+ }
+ else
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_CHANGEDEVICE,iY,-1,-1,iLB,iRB);
+ pClass->GetSaveInfo();
+ }
+ }
+
+ // enable input again
+ pClass->m_bIgnoreInput=false;
+
+ return 0;
+}
+
+HRESULT CScene_MultiGameJoinLoad::OnTimer( XUIMessageTimer *pTimer, BOOL& bHandled )
+{
+ // 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
+ switch(pTimer->nId)
+ {
+
+
+ case JOIN_LOAD_ONLINE_TIMER_ID:
+ {
+ XPARTY_USER_LIST partyList;
+
+ if((XPartyGetUserList( &partyList ) != XPARTY_E_NOT_IN_PARTY ) && (partyList.dwUserCount>1))
+ {
+ m_bInParty=true;
+ }
+ else
+ {
+ m_bInParty=false;
+ }
+
+ bool bMultiplayerAllowed = ProfileManager.IsSignedInLive( m_iPad ) && ProfileManager.AllowedToPlayMultiplayer(m_iPad);
+ if(bMultiplayerAllowed != m_bMultiplayerAllowed)
+ {
+ if( bMultiplayerAllowed )
+ {
+// m_CheckboxOnline.SetEnable(TRUE);
+// m_CheckboxPrivate.SetEnable(TRUE);
+ }
+ else
+ {
+ m_bInParty = false;
+ m_pGamesList->RemoveAllData();
+ //m_GamesList.DeleteItems(0, m_GamesList.GetItemCount() );
+ m_pGamesList->SetEnable(FALSE);
+ //XuiElementSetDisableFocusRecursion( m_pGamesList->m_hObj, TRUE);
+ m_NetGamesListTimer.SetShow( TRUE );
+ m_LabelNoGames.SetShow( FALSE );
+ }
+
+ int iLB = -1;
+ if(m_bInParty)
+ {
+ if( m_bShowingPartyGamesOnly ) iLB = IDS_TOOLTIPS_ALL_GAMES;
+ else iLB = IDS_TOOLTIPS_PARTY_GAMES;
+ }
+ int iRB=-1;
+ int iY=-1;
+
+ if( DoesGamesListHaveFocus() )
+ {
+ }
+ else if(DoesSavesListHaveFocus())
+ {
+ if(ProfileManager.IsSignedInLive( m_iPad ))
+ {
+ iY=IDS_TOOLTIPS_UPLOAD_SAVE_FOR_XBOXONE;
+ }
+
+ if(StorageManager.GetSaveDisabled())
+ {
+ iRB=IDS_TOOLTIPS_DELETESAVE;
+ }
+ else
+ {
+ if(StorageManager.EnoughSpaceForAMinSaveGame())
+ {
+ iRB=IDS_TOOLTIPS_SAVEOPTIONS;
+ }
+ else
+ {
+ iRB=IDS_TOOLTIPS_DELETESAVE;
+ }
+ }
+ }
+ else if(DoesMashUpWorldHaveFocus())
+ {
+ // If it's a mash-up pack world, give the Hide option
+ iRB=IDS_TOOLTIPS_HIDE;
+ }
+
+ if(ProfileManager.IsFullVersion()==false )
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, -1, -1,-1,-1,iLB);
+ }
+ else if(StorageManager.GetSaveDisabled())
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE,-1,-1,-1,iLB,iRB);
+ }
+ else
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, IDS_TOOLTIPS_CHANGEDEVICE,iY,-1,-1,iLB,iRB);
+ }
+ m_bMultiplayerAllowed = bMultiplayerAllowed;
+ }
+ }
+ break;
+ case JOIN_LOAD_SEARCH_MINIMUM_TIMER_ID:
+ {
+ XuiKillTimer( m_hObj, JOIN_LOAD_SEARCH_MINIMUM_TIMER_ID );
+ m_NetGamesListTimer.SetShow( FALSE );
+ m_LabelNoGames.SetShow( TRUE );
+ }
+ break;
+ case JOIN_LOAD_SCROLL_GAME_NAMES_TIMER_ID:
+ {
+ // This is called by the gameslist callback function, so isn't needed on a timer
+ //UpdateGamesListLabels();
+ }
+ break;
+ case CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID:
+ {
+ // also check for any new texture packs info being available
+ // for each item in the mem list, check it's in the data list
+
+ //CXuiCtrl4JList::LIST_ITEM_INFO ListInfo;
+ // for each iConfig, check if the data is available, and add it to the List, then remove it from the viConfig
+
+ for(int i=0;i<m_iTexturePacksNotInstalled;i++)
+ {
+ if(m_iConfigA[i]!=-1)
+ {
+ DWORD dwBytes=0;
+ PBYTE pbData=NULL;
+ //app.DebugPrintf("Retrieving iConfig %d from TPD\n",m_iConfigA[i]);
+
+ app.GetTPD(m_iConfigA[i],&pbData,&dwBytes);
+
+ if(dwBytes > 0 && pbData)
+ {
+ //update the games list
+ UpdateGamesList();
+
+ m_iConfigA[i]=-1;
+ }
+ }
+ }
+ bool bAllDone=true;
+ for(int i=0;i<m_iTexturePacksNotInstalled;i++)
+ {
+ if(m_iConfigA[i]!=-1)
+ {
+ bAllDone = false;
+ }
+ }
+
+ if(bAllDone)
+ {
+ // kill this timer
+ XuiKillTimer(m_hObj,CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID);
+ }
+ }
+ break;
+ }
+
+ return S_OK;
+}
+
+/*
+int CScene_MultiGameJoinLoad::LoadSaveDataReturned(void *pParam,bool bContinue)
+{
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
+
+ if(bContinue==true)
+ {
+ bool isClientSide = ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad());
+
+ // 4J Stu - If we only have one controller connected, then don't show the sign-in UI again
+ DWORD connectedControllers = 0;
+ for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
+ {
+ if( InputManager.IsPadConnected(i) || ProfileManager.IsSignedIn(i) ) ++connectedControllers;
+ }
+
+ if(!isClientSide || connectedControllers == 1 || !RenderManager.IsHiDef())
+ {
+ DWORD dwLocalUsersMask = CGameNetworkManager::GetLocalPlayerMask(ProfileManager.GetPrimaryPad());
+
+ // No guest problems so we don't need to force a sign-in of players here
+ StartGameFromSave(pClass, dwLocalUsersMask);
+ }
+ else
+ {
+ ProfileManager.RequestSignInUI(false, false, false, true, false,&CScene_MultiGameJoinLoad::StartGame_SignInReturned, pParam,ProfileManager.GetPrimaryPad());
+ }
+ }
+ else
+ {
+ pClass->m_bIgnoreInput=false;
+ }
+ return 0;
+}
+*/
+
+int CScene_MultiGameJoinLoad::StartGame_SignInReturned(void *pParam,bool bContinue, int iPad)
+{
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
+
+ if(bContinue==true)
+ {
+ // It's possible that the player has not signed in - they can back out
+ if(ProfileManager.IsSignedIn(iPad))
+ {
+ DWORD dwLocalUsersMask = 0;
+
+ for(unsigned int index = 0; index < XUSER_MAX_COUNT; ++index)
+ {
+ if(ProfileManager.IsSignedIn(index) )
+ {
+ dwLocalUsersMask |= CGameNetworkManager::GetLocalPlayerMask(index);
+ }
+ }
+ StartGameFromSave(pClass, dwLocalUsersMask);
+ }
+ }
+ else
+ {
+ pClass->m_bIgnoreInput=false;
+ }
+ return 0;
+}
+
+// 4J Stu - Shared functionality that is the same whether we needed a quadrant sign-in or not
+void CScene_MultiGameJoinLoad::StartGameFromSave(CScene_MultiGameJoinLoad* pClass, DWORD dwLocalUsersMask)
+{
+ /*bool isClientSide = ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()) && pClass->m_CheckboxOnline.IsChecked() == TRUE;
+ //bool isPrivate = pClass->m_CheckboxPrivate.IsChecked() == TRUE;
+
+ SenStatGameEvent(ProfileManager.GetPrimaryPad(),eTelemetryGameEvent_Load,Minecraft::GetInstance()->options->difficulty, isClientSide, ProfileManager.IsFullVersion(), 1,0 );
+
+ g_NetworkManager.HostGame(dwLocalUsersMask,isClientSide,isPrivate,MINECRAFT_NET_MAX_PLAYERS,0);
+
+ LoadingInputParams *loadingParams = new LoadingInputParams();
+ loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc;
+ loadingParams->lpParam = NULL;
+
+ UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
+ completionData->bShowBackground=TRUE;
+ completionData->bShowLogo=TRUE;
+ completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes;
+ completionData->iPad = DEFAULT_XUI_MENU_USER;
+ loadingParams->completionData = completionData;
+
+ app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);*/
+}
+
+int CScene_MultiGameJoinLoad::DeleteSaveDataReturned(void *pParam,bool bSuccess)
+{
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
+
+ if(bSuccess==true)
+ {
+ // need to re-get the saves list and update the display
+ // clear the saves list
+ pClass->m_pSavesList->RemoveAllData();
+ pClass->m_iSaveInfoC=0;
+ pClass->GetSaveInfo();
+ }
+
+ pClass->m_bIgnoreInput=false;
+
+ return 0;
+}
+
+void CScene_MultiGameJoinLoad::LoadLevelGen(LevelGenerationOptions *levelGen)
+{
+ // Load data from disc
+ //File saveFile( L"Tutorial\\Tutorial" );
+ //LoadSaveFromDisk(&saveFile);
+
+ // clear out the app's terrain features list
+ app.ClearTerrainFeaturePosition();
+
+ StorageManager.ResetSaveData();
+ // Make our next save default to the name of the level
+ StorageManager.SetSaveTitle(levelGen->getDefaultSaveName().c_str());
+
+ bool isClientSide = false;
+ bool isPrivate = false;
+ int maxPlayers = MINECRAFT_NET_MAX_PLAYERS;
+
+ if( app.GetTutorialMode() )
+ {
+ isClientSide = false;
+ maxPlayers = 4;
+ }
+
+ g_NetworkManager.HostGame(0,isClientSide,isPrivate,maxPlayers,0);
+
+ NetworkGameInitData *param = new NetworkGameInitData();
+ param->seed = 0;
+ param->saveData = NULL;
+ param->settings = app.GetGameHostOption( eGameHostOption_Tutorial );
+ param->levelGen = levelGen;
+
+ if(levelGen->requiresTexturePack())
+ {
+ param->texturePackId = levelGen->getRequiredTexturePackId();
+
+ Minecraft *pMinecraft = Minecraft::GetInstance();
+ pMinecraft->skins->selectTexturePackById(param->texturePackId);
+ //pMinecraft->skins->updateUI();
+ }
+
+ LoadingInputParams *loadingParams = new LoadingInputParams();
+ loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc;
+ loadingParams->lpParam = (LPVOID)param;
+
+ UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
+ completionData->bShowBackground=TRUE;
+ completionData->bShowLogo=TRUE;
+ completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes;
+ completionData->iPad = DEFAULT_XUI_MENU_USER;
+ loadingParams->completionData = completionData;
+
+ app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);
+}
+
+void CScene_MultiGameJoinLoad::LoadSaveFromDisk(File *saveFile)
+{
+ // we'll only be coming in here when the tutorial is loaded now
+
+ StorageManager.ResetSaveData();
+
+ // Make our next save default to the name of the level
+ StorageManager.SetSaveTitle(saveFile->getName().c_str());
+
+ __int64 fileSize = saveFile->length();
+ FileInputStream fis(*saveFile);
+ byteArray ba(fileSize);
+ fis.read(ba);
+ fis.close();
+
+ bool isClientSide = false;
+ bool isPrivate = false;
+ int maxPlayers = MINECRAFT_NET_MAX_PLAYERS;
+
+ if( app.GetTutorialMode() )
+ {
+ isClientSide = false;
+ maxPlayers = 4;
+ }
+
+ app.SetGameHostOption(eGameHostOption_GameType,GameType::CREATIVE->getId());
+
+ g_NetworkManager.HostGame(0,isClientSide,isPrivate,maxPlayers,0);
+
+ LoadSaveDataThreadParam *saveData = new LoadSaveDataThreadParam(ba.data, ba.length, saveFile->getName());
+
+ NetworkGameInitData *param = new NetworkGameInitData();
+ param->seed = 0;
+ param->saveData = saveData;
+ param->settings = app.GetGameHostOption( eGameHostOption_All );
+
+ LoadingInputParams *loadingParams = new LoadingInputParams();
+ loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc;
+ loadingParams->lpParam = (LPVOID)param;
+
+ UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
+ completionData->bShowBackground=TRUE;
+ completionData->bShowLogo=TRUE;
+ completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes;
+ completionData->iPad = DEFAULT_XUI_MENU_USER;
+ loadingParams->completionData = completionData;
+
+ app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);
+}
+
+int CScene_MultiGameJoinLoad::DeleteSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
+{
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
+ // results switched for this dialog
+ if(result==C4JStorage::EMessage_ResultDecline)
+ {
+ if(app.DebugSettingsOn() && app.GetLoadSavesFromFolderEnabled())
+ {
+ pClass->m_bIgnoreInput=false;
+ }
+ else
+ {
+ XCONTENT_DATA XContentData;
+ StorageManager.GetSaveCacheFileInfo(pClass->m_iChangingSaveGameInfoIndex-pClass->m_iDefaultButtonsC,XContentData);
+ StorageManager.DeleteSaveData(&XContentData,CScene_MultiGameJoinLoad::DeleteSaveDataReturned,pClass);
+ pClass->m_SavesListTimer.SetShow( TRUE );
+ }
+ }
+ else
+ {
+ pClass->m_bIgnoreInput=false;
+ }
+ return 0;
+}
+
+int CScene_MultiGameJoinLoad::SaveTransferDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
+{
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
+ // results switched for this dialog
+ if(result==C4JStorage::EMessage_ResultAccept)
+ {
+ // upload the save
+
+ // first load the save
+ int iIndex=pClass->m_pSavesList->GetData(pClass->m_pSavesList->GetCurSel()).iIndex-pClass->m_iDefaultButtonsC;
+ XCONTENT_DATA ContentData;
+
+ // 4J-PB - ensure we've switched to the right title group id for uploading to
+ app.TMSPP_SetTitleGroupID(SAVETRANSFER_GROUP_ID);
+ StorageManager.GetSaveCacheFileInfo(iIndex,ContentData);
+ C4JStorage::ELoadGameStatus eLoadStatus=StorageManager.LoadSaveData(&ContentData,CScene_MultiGameJoinLoad::LoadSaveDataReturned,pClass);
+
+ pClass->m_bIgnoreInput=false;
+ }
+ else
+ {
+ pClass->m_bIgnoreInput=false;
+ }
+ return 0;
+}
+
+int CScene_MultiGameJoinLoad::UploadSaveForXboxOneThreadProc( LPVOID lpParameter )
+{
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad *) lpParameter;
+ Minecraft *pMinecraft = Minecraft::GetInstance();
+
+ pMinecraft->progressRenderer->progressStart(IDS_SAVE_TRANSFER_TITLE);
+ pMinecraft->progressRenderer->progressStage( IDS_SAVE_TRANSFER_UPLOADING );
+
+ // Delete the marker file
+ DeleteFile(pClass, "completemarker");
+ if(!WaitForTransferComplete(pClass)) return 0;
+
+ // Upload the save data
+ {
+ unsigned int uiSaveBytes;
+ uiSaveBytes=StorageManager.GetSaveSize();
+ pClass->m_pbSaveTransferData=new BYTE [uiSaveBytes];
+
+ StorageManager.GetSaveData(pClass->m_pbSaveTransferData,&uiSaveBytes);
+
+ app.DebugPrintf("Uploading save data (%d bytes)\n", uiSaveBytes);
+ UploadFile(pClass, "savedata", pClass->m_pbSaveTransferData, uiSaveBytes);
+ }
+
+ if(!WaitForTransferComplete(pClass)) return 0;
+ if(pClass->m_bTransferFail)
+ {
+ // something went wrong, user has been informed
+ pMinecraft->progressRenderer->progressStage( IDS_SAVE_TRANSFER_UPLOADFAILED );
+ return 0;
+ }
+
+ // Upload the metadata and thumbnail
+ {
+ ByteArrayOutputStream baos;
+ DataOutputStream dos(&baos);
+
+ LPCWSTR title = StorageManager.GetSaveTitle();
+ dos.writeUTF(title);
+
+ char szUniqueMapName[14];
+ StorageManager.GetSaveUniqueFilename(szUniqueMapName);
+ dos.writeUTF(convStringToWstring(szUniqueMapName));
+
+ {
+ // set the save icon
+ PBYTE pbImageData=NULL;
+ DWORD dwImageBytes=0;
+ XCONTENT_DATA XContentData;
+ int iIndex=pClass->m_pSavesList->GetData(pClass->m_pSavesList->GetCurSel()).iIndex-pClass->m_iDefaultButtonsC;
+ StorageManager.GetSaveCacheFileInfo(iIndex,XContentData);
+ StorageManager.GetSaveCacheFileInfo(iIndex,&pbImageData,&dwImageBytes);
+
+ // if there is no thumbnail, retrieve the default one from the file.
+ // Don't delete the image data after creating the xuibrush, since we'll use it in the rename of the save
+ if(pbImageData==NULL)
+ {
+ DWORD dwResult=XContentGetThumbnail(ProfileManager.GetPrimaryPad(),&XContentData,NULL,&dwImageBytes,NULL);
+ if(dwResult==ERROR_SUCCESS)
+ {
+ pClass->m_pbSaveTransferData = new BYTE[dwImageBytes];
+ 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
+ XContentGetThumbnail(ProfileManager.GetPrimaryPad(),&XContentData,pbImageData,&dwImageBytes,NULL);
+ }
+ }
+
+ dos.writeInt(dwImageBytes);
+
+ byteArray ba(pbImageData, dwImageBytes);
+ dos.write(ba);
+ }
+
+ pClass->m_pbSaveTransferData=new BYTE [baos.size()];
+ memcpy(pClass->m_pbSaveTransferData,baos.buf.data,baos.size());
+
+ app.DebugPrintf("Uploading meta data (%d bytes)\n", baos.size());
+ UploadFile(pClass, "metadata", pClass->m_pbSaveTransferData, baos.size());
+ }
+
+ // Wait for metadata and thumbnail
+ if(!WaitForTransferComplete(pClass)) return 0;
+ if(pClass->m_bTransferFail)
+ {
+ // something went wrong, user has been informed
+ pMinecraft->progressRenderer->progressStage( IDS_SAVE_TRANSFER_UPLOADFAILED );
+ return 0;
+ }
+
+ // Upload the marker file
+ {
+ char singleByteData[1] = {1};
+ app.DebugPrintf("Uploading marker (%d bytes)\n", 1);
+ UploadFile(pClass, "completemarker", &singleByteData, 1);
+ }
+
+ // Wait for marker
+ if(!WaitForTransferComplete(pClass)) return 0;
+ if(pClass->m_bTransferFail)
+ {
+ // something went wrong, user has been informed
+ pMinecraft->progressRenderer->progressStage( IDS_SAVE_TRANSFER_UPLOADFAILED );
+
+ return 0;
+ }
+ // change text for completion confirmation
+ pMinecraft->progressRenderer->progressStage( IDS_SAVE_TRANSFER_UPLOADCOMPLETE );
+
+ // done
+ return 0;
+}
+
+void CScene_MultiGameJoinLoad::DeleteFile(CScene_MultiGameJoinLoad *pClass, char *filename)
+{
+ pClass->m_fProgress=0.0f;
+ pClass->m_bTransferComplete=false;
+
+ C4JStorage::ETMSStatus result = StorageManager.TMSPP_DeleteFile(
+ ProfileManager.GetPrimaryPad(),
+ filename,
+ C4JStorage::TMS_FILETYPE_BINARY,
+ &CScene_MultiGameJoinLoad::DeleteComplete,
+ pClass,
+ NULL);
+
+ if(result != C4JStorage::ETMSStatus_DeleteInProgress)
+ {
+ DeleteComplete(pClass,ProfileManager.GetPrimaryPad(), -1);
+ }
+}
+
+void CScene_MultiGameJoinLoad::UploadFile(CScene_MultiGameJoinLoad *pClass, char *filename, LPVOID data, DWORD size)
+{
+ pClass->m_fProgress=0.0f;
+ pClass->m_bTransferComplete=false;
+
+ C4JStorage::ETMSStatus result = StorageManager.TMSPP_WriteFileWithProgress(
+ ProfileManager.GetPrimaryPad(),
+ C4JStorage::eGlobalStorage_TitleUser,
+ C4JStorage::TMS_FILETYPE_BINARY,
+ C4JStorage::TMS_UGCTYPE_NONE,
+ filename,
+ (CHAR *)data,
+ size,
+ &CScene_MultiGameJoinLoad::TransferComplete,pClass, 0,
+ &CScene_MultiGameJoinLoad::Progress,pClass);
+
+#ifdef _DEBUG_MENUS_ENABLED
+ if(app.GetWriteSavesToFolderEnabled())
+ {
+ File targetFileDir(L"GAME:\\FakeTMSPP");
+ if(!targetFileDir.exists()) targetFileDir.mkdir();
+ string path = string( wstringtofilename( targetFileDir.getPath() ) ).append("\\").append(filename);
+ HANDLE hSaveFile = CreateFile( path.c_str(), GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, NULL);
+
+ DWORD numberOfBytesWritten = 0;
+ WriteFile( hSaveFile,data,size,&numberOfBytesWritten,NULL);
+ assert(numberOfBytesWritten == size);
+
+ CloseHandle(hSaveFile);
+ }
+#endif
+
+ if(result != C4JStorage::ETMSStatus_WriteInProgress)
+ {
+ TransferComplete(pClass,ProfileManager.GetPrimaryPad(), -1);
+ }
+}
+
+bool CScene_MultiGameJoinLoad::WaitForTransferComplete( CScene_MultiGameJoinLoad *pClass )
+{
+ Minecraft *pMinecraft = Minecraft::GetInstance();
+ // loop until complete
+ while(pClass->m_bTransferComplete==false)
+ {
+ // check for a cancel
+ if(pClass->m_bSaveTransferInProgress==false)
+ {
+ // cancelled
+ return false;
+ }
+ Sleep(50);
+ // update the progress
+ pMinecraft->progressRenderer->progressStagePercentage((unsigned int)(pClass->m_fProgress*100.0f));
+ }
+
+ // was there a transfer error?
+
+ return true;
+}
+
+int CScene_MultiGameJoinLoad::SaveOptionsDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
+{
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
+
+ // results switched for this dialog
+ // EMessage_ResultAccept means cancel
+ if(result==C4JStorage::EMessage_ResultDecline || result==C4JStorage::EMessage_ResultThirdOption)
+ {
+ if(result==C4JStorage::EMessage_ResultDecline) // rename
+ {
+ ZeroMemory(pClass->m_wchNewName,sizeof(WCHAR)*XCONTENT_MAX_DISPLAYNAME_LENGTH);
+ // bring up a keyboard
+ 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());
+ }
+ else // delete
+ {
+ // delete the save game
+ // Have to ask the player if they are sure they want to delete this game
+ UINT uiIDA[2];
+ uiIDA[0]=IDS_CONFIRM_CANCEL;
+ uiIDA[1]=IDS_CONFIRM_OK;
+ StorageManager.RequestMessageBox(IDS_TOOLTIPS_DELETESAVE, IDS_TEXT_DELETE_SAVE, uiIDA, 2, iPad,&CScene_MultiGameJoinLoad::DeleteSaveDialogReturned,pClass, app.GetStringTable());
+ //pClass->m_bIgnoreInput=false;
+ }
+ }
+ else
+ {
+ pClass->m_bIgnoreInput=false;
+ }
+ return 0;
+}
+
+int CScene_MultiGameJoinLoad::LoadSaveDataReturned(void *pParam,bool bContinue)
+{
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
+
+ if(bContinue==true)
+ {
+ pClass->m_bSaveTransferInProgress=true;
+ LoadingInputParams *loadingParams = new LoadingInputParams();
+ loadingParams->func = &CScene_MultiGameJoinLoad::UploadSaveForXboxOneThreadProc;
+ loadingParams->lpParam = (LPVOID)pParam;
+
+ UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
+ completionData->bShowBackground=TRUE;
+ completionData->bShowLogo=TRUE;
+ completionData->type = e_ProgressCompletion_NavigateBack;
+ completionData->iPad = DEFAULT_XUI_MENU_USER;
+ completionData->bRequiresUserAction=TRUE;
+ loadingParams->completionData = completionData;
+
+ loadingParams->cancelFunc=&CScene_MultiGameJoinLoad::CancelSaveUploadCallback;
+ loadingParams->completeFunc=&CScene_MultiGameJoinLoad::SaveUploadCompleteCallback;
+ loadingParams->m_cancelFuncParam=pClass;
+ loadingParams->m_completeFuncParam=pClass;
+ loadingParams->cancelText=IDS_TOOLTIPS_CANCEL;
+
+ app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);
+ }
+ else
+ {
+ // switch back to the normal title group id
+ app.TMSPP_SetTitleGroupID(GROUP_ID);
+
+ // the save is corrupt!
+
+ pClass->SetShow( TRUE );
+ pClass->m_bIgnoreInput=false;
+
+ // give the option to delete the save
+ UINT uiIDA[2];
+ uiIDA[0]=IDS_CONFIRM_CANCEL;
+ uiIDA[1]=IDS_CONFIRM_OK;
+ StorageManager.RequestMessageBox(IDS_CORRUPT_OR_DAMAGED_SAVE_TITLE, IDS_CORRUPT_OR_DAMAGED_SAVE_TEXT, uiIDA, 2,
+ pClass->m_iPad,&CScene_MultiGameJoinLoad::DeleteSaveDialogReturned,pClass, app.GetStringTable());
+
+ }
+
+ return 0;
+}
+
+int CScene_MultiGameJoinLoad::Progress(void *pParam,float fProgress)
+{
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
+
+ app.DebugPrintf("Progress - %f\n",fProgress);
+ pClass->m_fProgress=fProgress;
+ return 0;
+}
+
+int CScene_MultiGameJoinLoad::TransferComplete(void *pParam,int iPad, int iResult)
+{
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
+
+ delete [] pClass->m_pbSaveTransferData;
+ pClass->m_pbSaveTransferData = NULL;
+ if(iResult!=0)
+ {
+ // There was a transfer fail
+ // Display a dialog
+ UINT uiIDA[1];
+ uiIDA[0]=IDS_CONFIRM_OK;
+ StorageManager.RequestMessageBox(IDS_SAVE_TRANSFER_TITLE, IDS_SAVE_TRANSFER_UPLOADFAILED, uiIDA, 1, ProfileManager.GetPrimaryPad(),NULL,NULL,app.GetStringTable());
+ pClass->m_bTransferFail=true;
+ }
+ else
+ {
+ pClass->m_bTransferFail=false;
+ }
+ pClass->m_bTransferComplete=true;
+ //pClass->m_bSaveTransferInProgress=false;
+ return 0;
+}
+
+int CScene_MultiGameJoinLoad::DeleteComplete(void *pParam,int iPad, int iResult)
+{
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
+ pClass->m_bTransferComplete=true;
+ return 0;
+}
+
+int CScene_MultiGameJoinLoad::KeyboardReturned(void *pParam,bool bSet)
+{
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
+ HRESULT hr = S_OK;
+
+ // if the user has left the name empty, treat this as backing out
+ if((pClass->m_wchNewName[0]!=0) && bSet)
+ {
+#ifdef _XBOX
+ XCONTENT_DATA XContentData;
+ StorageManager.GetSaveCacheFileInfo(pClass->m_iChangingSaveGameInfoIndex-pClass->m_iDefaultButtonsC,XContentData);
+
+ C4JStorage::ELoadGameStatus eLoadStatus=StorageManager.LoadSaveData(&XContentData,CScene_MultiGameJoinLoad::LoadSaveDataForRenameReturned,pClass);
+
+ if(eLoadStatus==C4JStorage::ELoadGame_DeviceRemoved)
+ {
+ // disable saving
+ StorageManager.SetSaveDisabled(true);
+ StorageManager.SetSaveDeviceSelected(ProfileManager.GetPrimaryPad(),false);
+ UINT uiIDA[1];
+ uiIDA[0]=IDS_OK;
+ StorageManager.RequestMessageBox(IDS_STORAGEDEVICEPROBLEM_TITLE, IDS_FAILED_TO_LOADSAVE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(),&CScene_MultiGameJoinLoad::DeviceRemovedDialogReturned,pClass);
+ }
+#else
+ // rename the save
+
+#endif
+ }
+ else
+ {
+ pClass->m_bIgnoreInput=false;
+ }
+
+ return hr;
+}
+
+int CScene_MultiGameJoinLoad::LoadSaveDataForRenameReturned(void *pParam,bool bContinue)
+{
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
+#ifdef _XBOX
+ if(bContinue==true)
+ {
+ // set the save icon
+ PBYTE pbImageData=NULL;
+ DWORD dwImageBytes=0;
+ HXUIBRUSH hXuiBrush;
+ XCONTENT_DATA XContentData;
+ StorageManager.GetSaveCacheFileInfo(pClass->m_iChangingSaveGameInfoIndex-pClass->m_iDefaultButtonsC,XContentData);
+ StorageManager.GetSaveCacheFileInfo(pClass->m_iChangingSaveGameInfoIndex-pClass->m_iDefaultButtonsC,&pbImageData,&dwImageBytes);
+
+ // if there is no thumbnail, retrieve the default one from the file.
+ // Don't delete the image data after creating the xuibrush, since we'll use it in the rename of the save
+ if(pbImageData==NULL)
+ {
+ DWORD dwResult=XContentGetThumbnail(ProfileManager.GetPrimaryPad(),&XContentData,NULL,&dwImageBytes,NULL);
+ if(dwResult==ERROR_SUCCESS)
+ {
+ pbImageData = new BYTE[dwImageBytes];
+ XContentGetThumbnail(ProfileManager.GetPrimaryPad(),&XContentData,pbImageData,&dwImageBytes,NULL);
+ XuiCreateTextureBrushFromMemory(pbImageData,dwImageBytes,&hXuiBrush);
+ }
+ }
+ else
+ {
+ XuiCreateTextureBrushFromMemory(pbImageData,dwImageBytes,&hXuiBrush);
+ }
+ // save the data with this icon
+ StorageManager.CopySaveDataToNewSave( pbImageData,dwImageBytes,pClass->m_wchNewName,&CScene_MultiGameJoinLoad::CopySaveReturned,pClass);
+ }
+ else
+#endif
+ {
+ //pClass->SetShow( TRUE );
+ pClass->m_bIgnoreInput=false;
+ }
+ return 0;
+}
+
+int CScene_MultiGameJoinLoad::CopySaveReturned(void *pParam,bool bResult)
+{
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad*)pParam;
+#ifdef _XBOX
+ if(bResult)
+ {
+ // and delete the old save
+ XCONTENT_DATA XContentData;
+ StorageManager.GetSaveCacheFileInfo(pClass->m_iChangingSaveGameInfoIndex-pClass->m_iDefaultButtonsC,XContentData);
+ StorageManager.DeleteSaveData(&XContentData,CScene_MultiGameJoinLoad::DeleteSaveDataReturned,pClass);
+ pClass->m_SavesListTimer.SetShow( TRUE );
+ }
+ else
+#endif
+ {
+ //pClass->SetShow( TRUE );
+ pClass->m_bIgnoreInput=false;
+ }
+
+ return 0;
+}
+
+int CScene_MultiGameJoinLoad::TexturePackDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
+{
+ CScene_MultiGameJoinLoad *pClass = (CScene_MultiGameJoinLoad *)pParam;
+
+ // Exit with or without saving
+ // Decline means install full version of the texture pack in this dialog
+ if(result==C4JStorage::EMessage_ResultDecline || result==C4JStorage::EMessage_ResultAccept)
+ {
+ // we need to enable background downloading for the DLC
+ XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW);
+
+ ULONGLONG ullOfferID_Full;
+ ULONGLONG ullIndexA[1];
+ app.GetDLCFullOfferIDForPackID(pClass->m_initData->selectedSession->data.texturePackParentId,&ullOfferID_Full);
+
+ if( result==C4JStorage::EMessage_ResultAccept ) // Full version
+ {
+ ullIndexA[0]=ullOfferID_Full;
+ StorageManager.InstallOffer(1,ullIndexA,NULL,NULL);
+
+ }
+ else // trial version
+ {
+ // if there is no trial version, this is a Cancel
+ DLC_INFO *pDLCInfo=app.GetDLCInfoForFullOfferID(ullOfferID_Full);
+ if(pDLCInfo->ullOfferID_Trial!=0LL)
+ {
+ ullIndexA[0]=pDLCInfo->ullOfferID_Trial;
+ StorageManager.InstallOffer(1,ullIndexA,NULL,NULL);
+ }
+ }
+ }
+ pClass->m_bIgnoreInput=false;
+ return 0;
+}
+
+HRESULT CScene_MultiGameJoinLoad::OnCustomMessage_DLCInstalled()
+{
+ // mounted DLC may have changed
+
+ if(app.StartInstallDLCProcess(m_iPad)==false)
+ {
+ // not doing a mount, so re-enable input
+ m_bIgnoreInput=false;
+ }
+ else
+ {
+ m_bIgnoreInput=true;
+ // clear out the saves list and re-fill
+
+ m_pSavesList->RemoveAllData();
+ m_SavesListTimer.SetShow( TRUE );
+ }
+ // this will send a CustomMessage_DLCMountingComplete when done
+ return S_OK;
+}
+
+HRESULT CScene_MultiGameJoinLoad::OnCustomMessage_DLCMountingComplete()
+{
+
+ VOID *pObj;
+ XuiObjectFromHandle( m_SavesList, &pObj );
+ m_pSavesList = (CXuiCtrl4JList *)pObj;
+
+ m_iChangingSaveGameInfoIndex = 0;
+
+ m_generators = app.getLevelGenerators();
+ m_iDefaultButtonsC = 0;
+ m_iMashUpButtonsC = 0;
+ XPARTY_USER_LIST partyList;
+
+ if((XPartyGetUserList( &partyList ) != XPARTY_E_NOT_IN_PARTY ) && (partyList.dwUserCount>1))
+ {
+ m_bInParty=true;
+ }
+ else
+ {
+ m_bInParty=false;
+ }
+
+ int iLB = -1;
+
+ int iY=-1;
+ if(DoesSavesListHaveFocus())
+ {
+ if(ProfileManager.IsSignedInLive( m_iPad ))
+ {
+ iY=IDS_TOOLTIPS_UPLOAD_SAVE_FOR_XBOXONE;
+ }
+ }
+ if(m_bInParty) iLB = IDS_TOOLTIPS_PARTY_GAMES;
+ // check if we're in the trial version
+ if(ProfileManager.IsFullVersion()==false)
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK, -1, -1, -1, -1,iLB);
+
+ AddDefaultButtons();
+
+ m_pSavesList->SetCurSelVisible(0);
+ }
+ else if(StorageManager.GetSaveDisabled())
+ {
+ if(StorageManager.GetSaveDeviceSelected(m_iPad))
+ {
+ // saving is disabled, but we should still be able to load from a selected save device
+
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_CHANGEDEVICE,iY,-1,-1,iLB,IDS_TOOLTIPS_DELETESAVE);
+
+ GetSaveInfo();
+ }
+ else
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,IDS_TOOLTIPS_SELECTDEVICE,iY,-1,-1,iLB);
+
+ AddDefaultButtons();
+ m_SavesListTimer.SetShow( FALSE );
+
+ m_pSavesList->SetCurSelVisible(0);
+ }
+ }
+ else
+ {
+ // 4J-PB - we need to check that there is enough space left to create a copy of the save (for a rename)
+ bool bCanRename = StorageManager.EnoughSpaceForAMinSaveGame();
+ 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);
+
+ GetSaveInfo();
+ }
+
+ m_bIgnoreInput=false;
+ app.m_dlcManager.checkForCorruptDLCAndAlert();
+ return S_OK;
+}
+
+/*
+void CScene_MultiGameJoinLoad::UpdateTooltips()
+{
+ int iA=IDS_TOOLTIPS_SELECT;
+ int iB=IDS_TOOLTIPS_BACK;
+ int iX=-1;
+ int iY=-1
+ int iLB = -1;
+ XPARTY_USER_LIST partyList;
+
+ if((XPartyGetUserList( &partyList ) != XPARTY_E_NOT_IN_PARTY ) && (partyList.dwUserCount>1))
+ {
+ m_bInParty=true;
+ }
+ else
+ {
+ m_bInParty=false;
+ }
+
+ if(m_bInParty) iLB = IDS_TOOLTIPS_PARTY_GAMES;
+
+ if(ProfileManager.IsFullVersion()==false)
+ {
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK, -1, -1, -1, -1,iLB);
+ }
+ else if(StorageManager.GetSaveDisabled())
+ {
+ if(StorageManager.GetSaveDeviceSelected(m_iPad))
+ {
+ // saving is disabled, but we should still be able to load from a selected save device
+ iX=IDS_TOOLTIPS_CHANGEDEVICE;
+ iRB=IDS_TOOLTIPS_DELETESAVE;
+ }
+ else
+ {
+ iX=IDS_TOOLTIPS_SELECTDEVICE;
+ }
+ }
+ else
+ {
+ // 4J-PB - we need to check that there is enough space left to create a copy of the save (for a rename)
+ bool bCanRename = StorageManager.EnoughSpaceForAMinSaveGame();
+
+ if(bCanRename)
+ {
+ iRB=IDS_TOOLTIPS_SAVEOPTIONS;
+ }
+ else
+ {
+ iRB=IDS_TOOLTIPS_DELETESAVE;
+ }
+ }
+
+ ui.SetTooltips( DEFAULT_XUI_MENU_USER, iA,iB, iX, iY, iLT, iRT,iLB, iRB);
+}
+*/
+
+
+
+#ifdef _XBOX
+bool CScene_MultiGameJoinLoad::GetSavesInfoCallback(LPVOID pParam,int iTotalSaveInfoC, C4JStorage::CACHEINFOSTRUCT *InfoA, int iPad, HRESULT hResult)
+{
+ CScene_MultiGameJoinLoad *pClass=(CScene_MultiGameJoinLoad *)pParam;
+ CXuiCtrl4JList::LIST_ITEM_INFO ListInfo;
+ PBYTE pbImageData=(PBYTE)InfoA;
+ PBYTE pbCurrentImagePtr;
+ HXUIBRUSH hXuiBrush;
+ HRESULT hr;
+
+ // move the image data pointer to the right place
+ if(iTotalSaveInfoC!=0)
+ {
+ pbImageData+=sizeof(C4JStorage::CACHEINFOSTRUCT)*iTotalSaveInfoC;
+ }
+
+ pClass->m_SavesListTimer.SetShow( FALSE );
+ pClass->m_SavesList.SetEnable(TRUE);
+
+ pClass->AddDefaultButtons();
+
+ for(int i=0;i<iTotalSaveInfoC;i++)
+ {
+ ZeroMemory(&ListInfo,sizeof(CXuiCtrl4JList::LIST_ITEM_INFO));
+ // Add these to the save list
+ if(!(app.DebugSettingsOn() && app.GetLoadSavesFromFolderEnabled()))
+ {
+ // if the save is corrupt, display this instead of the title
+ if(InfoA[i].dwImageBytes==0)
+ {
+ ListInfo.pwszText=app.GetString(IDS_CORRUPT_OR_DAMAGED_SAVE_TITLE);
+ ListInfo.bIsDamaged=true;
+ }
+ else
+ {
+ ListInfo.pwszText=InfoA[i].wchDisplayName;
+ ListInfo.bIsDamaged=false;
+ }
+ ListInfo.fEnabled=TRUE;
+ ListInfo.iData = -1;
+
+ pClass->m_pSavesList->AddData(ListInfo,-1);
+
+ // update the graphic on the list item
+
+ // if there is no thumbnail, this is a corrupt file
+ if(InfoA[i].dwImageBytes!=0)
+ {
+ pbCurrentImagePtr=pbImageData+InfoA[i].dwImageOffset;
+ hr=XuiCreateTextureBrushFromMemory(pbCurrentImagePtr,InfoA[i].dwImageBytes,&hXuiBrush);
+ pClass->m_pSavesList->UpdateGraphic(i+pClass->m_iDefaultButtonsC,hXuiBrush );
+ }
+ else
+ {
+ // we could put in a damaged save icon here
+ const DWORD LOCATOR_SIZE = 256; // Use this to allocate space to hold a ResourceLocator string
+ WCHAR szResourceLocator[ LOCATOR_SIZE ];
+ const ULONG_PTR c_ModuleHandle = (ULONG_PTR)GetModuleHandle(NULL);
+
+ swprintf(szResourceLocator, LOCATOR_SIZE, L"section://%X,%ls#%ls",c_ModuleHandle,L"media", L"media/Graphics/MinecraftBrokenIcon.png");
+
+ XuiCreateTextureBrush(szResourceLocator,&hXuiBrush);
+ pClass->m_pSavesList->UpdateGraphic(i+pClass->m_iDefaultButtonsC,hXuiBrush );
+ }
+ }
+ }
+
+ pClass->m_iSaveInfoC=iTotalSaveInfoC;
+
+ // 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
+ if(iTotalSaveInfoC>0)
+ {
+ pClass->m_pSavesList->SetCurSelVisible(pClass->m_iDefaultButtonsC);
+ pClass->m_bReady=true;
+ }
+
+ pClass->m_bRetrievingSaveInfo=false;
+
+ // 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
+ // This is to fix a bug where joining a game before the saves list has loaded causes a crash when this callback is called
+ // as the scene no longer exists
+ pClass->UpdateGamesList();
+
+ // Fix for #45154 - Frontend: DLC: Content can only be downloaded from the frontend if you have not joined/exited multiplayer
+ XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_AUTO);
+
+ return false;
+}
+#else
+int CScene_MultiGameJoinLoad::GetSavesInfoCallback(LPVOID lpParam,const bool)
+{
+ return true;
+}
+#endif
+
+void CScene_MultiGameJoinLoad::CancelSaveUploadCallback(LPVOID lpParam)
+{
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad *) lpParam;
+
+ StorageManager.TMSPP_CancelWriteFileWithProgress(pClass->m_iPad);
+
+ pClass->m_bSaveTransferInProgress=false;
+
+ // change back to the normal title group id
+ app.TMSPP_SetTitleGroupID(GROUP_ID);
+// app.getRemoteStorage()->abort();
+// pClass->m_eSaveUploadState = eSaveUpload_Idle;
+
+ UINT uiIDA[1] = { IDS_CONFIRM_OK };
+ ui.RequestMessageBox(IDS_XBONE_CANCEL_UPLOAD_TITLE, IDS_XBONE_CANCEL_UPLOAD_TEXT, uiIDA, 1, pClass->m_iPad, NULL, NULL, app.GetStringTable());
+}
+
+void CScene_MultiGameJoinLoad::SaveUploadCompleteCallback(LPVOID lpParam)
+{
+ CScene_MultiGameJoinLoad* pClass = (CScene_MultiGameJoinLoad *) lpParam;
+
+ pClass->m_bSaveTransferInProgress=false;
+ // change back to the normal title group id
+ app.TMSPP_SetTitleGroupID(GROUP_ID);
+ // app.getRemoteStorage()->abort();
+ // pClass->m_eSaveUploadState = eSaveUpload_Idle;
+} \ No newline at end of file