#include "../../Minecraft.World/Platform/stdafx.h" #include #include #include #include "../../Minecraft.World/Util/StringHelpers.h" #include "../Tutorial/TutorialMode.h" #include "../../Minecraft.World/IO/Files/ConsoleSaveFileIO.h" #include "../../Minecraft.Client/Player/LocalPlayer.h" #include "../../Minecraft.Client/Minecraft.h" #include "../../Minecraft.World/Util/AABB.h" #include "../../Minecraft.World/Util/Vec3.h" #include "../../Minecraft.World/Util/ArrayWithLength.h" #include "../../Minecraft.World/IO/Files/File.h" #include "../../Minecraft.World/IO/Streams/InputOutputStream.h" #include "../../Minecraft.Client/MinecraftServer.h" #include "../../Minecraft.Client/GameState/Options.h" #include "XUI_Ctrl_4JList.h" #include "XUI_MultiGameInfo.h" #include "XUI_MultiGameJoinLoad.h" #include "XUI_Ctrl_4JIcon.h" #include "XUI_LoadSettings.h" #include "../../Minecraft.World/Level/Storage/LevelSettings.h" #include "../../Minecraft.Client/Textures/Packs/TexturePackRepository.h" #include "../../Minecraft.Client/Textures/Packs/TexturePack.h" #include "../GameRules/ConsoleGameRules.h" #include "../../Minecraft.Client/Utils/StringTable.h" #include "../../Minecraft.Client/Textures/Packs/DLCTexturePack.h" #define GAME_CREATE_ONLINE_TIMER_ID 0 #define GAME_CREATE_ONLINE_TIMER_TIME 100 #define CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID 1 #define CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME 100 int CScene_LoadGameSettings::m_iDifficultyTitleSettingA[4] = { IDS_DIFFICULTY_TITLE_PEACEFUL, IDS_DIFFICULTY_TITLE_EASY, IDS_DIFFICULTY_TITLE_NORMAL, IDS_DIFFICULTY_TITLE_HARD}; HRESULT CScene_LoadGameSettings::OnInit(XUIMessageInit* pInitData, BOOL& bHandled) { m_hXuiBrush = NULL; m_bSetup = false; m_texturePackDescDisplayed = false; m_iConfigA = NULL; WCHAR TempString[256]; m_params = (LoadMenuInitData*)pInitData->pvInitData; m_MoreOptionsParams.bGenerateOptions = false; m_MoreOptionsParams.bPVP = true; m_MoreOptionsParams.bTrust = true; m_MoreOptionsParams.bFireSpreads = true; m_MoreOptionsParams.bTNT = true; m_MoreOptionsParams.bHostPrivileges = false; m_MoreOptionsParams.bResetNether = false; m_MoreOptionsParams.iPad = m_params->iPad; // 4J-JEV: Fix for: // TU12: Content: Gameplay: New "Mass Effect World" remembers and uses the // settings of another - lately created - World. m_MoreOptionsParams.bBonusChest = false; m_MoreOptionsParams.bFlatWorld = false; m_MoreOptionsParams.bStructures = true; m_iPad = m_params->iPad; m_iSaveGameInfoIndex = m_params->iSaveGameInfoIndex; m_levelGen = m_params->levelGen; MapChildControls(); XuiControlSetText(m_MoreOptions, app.GetString(IDS_MORE_OPTIONS)); XuiControlSetText(m_ButtonLoad, app.GetString(IDS_LOAD)); XuiControlSetText(m_pTexturePacksList->m_hObj, app.GetString(IDS_DLC_MENU_TEXTUREPACKS)); m_bMultiplayerAllowed = ProfileManager.IsSignedInLive(m_iPad) && ProfileManager.AllowedToPlayMultiplayer(m_iPad); // 4J-PB - read the settings for the online flag. We'll only save this // setting if the user changed it. bool bGameSetting_Online = (app.GetGameSettings(m_iPad, eGameSetting_Online) != 0); m_MoreOptionsParams.bOnlineSettingChangedBySystem = false; // Set the text for friends of friends, and default to on if (m_bMultiplayerAllowed) { m_MoreOptionsParams.bOnlineGame = bGameSetting_Online; if (bGameSetting_Online) { m_MoreOptionsParams.bInviteOnly = app.GetGameSettings(m_iPad, eGameSetting_InviteOnly) != 0; m_MoreOptionsParams.bAllowFriendsOfFriends = app.GetGameSettings(m_iPad, eGameSetting_FriendsOfFriends) != 0; } else { m_MoreOptionsParams.bInviteOnly = false; m_MoreOptionsParams.bAllowFriendsOfFriends = false; } } else { m_MoreOptionsParams.bOnlineGame = false; m_MoreOptionsParams.bInviteOnly = false; m_MoreOptionsParams.bAllowFriendsOfFriends = false; if (bGameSetting_Online) { // The profile settings say Online, but either the player is // offline, or they are not allowed to play online m_MoreOptionsParams.bOnlineSettingChangedBySystem = true; } } XuiSetTimer(m_hObj, GAME_CREATE_ONLINE_TIMER_ID, GAME_CREATE_ONLINE_TIMER_TIME); XuiSetTimer(m_hObj, CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID, CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME); m_ButtonGameMode.SetText(app.GetString(IDS_GAMEMODE_SURVIVAL)); m_bGameModeSurvival = true; m_CurrentDifficulty = app.GetGameSettings(m_iPad, eGameSetting_Difficulty); m_SliderDifficulty.SetValue(m_CurrentDifficulty); swprintf((WCHAR*)TempString, 256, L"%ls: %ls", app.GetString(IDS_SLIDER_DIFFICULTY), app.GetString(m_iDifficultyTitleSettingA[m_CurrentDifficulty])); m_SliderDifficulty.SetText(TempString); m_bHasBeenInCreative = false; if (m_levelGen) { m_GameName.SetText(m_levelGen->getDisplayName()); if (m_levelGen->requiresTexturePack()) { m_MoreOptionsParams.dwTexturePack = m_levelGen->getRequiredTexturePackId(); m_pTexturePacksList->SetEnable(FALSE); // retrieve the save icon from the texture pack, if there is one TexturePack* tp = Minecraft::GetInstance()->skins->getTexturePackById( m_MoreOptionsParams.dwTexturePack); std::uint32_t imageBytes = 0; std::uint8_t* imageData = tp->getPackIcon(imageBytes); if (imageBytes > 0 && imageData) { XuiCreateTextureBrushFromMemory(imageData, imageBytes, &m_hXuiBrush); } // Set this level as created in creative mode, so that people can't // use the themed worlds as an easy way to get achievements m_bHasBeenInCreative = true; m_GameCreatedMode.SetText(app.GetString(IDS_CREATED_IN_CREATIVE)); } } else { // set the save icon PBYTE pbImageData = NULL; DWORD dwImageBytes = 0; StorageManager.GetSaveCacheFileInfo(m_params->iSaveGameInfoIndex, m_XContentData); StorageManager.GetSaveCacheFileInfo(m_params->iSaveGameInfoIndex, &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 bool bHostOptionsRead = false; unsigned int uiHostOptions = 0; if (pbImageData == NULL) { DWORD dwResult = XContentGetThumbnail( ProfileManager.GetPrimaryPad(), &m_XContentData, NULL, &dwImageBytes, NULL); if (dwResult == ERROR_SUCCESS) { pbImageData = new BYTE[dwImageBytes]; XContentGetThumbnail(ProfileManager.GetPrimaryPad(), &m_XContentData, pbImageData, &dwImageBytes, NULL); XuiCreateTextureBrushFromMemory(pbImageData, dwImageBytes, &m_hXuiBrush); } } else { // retrieve the seed value from the image metadata ZeroMemory(m_szSeed, 50); app.GetImageTextData(pbImageData, dwImageBytes, (unsigned char*)&m_szSeed, uiHostOptions, bHostOptionsRead, m_MoreOptionsParams.dwTexturePack); XuiCreateTextureBrushFromMemory(pbImageData, dwImageBytes, &m_hXuiBrush); // #ifdef _DEBUG // // dump out the thumbnail // HANDLE hThumbnail = // CreateFile("GAME:\\thumbnail.png", GENERIC_WRITE, 0, NULL, // OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, NULL); DWORD dwBytes; // WriteFile(hThumbnail,pbImageData,dwImageBytes,&dwBytes,NULL); // XCloseHandle(hThumbnail); // #endif if (m_szSeed[0] != 0) { swprintf((WCHAR*)TempString, 256, L"%ls: %hs", app.GetString(IDS_SEED), m_szSeed); m_GameSeed.SetText(TempString); } else { m_GameSeed.SetText(L""); } } // Setup all the text and checkboxes to match what the game was saved // with on if (bHostOptionsRead) { m_MoreOptionsParams.bPVP = app.GetGameHostOption(uiHostOptions, eGameHostOption_PvP) > 0; m_MoreOptionsParams.bTrust = app.GetGameHostOption(uiHostOptions, eGameHostOption_TrustPlayers) > 0; m_MoreOptionsParams.bFireSpreads = app.GetGameHostOption(uiHostOptions, eGameHostOption_FireSpreads) > 0; m_MoreOptionsParams.bTNT = app.GetGameHostOption(uiHostOptions, eGameHostOption_TNT) > 0; m_MoreOptionsParams.bHostPrivileges = app.GetGameHostOption(uiHostOptions, eGameHostOption_CheatsEnabled) > 0; m_bHasBeenInCreative = app.GetGameHostOption(uiHostOptions, eGameHostOption_HasBeenInCreative) > 0; if (app.GetGameHostOption(uiHostOptions, eGameHostOption_HasBeenInCreative) > 0) { m_GameCreatedMode.SetText( app.GetString(IDS_CREATED_IN_CREATIVE)); } else { m_GameCreatedMode.SetText( app.GetString(IDS_CREATED_IN_SURVIVAL)); } if (app.GetGameHostOption(uiHostOptions, eGameHostOption_GameType) > 0) { m_ButtonGameMode.SetText(app.GetString(IDS_GAMEMODE_CREATIVE)); m_bGameModeSurvival = false; } if (app.GetGameHostOption(uiHostOptions, eGameHostOption_FriendsOfFriends) && !(m_bMultiplayerAllowed && bGameSetting_Online)) { m_MoreOptionsParams.bAllowFriendsOfFriends = true; } } m_GameName.SetText(m_XContentData.szDisplayName); } // 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); } } int iRB = -1; ui.SetTooltips(DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, -1, -1); // if(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen()) { CXuiSceneBase::ShowLogo(DEFAULT_XUI_MENU_USER, FALSE); } TelemetryManager->RecordMenuShown(m_iPad, eUIScene_LoadMenu, 0); m_iTexturePacksNotInstalled = 0; // 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 { m_bIgnoreInput = false; Minecraft* pMinecraft = Minecraft::GetInstance(); m_pTexturePacksList->SetSelectionChangedHandle(m_hObj); int texturePacksCount = pMinecraft->skins->getTexturePackCount(); CXuiCtrl4JList::LIST_ITEM_INFO ListInfo; HRESULT hr; for (unsigned int i = 0; i < texturePacksCount; ++i) { TexturePack* tp = pMinecraft->skins->getTexturePackByIndex(i); ZeroMemory(&ListInfo, sizeof(CXuiCtrl4JList::LIST_ITEM_INFO)); std::uint32_t imageBytes = 0; std::uint8_t* imageData = tp->getPackIcon(imageBytes); if (imageBytes > 0 && imageData) { ListInfo.fEnabled = TRUE; DLCTexturePack* pDLCTexPack = (DLCTexturePack*)tp; if (pDLCTexPack) { int id = pDLCTexPack->getDLCParentPackId(); if (id == 0) { // default texture pack - should come first ListInfo.iSortIndex = 0x0FFFFFFF; } else { ListInfo.iSortIndex = id; ListInfo.iData = id; } } #ifdef _DEBUG app.DebugPrintf("TP - "); OutputDebugStringW(tp->getName().c_str()); app.DebugPrintf(", sort index - %d\n", ListInfo.iSortIndex); #endif hr = XuiCreateTextureBrushFromMemory(imageData, imageBytes, &ListInfo.hXuiBrush); m_pTexturePacksList->AddData(ListInfo, 0, CXuiCtrl4JList::eSortList_Index); } } m_currentTexturePackIndex = m_pTexturePacksList->GetIndexByUserData( m_MoreOptionsParams.dwTexturePack); m_pTexturePacksList->SetCurSel(m_currentTexturePackIndex); m_pTexturePacksList->SetTopItem( m_currentTexturePackIndex); // scroll the item into view if it's // not visible UpdateTexturePackDescription(m_currentTexturePackIndex); // 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; 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) { // some missing bNeedToGetTPD = true; m_iTexturePacksNotInstalled++; } } if (bNeedToGetTPD == true) { // add a TMS request for them 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; } } } } m_bSetup = true; return S_OK; } HRESULT CScene_LoadGameSettings::OnControlNavigate( XUIMessageControlNavigate* pControlNavigateData, BOOL& bHandled) { pControlNavigateData->hObjDest = XuiControlGetNavigation( pControlNavigateData->hObjSource, pControlNavigateData->nControlNavigate, TRUE, TRUE); if (pControlNavigateData->hObjDest != NULL) { bHandled = TRUE; } return S_OK; } HRESULT CScene_LoadGameSettings::LaunchGame(void) { // stop the timer running that causes a check for new texture packs in TMS // but not installed, since this will run all through the load game, and // will crash if it tries to create an hbrush XuiKillTimer(m_hObj, CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID); if ((m_bGameModeSurvival != true || m_bHasBeenInCreative) || m_MoreOptionsParams.bHostPrivileges) { unsigned int uiIDA[2]; uiIDA[0] = IDS_CONFIRM_OK; uiIDA[1] = IDS_CONFIRM_CANCEL; if (m_bGameModeSurvival != true || m_bHasBeenInCreative) { // 4J-PB - Need different text for Survival mode with a level that // has been saved in Creative if (m_bGameModeSurvival) { StorageManager.RequestMessageBox( IDS_TITLE_START_GAME, IDS_CONFIRM_START_SAVEDINCREATIVE, uiIDA, 2, m_iPad, &CScene_LoadGameSettings::ConfirmLoadReturned, this, app.GetStringTable()); } else // it's creative mode { // has it previously been saved in creative? if (m_bHasBeenInCreative) { // 4J-PB - We don't really need to tell the user this will // have achievements disabled, since they already saved it // in creative and they got the warning then inform them // that leaderboard writes and achievements will be disabled // StorageManager.RequestMessageBox(IDS_TITLE_START_GAME, // IDS_CONFIRM_START_SAVEDINCREATIVE_CONTINUE, uiIDA, 1, // m_iPad,&CScene_LoadGameSettings::ConfirmLoadReturned,this,app.GetStringTable()); if (m_levelGen != NULL) { LoadLevelGen(m_levelGen); } else { C4JStorage::ELoadGameStatus eLoadStatus = StorageManager.LoadSaveData( &m_XContentData, CScene_LoadGameSettings::LoadSaveDataReturned, this); if (eLoadStatus == C4JStorage::ELoadGame_DeviceRemoved) { // disable saving StorageManager.SetSaveDisabled(true); StorageManager.SetSaveDeviceSelected(m_iPad, false); unsigned int uiIDA[1]; uiIDA[0] = IDS_OK; StorageManager.RequestMessageBox( IDS_STORAGEDEVICEPROBLEM_TITLE, IDS_FAILED_TO_LOADSAVE_TEXT, uiIDA, 1, m_iPad, &CScene_LoadGameSettings:: DeviceRemovedDialogReturned, this); } } } else { // ask if they're sure they want to turn this into a // creative map StorageManager.RequestMessageBox( IDS_TITLE_START_GAME, IDS_CONFIRM_START_CREATIVE, uiIDA, 2, m_iPad, &CScene_LoadGameSettings::ConfirmLoadReturned, this, app.GetStringTable()); } } } else { StorageManager.RequestMessageBox( IDS_TITLE_START_GAME, IDS_CONFIRM_START_HOST_PRIVILEGES, uiIDA, 2, m_iPad, &CScene_LoadGameSettings::ConfirmLoadReturned, this, app.GetStringTable()); } } else { if (m_levelGen != NULL) { LoadLevelGen(m_levelGen); } else { C4JStorage::ELoadGameStatus eLoadStatus = StorageManager.LoadSaveData( &m_XContentData, CScene_LoadGameSettings::LoadSaveDataReturned, this); if (eLoadStatus == C4JStorage::ELoadGame_DeviceRemoved) { // disable saving StorageManager.SetSaveDisabled(true); StorageManager.SetSaveDeviceSelected(m_iPad, false); unsigned int uiIDA[1]; uiIDA[0] = IDS_OK; StorageManager.RequestMessageBox( IDS_STORAGEDEVICEPROBLEM_TITLE, IDS_FAILED_TO_LOADSAVE_TEXT, uiIDA, 1, m_iPad, &CScene_LoadGameSettings::DeviceRemovedDialogReturned, this); } } } return 0; } int CScene_LoadGameSettings::CheckResetNetherReturned( void* pParam, int iPad, C4JStorage::EMessageResult result) { CScene_LoadGameSettings* pClass = (CScene_LoadGameSettings*)pParam; // results switched for this dialog if (result == C4JStorage::EMessage_ResultDecline) { // continue and reset the nether pClass->LaunchGame(); } else { // turn off the reset nether and continue pClass->m_MoreOptionsParams.bResetNether = FALSE; pClass->LaunchGame(); } return 0; } HRESULT CScene_LoadGameSettings::OnNotifyPressEx( HXUIOBJ hObjPressed, XUINotifyPress* pNotifyPressData, BOOL& rfHandled) { // 4J-PB - stop people double pressing this if (m_bIgnoreInput) return S_OK; Minecraft* pMinecraft = Minecraft::GetInstance(); // This assumes all buttons can only be pressed with the A button ui.AnimateKeyPress(pNotifyPressData->UserIndex, VK_PAD_A); if (hObjPressed == m_ButtonLoad) { // Check if we need to upsell the texture pack if (m_MoreOptionsParams.dwTexturePack != 0) { // texture pack hasn't been set yet, so check what it will be TexturePack* pTexturePack = pMinecraft->skins->getTexturePackById( m_MoreOptionsParams.dwTexturePack); if (pTexturePack == NULL) { // They've selected a texture pack they don't have yet // upsell CXuiCtrl4JList::LIST_ITEM_INFO ListItem; // get the current index of the list, and then get the data ListItem = m_pTexturePacksList->GetData(m_currentTexturePackIndex); // upsell the texture pack ULONGLONG ullOfferID_Full; app.GetDLCFullOfferIDForPackID(ListItem.iData, &ullOfferID_Full); // 4J-PB - if the full offer id is 0, then the texture pack dlc // load failed if (ullOfferID_Full != 0LL) { // tell sentient about the upsell of the full version of the // skin pack TelemetryManager->RecordUpsellPresented( ProfileManager.GetPrimaryPad(), eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF); unsigned int 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_LoadGameSettings::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_LoadGameSettings::TexturePackDialogReturned, this, app.GetStringTable()); } return S_OK; } } } // if the profile data has been changed, then force a profile write (we // save the online/invite/friends of friends settings) It seems we're // allowed to break the 5 minute rule if it's the result of a user // action check the checkboxes // Only save the online setting if the user changed it - we may change // it because we're offline, but don't want that saved if (!m_MoreOptionsParams.bOnlineSettingChangedBySystem) { app.SetGameSettings(m_iPad, eGameSetting_Online, m_MoreOptionsParams.bOnlineGame ? 1 : 0); } app.SetGameSettings(m_iPad, eGameSetting_InviteOnly, m_MoreOptionsParams.bInviteOnly ? 1 : 0); app.SetGameSettings(m_iPad, eGameSetting_FriendsOfFriends, m_MoreOptionsParams.bAllowFriendsOfFriends ? 1 : 0); app.CheckGameSettingsChanged(true, pNotifyPressData->UserIndex); SetShow(FALSE); m_bIgnoreInput = true; // Check that we have the rights to use a texture pack we have selected. if (m_MoreOptionsParams.dwTexturePack != 0) { // texture pack hasn't been set yet, so check what it will be TexturePack* pTexturePack = pMinecraft->skins->getTexturePackById( m_MoreOptionsParams.dwTexturePack); if (pTexturePack == NULL) { // DLC corrupt, so use the default textures m_MoreOptionsParams.dwTexturePack = 0; } else { m_pDLCPack = pTexturePack->getDLCPack(); // do we have a license? if (m_pDLCPack && !m_pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"")) { // no unsigned int uiIDA[1]; uiIDA[0] = IDS_OK; if (!ProfileManager.IsSignedInLive( pNotifyPressData->UserIndex)) { // need to be signed in to live StorageManager.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1); return S_OK; } else { // upsell DLC_INFO* pDLCInfo = app.GetDLCInfoForTrialOfferID( m_pDLCPack->getPurchaseOfferId()); ULONGLONG ullOfferID_Full; if (pDLCInfo != NULL) { ullOfferID_Full = pDLCInfo->ullOfferID_Full; } else { ullOfferID_Full = pTexturePack->getDLCPack() ->getPurchaseOfferId(); } // tell sentient about the upsell of the full version of // the texture pack TelemetryManager->RecordUpsellPresented( pNotifyPressData->UserIndex, eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF); unsigned int uiIDA[2]; uiIDA[0] = IDS_CONFIRM_OK; uiIDA[1] = IDS_CONFIRM_CANCEL; // StorageManager.RequestMessageBox(IDS_UNLOCK_DLC_TITLE, // IDS_UNLOCK_DLC_SKIN, uiIDA, 2, // pInputData->UserIndex,&CScene_SkinSelect::UnlockSkinReturned,this,app.GetStringTable()); StorageManager.RequestMessageBox( IDS_UNLOCK_DLC_TEXTUREPACK_TITLE, IDS_UNLOCK_DLC_TEXTUREPACK_TEXT, uiIDA, 2, pNotifyPressData->UserIndex, &CScene_LoadGameSettings::UnlockTexturePackReturned, this, app.GetStringTable()); return S_OK; } } } } // Reset the background downloading, in case we changed it by attempting // to download a texture pack XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_AUTO); // Check if they have the Reset Nether flag set, and confirm they want // to do this if (m_MoreOptionsParams.bResetNether) { unsigned int uiIDA[2]; uiIDA[0] = IDS_DONT_RESET_NETHER; uiIDA[1] = IDS_RESET_NETHER; StorageManager.RequestMessageBox( IDS_RESETNETHER_TITLE, IDS_RESETNETHER_TEXT, uiIDA, 2, pNotifyPressData->UserIndex, &CScene_LoadGameSettings::CheckResetNetherReturned, this, app.GetStringTable()); } else { LaunchGame(); } } else if (hObjPressed == m_MoreOptions) { app.NavigateToScene(pNotifyPressData->UserIndex, eUIScene_LaunchMoreOptionsMenu, &m_MoreOptionsParams); } else if (hObjPressed == m_ButtonGameMode) { if (m_bGameModeSurvival) { m_ButtonGameMode.SetText(app.GetString(IDS_GAMEMODE_CREATIVE)); m_bGameModeSurvival = false; } else { m_ButtonGameMode.SetText(app.GetString(IDS_GAMEMODE_SURVIVAL)); m_bGameModeSurvival = true; } } else if (hObjPressed == m_pTexturePacksList->m_hObj) { UpdateCurrentTexturePack(); } return S_OK; } HRESULT CScene_LoadGameSettings::OnKeyDown(XUIMessageInput* pInputData, BOOL& rfHandled) { if (m_bIgnoreInput) return S_OK; ui.AnimateKeyPress(pInputData->UserIndex, pInputData->dwKeyCode); // Explicitly handle B button presses switch (pInputData->dwKeyCode) { case VK_PAD_B: case VK_ESCAPE: app.SetCorruptSaveDeleted(false); app.NavigateBack(pInputData->UserIndex); rfHandled = TRUE; break; case VK_PAD_RSHOULDER: /* if(app.m_bTransferSavesToXboxOne && ProfileManager.IsFullVersion()) { app.NavigateToScene(m_iPad,eUIScene_TransferToXboxOne,m_params); } */ break; } return S_OK; } HRESULT CScene_LoadGameSettings::OnFontRendererChange() { int iRB = -1; ui.SetTooltips(DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, -1, -1, -1, -1, -1, -1, -1, true); return S_OK; } int CScene_LoadGameSettings::ConfirmLoadReturned( void* pParam, int iPad, C4JStorage::EMessageResult result) { CScene_LoadGameSettings* pClass = (CScene_LoadGameSettings*)pParam; if (result == C4JStorage::EMessage_ResultAccept) { if (pClass->m_levelGen != NULL) { pClass->LoadLevelGen(pClass->m_levelGen); } else { C4JStorage::ELoadGameStatus eLoadStatus = StorageManager.LoadSaveData( &pClass->m_XContentData, CScene_LoadGameSettings::LoadSaveDataReturned, pClass); if (eLoadStatus == C4JStorage::ELoadGame_DeviceRemoved) { // disable saving StorageManager.SetSaveDisabled(true); StorageManager.SetSaveDeviceSelected(pClass->m_iPad, false); unsigned int uiIDA[1]; uiIDA[0] = IDS_OK; StorageManager.RequestMessageBox( IDS_STORAGEDEVICEPROBLEM_TITLE, IDS_FAILED_TO_LOADSAVE_TEXT, uiIDA, 1, pClass->m_iPad, &CScene_LoadGameSettings::DeviceRemovedDialogReturned, pClass); } } } else { pClass->SetShow(TRUE); pClass->m_bIgnoreInput = false; } return 0; } HRESULT CScene_LoadGameSettings::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 GAME_CREATE_ONLINE_TIMER_ID: { bool bMultiplayerAllowed = ProfileManager.IsSignedInLive(m_iPad) && ProfileManager.AllowedToPlayMultiplayer(m_iPad); if (bMultiplayerAllowed != m_bMultiplayerAllowed) { if (bMultiplayerAllowed) { bool bGameSetting_Online = (app.GetGameSettings(m_iPad, eGameSetting_Online) != 0); m_MoreOptionsParams.bOnlineGame = bGameSetting_Online; if (bGameSetting_Online) { m_MoreOptionsParams.bInviteOnly = app.GetGameSettings(m_iPad, eGameSetting_InviteOnly) != 0; m_MoreOptionsParams.bAllowFriendsOfFriends = app.GetGameSettings( m_iPad, eGameSetting_FriendsOfFriends) != 0; } else { m_MoreOptionsParams.bInviteOnly = false; m_MoreOptionsParams.bAllowFriendsOfFriends = false; } } else { m_MoreOptionsParams.bOnlineGame = false; m_MoreOptionsParams.bInviteOnly = false; m_MoreOptionsParams.bAllowFriendsOfFriends = false; } m_bMultiplayerAllowed = bMultiplayerAllowed; } } 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) { unsigned int dwBytes = 0; std::uint8_t* pbData = NULL; app.GetTPD(m_iConfigA[i], &pbData, &dwBytes); ZeroMemory(&ListInfo, sizeof(CXuiCtrl4JList::LIST_ITEM_INFO)); if (dwBytes > 0 && pbData) { unsigned int dwImageBytes = 0; std::uint8_t* pbImageData = NULL; app.GetFileFromTPD(eTPDFileType_Icon, pbData, dwBytes, &pbImageData, &dwImageBytes); ListInfo.fEnabled = TRUE; ListInfo.iData = m_iConfigA[i]; HRESULT hr = XuiCreateTextureBrushFromMemory( pbImageData, dwImageBytes, &ListInfo.hXuiBrush); ListInfo.iSortIndex = m_iConfigA[i]; m_pTexturePacksList->AddData( ListInfo, 0, CXuiCtrl4JList::eSortList_Index); m_iConfigA[i] = -1; m_currentTexturePackIndex = m_pTexturePacksList->GetIndexByUserData( m_MoreOptionsParams.dwTexturePack); m_pTexturePacksList->SetCurSel( m_currentTexturePackIndex); m_pTexturePacksList->SetTopItem( m_currentTexturePackIndex); // scroll the item into // view if it's not // visible } } } 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; } PBYTE pbData; int CScene_LoadGameSettings::Progress(void* pParam, float fProgress) { app.DebugPrintf("Progress - %f\n", fProgress); return 0; } int CScene_LoadGameSettings::LoadSaveDataReturned(void* pParam, bool bContinue) { CScene_LoadGameSettings* pClass = (CScene_LoadGameSettings*)pParam; if (bContinue == true) { bool isClientSide = ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()) && pClass->m_MoreOptionsParams.bOnlineGame; // 4J Stu - If we only have one controller connected, then don't show // the sign-in UI again int 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()) { // Check if user-created content is allowed, as we cannot play // multiplayer if it's not bool noUGC = false; bool pccAllowed = true; bool pccFriendsAllowed = true; ProfileManager.AllowedPlayerCreatedContent( ProfileManager.GetPrimaryPad(), false, &pccAllowed, &pccFriendsAllowed); if (!pccAllowed && !pccFriendsAllowed) noUGC = true; if (isClientSide && noUGC) { pClass->SetShow(TRUE); pClass->m_bIgnoreInput = false; unsigned int uiIDA[1]; uiIDA[0] = IDS_CONFIRM_OK; StorageManager.RequestMessageBox( IDS_FAILED_TO_CREATE_GAME_TITLE, IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_CREATE, uiIDA, 1, ProfileManager.GetPrimaryPad(), NULL, NULL, app.GetStringTable()); } else { unsigned int 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_LoadGameSettings::StartGame_SignInReturned, pParam, ProfileManager.GetPrimaryPad()); } } else { // the save is corrupt! pClass->SetShow(TRUE); pClass->m_bIgnoreInput = false; // give the option to delete the save unsigned int 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_LoadGameSettings::DeleteSaveDialogReturned, pClass, app.GetStringTable()); } return 0; } int CScene_LoadGameSettings::DeleteSaveDialogReturned( void* pParam, int iPad, C4JStorage::EMessageResult result) { CScene_LoadGameSettings* pClass = (CScene_LoadGameSettings*)pParam; // results switched for this dialog if (result == C4JStorage::EMessage_ResultDecline) { #ifdef _XBOX StorageManager.DeleteSaveData( &pClass->m_XContentData, CScene_LoadGameSettings::DeleteSaveDataReturned, pClass); #endif } else { pClass->m_bIgnoreInput = false; } return 0; } int CScene_LoadGameSettings::DeleteSaveDataReturned(void* pParam, bool bSuccess) { CScene_LoadGameSettings* pClass = (CScene_LoadGameSettings*)pParam; app.SetCorruptSaveDeleted(true); app.NavigateBack(pClass->m_iPad); return 0; } int CScene_LoadGameSettings::DeviceRemovedDialogReturned( void* pParam, int iPad, C4JStorage::EMessageResult result) { // need to back out of this scene app.NavigateBack(iPad); return 0; } // 4J Stu - Shared functionality that is the same whether we needed a quadrant // sign-in or not void CScene_LoadGameSettings::StartGameFromSave(CScene_LoadGameSettings* pClass, DWORD dwLocalUsersMask) { int saveOrCheckpointId = 0; bool validSave = StorageManager.GetSaveUniqueNumber(&saveOrCheckpointId); TelemetryManager->RecordLevelResume( pClass->m_iPad, eSen_FriendOrMatch_Playing_With_Invited_Friends, eSen_CompeteOrCoop_Coop_and_Competitive, app.GetGameSettings(pClass->m_iPad, eGameSetting_Difficulty), app.GetLocalPlayerCount(), g_NetworkManager.GetOnlinePlayerCount(), saveOrCheckpointId); bool isClientSide = ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()) && pClass->m_MoreOptionsParams.bOnlineGame; bool isPrivate = (app.GetGameSettings(pClass->m_iPad, eGameSetting_InviteOnly) > 0) ? true : false; g_NetworkManager.HostGame(dwLocalUsersMask, isClientSide, isPrivate, MINECRAFT_NET_MAX_PLAYERS, 0); NetworkGameInitData* param = new NetworkGameInitData(); param->seed = 0; param->saveData = NULL; param->texturePackId = pClass->m_MoreOptionsParams.dwTexturePack; Minecraft* pMinecraft = Minecraft::GetInstance(); pMinecraft->skins->selectTexturePackById( pClass->m_MoreOptionsParams.dwTexturePack); // pMinecraft->skins->updateUI(); app.SetGameHostOption(eGameHostOption_Difficulty, Minecraft::GetInstance()->options->difficulty); app.SetGameHostOption( eGameHostOption_FriendsOfFriends, app.GetGameSettings(pClass->m_iPad, eGameSetting_FriendsOfFriends)); app.SetGameHostOption( eGameHostOption_Gamertags, app.GetGameSettings(pClass->m_iPad, eGameSetting_GamertagsVisible)); app.SetGameHostOption( eGameHostOption_BedrockFog, app.GetGameSettings(pClass->m_iPad, eGameSetting_BedrockFog) ? 1 : 0); app.SetGameHostOption(eGameHostOption_PvP, pClass->m_MoreOptionsParams.bPVP); app.SetGameHostOption(eGameHostOption_TrustPlayers, pClass->m_MoreOptionsParams.bTrust); app.SetGameHostOption(eGameHostOption_FireSpreads, pClass->m_MoreOptionsParams.bFireSpreads); app.SetGameHostOption(eGameHostOption_TNT, pClass->m_MoreOptionsParams.bTNT); app.SetGameHostOption(eGameHostOption_HostCanFly, pClass->m_MoreOptionsParams.bHostPrivileges); app.SetGameHostOption(eGameHostOption_HostCanChangeHunger, pClass->m_MoreOptionsParams.bHostPrivileges); app.SetGameHostOption(eGameHostOption_HostCanBeInvisible, pClass->m_MoreOptionsParams.bHostPrivileges); // flag if the user wants to reset the Nether to force a Fortress with // netherwart etc. app.SetResetNether(pClass->m_MoreOptionsParams.bResetNether); // clear out the app's terrain features list app.ClearTerrainFeaturePosition(); app.SetGameHostOption(eGameHostOption_GameType, pClass->m_bGameModeSurvival ? GameType::SURVIVAL->getId() : GameType::CREATIVE->getId()); param->settings = app.GetGameHostOption(eGameHostOption_All); LoadingInputParams* loadingParams = new LoadingInputParams(); loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc; loadingParams->lpParam = param; // Reset the autosave timer app.SetAutosaveTimerTime(); 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_LoadGameSettings::StartGame_SignInReturned(void* pParam, bool bContinue, int iPad) { CScene_LoadGameSettings* pClass = (CScene_LoadGameSettings*)pParam; if (bContinue == true) { // It's possible that the player has not signed in - they can back out if (ProfileManager.IsSignedIn(iPad)) { unsigned int dwLocalUsersMask = 0; bool isClientSide = ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()) && pClass->m_MoreOptionsParams.bOnlineGame; bool noPrivileges = false; for (unsigned int index = 0; index < XUSER_MAX_COUNT; ++index) { if (ProfileManager.IsSignedIn(index)) { if (!ProfileManager.AllowedToPlayMultiplayer(index)) noPrivileges = true; dwLocalUsersMask |= CGameNetworkManager::GetLocalPlayerMask(index); } } // Check if user-created content is allowed, as we cannot play // multiplayer if it's not bool noUGC = false; bool pccAllowed = true; bool pccFriendsAllowed = true; ProfileManager.AllowedPlayerCreatedContent( ProfileManager.GetPrimaryPad(), false, &pccAllowed, &pccFriendsAllowed); if (!pccAllowed && !pccFriendsAllowed) noUGC = true; if (isClientSide && (noPrivileges || noUGC)) { if (noUGC) { pClass->SetShow(TRUE); pClass->m_bIgnoreInput = false; // pClass->m_bAbortSearch=false; unsigned int uiIDA[1]; uiIDA[0] = IDS_CONFIRM_OK; StorageManager.RequestMessageBox( IDS_FAILED_TO_CREATE_GAME_TITLE, IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_CREATE, uiIDA, 1, ProfileManager.GetPrimaryPad(), NULL, NULL, app.GetStringTable()); } else { pClass->SetShow(TRUE); pClass->m_bIgnoreInput = false; // pClass->m_bAbortSearch=false; unsigned int uiIDA[1]; uiIDA[0] = IDS_CONFIRM_OK; StorageManager.RequestMessageBox( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_HOST_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(), NULL, NULL, app.GetStringTable()); } } else { StartGameFromSave(pClass, dwLocalUsersMask); } } } else { pClass->SetShow(TRUE); pClass->m_bIgnoreInput = false; // pClass->m_bAbortSearch=false; } return 0; } HRESULT CScene_LoadGameSettings::OnGetSourceDataImage( XUIMessageGetSourceImage* pGetSourceImageData, BOOL& bHandled) { if (pGetSourceImageData->bItemData) { pGetSourceImageData->hBrush = m_hXuiBrush; bHandled = TRUE; } return S_OK; } HRESULT CScene_LoadGameSettings::OnNotifyValueChanged( HXUIOBJ hObjSource, XUINotifyValueChanged* pNotifyValueChanged, BOOL& bHandled) { WCHAR TempString[256]; if (hObjSource == m_SliderDifficulty.GetSlider()) { app.SetGameSettings(m_iPad, eGameSetting_Difficulty, pNotifyValueChanged->nValue); swprintf((WCHAR*)TempString, 256, L"%ls: %ls", app.GetString(IDS_SLIDER_DIFFICULTY), app.GetString( m_iDifficultyTitleSettingA[pNotifyValueChanged->nValue])); m_SliderDifficulty.SetText(TempString); } return S_OK; } HRESULT CScene_LoadGameSettings::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); } else if (pTransition->dwTransType == XUI_TRANSITION_TO || pTransition->dwTransType == XUI_TRANSITION_BACKTO) { m_SliderDifficulty.SetValueDisplay(FALSE); // 4J-PB - Need to check for installed DLC, which might have happened // while you were on the More Options scene if (pTransition->dwTransType == XUI_TRANSITION_BACKTO) { // 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_pTexturePacksList->RemoveAllData(); } } } return S_OK; } HRESULT CScene_LoadGameSettings::OnTransitionEnd( 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) { } else if (pTransition->dwTransType == XUI_TRANSITION_TO || pTransition->dwTransType == XUI_TRANSITION_BACKTO) { if (m_bSetup && m_texturePackDescDisplayed) { XUITimeline* timeline; XUINamedFrame *startFrame, *endFrame; GetTimeline(&timeline); startFrame = timeline->FindNamedFrame(L"SlideOutEnd"); endFrame = timeline->FindNamedFrame(L"SlideOutEnd"); timeline->Play(startFrame->m_dwFrame, startFrame->m_dwFrame, endFrame->m_dwFrame, FALSE, FALSE); m_texturePackDescDisplayed = true; } } return S_OK; } int CScene_LoadGameSettings::UnlockTexturePackReturned( void* pParam, int iPad, C4JStorage::EMessageResult result) { CScene_LoadGameSettings* pScene = (CScene_LoadGameSettings*)pParam; if (result == C4JStorage::EMessage_ResultAccept) { if (ProfileManager.IsSignedIn(iPad)) { ULONGLONG ullIndexA[1]; DLC_INFO* pDLCInfo = app.GetDLCInfoForTrialOfferID( pScene->m_pDLCPack->getPurchaseOfferId()); if (pDLCInfo != NULL) { ullIndexA[0] = pDLCInfo->ullOfferID_Full; } else { ullIndexA[0] = pScene->m_pDLCPack->getPurchaseOfferId(); } StorageManager.InstallOffer(1, ullIndexA, NULL, NULL); // the license change coming in when the offer has been installed // will cause this scene to refresh } } else { TelemetryManager->RecordUpsellResponded( iPad, eSet_UpsellID_Texture_DLC, (pScene->m_pDLCPack->getPurchaseOfferId() & 0xFFFFFFFF), eSen_UpsellOutcome_Declined); } pScene->m_bIgnoreInput = false; pScene->SetShow(TRUE); return 0; } HRESULT CScene_LoadGameSettings::OnNotifySelChanged( HXUIOBJ hObjSource, XUINotifySelChanged* pNotifySelChangedData, BOOL& bHandled) { if (hObjSource == m_pTexturePacksList->m_hObj) { UpdateTexturePackDescription(pNotifySelChangedData->iItem); if (m_bSetup && !m_texturePackDescDisplayed) { XUITimeline* timeline; XUINamedFrame *startFrame, *endFrame; GetTimeline(&timeline); startFrame = timeline->FindNamedFrame(L"SlideOut"); endFrame = timeline->FindNamedFrame(L"SlideOutEnd"); timeline->Play(startFrame->m_dwFrame, startFrame->m_dwFrame, endFrame->m_dwFrame, FALSE, FALSE); m_texturePackDescDisplayed = true; } } return S_OK; } HRESULT CScene_LoadGameSettings::OnNotifyKillFocus( HXUIOBJ hObjSource, XUINotifyFocus* pNotifyFocusData, BOOL& bHandled) { HXUIOBJ hSourceParent, hDestParent; XuiElementGetParent(hObjSource, &hSourceParent); XuiElementGetParent(pNotifyFocusData->hObjOther, &hDestParent); if (hSourceParent != hDestParent && pNotifyFocusData->hObjOther != m_pTexturePacksList->m_hObj && hSourceParent == m_pTexturePacksList->m_hObj) { m_pTexturePacksList->SetCurSel(m_currentTexturePackIndex); m_pTexturePacksList->SetTopItem( m_currentTexturePackIndex); // scroll the item into view if it's // not visible } else if (!m_texturePackDescDisplayed && pNotifyFocusData->hObjOther == m_pTexturePacksList->m_hObj) { int texturePacksCount = Minecraft::GetInstance()->skins->getTexturePackCount(); if (texturePacksCount == 1) { XUITimeline* timeline; XUINamedFrame *startFrame, *endFrame; GetTimeline(&timeline); startFrame = timeline->FindNamedFrame(L"SlideOut"); endFrame = timeline->FindNamedFrame(L"SlideOutEnd"); timeline->Play(startFrame->m_dwFrame, startFrame->m_dwFrame, endFrame->m_dwFrame, FALSE, FALSE); m_texturePackDescDisplayed = true; } } return S_OK; } void CScene_LoadGameSettings::UpdateTexturePackDescription(int index) { int iTexPackId = m_pTexturePacksList->GetData(index).iData; TexturePack* tp = Minecraft::GetInstance()->skins->getTexturePackById(iTexPackId); if (tp == NULL) { // this is probably a texture pack icon added from TMS unsigned int dwBytes = 0; unsigned int dwFileBytes = 0; std::uint8_t* pbData = NULL; std::uint8_t* pbFileData = NULL; CXuiCtrl4JList::LIST_ITEM_INFO ListItem; // get the current index of the list, and then get the data ListItem = m_pTexturePacksList->GetData(index); app.GetTPD(ListItem.iData, &pbData, &dwBytes); app.GetFileFromTPD(eTPDFileType_Loc, pbData, dwBytes, &pbFileData, &dwFileBytes); if (dwFileBytes > 0 && pbFileData) { StringTable* pStringTable = new StringTable(pbFileData, dwFileBytes); m_texturePackTitle.SetText( pStringTable->getString(L"IDS_DISPLAY_NAME")); m_texturePackDescription.SetText( pStringTable->getString(L"IDS_TP_DESCRIPTION")); } app.GetFileFromTPD(eTPDFileType_Icon, pbData, dwBytes, &pbFileData, &dwFileBytes); if (dwFileBytes > 0 && pbFileData) { XuiCreateTextureBrushFromMemory(pbFileData, dwFileBytes, &m_hTexturePackIconBrush); m_texturePackIcon->UseBrush(m_hTexturePackIconBrush); } app.GetFileFromTPD(eTPDFileType_Comparison, pbData, dwBytes, &pbFileData, &dwFileBytes); if (dwFileBytes > 0 && pbFileData) { XuiCreateTextureBrushFromMemory(pbFileData, dwFileBytes, &m_hTexturePackComparisonBrush); m_texturePackComparison->UseBrush(m_hTexturePackComparisonBrush); } else { m_texturePackComparison->UseBrush(NULL); } } else { m_texturePackTitle.SetText(tp->getName().c_str()); m_texturePackDescription.SetText(tp->getDesc1().c_str()); std::uint32_t imageBytes = 0; std::uint8_t* imageData = tp->getPackIcon(imageBytes); if (imageBytes > 0 && imageData) { XuiCreateTextureBrushFromMemory(imageData, imageBytes, &m_hTexturePackIconBrush); m_texturePackIcon->UseBrush(m_hTexturePackIconBrush); } else { m_texturePackIcon->UseBrush(NULL); } imageData = tp->getPackComparison(imageBytes); if (imageBytes > 0 && imageData) { XuiCreateTextureBrushFromMemory(imageData, imageBytes, &m_hTexturePackComparisonBrush); m_texturePackComparison->UseBrush(m_hTexturePackComparisonBrush); } else { m_texturePackComparison->UseBrush(NULL); } } } void CScene_LoadGameSettings::ClearTexturePackDescription() { m_texturePackTitle.SetText(L" "); m_texturePackDescription.SetText(L" "); m_texturePackComparison->UseBrush(NULL); m_texturePackIcon->UseBrush(NULL); } void CScene_LoadGameSettings::UpdateCurrentTexturePack() { m_currentTexturePackIndex = m_pTexturePacksList->GetCurSel(); int iTexPackId = m_pTexturePacksList->GetData(m_currentTexturePackIndex).iData; TexturePack* tp = Minecraft::GetInstance()->skins->getTexturePackById(iTexPackId); // if the texture pack is null, you don't have it yet if (tp == NULL) { // Upsell CXuiCtrl4JList::LIST_ITEM_INFO ListItem; // get the current index of the list, and then get the data ListItem = m_pTexturePacksList->GetData(m_currentTexturePackIndex); // upsell the texture pack // tell sentient about the upsell of the full version of the skin pack ULONGLONG ullOfferID_Full; app.GetDLCFullOfferIDForPackID(ListItem.iData, &ullOfferID_Full); TelemetryManager->RecordUpsellPresented(ProfileManager.GetPrimaryPad(), eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF); unsigned int 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_LoadGameSettings::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_LoadGameSettings::TexturePackDialogReturned, this, app.GetStringTable()); } // do set the texture pack id, and on the user pressing create world, // check they have it m_MoreOptionsParams.dwTexturePack = ListItem.iData; return; } else { m_MoreOptionsParams.dwTexturePack = tp->getId(); } } HRESULT CScene_LoadGameSettings::OnDestroy() { if (m_hXuiBrush) { XuiDestroyBrush(m_hXuiBrush); } // 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; } void CScene_LoadGameSettings::LoadLevelGen(LevelGenerationOptions* levelGen) { bool isClientSide = ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()) && m_MoreOptionsParams.bOnlineGame; // 4J Stu - If we only have one controller connected, then don't show the // sign-in UI again int 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()) { // Check if user-created content is allowed, as we cannot play // multiplayer if it's not bool noUGC = false; bool pccAllowed = true; bool pccFriendsAllowed = true; ProfileManager.AllowedPlayerCreatedContent( ProfileManager.GetPrimaryPad(), false, &pccAllowed, &pccFriendsAllowed); if (!pccAllowed && !pccFriendsAllowed) noUGC = true; if (isClientSide && noUGC) { SetShow(TRUE); m_bIgnoreInput = false; unsigned int uiIDA[1]; uiIDA[0] = IDS_CONFIRM_OK; StorageManager.RequestMessageBox( IDS_FAILED_TO_CREATE_GAME_TITLE, IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_CREATE, uiIDA, 1, ProfileManager.GetPrimaryPad(), NULL, NULL, app.GetStringTable()); return; } } unsigned int dwLocalUsersMask = 0; dwLocalUsersMask |= CGameNetworkManager::GetLocalPlayerMask(ProfileManager.GetPrimaryPad()); // Load data from disc // File saveFile( L"Tutorial\\Tutorial" ); // LoadSaveFromDisk(&saveFile); StorageManager.ResetSaveData(); // Make our next save default to the name of the level StorageManager.SetSaveTitle(levelGen->getDefaultSaveName().c_str()); bool isPrivate = (app.GetGameSettings(m_iPad, eGameSetting_InviteOnly) > 0) ? true : false; g_NetworkManager.HostGame(dwLocalUsersMask, isClientSide, isPrivate, MINECRAFT_NET_MAX_PLAYERS, 0); NetworkGameInitData* param = new NetworkGameInitData(); param->seed = 0; param->saveData = NULL; param->levelGen = levelGen; if (levelGen->requiresTexturePack()) { param->texturePackId = levelGen->getRequiredTexturePackId(); Minecraft* pMinecraft = Minecraft::GetInstance(); pMinecraft->skins->selectTexturePackById(param->texturePackId); // pMinecraft->skins->updateUI(); } app.SetGameHostOption(eGameHostOption_Difficulty, Minecraft::GetInstance()->options->difficulty); app.SetGameHostOption( eGameHostOption_FriendsOfFriends, app.GetGameSettings(m_iPad, eGameSetting_FriendsOfFriends)); app.SetGameHostOption( eGameHostOption_Gamertags, app.GetGameSettings(m_iPad, eGameSetting_GamertagsVisible)); app.SetGameHostOption( eGameHostOption_BedrockFog, app.GetGameSettings(m_iPad, eGameSetting_BedrockFog) ? 1 : 0); // 4J-JEV: Fix for: // TU12: Content: Gameplay: New "Mass Effect World" remembers and uses the // settings of another - lately created - World. app.SetGameHostOption(eGameHostOption_LevelType, m_MoreOptionsParams.bFlatWorld); app.SetGameHostOption(eGameHostOption_Structures, m_MoreOptionsParams.bStructures); app.SetGameHostOption(eGameHostOption_BonusChest, m_MoreOptionsParams.bBonusChest); app.SetGameHostOption(eGameHostOption_PvP, m_MoreOptionsParams.bPVP); app.SetGameHostOption(eGameHostOption_TrustPlayers, m_MoreOptionsParams.bTrust); app.SetGameHostOption(eGameHostOption_FireSpreads, m_MoreOptionsParams.bFireSpreads); app.SetGameHostOption(eGameHostOption_TNT, m_MoreOptionsParams.bTNT); app.SetGameHostOption(eGameHostOption_HostCanFly, m_MoreOptionsParams.bHostPrivileges); app.SetGameHostOption(eGameHostOption_HostCanChangeHunger, m_MoreOptionsParams.bHostPrivileges); app.SetGameHostOption(eGameHostOption_HostCanBeInvisible, m_MoreOptionsParams.bHostPrivileges); // flag if the user wants to reset the Nether to force a Fortress with // netherwart etc. app.SetResetNether(m_MoreOptionsParams.bResetNether); // clear out the app's terrain features list app.ClearTerrainFeaturePosition(); app.SetGameHostOption(eGameHostOption_GameType, m_bGameModeSurvival ? GameType::SURVIVAL->getId() : GameType::CREATIVE->getId()); param->settings = app.GetGameHostOption(eGameHostOption_All); LoadingInputParams* loadingParams = new LoadingInputParams(); loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc; loadingParams->lpParam = param; // Reset the autosave timer app.SetAutosaveTimerTime(); 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); } HRESULT CScene_LoadGameSettings::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 texture pack list and do again m_pTexturePacksList->RemoveAllData(); m_iTexturePacksNotInstalled = 0; } // this will send a CustomMessage_DLCMountingComplete when done return S_OK; } HRESULT CScene_LoadGameSettings::OnCustomMessage_DLCMountingComplete() { m_pTexturePacksList->SetSelectionChangedHandle(m_hObj); Minecraft* pMinecraft = Minecraft::GetInstance(); int texturePacksCount = pMinecraft->skins->getTexturePackCount(); CXuiCtrl4JList::LIST_ITEM_INFO ListInfo; HRESULT hr; for (unsigned int i = 0; i < texturePacksCount; ++i) { TexturePack* tp = pMinecraft->skins->getTexturePackByIndex(i); ZeroMemory(&ListInfo, sizeof(CXuiCtrl4JList::LIST_ITEM_INFO)); std::uint32_t imageBytes = 0; std::uint8_t* imageData = tp->getPackIcon(imageBytes); if (imageBytes > 0 && imageData) { ListInfo.fEnabled = TRUE; hr = XuiCreateTextureBrushFromMemory(imageData, imageBytes, &ListInfo.hXuiBrush); DLCTexturePack* pDLCTexPack = (DLCTexturePack*)tp; if (pDLCTexPack) { int id = pDLCTexPack->getDLCParentPackId(); if (id == 0) { // default texture pack - should come first ListInfo.iSortIndex = 0x0FFFFFFF; } else { ListInfo.iSortIndex = id; ListInfo.iData = id; } } m_pTexturePacksList->AddData(ListInfo, 0, CXuiCtrl4JList::eSortList_Index); } } m_currentTexturePackIndex = m_pTexturePacksList->GetIndexByUserData( m_MoreOptionsParams.dwTexturePack); m_pTexturePacksList->SetCurSel(m_currentTexturePackIndex); m_pTexturePacksList->SetTopItem( m_currentTexturePackIndex); // scroll the item into view if it's not // visible m_iTexturePacksNotInstalled = 0; // 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; 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); if (m_iConfigA != NULL) { delete m_iConfigA; } 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; } } } UpdateTexturePackDescription(m_currentTexturePackIndex); m_bIgnoreInput = false; app.m_dlcManager.checkForCorruptDLCAndAlert(); return S_OK; } int CScene_LoadGameSettings::TexturePackDialogReturned( void* pParam, int iPad, C4JStorage::EMessageResult result) { CScene_LoadGameSettings* pClass = (CScene_LoadGameSettings*)pParam; #ifdef _XBOX pClass->m_currentTexturePackIndex = pClass->m_pTexturePacksList->GetCurSel(); // 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]; CXuiCtrl4JList::LIST_ITEM_INFO ListItem; // get the current index of the list, and then get the data ListItem = pClass->m_pTexturePacksList->GetData( pClass->m_currentTexturePackIndex); app.GetDLCFullOfferIDForPackID(ListItem.iData, &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); } } } #endif pClass->m_bIgnoreInput = false; return 0; } HRESULT CScene_LoadGameSettings::OnNavReturn(HXUIOBJ hObj, BOOL& rfHandled) { // update the tooltips int iRB = -1; #ifdef _XBOX #endif CXuiSceneBase::SetTooltips(DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, -1, -1, -1, -1, -1, iRB); return S_OK; }