4jcraft/Minecraft.Client/Platform/Common/XUI/XUI_MultiGameJoinLoad.cpp

2741 lines
101 KiB
C++

#include "../../Minecraft.World/Platform/stdafx.h"
#include <xuiresource.h>
#include <xuiapp.h>
#include <thread>
#include <chrono>
#include <assert.h>
#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.Client/Rendering/EntityRenderers/ProgressRenderer.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 "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 "../../Minecraft.Client/MinecraftServer.h"
#include "../../Minecraft.Client/GameState/Options.h"
#include "../GameRules/LevelGenerationOptions.h"
#include "../../Minecraft.Client/Textures/Packs/TexturePackRepository.h"
#include "../../Minecraft.Client/Textures/Packs/TexturePack.h"
#include "../../Minecraft.World/Level/Storage/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));
constexpr int 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());
std::uint32_t imageBytes = 0;
std::uint8_t* imageData = tp->getPackIcon(imageBytes);
HXUIBRUSH hXuiBrush;
if (imageBytes > 0 && imageData) {
XuiCreateTextureBrushFromMemory(imageData, imageBytes,
&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++) {
std::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;
int 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);
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_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
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,
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) {
int 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
int nIndex = m_pSavesList->GetCurSel();
m_iChangingSaveGameInfoIndex =
m_pSavesList->GetData(nIndex).iIndex;
unsigned int 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
unsigned int 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()) {
unsigned int 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
unsigned int 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;
}
int 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() != FALSE;
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;
std::uint32_t imageBytes = 0;
std::uint8_t* imageData = NULL;
if (tp == NULL) {
unsigned int dwBytes = 0;
std::uint8_t* pbData = NULL;
app.GetTPD(sessionInfo->data.texturePackParentId, &pbData,
&dwBytes);
// is it in the tpd data ?
unsigned int tpdImageBytes = 0;
app.GetFileFromTPD(eTPDFileType_Icon, pbData, dwBytes,
&imageData, &tpdImageBytes);
imageBytes = static_cast<std::uint32_t>(tpdImageBytes);
if (imageBytes > 0 && imageData) {
hr = XuiCreateTextureBrushFromMemory(
imageData, imageBytes, &hXuiBrush);
m_pGamesList->UpdateGraphic(sessionIndex, hXuiBrush);
}
} else {
imageData = tp->getPackIcon(imageBytes);
if (imageBytes > 0 && imageData) {
hr = XuiCreateTextureBrushFromMemory(
imageData, imageBytes, &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;
std::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) {
unsigned int dwBytes = 0;
std::uint8_t* 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 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())
{
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_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)) {
unsigned int 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 = 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 = 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();
std::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;
}
std::this_thread::sleep_for(std::chrono::milliseconds(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
unsigned int 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
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_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
unsigned int 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);
unsigned int 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
constexpr int 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;
unsigned int 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;
}