4jcraft/Minecraft.Client/Platform/Common/UI/UIScene_LoadOrJoinMenu.cpp

3849 lines
150 KiB
C++

#include <thread>
#include <chrono>
#include "../../Minecraft.World/Platform/stdafx.h"
#include "UI.h"
#include "UIScene_LoadOrJoinMenu.h"
#include "../../Minecraft.World/Util/StringHelpers.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.item.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.chunk.storage.h"
#include "../../Minecraft.World/IO/Files/ConsoleSaveFile.h"
#include "../../Minecraft.World/IO/Files/ConsoleSaveFileOriginal.h"
#include "../../Minecraft.World/IO/Files/ConsoleSaveFileSplit.h"
#include "../../Minecraft.World/Util/PortableFileIO.h"
#include "../../Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.h"
#include "../../Minecraft.Client/MinecraftServer.h"
#include "../../Minecraft.Client/Textures/Packs/TexturePackRepository.h"
#include "../../Minecraft.Client/Textures/Packs/TexturePack.h"
#include "../Network/SessionInfo.h"
#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__)
#include "../Network/Sony/SonyHttp.h"
#include "../Network/Sony/SonyRemoteStorage.h"
#endif
#if defined(__ORBIS__) || defined(__PSVITA__)
#include <ces.h>
#endif
#ifdef __PSVITA__
#include "message_dialog.h"
#endif
#ifdef SONY_REMOTE_STORAGE_DOWNLOAD
unsigned long UIScene_LoadOrJoinMenu::m_ulFileSize = 0L;
std::wstring UIScene_LoadOrJoinMenu::m_wstrStageText = L"";
bool UIScene_LoadOrJoinMenu::m_bSaveTransferRunning = false;
#endif
#define JOIN_LOAD_ONLINE_TIMER_ID 0
#define JOIN_LOAD_ONLINE_TIMER_TIME 100
#ifdef _XBOX
#define CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID 3
#define CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME 50
#endif
#ifdef _XBOX_ONE
UIScene_LoadOrJoinMenu::ESaveTransferFiles
UIScene_LoadOrJoinMenu::s_eSaveTransferFile;
unsigned long UIScene_LoadOrJoinMenu::s_ulFileSize = 0L;
byteArray UIScene_LoadOrJoinMenu::s_transferData = byteArray();
std::wstring UIScene_LoadOrJoinMenu::m_wstrStageText = L"";
#ifdef _DEBUG_MENUS_ENABLED
C4JStorage::SAVETRANSFER_FILE_DETAILS
UIScene_LoadOrJoinMenu::m_debugTransferDetails;
#endif
#endif
namespace {
int LoadOrJoinThumbnailReturnedThunk(void* lpParam, std::uint8_t* thumbnailData,
unsigned int thumbnailBytes) {
return UIScene_LoadOrJoinMenu::LoadSaveDataThumbnailReturned(
lpParam, thumbnailData, thumbnailBytes);
}
} // namespace
int UIScene_LoadOrJoinMenu::LoadSaveDataThumbnailReturned(
void* lpParam, std::uint8_t* pbThumbnail, unsigned int dwThumbnailBytes) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)lpParam;
app.DebugPrintf("Received data for save thumbnail\n");
if (pbThumbnail && dwThumbnailBytes) {
pClass->m_saveDetails[pClass->m_iRequestingThumbnailId]
.pbThumbnailData = new std::uint8_t[dwThumbnailBytes];
memcpy(pClass->m_saveDetails[pClass->m_iRequestingThumbnailId]
.pbThumbnailData,
pbThumbnail, dwThumbnailBytes);
pClass->m_saveDetails[pClass->m_iRequestingThumbnailId]
.dwThumbnailSize = dwThumbnailBytes;
} else {
pClass->m_saveDetails[pClass->m_iRequestingThumbnailId]
.pbThumbnailData = NULL;
pClass->m_saveDetails[pClass->m_iRequestingThumbnailId]
.dwThumbnailSize = 0;
app.DebugPrintf("Save thumbnail data is NULL, or has size 0\n");
}
pClass->m_bSaveThumbnailReady = true;
return 0;
}
int UIScene_LoadOrJoinMenu::LoadSaveCallback(void* lpParam, bool bRes) {
// UIScene_LoadOrJoinMenu *pClass= (UIScene_LoadOrJoinMenu *)lpParam;
// Get the save data now
if (bRes) {
app.DebugPrintf("Loaded save OK\n");
}
return 0;
}
UIScene_LoadOrJoinMenu::UIScene_LoadOrJoinMenu(int iPad, void* initData,
UILayer* parentLayer)
: UIScene(iPad, parentLayer) {
// Setup all the Iggy references we need for this scene
initialiseMovie();
app.SetLiveLinkRequired(true);
m_iRequestingThumbnailId = 0;
m_iSaveInfoC = 0;
m_bIgnoreInput = false;
m_bShowingPartyGamesOnly = false;
m_bInParty = false;
m_currentSessions = NULL;
m_iState = e_SavesIdle;
// m_bRetrievingSaveInfo=false;
m_buttonListSaves.init(eControl_SavesList);
m_buttonListGames.init(eControl_GamesList);
m_labelSavesListTitle.init(IDS_START_GAME);
m_labelJoinListTitle.init(IDS_JOIN_GAME);
m_labelNoGames.init(IDS_NO_GAMES_FOUND);
m_labelNoGames.setVisible(false);
m_controlSavesTimer.setVisible(true);
m_controlJoinTimer.setVisible(true);
#if defined(_XBOX_ONE) || defined(__ORBIS__)
m_spaceIndicatorSaves.init(L"", eControl_SpaceIndicator, 0,
(4LL * 1024LL * 1024LL * 1024LL));
#endif
m_bUpdateSaveSize = false;
m_bAllLoaded = false;
m_bRetrievingSaveThumbnails = false;
m_bSaveThumbnailReady = false;
m_bExitScene = false;
m_pSaveDetails = NULL;
m_bSavesDisplayed = false;
m_saveDetails = NULL;
m_iSaveDetailsCount = 0;
m_iTexturePacksNotInstalled = 0;
m_bCopying = false;
m_bCopyingCancelled = false;
#ifndef _XBOX_ONE
m_bSaveTransferCancelled = false;
m_bSaveTransferInProgress = false;
#endif
m_eAction = eAction_None;
m_bMultiplayerAllowed = ProfileManager.IsSignedInLive(m_iPad) &&
ProfileManager.AllowedToPlayMultiplayer(m_iPad);
#ifdef _XBOX_ONE
// 4J-PB - in order to buy the skin packs & texture packs, we need the
// signed offer ids for them, which we get in the availability info we need
// to retrieve this info though, so do it here
app.AddDLCRequest(e_Marketplace_Content); // content is skin packs, texture
// packs and mash-up packs
#endif
int iLB = -1;
#ifdef _XBOX
XPARTY_USER_LIST partyList;
if ((XPartyGetUserList(&partyList) != XPARTY_E_NOT_IN_PARTY) &&
(partyList.dwUserCount > 1)) {
m_bInParty = true;
} else {
m_bInParty = false;
}
#endif
#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) || \
defined(_DURANGO)
// Always clear the saves when we enter this menu
StorageManager.ClearSavesInfo();
#endif
// 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 || app.DLCInstallPending()) {
// 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 = true;
} else {
Initialise();
}
#ifdef __PSVITA__
if (CGameNetworkManager::usingAdhocMode() &&
SQRNetworkManager_AdHoc_Vita::GetAdhocStatus()) {
g_NetworkManager
.startAdhocMatching(); // create the client matching context and
// clear out the friends list
}
#endif
UpdateGamesList();
g_NetworkManager.SetSessionsUpdatedCallback(&UpdateGamesListCallback, this);
m_initData = new JoinMenuInitData();
// 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 - Only Xbox will not have trial DLC patched into the game
#ifdef _XBOX
// 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();
for (unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i) {
bTexturePackAlreadyListed = false;
#if defined(__PS3__) || defined(__ORBIS__)
char* pchDLCName = app.GetDLCInfoTextures(i);
pDLCInfo = app.GetDLCInfo(pchDLCName);
#else
ULONGLONG ull = app.GetDLCInfoTexturesFullOffer(i);
pDLCInfo = app.GetDLCInfoForFullOfferID(ull);
#endif
for (unsigned int i = 0; i < texturePacksCount; ++i) {
TexturePack* tp = pMinecraft->skins->getTexturePackByIndex(i);
if (pDLCInfo && 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;
#if defined(__PS3__) || defined(__ORBIS__)
char* pchDLCName = app.GetDLCInfoTextures(i);
pDLCInfo = app.GetDLCInfo(pchDLCName);
#else
ULONGLONG ull = app.GetDLCInfoTexturesFullOffer(i);
pDLCInfo = app.GetDLCInfoForFullOfferID(ull);
#endif
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;
}
}
}
addTimer(CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID,
CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME);
#endif
#ifdef SONY_REMOTE_STORAGE_DOWNLOAD
m_eSaveTransferState = eSaveTransfer_Idle;
#endif
}
UIScene_LoadOrJoinMenu::~UIScene_LoadOrJoinMenu() {
g_NetworkManager.SetSessionsUpdatedCallback(NULL, NULL);
app.SetLiveLinkRequired(false);
if (m_currentSessions) {
for (AUTO_VAR(it, m_currentSessions->begin());
it < m_currentSessions->end(); ++it) {
delete (*it);
}
}
#if TO_BE_IMPLEMENTED
// Reset the background downloading, in case we changed it by attempting to
// download a texture pack
XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_AUTO);
#endif
if (m_saveDetails) {
for (int i = 0; i < m_iSaveDetailsCount; ++i) {
delete m_saveDetails[i].pbThumbnailData;
}
delete[] m_saveDetails;
}
}
void UIScene_LoadOrJoinMenu::updateTooltips() {
#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__
if (m_eSaveTransferState != eSaveTransfer_Idle) {
// we're in a full screen progress for the save download here, so don't
// change the tooltips
return;
}
#endif
// 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;
int iLB = -1;
int iX = -1;
if (DoesGamesListHaveFocus() && m_buttonListGames.getItemCount() > 0) {
iY = IDS_TOOLTIPS_VIEW_GAMERCARD;
} else if (DoesSavesListHaveFocus()) {
if ((m_iDefaultButtonsC > 0) &&
(m_iSaveListIndex >= m_iDefaultButtonsC)) {
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 (m_bInParty) {
if (m_bShowingPartyGamesOnly)
iLB = IDS_TOOLTIPS_ALL_GAMES;
else
iLB = IDS_TOOLTIPS_PARTY_GAMES;
}
#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__)
if (m_iPad == ProfileManager.GetPrimaryPad())
iY = IDS_TOOLTIPS_GAME_INVITES;
#endif
if (ProfileManager.IsFullVersion() == false) {
iRB = -1;
} else if (StorageManager.GetSaveDisabled()) {
#ifdef _XBOX
iX = IDS_TOOLTIPS_SELECTDEVICE;
#endif
} else {
#if defined _XBOX_ONE
if (ProfileManager.IsSignedInLive(m_iPad)) {
// Is there a save from 360 on TMS?
iX = IDS_TOOLTIPS_SAVETRANSFER_DOWNLOAD;
}
#elif defined SONY_REMOTE_STORAGE_DOWNLOAD
// Is there a save from PS3 or PSVita available?
// Sony asked that this be displayed at all times so users are aware of
// the functionality. We'll display some text when there's no save
// available
// if(app.getRemoteStorage()->saveIsAvailable())
{
bool bSignedInLive = ProfileManager.IsSignedInLive(m_iPad);
if (bSignedInLive) {
iX = IDS_TOOLTIPS_SAVETRANSFER_DOWNLOAD;
}
}
#else
iX = IDS_TOOLTIPS_CHANGEDEVICE;
#endif
}
ui.SetTooltips(DEFAULT_XUI_MENU_USER, IDS_TOOLTIPS_SELECT,
IDS_TOOLTIPS_BACK, iX, iY, -1, -1, iLB, iRB);
}
//
void UIScene_LoadOrJoinMenu::Initialise() {
m_iSaveListIndex = 0;
m_iGameListIndex = 0;
m_iDefaultButtonsC = 0;
m_iMashUpButtonsC = 0;
// Check if we're in the trial version
if (ProfileManager.IsFullVersion() == false) {
AddDefaultButtons();
#if TO_BE_IMPLEMENTED
m_pSavesList->SetCurSelVisible(0);
#endif
} else if (StorageManager.GetSaveDisabled()) {
#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__)
GetSaveInfo();
#else
#if TO_BE_IMPLEMENTED
if (StorageManager.GetSaveDeviceSelected(m_iPad))
#endif
{
// saving is disabled, but we should still be able to load from a
// selected save device
GetSaveInfo();
}
#if TO_BE_IMPLEMENTED
else {
AddDefaultButtons();
m_controlSavesTimer.setVisible(false);
}
#endif
#endif // __PS3__ || __ORBIS
} 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();
GetSaveInfo();
}
m_bIgnoreInput = false;
app.m_dlcManager.checkForCorruptDLCAndAlert();
}
void UIScene_LoadOrJoinMenu::updateComponents() {
m_parentLayer->showComponent(m_iPad, eUIComponent_Panorama, true);
m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, true);
}
void UIScene_LoadOrJoinMenu::handleDestroy() {
#ifdef __PSVITA__
app.DebugPrintf("missing InputManager.DestroyKeyboard on Vita !!!!!!\n");
#endif
// shut down the keyboard if it is displayed
#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO)
InputManager.DestroyKeyboard();
#endif
}
void UIScene_LoadOrJoinMenu::handleGainFocus(bool navBack) {
UIScene::handleGainFocus(navBack);
updateTooltips();
// Add load online timer
addTimer(JOIN_LOAD_ONLINE_TIMER_ID, JOIN_LOAD_ONLINE_TIMER_TIME);
if (navBack) {
app.SetLiveLinkRequired(true);
m_bMultiplayerAllowed = ProfileManager.IsSignedInLive(m_iPad) &&
ProfileManager.AllowedToPlayMultiplayer(m_iPad);
// re-enable button presses
m_bIgnoreInput = false;
// 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_buttonListSaves.clearList();
m_controlSavesTimer.setVisible(true);
}
if (m_bMultiplayerAllowed) {
#if TO_BE_IMPLEMENTED
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();
}
#endif
} else {
m_buttonListGames.clearList();
m_controlJoinTimer.setVisible(true);
m_labelNoGames.setVisible(false);
#if TO_BE_IMPLEMENTED
m_SavesList.InitFocus(m_iPad);
#endif
}
// are we back here because of a delete of a corrupt save?
if (app.GetCorruptSaveDeleted()) {
// wipe the list and repopulate it
m_iState = e_SavesRepopulateAfterDelete;
app.SetCorruptSaveDeleted(false);
}
}
}
void UIScene_LoadOrJoinMenu::handleLoseFocus() {
// Kill load online timer
killTimer(JOIN_LOAD_ONLINE_TIMER_ID);
}
std::wstring UIScene_LoadOrJoinMenu::getMoviePath() {
return L"LoadOrJoinMenu";
}
void UIScene_LoadOrJoinMenu::tick() {
UIScene::tick();
#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || \
defined _WINDOWS64 || defined __PSVITA__)
if (m_bExitScene) // navigate forward or back
{
if (!m_bRetrievingSaveThumbnails) {
// need to wait for any callback retrieving thumbnail to complete
navigateBack();
}
}
// Stop loading thumbnails if we navigate forwards
if (hasFocus(m_iPad)) {
#ifdef SONY_REMOTE_STORAGE_DOWNLOAD
// if the loadOrJoin menu has focus again, we can clear the saveTransfer
// flag now. Added so we can delay the ehternet disconnect till it's
// cleaned up
if (m_eSaveTransferState == eSaveTransfer_Idle)
m_bSaveTransferRunning = false;
#endif
#if defined(_XBOX_ONE) || defined(__ORBIS__)
if (m_bUpdateSaveSize) {
if ((m_iDefaultButtonsC > 0) &&
(m_iSaveListIndex >= m_iDefaultButtonsC)) {
m_spaceIndicatorSaves.selectSave(m_iSaveListIndex -
m_iDefaultButtonsC);
} else {
m_spaceIndicatorSaves.selectSave(-1);
}
m_bUpdateSaveSize = false;
}
#endif
// Display the saves if we have them
if (!m_bSavesDisplayed) {
m_pSaveDetails = StorageManager.ReturnSavesInfo();
if (m_pSaveDetails != NULL) {
// CD - Fix - Adding define for ORBIS/XBOXONE
#if defined(_XBOX_ONE) || defined(__ORBIS__)
m_spaceIndicatorSaves.reset();
#endif
AddDefaultButtons();
m_bSavesDisplayed = true;
UpdateGamesList();
if (m_saveDetails != NULL) {
for (unsigned int i = 0; i < m_iSaveDetailsCount; ++i) {
if (m_saveDetails[i].pbThumbnailData != NULL) {
delete m_saveDetails[i].pbThumbnailData;
}
}
delete m_saveDetails;
}
m_saveDetails = new SaveListDetails[m_pSaveDetails->iSaveC];
m_iSaveDetailsCount = m_pSaveDetails->iSaveC;
for (unsigned int i = 0; i < m_pSaveDetails->iSaveC; ++i) {
#if defined(_XBOX_ONE)
m_spaceIndicatorSaves.addSave(
m_pSaveDetails->SaveInfoA[i].totalSize);
#elif defined(__ORBIS__)
m_spaceIndicatorSaves.addSave(
m_pSaveDetails->SaveInfoA[i].blocksUsed * (32 * 1024));
#endif
#ifdef _DURANGO
m_buttonListSaves.addItem(
m_pSaveDetails->SaveInfoA[i].UTF16SaveTitle, L"");
m_saveDetails[i].saveId = i;
memcpy(m_saveDetails[i].UTF16SaveName,
m_pSaveDetails->SaveInfoA[i].UTF16SaveTitle, 128);
memcpy(m_saveDetails[i].UTF16SaveFilename,
m_pSaveDetails->SaveInfoA[i].UTF16SaveFilename,
MAX_SAVEFILENAME_LENGTH);
#else
m_buttonListSaves.addItem(
m_pSaveDetails->SaveInfoA[i].UTF8SaveTitle, L"");
m_saveDetails[i].saveId = i;
memcpy(m_saveDetails[i].UTF8SaveName,
m_pSaveDetails->SaveInfoA[i].UTF8SaveTitle, 128);
memcpy(m_saveDetails[i].UTF8SaveFilename,
m_pSaveDetails->SaveInfoA[i].UTF8SaveFilename,
MAX_SAVEFILENAME_LENGTH);
#endif
}
m_controlSavesTimer.setVisible(false);
// set focus on the first button
}
}
if (!m_bExitScene && m_bSavesDisplayed &&
!m_bRetrievingSaveThumbnails && !m_bAllLoaded) {
if (m_iRequestingThumbnailId <
(m_buttonListSaves.getItemCount() - m_iDefaultButtonsC)) {
m_bRetrievingSaveThumbnails = true;
app.DebugPrintf("Requesting the first thumbnail\n");
// set the save to load
PSAVE_DETAILS pSaveDetails = StorageManager.ReturnSavesInfo();
C4JStorage::ESaveGameState eLoadStatus =
StorageManager.LoadSaveDataThumbnail(
&pSaveDetails->SaveInfoA[(int)m_iRequestingThumbnailId],
&LoadOrJoinThumbnailReturnedThunk, this);
if (eLoadStatus != C4JStorage::ESaveGame_GetSaveThumbnail) {
// something went wrong
m_bRetrievingSaveThumbnails = false;
m_bAllLoaded = true;
}
}
} else if (m_bSavesDisplayed && m_bSaveThumbnailReady) {
m_bSaveThumbnailReady = false;
// check we're not waiting to exit the scene
if (!m_bExitScene) {
// convert to utf16
std::uint16_t u16Message[MAX_SAVEFILENAME_LENGTH];
#ifdef _DURANGO
// Already utf16 on durango
memcpy(
u16Message,
m_saveDetails[m_iRequestingThumbnailId].UTF16SaveFilename,
MAX_SAVEFILENAME_LENGTH);
#elif defined(_WINDOWS64)
int result = ::MultiByteToWideChar(
CP_UTF8, // convert from UTF-8
MB_ERR_INVALID_CHARS, // error on invalid chars
m_saveDetails[m_iRequestingThumbnailId]
.UTF8SaveFilename, // source UTF-8 string
MAX_SAVEFILENAME_LENGTH, // total length of source UTF-8
// string,
// in CHAR's (= bytes), including end-of-string \0
(wchar_t*)u16Message, // destination buffer
MAX_SAVEFILENAME_LENGTH // size of destination buffer, in
// WCHAR's
);
#else
#ifdef __PS3
size_t srcmax, dstmax;
#else
std::uint32_t srcmax, dstmax;
std::uint32_t srclen, dstlen;
#endif
srcmax = MAX_SAVEFILENAME_LENGTH;
dstmax = MAX_SAVEFILENAME_LENGTH;
#if defined(__PS3__)
L10nResult lres = UTF8stoUTF16s(
(std::uint8_t*)m_saveDetails[m_iRequestingThumbnailId]
.UTF8SaveFilename,
&srcmax, u16Message, &dstmax);
#else
SceCesUcsContext context;
sceCesUcsContextInit(&context);
sceCesUtf8StrToUtf16Str(
&context,
(std::uint8_t*)m_saveDetails[m_iRequestingThumbnailId]
.UTF8SaveFilename,
srcmax, &srclen, u16Message, dstmax, &dstlen);
#endif
#endif
if (m_saveDetails[m_iRequestingThumbnailId].pbThumbnailData) {
registerSubstitutionTexture(
(wchar_t*)u16Message,
m_saveDetails[m_iRequestingThumbnailId].pbThumbnailData,
m_saveDetails[m_iRequestingThumbnailId]
.dwThumbnailSize);
}
m_buttonListSaves.setTextureName(
m_iRequestingThumbnailId + m_iDefaultButtonsC,
(wchar_t*)u16Message);
++m_iRequestingThumbnailId;
if (m_iRequestingThumbnailId <
(m_buttonListSaves.getItemCount() - m_iDefaultButtonsC)) {
app.DebugPrintf("Requesting another thumbnail\n");
// set the save to load
PSAVE_DETAILS pSaveDetails =
StorageManager.ReturnSavesInfo();
C4JStorage::ESaveGameState eLoadStatus =
StorageManager.LoadSaveDataThumbnail(
&pSaveDetails
->SaveInfoA[(int)m_iRequestingThumbnailId],
&LoadOrJoinThumbnailReturnedThunk, this);
if (eLoadStatus != C4JStorage::ESaveGame_GetSaveThumbnail) {
// something went wrong
m_bRetrievingSaveThumbnails = false;
m_bAllLoaded = true;
}
} else {
m_bRetrievingSaveThumbnails = false;
m_bAllLoaded = true;
}
} else {
// stop retrieving thumbnails, and exit
m_bRetrievingSaveThumbnails = false;
}
}
}
switch (m_iState) {
case e_SavesIdle:
break;
case e_SavesRepopulate:
m_bIgnoreInput = false;
m_iState = e_SavesIdle;
m_bAllLoaded = false;
m_bRetrievingSaveThumbnails = false;
m_iRequestingThumbnailId = 0;
GetSaveInfo();
break;
case e_SavesRepopulateAfterMashupHide:
m_bIgnoreInput = false;
m_iRequestingThumbnailId = 0;
m_bAllLoaded = false;
m_bRetrievingSaveThumbnails = false;
m_bSavesDisplayed = false;
m_iSaveInfoC = 0;
m_buttonListSaves.clearList();
GetSaveInfo();
m_iState = e_SavesIdle;
break;
case e_SavesRepopulateAfterDelete:
case e_SavesRepopulateAfterTransferDownload:
m_bIgnoreInput = false;
m_iRequestingThumbnailId = 0;
m_bAllLoaded = false;
m_bRetrievingSaveThumbnails = false;
m_bSavesDisplayed = false;
m_iSaveInfoC = 0;
m_buttonListSaves.clearList();
StorageManager.ClearSavesInfo();
GetSaveInfo();
m_iState = e_SavesIdle;
break;
}
#else
if (!m_bSavesDisplayed) {
AddDefaultButtons();
m_bSavesDisplayed = true;
m_controlSavesTimer.setVisible(false);
}
#endif
#ifdef _XBOX_ONE
if (g_NetworkManager.ShouldMessageForFullSession()) {
unsigned int uiIDA[1];
uiIDA[0] = IDS_CONFIRM_OK;
ui.RequestErrorMessage(IDS_CONNECTION_FAILED, IDS_IN_PARTY_SESSION_FULL,
uiIDA, 1, ProfileManager.GetPrimaryPad());
}
#endif
// SAVE TRANSFERS
#ifdef __ORBIS__
// check the status of the PSPlus common dialog
switch (sceNpCommerceDialogUpdateStatus()) {
case SCE_COMMON_DIALOG_STATUS_FINISHED: {
SceNpCommerceDialogResult Result;
sceNpCommerceDialogGetResult(&Result);
sceNpCommerceDialogTerminate();
if (Result.authorized) {
// they just became a PSPlus member
ProfileManager.PsPlusUpdate(ProfileManager.GetPrimaryPad(),
&Result);
} else {
}
// 4J-JEV: Fix for PS4 #5148 - [ONLINE] If the user attempts to join
// a game when they do not have Playstation Plus, the title will
// lose all functionality.
m_bIgnoreInput = false;
} break;
default:
break;
}
#endif
}
void UIScene_LoadOrJoinMenu::GetSaveInfo() {
unsigned int uiSaveC = 0;
// This will return with the number retrieved in uiSaveC
if (app.DebugSettingsOn() && app.GetLoadSavesFromFolderEnabled()) {
#ifdef __ORBIS__
// We need to make sure this is non-null so that we have an idea of free
// space
m_pSaveDetails = StorageManager.ReturnSavesInfo();
if (m_pSaveDetails == NULL) {
C4JStorage::ESaveGameState eSGIStatus =
StorageManager.GetSavesInfo(m_iPad, NULL, this, "save");
}
#endif
uiSaveC = 0;
#ifdef _XBOX
File savesDir(L"GAME:\\Saves");
#else
File savesDir(L"Saves");
#endif
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;
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;
m_buttonListSaves.addItem(name, L"");
}
m_bSavesDisplayed = true;
m_bAllLoaded = true;
m_bIgnoreInput = false;
} else {
// clear the saves list
m_bSavesDisplayed =
false; // we're blocking the exit from this scene until complete
m_buttonListSaves.clearList();
m_iSaveInfoC = 0;
m_controlSavesTimer.setVisible(true);
m_pSaveDetails = StorageManager.ReturnSavesInfo();
if (m_pSaveDetails == NULL) {
C4JStorage::ESaveGameState eSGIStatus =
StorageManager.GetSavesInfo(m_iPad, NULL, this, (char*)"save");
}
#if TO_BE_IMPLEMENTED
if (eSGIStatus == C4JStorage::ESGIStatus_NoSaves) {
uiSaveC = 0;
m_controlSavesTimer.setVisible(false);
m_SavesList.SetEnable(TRUE);
}
#endif
}
return;
}
void UIScene_LoadOrJoinMenu::AddDefaultButtons() {
m_iDefaultButtonsC = 0;
m_iMashUpButtonsC = 0;
m_generators.clear();
m_buttonListSaves.addItem(app.GetString(IDS_CREATE_NEW_WORLD));
m_iDefaultButtonsC++;
int i = 0;
for (AUTO_VAR(it, app.getLevelGenerators()->begin());
it != app.getLevelGenerators()->end(); ++it) {
LevelGenerationOptions* levelGen = *it;
// retrieve the save icon from the texture pack, if there is one
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;
}
}
// 4J-JEV: For debug. Ignore worlds with no name.
LPCWSTR wstr = levelGen->getWorldName();
m_buttonListSaves.addItem(wstr);
m_generators.push_back(levelGen);
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);
if (imageBytes > 0 && imageData) {
wchar_t imageName[64];
swprintf(imageName, 64, L"tpack%08x", tp->getId());
registerSubstitutionTexture(imageName, imageData, imageBytes);
m_buttonListSaves.setTextureName(
m_buttonListSaves.getItemCount() - 1, imageName);
}
}
++i;
}
m_iDefaultButtonsC += i;
}
void UIScene_LoadOrJoinMenu::handleInput(int iPad, int key, bool repeat,
bool pressed, bool released,
bool& handled) {
if (m_bIgnoreInput) return;
// if we're retrieving save info, ignore key presses
if (!m_bSavesDisplayed) return;
ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released);
switch (key) {
case ACTION_MENU_CANCEL:
if (pressed) {
#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__)
m_bExitScene = true;
#else
navigateBack();
#endif
handled = true;
}
break;
case ACTION_MENU_X:
#if TO_BE_IMPLEMENTED
// 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);
ui.PlayUISFX(eSFX_Press);
#endif
// Save Transfer
#ifdef _XBOX_ONE
if (ProfileManager.IsSignedInLive(m_iPad)) {
UIScene_LoadOrJoinMenu::s_ulFileSize = 0;
LaunchSaveTransfer();
}
#endif
#ifdef SONY_REMOTE_STORAGE_DOWNLOAD
{
bool bSignedInLive = ProfileManager.IsSignedInLive(iPad);
if (bSignedInLive) {
LaunchSaveTransfer();
}
}
#endif
break;
case ACTION_MENU_Y:
#if defined(__PS3__) || defined(__PSVITA__) || defined(__ORBIS__)
m_eAction = eAction_ViewInvites;
if (pressed && iPad == ProfileManager.GetPrimaryPad()) {
#ifdef __ORBIS__
// Check if PSN is unavailable because of age restriction
int npAvailability = ProfileManager.getNPAvailability(iPad);
if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) {
unsigned int uiIDA[1];
uiIDA[0] = IDS_OK;
ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE,
IDS_CONTENT_RESTRICTION, uiIDA, 1,
iPad);
break;
}
#endif
// are we offline?
if (!ProfileManager.IsSignedInLive(iPad)) {
// get them to sign in to online
unsigned int uiIDA[2];
uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT;
uiIDA[1] = IDS_PRO_NOTONLINE_DECLINE;
ui.RequestAlertMessage(
IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA,
2, ProfileManager.GetPrimaryPad(),
&UIScene_LoadOrJoinMenu::MustSignInReturnedPSN, this);
} else {
#ifdef __ORBIS__
SQRNetworkManager_Orbis::RecvInviteGUI();
#elif defined __PSVITA__
SQRNetworkManager_Vita::RecvInviteGUI();
#else
int ret = sceNpBasicRecvMessageCustom(
SCE_NP_BASIC_MESSAGE_MAIN_TYPE_INVITE,
SCE_NP_BASIC_RECV_MESSAGE_OPTIONS_INCLUDE_BOOTABLE,
SYS_MEMORY_CONTAINER_ID_INVALID);
app.DebugPrintf(
"sceNpBasicRecvMessageCustom return %d ( %08x )\n", ret,
ret);
#endif
}
}
#elif defined(_DURANGO)
if (getControlFocus() == eControl_GamesList &&
m_buttonListGames.getItemCount() > 0) {
const int nIndex = m_buttonListGames.getCurrentSelection();
FriendSessionInfo* pSelectedSession =
m_currentSessions->at(nIndex);
PlayerUID uid = pSelectedSession->searchResult.m_playerXuids[0];
if (uid != INVALID_XUID)
ProfileManager.ShowProfileCard(
ProfileManager.GetLockedProfile(), uid);
ui.PlayUISFX(eSFX_Press);
}
#endif // __PS3__ || __ORBIS__
break;
case ACTION_MENU_RIGHT_SCROLL:
if (DoesSavesListHaveFocus()) {
// 4J-PB - check we are on a valid save
if ((m_iDefaultButtonsC != 0) &&
(m_iSaveListIndex >= m_iDefaultButtonsC)) {
m_bIgnoreInput = true;
// 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;
ui.RequestAlertMessage(
IDS_TOOLTIPS_DELETESAVE, IDS_TEXT_DELETE_SAVE,
uiIDA, 2, iPad,
&UIScene_LoadOrJoinMenu::DeleteSaveDialogReturned,
this);
} else {
if (StorageManager.EnoughSpaceForAMinSaveGame()) {
unsigned int uiIDA[4];
uiIDA[0] = IDS_CONFIRM_CANCEL;
uiIDA[1] = IDS_TITLE_RENAMESAVE;
uiIDA[2] = IDS_TOOLTIPS_DELETESAVE;
int numOptions = 3;
#ifdef SONY_REMOTE_STORAGE_UPLOAD
if (ProfileManager.IsSignedInLive(
ProfileManager.GetPrimaryPad())) {
numOptions = 4;
uiIDA[3] = IDS_TOOLTIPS_SAVETRANSFER_UPLOAD;
}
#endif
#if defined _XBOX_ONE || defined __ORBIS__
numOptions = 4;
uiIDA[3] = IDS_COPYSAVE;
#endif
ui.RequestAlertMessage(
IDS_TOOLTIPS_SAVEOPTIONS, IDS_TEXT_SAVEOPTIONS,
uiIDA, numOptions, iPad,
&UIScene_LoadOrJoinMenu::
SaveOptionsDialogReturned,
this);
} 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;
ui.RequestAlertMessage(IDS_TOOLTIPS_DELETESAVE,
IDS_TEXT_DELETE_SAVE, uiIDA,
2, iPad,
&UIScene_LoadOrJoinMenu::
DeleteSaveDialogReturned,
this);
}
}
ui.PlayUISFX(eSFX_Press);
}
} else if (DoesMashUpWorldHaveFocus()) {
// hiding a mash-up world
if ((m_iSaveListIndex != JOIN_LOAD_CREATE_BUTTON_INDEX)) {
LevelGenerationOptions* levelGen =
m_generators.at(m_iSaveListIndex - 1);
if (!levelGen->isTutorial()) {
if (levelGen->requiresTexturePack()) {
unsigned int uiPackID =
levelGen->getRequiredTexturePackId();
m_bIgnoreInput = true;
app.HideMashupPackWorld(m_iPad, uiPackID);
// update the saves list
m_iState = e_SavesRepopulateAfterMashupHide;
}
}
}
ui.PlayUISFX(eSFX_Press);
}
break;
case ACTION_MENU_LEFT_SCROLL:
#ifdef _XBOX
if (m_bInParty) {
m_bShowingPartyGamesOnly = !m_bShowingPartyGamesOnly;
UpdateGamesList();
CXuiSceneBase::PlayUISFX(eSFX_Press);
}
#endif
break;
case ACTION_MENU_LEFT:
case ACTION_MENU_RIGHT: {
// if we are on the saves menu, check there are games in the games
// list to move to
if (DoesSavesListHaveFocus()) {
if (m_buttonListGames.getItemCount() > 0) {
sendInputToMovie(key, repeat, pressed, released);
}
} else {
sendInputToMovie(key, repeat, pressed, released);
}
} break;
case ACTION_MENU_OK:
#ifdef __ORBIS__
case ACTION_MENU_TOUCHPAD_PRESS:
#endif
case ACTION_MENU_UP:
case ACTION_MENU_DOWN:
case ACTION_MENU_PAGEUP:
case ACTION_MENU_PAGEDOWN:
sendInputToMovie(key, repeat, pressed, released);
handled = true;
break;
}
}
int UIScene_LoadOrJoinMenu::KeyboardCompleteWorldNameCallback(void* lpParam,
bool bRes) {
// 4J HEG - No reason to set value if keyboard was cancelled
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)lpParam;
pClass->m_bIgnoreInput = false;
if (bRes) {
std::uint16_t ui16Text[128];
ZeroMemory(ui16Text, 128 * sizeof(std::uint16_t));
InputManager.GetText(ui16Text);
// check the name is valid
if (ui16Text[0] != 0) {
#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || \
defined(__PSVITA__))
// open the save and overwrite the metadata
StorageManager.RenameSaveData(
pClass->m_iSaveListIndex - pClass->m_iDefaultButtonsC, ui16Text,
&UIScene_LoadOrJoinMenu::RenameSaveDataReturned, pClass);
#endif
} else {
pClass->m_bIgnoreInput = false;
pClass->updateTooltips();
}
} else {
pClass->m_bIgnoreInput = false;
pClass->updateTooltips();
}
return 0;
}
void UIScene_LoadOrJoinMenu::handleInitFocus(F64 controlId, F64 childId) {
app.DebugPrintf(app.USER_SR,
"UIScene_LoadOrJoinMenu::handleInitFocus - %d , %d\n",
(int)controlId, (int)childId);
}
void UIScene_LoadOrJoinMenu::handleFocusChange(F64 controlId, F64 childId) {
app.DebugPrintf(app.USER_SR,
"UIScene_LoadOrJoinMenu::handleFocusChange - %d , %d\n",
(int)controlId, (int)childId);
switch ((int)controlId) {
case eControl_GamesList:
m_iGameListIndex = childId;
m_buttonListGames.updateChildFocus((int)childId);
break;
case eControl_SavesList:
m_iSaveListIndex = childId;
m_bUpdateSaveSize = true;
break;
};
updateTooltips();
}
#ifdef SONY_REMOTE_STORAGE_DOWNLOAD
void UIScene_LoadOrJoinMenu::remoteStorageGetSaveCallback(
void* lpParam, SonyRemoteStorage::Status s, int error_code) {
app.DebugPrintf("remoteStorageGetCallback err : 0x%08x\n", error_code);
assert(error_code == 0);
((UIScene_LoadOrJoinMenu*)lpParam)->LoadSaveFromCloud();
}
#endif
void UIScene_LoadOrJoinMenu::handlePress(F64 controlId, F64 childId) {
switch ((int)controlId) {
case eControl_SavesList: {
m_bIgnoreInput = true;
int lGenID = (int)childId - 1;
// CD - Added for audio
ui.PlayUISFX(eSFX_Press);
if ((int)childId == JOIN_LOAD_CREATE_BUTTON_INDEX) {
app.SetTutorialMode(false);
m_controlJoinTimer.setVisible(false);
app.SetCorruptSaveDeleted(false);
CreateWorldMenuInitData* params = new CreateWorldMenuInitData();
params->iPad = m_iPad;
ui.NavigateToScene(m_iPad, eUIScene_CreateWorldMenu,
(void*)params);
} else if (lGenID < m_generators.size()) {
LevelGenerationOptions* levelGen = m_generators.at(lGenID);
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;
params->saveDetails = NULL;
// navigate to the settings scene
ui.NavigateToScene(ProfileManager.GetPrimaryPad(),
eUIScene_LoadMenu, params);
}
} else {
#ifdef __ORBIS__
// check if this is a damaged save
PSAVE_INFO pSaveInfo =
&m_pSaveDetails
->SaveInfoA[((int)childId) - m_iDefaultButtonsC];
if (pSaveInfo->thumbnailData == NULL &&
pSaveInfo->modifiedTime ==
0) // no thumbnail data and time of zero and zero
// blocks useset for corrupt files
{
// give the option to delete the save
unsigned int uiIDA[2];
uiIDA[0] = IDS_CONFIRM_CANCEL;
uiIDA[1] = IDS_CONFIRM_OK;
ui.RequestAlertMessage(
IDS_CORRUPT_OR_DAMAGED_SAVE_TITLE,
IDS_CORRUPT_OR_DAMAGED_SAVE_TEXT, uiIDA, 2,
ProfileManager.GetPrimaryPad(),
&UIScene_LoadOrJoinMenu::DeleteSaveDialogReturned,
this);
} else
#endif
{
app.SetTutorialMode(false);
if (app.DebugSettingsOn() &&
app.GetLoadSavesFromFolderEnabled()) {
LoadSaveFromDisk(
m_saves->at((int)childId - 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 =
((int)childId) - m_iDefaultButtonsC;
// params->pbSaveRenamed=&m_bSaveRenamed;
params->levelGen = NULL;
params->saveDetails =
&m_saveDetails[((int)childId) - m_iDefaultButtonsC];
#ifdef _XBOX_ONE
// On XB1, saves might need syncing, in which case
// inform the user so they can decide whether they want
// to wait for this to happen
if (m_pSaveDetails
->SaveInfoA[params->iSaveGameInfoIndex]
.needsSync) {
unsigned int uiIDA[2];
uiIDA[0] = IDS_CONFIRM_SYNC;
uiIDA[1] = IDS_CONFIRM_CANCEL;
m_loadMenuInitData = params;
ui.RequestAlertMessage(
IDS_LOAD_SAVED_WORLD, IDS_CONFIRM_SYNC_REQUIRED,
uiIDA, 2, ProfileManager.GetPrimaryPad(),
&NeedSyncMessageReturned, this);
} else
#endif
{
// navigate to the settings scene
ui.NavigateToScene(ProfileManager.GetPrimaryPad(),
eUIScene_LoadMenu, params);
}
}
}
}
} break;
case eControl_GamesList: {
m_bIgnoreInput = true;
m_eAction = eAction_JoinGame;
// CD - Added for audio
ui.PlayUISFX(eSFX_Press);
{
int nIndex = (int)childId;
m_iGameListIndex = nIndex;
CheckAndJoinGame(nIndex);
}
break;
}
}
}
void UIScene_LoadOrJoinMenu::CheckAndJoinGame(int gameIndex) {
if (m_buttonListGames.getItemCount() > 0 &&
gameIndex < m_currentSessions->size()) {
#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__)
// 4J-PB - is the player allowed to join games?
bool noUGC = false;
bool bContentRestricted = false;
// we're online, since we are joining a game
ProfileManager.GetChatAndContentRestrictions(m_iPad, true, &noUGC,
&bContentRestricted, NULL);
#ifdef __ORBIS__
// 4J Stu - On PS4 we don't restrict playing multiplayer based on chat
// restriction, so remove this check
noUGC = false;
bool bPlayStationPlus = true;
int iPadWithNoPlaystationPlus = 0;
bool isSignedInLive = true;
int iPadNotSignedInLive = -1;
for (unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) {
if (InputManager.IsPadConnected(i) ||
ProfileManager.IsSignedIn(i)) {
if (isSignedInLive && !ProfileManager.IsSignedInLive(i)) {
// Record the first non signed in live pad
iPadNotSignedInLive = i;
}
isSignedInLive =
isSignedInLive && ProfileManager.IsSignedInLive(i);
if (ProfileManager.HasPlayStationPlus(i) == false) {
bPlayStationPlus = false;
break;
}
}
}
#endif
#ifdef __PSVITA__
if (CGameNetworkManager::usingAdhocMode()) {
bContentRestricted = false;
noUGC = false;
}
#endif
if (noUGC) {
// not allowed to join
#ifndef __PSVITA__
unsigned int uiIDA[1];
uiIDA[0] = IDS_CONFIRM_OK;
// Not allowed to play online
ui.RequestAlertMessage(IDS_ONLINE_GAME, IDS_CHAT_RESTRICTION_UGC,
uiIDA, 1, m_iPad, NULL, this);
#else
// Not allowed to play online
ProfileManager.ShowSystemMessage(
SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION, 0);
#endif
m_bIgnoreInput = false;
return;
} else if (bContentRestricted) {
ui.RequestContentRestrictedMessageBox();
m_bIgnoreInput = false;
return;
}
#ifdef __ORBIS__
// If this is an online game but not all players are signed in to Live,
// stop!
else if (!isSignedInLive) {
unsigned int uiIDA[1];
uiIDA[0] = IDS_CONFIRM_OK;
// Check if PSN is unavailable because of age restriction
int npAvailability =
ProfileManager.getNPAvailability(iPadNotSignedInLive);
if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) {
m_bIgnoreInput = false;
// 4J Stu - This is a bit messy and is due to the library
// incorrectly returning false for IsSignedInLive if the
// npAvailability isn't SCE_OK
ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE,
IDS_CONTENT_RESTRICTION, uiIDA, 1,
iPadNotSignedInLive);
} else {
ui.RequestErrorMessage(
IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1,
iPadNotSignedInLive,
&UIScene_LoadOrJoinMenu::MustSignInReturnedPSN, this);
}
return;
} else if (bPlayStationPlus == false) {
if (ProfileManager.RequestingPlaystationPlus(
iPadWithNoPlaystationPlus)) {
// MGH - added this so we don't try and upsell when we don't
// know if the player has PS Plus yet (if it can't connect to
// the PS Plus server).
unsigned int uiIDA[1];
uiIDA[0] = IDS_OK;
ui.RequestAlertMessage(
IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1,
ProfileManager.GetPrimaryPad(), NULL, NULL);
return;
}
// PS Plus upsell
// 4J-PB - we're not allowed to show the text Playstation Plus -
// have to call the upsell all the time! upsell psplus
std::int32_t iResult = sceNpCommerceDialogInitialize();
SceNpCommerceDialogParam param;
sceNpCommerceDialogParamInitialize(&param);
param.mode = SCE_NP_COMMERCE_DIALOG_MODE_PLUS;
param.features = SCE_NP_PLUS_FEATURE_REALTIME_MULTIPLAY;
param.userId = ProfileManager.getUserID(iPadWithNoPlaystationPlus);
iResult = sceNpCommerceDialogOpen(&param);
// unsigned int uiIDA[2];
// uiIDA[0]=IDS_CONFIRM_OK;
// uiIDA[1]=IDS_PLAYSTATIONPLUS_SIGNUP;
// ui.RequestMessageBox(
// IDS_FAILED_TO_CREATE_GAME_TITLE,
// IDS_NO_PLAYSTATIONPLUS,
// uiIDA,2,ProfileManager.GetPrimaryPad(),&UIScene_LoadOrJoinMenu::PSPlusReturned,this,
// app.GetStringTable(),NULL,0,false);
m_bIgnoreInput = false;
return;
}
#endif
#endif
// CScene_MultiGameInfo::JoinMenuInitData *initData = new
// CScene_MultiGameInfo::JoinMenuInitData();
m_initData->iPad = 0;
;
m_initData->selectedSession = m_currentSessions->at(gameIndex);
// 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
#ifdef _XBOX
ULONGLONG ullOfferID_Full;
app.GetDLCFullOfferIDForPackID(
m_initData->selectedSession->data.texturePackParentId,
&ullOfferID_Full);
TelemetryManager->RecordUpsellPresented(
m_iPad, eSet_UpsellID_Texture_DLC,
ullOfferID_Full & 0xFFFFFFFF);
#endif
unsigned int uiIDA[2];
uiIDA[0] = IDS_TEXTUREPACK_FULLVERSION;
// uiIDA[1]=IDS_TEXTURE_PACK_TRIALVERSION;
uiIDA[1] = IDS_CONFIRM_CANCEL;
// Give the player a warning about the texture pack missing
ui.RequestAlertMessage(
IDS_DLC_TEXTUREPACK_NOT_PRESENT_TITLE,
IDS_DLC_TEXTUREPACK_NOT_PRESENT, uiIDA, 2, m_iPad,
&UIScene_LoadOrJoinMenu::TexturePackDialogReturned, this);
return;
}
#ifdef __PSVITA__
if (CGameNetworkManager::usingAdhocMode() &&
!SQRNetworkManager_AdHoc_Vita::GetAdhocStatus()) {
// not connected to adhoc anymore, must have connected back to
// PSN to buy texture pack so sign in again
SQRNetworkManager_AdHoc_Vita::AttemptAdhocSignIn(
&UIScene_LoadOrJoinMenu::SignInAdhocReturned, this);
return;
}
#endif
}
m_controlJoinTimer.setVisible(false);
#ifdef _XBOX
// Reset the background downloading, in case we changed it by attempting
// to download a texture pack
XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_AUTO);
#endif
m_bIgnoreInput = true;
ui.NavigateToScene(ProfileManager.GetPrimaryPad(), eUIScene_JoinMenu,
m_initData);
}
}
void UIScene_LoadOrJoinMenu::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;
// TODO int maxPlayers = MINECRAFT_NET_MAX_PLAYERS;
int maxPlayers = 8;
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();
}
#ifndef _XBOX
g_NetworkManager.FakeLocalPlayerJoined();
#endif
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;
ui.NavigateToScene(ProfileManager.GetPrimaryPad(),
eUIScene_FullscreenProgress, loadingParams);
}
void UIScene_LoadOrJoinMenu::UpdateGamesListCallback(void* pParam) {
if (pParam != NULL) {
UIScene_LoadOrJoinMenu* pScene = (UIScene_LoadOrJoinMenu*)pParam;
pScene->UpdateGamesList();
}
}
void UIScene_LoadOrJoinMenu::UpdateGamesList() {
// If we're ignoring input scene isn't active so do nothing
if (m_bIgnoreInput) return;
// If a texture pack is loading, or will be loading, then ignore this ( we
// are going to be destroyed anyway)
if (Minecraft::GetInstance()->skins->getSelected()->isLoadingData() ||
(Minecraft::GetInstance()->skins->needsUIUpdate() ||
ui.IsReloadingSkin()))
return;
// if we're retrieving save info, don't show the list yet as we will be
// ignoring press events
if (!m_bSavesDisplayed) {
return;
}
FriendSessionInfo* pSelectedSession = NULL;
if (DoesGamesListHaveFocus() && m_buttonListGames.getItemCount() > 0) {
const int nIndex = m_buttonListGames.getCurrentSelection();
pSelectedSession = m_currentSessions->at(nIndex);
}
SessionID selectedSessionId;
ZeroMemory(&selectedSessionId, sizeof(SessionID));
if (pSelectedSession != NULL)
selectedSessionId = pSelectedSession->sessionId;
pSelectedSession = NULL;
m_controlJoinTimer.setVisible(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;
int iX = -1;
delete m_currentSessions;
m_currentSessions =
g_NetworkManager.GetSessionList(m_iPad, 1, m_bShowingPartyGamesOnly);
// Update the xui list displayed
unsigned int xuiListSize = m_buttonListGames.getItemCount();
unsigned int filteredListSize = (unsigned int)m_currentSessions->size();
const bool gamesListHasFocus = DoesGamesListHaveFocus();
if (filteredListSize > 0) {
#if TO_BE_IMPLEMENTED
if (!m_pGamesList->IsEnabled()) {
m_pGamesList->SetEnable(TRUE);
m_pGamesList->SetCurSel(0);
}
#endif
m_labelNoGames.setVisible(false);
m_controlJoinTimer.setVisible(false);
} else {
#if TO_BE_IMPLEMENTED
m_pGamesList->SetEnable(FALSE);
#endif
m_controlJoinTimer.setVisible(false);
m_labelNoGames.setVisible(true);
#if TO_BE_IMPLEMENTED
if (gamesListHasFocus) m_pGamesList->InitFocus(m_iPad);
#endif
}
// clear out the games list and re-fill
m_buttonListGames.clearList();
if (filteredListSize > 0) {
// Reset the focus to the selected session if it still exists
unsigned int sessionIndex = 0;
m_buttonListGames.setCurrentSelection(0);
for (AUTO_VAR(it, m_currentSessions->begin());
it < m_currentSessions->end(); ++it) {
FriendSessionInfo* sessionInfo = *it;
wchar_t textureName[64] = L"\0";
// 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) {
swprintf(textureName, 64, L"%ls",
sessionInfo->displayLabel);
registerSubstitutionTexture(textureName, imageData,
imageBytes);
}
} else {
imageData = tp->getPackIcon(imageBytes);
if (imageBytes > 0 && imageData) {
swprintf(textureName, 64, L"%ls",
sessionInfo->displayLabel);
registerSubstitutionTexture(textureName, imageData,
imageBytes);
}
}
} else {
// default texture pack
Minecraft* pMinecraft = Minecraft::GetInstance();
TexturePack* tp = pMinecraft->skins->getTexturePackByIndex(0);
std::uint32_t imageBytes = 0;
std::uint8_t* imageData = tp->getPackIcon(imageBytes);
if (imageBytes > 0 && imageData) {
swprintf(textureName, 64, L"%ls",
sessionInfo->displayLabel);
registerSubstitutionTexture(textureName, imageData,
imageBytes);
}
}
m_buttonListGames.addItem(sessionInfo->displayLabel, textureName);
if (memcmp(&selectedSessionId, &sessionInfo->sessionId,
sizeof(SessionID)) == 0) {
m_buttonListGames.setCurrentSelection(sessionIndex);
break;
}
++sessionIndex;
}
}
updateTooltips();
}
void UIScene_LoadOrJoinMenu::HandleDLCMountingComplete() { Initialise(); }
bool UIScene_LoadOrJoinMenu::DoesSavesListHaveFocus() {
if (m_buttonListSaves.hasFocus()) {
// check it's not the first or second element (new world or tutorial)
if (m_iSaveListIndex > (m_iDefaultButtonsC - 1)) {
return true;
}
}
return false;
}
bool UIScene_LoadOrJoinMenu::DoesMashUpWorldHaveFocus() {
if (m_buttonListSaves.hasFocus()) {
// check it's not the first or second element (new world or tutorial)
if (m_iSaveListIndex > (m_iDefaultButtonsC - 1)) {
return false;
}
if (m_iSaveListIndex > (m_iDefaultButtonsC - 1 - m_iMashUpButtonsC)) {
return true;
} else
return false;
} else
return false;
}
bool UIScene_LoadOrJoinMenu::DoesGamesListHaveFocus() {
return m_buttonListGames.hasFocus();
}
void UIScene_LoadOrJoinMenu::handleTimerComplete(int id) {
switch (id) {
case JOIN_LOAD_ONLINE_TIMER_ID: {
#ifdef _XBOX
XPARTY_USER_LIST partyList;
if ((XPartyGetUserList(&partyList) != XPARTY_E_NOT_IN_PARTY) &&
(partyList.dwUserCount > 1)) {
m_bInParty = true;
} else {
m_bInParty = false;
}
#endif
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_buttonListGames.clearList();
m_controlJoinTimer.setVisible(true);
m_labelNoGames.setVisible(false);
}
m_bMultiplayerAllowed = bMultiplayerAllowed;
}
} break;
// 4J-PB - Only Xbox will not have trial DLC patched into the game
#ifdef _XBOX
case CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID: {
#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__)
for (int i = 0; i < m_iTexturePacksNotInstalled; i++) {
if (m_iConfigA[i] != -1) {
DLC_INFO* pDLCInfo =
app.GetDLCInfoFromTPackID(m_iConfigA[i]);
if (pDLCInfo) {
// retrieve the image - if we haven't already
std::wstring textureName =
filenametowstring(pDLCInfo->chImageURL);
if (hasRegisteredSubstitutionTexture(textureName) ==
false) {
std::uint8_t* pbImageData = NULL;
int iImageDataBytes = 0;
SonyHttp::getDataFromURL(pDLCInfo->chImageURL,
(void**)&pbImageData,
&iImageDataBytes);
if (iImageDataBytes != 0) {
// set the image
registerSubstitutionTexture(
textureName, pbImageData, iImageDataBytes,
true);
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
killTimer(CHECKFORAVAILABLETEXTUREPACKS_TIMER_ID);
}
#endif
} break;
#endif
}
}
void UIScene_LoadOrJoinMenu::LoadSaveFromDisk(
File* saveFile, ESavePlatform savePlatform /*= SAVE_FILE_PLATFORM_LOCAL*/) {
// 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_t 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);
param->savePlatform = savePlatform;
#ifndef _XBOX
g_NetworkManager.FakeLocalPlayerJoined();
#endif
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;
ui.NavigateToScene(ProfileManager.GetPrimaryPad(),
eUIScene_FullscreenProgress, loadingParams);
}
#ifdef SONY_REMOTE_STORAGE_DOWNLOAD
void UIScene_LoadOrJoinMenu::LoadSaveFromCloud() {
wchar_t wFileName[128];
mbstowcs(
wFileName, app.getRemoteStorage()->getLocalFilename(),
strlen(app.getRemoteStorage()->getLocalFilename()) + 1); // plus null
File cloudFile(wFileName);
StorageManager.ResetSaveData();
// Make our next save default to the name of the level
wchar_t wSaveName[128];
mbstowcs(
wSaveName, app.getRemoteStorage()->getSaveNameUTF8(),
strlen(app.getRemoteStorage()->getSaveNameUTF8()) + 1); // plus null
StorageManager.SetSaveTitle(wSaveName);
int64_t fileSize = cloudFile.length();
FileInputStream fis(cloudFile);
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_All,
app.getRemoteStorage()->getSaveHostOptions());
g_NetworkManager.HostGame(0, isClientSide, isPrivate, maxPlayers, 0);
LoadSaveDataThreadParam* saveData =
new LoadSaveDataThreadParam(ba.data, ba.length, cloudFile.getName());
NetworkGameInitData* param = new NetworkGameInitData();
param->seed = app.getRemoteStorage()->getSaveSeed();
param->saveData = saveData;
param->settings = app.GetGameHostOption(eGameHostOption_All);
param->savePlatform = app.getRemoteStorage()->getSavePlatform();
param->texturePackId = app.getRemoteStorage()->getSaveTexturePack();
#ifndef _XBOX
g_NetworkManager.FakeLocalPlayerJoined();
#endif
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;
ui.NavigateToScene(ProfileManager.GetPrimaryPad(),
eUIScene_FullscreenProgress, loadingParams);
}
#endif // SONY_REMOTE_STORAGE_DOWNLOAD
int UIScene_LoadOrJoinMenu::DeleteSaveDialogReturned(
void* pParam, int iPad, C4JStorage::EMessageResult result) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam;
// results switched for this dialog
// Check that we have a valid save selected (can get a bad index if the save
// list has been refreshed)
bool validSelection =
pClass->m_iDefaultButtonsC != 0 &&
pClass->m_iSaveListIndex >= pClass->m_iDefaultButtonsC;
if (result == C4JStorage::EMessage_ResultDecline && validSelection) {
if (app.DebugSettingsOn() && app.GetLoadSavesFromFolderEnabled()) {
pClass->m_bIgnoreInput = false;
} else {
StorageManager.DeleteSaveData(
&pClass->m_pSaveDetails->SaveInfoA[pClass->m_iSaveListIndex -
pClass->m_iDefaultButtonsC],
UIScene_LoadOrJoinMenu::DeleteSaveDataReturned,
reinterpret_cast<void*>(pClass->GetCallbackUniqueId()));
pClass->m_controlSavesTimer.setVisible(true);
}
} else {
pClass->m_bIgnoreInput = false;
}
return 0;
}
int UIScene_LoadOrJoinMenu::DeleteSaveDataReturned(void* lpParam, bool bRes) {
ui.EnterCallbackIdCriticalSection();
UIScene_LoadOrJoinMenu* pClass =
(UIScene_LoadOrJoinMenu*)ui.GetSceneFromCallbackId((size_t)lpParam);
if (pClass) {
if (bRes) {
// wipe the list and repopulate it
pClass->m_iState = e_SavesRepopulateAfterDelete;
} else
pClass->m_bIgnoreInput = false;
pClass->updateTooltips();
}
ui.LeaveCallbackIdCriticalSection();
return 0;
}
int UIScene_LoadOrJoinMenu::RenameSaveDataReturned(void* lpParam, bool bRes) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)lpParam;
if (bRes) {
pClass->m_iState = e_SavesRepopulate;
} else
pClass->m_bIgnoreInput = false;
pClass->updateTooltips();
return 0;
}
#ifdef __ORBIS__
void UIScene_LoadOrJoinMenu::LoadRemoteFileFromDisk(char* remoteFilename) {
wchar_t wSaveName[128];
mbstowcs(wSaveName, remoteFilename,
strlen(remoteFilename) + 1); // plus null
// processConsoleSave(wSaveName, L"ProcessedSave.bin");
// File remoteFile(L"ProcessedSave.bin");
File remoteFile(wSaveName);
LoadSaveFromDisk(&remoteFile, SAVE_FILE_PLATFORM_PS3);
}
#endif
int UIScene_LoadOrJoinMenu::SaveOptionsDialogReturned(
void* pParam, int iPad, C4JStorage::EMessageResult result) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam;
// results switched for this dialog
// EMessage_ResultAccept means cancel
switch (result) {
case C4JStorage::EMessage_ResultDecline: // rename
{
pClass->m_bIgnoreInput = true;
#ifdef _DURANGO
// bring up a keyboard
InputManager.RequestKeyboard(
app.GetString(IDS_RENAME_WORLD_TITLE),
(pClass->m_saveDetails[pClass->m_iSaveListIndex -
pClass->m_iDefaultButtonsC])
.UTF16SaveName,
0, 25,
&UIScene_LoadOrJoinMenu::KeyboardCompleteWorldNameCallback,
pClass, C_4JInput::EKeyboardMode_Default);
#else
// bring up a keyboard
wchar_t wSaveName[128];
// CD - Fix - We must memset the SaveName
ZeroMemory(wSaveName, 128 * sizeof(wchar_t));
mbstowcs(
wSaveName,
pClass
->m_saveDetails[pClass->m_iSaveListIndex -
pClass->m_iDefaultButtonsC]
.UTF8SaveName,
strlen(pClass->m_saveDetails->UTF8SaveName) + 1); // plus null
LPWSTR ptr = wSaveName;
InputManager.RequestKeyboard(
app.GetString(IDS_RENAME_WORLD_TITLE), wSaveName, 0, 25,
&UIScene_LoadOrJoinMenu::KeyboardCompleteWorldNameCallback,
pClass, C_4JInput::EKeyboardMode_Default);
#endif
} break;
case C4JStorage::EMessage_ResultThirdOption: // 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;
ui.RequestAlertMessage(
IDS_TOOLTIPS_DELETESAVE, IDS_TEXT_DELETE_SAVE, uiIDA, 2, iPad,
&UIScene_LoadOrJoinMenu::DeleteSaveDialogReturned, pClass);
} break;
#ifdef SONY_REMOTE_STORAGE_UPLOAD
case C4JStorage::EMessage_ResultFourthOption: // upload to cloud
{
unsigned int uiIDA[2];
uiIDA[0] = IDS_CONFIRM_OK;
uiIDA[1] = IDS_CONFIRM_CANCEL;
ui.RequestAlertMessage(
IDS_TOOLTIPS_SAVETRANSFER_UPLOAD, IDS_SAVE_TRANSFER_TEXT, uiIDA,
2, iPad, &UIScene_LoadOrJoinMenu::SaveTransferDialogReturned,
pClass);
} break;
#endif // SONY_REMOTE_STORAGE_UPLOAD
#if defined _XBOX_ONE || defined __ORBIS__
case C4JStorage::EMessage_ResultFourthOption: // copy save
{
unsigned int uiIDA[2];
uiIDA[0] = IDS_CONFIRM_OK;
uiIDA[1] = IDS_CONFIRM_CANCEL;
ui.RequestAlertMessage(
IDS_COPYSAVE, IDS_TEXT_COPY_SAVE, uiIDA, 2, iPad,
&UIScene_LoadOrJoinMenu::CopySaveDialogReturned, pClass);
} break;
#endif
case C4JStorage::EMessage_Cancelled:
default: {
// reset the tooltips
pClass->updateTooltips();
pClass->m_bIgnoreInput = false;
} break;
}
return 0;
}
#if defined(__PSVITA__)
int UIScene_LoadOrJoinMenu::SignInAdhocReturned(void* pParam, bool bContinue,
int iPad) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam;
pClass->m_bIgnoreInput = false;
return 0;
}
int UIScene_LoadOrJoinMenu::MustSignInTexturePack(
void* pParam, int iPad, C4JStorage::EMessageResult result) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam;
if (result == C4JStorage::EMessage_ResultAccept) {
SQRNetworkManager_Vita::AttemptPSNSignIn(
&UIScene_LoadOrJoinMenu::MustSignInReturnedTexturePack, pClass);
} else {
pClass->m_bIgnoreInput = false;
}
return 0;
}
int UIScene_LoadOrJoinMenu::MustSignInReturnedTexturePack(void* pParam,
bool bContinue,
int iPad) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam;
int commerceState = app.GetCommerceState();
while (commerceState != CConsoleMinecraftApp::eCommerce_State_Offline &&
commerceState != CConsoleMinecraftApp::eCommerce_State_Online &&
commerceState != CConsoleMinecraftApp::eCommerce_State_Error) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
commerceState = app.GetCommerceState();
}
if (bContinue == true) {
SONYDLC* pSONYDLCInfo = app.GetSONYDLCInfo(
pClass->m_initData->selectedSession->data.texturePackParentId);
if (pSONYDLCInfo != NULL) {
char chName[42];
char chKeyName[20];
char chSkuID[SCE_NP_COMMERCE2_SKU_ID_LEN];
memset(chSkuID, 0, SCE_NP_COMMERCE2_SKU_ID_LEN);
// we have to retrieve the skuid from the store info, it can't be
// hardcoded since Sony may change it. So we assume the first sku
// for the product is the one we want MGH - keyname in the DLC file
// is 16 chars long, but there's no space for a NULL terminating
// char
memset(chKeyName, 0, sizeof(chKeyName));
strncpy(chKeyName, pSONYDLCInfo->chDLCKeyname, 16);
#ifdef __ORBIS__
strcpy(chName, chKeyName);
#else
sprintf(chName, "%s-%s", app.GetCommerceCategory(), chKeyName);
#endif
app.GetDLCSkuIDFromProductList(chName, chSkuID);
// 4J-PB - need to check for an empty store
if (app.CheckForEmptyStore(iPad) == false) {
if (app.DLCAlreadyPurchased(chSkuID)) {
app.DownloadAlreadyPurchased(chSkuID);
} else {
app.Checkout(chSkuID);
}
}
}
}
pClass->m_bIgnoreInput = false;
return 0;
}
#endif
int UIScene_LoadOrJoinMenu::TexturePackDialogReturned(
void* pParam, int iPad, C4JStorage::EMessageResult result) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam;
// Exit with or without saving
if (result == C4JStorage::EMessage_ResultAccept) {
// we need to enable background downloading for the DLC
XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW);
#if defined __PSVITA__ || defined __PS3__ || defined __ORBIS__
#ifdef __PSVITA__
if (!ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()) &&
CGameNetworkManager::usingAdhocMode()) {
// get them to sign in to online
unsigned int uiIDA[2];
uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT;
uiIDA[1] = IDS_PRO_NOTONLINE_DECLINE;
ui.RequestAlertMessage(
IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA,
2, ProfileManager.GetPrimaryPad(),
&UIScene_LoadOrJoinMenu::MustSignInTexturePack, pClass);
return;
}
#endif
SONYDLC* pSONYDLCInfo = app.GetSONYDLCInfo(
pClass->m_initData->selectedSession->data.texturePackParentId);
if (pSONYDLCInfo != NULL) {
char chName[42];
char chKeyName[20];
char chSkuID[SCE_NP_COMMERCE2_SKU_ID_LEN];
memset(chSkuID, 0, SCE_NP_COMMERCE2_SKU_ID_LEN);
// we have to retrieve the skuid from the store info, it can't be
// hardcoded since Sony may change it. So we assume the first sku
// for the product is the one we want MGH - keyname in the DLC file
// is 16 chars long, but there's no space for a NULL terminating
// char
memset(chKeyName, 0, sizeof(chKeyName));
strncpy(chKeyName, pSONYDLCInfo->chDLCKeyname, 16);
#ifdef __ORBIS__
strcpy(chName, chKeyName);
#else
sprintf(chName, "%s-%s", app.GetCommerceCategory(), chKeyName);
#endif
app.GetDLCSkuIDFromProductList(chName, chSkuID);
// 4J-PB - need to check for an empty store
if (app.CheckForEmptyStore(iPad) == false) {
if (app.DLCAlreadyPurchased(chSkuID)) {
app.DownloadAlreadyPurchased(chSkuID);
} else {
app.Checkout(chSkuID);
}
}
}
#endif
#if defined _XBOX_ONE
if (ProfileManager.IsSignedIn(iPad)) {
if (ProfileManager.IsSignedInLive(iPad)) {
std::wstring ProductId;
app.GetDLCFullOfferIDForPackID(
pClass->m_initData->selectedSession->data
.texturePackParentId,
ProductId);
StorageManager.InstallOffer(1, (WCHAR*)ProductId.c_str(), NULL,
NULL);
} else {
// 4J-JEV: Fix for XB1: #165863 - XR-074: Compliance: With no
// active network connection user is unable to convert from
// Trial to Full texture pack and is not messaged why.
unsigned int uiIDA[1] = {IDS_CONFIRM_OK};
ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE,
IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1,
iPad);
}
}
#endif
}
pClass->m_bIgnoreInput = false;
return 0;
}
#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__
int UIScene_LoadOrJoinMenu::MustSignInReturnedPSN(
void* pParam, int iPad, C4JStorage::EMessageResult result) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam;
if (result == C4JStorage::EMessage_ResultAccept) {
#if defined(__PS3__)
SQRNetworkManager_PS3::AttemptPSNSignIn(
&UIScene_LoadOrJoinMenu::PSN_SignInReturned, pClass);
#elif defined __PSVITA__
SQRNetworkManager_Vita::AttemptPSNSignIn(
&UIScene_LoadOrJoinMenu::PSN_SignInReturned, pClass);
#else
SQRNetworkManager_Orbis::AttemptPSNSignIn(
&UIScene_LoadOrJoinMenu::PSN_SignInReturned, pClass, false, iPad);
#endif
} else {
pClass->m_bIgnoreInput = false;
}
return 0;
}
int UIScene_LoadOrJoinMenu::PSN_SignInReturned(void* pParam, bool bContinue,
int iPad) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam;
if (bContinue == true) {
switch (pClass->m_eAction) {
case eAction_ViewInvites:
// Check if we're signed in to LIVE
if (ProfileManager.IsSignedInLive(iPad)) {
#if defined(__PS3__)
int ret = sceNpBasicRecvMessageCustom(
SCE_NP_BASIC_MESSAGE_MAIN_TYPE_INVITE,
SCE_NP_BASIC_RECV_MESSAGE_OPTIONS_INCLUDE_BOOTABLE,
SYS_MEMORY_CONTAINER_ID_INVALID);
app.DebugPrintf(
"sceNpBasicRecvMessageCustom return %d ( %08x )\n", ret,
ret);
#elif defined __PSVITA__
SQRNetworkManager_Vita::RecvInviteGUI();
#else
SQRNetworkManager_Orbis::RecvInviteGUI();
#endif
}
break;
case eAction_JoinGame:
pClass->CheckAndJoinGame(pClass->m_iGameListIndex);
break;
}
} else {
pClass->m_bIgnoreInput = false;
}
return 0;
}
#endif
#ifdef SONY_REMOTE_STORAGE_DOWNLOAD
void UIScene_LoadOrJoinMenu::LaunchSaveTransfer() {
LoadingInputParams* loadingParams = new LoadingInputParams();
loadingParams->func =
&UIScene_LoadOrJoinMenu::DownloadSonyCrossSaveThreadProc;
loadingParams->lpParam = this;
UIFullscreenProgressCompletionData* completionData =
new UIFullscreenProgressCompletionData();
completionData->bShowBackground = TRUE;
completionData->bShowLogo = TRUE;
completionData->type = e_ProgressCompletion_NavigateBackToScene;
completionData->iPad = DEFAULT_XUI_MENU_USER;
loadingParams->completionData = completionData;
loadingParams->cancelFunc =
&UIScene_LoadOrJoinMenu::CancelSaveTransferCallback;
loadingParams->m_cancelFuncParam = this;
loadingParams->cancelText = IDS_TOOLTIPS_CANCEL;
ui.NavigateToScene(m_iPad, eUIScene_FullscreenProgress, loadingParams);
}
int UIScene_LoadOrJoinMenu::CreateDummySaveDataCallback(void* lpParam,
bool bRes) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)lpParam;
if (bRes) {
pClass->m_eSaveTransferState = eSaveTransfer_GetSavesInfo;
} else {
pClass->m_eSaveTransferState = eSaveTransfer_Error;
app.DebugPrintf("CreateDummySaveDataCallback failed\n");
}
return 0;
}
int UIScene_LoadOrJoinMenu::CrossSaveGetSavesInfoCallback(
void* lpParam, SAVE_DETAILS* pSaveDetails, bool bRes) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)lpParam;
if (bRes) {
pClass->m_eSaveTransferState = eSaveTransfer_GetFileData;
} else {
pClass->m_eSaveTransferState = eSaveTransfer_Error;
app.DebugPrintf("CrossSaveGetSavesInfoCallback failed\n");
}
return 0;
}
int UIScene_LoadOrJoinMenu::LoadCrossSaveDataCallback(void* pParam,
bool bIsCorrupt,
bool bIsOwner) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam;
if (bIsCorrupt == false && bIsOwner) {
pClass->m_eSaveTransferState = eSaveTransfer_CreatingNewSave;
} else {
pClass->m_eSaveTransferState = eSaveTransfer_Error;
app.DebugPrintf("LoadCrossSaveDataCallback failed \n");
}
return 0;
}
int UIScene_LoadOrJoinMenu::CrossSaveFinishedCallback(
void* pParam, int iPad, C4JStorage::EMessageResult result) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam;
pClass->m_eSaveTransferState = eSaveTransfer_Idle;
return 0;
}
int UIScene_LoadOrJoinMenu::CrossSaveDeleteOnErrorReturned(void* lpParam,
bool bRes) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)lpParam;
pClass->m_eSaveTransferState = eSaveTransfer_ErrorMesssage;
return 0;
}
int UIScene_LoadOrJoinMenu::RemoteSaveNotFoundCallback(
void* pParam, int iPad, C4JStorage::EMessageResult result) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam;
pClass->m_eSaveTransferState = eSaveTransfer_Idle;
return 0;
}
// MGH - added this global to force the delete of the previous data, for the
// remote storage saves
// need to speak to Chris why this is necessary
bool g_bForceVitaSaveWipe = false;
int UIScene_LoadOrJoinMenu::DownloadSonyCrossSaveThreadProc(void* lpParameter) {
m_bSaveTransferRunning = true;
#ifdef __PS3__
StorageManager.SetSaveTransferInProgress(true);
#endif
Compression::UseDefaultThreadStorage();
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)lpParameter;
pClass->m_saveTransferDownloadCancelled = false;
m_bSaveTransferRunning = true;
bool bAbortCalled = false;
Minecraft* pMinecraft = Minecraft::GetInstance();
bool bSaveFileCreated = false;
wchar_t wSaveName[128];
// get the save file size
pMinecraft->progressRenderer->progressStagePercentage(0);
pMinecraft->progressRenderer->progressStart(
IDS_TOOLTIPS_SAVETRANSFER_DOWNLOAD);
pMinecraft->progressRenderer->progressStage(
IDS_TOOLTIPS_SAVETRANSFER_DOWNLOAD);
ConsoleSaveFile* pSave = NULL;
pClass->m_eSaveTransferState = eSaveTransfer_GetRemoteSaveInfo;
while (pClass->m_eSaveTransferState != eSaveTransfer_Idle) {
switch (pClass->m_eSaveTransferState) {
case eSaveTransfer_Idle:
break;
case eSaveTransfer_GetRemoteSaveInfo:
app.DebugPrintf("UIScene_LoadOrJoinMenu getSaveInfo\n");
app.getRemoteStorage()->getSaveInfo();
pClass->m_eSaveTransferState =
eSaveTransfer_GettingRemoteSaveInfo;
break;
case eSaveTransfer_GettingRemoteSaveInfo:
if (pClass->m_saveTransferDownloadCancelled) {
pClass->m_eSaveTransferState = eSaveTransfer_Error;
break;
}
if (app.getRemoteStorage()->waitingForSaveInfo() == false) {
if (app.getRemoteStorage()->saveIsAvailable()) {
if (app.getRemoteStorage()->saveVersionSupported()) {
pClass->m_eSaveTransferState =
eSaveTransfer_CreateDummyFile;
} else {
// must be a newer version of the save in the cloud
// that we don't support yet
unsigned int uiIDA[1];
uiIDA[0] = IDS_CONFIRM_OK;
ui.RequestAlertMessage(
IDS_TOOLTIPS_SAVETRANSFER_DOWNLOAD,
IDS_SAVE_TRANSFER_WRONG_VERSION, uiIDA, 1,
ProfileManager.GetPrimaryPad(),
RemoteSaveNotFoundCallback, pClass);
}
} else {
// no save available, inform the user about the
// functionality
unsigned int uiIDA[1];
uiIDA[0] = IDS_CONFIRM_OK;
ui.RequestAlertMessage(
IDS_TOOLTIPS_SAVETRANSFER_DOWNLOAD,
IDS_SAVE_TRANSFER_NOT_AVAILABLE_TEXT, uiIDA, 1,
ProfileManager.GetPrimaryPad(),
RemoteSaveNotFoundCallback, pClass);
}
}
break;
case eSaveTransfer_CreateDummyFile: {
StorageManager.ResetSaveData();
byte* compData = (byte*)StorageManager.AllocateSaveData(
app.getRemoteStorage()->getSaveFilesize());
// Make our next save default to the name of the level
const char* pNameUTF8 =
app.getRemoteStorage()->getSaveNameUTF8();
mbstowcs(wSaveName, pNameUTF8,
strlen(pNameUTF8) + 1); // plus null
StorageManager.SetSaveTitle(wSaveName);
std::uint8_t* pbThumbnailData = NULL;
unsigned int dwThumbnailDataSize = 0;
std::uint8_t* pbDataSaveImage = NULL;
unsigned int dwDataSizeSaveImage = 0;
StorageManager.GetDefaultSaveImage(
&pbDataSaveImage,
&dwDataSizeSaveImage); // Get the default save thumbnail
// (as set by SetDefaultImages) for
// use on saving games t
StorageManager.GetDefaultSaveThumbnail(
&pbThumbnailData,
&dwThumbnailDataSize); // Get the default save image (as
// set by SetDefaultImages) for use
// on saving games that
std::uint8_t bTextMetadata[88];
ZeroMemory(bTextMetadata, 88);
unsigned int hostOptions =
app.getRemoteStorage()->getSaveHostOptions();
#ifdef __ORBIS__
app.SetGameHostOption(
hostOptions, eGameHostOption_WorldSize,
e_worldSize_Classic); // force the classic world size on,
// otherwise it's unknown and we
// can't expand
#endif
int iTextMetadataBytes = app.CreateImageTextData(
bTextMetadata, app.getRemoteStorage()->getSaveSeed(), true,
hostOptions, app.getRemoteStorage()->getSaveTexturePack());
// set the icon and save image
StorageManager.SetSaveImages(
pbThumbnailData, dwThumbnailDataSize, pbDataSaveImage,
dwDataSizeSaveImage, bTextMetadata, iTextMetadataBytes);
app.getRemoteStorage()->waitForStorageManagerIdle();
C4JStorage::ESaveGameState saveState =
StorageManager.SaveSaveData(
&UIScene_LoadOrJoinMenu::CreateDummySaveDataCallback,
lpParameter);
if (saveState == C4JStorage::ESaveGame_Save) {
pClass->m_eSaveTransferState =
eSaveTransfer_CreatingDummyFile;
} else {
app.DebugPrintf("Failed to create dummy save file\n");
pClass->m_eSaveTransferState = eSaveTransfer_Error;
}
} break;
case eSaveTransfer_CreatingDummyFile:
break;
case eSaveTransfer_GetSavesInfo: {
// we can't cancel here, we need the saves info so we can delete
// the file
if (pClass->m_saveTransferDownloadCancelled) {
wchar_t wcTemp[256];
swprintf(
wcTemp, 256,
app.GetString(
IDS_CANCEL)); // MGH - should change this string to
// "cancelling download"
m_wstrStageText = wcTemp;
pMinecraft->progressRenderer->progressStage(
m_wstrStageText);
}
app.getRemoteStorage()->waitForStorageManagerIdle();
app.DebugPrintf("CALL GetSavesInfo B\n");
C4JStorage::ESaveGameState eSGIStatus =
StorageManager.GetSavesInfo(
pClass->m_iPad,
&UIScene_LoadOrJoinMenu::CrossSaveGetSavesInfoCallback,
pClass, "save");
pClass->m_eSaveTransferState = eSaveTransfer_GettingSavesInfo;
} break;
case eSaveTransfer_GettingSavesInfo:
if (pClass->m_saveTransferDownloadCancelled) {
wchar_t wcTemp[256];
swprintf(
wcTemp, 256,
app.GetString(
IDS_CANCEL)); // MGH - should change this string to
// "cancelling download"
m_wstrStageText = wcTemp;
pMinecraft->progressRenderer->progressStage(
m_wstrStageText);
}
break;
case eSaveTransfer_GetFileData: {
bSaveFileCreated = true;
StorageManager.GetSaveUniqueFileDir(
pClass->m_downloadedUniqueFilename);
if (pClass->m_saveTransferDownloadCancelled) {
pClass->m_eSaveTransferState = eSaveTransfer_Error;
break;
}
PSAVE_DETAILS pSaveDetails = StorageManager.ReturnSavesInfo();
int idx = pClass->m_iSaveListIndex - pClass->m_iDefaultButtonsC;
app.getRemoteStorage()->waitForStorageManagerIdle();
bool bGettingOK = app.getRemoteStorage()->getSaveData(
pClass->m_downloadedUniqueFilename, SaveTransferReturned,
pClass);
if (bGettingOK) {
pClass->m_eSaveTransferState =
eSaveTransfer_GettingFileData;
} else {
pClass->m_eSaveTransferState = eSaveTransfer_Error;
app.DebugPrintf(
"app.getRemoteStorage()->getSaveData failed\n");
}
}
case eSaveTransfer_GettingFileData: {
wchar_t wcTemp[256];
int dataProgress = app.getRemoteStorage()->getDataProgress();
pMinecraft->progressRenderer->progressStagePercentage(
dataProgress);
// swprintf(wcTemp, 256, L"Downloading data : %d",
// dataProgress);//app.GetString(IDS_SAVETRANSFER_STAGE_GET_DATA),0,pClass->m_ulFileSize);
swprintf(wcTemp, 256,
app.GetString(IDS_SAVETRANSFER_STAGE_GET_DATA),
dataProgress);
m_wstrStageText = wcTemp;
pMinecraft->progressRenderer->progressStage(m_wstrStageText);
if (pClass->m_saveTransferDownloadCancelled &&
bAbortCalled == false) {
app.getRemoteStorage()->abort();
bAbortCalled = true;
}
} break;
case eSaveTransfer_FileDataRetrieved:
pClass->m_eSaveTransferState = eSaveTransfer_LoadSaveFromDisc;
break;
case eSaveTransfer_LoadSaveFromDisc: {
if (pClass->m_saveTransferDownloadCancelled) {
pClass->m_eSaveTransferState = eSaveTransfer_Error;
break;
}
PSAVE_DETAILS pSaveDetails = StorageManager.ReturnSavesInfo();
int saveInfoIndex = -1;
for (int i = 0; i < pSaveDetails->iSaveC; i++) {
if (strcmp(pSaveDetails->SaveInfoA[i].UTF8SaveFilename,
pClass->m_downloadedUniqueFilename) == 0) {
// found it
saveInfoIndex = i;
}
}
if (saveInfoIndex == -1) {
pClass->m_eSaveTransferState = eSaveTransfer_Error;
app.DebugPrintf(
"CrossSaveGetSavesInfoCallback failed - couldn't find "
"save\n");
} else {
#ifdef __PS3__
// ignore the CRC on PS3
C4JStorage::ESaveGameState eLoadStatus =
StorageManager.LoadSaveData(
&pSaveDetails->SaveInfoA[saveInfoIndex],
&LoadCrossSaveDataCallback, pClass, true);
#else
C4JStorage::ESaveGameState eLoadStatus =
StorageManager.LoadSaveData(
&pSaveDetails->SaveInfoA[saveInfoIndex],
&LoadCrossSaveDataCallback, pClass);
#endif
if (eLoadStatus == C4JStorage::ESaveGame_Load) {
pClass->m_eSaveTransferState =
eSaveTransfer_LoadingSaveFromDisc;
} else {
pClass->m_eSaveTransferState = eSaveTransfer_Error;
}
}
} break;
case eSaveTransfer_LoadingSaveFromDisc:
break;
case eSaveTransfer_CreatingNewSave: {
unsigned int fileSize = StorageManager.GetSaveSize();
byteArray ba(fileSize);
StorageManager.GetSaveData(ba.data, &fileSize);
assert(ba.length == fileSize);
StorageManager.ResetSaveData();
{
std::uint8_t* pbThumbnailData = NULL;
unsigned int dwThumbnailDataSize = 0;
std::uint8_t* pbDataSaveImage = NULL;
unsigned int dwDataSizeSaveImage = 0;
StorageManager.GetDefaultSaveImage(
&pbDataSaveImage,
&dwDataSizeSaveImage); // Get the default save
// thumbnail (as set by
// SetDefaultImages) for use on
// saving games t
StorageManager.GetDefaultSaveThumbnail(
&pbThumbnailData,
&dwThumbnailDataSize); // Get the default save image
// (as set by SetDefaultImages)
// for use on saving games that
std::uint8_t bTextMetadata[88];
ZeroMemory(bTextMetadata, 88);
unsigned int remoteHostOptions =
app.getRemoteStorage()->getSaveHostOptions();
app.SetGameHostOption(eGameHostOption_All,
remoteHostOptions);
int iTextMetadataBytes = app.CreateImageTextData(
bTextMetadata, app.getRemoteStorage()->getSaveSeed(),
true, remoteHostOptions,
app.getRemoteStorage()->getSaveTexturePack());
// set the icon and save image
StorageManager.SetSaveImages(
pbThumbnailData, dwThumbnailDataSize, pbDataSaveImage,
dwDataSizeSaveImage, bTextMetadata, iTextMetadataBytes);
}
#ifdef SPLIT_SAVES
ConsoleSaveFileOriginal oldFormatSave(
wSaveName, ba.data, ba.length, false,
app.getRemoteStorage()->getSavePlatform());
pSave = new ConsoleSaveFileSplit(&oldFormatSave, false,
pMinecraft->progressRenderer);
pMinecraft->progressRenderer->progressStage(
IDS_SAVETRANSFER_STAGE_SAVING);
pSave->Flush(false, false);
pClass->m_eSaveTransferState = eSaveTransfer_Saving;
#else
pSave = new ConsoleSaveFileOriginal(
wSaveName, ba.data, ba.length, false,
app.getRemoteStorage()->getSavePlatform());
pClass->m_eSaveTransferState = eSaveTransfer_Converting;
pMinecraft->progressRenderer->progressStage(
IDS_SAVETRANSFER_STAGE_CONVERTING);
#endif
delete ba.data;
} break;
case eSaveTransfer_Converting: {
pSave->ConvertToLocalPlatform(); // check if we need to convert
// this file from PS3->PS4
pClass->m_eSaveTransferState = eSaveTransfer_Saving;
pMinecraft->progressRenderer->progressStage(
IDS_SAVETRANSFER_STAGE_SAVING);
StorageManager.SetSaveTitle(wSaveName);
StorageManager.SetSaveUniqueFilename(
pClass->m_downloadedUniqueFilename);
app.getRemoteStorage()
->waitForStorageManagerIdle(); // we need to wait for the
// save system to be idle
// here, as Flush doesn't
// check for it.
pSave->Flush(false, false);
} break;
case eSaveTransfer_Saving: {
// On Durango/Orbis, we need to wait for all the asynchronous
// saving processes to complete before destroying the levels, as
// that will ultimately delete the directory level storage &
// therefore the ConsoleSaveSplit instance, which needs to be
// around until all the sub files have completed saving.
#if defined(_DURANGO) || defined(__ORBIS__)
while (StorageManager.GetSaveState() !=
C4JStorage::ESaveGame_Idle) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
StorageManager.Tick();
}
#endif
delete pSave;
pMinecraft->progressRenderer->progressStage(
IDS_PROGRESS_SAVING_TO_DISC);
pClass->m_eSaveTransferState = eSaveTransfer_Succeeded;
} break;
case eSaveTransfer_Succeeded: {
// if we've arrived here, the save has been created successfully
pClass->m_iState = e_SavesRepopulate;
pClass->updateTooltips();
unsigned int uiIDA[1];
uiIDA[0] = IDS_CONFIRM_OK;
app.getRemoteStorage()
->waitForStorageManagerIdle(); // wait for everything to
// complete before we hand
// control back to the
// player
ui.RequestErrorMessage(IDS_TOOLTIPS_SAVETRANSFER_DOWNLOAD,
IDS_SAVE_TRANSFER_DOWNLOADCOMPLETE,
uiIDA, 1, ProfileManager.GetPrimaryPad(),
CrossSaveFinishedCallback, pClass);
pClass->m_eSaveTransferState = eSaveTransfer_Finished;
} break;
case eSaveTransfer_Cancelled: // this is no longer used
{
assert(0); // pClass->m_eSaveTransferState =
// eSaveTransfer_Idle;
} break;
case eSaveTransfer_Error: {
if (bSaveFileCreated) {
if (pClass->m_saveTransferDownloadCancelled) {
wchar_t wcTemp[256];
swprintf(wcTemp, 256,
app.GetString(
IDS_CANCEL)); // MGH - should change this
// string to "cancelling
// download"
m_wstrStageText = wcTemp;
pMinecraft->progressRenderer->progressStage(
m_wstrStageText);
pMinecraft->progressRenderer->progressStage(
m_wstrStageText);
}
// if the save file has already been created we have to
// delete it again if there's been an error
PSAVE_DETAILS pSaveDetails =
StorageManager.ReturnSavesInfo();
int saveInfoIndex = -1;
for (int i = 0; i < pSaveDetails->iSaveC; i++) {
if (strcmp(pSaveDetails->SaveInfoA[i].UTF8SaveFilename,
pClass->m_downloadedUniqueFilename) == 0) {
// found it
saveInfoIndex = i;
}
}
if (saveInfoIndex == -1) {
app.DebugPrintf(
"eSaveTransfer_Error failed - couldn't find "
"save\n");
assert(0);
pClass->m_eSaveTransferState =
eSaveTransfer_ErrorMesssage;
} else {
// delete the save file
app.getRemoteStorage()->waitForStorageManagerIdle();
C4JStorage::ESaveGameState eDeleteStatus =
StorageManager.DeleteSaveData(
&pSaveDetails->SaveInfoA[saveInfoIndex],
UIScene_LoadOrJoinMenu::
CrossSaveDeleteOnErrorReturned,
pClass);
if (eDeleteStatus == C4JStorage::ESaveGame_Delete) {
pClass->m_eSaveTransferState =
eSaveTransfer_ErrorDeletingSave;
} else {
app.DebugPrintf(
"StorageManager.DeleteSaveData failed!!\n");
pClass->m_eSaveTransferState =
eSaveTransfer_ErrorMesssage;
}
}
} else {
pClass->m_eSaveTransferState = eSaveTransfer_ErrorMesssage;
}
} break;
case eSaveTransfer_ErrorDeletingSave:
break;
case eSaveTransfer_ErrorMesssage: {
app.getRemoteStorage()
->waitForStorageManagerIdle(); // wait for everything to
// complete before we hand
// control back to the
// player
if (pClass->m_saveTransferDownloadCancelled) {
pClass->m_eSaveTransferState = eSaveTransfer_Idle;
} else {
unsigned int uiIDA[1];
uiIDA[0] = IDS_CONFIRM_OK;
UINT errorMessage = IDS_SAVE_TRANSFER_DOWNLOADFAILED;
if (!ProfileManager.IsSignedInLive(
ProfileManager.GetPrimaryPad())) {
errorMessage =
IDS_ERROR_NETWORK; // show "A network error has
// occurred."
#ifdef __ORBIS__
if (!ProfileManager.isSignedInPSN(
ProfileManager.GetPrimaryPad())) {
errorMessage =
IDS_PRO_NOTONLINE_TEXT; // show "not signed
// into PSN"
}
#endif
#ifdef __VITA__
if (!ProfileManager.IsSignedInPSN(
ProfileManager.GetPrimaryPad())) {
errorMessage =
IDS_PRO_NOTONLINE_TEXT; // show "not signed
// into PSN"
}
#endif
}
ui.RequestErrorMessage(IDS_TOOLTIPS_SAVETRANSFER_DOWNLOAD,
errorMessage, uiIDA, 1,
ProfileManager.GetPrimaryPad(),
CrossSaveFinishedCallback, pClass);
pClass->m_eSaveTransferState = eSaveTransfer_Finished;
}
if (bSaveFileCreated) // save file has been created, then
// deleted.
pClass->m_iState = e_SavesRepopulateAfterDelete;
else
pClass->m_iState = e_SavesRepopulate;
pClass->updateTooltips();
} break;
case eSaveTransfer_Finished: {
}
// waiting to dismiss the dialog
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
m_bSaveTransferRunning = false;
#ifdef __PS3__
StorageManager.SetSaveTransferInProgress(false);
#endif
return 0;
}
void UIScene_LoadOrJoinMenu::SaveTransferReturned(void* lpParam,
SonyRemoteStorage::Status s,
int error_code) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)lpParam;
if (s == SonyRemoteStorage::e_getDataSucceeded) {
pClass->m_eSaveTransferState = eSaveTransfer_FileDataRetrieved;
} else {
pClass->m_eSaveTransferState = eSaveTransfer_Error;
app.DebugPrintf(
"SaveTransferReturned failed with error code : 0x%08x\n",
error_code);
}
}
ConsoleSaveFile* UIScene_LoadOrJoinMenu::SonyCrossSaveConvert() { return NULL; }
void UIScene_LoadOrJoinMenu::CancelSaveTransferCallback(void* lpParam) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)lpParam;
pClass->m_saveTransferDownloadCancelled = true;
ui.SetTooltips(
DEFAULT_XUI_MENU_USER, -1, -1, -1, -1, -1, -1, -1,
-1); // MGH - added - remove the "cancel" tooltip, so the player knows
// it's underway (really needs a "cancelling" message)
}
#endif
#ifdef SONY_REMOTE_STORAGE_UPLOAD
void UIScene_LoadOrJoinMenu::LaunchSaveUpload() {
LoadingInputParams* loadingParams = new LoadingInputParams();
loadingParams->func =
&UIScene_LoadOrJoinMenu::UploadSonyCrossSaveThreadProc;
loadingParams->lpParam = this;
UIFullscreenProgressCompletionData* completionData =
new UIFullscreenProgressCompletionData();
completionData->bShowBackground = TRUE;
completionData->bShowLogo = TRUE;
completionData->type = e_ProgressCompletion_NavigateBackToScene;
completionData->iPad = DEFAULT_XUI_MENU_USER;
loadingParams->completionData = completionData;
// 4J-PB - Waiting for Sony to fix canceling a save upload
loadingParams->cancelFunc =
&UIScene_LoadOrJoinMenu::CancelSaveUploadCallback;
loadingParams->m_cancelFuncParam = this;
loadingParams->cancelText = IDS_TOOLTIPS_CANCEL;
ui.NavigateToScene(m_iPad, eUIScene_FullscreenProgress, loadingParams);
}
int UIScene_LoadOrJoinMenu::CrossSaveUploadFinishedCallback(
void* pParam, int iPad, C4JStorage::EMessageResult result) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam;
pClass->m_eSaveUploadState = eSaveUpload_Idle;
return 0;
}
int UIScene_LoadOrJoinMenu::UploadSonyCrossSaveThreadProc(void* lpParameter) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)lpParameter;
pClass->m_saveTransferUploadCancelled = false;
bool bAbortCalled = false;
Minecraft* pMinecraft = Minecraft::GetInstance();
// get the save file size
pMinecraft->progressRenderer->progressStagePercentage(0);
pMinecraft->progressRenderer->progressStart(
IDS_TOOLTIPS_SAVETRANSFER_UPLOAD);
pMinecraft->progressRenderer->progressStage(
IDS_TOOLTIPS_SAVETRANSFER_UPLOAD);
PSAVE_DETAILS pSaveDetails = StorageManager.ReturnSavesInfo();
int idx = pClass->m_iSaveListIndex - pClass->m_iDefaultButtonsC;
bool bSettingOK = app.getRemoteStorage()->setSaveData(
&pSaveDetails->SaveInfoA[idx], SaveUploadReturned, pClass);
if (bSettingOK) {
pClass->m_eSaveUploadState = eSaveUpload_UploadingFileData;
pMinecraft->progressRenderer->progressStagePercentage(0);
} else {
pClass->m_eSaveUploadState = eSaveUpload_Error;
}
while (pClass->m_eSaveUploadState != eSaveUpload_Idle) {
switch (pClass->m_eSaveUploadState) {
case eSaveUpload_Idle:
break;
case eSaveUpload_UploadingFileData: {
wchar_t wcTemp[256];
int dataProgress = app.getRemoteStorage()->getDataProgress();
pMinecraft->progressRenderer->progressStagePercentage(
dataProgress);
// swprintf(wcTemp, 256, L"Uploading data : %d",
// dataProgress);//app.GetString(IDS_SAVETRANSFER_STAGE_GET_DATA),0,pClass->m_ulFileSize);
swprintf(wcTemp, 256,
app.GetString(IDS_SAVETRANSFER_STAGE_PUT_DATA),
dataProgress);
m_wstrStageText = wcTemp;
pMinecraft->progressRenderer->progressStage(m_wstrStageText);
// 4J-PB - Waiting for Sony to fix canceling a save upload
if (pClass->m_saveTransferUploadCancelled &&
bAbortCalled == false) {
// we only really want to be able to cancel during the
// download of data, if it's taking a long time
app.getRemoteStorage()->abort();
bAbortCalled = true;
}
} break;
case eSaveUpload_FileDataUploaded: {
unsigned int uiIDA[1];
uiIDA[0] = IDS_CONFIRM_OK;
ui.RequestErrorMessage(IDS_TOOLTIPS_SAVETRANSFER_UPLOAD,
IDS_SAVE_TRANSFER_UPLOADCOMPLETE, uiIDA,
1, ProfileManager.GetPrimaryPad(),
CrossSaveUploadFinishedCallback, pClass);
pClass->m_eSaveUploadState = esaveUpload_Finished;
} break;
case eSaveUpload_Cancelled: // this is no longer used
assert(0); // pClass->m_eSaveUploadState =
// eSaveUpload_Idle;
break;
case eSaveUpload_Error: {
if (pClass->m_saveTransferUploadCancelled) {
pClass->m_eSaveUploadState = eSaveUpload_Idle;
} else {
unsigned int uiIDA[1];
uiIDA[0] = IDS_CONFIRM_OK;
ui.RequestErrorMessage(
IDS_TOOLTIPS_SAVETRANSFER_UPLOAD,
IDS_SAVE_TRANSFER_UPLOADFAILED, uiIDA, 1,
ProfileManager.GetPrimaryPad(),
CrossSaveUploadFinishedCallback, pClass);
pClass->m_eSaveUploadState = esaveUpload_Finished;
}
} break;
case esaveUpload_Finished:
// waiting for dialog to be dismissed
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
return 0;
}
void UIScene_LoadOrJoinMenu::SaveUploadReturned(void* lpParam,
SonyRemoteStorage::Status s,
int error_code) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)lpParam;
if (pClass->m_saveTransferUploadCancelled) {
unsigned int uiIDA[1] = {IDS_CONFIRM_OK};
ui.RequestErrorMessage(IDS_CANCEL_UPLOAD_TITLE, IDS_CANCEL_UPLOAD_TEXT,
uiIDA, 1, ProfileManager.GetPrimaryPad(),
CrossSaveUploadFinishedCallback, pClass);
pClass->m_eSaveUploadState = esaveUpload_Finished;
} else {
if (s == SonyRemoteStorage::e_setDataSucceeded)
pClass->m_eSaveUploadState = eSaveUpload_FileDataUploaded;
else if (!pClass->m_saveTransferUploadCancelled)
pClass->m_eSaveUploadState = eSaveUpload_Error;
}
}
void UIScene_LoadOrJoinMenu::CancelSaveUploadCallback(void* lpParam) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)lpParam;
pClass->m_saveTransferUploadCancelled = true;
app.DebugPrintf("m_saveTransferUploadCancelled = true\n");
ui.SetTooltips(
DEFAULT_XUI_MENU_USER, -1, -1, -1, -1, -1, -1, -1,
-1); // MGH - added - remove the "cancel" tooltip, so the player knows
// it's underway (really needs a "cancelling" message)
pClass->m_bIgnoreInput = true;
}
int UIScene_LoadOrJoinMenu::SaveTransferDialogReturned(
void* pParam, int iPad, C4JStorage::EMessageResult result) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam;
// results switched for this dialog
if (result == C4JStorage::EMessage_ResultAccept) {
// upload the save
pClass->LaunchSaveUpload();
pClass->m_bIgnoreInput = false;
} else {
pClass->m_bIgnoreInput = false;
}
return 0;
}
#endif // SONY_REMOTE_STORAGE_UPLOAD
#if defined _XBOX_ONE
void UIScene_LoadOrJoinMenu::LaunchSaveTransfer() {
SaveTransferStateContainer* stateContainer =
new SaveTransferStateContainer();
stateContainer->m_iProgress = 0;
stateContainer->m_bSaveTransferInProgress = false;
stateContainer->m_bSaveTransferCancelled = false;
stateContainer->m_iPad = m_iPad;
stateContainer->m_eSaveTransferState = C4JStorage::eSaveTransfer_Idle;
stateContainer->m_pClass = this;
LoadingInputParams* loadingParams = new LoadingInputParams();
loadingParams->func =
&UIScene_LoadOrJoinMenu::DownloadXbox360SaveThreadProc;
loadingParams->lpParam = stateContainer;
UIFullscreenProgressCompletionData* completionData =
new UIFullscreenProgressCompletionData();
completionData->bShowBackground = TRUE;
completionData->bShowLogo = TRUE;
completionData->type = e_ProgressCompletion_NavigateBackToScene;
completionData->iPad = DEFAULT_XUI_MENU_USER;
completionData->bRequiresUserAction = TRUE;
loadingParams->completionData = completionData;
loadingParams->cancelFunc =
&UIScene_LoadOrJoinMenu::CancelSaveTransferCallback;
loadingParams->m_cancelFuncParam = stateContainer;
loadingParams->cancelText = IDS_TOOLTIPS_CANCEL;
ui.NavigateToScene(m_iPad, eUIScene_FullscreenProgress, loadingParams);
}
int UIScene_LoadOrJoinMenu::DownloadXbox360SaveThreadProc(void* lpParameter) {
Compression::UseDefaultThreadStorage();
SaveTransferStateContainer* pStateContainer =
(SaveTransferStateContainer*)lpParameter;
Minecraft* pMinecraft = Minecraft::GetInstance();
ConsoleSaveFile* pSave = NULL;
while (StorageManager.SaveTransferClearState() !=
C4JStorage::eSaveTransfer_Idle) {
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
pStateContainer->m_bSaveTransferInProgress = true;
UIScene_LoadOrJoinMenu::s_eSaveTransferFile = eSaveTransferFile_Marker;
RequestFileSize(pStateContainer, L"completemarker");
while ((pStateContainer->m_eSaveTransferState !=
C4JStorage::eSaveTransfer_Idle) &&
pStateContainer->m_bSaveTransferInProgress &&
!pStateContainer->m_bSaveTransferCancelled) {
switch (pStateContainer->m_eSaveTransferState) {
case C4JStorage::eSaveTransfer_Idle:
break;
case C4JStorage::eSaveTransfer_FileSizeRetrieved:
switch (UIScene_LoadOrJoinMenu::s_eSaveTransferFile) {
case eSaveTransferFile_Marker:
if (UIScene_LoadOrJoinMenu::s_ulFileSize == 0) {
pMinecraft->progressRenderer->progressStage(
IDS_SAVETRANSFER_NONE_FOUND);
pStateContainer->m_eSaveTransferState =
C4JStorage::eSaveTransfer_Idle;
} else {
RequestFileData(pStateContainer, L"completemarker");
}
break;
case eSaveTransferFile_Metadata:
RequestFileData(pStateContainer, L"metadata");
break;
case eSaveTransferFile_SaveData:
RequestFileData(pStateContainer, L"savedata");
break;
};
break;
case C4JStorage::eSaveTransfer_GettingFileData:
break;
case C4JStorage::eSaveTransfer_FileDataRetrieved:
switch (UIScene_LoadOrJoinMenu::s_eSaveTransferFile) {
case eSaveTransferFile_Marker:
// MGH - the marker file now contains the save file
// version number if the version is higher than we
// handle, cancel the download.
if (UIScene_LoadOrJoinMenu::s_transferData[0] >
SAVE_FILE_VERSION_NUMBER) {
pMinecraft->progressRenderer->progressStage(
IDS_SAVETRANSFER_NONE_FOUND);
pStateContainer->m_eSaveTransferState =
C4JStorage::eSaveTransfer_Idle;
} else {
UIScene_LoadOrJoinMenu::s_eSaveTransferFile =
eSaveTransferFile_Metadata;
RequestFileSize(pStateContainer, L"metadata");
}
break;
case eSaveTransferFile_Metadata: {
ByteArrayInputStream bais(
UIScene_LoadOrJoinMenu::s_transferData);
DataInputStream dis(&bais);
std::wstring saveTitle = dis.readUTF();
StorageManager.SetSaveTitle(saveTitle.c_str());
std::wstring saveUniqueName = dis.readUTF();
// 4J Stu - Don't set this any more. We added it so that
// we could share the ban list data for this save
// However if the player downloads the same save
// multiple times, it will overwrite the previous
// version with that filname, and they could have made
// changes to it.
// StorageManager.SetSaveUniqueFilename((wchar_t
// *)saveUniqueName.c_str());
int thumbnailSize = dis.readInt();
if (thumbnailSize > 0) {
byteArray ba(thumbnailSize);
dis.readFully(ba);
// retrieve the seed value from the image metadata,
// we need to change to host options, then set it
// back again
bool bHostOptionsRead = false;
unsigned int uiHostOptions = 0;
DWORD dwTexturePack;
int64_t seedVal;
char szSeed[50];
ZeroMemory(szSeed, 50);
app.GetImageTextData(
ba.data, ba.length, (unsigned char*)&szSeed,
uiHostOptions, bHostOptionsRead, dwTexturePack);
sscanf_s(szSeed, "%I64d", &seedVal);
app.SetGameHostOption(
uiHostOptions, eGameHostOption_WorldSize,
e_worldSize_Classic); // force the classic
// world size on,
// otherwise it's unknown
// and we can't expand
BYTE bTextMetadata[88];
ZeroMemory(bTextMetadata, 88);
int iTextMetadataBytes = app.CreateImageTextData(
bTextMetadata, seedVal, true, uiHostOptions,
dwTexturePack);
// set the icon and save image
StorageManager.SetSaveImages(ba.data, ba.length,
NULL, 0, bTextMetadata,
iTextMetadataBytes);
delete ba.data;
}
UIScene_LoadOrJoinMenu::s_transferData = byteArray();
UIScene_LoadOrJoinMenu::s_eSaveTransferFile =
eSaveTransferFile_SaveData;
RequestFileSize(pStateContainer, L"savedata");
} break;
case eSaveTransferFile_SaveData: {
#ifdef SPLIT_SAVES
if (!pStateContainer->m_bSaveTransferCancelled) {
ConsoleSaveFileOriginal oldFormatSave(
L"Temp name",
UIScene_LoadOrJoinMenu::s_transferData.data,
UIScene_LoadOrJoinMenu::s_transferData.length,
false, SAVE_FILE_PLATFORM_X360);
pSave = new ConsoleSaveFileSplit(
&oldFormatSave, false,
pMinecraft->progressRenderer);
pMinecraft->progressRenderer->progressStage(
IDS_SAVETRANSFER_STAGE_SAVING);
if (!pStateContainer->m_bSaveTransferCancelled)
pSave->Flush(false, false);
}
pStateContainer->m_eSaveTransferState =
C4JStorage::eSaveTransfer_Saving;
#else
pSave = new ConsoleSaveFileOriginal(
wSaveName, m_transferData.data,
m_transferData.length, false,
SAVE_FILE_PLATFORM_X360);
pStateContainer->m_eSaveTransferState =
C4JStorage::eSaveTransfer_Converting;
#endif
delete UIScene_LoadOrJoinMenu::s_transferData.data;
UIScene_LoadOrJoinMenu::s_transferData = byteArray();
} break;
};
pStateContainer->m_iProgress = 0;
break;
case C4JStorage::eSaveTransfer_Converting:
#if 0
pSave->ConvertToLocalPlatform();
pMinecraft->progressRenderer->progressStage(IDS_SAVETRANSFER_STAGE_SAVING);
if(!pStateContainer->m_bSaveTransferCancelled) pSave->Flush(false,false);
pStateContainer->m_iProgress+=1;
if(pStateContainer->m_iProgress==101)
{
pStateContainer->m_eSaveTransferState=C4JStorage::eSaveTransfer_Saving;
pStateContainer->m_iProgress=0;
break;
}
pMinecraft->progressRenderer->progressStagePercentage(pStateContainer->m_iProgress);
#endif
break;
case C4JStorage::eSaveTransfer_Saving:
// On Durango/Orbis, we need to wait for all the asynchronous
// saving processes to complete before destroying the levels, as
// that will ultimately delete the directory level storage &
// therefore the ConsoleSaveSplit instance, which needs to be
// around until all the sub files have completed saving.
#if defined(_DURANGO) || defined(__ORBIS__)
pMinecraft->progressRenderer->progressStage(
IDS_PROGRESS_SAVING_TO_DISC);
while (StorageManager.GetSaveState() !=
C4JStorage::ESaveGame_Idle) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
// 4J Stu - DO NOT tick this here. The main thread should be
// the only place ticking the StorageManager. You WILL get
// crashes.
// StorageManager.Tick();
}
#endif
delete pSave;
#ifdef _XBOX_ONE
pMinecraft->progressRenderer->progressStage(
IDS_SAVE_TRANSFER_DOWNLOAD_AND_CONVERT_COMPLETE);
#endif
pStateContainer->m_eSaveTransferState =
C4JStorage::eSaveTransfer_Idle;
// wipe the list and repopulate it
if (!pStateContainer->m_bSaveTransferCancelled)
pStateContainer->m_pClass->m_iState =
e_SavesRepopulateAfterTransferDownload;
// pClass->m_iProgress+=1;
// if(pClass->m_iProgress==101)
//{
// pClass->m_iProgress=0;
// pClass->m_eSaveTransferState=C4JStorage::eSaveTransfer_Idle;
// pMinecraft->progressRenderer->progressStage(
// IDS_SAVE_TRANSFER_DOWNLOAD_AND_CONVERT_COMPLETE );
// break;
//}
// pMinecraft->progressRenderer->progressStagePercentage(pClass->m_iProgress);
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
if (pStateContainer->m_bSaveTransferCancelled) {
wchar_t wcTemp[256];
pStateContainer->m_bSaveTransferCancelled = false;
swprintf(wcTemp, app.GetString(IDS_SAVE_TRANSFER_DOWNLOAD_CANCELLED));
m_wstrStageText = wcTemp;
pMinecraft->progressRenderer->progressStage(m_wstrStageText);
}
pStateContainer->m_eSaveTransferState = C4JStorage::eSaveTransfer_Idle;
pStateContainer->m_bSaveTransferInProgress = false;
delete pStateContainer;
return 0;
}
void UIScene_LoadOrJoinMenu::RequestFileSize(SaveTransferStateContainer* pClass,
wchar_t* filename) {
Minecraft* pMinecraft = Minecraft::GetInstance();
// get the save file size
pMinecraft->progressRenderer->progressStart(IDS_SAVETRANSFER_TITLE_GET);
pMinecraft->progressRenderer->progressStage(
IDS_SAVETRANSFER_STAGE_GET_DETAILS);
#ifdef _DEBUG_MENUS_ENABLED
if (app.GetLoadSavesFromFolderEnabled()) {
ZeroMemory(&m_debugTransferDetails,
sizeof(C4JStorage::SAVETRANSFER_FILE_DETAILS));
File targetFile(std::wstring(L"FakeTMSPP\\").append(filename));
if (targetFile.exists())
m_debugTransferDetails.ulFileLen = targetFile.length();
SaveTransferReturned(pClass, &m_debugTransferDetails);
} else
#endif
{
do {
pMinecraft->progressRenderer->progressStart(
IDS_SAVETRANSFER_TITLE_GET);
pMinecraft->progressRenderer->progressStage(
IDS_SAVETRANSFER_STAGE_GET_DETAILS);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
pClass->m_eSaveTransferState =
StorageManager.SaveTransferGetDetails(
pClass->m_iPad, C4JStorage::eGlobalStorage_TitleUser,
filename, &UIScene_LoadOrJoinMenu::SaveTransferReturned,
pClass);
} while (pClass->m_eSaveTransferState ==
C4JStorage::eSaveTransfer_Busy &&
!pClass->m_bSaveTransferCancelled);
}
}
void UIScene_LoadOrJoinMenu::RequestFileData(SaveTransferStateContainer* pClass,
wchar_t* filename) {
Minecraft* pMinecraft = Minecraft::GetInstance();
wchar_t wcTemp[256];
pMinecraft->progressRenderer->progressStagePercentage(0);
swprintf(wcTemp, app.GetString(IDS_SAVETRANSFER_STAGE_GET_DATA), 0,
UIScene_LoadOrJoinMenu::s_ulFileSize);
m_wstrStageText = wcTemp;
pMinecraft->progressRenderer->progressStage(m_wstrStageText);
#ifdef _DEBUG_MENUS_ENABLED
if (app.GetLoadSavesFromFolderEnabled()) {
File targetFile(std::wstring(L"FakeTMSPP\\").append(filename));
if (targetFile.exists()) {
const std::size_t fileLength =
static_cast<std::size_t>(m_debugTransferDetails.ulFileLen);
m_debugTransferDetails.pbData = new std::uint8_t[fileLength];
const PortableFileIO::BinaryReadResult readResult =
PortableFileIO::ReadBinaryFile(targetFile.getPath(),
m_debugTransferDetails.pbData,
fileLength);
assert(readResult.status == PortableFileIO::BinaryReadStatus::ok);
assert(readResult.bytesRead == fileLength);
if ((readResult.status == PortableFileIO::BinaryReadStatus::ok) &&
(readResult.bytesRead == fileLength)) {
SaveTransferReturned(pClass, &m_debugTransferDetails);
} else {
delete[] m_debugTransferDetails.pbData;
m_debugTransferDetails.pbData = NULL;
}
}
} else
#endif
{
do {
pMinecraft->progressRenderer->progressStart(
IDS_SAVETRANSFER_TITLE_GET);
pMinecraft->progressRenderer->progressStage(-1);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
pClass->m_eSaveTransferState = StorageManager.SaveTransferGetData(
pClass->m_iPad, C4JStorage::eGlobalStorage_TitleUser, filename,
&UIScene_LoadOrJoinMenu::SaveTransferReturned,
&UIScene_LoadOrJoinMenu::SaveTransferUpdateProgress, pClass,
pClass);
} while (pClass->m_eSaveTransferState ==
C4JStorage::eSaveTransfer_Busy &&
!pClass->m_bSaveTransferCancelled);
}
}
int UIScene_LoadOrJoinMenu::SaveTransferReturned(
void* lpParam,
C4JStorage::SAVETRANSFER_FILE_DETAILS* pSaveTransferDetails) {
SaveTransferStateContainer* pClass = (SaveTransferStateContainer*)lpParam;
app.DebugPrintf("Save Transfer - size is %d\n",
pSaveTransferDetails->ulFileLen);
// if the file data is null, then assume this is the file size retrieval
if (pSaveTransferDetails->pbData == NULL) {
pClass->m_eSaveTransferState =
C4JStorage::eSaveTransfer_FileSizeRetrieved;
UIScene_LoadOrJoinMenu::s_ulFileSize = pSaveTransferDetails->ulFileLen;
} else {
delete UIScene_LoadOrJoinMenu::s_transferData.data;
UIScene_LoadOrJoinMenu::s_transferData = byteArray(
pSaveTransferDetails->pbData, UIScene_LoadOrJoinMenu::s_ulFileSize);
pClass->m_eSaveTransferState =
C4JStorage::eSaveTransfer_FileDataRetrieved;
}
return 0;
}
int UIScene_LoadOrJoinMenu::SaveTransferUpdateProgress(
void* lpParam, unsigned long ulBytesReceived) {
wchar_t wcTemp[256];
SaveTransferStateContainer* pClass = (SaveTransferStateContainer*)lpParam;
Minecraft* pMinecraft = Minecraft::GetInstance();
if (pClass->m_bSaveTransferCancelled) // was cancelled
{
pMinecraft->progressRenderer->progressStage(
IDS_SAVE_TRANSFER_DOWNLOAD_CANCELLING);
swprintf(wcTemp, app.GetString(IDS_SAVE_TRANSFER_DOWNLOAD_CANCELLING));
m_wstrStageText = wcTemp;
pMinecraft->progressRenderer->progressStage(m_wstrStageText);
} else {
unsigned int uiProgress =
(unsigned int)(((float)ulBytesReceived /
float(UIScene_LoadOrJoinMenu::s_ulFileSize)) *
100.0f);
pMinecraft->progressRenderer->progressStagePercentage(uiProgress);
swprintf(wcTemp, app.GetString(IDS_SAVETRANSFER_STAGE_GET_DATA),
((float)(ulBytesReceived)) / 1024000.0f,
((float)UIScene_LoadOrJoinMenu::s_ulFileSize) / 1024000.0f);
m_wstrStageText = wcTemp;
pMinecraft->progressRenderer->progressStage(m_wstrStageText);
}
return 0;
}
void UIScene_LoadOrJoinMenu::CancelSaveTransferCallback(void* lpParam) {
SaveTransferStateContainer* pClass = (SaveTransferStateContainer*)lpParam;
if (!pClass->m_bSaveTransferCancelled) {
StorageManager.CancelSaveTransfer(
UIScene_LoadOrJoinMenu::CancelSaveTransferCompleteCallback, pClass);
pClass->m_bSaveTransferCancelled = true;
}
// pClass->m_bSaveTransferInProgress=false;
}
int UIScene_LoadOrJoinMenu::CancelSaveTransferCompleteCallback(void* lpParam) {
SaveTransferStateContainer* pClass = (SaveTransferStateContainer*)lpParam;
// change the state to idle to get the download thread to terminate
pClass->m_eSaveTransferState = C4JStorage::eSaveTransfer_Idle;
return 0;
}
int UIScene_LoadOrJoinMenu::NeedSyncMessageReturned(
void* pParam, int iPad, C4JStorage::EMessageResult result) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam;
LoadMenuInitData* params = (LoadMenuInitData*)pParam;
if (result == C4JStorage::EMessage_ResultAccept) {
// navigate to the settings scene
ui.NavigateToScene(ProfileManager.GetPrimaryPad(), eUIScene_LoadMenu,
pClass->m_loadMenuInitData);
} else {
delete pClass->m_loadMenuInitData;
pClass->m_bIgnoreInput = false;
}
return 0;
}
#endif
#ifdef _XBOX_ONE
void UIScene_LoadOrJoinMenu::HandleDLCLicenseChange() {
// may have installed Halloween on this menu
app.StartInstallDLCProcess(m_iPad);
}
#endif
#if defined _XBOX_ONE || defined __ORBIS__
int UIScene_LoadOrJoinMenu::CopySaveDialogReturned(
void* pParam, int iPad, C4JStorage::EMessageResult result) {
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)pParam;
if (result == C4JStorage::EMessage_ResultAccept) {
LoadingInputParams* loadingParams = new LoadingInputParams();
void* uniqueId = reinterpret_cast<void*>(pClass->GetCallbackUniqueId());
loadingParams->func = &UIScene_LoadOrJoinMenu::CopySaveThreadProc;
loadingParams->lpParam = uniqueId;
loadingParams->waitForThreadToDelete = true;
UIFullscreenProgressCompletionData* completionData =
new UIFullscreenProgressCompletionData();
completionData->bShowBackground = TRUE;
completionData->bShowLogo = TRUE;
completionData->type = e_ProgressCompletion_NavigateBackToScene;
completionData->iPad = DEFAULT_XUI_MENU_USER;
loadingParams->completionData = completionData;
loadingParams->cancelFunc =
&UIScene_LoadOrJoinMenu::CancelCopySaveCallback;
loadingParams->m_cancelFuncParam = uniqueId;
loadingParams->cancelText = IDS_TOOLTIPS_CANCEL;
ui.NavigateToScene(iPad, eUIScene_FullscreenProgress, loadingParams);
} else {
pClass->m_bIgnoreInput = false;
}
return 0;
}
int UIScene_LoadOrJoinMenu::CopySaveThreadProc(void* lpParameter) {
Minecraft* pMinecraft = Minecraft::GetInstance();
pMinecraft->progressRenderer->progressStart(IDS_PROGRESS_COPYING_SAVE);
pMinecraft->progressRenderer->progressStage(-1);
ui.EnterCallbackIdCriticalSection();
UIScene_LoadOrJoinMenu* pClass =
(UIScene_LoadOrJoinMenu*)ui.GetSceneFromCallbackId((size_t)lpParameter);
if (pClass) {
pClass->m_bCopying = true;
pClass->m_bCopyingCancelled = false;
ui.LeaveCallbackIdCriticalSection();
// Copy save data takes two callbacks - one for completion, and one for
// progress. The progress callback also lets us cancel the operation, if
// we return false.
StorageManager.CopySaveData(
&pClass->m_pSaveDetails->SaveInfoA[pClass->m_iSaveListIndex -
pClass->m_iDefaultButtonsC],
UIScene_LoadOrJoinMenu::CopySaveDataReturned,
UIScene_LoadOrJoinMenu::CopySaveDataProgress, lpParameter);
bool bContinue = true;
do {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
ui.EnterCallbackIdCriticalSection();
pClass = (UIScene_LoadOrJoinMenu*)ui.GetSceneFromCallbackId(
(size_t)lpParameter);
if (pClass) {
bContinue = pClass->m_bCopying;
} else {
bContinue = false;
}
ui.LeaveCallbackIdCriticalSection();
} while (bContinue);
} else {
ui.LeaveCallbackIdCriticalSection();
}
return 0;
}
int UIScene_LoadOrJoinMenu::CopySaveDataReturned(
void* lpParam, bool success, C4JStorage::ESaveGameState stat) {
ui.EnterCallbackIdCriticalSection();
UIScene_LoadOrJoinMenu* pClass =
(UIScene_LoadOrJoinMenu*)ui.GetSceneFromCallbackId((size_t)lpParam);
if (pClass) {
if (success) {
pClass->m_bCopying = false;
// wipe the list and repopulate it
pClass->m_iState = e_SavesRepopulateAfterDelete;
ui.LeaveCallbackIdCriticalSection();
} else {
#ifdef __ORBIS__
unsigned int uiIDA[1];
// you cancelled the save on exit after choosing exit and save? You
// go back to the Exit choices then.
uiIDA[0] = IDS_OK;
if (stat == C4JStorage::ESaveGame_CopyCompleteFailLocalStorage) {
ui.LeaveCallbackIdCriticalSection();
ui.RequestErrorMessage(
IDS_COPYSAVE_FAILED_TITLE, IDS_COPYSAVE_FAILED_LOCAL, uiIDA,
1, ProfileManager.GetPrimaryPad(),
CopySaveErrorDialogFinishedCallback, lpParam);
} else if (stat == C4JStorage::ESaveGame_CopyCompleteFailQuota) {
ui.LeaveCallbackIdCriticalSection();
ui.RequestErrorMessage(
IDS_COPYSAVE_FAILED_TITLE, IDS_COPYSAVE_FAILED_QUOTA, uiIDA,
1, ProfileManager.GetPrimaryPad(),
CopySaveErrorDialogFinishedCallback, lpParam);
} else {
pClass->m_bCopying = false;
ui.LeaveCallbackIdCriticalSection();
}
#else
pClass->m_bCopying = false;
ui.LeaveCallbackIdCriticalSection();
#endif
}
} else {
ui.LeaveCallbackIdCriticalSection();
}
return 0;
}
bool UIScene_LoadOrJoinMenu::CopySaveDataProgress(void* lpParam, int percent) {
bool bContinue = false;
ui.EnterCallbackIdCriticalSection();
UIScene_LoadOrJoinMenu* pClass =
(UIScene_LoadOrJoinMenu*)ui.GetSceneFromCallbackId((size_t)lpParam);
if (pClass) {
bContinue = !pClass->m_bCopyingCancelled;
}
ui.LeaveCallbackIdCriticalSection();
Minecraft* pMinecraft = Minecraft::GetInstance();
pMinecraft->progressRenderer->progressStagePercentage(percent);
return bContinue;
}
void UIScene_LoadOrJoinMenu::CancelCopySaveCallback(void* lpParam) {
ui.EnterCallbackIdCriticalSection();
UIScene_LoadOrJoinMenu* pClass =
(UIScene_LoadOrJoinMenu*)ui.GetSceneFromCallbackId((size_t)lpParam);
if (pClass) {
pClass->m_bCopyingCancelled = true;
}
ui.LeaveCallbackIdCriticalSection();
}
int UIScene_LoadOrJoinMenu::CopySaveErrorDialogFinishedCallback(
void* pParam, int iPad, C4JStorage::EMessageResult result) {
ui.EnterCallbackIdCriticalSection();
UIScene_LoadOrJoinMenu* pClass =
(UIScene_LoadOrJoinMenu*)ui.GetSceneFromCallbackId((size_t)pParam);
if (pClass) {
pClass->m_bCopying = false;
}
ui.LeaveCallbackIdCriticalSection();
return 0;
}
#endif // _XBOX_ONE