Files
MinecraftConsoles/Minecraft.Client/Common/Consoles_App.cpp
Loki Rautio 087b7e7abf Revert "Project modernization (#630)"
This code was not tested and breaks in Release builds, reverting to restore
functionality of the nightly. All in-game menus do not work and generating
a world crashes.

This reverts commit a9be52c41a.
2026-03-07 21:12:22 -06:00

10209 lines
304 KiB
C++

#include "stdafx.h"
#include "..\..\Minecraft.World\net.minecraft.world.entity.item.h"
#include "..\..\Minecraft.World\net.minecraft.world.entity.player.h"
#include "..\..\Minecraft.World\net.minecraft.world.level.tile.entity.h"
#include "..\..\Minecraft.World\net.minecraft.world.phys.h"
#include "..\..\Minecraft.World\InputOutputStream.h"
#include "..\..\Minecraft.World\compression.h"
#include "..\Options.h"
#include "..\MinecraftServer.h"
#include "..\MultiPlayerLevel.h"
#include "..\GameRenderer.h"
#include "..\ProgressRenderer.h"
#include "..\LevelRenderer.h"
#include "..\MobSkinMemTextureProcessor.h"
#include "..\Minecraft.h"
#include "..\ClientConnection.h"
#include "..\MultiPlayerLocalPlayer.h"
#include "..\LocalPlayer.h"
#include "..\..\Minecraft.World\Player.h"
#include "..\..\Minecraft.World\Inventory.h"
#include "..\..\Minecraft.World\Level.h"
#include "..\..\Minecraft.World\FurnaceTileEntity.h"
#include "..\..\Minecraft.World\Container.h"
#include "..\..\Minecraft.World\DispenserTileEntity.h"
#include "..\..\Minecraft.World\SignTileEntity.h"
#include "..\StatsCounter.h"
#include "..\GameMode.h"
#include "..\Xbox\Social\SocialManager.h"
#include "Tutorial\TutorialMode.h"
#if defined _XBOX || defined _WINDOWS64
#include "..\Xbox\XML\ATGXmlParser.h"
#include "..\Xbox\XML\xmlFilesCallback.h"
#endif
#include "Minecraft_Macros.h"
#include "..\PlayerList.h"
#include "..\ServerPlayer.h"
#include "GameRules\ConsoleGameRules.h"
#include "GameRules\ConsoleSchematicFile.h"
#include "..\User.h"
#include "..\..\Minecraft.World\LevelData.h"
#include "..\..\Minecraft.World\net.minecraft.world.entity.player.h"
#include "..\EntityRenderDispatcher.h"
#include "..\..\Minecraft.World\compression.h"
#include "..\TexturePackRepository.h"
#include "..\DLCTexturePack.h"
#include "DLC\DLCPack.h"
#include "..\StringTable.h"
#ifndef _XBOX
#include "..\ArchiveFile.h"
#endif
#include "..\Minecraft.h"
#ifdef _XBOX
#include "..\Xbox\GameConfig\Minecraft.spa.h"
#include "..\Xbox\Network\NetworkPlayerXbox.h"
#include "XUI\XUI_TextEntry.h"
#include "XUI\XUI_XZP_Icons.h"
#include "XUI\XUI_PauseMenu.h"
#else
#include "UI\UI.h"
#include "UI\UIScene_PauseMenu.h"
#endif
#ifdef __PS3__
#include <sys/tty.h>
#endif
#ifdef __ORBIS__
#include <save_data_dialog.h>
#endif
#include "..\Common\Leaderboards\LeaderboardManager.h"
//CMinecraftApp app;
unsigned int CMinecraftApp::m_uiLastSignInData = 0;
const float CMinecraftApp::fSafeZoneX = 64.0f; // 5% of 1280
const float CMinecraftApp::fSafeZoneY = 36.0f; // 5% of 720
int CMinecraftApp::s_iHTMLFontSizesA[eHTMLSize_COUNT] =
{
#ifdef _XBOX
14,12,14,24
#else
//20,15,20,24
20,13,20,26
#endif
};
CMinecraftApp::CMinecraftApp()
{
if(GAME_SETTINGS_PROFILE_DATA_BYTES != sizeof(GAME_SETTINGS))
{
// 4J Stu - See comment for GAME_SETTINGS_PROFILE_DATA_BYTES in Xbox_App.h
DebugPrintf("WARNING: The size of the profile GAME_SETTINGS struct has changed, so all stat data is likely incorrect. Is: %d, Should be: %d\n",sizeof(GAME_SETTINGS),GAME_SETTINGS_PROFILE_DATA_BYTES);
#ifndef _CONTENT_PACKAGE
__debugbreak();
#endif
}
for(int i=0;i<XUSER_MAX_COUNT;i++)
{
m_eTMSAction[i]=eTMSAction_Idle;
m_eXuiAction[i]=eAppAction_Idle;
m_eXuiActionParam[i] = NULL;
//m_dwAdditionalModelParts[i] = 0;
if(FAILED(XUserGetSigninInfo(i,XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY ,&m_currentSigninInfo[i])))
{
m_currentSigninInfo[i].xuid = INVALID_XUID;
m_currentSigninInfo[i].dwGuestNumber = 0;
}
DebugPrintf("Player at index %d has guest number %d\n", i,m_currentSigninInfo[i].dwGuestNumber );
m_bRead_BannedListA[i]=false;
SetBanListCheck(i,false);
m_uiOpacityCountDown[i]=0;
}
m_eGlobalXuiAction=eAppAction_Idle;
m_eGlobalXuiServerAction=eXuiServerAction_Idle;
m_bResourcesLoaded=false;
m_bGameStarted=false;
m_bIsAppPaused=false;
//m_bSplitScreenEnabled = false;
m_bIntroRunning=false;
m_eGameMode=eMode_Singleplayer;
m_bLoadSavesFromFolderEnabled = false;
m_bWriteSavesToFolderEnabled = false;
//m_bInterfaceRenderingOff = false;
//m_bHandRenderingOff = false;
m_bTutorialMode = false;
m_disconnectReason = DisconnectPacket::eDisconnect_None;
m_bLiveLinkRequired = false;
m_bChangingSessionType = false;
m_bReallyChangingSessionType = false;
#ifdef _DEBUG_MENUS_ENABLED
#ifdef _CONTENT_PACKAGE
m_bDebugOptions=false; // make them off by default in a content package build
#else
m_bDebugOptions=true;
#endif
#else
m_bDebugOptions=false;
#endif
//ZeroMemory(m_PreviewBuffer,sizeof(XSOCIAL_PREVIEWIMAGE)*XUSER_MAX_COUNT);
m_xuidNotch = INVALID_XUID;
ZeroMemory(&m_InviteData,sizeof(JoinFromInviteData) );
// m_bRead_TMS_XUIDS_XML=false;
// m_bRead_TMS_DLCINFO_XML=false;
m_pDLCFileBuffer=NULL;
m_dwDLCFileSize=0;
m_pBannedListFileBuffer=NULL;
m_dwBannedListFileSize=0;
m_bDefaultCapeInstallAttempted=false;
m_bDLCInstallProcessCompleted=false;
m_bDLCInstallPending=false;
m_iTotalDLC = 0;
m_iTotalDLCInstalled = 0;
mfTrialPausedTime=0.0f;
m_uiAutosaveTimer=0;
ZeroMemory(m_pszUniqueMapName,14);
m_bNewDLCAvailable=false;
m_bSeenNewDLCTip=false;
m_uiGameHostSettings=0;
#ifdef _LARGE_WORLDS
m_GameNewWorldSize = 0;
m_bGameNewWorldSizeUseMoat = false;
m_GameNewHellScale = 0;
#endif
ZeroMemory(m_playerColours,MINECRAFT_NET_MAX_PLAYERS);
m_iDLCOfferC=0;
m_bAllDLCContentRetrieved=true;
InitializeCriticalSection(&csDLCDownloadQueue);
m_bAllTMSContentRetrieved=true;
m_bTickTMSDLCFiles=true;
InitializeCriticalSection(&csTMSPPDownloadQueue);
InitializeCriticalSection(&csAdditionalModelParts);
InitializeCriticalSection(&csAdditionalSkinBoxes);
InitializeCriticalSection(&csAnimOverrideBitmask);
InitializeCriticalSection(&csMemFilesLock);
InitializeCriticalSection(&csMemTPDLock);
InitializeCriticalSection(&m_saveNotificationCriticalSection);
m_saveNotificationDepth = 0;
m_dwRequiredTexturePackID=0;
m_bResetNether=false;
#ifdef _XBOX
// m_bTransferSavesToXboxOne=false;
// m_uiTransferSlotC=5;
#endif
#if (defined _CONTENT_PACAKGE) || (defined _XBOX)
m_bUseDPadForDebug = false;
#else
m_bUseDPadForDebug = true;
#endif
#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
for(int i=0;i<XUSER_MAX_COUNT;i++)
{
m_eOptionsStatusA[i]=C4JStorage::eOptions_Callback_Idle;
}
#endif
for(int i=0;i<XUSER_MAX_COUNT;i++)
{
m_vBannedListA[i] = new vector<PBANNEDLISTDATA>;
}
LocaleAndLanguageInit();
#ifdef _XBOX_ONE
m_hasReachedMainMenu = false;
#endif
}
void CMinecraftApp::DebugPrintf(const char *szFormat, ...)
{
#ifndef _FINAL_BUILD
char buf[1024];
va_list ap;
va_start(ap, szFormat);
vsnprintf(buf, sizeof(buf), szFormat, ap);
va_end(ap);
OutputDebugStringA(buf);
#endif
}
void CMinecraftApp::DebugPrintf(int user, const char *szFormat, ...)
{
#ifndef _FINAL_BUILD
if(user == USER_NONE)
return;
char buf[1024];
va_list ap;
va_start(ap, szFormat);
vsnprintf(buf, sizeof(buf), szFormat, ap);
va_end(ap);
#ifdef __PS3__
unsigned int writelen;
sys_tty_write(SYS_TTYP_USER1 + ( user - 1 ), buf, strlen(buf), &writelen );
#elif defined __PSVITA__
switch(user)
{
case 0:
{
SceUID tty2 = sceIoOpen("tty2:", SCE_O_WRONLY, 0);
if(tty2>=0)
{
std::string string1(buf);
sceIoWrite(tty2, string1.c_str(), string1.length());
sceIoClose(tty2);
}
}
break;
case 1:
{
SceUID tty3 = sceIoOpen("tty3:", SCE_O_WRONLY, 0);
if(tty3>=0)
{
std::string string1(buf);
sceIoWrite(tty3, string1.c_str(), string1.length());
sceIoClose(tty3);
}
}
break;
default:
OutputDebugStringA(buf);
break;
}
#else
OutputDebugStringA(buf);
#endif
#ifndef _XBOX
if(user == USER_UI)
{
ui.logDebugString(buf);
}
#endif
#endif
}
LPCWSTR CMinecraftApp::GetString(int iID)
{
//return L"Değişiklikler ve Yenilikler";
//return L"ÕÕÕÕÖÖÖÖ";
return app.m_stringTable->getString(iID);
}
void CMinecraftApp::SetAction(int iPad, eXuiAction action, LPVOID param)
{
if( ( m_eXuiAction[iPad] == eAppAction_ReloadTexturePack ) && ( action == eAppAction_EthernetDisconnected ) )
{
app.DebugPrintf("Invalid change of App action for pad %d from %d to %d, ignoring\n", iPad, m_eXuiAction[iPad], action);
}
else if( ( m_eXuiAction[iPad] == eAppAction_ReloadTexturePack ) && ( action == eAppAction_ExitWorld ) )
{
app.DebugPrintf("Invalid change of App action for pad %d from %d to %d, ignoring\n", iPad, m_eXuiAction[iPad], action);
}
else if(m_eXuiAction[iPad] == eAppAction_ExitWorldCapturedThumbnail && action != eAppAction_Idle)
{
app.DebugPrintf("Invalid change of App action for pad %d from %d to %d, ignoring\n", iPad, m_eXuiAction[iPad], action);
}
else
{
app.DebugPrintf("Changing App action for pad %d from %d to %d\n", iPad, m_eXuiAction[iPad], action);
m_eXuiAction[iPad]=action;
m_eXuiActionParam[iPad] = param;
}
}
bool CMinecraftApp::IsAppPaused()
{
#if defined(_XBOX_ONE) || defined(__ORBIS__)
bool paused = m_bIsAppPaused;
EnterCriticalSection(&m_saveNotificationCriticalSection);
if( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 )
{
paused |= m_saveNotificationDepth > 0;
}
LeaveCriticalSection(&m_saveNotificationCriticalSection);
return paused;
#else
return m_bIsAppPaused;
#endif
}
void CMinecraftApp::SetAppPaused(bool val)
{
m_bIsAppPaused = val;
}
void CMinecraftApp::HandleButtonPresses()
{
for(int i=0;i<4;i++)
{
HandleButtonPresses(i);
}
}
void CMinecraftApp::HandleButtonPresses(int iPad)
{
// // test an update of the profile data
// void *pData=ProfileManager.GetGameDefinedProfileData(iPad);
//
// unsigned char *pchData= (unsigned char *)pData;
// int iCount=0;
// for(int i=0;i<GAME_DEFINED_PROFILE_DATA_BYTES;i++)
// {
// pchData[i]=0xBC;
// //if(iCount==255) iCount = 0;
// }
// ProfileManager.WriteToProfile(iPad,true);
}
bool CMinecraftApp::LoadInventoryMenu(int iPad,shared_ptr<LocalPlayer> player,bool bNavigateBack)
{
bool success = true;
InventoryScreenInput* initData = new InventoryScreenInput();
initData->player = player;
initData->bNavigateBack=bNavigateBack;
initData->iPad = iPad;
if(app.GetLocalPlayerCount()>1)
{
initData->bSplitscreen=true;
success = ui.NavigateToScene(iPad,eUIScene_InventoryMenu,initData);
}
else
{
initData->bSplitscreen=false;
success = ui.NavigateToScene(iPad,eUIScene_InventoryMenu,initData);
}
return success;
}
bool CMinecraftApp::LoadCreativeMenu(int iPad,shared_ptr<LocalPlayer> player,bool bNavigateBack)
{
bool success = true;
InventoryScreenInput* initData = new InventoryScreenInput();
initData->player = player;
initData->bNavigateBack=bNavigateBack;
initData->iPad = iPad;
if(app.GetLocalPlayerCount()>1)
{
initData->bSplitscreen=true;
success = ui.NavigateToScene(iPad,eUIScene_CreativeMenu,initData);
}
else
{
initData->bSplitscreen=false;
success = ui.NavigateToScene(iPad,eUIScene_CreativeMenu,initData);
}
return success;
}
bool CMinecraftApp::LoadCrafting2x2Menu(int iPad,shared_ptr<LocalPlayer> player)
{
bool success = true;
CraftingPanelScreenInput* initData = new CraftingPanelScreenInput();
initData->player = player;
initData->iContainerType=RECIPE_TYPE_2x2;
initData->iPad = iPad;
initData->x = 0;
initData->y = 0;
initData->z = 0;
if(app.GetLocalPlayerCount()>1)
{
initData->bSplitscreen=true;
success = ui.NavigateToScene(iPad,eUIScene_Crafting2x2Menu, initData);
}
else
{
initData->bSplitscreen=false;
success = ui.NavigateToScene(iPad,eUIScene_Crafting2x2Menu, initData);
}
return success;
}
bool CMinecraftApp::LoadCrafting3x3Menu(int iPad,shared_ptr<LocalPlayer> player, int x, int y, int z)
{
bool success = true;
CraftingPanelScreenInput* initData = new CraftingPanelScreenInput();
initData->player = player;
initData->iContainerType=RECIPE_TYPE_3x3;
initData->iPad = iPad;
initData->x = x;
initData->y = y;
initData->z = z;
if(app.GetLocalPlayerCount()>1)
{
initData->bSplitscreen=true;
success = ui.NavigateToScene(iPad,eUIScene_Crafting3x3Menu, initData);
}
else
{
initData->bSplitscreen=false;
success = ui.NavigateToScene(iPad,eUIScene_Crafting3x3Menu, initData);
}
return success;
}
bool CMinecraftApp::LoadFireworksMenu(int iPad,shared_ptr<LocalPlayer> player, int x, int y, int z)
{
bool success = true;
FireworksScreenInput* initData = new FireworksScreenInput();
initData->player = player;
initData->iPad = iPad;
initData->x = x;
initData->y = y;
initData->z = z;
if(app.GetLocalPlayerCount()>1)
{
initData->bSplitscreen=true;
success = ui.NavigateToScene(iPad,eUIScene_FireworksMenu, initData);
}
else
{
initData->bSplitscreen=false;
success = ui.NavigateToScene(iPad,eUIScene_FireworksMenu, initData);
}
return success;
}
bool CMinecraftApp::LoadEnchantingMenu(int iPad,shared_ptr<Inventory> inventory, int x, int y, int z, Level *level, const wstring &name)
{
bool success = true;
EnchantingScreenInput* initData = new EnchantingScreenInput();
initData->inventory = inventory;
initData->level = level;
initData->x = x;
initData->y = y;
initData->z = z;
initData->iPad = iPad;
initData->name = name;
if(app.GetLocalPlayerCount()>1)
{
initData->bSplitscreen=true;
success = ui.NavigateToScene(iPad,eUIScene_EnchantingMenu, initData);
}
else
{
initData->bSplitscreen=false;
success = ui.NavigateToScene(iPad,eUIScene_EnchantingMenu, initData);
}
return success;
}
bool CMinecraftApp::LoadFurnaceMenu(int iPad,shared_ptr<Inventory> inventory, shared_ptr<FurnaceTileEntity> furnace)
{
bool success = true;
FurnaceScreenInput* initData = new FurnaceScreenInput();
initData->furnace = furnace;
initData->inventory = inventory;
initData->iPad = iPad;
// Load the scene.
if(app.GetLocalPlayerCount()>1)
{
initData->bSplitscreen=true;
success = ui.NavigateToScene(iPad,eUIScene_FurnaceMenu, initData);
}
else
{
initData->bSplitscreen=false;
success = ui.NavigateToScene(iPad,eUIScene_FurnaceMenu, initData);
}
return success;
}
bool CMinecraftApp::LoadBrewingStandMenu(int iPad,shared_ptr<Inventory> inventory, shared_ptr<BrewingStandTileEntity> brewingStand)
{
bool success = true;
BrewingScreenInput* initData = new BrewingScreenInput();
initData->brewingStand = brewingStand;
initData->inventory = inventory;
initData->iPad = iPad;
// Load the scene.
if(app.GetLocalPlayerCount()>1)
{
initData->bSplitscreen=true;
success = ui.NavigateToScene(iPad,eUIScene_BrewingStandMenu, initData);
}
else
{
initData->bSplitscreen=false;
success = ui.NavigateToScene(iPad,eUIScene_BrewingStandMenu, initData);
}
return success;
}
bool CMinecraftApp::LoadContainerMenu(int iPad,shared_ptr<Container> inventory, shared_ptr<Container> container)
{
bool success = true;
ContainerScreenInput* initData = new ContainerScreenInput();
initData->inventory = inventory;
initData->container = container;
initData->iPad = iPad;
// Load the scene.
if(app.GetLocalPlayerCount()>1)
{
initData->bSplitscreen=true;
bool bLargeChest = (initData->container->getContainerSize() > 3*9)?true:false;
if(bLargeChest)
{
success = ui.NavigateToScene(iPad,eUIScene_LargeContainerMenu,initData);
}
else
{
success = ui.NavigateToScene(iPad,eUIScene_ContainerMenu,initData);
}
}
else
{
initData->bSplitscreen=false;
success = ui.NavigateToScene(iPad,eUIScene_ContainerMenu,initData);
}
return success;
}
bool CMinecraftApp::LoadTrapMenu(int iPad,shared_ptr<Container> inventory, shared_ptr<DispenserTileEntity> trap)
{
bool success = true;
TrapScreenInput* initData = new TrapScreenInput();
initData->inventory = inventory;
initData->trap = trap;
initData->iPad = iPad;
// Load the scene.
if(app.GetLocalPlayerCount()>1)
{
initData->bSplitscreen=true;
success = ui.NavigateToScene(iPad,eUIScene_DispenserMenu, initData);
}
else
{
initData->bSplitscreen=false;
success = ui.NavigateToScene(iPad,eUIScene_DispenserMenu, initData);
}
return success;
}
bool CMinecraftApp::LoadSignEntryMenu(int iPad,shared_ptr<SignTileEntity> sign)
{
bool success = true;
SignEntryScreenInput* initData = new SignEntryScreenInput();
initData->sign = sign;
initData->iPad = iPad;
success = ui.NavigateToScene(iPad,eUIScene_SignEntryMenu, initData);
delete initData;
return success;
}
bool CMinecraftApp::LoadRepairingMenu(int iPad,shared_ptr<Inventory> inventory, Level *level, int x, int y, int z)
{
bool success = true;
AnvilScreenInput *initData = new AnvilScreenInput();
initData->inventory = inventory;
initData->level = level;
initData->x = x;
initData->y = y;
initData->z = z;
initData->iPad = iPad;
if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true;
else initData->bSplitscreen=false;
success = ui.NavigateToScene(iPad,eUIScene_AnvilMenu, initData);
return success;
}
bool CMinecraftApp::LoadTradingMenu(int iPad, shared_ptr<Inventory> inventory, shared_ptr<Merchant> trader, Level *level, const wstring &name)
{
bool success = true;
TradingScreenInput *initData = new TradingScreenInput();
initData->inventory = inventory;
initData->trader = trader;
initData->level = level;
initData->iPad = iPad;
if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true;
else initData->bSplitscreen=false;
success = ui.NavigateToScene(iPad,eUIScene_TradingMenu, initData);
return success;
}
bool CMinecraftApp::LoadHopperMenu(int iPad ,shared_ptr<Inventory> inventory, shared_ptr<HopperTileEntity> hopper)
{
bool success = true;
HopperScreenInput *initData = new HopperScreenInput();
initData->inventory = inventory;
initData->hopper = hopper;
initData->iPad = iPad;
if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true;
else initData->bSplitscreen=false;
success = ui.NavigateToScene(iPad,eUIScene_HopperMenu, initData);
return success;
}
bool CMinecraftApp::LoadHopperMenu(int iPad ,shared_ptr<Inventory> inventory, shared_ptr<MinecartHopper> hopper)
{
bool success = true;
HopperScreenInput *initData = new HopperScreenInput();
initData->inventory = inventory;
initData->hopper = dynamic_pointer_cast<Container>(hopper);
initData->iPad = iPad;
if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true;
else initData->bSplitscreen=false;
success = ui.NavigateToScene(iPad,eUIScene_HopperMenu, initData);
return success;
}
bool CMinecraftApp::LoadHorseMenu(int iPad ,shared_ptr<Inventory> inventory, shared_ptr<Container> container, shared_ptr<EntityHorse> horse)
{
bool success = true;
HorseScreenInput *initData = new HorseScreenInput();
initData->inventory = inventory;
initData->container = container;
initData->horse = horse;
initData->iPad = iPad;
if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true;
else initData->bSplitscreen=false;
success = ui.NavigateToScene(iPad,eUIScene_HorseMenu, initData);
return success;
}
bool CMinecraftApp::LoadBeaconMenu(int iPad ,shared_ptr<Inventory> inventory, shared_ptr<BeaconTileEntity> beacon)
{
bool success = true;
BeaconScreenInput *initData = new BeaconScreenInput();
initData->inventory = inventory;
initData->beacon = beacon;
initData->iPad = iPad;
if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true;
else initData->bSplitscreen=false;
success = ui.NavigateToScene(iPad,eUIScene_BeaconMenu, initData);
return success;
}
//////////////////////////////////////////////
// GAME SETTINGS
//////////////////////////////////////////////
#ifdef _WINDOWS64
static void Win64_GetSettingsPath(char *outPath, DWORD size)
{
GetModuleFileNameA(NULL, outPath, size);
char *lastSlash = strrchr(outPath, '\\');
if (lastSlash) *(lastSlash + 1) = '\0';
strncat_s(outPath, size, "settings.dat", _TRUNCATE);
}
static void Win64_SaveSettings(GAME_SETTINGS *gs)
{
if (!gs) return;
char filePath[MAX_PATH] = {};
Win64_GetSettingsPath(filePath, MAX_PATH);
FILE *f = NULL;
if (fopen_s(&f, filePath, "wb") == 0 && f)
{
fwrite(gs, sizeof(GAME_SETTINGS), 1, f);
fclose(f);
}
}
static void Win64_LoadSettings(GAME_SETTINGS *gs)
{
if (!gs) return;
char filePath[MAX_PATH] = {};
Win64_GetSettingsPath(filePath, MAX_PATH);
FILE *f = NULL;
if (fopen_s(&f, filePath, "rb") == 0 && f)
{
GAME_SETTINGS temp = {};
if (fread(&temp, sizeof(GAME_SETTINGS), 1, f) == 1)
memcpy(gs, &temp, sizeof(GAME_SETTINGS));
fclose(f);
}
}
#endif
void CMinecraftApp::InitGameSettings()
{
for(int i=0;i<XUSER_MAX_COUNT;i++)
{
#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
GameSettingsA[i]=(GAME_SETTINGS *)StorageManager.GetGameDefinedProfileData(i);
#else
GameSettingsA[i]=(GAME_SETTINGS *)ProfileManager.GetGameDefinedProfileData(i);
#endif
// clear the flag to say the settings have changed
GameSettingsA[i]->bSettingsChanged=false;
//SetDefaultGameSettings(i); - done on a callback from the profile manager
// 4J-PB - adding in for Windows & PS3 to set the defaults for the joypad
#if defined _WINDOWS64// || defined __PSVITA__
C_4JProfile::PROFILESETTINGS *pProfileSettings=ProfileManager.GetDashboardProfileSettings(i);
// clear this for now - it will come from reading the system values
memset(pProfileSettings,0,sizeof(C_4JProfile::PROFILESETTINGS));
SetDefaultOptions(pProfileSettings,i);
Win64_LoadSettings(GameSettingsA[i]);
ApplyGameSettingsChanged(i);
#elif defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__
C4JStorage::PROFILESETTINGS *pProfileSettings=StorageManager.GetDashboardProfileSettings(i);
// 4J-PB - don't cause an options write to happen here
SetDefaultOptions(pProfileSettings,i,false);
#endif
}
}
#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
int CMinecraftApp::SetDefaultOptions(C4JStorage::PROFILESETTINGS *pSettings,const int iPad,bool bWriteProfile)
#else
int CMinecraftApp::SetDefaultOptions(C_4JProfile::PROFILESETTINGS *pSettings,const int iPad)
#endif
{
SetGameSettings(iPad,eGameSetting_MusicVolume,DEFAULT_VOLUME_LEVEL);
SetGameSettings(iPad,eGameSetting_SoundFXVolume,DEFAULT_VOLUME_LEVEL);
SetGameSettings(iPad,eGameSetting_RenderDistance,16);
SetGameSettings(iPad,eGameSetting_Gamma,50);
SetGameSettings(iPad,eGameSetting_FOV,0);
// 4J-PB - Don't reset the difficult level if we're in-game
if(Minecraft::GetInstance()->level==NULL)
{
app.DebugPrintf("SetDefaultOptions - Difficulty = 1\n");
SetGameSettings(iPad,eGameSetting_Difficulty,1);
}
SetGameSettings(iPad,eGameSetting_Sensitivity_InGame,100);
SetGameSettings(iPad,eGameSetting_ViewBob,1);
SetGameSettings(iPad,eGameSetting_ControlScheme,0);
SetGameSettings(iPad,eGameSetting_ControlInvertLook,(pSettings->iYAxisInversion!=0)?1:0);
SetGameSettings(iPad,eGameSetting_ControlSouthPaw,pSettings->bSwapSticks?1:0);
SetGameSettings(iPad,eGameSetting_SplitScreenVertical,0);
SetGameSettings(iPad,eGameSetting_GamertagsVisible,1);
// Interim TU 1.6.6
SetGameSettings(iPad,eGameSetting_Sensitivity_InMenu,100);
SetGameSettings(iPad,eGameSetting_DisplaySplitscreenGamertags,1);
SetGameSettings(iPad,eGameSetting_Hints,1);
SetGameSettings(iPad,eGameSetting_Autosave,2);
SetGameSettings(iPad,eGameSetting_Tooltips,1);
SetGameSettings(iPad,eGameSetting_InterfaceOpacity,80);
// TU 5
SetGameSettings(iPad,eGameSetting_Clouds,1);
SetGameSettings(iPad,eGameSetting_Online,1);
SetGameSettings(iPad,eGameSetting_InviteOnly,0);
SetGameSettings(iPad,eGameSetting_FriendsOfFriends,1);
// default the update changes message to zero
// 4J-PB - We'll only display the message if the profile is pre-TU5
//SetGameSettings(iPad,eGameSetting_DisplayUpdateMessage,0);
// TU 6
SetGameSettings(iPad,eGameSetting_BedrockFog,0);
SetGameSettings(iPad,eGameSetting_DisplayHUD,1);
SetGameSettings(iPad,eGameSetting_DisplayHand,1);
// TU 7
SetGameSettings(iPad,eGameSetting_CustomSkinAnim,1);
// TU 9
SetGameSettings(iPad,eGameSetting_DeathMessages,1);
SetGameSettings(iPad,eGameSetting_UISize,1);
SetGameSettings(iPad,eGameSetting_UISizeSplitscreen,2);
SetGameSettings(iPad,eGameSetting_AnimatedCharacter,1);
// TU 12
GameSettingsA[iPad]->ucCurrentFavoriteSkinPos=0;
for(int i=0;i<MAX_FAVORITE_SKINS;i++)
{
GameSettingsA[iPad]->uiFavoriteSkinA[i]=0xFFFFFFFF;
}
// TU 13
GameSettingsA[iPad]->uiMashUpPackWorldsDisplay=0xFFFFFFFF;
// 1.6.4
app.SetGameHostOption(eGameHostOption_MobGriefing, 1);
app.SetGameHostOption(eGameHostOption_KeepInventory, 0);
app.SetGameHostOption(eGameHostOption_DoMobSpawning, 1 );
app.SetGameHostOption(eGameHostOption_DoMobLoot, 1 );
app.SetGameHostOption(eGameHostOption_DoTileDrops, 1 );
app.SetGameHostOption(eGameHostOption_NaturalRegeneration, 1 );
app.SetGameHostOption(eGameHostOption_DoDaylightCycle, 1 );
// 4J-PB - leave these in, or remove from everywhere they are referenced!
// Although probably best to leave in unless we split the profile settings into platform specific classes - having different meaning per platform for the same bitmask could get confusing
//#ifdef __PS3__
// PS3DEC13
SetGameSettings(iPad,eGameSetting_PS3_EULA_Read,0); // EULA not read
// PS3 1.05 - added Greek
// 4J-JEV: We cannot change these in-game, as they could affect localised strings and font.
// XB1: Fix for #172947 - Content: Gameplay: While playing in language different form system default one and resetting options to their defaults in active gameplay causes in-game language to change and HUD to disappear
if (!app.GetGameStarted())
{
GameSettingsA[iPad]->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
GameSettingsA[iPad]->ucLocale = MINECRAFT_LANGUAGE_DEFAULT; // use the system locale
}
//#endif
#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
GameSettingsA[iPad]->bSettingsChanged=bWriteProfile;
#endif
return 0;
}
#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
int CMinecraftApp::DefaultOptionsCallback(LPVOID pParam,C4JStorage::PROFILESETTINGS *pSettings, const int iPad)
#else
int CMinecraftApp::DefaultOptionsCallback(LPVOID pParam,C_4JProfile::PROFILESETTINGS *pSettings, const int iPad)
#endif
{
CMinecraftApp *pApp=(CMinecraftApp *)pParam;
// flag the default options to be set
pApp->DebugPrintf("Setting default options for player %d", iPad);
pApp->SetAction(iPad,eAppAction_SetDefaultOptions, (LPVOID)pSettings);
//pApp->SetDefaultOptions(pSettings,iPad);
// if the profile data has been changed, then force a profile write
// It seems we're allowed to break the 5 minute rule if it's the result of a user action
//pApp->CheckGameSettingsChanged();
return 0;
}
#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
wstring CMinecraftApp::toStringOptionsStatus(const C4JStorage::eOptionsCallback &eStatus)
{
#ifndef _CONTENT_PACKAGE
switch(eStatus)
{
case C4JStorage::eOptions_Callback_Idle: return L"Idle";
case C4JStorage::eOptions_Callback_Write: return L"Write";
case C4JStorage::eOptions_Callback_Write_Fail_NoSpace: return L"Write_Fail_NoSpace";
case C4JStorage::eOptions_Callback_Write_Fail: return L"Write_Fail";
case C4JStorage::eOptions_Callback_Read: return L"Read";
case C4JStorage::eOptions_Callback_Read_Fail: return L"Read_Fail";
case C4JStorage::eOptions_Callback_Read_FileNotFound: return L"Read_FileNotFound";
case C4JStorage::eOptions_Callback_Read_Corrupt: return L"Read_Corrupt";
case C4JStorage::eOptions_Callback_Read_CorruptDeletePending: return L"Read_CorruptDeletePending";
case C4JStorage::eOptions_Callback_Read_CorruptDeleted: return L"Read_CorruptDeleted";
default: return L"[UNRECOGNISED_OPTIONS_STATUS]";
}
#else
return L"";
#endif
}
#ifdef __ORBIS__
int CMinecraftApp::OptionsDataCallback(LPVOID pParam,int iPad,unsigned short usVersion,C4JStorage::eOptionsCallback eStatus,int iBlocksRequired)
{
CMinecraftApp *pApp=(CMinecraftApp *)pParam;
pApp->m_eOptionsStatusA[iPad]=eStatus;
pApp->m_eOptionsBlocksRequiredA[iPad]=iBlocksRequired;
return 0;
}
int CMinecraftApp::GetOptionsBlocksRequired(int iPad)
{
return m_eOptionsBlocksRequiredA[iPad];
}
#else
int CMinecraftApp::OptionsDataCallback(LPVOID pParam,int iPad,unsigned short usVersion,C4JStorage::eOptionsCallback eStatus)
{
CMinecraftApp *pApp=(CMinecraftApp *)pParam;
#ifndef _CONTENT_PACKAGE
pApp->DebugPrintf("[OptionsDataCallback] Pad_%i: new status == %ls(%i).\n", iPad, pApp->toStringOptionsStatus(eStatus).c_str(), (int) eStatus);
#endif
pApp->m_eOptionsStatusA[iPad] = eStatus;
return 0;
}
#endif
C4JStorage::eOptionsCallback CMinecraftApp::GetOptionsCallbackStatus(int iPad)
{
return m_eOptionsStatusA[iPad];
}
void CMinecraftApp::SetOptionsCallbackStatus(int iPad, C4JStorage::eOptionsCallback eStatus)
{
m_eOptionsStatusA[iPad]=eStatus;
}
#endif
int CMinecraftApp::OldProfileVersionCallback(LPVOID pParam,unsigned char *pucData, const unsigned short usVersion, const int iPad)
{
// check what needs to be done with this version to update to the current one
switch(usVersion)
{
#ifdef _XBOX
case PROFILE_VERSION_1:
case PROFILE_VERSION_2:
// need to fill in values for the new profile data. No need to save the profile - that'll happen if they get changed, or if the auto save for the profile kicks in
{
GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
pGameSettings->ucMenuSensitivity=100; //eGameSetting_Sensitivity_InMenu
pGameSettings->ucInterfaceOpacity=80; //eGameSetting_Sensitivity_InMenu
pGameSettings->usBitmaskValues|=0x0200; //eGameSetting_DisplaySplitscreenGamertags - on
pGameSettings->usBitmaskValues|=0x0400; //eGameSetting_Hints - on
pGameSettings->usBitmaskValues|=0x1000; //eGameSetting_Autosave - 2
pGameSettings->usBitmaskValues|=0x8000; //eGameSetting_Tooltips - on
// 4J-PB - Let's also award all the achievements they have again because of the profile bug that seemed to stop the awards of some
// Changing this to check the system achievements at sign-in and award any that the game says we have and the system says we haven't
//ProfileManager.ReAwardAchievements(iPad);
pGameSettings->uiBitmaskValues=0L; // reset
pGameSettings->uiBitmaskValues|=GAMESETTING_CLOUDS; //eGameSetting_Clouds - on
pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on
//eGameSetting_GameSetting_Invite - off
pGameSettings->uiBitmaskValues|=GAMESETTING_FRIENDSOFFRIENDS; //eGameSetting_GameSetting_FriendsOfFriends - on
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
// TU6
pGameSettings->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG; //eGameSetting_BedrockFog - off
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHUD; //eGameSetting_DisplayHUD - on
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHAND; //eGameSetting_DisplayHand - on
// TU7
pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on
// TU9
pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on
pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2
pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3
pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on
// TU12
// favorite skins added, but only set in TU12 - set to FFs
for(int i=0;i<MAX_FAVORITE_SKINS;i++)
{
pGameSettings->uiFavoriteSkinA[i]=0xFFFFFFFF;
}
pGameSettings->ucCurrentFavoriteSkinPos=0;
// Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list
pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF;
// PS3 1.05 - added Greek
pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
}
break;
case PROFILE_VERSION_3:
{
GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
pGameSettings->uiBitmaskValues=0L; // reset
pGameSettings->uiBitmaskValues|=GAMESETTING_CLOUDS; //eGameSetting_Clouds - on
pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on
//eGameSetting_GameSetting_Invite - off
pGameSettings->uiBitmaskValues|=GAMESETTING_FRIENDSOFFRIENDS; //eGameSetting_GameSetting_FriendsOfFriends - on
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
// TU6
pGameSettings->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG; //eGameSetting_BedrockFog - off
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHUD; //eGameSetting_DisplayHUD - on
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHAND; //eGameSetting_DisplayHand - on
// TU7
pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on
// TU9
pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on
pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2
pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3
pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on
// TU12
// favorite skins added, but only set in TU12 - set to FFs
for(int i=0;i<MAX_FAVORITE_SKINS;i++)
{
pGameSettings->uiFavoriteSkinA[i]=0xFFFFFFFF;
}
pGameSettings->ucCurrentFavoriteSkinPos=0;
// Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list
pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF;
// PS3 1.05 - added Greek
pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
}
break;
case PROFILE_VERSION_4:
{
GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
pGameSettings->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG; //eGameSetting_BedrockFog - off
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHUD; //eGameSetting_DisplayHUD - on
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHAND; //eGameSetting_DisplayHand - on
// TU7
pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on
// TU9
pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on
pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2
pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3
pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on
// Set the online flag to on, so it's not saved if a game starts offline when the user didn't change it to be offline (xbox disconnected from LIVE)
pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on
// TU12
// favorite skins added, but only set in TU12 - set to FFs
for(int i=0;i<MAX_FAVORITE_SKINS;i++)
{
pGameSettings->uiFavoriteSkinA[i]=0xFFFFFFFF;
}
pGameSettings->ucCurrentFavoriteSkinPos=0;
// Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list
pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF;
// PS3 1.05 - added Greek
pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
}
break;
case PROFILE_VERSION_5:
{
GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
// reset the display new message counter
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
// TU7
pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on
// TU9
pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on
pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2
pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3
pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on
// Set the online flag to on, so it's not saved if a game starts offline when the user didn't change it to be offline (xbox disconnected from LIVE)
pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on
// TU12
// favorite skins added, but only set in TU12 - set to FFs
for(int i=0;i<MAX_FAVORITE_SKINS;i++)
{
pGameSettings->uiFavoriteSkinA[i]=0xFFFFFFFF;
}
pGameSettings->ucCurrentFavoriteSkinPos=0;
// Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list
pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF;
// PS3 1.05 - added Greek
pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
}
break;
case PROFILE_VERSION_6:
{
GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
// Added gui size for splitscreen and fullscreen
// Added death messages toggle
// reset the display new message counter
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
// TU9
pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on
pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2
pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3
pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on
// Set the online flag to on, so it's not saved if a game starts offline when the user didn't change it to be offline (xbox disconnected from LIVE)
pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on
// TU12
// favorite skins added, but only set in TU12 - set to FFs
for(int i=0;i<MAX_FAVORITE_SKINS;i++)
{
pGameSettings->uiFavoriteSkinA[i]=0xFFFFFFFF;
}
pGameSettings->ucCurrentFavoriteSkinPos=0;
// Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list
pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF;
// PS3 1.05 - added Greek
pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
}
break;
case PROFILE_VERSION_7:
{
GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
// reset the display new message counter
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
// TU12
// favorite skins added, but only set in TU12 - set to FFs
for(int i=0;i<MAX_FAVORITE_SKINS;i++)
{
pGameSettings->uiFavoriteSkinA[i]=0xFFFFFFFF;
}
pGameSettings->ucCurrentFavoriteSkinPos=0;
// Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list
pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF;
// PS3 1.05 - added Greek
pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
}
break;
#endif
case PROFILE_VERSION_8:
{
GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
// reset the display new message counter
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
// Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list
pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF;
// PS3DEC13
pGameSettings->uiBitmaskValues&=~GAMESETTING_PS3EULAREAD; //eGameSetting_PS3_EULA_Read - off
// PS3 1.05 - added Greek
pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
}
break;
case PROFILE_VERSION_9:
// PS3DEC13
{
GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
pGameSettings->uiBitmaskValues&=~GAMESETTING_PS3EULAREAD; //eGameSetting_PS3_EULA_Read - off
// PS3 1.05 - added Greek
pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
}
break;
case PROFILE_VERSION_10:
{
GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
}
break;
case PROFILE_VERSION_11:
{
GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
}
break;
case PROFILE_VERSION_12:
{
GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
}
break;
default:
{
// This might be from a version during testing of new profile updates
app.DebugPrintf("Don't know what to do with this profile version!\n");
#ifndef _CONTENT_PACKAGE
// __debugbreak();
#endif
GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
pGameSettings->ucMenuSensitivity=100; //eGameSetting_Sensitivity_InMenu
pGameSettings->ucInterfaceOpacity=80; //eGameSetting_Sensitivity_InMenu
pGameSettings->usBitmaskValues|=0x0200; //eGameSetting_DisplaySplitscreenGamertags - on
pGameSettings->usBitmaskValues|=0x0400; //eGameSetting_Hints - on
pGameSettings->usBitmaskValues|=0x1000; //eGameSetting_Autosave - 2
pGameSettings->usBitmaskValues|=0x8000; //eGameSetting_Tooltips - on
pGameSettings->uiBitmaskValues=0L; // reset
pGameSettings->uiBitmaskValues|=GAMESETTING_CLOUDS; //eGameSetting_Clouds - on
pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on
//eGameSetting_GameSetting_Invite - off
pGameSettings->uiBitmaskValues|=GAMESETTING_FRIENDSOFFRIENDS; //eGameSetting_GameSetting_FriendsOfFriends - on
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
pGameSettings->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG; //eGameSetting_BedrockFog - off
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHUD; //eGameSetting_DisplayHUD - on
pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHAND; //eGameSetting_DisplayHand - on
pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on
pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on
pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2
pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3
pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on
// TU12
// favorite skins added, but only set in TU12 - set to FFs
for(int i=0;i<MAX_FAVORITE_SKINS;i++)
{
pGameSettings->uiFavoriteSkinA[i]=0xFFFFFFFF;
}
pGameSettings->ucCurrentFavoriteSkinPos=0;
// Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list
pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF;
// PS3DEC13
pGameSettings->uiBitmaskValues&=~GAMESETTING_PS3EULAREAD; //eGameSetting_PS3_EULA_Read - off
// PS3 1.05 - added Greek
pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
}
break;
}
return 0;
}
void CMinecraftApp::ApplyGameSettingsChanged(int iPad)
{
ActionGameSettings(iPad,eGameSetting_MusicVolume );
ActionGameSettings(iPad,eGameSetting_SoundFXVolume );
ActionGameSettings(iPad,eGameSetting_RenderDistance );
ActionGameSettings(iPad,eGameSetting_Gamma );
ActionGameSettings(iPad,eGameSetting_FOV );
ActionGameSettings(iPad,eGameSetting_Difficulty );
ActionGameSettings(iPad,eGameSetting_Sensitivity_InGame );
ActionGameSettings(iPad,eGameSetting_ViewBob );
ActionGameSettings(iPad,eGameSetting_ControlScheme );
ActionGameSettings(iPad,eGameSetting_ControlInvertLook);
ActionGameSettings(iPad,eGameSetting_ControlSouthPaw);
ActionGameSettings(iPad,eGameSetting_SplitScreenVertical);
ActionGameSettings(iPad,eGameSetting_GamertagsVisible);
// Interim TU 1.6.6
ActionGameSettings(iPad,eGameSetting_Sensitivity_InMenu );
ActionGameSettings(iPad,eGameSetting_DisplaySplitscreenGamertags);
ActionGameSettings(iPad,eGameSetting_Hints);
ActionGameSettings(iPad,eGameSetting_InterfaceOpacity);
ActionGameSettings(iPad,eGameSetting_Tooltips);
ActionGameSettings(iPad,eGameSetting_Clouds);
ActionGameSettings(iPad,eGameSetting_BedrockFog);
ActionGameSettings(iPad,eGameSetting_DisplayHUD);
ActionGameSettings(iPad,eGameSetting_DisplayHand);
ActionGameSettings(iPad,eGameSetting_CustomSkinAnim);
ActionGameSettings(iPad,eGameSetting_DeathMessages);
ActionGameSettings(iPad,eGameSetting_UISize);
ActionGameSettings(iPad,eGameSetting_UISizeSplitscreen);
ActionGameSettings(iPad,eGameSetting_AnimatedCharacter);
ActionGameSettings(iPad,eGameSetting_PS3_EULA_Read);
}
void CMinecraftApp::ActionGameSettings(int iPad,eGameSetting eVal)
{
Minecraft *pMinecraft=Minecraft::GetInstance();
switch(eVal)
{
case eGameSetting_MusicVolume:
if(iPad==ProfileManager.GetPrimaryPad())
{
pMinecraft->options->set(Options::Option::MUSIC,((float)GameSettingsA[iPad]->ucMusicVolume)/100.0f);
}
break;
case eGameSetting_SoundFXVolume:
if(iPad==ProfileManager.GetPrimaryPad())
{
pMinecraft->options->set(Options::Option::SOUND,((float)GameSettingsA[iPad]->ucSoundFXVolume)/100.0f);
}
break;
case eGameSetting_RenderDistance:
if(iPad == ProfileManager.GetPrimaryPad())
{
int dist = (GameSettingsA[iPad]->uiBitmaskValues >> 16) & 0xFF;
int level = UIScene_SettingsGraphicsMenu::DistanceToLevel(dist);
pMinecraft->options->set(Options::Option::RENDER_DISTANCE, 3 - level);
}
break;
case eGameSetting_Gamma:
if(iPad==ProfileManager.GetPrimaryPad())
{
#if defined(_WIN64) || defined(_WINDOWS64)
pMinecraft->options->set(Options::Option::GAMMA, ((float)GameSettingsA[iPad]->ucGamma) / 100.0f);
#else
// ucGamma range is 0-100, UpdateGamma is 0 - 32768
float fVal=((float)GameSettingsA[iPad]->ucGamma)*327.68f;
RenderManager.UpdateGamma((unsigned short)fVal);
#endif
}
break;
case eGameSetting_FOV:
if(iPad==ProfileManager.GetPrimaryPad())
{
float fovDeg = 70.0f + (float)GameSettingsA[iPad]->ucFov * 40.0f / 100.0f;
pMinecraft->gameRenderer->SetFovVal(fovDeg);
pMinecraft->options->set(Options::Option::FOV, (float)GameSettingsA[iPad]->ucFov / 100.0f);
}
break;
case eGameSetting_Difficulty:
if(iPad==ProfileManager.GetPrimaryPad())
{
pMinecraft->options->toggle(Options::Option::DIFFICULTY,GameSettingsA[iPad]->usBitmaskValues&0x03);
app.DebugPrintf("Difficulty toggle to %d\n",GameSettingsA[iPad]->usBitmaskValues&0x03);
// Update the Game Host setting
app.SetGameHostOption(eGameHostOption_Difficulty,pMinecraft->options->difficulty);
// send this to the other players if we are in-game
bool bInGame=pMinecraft->level!=NULL;
// Game Host only (and for now we can't change the diff while in game, so this shouldn't happen)
if(bInGame && g_NetworkManager.IsHost() && (iPad==ProfileManager.GetPrimaryPad()))
{
app.SetXuiServerAction(iPad,eXuiServerAction_ServerSettingChanged_Difficulty);
}
}
else
{
app.DebugPrintf("NOT ACTIONING DIFFICULTY - Primary pad is %d, This pad is %d\n",ProfileManager.GetPrimaryPad(),iPad);
}
break;
case eGameSetting_Sensitivity_InGame:
// 4J-PB - we don't use the options value
// tell the input that we've changed the sensitivity - range of the slider is 0 to 200, default is 100
pMinecraft->options->set(Options::Option::SENSITIVITY,((float)GameSettingsA[iPad]->ucSensitivity)/100.0f);
//InputManager.SetJoypadSensitivity(iPad,((float)GameSettingsA[iPad]->ucSensitivity)/100.0f);
break;
case eGameSetting_ViewBob:
// 4J-PB - not handled here any more - it's read from the gamesettings per player
//pMinecraft->options->toggle(Options::Option::VIEW_BOBBING,GameSettingsA[iPad]->usBitmaskValues&0x04);
break;
case eGameSetting_ControlScheme:
InputManager.SetJoypadMapVal(iPad,(GameSettingsA[iPad]->usBitmaskValues&0x30)>>4);
break;
case eGameSetting_ControlInvertLook:
// Nothing specific to do for this setting.
break;
case eGameSetting_ControlSouthPaw:
// What is the setting?
if ( GameSettingsA[iPad]->usBitmaskValues & 0x80 )
{
// Southpaw.
InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_LX, AXIS_MAP_RX );
InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_LY, AXIS_MAP_RY );
InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_RX, AXIS_MAP_LX );
InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_RY, AXIS_MAP_LY );
InputManager.SetJoypadStickTriggerMap( iPad, TRIGGER_MAP_0, TRIGGER_MAP_1 );
InputManager.SetJoypadStickTriggerMap( iPad, TRIGGER_MAP_1, TRIGGER_MAP_0 );
}
else
{
// Right handed.
InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_LX, AXIS_MAP_LX );
InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_LY, AXIS_MAP_LY );
InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_RX, AXIS_MAP_RX );
InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_RY, AXIS_MAP_RY );
InputManager.SetJoypadStickTriggerMap( iPad, TRIGGER_MAP_0, TRIGGER_MAP_0 );
InputManager.SetJoypadStickTriggerMap( iPad, TRIGGER_MAP_1, TRIGGER_MAP_1 );
}
break;
case eGameSetting_SplitScreenVertical:
if(iPad==ProfileManager.GetPrimaryPad())
{
pMinecraft->updatePlayerViewportAssignments();
}
break;
case eGameSetting_GamertagsVisible:
{
bool bInGame=pMinecraft->level!=NULL;
// Game Host only
if(bInGame && g_NetworkManager.IsHost() && (iPad==ProfileManager.GetPrimaryPad()))
{
// Update the Game Host setting if you are the host and you are in-game
app.SetGameHostOption(eGameHostOption_Gamertags,((GameSettingsA[iPad]->usBitmaskValues&0x0008)!=0)?1:0);
app.SetXuiServerAction(iPad,eXuiServerAction_ServerSettingChanged_Gamertags);
PlayerList *players = MinecraftServer::getInstance()->getPlayerList();
for( auto& decorationPlayer : players->players )
{
decorationPlayer->setShowOnMaps((app.GetGameHostOption(eGameHostOption_Gamertags)!=0)?true:false);
}
}
}
break;
// Interim TU 1.6.6
case eGameSetting_Sensitivity_InMenu:
// 4J-PB - we don't use the options value
// tell the input that we've changed the sensitivity - range of the slider is 0 to 200, default is 100
//pMinecraft->options->set(Options::Option::SENSITIVITY,((float)GameSettingsA[iPad]->ucSensitivity)/100.0f);
//InputManager.SetJoypadSensitivity(iPad,((float)GameSettingsA[iPad]->ucSensitivity)/100.0f);
break;
case eGameSetting_DisplaySplitscreenGamertags:
for( BYTE idx = 0; idx < XUSER_MAX_COUNT; ++idx)
{
if(pMinecraft->localplayers[idx] != NULL)
{
if(pMinecraft->localplayers[idx]->m_iScreenSection==C4JRender::VIEWPORT_TYPE_FULLSCREEN)
{
ui.DisplayGamertag(idx,false);
}
else
{
ui.DisplayGamertag(idx,true);
}
}
}
break;
case eGameSetting_InterfaceOpacity:
// update the tooltips display
ui.RefreshTooltips( iPad);
break;
case eGameSetting_Hints:
//nothing to do here
break;
case eGameSetting_Tooltips:
if((GameSettingsA[iPad]->usBitmaskValues&0x8000)!=0)
{
ui.SetEnableTooltips(iPad,TRUE);
}
else
{
ui.SetEnableTooltips(iPad,FALSE);
}
break;
case eGameSetting_Clouds:
//nothing to do here
break;
case eGameSetting_Online:
//nothing to do here
break;
case eGameSetting_InviteOnly:
//nothing to do here
break;
case eGameSetting_FriendsOfFriends:
//nothing to do here
break;
case eGameSetting_BedrockFog:
{
bool bInGame=pMinecraft->level!=NULL;
// Game Host only
if(bInGame && g_NetworkManager.IsHost() && (iPad==ProfileManager.GetPrimaryPad()))
{
// Update the Game Host setting if you are the host and you are in-game
app.SetGameHostOption(eGameHostOption_BedrockFog,GetGameSettings(iPad,eGameSetting_BedrockFog)?1:0);
app.SetXuiServerAction(iPad,eXuiServerAction_ServerSettingChanged_BedrockFog);
}
}
break;
case eGameSetting_DisplayHUD:
//nothing to do here
break;
case eGameSetting_DisplayHand:
//nothing to do here
break;
case eGameSetting_CustomSkinAnim:
//nothing to do here
break;
case eGameSetting_DeathMessages:
//nothing to do here
break;
case eGameSetting_UISize:
//nothing to do here
break;
case eGameSetting_UISizeSplitscreen:
//nothing to do here
break;
case eGameSetting_AnimatedCharacter:
//nothing to do here
break;
case eGameSetting_PS3_EULA_Read:
//nothing to do here
break;
case eGameSetting_PSVita_NetworkModeAdhoc:
//nothing to do here
break;
}
}
void CMinecraftApp::SetPlayerSkin(int iPad,const wstring &name)
{
DWORD skinId = app.getSkinIdFromPath(name);
SetPlayerSkin(iPad,skinId);
}
void CMinecraftApp::SetPlayerSkin(int iPad,DWORD dwSkinId)
{
DebugPrintf("Setting skin for %d to %08X\n", iPad, dwSkinId);
GameSettingsA[iPad]->dwSelectedSkin = dwSkinId;
GameSettingsA[iPad]->bSettingsChanged = true;
TelemetryManager->RecordSkinChanged(iPad, GameSettingsA[iPad]->dwSelectedSkin);
if(Minecraft::GetInstance()->localplayers[iPad]!=NULL) Minecraft::GetInstance()->localplayers[iPad]->setAndBroadcastCustomSkin(dwSkinId);
}
wstring CMinecraftApp::GetPlayerSkinName(int iPad)
{
return app.getSkinPathFromId(GameSettingsA[iPad]->dwSelectedSkin);
}
DWORD CMinecraftApp::GetPlayerSkinId(int iPad)
{
// 4J-PB -check the user has rights to use this skin - they may have had at some point but the entitlement has been removed.
DLCPack *Pack=NULL;
DLCSkinFile *skinFile=NULL;
DWORD dwSkin=GameSettingsA[iPad]->dwSelectedSkin;
wchar_t chars[256];
if( GET_IS_DLC_SKIN_FROM_BITMASK(dwSkin) )
{
// 4J Stu - DLC skins are numbered using decimal rather than hex to make it easier to number manually
swprintf(chars, 256, L"dlcskin%08d.png", GET_DLC_SKIN_ID_FROM_BITMASK(dwSkin));
Pack=app.m_dlcManager.getPackContainingSkin(chars);
if(Pack)
{
skinFile = Pack->getSkinFile(chars);
bool bSkinIsFree = skinFile->getParameterAsBool( DLCManager::e_DLCParamType_Free );
bool bLicensed = Pack->hasPurchasedFile( DLCManager::e_DLCType_Skin, skinFile->getPath() );
if(bSkinIsFree || bLicensed)
{
return dwSkin;
}
else
{
return 0;
}
}
}
return dwSkin;
}
DWORD CMinecraftApp::GetAdditionalModelParts(int iPad)
{
return m_dwAdditionalModelParts[iPad];
}
void CMinecraftApp::SetPlayerCape(int iPad,const wstring &name)
{
DWORD capeId = Player::getCapeIdFromPath(name);
SetPlayerCape(iPad,capeId);
}
void CMinecraftApp::SetPlayerCape(int iPad,DWORD dwCapeId)
{
DebugPrintf("Setting cape for %d to %08X\n", iPad, dwCapeId);
GameSettingsA[iPad]->dwSelectedCape = dwCapeId;
GameSettingsA[iPad]->bSettingsChanged = true;
//SentientManager.RecordSkinChanged(iPad, GameSettingsA[iPad]->dwSelectedSkin);
if(Minecraft::GetInstance()->localplayers[iPad]!=NULL) Minecraft::GetInstance()->localplayers[iPad]->setAndBroadcastCustomCape(dwCapeId);
}
wstring CMinecraftApp::GetPlayerCapeName(int iPad)
{
return Player::getCapePathFromId(GameSettingsA[iPad]->dwSelectedCape);
}
DWORD CMinecraftApp::GetPlayerCapeId(int iPad)
{
return GameSettingsA[iPad]->dwSelectedCape;
}
void CMinecraftApp::SetPlayerFavoriteSkin(int iPad, int iIndex,unsigned int uiSkinID)
{
DebugPrintf("Setting favorite skin for %d to %08X\n", iPad, uiSkinID);
GameSettingsA[iPad]->uiFavoriteSkinA[iIndex] = uiSkinID;
GameSettingsA[iPad]->bSettingsChanged = true;
}
unsigned int CMinecraftApp::GetPlayerFavoriteSkin(int iPad,int iIndex)
{
return GameSettingsA[iPad]->uiFavoriteSkinA[iIndex];
}
unsigned char CMinecraftApp::GetPlayerFavoriteSkinsPos(int iPad)
{
return GameSettingsA[iPad]->ucCurrentFavoriteSkinPos;
}
void CMinecraftApp::SetPlayerFavoriteSkinsPos(int iPad, int iPos)
{
GameSettingsA[iPad]->ucCurrentFavoriteSkinPos=(unsigned char)iPos;
GameSettingsA[iPad]->bSettingsChanged = true;
}
unsigned int CMinecraftApp::GetPlayerFavoriteSkinsCount(int iPad)
{
unsigned int uiCount=0;
for(int i=0;i<MAX_FAVORITE_SKINS;i++)
{
if(GameSettingsA[iPad]->uiFavoriteSkinA[i]!=0xFFFFFFFF)
{
uiCount++;
}
else
{
break;
}
}
return uiCount;
}
void CMinecraftApp::ValidateFavoriteSkins(int iPad)
{
unsigned int uiCount=GetPlayerFavoriteSkinsCount(iPad);
// remove invalid skins
unsigned int uiValidSkin=0;
wchar_t chars[256];
for(unsigned int i=0;i<uiCount;i++)
{
// get the pack number from the skin id
swprintf(chars, 256, L"dlcskin%08d.png", app.GetPlayerFavoriteSkin(iPad,i));
// Also check they haven't reverted to a trial pack
DLCPack *pDLCPack=app.m_dlcManager.getPackContainingSkin(chars);
if(pDLCPack!=NULL)
{
// 4J-PB - We should let players add the free skins to their favourites as well!
//DLCFile *pDLCFile=pDLCPack->getFile(DLCManager::e_DLCType_Skin,chars);
DLCSkinFile *pSkinFile = pDLCPack->getSkinFile(chars);
if( pDLCPack->hasPurchasedFile(DLCManager::e_DLCType_Skin, L"") || (pSkinFile && pSkinFile->isFree()))
{
GameSettingsA[iPad]->uiFavoriteSkinA[uiValidSkin++]=GameSettingsA[iPad]->uiFavoriteSkinA[i];
}
}
}
for(unsigned int i=uiValidSkin;i<MAX_FAVORITE_SKINS;i++)
{
GameSettingsA[iPad]->uiFavoriteSkinA[i]=0xFFFFFFFF;
}
}
// Mash-up pack worlds
void CMinecraftApp::HideMashupPackWorld(int iPad, unsigned int iMashupPackID)
{
unsigned int uiPackID=iMashupPackID - 1024; // mash-up ids start at 1024
GameSettingsA[iPad]->uiMashUpPackWorldsDisplay&=~(1<<uiPackID);
GameSettingsA[iPad]->bSettingsChanged = true;
}
void CMinecraftApp::EnableMashupPackWorlds(int iPad)
{
GameSettingsA[iPad]->uiMashUpPackWorldsDisplay=0xFFFFFFFF;
GameSettingsA[iPad]->bSettingsChanged = true;
}
unsigned int CMinecraftApp::GetMashupPackWorlds(int iPad)
{
return GameSettingsA[iPad]->uiMashUpPackWorldsDisplay;
}
void CMinecraftApp::SetMinecraftLanguage(int iPad, unsigned char ucLanguage)
{
GameSettingsA[iPad]->ucLanguage = ucLanguage;
GameSettingsA[iPad]->bSettingsChanged = true;
}
unsigned char CMinecraftApp::GetMinecraftLanguage(int iPad)
{
// if there are no game settings read yet, return the default language
if(GameSettingsA[iPad]==NULL)
{
return 0;
}
else
{
return GameSettingsA[iPad]->ucLanguage;
}
}
void CMinecraftApp::SetMinecraftLocale(int iPad, unsigned char ucLocale)
{
GameSettingsA[iPad]->ucLocale = ucLocale;
GameSettingsA[iPad]->bSettingsChanged = true;
}
unsigned char CMinecraftApp::GetMinecraftLocale(int iPad)
{
// if there are no game settings read yet, return the default language
if(GameSettingsA[iPad]==NULL)
{
return 0;
}
else
{
return GameSettingsA[iPad]->ucLocale;
}
}
void CMinecraftApp::SetGameSettings(int iPad,eGameSetting eVal,unsigned char ucVal)
{
//Minecraft *pMinecraft=Minecraft::GetInstance();
switch(eVal)
{
case eGameSetting_MusicVolume:
if(GameSettingsA[iPad]->ucMusicVolume!=ucVal)
{
GameSettingsA[iPad]->ucMusicVolume=ucVal;
if(iPad==ProfileManager.GetPrimaryPad())
{
ActionGameSettings(iPad,eVal);
}
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_SoundFXVolume:
if(GameSettingsA[iPad]->ucSoundFXVolume!=ucVal)
{
GameSettingsA[iPad]->ucSoundFXVolume=ucVal;
if(iPad==ProfileManager.GetPrimaryPad())
{
ActionGameSettings(iPad,eVal);
}
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_RenderDistance:
{
unsigned int val = ucVal & 0xFF;
GameSettingsA[iPad]->uiBitmaskValues &= ~(0xFF << 16);
GameSettingsA[iPad]->uiBitmaskValues |= val << 16;
if(iPad == ProfileManager.GetPrimaryPad())
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged = true;
}
break;
case eGameSetting_Gamma:
if(GameSettingsA[iPad]->ucGamma!=ucVal)
{
GameSettingsA[iPad]->ucGamma=ucVal;
if(iPad==ProfileManager.GetPrimaryPad())
{
ActionGameSettings(iPad,eVal);
}
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_FOV:
if(GameSettingsA[iPad]->ucFov!=ucVal)
{
GameSettingsA[iPad]->ucFov=ucVal;
if(iPad==ProfileManager.GetPrimaryPad())
{
ActionGameSettings(iPad,eVal);
}
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_Difficulty:
if((GameSettingsA[iPad]->usBitmaskValues&0x03)!=(ucVal&0x03))
{
GameSettingsA[iPad]->usBitmaskValues&=~0x03;
GameSettingsA[iPad]->usBitmaskValues|=ucVal&0x03;
if(iPad==ProfileManager.GetPrimaryPad())
{
ActionGameSettings(iPad,eVal);
}
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_Sensitivity_InGame:
if(GameSettingsA[iPad]->ucSensitivity!=ucVal)
{
GameSettingsA[iPad]->ucSensitivity=ucVal;
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_ViewBob:
if((GameSettingsA[iPad]->usBitmaskValues&0x0004)!=((ucVal&0x01)<<2))
{
if(ucVal!=0)
{
GameSettingsA[iPad]->usBitmaskValues|=0x0004;
}
else
{
GameSettingsA[iPad]->usBitmaskValues&=~0x0004;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_ControlScheme: // bits 5 and 6
if((GameSettingsA[iPad]->usBitmaskValues&0x30)!=((ucVal&0x03)<<4))
{
GameSettingsA[iPad]->usBitmaskValues&=~0x0030;
if(ucVal!=0)
{
GameSettingsA[iPad]->usBitmaskValues|=(ucVal&0x03)<<4;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_ControlInvertLook:
if((GameSettingsA[iPad]->usBitmaskValues&0x0040)!=((ucVal&0x01)<<6))
{
if(ucVal!=0)
{
GameSettingsA[iPad]->usBitmaskValues|=0x0040;
}
else
{
GameSettingsA[iPad]->usBitmaskValues&=~0x0040;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_ControlSouthPaw:
if((GameSettingsA[iPad]->usBitmaskValues&0x0080)!=((ucVal&0x01)<<7))
{
if(ucVal!=0)
{
GameSettingsA[iPad]->usBitmaskValues|=0x0080;
}
else
{
GameSettingsA[iPad]->usBitmaskValues&=~0x0080;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_SplitScreenVertical:
if((GameSettingsA[iPad]->usBitmaskValues&0x0100)!=((ucVal&0x01)<<8))
{
if(ucVal!=0)
{
GameSettingsA[iPad]->usBitmaskValues|=0x0100;
}
else
{
GameSettingsA[iPad]->usBitmaskValues&=~0x0100;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_GamertagsVisible:
if((GameSettingsA[iPad]->usBitmaskValues&0x0008)!=((ucVal&0x01)<<3))
{
if(ucVal!=0)
{
GameSettingsA[iPad]->usBitmaskValues|=0x0008;
}
else
{
GameSettingsA[iPad]->usBitmaskValues&=~0x0008;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
// 4J-PB - Added for Interim TU for 1.6.6
case eGameSetting_Sensitivity_InMenu:
if(GameSettingsA[iPad]->ucMenuSensitivity!=ucVal)
{
GameSettingsA[iPad]->ucMenuSensitivity=ucVal;
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_DisplaySplitscreenGamertags:
if((GameSettingsA[iPad]->usBitmaskValues&0x0200)!=((ucVal&0x01)<<9))
{
if(ucVal!=0)
{
GameSettingsA[iPad]->usBitmaskValues|=0x0200;
}
else
{
GameSettingsA[iPad]->usBitmaskValues&=~0x0200;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_Hints:
if((GameSettingsA[iPad]->usBitmaskValues&0x0400)!=((ucVal&0x01)<<10))
{
if(ucVal!=0)
{
GameSettingsA[iPad]->usBitmaskValues|=0x0400;
}
else
{
GameSettingsA[iPad]->usBitmaskValues&=~0x0400;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_Autosave:
if((GameSettingsA[iPad]->usBitmaskValues&0x7800)!=((ucVal&0x0F)<<11))
{
GameSettingsA[iPad]->usBitmaskValues&=~0x7800;
if(ucVal!=0)
{
GameSettingsA[iPad]->usBitmaskValues|=(ucVal&0x0F)<<11;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_Tooltips:
if((GameSettingsA[iPad]->usBitmaskValues&0x8000)!=((ucVal&0x01)<<15))
{
if(ucVal!=0)
{
GameSettingsA[iPad]->usBitmaskValues|=0x8000;
}
else
{
GameSettingsA[iPad]->usBitmaskValues&=~0x8000;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_InterfaceOpacity:
if(GameSettingsA[iPad]->ucInterfaceOpacity!=ucVal)
{
GameSettingsA[iPad]->ucInterfaceOpacity=ucVal;
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_Clouds:
if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_CLOUDS)!=(ucVal&0x01))
{
if(ucVal==1)
{
GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_CLOUDS;
}
else
{
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_CLOUDS;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_Online:
if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_ONLINE)!=(ucVal&0x01)<<1)
{
if(ucVal==1)
{
GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_ONLINE;
}
else
{
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_ONLINE;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_InviteOnly:
if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_INVITEONLY)!=(ucVal&0x01)<<2)
{
if(ucVal==1)
{
GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_INVITEONLY;
}
else
{
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_INVITEONLY;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_FriendsOfFriends:
if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_FRIENDSOFFRIENDS)!=(ucVal&0x01)<<3)
{
if(ucVal==1)
{
GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_FRIENDSOFFRIENDS;
}
else
{
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_FRIENDSOFFRIENDS;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_DisplayUpdateMessage:
if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYUPDATEMSG)!=(ucVal&0x03)<<4)
{
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_DISPLAYUPDATEMSG;
if(ucVal>0)
{
GameSettingsA[iPad]->uiBitmaskValues|=(ucVal&0x03)<<4;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_BedrockFog:
if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_BEDROCKFOG)!=(ucVal&0x01)<<6)
{
if(ucVal==1)
{
GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_BEDROCKFOG;
}
else
{
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_DisplayHUD:
if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYHUD)!=(ucVal&0x01)<<7)
{
if(ucVal==1)
{
GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_DISPLAYHUD;
}
else
{
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_DISPLAYHUD;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_DisplayHand:
if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYHAND)!=(ucVal&0x01)<<8)
{
if(ucVal==1)
{
GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_DISPLAYHAND;
}
else
{
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_DISPLAYHAND;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_CustomSkinAnim:
if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_CUSTOMSKINANIM)!=(ucVal&0x01)<<9)
{
if(ucVal==1)
{
GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM;
}
else
{
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_CUSTOMSKINANIM;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
// TU9
case eGameSetting_DeathMessages:
if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DEATHMESSAGES)!=(ucVal&0x01)<<10)
{
if(ucVal==1)
{
GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES;
}
else
{
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_DEATHMESSAGES;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_UISize:
if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_UISIZE)!=((ucVal&0x03)<<11))
{
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_UISIZE;
if(ucVal!=0)
{
GameSettingsA[iPad]->uiBitmaskValues|=(ucVal&0x03)<<11;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_UISizeSplitscreen:
if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_UISIZE_SPLITSCREEN)!=((ucVal&0x03)<<13))
{
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_UISIZE_SPLITSCREEN;
if(ucVal!=0)
{
GameSettingsA[iPad]->uiBitmaskValues|=(ucVal&0x03)<<13;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_AnimatedCharacter:
if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_ANIMATEDCHARACTER)!=(ucVal&0x01)<<15)
{
if(ucVal==1)
{
GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER;
}
else
{
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_ANIMATEDCHARACTER;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_PS3_EULA_Read:
if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PS3EULAREAD)!=(ucVal&0x01)<<16)
{
if(ucVal==1)
{
GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_PS3EULAREAD;
}
else
{
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_PS3EULAREAD;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_PSVita_NetworkModeAdhoc:
if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PSVITANETWORKMODEADHOC)!=(ucVal&0x01)<<17)
{
if(ucVal==1)
{
GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_PSVITANETWORKMODEADHOC;
}
else
{
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_PSVITANETWORKMODEADHOC;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
}
}
unsigned char CMinecraftApp::GetGameSettings(eGameSetting eVal)
{
int iPad=ProfileManager.GetPrimaryPad();
return GetGameSettings(iPad,eVal);
}
unsigned char CMinecraftApp::GetGameSettings(int iPad,eGameSetting eVal)
{
switch(eVal)
{
case eGameSetting_MusicVolume:
return GameSettingsA[iPad]->ucMusicVolume;
break;
case eGameSetting_SoundFXVolume:
return GameSettingsA[iPad]->ucSoundFXVolume;
break;
case eGameSetting_RenderDistance:
{
int val = (GameSettingsA[iPad]->uiBitmaskValues >> 16) & 0xFF;
if(val == 0) return val = 16; //brain
return val;
break;
}
case eGameSetting_Gamma:
return GameSettingsA[iPad]->ucGamma;
break;
case eGameSetting_FOV:
return GameSettingsA[iPad]->ucFov;
break;
case eGameSetting_Difficulty:
return GameSettingsA[iPad]->usBitmaskValues&0x0003;
break;
case eGameSetting_Sensitivity_InGame:
return GameSettingsA[iPad]->ucSensitivity;
break;
case eGameSetting_ViewBob:
return ((GameSettingsA[iPad]->usBitmaskValues&0x0004)>>2);
break;
case eGameSetting_GamertagsVisible:
return ((GameSettingsA[iPad]->usBitmaskValues&0x0008)>>3);
break;
case eGameSetting_ControlScheme:
return ((GameSettingsA[iPad]->usBitmaskValues&0x0030)>>4); // 2 bits
break;
case eGameSetting_ControlInvertLook:
return ((GameSettingsA[iPad]->usBitmaskValues&0x0040)>>6);
break;
case eGameSetting_ControlSouthPaw:
return ((GameSettingsA[iPad]->usBitmaskValues&0x0080)>>7);
break;
case eGameSetting_SplitScreenVertical:
return ((GameSettingsA[iPad]->usBitmaskValues&0x0100)>>8);
break;
// 4J-PB - Added for Interim TU for 1.6.6
case eGameSetting_Sensitivity_InMenu:
return GameSettingsA[iPad]->ucMenuSensitivity;
break;
case eGameSetting_DisplaySplitscreenGamertags:
return ((GameSettingsA[iPad]->usBitmaskValues&0x0200)>>9);
break;
case eGameSetting_Hints:
return ((GameSettingsA[iPad]->usBitmaskValues&0x0400)>>10);
break;
case eGameSetting_Autosave:
{
unsigned char ucVal=(GameSettingsA[iPad]->usBitmaskValues&0x7800)>>11;
return ucVal;
}
break;
case eGameSetting_Tooltips:
return ((GameSettingsA[iPad]->usBitmaskValues&0x8000)>>15);
break;
case eGameSetting_InterfaceOpacity:
return GameSettingsA[iPad]->ucInterfaceOpacity;
break;
case eGameSetting_Clouds:
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_CLOUDS);
break;
case eGameSetting_Online:
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_ONLINE)>>1;
break;
case eGameSetting_InviteOnly:
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_INVITEONLY)>>2;
break;
case eGameSetting_FriendsOfFriends:
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_FRIENDSOFFRIENDS)>>3;
break;
case eGameSetting_DisplayUpdateMessage:
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYUPDATEMSG)>>4;
break;
case eGameSetting_BedrockFog:
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_BEDROCKFOG)>>6;
break;
case eGameSetting_DisplayHUD:
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYHUD)>>7;
break;
case eGameSetting_DisplayHand:
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYHAND)>>8;
break;
case eGameSetting_CustomSkinAnim:
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_CUSTOMSKINANIM)>>9;
break;
// TU9
case eGameSetting_DeathMessages:
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DEATHMESSAGES)>>10;
break;
case eGameSetting_UISize:
{
unsigned char ucVal=(GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_UISIZE)>>11;
return ucVal;
}
break;
case eGameSetting_UISizeSplitscreen:
{
unsigned char ucVal=(GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_UISIZE_SPLITSCREEN)>>13;
return ucVal;
}
break;
case eGameSetting_AnimatedCharacter:
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_ANIMATEDCHARACTER)>>15;
case eGameSetting_PS3_EULA_Read:
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PS3EULAREAD)>>16;
case eGameSetting_PSVita_NetworkModeAdhoc:
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PSVITANETWORKMODEADHOC)>>17;
}
return 0;
}
void CMinecraftApp::CheckGameSettingsChanged(bool bOverride5MinuteTimer, int iPad)
{
// If the settings have changed, write them to the profile
if(iPad==XUSER_INDEX_ANY)
{
for(int i=0;i<XUSER_MAX_COUNT;i++)
{
if(GameSettingsA[i]->bSettingsChanged)
{
#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__ )
StorageManager.WriteToProfile(i,true, bOverride5MinuteTimer);
#else
ProfileManager.WriteToProfile(i,true, bOverride5MinuteTimer);
#ifdef _WINDOWS64
Win64_SaveSettings(GameSettingsA[i]);
#endif
#endif
GameSettingsA[i]->bSettingsChanged=false;
}
}
}
else
{
if(GameSettingsA[iPad]->bSettingsChanged)
{
#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
StorageManager.WriteToProfile(iPad,true, bOverride5MinuteTimer);
#else
ProfileManager.WriteToProfile(iPad,true, bOverride5MinuteTimer);
#ifdef _WINDOWS64
Win64_SaveSettings(GameSettingsA[iPad]);
#endif
#endif
GameSettingsA[iPad]->bSettingsChanged=false;
}
}
}
void CMinecraftApp::ClearGameSettingsChangedFlag(int iPad)
{
GameSettingsA[iPad]->bSettingsChanged=false;
}
///////////////////////////
//
// Remove the debug settings in the release build
//
////////////////////////////
#ifndef _DEBUG
unsigned int CMinecraftApp::GetGameSettingsDebugMask(int iPad,bool bOverridePlayer) //bOverridePlayer is to force the send for the server to get the read options
{
return 0;
}
void CMinecraftApp::SetGameSettingsDebugMask(int iPad, unsigned int uiVal)
{
}
void CMinecraftApp::ActionDebugMask(int iPad,bool bSetAllClear)
{
}
#else
unsigned int CMinecraftApp::GetGameSettingsDebugMask(int iPad,bool bOverridePlayer) //bOverridePlayer is to force the send for the server to get the read options
{
if(iPad==-1)
{
iPad=ProfileManager.GetPrimaryPad();
}
if(iPad < 0) iPad = 0;
shared_ptr<Player> player = Minecraft::GetInstance()->localplayers[iPad];
if(bOverridePlayer || player==NULL)
{
return GameSettingsA[iPad]->uiDebugBitmask;
}
else
{
return player->GetDebugOptions();
}
}
void CMinecraftApp::SetGameSettingsDebugMask(int iPad, unsigned int uiVal)
{
#ifndef _CONTENT_PACKAGE
GameSettingsA[iPad]->bSettingsChanged=true;
GameSettingsA[iPad]->uiDebugBitmask=uiVal;
// update the value so the network server can use it
shared_ptr<Player> player = Minecraft::GetInstance()->localplayers[iPad];
if(player)
{
Minecraft::GetInstance()->localgameModes[iPad]->handleDebugOptions(uiVal,player);
}
#endif
}
void CMinecraftApp::ActionDebugMask(int iPad,bool bSetAllClear)
{
unsigned int ulBitmask=app.GetGameSettingsDebugMask(iPad);
if(bSetAllClear) ulBitmask=0L;
// these settings should only be actioned for the primary player
if(ProfileManager.GetPrimaryPad()!=iPad) return;
for(int i=0;i<eDebugSetting_Max;i++)
{
switch(i)
{
case eDebugSetting_LoadSavesFromDisk:
if(ulBitmask&(1<<i))
{
app.SetLoadSavesFromFolderEnabled(true);
}
else
{
app.SetLoadSavesFromFolderEnabled(false);
}
break;
case eDebugSetting_WriteSavesToDisk:
if(ulBitmask&(1<<i))
{
app.SetWriteSavesToFolderEnabled(true);
}
else
{
app.SetWriteSavesToFolderEnabled(false);
}
break;
case eDebugSetting_FreezePlayers: //eDebugSetting_InterfaceOff:
if(ulBitmask&(1<<i))
{
app.SetFreezePlayers(true);
// Turn off interface rendering.
//app.SetInterfaceRenderingOff( true );
}
else
{
app.SetFreezePlayers(false);
// Turn on interface rendering.
//app.SetInterfaceRenderingOff( false );
}
break;
case eDebugSetting_Safearea:
if(ulBitmask&(1<<i))
{
app.ShowSafeArea( TRUE );
}
else
{
app.ShowSafeArea( FALSE );
}
break;
//case eDebugSetting_HandRenderingOff:
// if(ulBitmask&(1<<i))
// {
// // Turn off hand rendering.
// //app.SetHandRenderingOff( true );
// }
// else
// {
// // Turn on hand rendering.
// //app.SetHandRenderingOff( false );
// }
// break;
case eDebugSetting_ShowUIConsole:
if(ulBitmask&(1<<i))
{
ui.ShowUIDebugConsole(true);
}
else
{
ui.ShowUIDebugConsole(false);
}
break;
case eDebugSetting_ShowUIMarketingGuide:
if(ulBitmask&(1<<i))
{
ui.ShowUIDebugMarketingGuide(true);
}
else
{
ui.ShowUIDebugMarketingGuide(false);
}
break;
case eDebugSetting_MobsDontAttack:
if(ulBitmask&(1<<i))
{
app.SetMobsDontAttackEnabled(true);
}
else
{
app.SetMobsDontAttackEnabled(false);
}
break;
case eDebugSetting_UseDpadForDebug:
if(ulBitmask&(1<<i))
{
app.SetUseDPadForDebug(true);
}
else
{
app.SetUseDPadForDebug(false);
}
break;
case eDebugSetting_MobsDontTick:
if(ulBitmask&(1<<i))
{
app.SetMobsDontTickEnabled(true);
}
else
{
app.SetMobsDontTickEnabled(false);
}
break;
}
}
}
#endif
int CMinecraftApp::DisplaySavingMessage(void *pParam, C4JStorage::ESavingMessage eVal, int iPad)
{
//CMinecraftApp* pClass = (CMinecraftApp*)pParam;
ui.ShowSavingMessage(iPad, eVal);
return 0;
}
void CMinecraftApp::SetActionConfirmed(LPVOID param)
{
XuiActionParam *actionInfo = (XuiActionParam *)param;
app.SetAction(actionInfo->iPad, actionInfo->action);
}
void CMinecraftApp::HandleXuiActions(void)
{
eXuiAction eAction;
eTMSAction eTMS;
LPVOID param;
Minecraft *pMinecraft=Minecraft::GetInstance();
shared_ptr<MultiplayerLocalPlayer> player;
// are there any global actions to deal with?
eAction = app.GetGlobalXuiAction();
if(eAction!=eAppAction_Idle)
{
switch(eAction)
{
case eAppAction_DisplayLavaMessage:
// Display a warning about placing lava in the spawn area
{
UINT uiIDA[1];
uiIDA[0]=IDS_CONFIRM_OK;
C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_CANT_PLACE_NEAR_SPAWN_TITLE, IDS_CANT_PLACE_NEAR_SPAWN_TEXT, uiIDA,1,XUSER_INDEX_ANY);
if(result != C4JStorage::EMessage_Busy) SetGlobalXuiAction(eAppAction_Idle);
}
break;
default:
break;
}
}
// are there any app actions to deal with?
for(int i=0;i<XUSER_MAX_COUNT;i++)
{
eAction = app.GetXuiAction(i);
param = m_eXuiActionParam[i];
if(eAction!=eAppAction_Idle)
{
switch(eAction)
{
// the renderer will capture a screenshot
case eAppAction_SocialPost:
if(ProfileManager.IsFullVersion())
{
// Facebook Share
if( CSocialManager::Instance()->IsTitleAllowedToPostImages() && CSocialManager::Instance()->AreAllUsersAllowedToPostImages() )
{
// disable character name tags for the shot
//m_bwasHidingGui = pMinecraft->options->hideGui; // 4J Stu - Removed 1.8.2 bug fix (TU6) as don't need this
pMinecraft->options->hideGui = true;
SetAction(i,eAppAction_SocialPostScreenshot);
}
else
{
SetAction(i,eAppAction_Idle);
}
}
else
{
SetAction(i,eAppAction_Idle);
}
break;
case eAppAction_SocialPostScreenshot:
{
SetAction(i,eAppAction_Idle);
bool bKeepHiding = false;
for(int j=0; j < XUSER_MAX_COUNT;++j)
{
if(app.GetXuiAction(j) == eAppAction_SocialPostScreenshot)
{
bKeepHiding = true;
break;
}
}
pMinecraft->options->hideGui=bKeepHiding;
// Facebook Share
if(app.GetLocalPlayerCount()>1)
{
ui.NavigateToScene(i,eUIScene_SocialPost);
}
else
{
ui.NavigateToScene(i,eUIScene_SocialPost);
}
}
break;
case eAppAction_SaveGame:
SetAction(i,eAppAction_Idle);
if(!GetChangingSessionType())
{
// If this is the trial game, do an upsell
if(ProfileManager.IsFullVersion())
{
// flag the render to capture the screenshot for the save
SetAction(i,eAppAction_SaveGameCapturedThumbnail);
}
else
{
// ask the player if they would like to upgrade, or they'll lose the level
UINT uiIDA[2];
uiIDA[0]=IDS_CONFIRM_OK;
uiIDA[1]=IDS_CONFIRM_CANCEL;
ui.RequestErrorMessage(IDS_UNLOCK_TITLE, IDS_UNLOCK_TOSAVE_TEXT, uiIDA, 2,i,&CMinecraftApp::UnlockFullSaveReturned,this);
}
}
break;
case eAppAction_AutosaveSaveGame:
{
// Need to run a check to see if the save exists in order to stop the dialog asking if we want to overwrite it coming up on an autosave
bool bSaveExists;
StorageManager.DoesSaveExist(&bSaveExists);
SetAction(i,eAppAction_Idle);
if(!GetChangingSessionType())
{
// flag the render to capture the screenshot for the save
SetAction(i,eAppAction_AutosaveSaveGameCapturedThumbnail);
}
}
break;
case eAppAction_SaveGameCapturedThumbnail:
// reset the autosave timer
app.SetAutosaveTimerTime();
SetAction(i,eAppAction_Idle);
// Check that there is a name for the save - if we're saving from the tutorial and this is the first save from the tutorial, we'll not have a name
/*if(StorageManager.GetSaveName()==NULL)
{
app.NavigateToScene(i,eUIScene_SaveWorld);
}
else*/
{
// turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
ui.HideAllGameUIElements();
// Hide the other players scenes
ui.ShowOtherPlayersBaseScene(ProfileManager.GetPrimaryPad(), false);
//INT saveOrCheckpointId = 0;
//bool validSave = StorageManager.GetSaveUniqueNumber(&saveOrCheckpointId);
//SentientManager.RecordLevelSaveOrCheckpoint(ProfileManager.GetPrimaryPad(), saveOrCheckpointId);
LoadingInputParams *loadingParams = new LoadingInputParams();
loadingParams->func = &UIScene_PauseMenu::SaveWorldThreadProc;
loadingParams->lpParam = (LPVOID)false;
// 4J-JEV - PS4: Fix for #5708 - [ONLINE] - If the user pulls their network cable out while saving the title will hang.
loadingParams->waitForThreadToDelete = true;
UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
completionData->bShowBackground=TRUE;
completionData->bShowLogo=TRUE;
completionData->type = e_ProgressCompletion_NavigateBackToScene;
completionData->iPad = ProfileManager.GetPrimaryPad();
if( ui.IsSceneInStack( ProfileManager.GetPrimaryPad(), eUIScene_EndPoem ) )
{
completionData->scene = eUIScene_EndPoem;
}
else
{
completionData->scene = eUIScene_PauseMenu;
}
loadingParams->completionData = completionData;
// 4J Stu - Xbox only
#ifdef _XBOX
// Temporarily make this scene fullscreen
CXuiSceneBase::SetPlayerBaseScenePosition( ProfileManager.GetPrimaryPad(), CXuiSceneBase::e_BaseScene_Fullscreen );
#endif
ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams , eUILayer_Fullscreen, eUIGroup_Fullscreen);
}
break;
case eAppAction_AutosaveSaveGameCapturedThumbnail:
{
app.SetAutosaveTimerTime();
SetAction(i,eAppAction_Idle);
#if defined(_XBOX_ONE) || defined(__ORBIS__)
app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_AutoSaveGame);
if(app.GetGameHostOption(eGameHostOption_DisableSaving)) StorageManager.SetSaveDisabled(true);
#else
// turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
ui.HideAllGameUIElements();
//app.CloseAllPlayersXuiScenes();
// Hide the other players scenes
ui.ShowOtherPlayersBaseScene(ProfileManager.GetPrimaryPad(), false);
// This just allows it to be shown
if(pMinecraft->localgameModes[ProfileManager.GetPrimaryPad()] != NULL) pMinecraft->localgameModes[ProfileManager.GetPrimaryPad()]->getTutorial()->showTutorialPopup(false);
//INT saveOrCheckpointId = 0;
//bool validSave = StorageManager.GetSaveUniqueNumber(&saveOrCheckpointId);
//SentientManager.RecordLevelSaveOrCheckpoint(ProfileManager.GetPrimaryPad(), saveOrCheckpointId);
LoadingInputParams *loadingParams = new LoadingInputParams();
loadingParams->func = &UIScene_PauseMenu::SaveWorldThreadProc;
loadingParams->lpParam = (LPVOID)true;
UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
completionData->bShowBackground=TRUE;
completionData->bShowLogo=TRUE;
completionData->type = e_ProgressCompletion_AutosaveNavigateBack;
completionData->iPad = ProfileManager.GetPrimaryPad();
//completionData->bAutosaveWasMenuDisplayed=ui.GetMenuDisplayed(ProfileManager.GetPrimaryPad());
loadingParams->completionData = completionData;
// 4J Stu - Xbox only
#ifdef _XBOX
// Temporarily make this scene fullscreen
CXuiSceneBase::SetPlayerBaseScenePosition( ProfileManager.GetPrimaryPad(), CXuiSceneBase::e_BaseScene_Fullscreen );
#endif
ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams , eUILayer_Fullscreen, eUIGroup_Fullscreen);
#endif
}
break;
case eAppAction_ExitPlayer:
// a secondary player has chosen to quit
{
int iPlayerC=g_NetworkManager.GetPlayerCount();
// Since the player is exiting, let's flush any profile writes for them, and hope we're not breaking TCR 136...
#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
StorageManager.ForceQueuedProfileWrites(i);
LeaderboardManager::Instance()->OpenSession();
for (int j = 0; j < XUSER_MAX_COUNT; j++)
{
if( ProfileManager.IsSignedIn(j) )
{
app.DebugPrintf("Stats save for an offline game for the player at index %d\n", 0);
Minecraft::GetInstance()->forceStatsSave(j);
}
}
LeaderboardManager::Instance()->CloseSession();
#else
ProfileManager.ForceQueuedProfileWrites(i);
#endif
// not required - it's done within the removeLocalPlayerIdx
// if(pMinecraft->level->isClientSide)
// {
// // we need to remove the qnetplayer, or this player won't be able to get back into the game until qnet times out and removes them
// g_NetworkManager.NotifyPlayerLeaving(g_NetworkManager.GetLocalPlayerByUserIndex(i));
// }
// if there are any tips showing, we need to close them
pMinecraft->gui->clearMessages(i);
// Make sure we've not got this player selected as current - this shouldn't be the case anyway
pMinecraft->setLocalPlayerIdx(ProfileManager.GetPrimaryPad());
pMinecraft->removeLocalPlayerIdx(i);
#ifdef _XBOX
// tell the xui scenes a splitscreen player left - has to come after removeLocalPlayerIdx which calls updatePlayerViewportAssignments
XUIMessage xuiMsg;
CustomMessage_Splitscreenplayer_Struct myMsgData;
CustomMessage_Splitscreenplayer( &xuiMsg, &myMsgData, false);
// send the message
for(int idx=0;idx<XUSER_MAX_COUNT;idx++)
{
if((i!=idx) && (pMinecraft->localplayers[idx]!=NULL))
{
XuiBroadcastMessage( CXuiSceneBase::GetPlayerBaseScene(idx), &xuiMsg );
}
}
#endif
#ifndef _XBOX
// Wipe out the tooltips
ui.SetTooltips(i, -1);
#endif
// Change the presence info
// Are we offline or online, and how many players are there
if(iPlayerC>2) // one player is about to leave here - they'll be set to idle in the qnet manager player leave
{
for(int iPlayer=0;iPlayer<XUSER_MAX_COUNT;iPlayer++)
{
if((iPlayer!=i) && pMinecraft->localplayers[iPlayer])
{
if(g_NetworkManager.IsLocalGame())
{
ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false);
}
else
{
ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER,false);
}
}
}
}
else
{
for(int iPlayer=0;iPlayer<XUSER_MAX_COUNT;iPlayer++)
{
if((iPlayer!=i) && pMinecraft->localplayers[iPlayer])
{
if(g_NetworkManager.IsLocalGame())
{
ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE,false);
}
else
{
ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER_1P,false);
}
}
}
}
#ifdef _DURANGO
ProfileManager.RemoveGamepadFromGame(i);
#endif
SetAction(i,eAppAction_Idle);
}
break;
case eAppAction_ExitPlayerPreLogin:
{
int iPlayerC=g_NetworkManager.GetPlayerCount();
// Since the player is exiting, let's flush any profile writes for them, and hope we're not breaking TCR 136...
#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
StorageManager.ForceQueuedProfileWrites(i);
#else
ProfileManager.ForceQueuedProfileWrites(i);
#endif
// if there are any tips showing, we need to close them
pMinecraft->gui->clearMessages(i);
// Make sure we've not got this player selected as current - this shouldn't be the case anyway
pMinecraft->setLocalPlayerIdx(ProfileManager.GetPrimaryPad());
pMinecraft->removeLocalPlayerIdx(i);
#ifdef _XBOX
// tell the xui scenes a splitscreen player left - has to come after removeLocalPlayerIdx which calls updatePlayerViewportAssignments
XUIMessage xuiMsg;
CustomMessage_Splitscreenplayer_Struct myMsgData;
CustomMessage_Splitscreenplayer( &xuiMsg, &myMsgData, false);
// send the message
for(int idx=0;idx<XUSER_MAX_COUNT;idx++)
{
if((i!=idx) && (pMinecraft->localplayers[idx]!=NULL))
{
XuiBroadcastMessage( CXuiSceneBase::GetPlayerBaseScene(idx), &xuiMsg );
}
}
#endif
#ifndef _XBOX
// Wipe out the tooltips
ui.SetTooltips(i, -1);
#endif
// Change the presence info
// Are we offline or online, and how many players are there
if(iPlayerC>2) // one player is about to leave here - they'll be set to idle in the qnet manager player leave
{
for(int iPlayer=0;iPlayer<XUSER_MAX_COUNT;iPlayer++)
{
if((iPlayer!=i) && pMinecraft->localplayers[iPlayer])
{
if(g_NetworkManager.IsLocalGame())
{
ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false);
}
else
{
ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER,false);
}
}
}
}
else
{
for(int iPlayer=0;iPlayer<XUSER_MAX_COUNT;iPlayer++)
{
if((iPlayer!=i) && pMinecraft->localplayers[iPlayer])
{
if(g_NetworkManager.IsLocalGame())
{
ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE,false);
}
else
{
ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER_1P,false);
}
}
}
}
SetAction(i,eAppAction_Idle);
}
break;
#ifdef __ORBIS__
case eAppAction_OptionsSaveNoSpace:
{
SetAction(i,eAppAction_Idle);
SceSaveDataDialogParam param;
SceSaveDataDialogSystemMessageParam sysParam;
SceSaveDataDialogItems items;
SceSaveDataDirName dirName;
sceSaveDataDialogParamInitialize(&param);
param.mode = SCE_SAVE_DATA_DIALOG_MODE_SYSTEM_MSG;
param.dispType = SCE_SAVE_DATA_DIALOG_TYPE_SAVE;
memset(&sysParam,0,sizeof(sysParam));
param.sysMsgParam = &sysParam;
param.sysMsgParam->sysMsgType = SCE_SAVE_DATA_DIALOG_SYSMSG_TYPE_NOSPACE_CONTINUABLE;
param.sysMsgParam->value = app.GetOptionsBlocksRequired(i);
memset(&items, 0, sizeof(items));
param.items = &items;
param.items->userId = ProfileManager.getUserID(i);
int ret = sceSaveDataDialogInitialize();
ret = sceSaveDataDialogOpen(&param);
app.SetOptionsSaveDataDialogRunning(true);//m_bOptionsSaveDataDialogRunning = true;
//pClass->m_eSaveIncompleteType = saveIncompleteType;
//StorageManager.SetSaveDisabled(true);
//pClass->EnterSaveNotificationSection();
}
break;
#endif
case eAppAction_ExitWorld:
SetAction(i,eAppAction_Idle);
// If we're already leaving don't exit
if (g_NetworkManager.IsLeavingGame())
{
break;
}
pMinecraft->gui->clearMessages();
// turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
ui.HideAllGameUIElements();
// reset the flag stopping new dlc message being shown if you've seen the message before
DisplayNewDLCTipAgain();
// clear the autosave timer that might be on screen
ui.ShowAutosaveCountdownTimer(false);
// Hide the selected item text
ui.HideAllGameUIElements();
// Since the player forced the exit, let's flush any profile writes, and hope we're not breaking TCR 136...
#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
StorageManager.ForceQueuedProfileWrites();
LeaderboardManager::Instance()->OpenSession();
for (int j = 0; j < XUSER_MAX_COUNT; j++)
{
if( ProfileManager.IsSignedIn(j) )
{
app.DebugPrintf("Stats save for an offline game for the player at index %d\n", 0);
Minecraft::GetInstance()->forceStatsSave(j);
}
}
LeaderboardManager::Instance()->CloseSession();
#elif (defined _XBOX)
ProfileManager.ForceQueuedProfileWrites();
#endif
// 4J-PB - cancel any possible string verifications queued with LIVE
//InputManager.CancelAllVerifyInProgress();
if(ProfileManager.IsFullVersion())
{
// In a split screen, only the primary player actually quits the game, others just remove their players
if( i != ProfileManager.GetPrimaryPad() )
{
// Make sure we've not got this player selected as current - this shouldn't be the case anyway
pMinecraft->setLocalPlayerIdx(ProfileManager.GetPrimaryPad());
pMinecraft->removeLocalPlayerIdx(i);
#ifdef _DURANGO
ProfileManager.RemoveGamepadFromGame(i);
#endif
SetAction(i,eAppAction_Idle);
return;
}
// flag to capture the save thumbnail
SetAction(i,eAppAction_ExitWorldCapturedThumbnail, param);
}
else
{
// ask the player if they would like to upgrade, or they'll lose the level
UINT uiIDA[2];
uiIDA[0]=IDS_CONFIRM_OK;
uiIDA[1]=IDS_CONFIRM_CANCEL;
ui.RequestErrorMessage(IDS_UNLOCK_TITLE, IDS_UNLOCK_TOSAVE_TEXT, uiIDA, 2, i,&CMinecraftApp::UnlockFullExitReturned,this);
}
// Change the presence info
// Are we offline or online, and how many players are there
if(g_NetworkManager.GetPlayerCount()>1)
{
for(int j=0;j<XUSER_MAX_COUNT;j++)
{
if(pMinecraft->localplayers[j])
{
if(g_NetworkManager.IsLocalGame())
{
app.SetRichPresenceContext(j,CONTEXT_GAME_STATE_BLANK);
ProfileManager.SetCurrentGameActivity(j,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false);
}
else
{
app.SetRichPresenceContext(j,CONTEXT_GAME_STATE_BLANK);
ProfileManager.SetCurrentGameActivity(j,CONTEXT_PRESENCE_MULTIPLAYER,false);
}
TelemetryManager->RecordLevelExit(j, eSen_LevelExitStatus_Exited);
}
}
}
else
{
app.SetRichPresenceContext(i,CONTEXT_GAME_STATE_BLANK);
if(g_NetworkManager.IsLocalGame())
{
ProfileManager.SetCurrentGameActivity(i,CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE,false);
}
else
{
ProfileManager.SetCurrentGameActivity(i,CONTEXT_PRESENCE_MULTIPLAYER_1P,false);
}
TelemetryManager->RecordLevelExit(i, eSen_LevelExitStatus_Exited);
}
break;
case eAppAction_ExitWorldCapturedThumbnail:
{
SetAction(i,eAppAction_Idle);
// Stop app running
SetGameStarted(false);
SetChangingSessionType(true); // Added to stop handling ethernet disconnects
ui.CloseAllPlayersScenes();
// turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
ui.HideAllGameUIElements();
// 4J Stu - Fix for #12368 - Crash: Game crashes when saving then exiting and selecting to save
for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
{
#ifdef _XBOX
app.TutorialSceneNavigateBack(idx,true);
#endif
// 4J Stu - Fix for #13257 - CRASH: Gameplay: Title crashed after exiting the tutorial
// It doesn't matter if they were in the tutorial already
pMinecraft->playerLeftTutorial( idx );
}
LoadingInputParams *loadingParams = new LoadingInputParams();
loadingParams->func = &UIScene_PauseMenu::ExitWorldThreadProc;
loadingParams->lpParam = param;
UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
// If param is non-null then this is a forced exit by the server, so make sure the player knows why
// 4J Stu - Changed - Don't use the FullScreenProgressScreen for action, use a dialog instead
completionData->bRequiresUserAction = FALSE;//(param != NULL) ? TRUE : FALSE;
completionData->bShowTips = (param != NULL) ? FALSE : TRUE;
completionData->bShowBackground=TRUE;
completionData->bShowLogo=TRUE;
completionData->type = e_ProgressCompletion_NavigateToHomeMenu;
completionData->iPad = DEFAULT_XUI_MENU_USER;
loadingParams->completionData = completionData;
ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);
}
break;
case eAppAction_ExitWorldTrial:
{
SetAction(i,eAppAction_Idle);
pMinecraft->gui->clearMessages();
// turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
ui.HideAllGameUIElements();
// Stop app running
SetGameStarted(false);
ui.CloseAllPlayersScenes();
// 4J Stu - Fix for #12368 - Crash: Game crashes when saving then exiting and selecting to save
for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
{
#ifdef _XBOX
app.TutorialSceneNavigateBack(idx,true);
#endif
// 4J Stu - Fix for #13257 - CRASH: Gameplay: Title crashed after exiting the tutorial
// It doesn't matter if they were in the tutorial already
pMinecraft->playerLeftTutorial( idx );
}
LoadingInputParams *loadingParams = new LoadingInputParams();
loadingParams->func = &UIScene_PauseMenu::ExitWorldThreadProc;
loadingParams->lpParam = param;
UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
completionData->bShowBackground=TRUE;
completionData->bShowLogo=TRUE;
completionData->type = e_ProgressCompletion_NavigateToHomeMenu;
completionData->iPad = DEFAULT_XUI_MENU_USER;
loadingParams->completionData = completionData;
ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);
}
break;
case eAppAction_ExitTrial:
//XLaunchNewImage(XLAUNCH_KEYWORD_DASH_ARCADE, 0);
ExitGame();
break;
case eAppAction_Respawn:
{
ConnectionProgressParams *param = new ConnectionProgressParams();
param->iPad = i;
param->stringId = IDS_PROGRESS_RESPAWNING;
param->showTooltips = false;
param->setFailTimer = false;
ui.NavigateToScene(i,eUIScene_ConnectingProgress, param);
// Need to reset this incase the player has already died and respawned
pMinecraft->localplayers[i]->SetPlayerRespawned(false);
SetAction(i,eAppAction_WaitForRespawnComplete);
if( app.GetLocalPlayerCount()>1 )
{
// In split screen mode, we don't want to do any async loading or flushing of the cache, just a simple respawn
pMinecraft->localplayers[i]->respawn();
// If the respawn requires a dimension change then the action will have changed
//if(app.GetXuiAction(i) == eAppAction_Respawn)
//{
// SetAction(i,eAppAction_Idle);
// CloseXuiScenes(i);
//}
}
else
{
//SetAction(i,eAppAction_WaitForRespawnComplete);
//LoadingInputParams *loadingParams = new LoadingInputParams();
//loadingParams->func = &CScene_Death::RespawnThreadProc;
//loadingParams->lpParam = (LPVOID)i;
// Disable game & update thread whilst we do any of this
//app.SetGameStarted(false);
pMinecraft->gameRenderer->DisableUpdateThread();
// 4J Stu - We don't need this on a thread in multiplayer as respawning is asynchronous.
pMinecraft->localplayers[i]->respawn();
//app.SetGameStarted(true);
pMinecraft->gameRenderer->EnableUpdateThread();
//UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
//completionData->bShowBackground=TRUE;
//completionData->bShowLogo=TRUE;
//completionData->type = e_ProgressCompletion_CloseUIScenes;
//completionData->iPad = i;
//loadingParams->completionData = completionData;
//app.NavigateToScene(i,eUIScene_FullscreenProgress, loadingParams, true);
}
}
break;
case eAppAction_WaitForRespawnComplete:
player = pMinecraft->localplayers[i];
if(player != NULL && player->GetPlayerRespawned())
{
SetAction(i,eAppAction_Idle);
if(ui.IsSceneInStack(i, eUIScene_EndPoem))
{
ui.NavigateBack(i,false,eUIScene_EndPoem);
}
else
{
ui.CloseUIScenes(i);
}
// clear the progress messages
// pMinecraft->progressRenderer->progressStart(-1);
// pMinecraft->progressRenderer->progressStage(-1);
}
else if(!g_NetworkManager.IsInGameplay())
{
SetAction(i,eAppAction_Idle);
}
break;
case eAppAction_WaitForDimensionChangeComplete:
player = pMinecraft->localplayers[i];
if(player != NULL && player->connection && player->connection->isStarted())
{
SetAction(i,eAppAction_Idle);
ui.CloseUIScenes(i);
}
else if(!g_NetworkManager.IsInGameplay())
{
SetAction(i,eAppAction_Idle);
}
break;
case eAppAction_PrimaryPlayerSignedOut:
{
//SetAction(i,eAppAction_Idle);
// clear the autosavetimer that might be displayed
ui.ShowAutosaveCountdownTimer(false);
// If the player signs out before the game started the server can be killed a bit earlier to stop
// the loading or saving of a new game continuing running while the UI/Guide is up
if(!app.GetGameStarted()) MinecraftServer::HaltServer(true);
// inform the player they are being returned to the menus because they signed out
StorageManager.SetSaveDeviceSelected(i,false);
// need to clear the player stats - can't assume it'll be done in setlevel - we may not be in the game
StatsCounter* pStats = Minecraft::GetInstance()->stats[ i ];
pStats->clear();
// 4J-PB - the libs will display the Returned to Title screen
// UINT uiIDA[1];
// uiIDA[0]=IDS_CONFIRM_OK;
//
// ui.RequestMessageBox(IDS_RETURNEDTOMENU_TITLE, IDS_RETURNEDTOTITLESCREEN_TEXT, uiIDA, 1, i,&CMinecraftApp::PrimaryPlayerSignedOutReturned,this,app.GetStringTable());
if( g_NetworkManager.IsInSession() )
{
app.SetAction(i,eAppAction_PrimaryPlayerSignedOutReturned);
}
else
{
app.SetAction(i,eAppAction_PrimaryPlayerSignedOutReturned_Menus);
MinecraftServer::resetFlags();
}
}
break;
case eAppAction_EthernetDisconnected:
{
app.DebugPrintf("Handling eAppAction_EthernetDisconnected\n");
SetAction(i,eAppAction_Idle);
// 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.
if(!g_NetworkManager.IsLeavingGame())
{
app.DebugPrintf("Handling eAppAction_EthernetDisconnected - Not leaving game\n");
// 4J-PB - not the same as a signout. We should only leave the game if this machine is not the host. We shouldn't get rid of the save device either.
if( g_NetworkManager.IsHost() )
{
app.DebugPrintf("Handling eAppAction_EthernetDisconnected - Is Host\n");
// If it's already a local game, then an ethernet disconnect should have no effect
if( !g_NetworkManager.IsLocalGame() && g_NetworkManager.IsInGameplay() )
{
// Change the session to an offline session
SetAction(i,eAppAction_ChangeSessionType);
}
else if(!g_NetworkManager.IsLocalGame() && !g_NetworkManager.IsInGameplay() )
{
// There are two cases here, either:
// 1. We're early enough in the create/load game that we can do a really minimal shutdown or
// 2. We're far enough in (game has started but the actual game started flag hasn't been set) that we should just wait until we're in the game and switch to offline mode
// If there's a non-null level then, for our purposes, the game has started
bool gameStarted = false;
for(int j = 0; j < pMinecraft->levels.length; j++)
{
if (pMinecraft->levels.data[i] != nullptr)
{
gameStarted = true;
break;
}
}
if (!gameStarted)
{
// 1. Exit
MinecraftServer::HaltServer();
// 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.
// 4J Stu - Leave the session
g_NetworkManager.LeaveGame(FALSE);
// need to clear the player stats - can't assume it'll be done in setlevel - we may not be in the game
StatsCounter* pStats = Minecraft::GetInstance()->stats[ i ];
pStats->clear();
UINT uiIDA[1];
uiIDA[0]=IDS_CONFIRM_OK;
ui.RequestErrorMessage(g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST), g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE), uiIDA, 1, i,&CMinecraftApp::EthernetDisconnectReturned,this);
}
else
{
// 2. Switch to offline
SetAction(i,eAppAction_ChangeSessionType);
}
}
}
else
{
#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__
if(UIScene_LoadOrJoinMenu::isSaveTransferRunning())
{
// the save transfer is still in progress, delay jumping back to the main menu until we've cleaned up
SetAction(i,eAppAction_EthernetDisconnected);
}
else
#endif
{
app.DebugPrintf("Handling eAppAction_EthernetDisconnected - Not host\n");
// need to clear the player stats - can't assume it'll be done in setlevel - we may not be in the game
StatsCounter* pStats = Minecraft::GetInstance()->stats[ i ];
pStats->clear();
UINT uiIDA[1];
uiIDA[0]=IDS_CONFIRM_OK;
ui.RequestErrorMessage(g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST), g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE), uiIDA, 1, i,&CMinecraftApp::EthernetDisconnectReturned,this);
}
}
}
}
break;
// We currently handle both these returns the same way.
case eAppAction_EthernetDisconnectedReturned:
case eAppAction_PrimaryPlayerSignedOutReturned:
{
SetAction(i,eAppAction_Idle);
pMinecraft->gui->clearMessages();
// turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
ui.HideAllGameUIElements();
// set the state back to pre-game
ProfileManager.ResetProfileProcessState();
if( g_NetworkManager.IsLeavingGame() )
{
// 4J Stu - If we are already leaving the game, then we just need to signal that the player signed out to stop saves
pMinecraft->progressRenderer->progressStartNoAbort( IDS_EXITING_GAME );
pMinecraft->progressRenderer->progressStage(-1);
// This has no effect on client machines
MinecraftServer::HaltServer(true);
}
else
{
// Stop app running
SetGameStarted(false);
// turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
ui.HideAllGameUIElements();
ui.CloseAllPlayersScenes();
// 4J Stu - Fix for #12368 - Crash: Game crashes when saving then exiting and selecting to save
for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
{
#ifdef _XBOX
app.TutorialSceneNavigateBack(idx,true);
#endif
// 4J Stu - Fix for #13257 - CRASH: Gameplay: Title crashed after exiting the tutorial
// It doesn't matter if they were in the tutorial already
pMinecraft->playerLeftTutorial( idx );
}
LoadingInputParams *loadingParams = new LoadingInputParams();
loadingParams->func = &CMinecraftApp::SignoutExitWorldThreadProc;
UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
completionData->bShowBackground=TRUE;
completionData->bShowLogo=TRUE;
completionData->iPad=DEFAULT_XUI_MENU_USER;
completionData->type = e_ProgressCompletion_NavigateToHomeMenu;
loadingParams->completionData = completionData;
ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);
}
}
break;
case eAppAction_PrimaryPlayerSignedOutReturned_Menus:
SetAction(i,eAppAction_Idle);
// set the state back to pre-game
ProfileManager.ResetProfileProcessState();
// clear the save device
StorageManager.SetSaveDeviceSelected(i,false);
ui.UpdatePlayerBasePositions();
// there are multiple layers in the help menu, so a navigate back isn't enough
ui.NavigateToHomeMenu();
break;
case eAppAction_EthernetDisconnectedReturned_Menus:
SetAction(i,eAppAction_Idle);
// set the state back to pre-game
ProfileManager.ResetProfileProcessState();
ui.UpdatePlayerBasePositions();
// there are multiple layers in the help menu, so a navigate back isn't enough
ui.NavigateToHomeMenu();
break;
case eAppAction_TrialOver:
{
SetAction(i,eAppAction_Idle);
UINT uiIDA[2];
uiIDA[0]=IDS_UNLOCK_TITLE;
uiIDA[1]=IDS_EXIT_GAME;
ui.RequestErrorMessage(IDS_TRIALOVER_TITLE, IDS_TRIALOVER_TEXT, uiIDA, 2, i,&CMinecraftApp::TrialOverReturned,this);
}
break;
// INVITES
case eAppAction_DashboardTrialJoinFromInvite:
{
TelemetryManager->RecordUpsellPresented(i, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID);
SetAction(i,eAppAction_Idle);
UINT uiIDA[2];
uiIDA[0]=IDS_CONFIRM_OK;
uiIDA[1]=IDS_CONFIRM_CANCEL;
ui.RequestErrorMessage(IDS_UNLOCK_TITLE, IDS_UNLOCK_ACCEPT_INVITE, uiIDA, 2, i,&CMinecraftApp::UnlockFullInviteReturned,this);
}
break;
case eAppAction_ExitAndJoinFromInvite:
{
UINT uiIDA[3];
SetAction(i,eAppAction_Idle);
// Check the player really wants to do this
#if defined(_XBOX_ONE) || defined(__ORBIS__)
// Show save option is saves ARE disabled
if(ProfileManager.IsFullVersion() && StorageManager.GetSaveDisabled() && i==ProfileManager.GetPrimaryPad() && g_NetworkManager.IsHost() && GetGameStarted() )
{
uiIDA[0]=IDS_CONFIRM_CANCEL;
uiIDA[1]=IDS_EXIT_GAME_SAVE;
uiIDA[2]=IDS_EXIT_GAME_NO_SAVE;
ui.RequestAlertMessage(IDS_EXIT_GAME, IDS_CONFIRM_LEAVE_VIA_INVITE, uiIDA, 3, i,&CMinecraftApp::ExitAndJoinFromInviteSaveDialogReturned,this);
}
else
#else
if(ProfileManager.IsFullVersion() && !StorageManager.GetSaveDisabled() && i==ProfileManager.GetPrimaryPad() && g_NetworkManager.IsHost() && GetGameStarted() )
{
uiIDA[0]=IDS_CONFIRM_CANCEL;
uiIDA[1]=IDS_EXIT_GAME_SAVE;
uiIDA[2]=IDS_EXIT_GAME_NO_SAVE;
ui.RequestAlertMessage(IDS_EXIT_GAME, IDS_CONFIRM_LEAVE_VIA_INVITE, uiIDA, 3, i,&CMinecraftApp::ExitAndJoinFromInviteSaveDialogReturned,this);
}
else
#endif
{
if(!ProfileManager.IsFullVersion())
{
TelemetryManager->RecordUpsellPresented(i, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID);
// upsell
uiIDA[0]=IDS_CONFIRM_OK;
uiIDA[1]=IDS_CONFIRM_CANCEL;
ui.RequestErrorMessage(IDS_UNLOCK_TITLE, IDS_UNLOCK_ACCEPT_INVITE, uiIDA, 2, i,&CMinecraftApp::UnlockFullInviteReturned,this);
}
else
{
uiIDA[0]=IDS_CONFIRM_CANCEL;
uiIDA[1]=IDS_CONFIRM_OK;
ui.RequestAlertMessage(IDS_EXIT_GAME, IDS_CONFIRM_LEAVE_VIA_INVITE, uiIDA, 2,i,&CMinecraftApp::ExitAndJoinFromInvite,this);
}
}
}
break;
case eAppAction_ExitAndJoinFromInviteConfirmed:
{
SetAction(i,eAppAction_Idle);
pMinecraft->gui->clearMessages();
// turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
ui.HideAllGameUIElements();
// Stop app running
SetGameStarted(false);
ui.CloseAllPlayersScenes();
// 4J Stu - Fix for #12368 - Crash: Game crashes when saving then exiting and selecting to save
for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
{
#ifdef _XBOX
app.TutorialSceneNavigateBack(idx,true);
#endif
// 4J Stu - Fix for #13257 - CRASH: Gameplay: Title crashed after exiting the tutorial
// It doesn't matter if they were in the tutorial already
pMinecraft->playerLeftTutorial( idx );
}
// 4J-PB - may have been using a texture pack with audio , so clean up anything texture pack related here
// unload any texture pack audio
// if there is audio in use, clear out the audio, and unmount the pack
TexturePack *pTexPack=Minecraft::GetInstance()->skins->getSelected();
DLCTexturePack *pDLCTexPack=NULL;
if(pTexPack->hasAudio())
{
// get the dlc texture pack, and store it
pDLCTexPack=(DLCTexturePack *)pTexPack;
}
// change to the default texture pack
pMinecraft->skins->selectTexturePackById(TexturePackRepository::DEFAULT_TEXTURE_PACK_ID);
if(pTexPack->hasAudio())
{
// need to stop the streaming audio - by playing streaming audio from the default texture pack now
// reset the streaming sounds back to the normal ones
#ifndef _XBOX
pMinecraft->soundEngine->SetStreamingSounds(eStream_Overworld_Calm1,eStream_Overworld_piano3,
eStream_Nether1,eStream_Nether4,
eStream_end_dragon,eStream_end_end,
eStream_CD_1);
#endif
pMinecraft->soundEngine->playStreaming(L"", 0, 0, 0, 1, 1);
#ifdef _XBOX
if(pDLCTexPack->m_pStreamedWaveBank!=NULL)
{
pDLCTexPack->m_pStreamedWaveBank->Destroy();
}
if(pDLCTexPack->m_pSoundBank!=NULL)
{
pDLCTexPack->m_pSoundBank->Destroy();
}
#endif
#ifdef _DURANGO
DWORD result = StorageManager.UnmountInstalledDLC(L"TPACK");
#else
DWORD result = StorageManager.UnmountInstalledDLC("TPACK");
#endif
app.DebugPrintf("Unmount result is %d\n",result);
}
#ifdef _XBOX_ONE
// 4J Stu - It's possible that we can sign in/remove players between the mask initially being set and this point
m_InviteData.dwLocalUsersMask = 0;
for(unsigned int index = 0; index < XUSER_MAX_COUNT; ++index)
{
if(ProfileManager.IsSignedIn(index) )
{
if(index==i || pMinecraft->localplayers[index]!=NULL )
{
m_InviteData.dwLocalUsersMask |= g_NetworkManager.GetLocalPlayerMask( index );
}
}
}
#endif
LoadingInputParams *loadingParams = new LoadingInputParams();
loadingParams->func = &CGameNetworkManager::ExitAndJoinFromInviteThreadProc;
loadingParams->lpParam = (LPVOID)&m_InviteData;
UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
completionData->bShowBackground=TRUE;
completionData->bShowLogo=TRUE;
completionData->iPad=DEFAULT_XUI_MENU_USER;
completionData->type = e_ProgressCompletion_NoAction;
loadingParams->completionData = completionData;
ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);
}
break;
case eAppAction_JoinFromInvite:
{
SetAction(i,eAppAction_Idle);
// 4J Stu - Move this state block from CPlatformNetworkManager::ExitAndJoinFromInviteThreadProc, as g_NetworkManager.JoinGameFromInviteInfo ultimately can call NavigateToScene,
/// and we should only be calling that from the main thread
app.SetTutorialMode( false );
g_NetworkManager.SetLocalGame(false);
JoinFromInviteData *inviteData = (JoinFromInviteData *)param;
// 4J-PB - clear any previous connection errors
Minecraft::GetInstance()->clearConnectionFailed();
app.DebugPrintf( "Changing Primary Pad on an invite accept - pad was %d, and is now %d\n", ProfileManager.GetPrimaryPad(), inviteData->dwUserIndex );
ProfileManager.SetLockedProfile(inviteData->dwUserIndex);
ProfileManager.SetPrimaryPad(inviteData->dwUserIndex);
#ifdef _XBOX_ONE
// 4J Stu - If a player is signed in (i.e. locked) but not in the mask, unlock them
for(unsigned int index = 0; index < XUSER_MAX_COUNT; ++index)
{
if( index != inviteData->dwUserIndex && ProfileManager.IsSignedIn(index) )
{
if( (m_InviteData.dwLocalUsersMask & g_NetworkManager.GetLocalPlayerMask( index ) ) == 0 )
{
ProfileManager.RemoveGamepadFromGame(index);
}
}
}
#endif
// change the minecraft player name
Minecraft::GetInstance()->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad()));
bool success = g_NetworkManager.JoinGameFromInviteInfo(
inviteData->dwUserIndex, // dwUserIndex
inviteData->dwLocalUsersMask, // dwUserMask
inviteData->pInviteInfo ); // pInviteInfo
if( !success )
{
app.DebugPrintf( "Failed joining game from invite\n" );
//return hr;
// 4J Stu - Copied this from XUI_FullScreenProgress to properly handle the fail case, as the thread will no longer be failing
UINT uiIDA[1];
uiIDA[0]=IDS_CONFIRM_OK;
ui.RequestErrorMessage( IDS_CONNECTION_FAILED, IDS_CONNECTION_LOST_SERVER, uiIDA,1,ProfileManager.GetPrimaryPad());
ui.NavigateToHomeMenu();
ui.UpdatePlayerBasePositions();
}
}
break;
case eAppAction_ChangeSessionType:
{
// If we are not in gameplay yet, then wait until the server is setup before changing the session type
if( g_NetworkManager.IsInGameplay() )
{
// This kicks off a thread that waits for the server to end, then closes the current session, starts a new one and joins the local players into it
SetAction(i,eAppAction_Idle);
if( !GetChangingSessionType() && !g_NetworkManager.IsLocalGame() )
{
SetGameStarted(false);
SetChangingSessionType(true);
SetReallyChangingSessionType(true);
// turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
ui.HideAllGameUIElements();
if( !ui.IsSceneInStack( ProfileManager.GetPrimaryPad(), eUIScene_EndPoem ) )
{
ui.CloseAllPlayersScenes();
}
ui.ShowOtherPlayersBaseScene(ProfileManager.GetPrimaryPad(), true);
// Remove this line to fix:
// #49084 - TU5: Code: Gameplay: The title crashes every time client navigates to 'Play game' menu and loads/creates new game after a "Connection to Xbox LIVE was lost" message has appeared.
//app.NavigateToScene(0,eUIScene_Main);
LoadingInputParams *loadingParams = new LoadingInputParams();
loadingParams->func = &CGameNetworkManager::ChangeSessionTypeThreadProc;
loadingParams->lpParam = NULL;
UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
#ifdef __PS3__
completionData->bRequiresUserAction=FALSE;
#else
completionData->bRequiresUserAction=TRUE;
#endif
completionData->bShowBackground=TRUE;
completionData->bShowLogo=TRUE;
completionData->iPad=DEFAULT_XUI_MENU_USER;
if( ui.IsSceneInStack( ProfileManager.GetPrimaryPad(), eUIScene_EndPoem ) )
{
completionData->type = e_ProgressCompletion_NavigateBackToScene;
completionData->scene = eUIScene_EndPoem;
}
else
{
completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes;
}
loadingParams->completionData = completionData;
ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);
}
}
else if( g_NetworkManager.IsLeavingGame() )
{
// If we are leaving the game, then ignore the state change
SetAction(i,eAppAction_Idle);
}
#if 0
// 4J-HG - Took this out since ChangeSessionType is only set in two places (both in EthernetDisconnected) and this case is handled there, plus this breaks
// this if statements original purpose (to allow us to wait for IsInGameplay before actioning switching to offline
// QNet must do this kind of thing automatically by itself, but on PS3 at least, we need the disconnection to definitely end up with us out of the game one way or another,
// and the other two cases above don't catch the case where we are just starting the game and get a disconnection during the loading/creation
else
{
if( g_NetworkManager.IsInSession() )
{
g_NetworkManager._LeaveGame();
}
}
#endif
}
break;
case eAppAction_SetDefaultOptions:
SetAction(i,eAppAction_Idle);
#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
SetDefaultOptions((C4JStorage::PROFILESETTINGS *)param,i);
#else
SetDefaultOptions((C_4JProfile::PROFILESETTINGS *)param,i);
#endif
// if the profile data has been changed, then force a profile write
// It seems we're allowed to break the 5 minute rule if it's the result of a user action
CheckGameSettingsChanged(true,i);
break;
case eAppAction_RemoteServerSave:
{
// If the remote server save has already finished, don't complete the action
if (GetGameStarted())
{
SetAction(ProfileManager.GetPrimaryPad(), eAppAction_Idle);
break;
}
SetAction(i,eAppAction_WaitRemoteServerSaveComplete);
for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
{
ui.CloseUIScenes(i, true);
}
// turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
ui.HideAllGameUIElements();
LoadingInputParams *loadingParams = new LoadingInputParams();
loadingParams->func = &CMinecraftApp::RemoteSaveThreadProc;
loadingParams->lpParam = NULL;
UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
completionData->bRequiresUserAction=FALSE;
completionData->bShowBackground=TRUE;
completionData->bShowLogo=TRUE;
completionData->iPad=DEFAULT_XUI_MENU_USER;
if( ui.IsSceneInStack( ProfileManager.GetPrimaryPad(), eUIScene_EndPoem ) )
{
completionData->type = e_ProgressCompletion_NavigateBackToScene;
completionData->scene = eUIScene_EndPoem;
}
else
{
completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes;
}
loadingParams->completionData = completionData;
loadingParams->cancelFunc = &CMinecraftApp::ExitGameFromRemoteSave;
loadingParams->cancelText = IDS_TOOLTIPS_EXIT;
ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);
}
break;
case eAppAction_WaitRemoteServerSaveComplete:
// Do nothing
break;
case eAppAction_FailedToJoinNoPrivileges:
{
UINT uiIDA[1];
uiIDA[0]=IDS_CONFIRM_OK;
C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad());
if(result != C4JStorage::EMessage_Busy) SetAction(i,eAppAction_Idle);
}
break;
case eAppAction_ProfileReadError:
// Return player to the main menu - code largely copied from that for handling
// eAppAction_PrimaryPlayerSignedOut, although I don't think we should have got as
// far as needing to halt the server, or running the game, before returning to the menu
if(!app.GetGameStarted()) MinecraftServer::HaltServer(true);
if( g_NetworkManager.IsInSession() )
{
app.SetAction(i,eAppAction_PrimaryPlayerSignedOutReturned);
}
else
{
app.SetAction(i,eAppAction_PrimaryPlayerSignedOutReturned_Menus);
MinecraftServer::resetFlags();
}
break;
case eAppAction_BanLevel:
{
// It's possible that this state can get set after the game has been exited (e.g. by network disconnection) so we can't ban the level at that point
if(g_NetworkManager.IsInGameplay() && !g_NetworkManager.IsLeavingGame())
{
TelemetryManager->RecordBanLevel(i);
#if defined _XBOX
INetworkPlayer *pHost=g_NetworkManager.GetHostPlayer();
// write the level to the banned level list, and exit the world
AddLevelToBannedLevelList(i,((NetworkPlayerXbox *)pHost)->GetUID(),GetUniqueMapName(),true);
#elif defined _XBOX_ONE
INetworkPlayer *pHost=g_NetworkManager.GetHostPlayer();
AddLevelToBannedLevelList(i,pHost->GetUID(),GetUniqueMapName(),true);
#endif
// primary player would exit the world, secondary would exit the player
if(ProfileManager.GetPrimaryPad()==i)
{
SetAction(i,eAppAction_ExitWorld);
}
else
{
SetAction(i,eAppAction_ExitPlayer);
}
}
}
break;
case eAppAction_LevelInBanLevelList:
{
UINT uiIDA[2];
uiIDA[0]=IDS_BUTTON_REMOVE_FROM_BAN_LIST;
uiIDA[1]=IDS_EXIT_GAME;
// pass in the gamertag format string
WCHAR wchFormat[40];
INetworkPlayer *player = g_NetworkManager.GetLocalPlayerByUserIndex(i);
// If not the primary player, but the primary player has banned this level and decided not to unban
// then we may have left the game by now
if(player)
{
swprintf(wchFormat, 40, L"%ls\n\n%%ls",player->GetOnlineName());
C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_BANNED_LEVEL_TITLE, IDS_PLAYER_BANNED_LEVEL, uiIDA,2,i,&CMinecraftApp::BannedLevelDialogReturned,this, wchFormat);
if(result != C4JStorage::EMessage_Busy) SetAction(i,eAppAction_Idle);
}
else
{
SetAction(i,eAppAction_Idle);
}
}
break;
case eAppAction_DebugText:
// launch the xui for text entry
{
#ifdef _XBOX
CScene_TextEntry::XuiTextInputParams *pDebugTextParams= new CScene_TextEntry::XuiTextInputParams;
pDebugTextParams->iPad=i;
pDebugTextParams->wch=(WCHAR)param;
app.NavigateToScene(i,eUIScene_TextEntry,pDebugTextParams);
#endif
SetAction(i,eAppAction_Idle);
}
break;
case eAppAction_ReloadTexturePack:
{
SetAction(i,eAppAction_Idle);
Minecraft *pMinecraft = Minecraft::GetInstance();
pMinecraft->textures->reloadAll();
pMinecraft->skins->updateUI();
if(!pMinecraft->skins->isUsingDefaultSkin())
{
TexturePack *pTexturePack = pMinecraft->skins->getSelected();
DLCPack *pDLCPack=pTexturePack->getDLCPack();
bool purchased = false;
// do we have a license?
if(pDLCPack && pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" ))
{
purchased = true;
}
#ifdef _XBOX
TelemetryManager->RecordTexturePackLoaded(i, pTexturePack->getId(), purchased?1:0);
#endif
}
// 4J-PB - If the texture pack has audio, we need to switch to this
if(pMinecraft->skins->getSelected()->hasAudio())
{
Minecraft::GetInstance()->soundEngine->playStreaming(L"", 0, 0, 0, 1, 1);
}
}
break;
case eAppAction_ReloadFont:
{
#ifndef _XBOX
app.DebugPrintf(
"[Consoles_App] eAppAction_ReloadFont, ingame='%s'.\n",
app.GetGameStarted() ? "Yes" : "No" );
SetAction(i,eAppAction_Idle);
ui.SetTooltips(i, -1);
ui.ReloadSkin();
ui.StartReloadSkinThread();
ui.setCleanupOnReload();
#endif
}
break;
case eAppAction_TexturePackRequired:
{
#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__
UINT uiIDA[2];
uiIDA[0]=IDS_TEXTUREPACK_FULLVERSION;
uiIDA[1]=IDS_CONFIRM_CANCEL; // let them continue without the texture pack here (as this is only really for r
// Give the player a warning about the texture pack missing
ui.RequestErrorMessage(IDS_DLC_TEXTUREPACK_NOT_PRESENT_TITLE, IDS_DLC_TEXTUREPACK_NOT_PRESENT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::TexturePackDialogReturned,this);
SetAction(i,eAppAction_Idle);
#else
#ifdef _XBOX
ULONGLONG ullOfferID_Full;
app.GetDLCFullOfferIDForPackID(app.GetRequiredTexturePackID(),&ullOfferID_Full);
TelemetryManager->RecordUpsellPresented(ProfileManager.GetPrimaryPad(), eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF);
#endif
UINT uiIDA[2];
uiIDA[0]=IDS_TEXTUREPACK_FULLVERSION;
uiIDA[1]=IDS_TEXTURE_PACK_TRIALVERSION;
// Give the player a warning about the texture pack missing
ui.RequestErrorMessage(IDS_DLC_TEXTUREPACK_NOT_PRESENT_TITLE, IDS_DLC_TEXTUREPACK_NOT_PRESENT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::TexturePackDialogReturned,this);
SetAction(i,eAppAction_Idle);
#endif
}
break;
}
}
// Any TMS actions?
eTMS = app.GetTMSAction(i);
if(eTMS!=eTMSAction_Idle)
{
switch(eTMS)
{
// TMS++ actions
case eTMSAction_TMSPP_RetrieveFiles_CreateLoad_SignInReturned:
case eTMSAction_TMSPP_RetrieveFiles_RunPlayGame:
#ifdef _XBOX
app.TMSPP_SetTitleGroupID(GROUP_ID);
SetTMSAction(i,eTMSAction_TMSPP_GlobalFileList);
#elif defined _XBOX_ONE
SetTMSAction(i,eTMSAction_TMSPP_GlobalFileList_Waiting);
app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_Title,eTMSAction_TMSPP_UserFileList);
#else
SetTMSAction(i,eTMSAction_TMSPP_UserFileList);
#endif
break;
#ifdef _XBOX
case eTMSAction_TMSPP_GlobalFileList:
SetTMSAction(i,eTMSAction_TMSPP_GlobalFileList_Waiting);
app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_Title,"\\",eTMSAction_TMSPP_UserFileList);
break;
#endif
case eTMSAction_TMSPP_UserFileList:
// retrieve the file list first
#if defined _XBOX
SetTMSAction(i,eTMSAction_TMSPP_UserFileList_Waiting);
app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_TitleUser,"\\",eTMSAction_TMSPP_XUIDSFile);
#elif defined _XBOX_ONE
SetTMSAction(i,eTMSAction_TMSPP_UserFileList_Waiting);
app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_TitleUser,eTMSAction_TMSPP_DLCFile);
#else
SetTMSAction(i,eTMSAction_TMSPP_XUIDSFile);
#endif
break;
case eTMSAction_TMSPP_XUIDSFile:
#ifdef _XBOX
SetTMSAction(i,eTMSAction_TMSPP_XUIDSFile_Waiting);
// pass in the next app action on the call or callback completing
app.TMSPP_ReadXuidsFile(i,eTMSAction_TMSPP_DLCFile);
#else
SetTMSAction(i,eTMSAction_TMSPP_DLCFile);
#endif
break;
case eTMSAction_TMSPP_DLCFile:
#if defined _XBOX || defined _XBOX_ONE
SetTMSAction(i,eTMSAction_TMSPP_DLCFile_Waiting);
// pass in the next app action on the call or callback completing
app.TMSPP_ReadDLCFile(i,eTMSAction_TMSPP_BannedListFile);
#else
SetTMSAction(i,eTMSAction_TMSPP_BannedListFile);
#endif
break;
case eTMSAction_TMSPP_BannedListFile:
// If we have one in TMSPP, then we can assume we can ignore TMS
#if defined _XBOX
SetTMSAction(i,eTMSAction_TMSPP_BannedListFile_Waiting);
// pass in the next app action on the call or callback completing
if(app.TMSPP_ReadBannedList(i,eTMSAction_TMS_RetrieveFiles_Complete)==false)
{
// we don't have a banned list in TMSPP, so we should check TMS
app.ReadBannedList(i, eTMSAction_TMS_RetrieveFiles_Complete,true);
}
#elif defined _XBOX_ONE
SetTMSAction(i,eTMSAction_TMSPP_BannedListFile_Waiting);
// pass in the next app action on the call or callback completing
app.TMSPP_ReadBannedList(i,eTMSAction_TMS_RetrieveFiles_Complete);
#else
SetTMSAction(i,eTMSAction_TMS_RetrieveFiles_Complete);
#endif
break;
// SPECIAL CASE - where the user goes directly in to Help & Options from the main menu
case eTMSAction_TMSPP_RetrieveFiles_HelpAndOptions:
case eTMSAction_TMSPP_RetrieveFiles_DLCMain:
// retrieve the file list first
#if defined _XBOX
// pass in the next app action on the call or callback completing
SetTMSAction(i,eTMSAction_TMSPP_XUIDSFile_Waiting);
app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_Title,"\\",eTMSAction_TMSPP_DLCFileOnly);
#elif defined _XBOX_ONE
SetTMSAction(i,eTMSAction_TMSPP_GlobalFileList_Waiting);
app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_Title,eTMSAction_TMSPP_RetrieveUserFilelist_DLCFileOnly);
#else
SetTMSAction(i,eTMSAction_TMSPP_DLCFileOnly);
#endif
break;
case eTMSAction_TMSPP_RetrieveUserFilelist_DLCFileOnly:
#if defined _XBOX
SetTMSAction(i,eTMSAction_TMSPP_UserFileList_Waiting);
app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_TitleUser,"\\",eTMSAction_TMSPP_XUIDSFile);
#elif defined _XBOX_ONE
//StorageManager.TMSPP_DeleteFile(i,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,L"TP06.png",NULL,NULL, 0);
SetTMSAction(i,eTMSAction_TMSPP_UserFileList_Waiting);
app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_TitleUser,eTMSAction_TMSPP_DLCFileOnly);
#else
SetTMSAction(i,eTMSAction_TMSPP_DLCFileOnly);
#endif
break;
case eTMSAction_TMSPP_DLCFileOnly:
#if defined _XBOX || defined _XBOX_ONE
SetTMSAction(i,eTMSAction_TMSPP_DLCFile_Waiting);
// pass in the next app action on the call or callback completing
app.TMSPP_ReadDLCFile(i,eTMSAction_TMSPP_RetrieveFiles_Complete);
#else
SetTMSAction(i,eTMSAction_TMSPP_RetrieveFiles_Complete);
#endif
break;
case eTMSAction_TMSPP_RetrieveFiles_Complete:
SetTMSAction(i,eTMSAction_Idle);
break;
// TMS files
/* case eTMSAction_TMS_RetrieveFiles_CreateLoad_SignInReturned:
case eTMSAction_TMS_RetrieveFiles_RunPlayGame:
#ifdef _XBOX
SetTMSAction(i,eTMSAction_TMS_XUIDSFile_Waiting);
// pass in the next app action on the call or callback completing
app.ReadXuidsFileFromTMS(i,eTMSAction_TMS_DLCFile,true);
#else
SetTMSAction(i,eTMSAction_TMS_DLCFile);
#endif
break;
case eTMSAction_TMS_DLCFile:
#ifdef _XBOX
SetTMSAction(i,eTMSAction_TMS_DLCFile_Waiting);
// pass in the next app action on the call or callback completing
app.ReadDLCFileFromTMS(i,eTMSAction_TMS_BannedListFile,true);
#else
SetTMSAction(i,eTMSAction_TMS_BannedListFile);
#endif
break;
case eTMSAction_TMS_RetrieveFiles_HelpAndOptions:
case eTMSAction_TMS_RetrieveFiles_DLCMain:
#ifdef _XBOX
SetTMSAction(i,eTMSAction_TMS_DLCFile_Waiting);
// pass in the next app action on the call or callback completing
app.ReadDLCFileFromTMS(i,eTMSAction_Idle,true);
#else
SetTMSAction(i,eTMSAction_Idle);
#endif
break;
case eTMSAction_TMS_BannedListFile:
#ifdef _XBOX
SetTMSAction(i,eTMSAction_TMS_BannedListFile_Waiting);
// pass in the next app action on the call or callback completing
app.ReadBannedList(i, eTMSAction_TMS_RetrieveFiles_Complete,true);
#else
SetTMSAction(i,eTMSAction_TMS_RetrieveFiles_Complete);
#endif
break;
*/
case eTMSAction_TMS_RetrieveFiles_Complete:
SetTMSAction(i,eTMSAction_Idle);
// if(StorageManager.SetSaveDevice(&CScene_Main::DeviceSelectReturned,pClass))
// {
// // save device already selected
// // ensure we've applied this player's settings
// app.ApplyGameSettingsChanged(ProfileManager.GetPrimaryPad());
// app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_MultiGameJoinLoad);
// }
break;
}
}
}
}
int CMinecraftApp::BannedLevelDialogReturned(void *pParam,int iPad,const C4JStorage::EMessageResult result)
{
CMinecraftApp* pApp = (CMinecraftApp*)pParam;
//Minecraft *pMinecraft=Minecraft::GetInstance();
if(result==C4JStorage::EMessage_ResultAccept)
{
#if defined _XBOX || defined _XBOX_ONE
INetworkPlayer *pHost = g_NetworkManager.GetHostPlayer();
// unban the level
if (pHost != NULL)
{
#if defined _XBOX
pApp->RemoveLevelFromBannedLevelList(iPad,((NetworkPlayerXbox *)pHost)->GetUID(),pApp->GetUniqueMapName());
#else
pApp->RemoveLevelFromBannedLevelList(iPad,pHost->GetUID(),pApp->GetUniqueMapName());
#endif
}
#endif
}
else
{
if( iPad == ProfileManager.GetPrimaryPad() )
{
pApp->SetAction(iPad,eAppAction_ExitWorld);
}
else
{
pApp->SetAction(iPad,eAppAction_ExitPlayer);
}
}
return 0;
}
void CMinecraftApp::loadMediaArchive()
{
wstring mediapath = L"";
#ifdef __PS3__
mediapath = L"Common\\Media\\MediaPS3.arc";
#elif _WINDOWS64
mediapath = L"Common\\Media\\MediaWindows64.arc";
#elif __ORBIS__
mediapath = L"Common\\Media\\MediaOrbis.arc";
#elif _DURANGO
mediapath = L"Common\\Media\\MediaDurango.arc";
#elif __PSVITA__
mediapath = L"Common\\Media\\MediaPSVita.arc";
#endif
if (!mediapath.empty())
{
m_mediaArchive = new ArchiveFile( File(mediapath) );
}
#if 0
string path = "Common\\media.arc";
HANDLE hFile = CreateFile( path.c_str(),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL );
if( hFile != INVALID_HANDLE_VALUE )
{
File fileHelper(convStringToWstring(path));
DWORD dwFileSize = fileHelper.length();
// Initialize memory.
PBYTE m_fBody = new BYTE[ dwFileSize ];
ZeroMemory(m_fBody, dwFileSize);
DWORD m_fSize = 0;
BOOL hr = ReadFile( hFile,
m_fBody,
dwFileSize,
&m_fSize,
NULL );
assert( m_fSize == dwFileSize );
CloseHandle( hFile );
m_mediaArchive = new ArchiveFile(m_fBody, m_fSize);
}
else
{
assert( false );
// AHHHHHHHHHHHH
m_mediaArchive = NULL;
}
#endif
}
void CMinecraftApp::loadStringTable()
{
#ifndef _XBOX
if(m_stringTable!=NULL)
{
// we need to unload the current string table, this is a reload
delete m_stringTable;
}
wstring localisationFile = L"languages.loc";
if (m_mediaArchive->hasFile(localisationFile))
{
byteArray locFile = m_mediaArchive->getFile(localisationFile);
m_stringTable = new StringTable(locFile.data, locFile.length);
delete locFile.data;
}
else
{
m_stringTable = NULL;
assert(false);
// AHHHHHHHHH.
}
#endif
}
int CMinecraftApp::PrimaryPlayerSignedOutReturned(void *pParam,int iPad,const C4JStorage::EMessageResult)
{
//CMinecraftApp* pApp = (CMinecraftApp*)pParam;
//Minecraft *pMinecraft=Minecraft::GetInstance();
// if the player is null, we're in the menus
//if(Minecraft::GetInstance()->player!=NULL)
// We always create a session before kicking of any of the game code, so even though we may still be joining/creating a game
// at this point we want to handle it differently from just being in a menu
if( g_NetworkManager.IsInSession() )
{
app.SetAction(iPad,eAppAction_PrimaryPlayerSignedOutReturned);
}
else
{
app.SetAction(iPad,eAppAction_PrimaryPlayerSignedOutReturned_Menus);
}
return 0;
}
int CMinecraftApp::EthernetDisconnectReturned(void *pParam,int iPad,const C4JStorage::EMessageResult)
{
//CMinecraftApp* pApp = (CMinecraftApp*)pParam;
Minecraft *pMinecraft=Minecraft::GetInstance();
// if the player is null, we're in the menus
if(Minecraft::GetInstance()->player!=NULL)
{
app.SetAction(pMinecraft->player->GetXboxPad(),eAppAction_EthernetDisconnectedReturned);
}
else
{
// 4J-PB - turn off the PSN store icon just in case this happened when we were in one of the DLC menus
#if defined __ORBIS__ || defined __PSVITA__
app.GetCommerce()->HidePsStoreIcon();
#endif
app.SetAction(iPad,eAppAction_EthernetDisconnectedReturned_Menus);
}
return 0;
}
int CMinecraftApp::SignoutExitWorldThreadProc( void* lpParameter )
{
// Share AABB & Vec3 pools with default (main thread) - should be ok as long as we don't tick the main thread whilst this thread is running
AABB::UseDefaultThreadStorage();
Vec3::UseDefaultThreadStorage();
Compression::UseDefaultThreadStorage();
//app.SetGameStarted(false);
Minecraft *pMinecraft=Minecraft::GetInstance();
int exitReasonStringId = -1;
bool saveStats = false;
if (pMinecraft->isClientSide() || g_NetworkManager.IsInSession() )
{
if(lpParameter != NULL )
{
switch( app.GetDisconnectReason() )
{
case DisconnectPacket::eDisconnect_Kicked:
exitReasonStringId = IDS_DISCONNECTED_KICKED;
break;
case DisconnectPacket::eDisconnect_NoUGC_AllLocal:
exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL;
break;
case DisconnectPacket::eDisconnect_NoUGC_Single_Local:
exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL;
break;
#ifdef _XBOX
case DisconnectPacket::eDisconnect_NoUGC_Remote:
exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_REMOTE;
break;
#endif
case DisconnectPacket::eDisconnect_NoFlying:
exitReasonStringId = IDS_DISCONNECTED_FLYING;
break;
case DisconnectPacket::eDisconnect_OutdatedServer:
exitReasonStringId = IDS_DISCONNECTED_SERVER_OLD;
break;
case DisconnectPacket::eDisconnect_OutdatedClient:
exitReasonStringId = IDS_DISCONNECTED_CLIENT_OLD;
break;
default:
exitReasonStringId = IDS_DISCONNECTED;
}
pMinecraft->progressRenderer->progressStartNoAbort( exitReasonStringId );
// 4J - Force a disconnection, this handles the situation that the server has already disconnected
if( pMinecraft->levels[0] != NULL ) pMinecraft->levels[0]->disconnect(false);
if( pMinecraft->levels[1] != NULL ) pMinecraft->levels[1]->disconnect(false);
}
else
{
exitReasonStringId = IDS_EXITING_GAME;
pMinecraft->progressRenderer->progressStartNoAbort( IDS_EXITING_GAME );
if( pMinecraft->levels[0] != NULL ) pMinecraft->levels[0]->disconnect();
if( pMinecraft->levels[1] != NULL ) pMinecraft->levels[1]->disconnect();
}
// 4J Stu - This only does something if we actually have a server, so don't need to do any other checks
MinecraftServer::HaltServer(true);
// We need to call the stats & leaderboards save before we exit the session
//pMinecraft->forceStatsSave();
saveStats = false;
// 4J Stu - Leave the session once the disconnect packet has been sent
g_NetworkManager.LeaveGame(FALSE);
}
else
{
if(lpParameter != NULL )
{
switch( app.GetDisconnectReason() )
{
case DisconnectPacket::eDisconnect_Kicked:
exitReasonStringId = IDS_DISCONNECTED_KICKED;
break;
case DisconnectPacket::eDisconnect_NoUGC_AllLocal:
exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL;
break;
case DisconnectPacket::eDisconnect_NoUGC_Single_Local:
exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL;
break;
#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__)
case DisconnectPacket::eDisconnect_ContentRestricted_AllLocal:
exitReasonStringId = IDS_CONTENT_RESTRICTION_MULTIPLAYER;
break;
case DisconnectPacket::eDisconnect_ContentRestricted_Single_Local:
exitReasonStringId = IDS_CONTENT_RESTRICTION;
break;
#endif
#ifdef _XBOX
case DisconnectPacket::eDisconnect_NoUGC_Remote:
exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_REMOTE;
break;
#endif
case DisconnectPacket::eDisconnect_OutdatedServer:
exitReasonStringId = IDS_DISCONNECTED_SERVER_OLD;
break;
case DisconnectPacket::eDisconnect_OutdatedClient:
exitReasonStringId = IDS_DISCONNECTED_CLIENT_OLD;
default:
exitReasonStringId = IDS_DISCONNECTED;
}
pMinecraft->progressRenderer->progressStartNoAbort( exitReasonStringId );
}
}
pMinecraft->setLevel(NULL,exitReasonStringId,nullptr,saveStats,true);
// 4J-JEV: Fix for #106402 - TCR #014 BAS Debug Output:
// TU12: Mass Effect Mash-UP: Save file "Default_DisplayName" is created on all storage devices after signing out from a re-launched pre-generated world
app.m_gameRules.unloadCurrentGameRules(); //
MinecraftServer::resetFlags();
// We can't start/join a new game until the session is destroyed, so wait for it to be idle again
while( g_NetworkManager.IsInSession() )
{
Sleep(1);
}
return S_OK;
}
int CMinecraftApp::UnlockFullInviteReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
{
//CMinecraftApp* pApp = (CMinecraftApp*)pParam;
Minecraft *pMinecraft=Minecraft::GetInstance();
bool bNoPlayer;
// bug 11285 - TCR 001: BAS Game Stability: CRASH - When trying to join a full version game with a trial version, the trial crashes
// 4J-PB - we may be in the main menus here, and we don't have a pMinecraft->player
if(pMinecraft->player==NULL)
{
bNoPlayer=true;
}
if(result==C4JStorage::EMessage_ResultAccept)
{
if(ProfileManager.IsSignedInLive(iPad))
{
// 4J-PB - need to check this user can access the store
#if defined(__PS3__) || defined(__PSVITA__)
bool bContentRestricted;
ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,NULL,&bContentRestricted,NULL);
if(bContentRestricted)
{
UINT uiIDA[1];
uiIDA[0]=IDS_CONFIRM_OK;
ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad());
}
else
#endif
{
ProfileManager.DisplayFullVersionPurchase(false,iPad,eSen_UpsellID_Full_Version_Of_Game);
}
}
#if defined(__PS3__)
else
{
// you're not signed in to PSN!
UINT uiIDA[2];
uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT;
uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE;
ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app);
}
#endif
}
else
{
TelemetryManager->RecordUpsellResponded(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, eSen_UpsellOutcome_Declined);
}
return 0;
}
int CMinecraftApp::UnlockFullSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
{
//CMinecraftApp* pApp = (CMinecraftApp*)pParam;
Minecraft *pMinecraft=Minecraft::GetInstance();
if(result==C4JStorage::EMessage_ResultAccept)
{
if(ProfileManager.IsSignedInLive(pMinecraft->player->GetXboxPad()))
{
// 4J-PB - need to check this user can access the store
#if defined(__PS3__) || defined(__PSVITA__)
bool bContentRestricted;
ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,NULL,&bContentRestricted,NULL);
if(bContentRestricted)
{
UINT uiIDA[1];
uiIDA[0]=IDS_CONFIRM_OK;
ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad());
}
else
#endif
{
ProfileManager.DisplayFullVersionPurchase(false,pMinecraft->player->GetXboxPad(),eSen_UpsellID_Full_Version_Of_Game);
}
}
#if defined(__PS3__)
else
{
// you're not signed in to PSN!
UINT uiIDA[2];
uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT;
uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE;
ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app);
}
#elif defined(__ORBIS__)
else
{
// Determine why they're not "signed in live"
if (ProfileManager.isSignedInPSN(iPad))
{
// Signed in to PSN but not connected (no internet access)
assert(!ProfileManager.isConnectedToPSN(iPad));
UINT uiIDA[1];
uiIDA[0] = IDS_OK;
ui.RequestErrorMessage( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad);
}
else
{
// Not signed in to PSN
UINT uiIDA[1];
uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT;
ui.RequestAlertMessage( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, iPad, &CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app);
}
}
#endif
}
else
{
TelemetryManager->RecordUpsellResponded(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, eSen_UpsellOutcome_Declined);
}
return 0;
}
int CMinecraftApp::UnlockFullExitReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
{
CMinecraftApp* pApp = (CMinecraftApp*)pParam;
Minecraft *pMinecraft=Minecraft::GetInstance();
if(result==C4JStorage::EMessage_ResultAccept)
{
if(ProfileManager.IsSignedInLive(pMinecraft->player->GetXboxPad()))
{
// 4J-PB - need to check this user can access the store
#if defined(__PS3__) || defined(__PSVITA__)
bool bContentRestricted;
ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,NULL,&bContentRestricted,NULL);
if(bContentRestricted)
{
UINT uiIDA[1];
uiIDA[0]=IDS_CONFIRM_OK;
ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad());
}
else
#endif
{
ProfileManager.DisplayFullVersionPurchase(false,pMinecraft->player->GetXboxPad(),eSen_UpsellID_Full_Version_Of_Game);
#if defined __ORBIS__ || defined __PS3__ || defined __PSVITA__
// still need to exit the trial or we'll be in the Pause menu with input ignored
pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial);
#endif
}
}
#if defined(__PS3__) || defined __PSVITA__
else
{
// you're not signed in to PSN!
UINT uiIDA[2];
uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT;
uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE;
ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturnedExitTrial,&app);
}
#elif defined(__ORBIS__)
else
{
// Determine why they're not "signed in live"
if (ProfileManager.isSignedInPSN(iPad))
{
// Signed in to PSN but not connected (no internet access)
assert(!ProfileManager.isConnectedToPSN(iPad));
UINT uiIDA[1];
uiIDA[0] = IDS_OK;
ui.RequestErrorMessage( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad);
// still need to exit the trial or we'll be in the Pause menu with input ignored
pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial);
}
else
{
// Not signed in to PSN
UINT uiIDA[1];
uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT;
ui.RequestAlertMessage( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, iPad, &CMinecraftApp::MustSignInFullVersionPurchaseReturnedExitTrial,&app);
}
}
#endif
}
else
{
TelemetryManager->RecordUpsellResponded(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, eSen_UpsellOutcome_Declined);
pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial);
}
return 0;
}
int CMinecraftApp::TrialOverReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
{
CMinecraftApp* pApp = (CMinecraftApp*)pParam;
Minecraft *pMinecraft=Minecraft::GetInstance();
if(result==C4JStorage::EMessage_ResultAccept)
{
// we need a signed in user for the unlock
if(ProfileManager.IsSignedInLive(pMinecraft->player->GetXboxPad()))
{
// 4J-PB - need to check this user can access the store
#if defined(__PS3__) || defined(__PSVITA__)
bool bContentRestricted;
ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,NULL,&bContentRestricted,NULL);
if(bContentRestricted)
{
UINT uiIDA[1];
uiIDA[0]=IDS_CONFIRM_OK;
ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad());
}
else
#endif
{
ProfileManager.DisplayFullVersionPurchase(false,pMinecraft->player->GetXboxPad(),eSen_UpsellID_Full_Version_Of_Game);
}
}
else
{
#if defined(__PS3__)
// you're not signed in to PSN!
UINT uiIDA[2];
uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT;
uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE;
ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app);
// 4J Stu - We can't actually exit the game, so just exit back to the main menu
//pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial);
#else
pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitTrial);
#endif
}
}
else
{
TelemetryManager->RecordUpsellResponded(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, eSen_UpsellOutcome_Declined);
#if defined(__PS3__) || defined(__ORBIS__)
// 4J Stu - We can't actually exit the game, so just exit back to the main menu
pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial);
#else
pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitTrial);
#endif
}
return 0;
}
void CMinecraftApp::ProfileReadErrorCallback(void *pParam)
{
CMinecraftApp *pApp=(CMinecraftApp *)pParam;
int iPrimaryPlayer=ProfileManager.GetPrimaryPad();
pApp->SetAction(iPrimaryPlayer, eAppAction_ProfileReadError);
}
void CMinecraftApp::ClearSignInChangeUsersMask()
{
// 4J-PB - When in the main menu, the user is on pad 0, and any change they make to their profile will be to pad 0 data
// If they then go in as a secondary player to a splitscreen game, their profile will not be read again on pad 1 if they were previously in a splitscreen game
// This is because m_uiLastSignInData remembers they were in previously, and doesn't read the profile data for them again
// Fix this by resetting the m_uiLastSignInData on pressing play game for secondary users. The Primary user does a read profile on play game anyway
int iPrimaryPlayer=ProfileManager.GetPrimaryPad();
if(m_uiLastSignInData!=0)
{
if(iPrimaryPlayer>=0)
{
m_uiLastSignInData=1<<iPrimaryPlayer;
}
else
{
m_uiLastSignInData=0;
}
}
}
void CMinecraftApp::SignInChangeCallback(LPVOID pParam,bool bPrimaryPlayerChanged,unsigned int uiSignInData)
{
#ifdef __PS3__
// this is normally set in the main menu, but we can go online in the create world screens, and the primary player name isn't updated
Minecraft::GetInstance()->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad()));
#endif
CMinecraftApp *pApp=(CMinecraftApp *)pParam;
// check if the primary player signed out
int iPrimaryPlayer=ProfileManager.GetPrimaryPad();
if((ProfileManager.GetLockedProfile()!=-1) && iPrimaryPlayer!=-1)
{
if ( ((uiSignInData & (1<<iPrimaryPlayer)) == 0) || bPrimaryPlayerChanged )
{
// Primary Player gone or there's been a sign out and sign in of the primary player, so kick them out
pApp->SetAction(iPrimaryPlayer,eAppAction_PrimaryPlayerSignedOut);
// 4J-PB - invalidate their banned level list
pApp->InvalidateBannedList(iPrimaryPlayer);
// need to ditch any DLCOffers info
StorageManager.ClearDLCOffers();
pApp->ClearAndResetDLCDownloadQueue();
pApp->ClearDLCInstalled();
}
else
{
unsigned int uiChangedPlayers = uiSignInData ^ m_uiLastSignInData;
if( g_NetworkManager.IsInSession() )
{
bool hasGuestIdChanged = false;
for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
{
DWORD guestNumber = 0;
if(ProfileManager.IsSignedIn(i))
{
XUSER_SIGNIN_INFO info;
XUserGetSigninInfo(i,XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY ,&info);
pApp->DebugPrintf("Player at index %d has guest number %d\n", i,info.dwGuestNumber );
guestNumber = info.dwGuestNumber;
}
if( pApp->m_currentSigninInfo[i].dwGuestNumber != 0 && guestNumber != 0 && pApp->m_currentSigninInfo[i].dwGuestNumber != guestNumber )
{
hasGuestIdChanged = true;
}
}
if( hasGuestIdChanged )
{
UINT uiIDA[1];
uiIDA[0]=IDS_CONFIRM_OK;
ui.RequestErrorMessage(IDS_GUEST_ORDER_CHANGED_TITLE, IDS_GUEST_ORDER_CHANGED_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad());
}
// 4J Stu - On PS4 we can also cause to exit players if they are signed out here, but we shouldn't do that if
// we are going to switch to an offline game as it will likely crash due to incompatible parallel processes
bool switchToOffline = false;
// If it's an online game, and the primary profile is no longer signed into LIVE then we act as if disconnected
if( !ProfileManager.IsSignedInLive( ProfileManager.GetLockedProfile() ) && !g_NetworkManager.IsLocalGame() )
{
switchToOffline = true;
}
//printf("Old: %x, New: %x, Changed: %x\n", m_ulLastSignInData, ulSignInData, changedPlayers);
for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
{
// Primary player shouldn't be subjected to these checks, and shouldn't call ExitPlayer
if(i == iPrimaryPlayer) continue;
// A guest a signed in or out, out of order which invalidates all the guest players we have in the game
if(hasGuestIdChanged && pApp->m_currentSigninInfo[i].dwGuestNumber != 0 && g_NetworkManager.GetLocalPlayerByUserIndex(i)!=NULL)
{
pApp->DebugPrintf("Recommending removal of player at index %d because their guest id changed\n",i);
pApp->SetAction(i, eAppAction_ExitPlayer);
}
else
{
XUSER_SIGNIN_INFO info;
XUserGetSigninInfo(i,XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY ,&info);
// 4J Stu - Also need to detect the case where the sign in mask is the same, but the player has swapped users (eg still signed in but xuid different)
// Fix for #48451 - TU5: Code: UI: Splitscreen: Title crashes when switching to a profile previously signed out via splitscreen profile selection
// 4J-PB - compiler complained about if below ('&&' within '||') - making it easier to read
bool bPlayerChanged=(uiChangedPlayers&(1<<i))==(1<<i);
bool bPlayerSignedIn=((uiSignInData&(1<<i))!=0);
if( bPlayerChanged && (!bPlayerSignedIn || (bPlayerSignedIn && !ProfileManager.AreXUIDSEqual(pApp->m_currentSigninInfo[i].xuid, info.xuid) ) ))
{
// 4J-PB - invalidate their banned level list
pApp->DebugPrintf("Player at index %d Left - invalidating their banned list\n",i);
pApp->InvalidateBannedList(i);
// 4J-HG: If either the player is in the network manager or in the game, need to exit player
// TODO: Do we need to check the network manager?
if (g_NetworkManager.GetLocalPlayerByUserIndex(i) != NULL || Minecraft::GetInstance()->localplayers[i] != NULL)
{
pApp->DebugPrintf("Player %d signed out\n", i);
pApp->SetAction(i, eAppAction_ExitPlayer);
}
}
}
#ifdef __ORBIS__
// check if any of the addition players have signed out of PSN (primary player is handled below)
if(!switchToOffline && i != ProfileManager.GetLockedProfile() && !g_NetworkManager.IsLocalGame())
{
if(g_NetworkManager.GetLocalPlayerByUserIndex(i)!=NULL)
{
if(ProfileManager.IsSignedInLive(i) == false)
{
pApp->DebugPrintf("Recommending removal of player at index %d because they're no longer signed into PSNd\n",i);
pApp->SetAction(i,eAppAction_ExitPlayer);
}
}
}
#endif
}
// If it's an online game, and the primary profile is no longer signed into LIVE then we act as if disconnected
if( switchToOffline )
{
pApp->SetAction(iPrimaryPlayer,eAppAction_EthernetDisconnected);
}
g_NetworkManager.HandleSignInChange();
}
// Some menus require the player to be signed in to live, so if this callback happens and the primary player is
// no longer signed in then nav back
else if ( pApp->GetLiveLinkRequired() && !ProfileManager.IsSignedInLive( ProfileManager.GetLockedProfile() ) )
{
#ifdef __PSVITA__
if(!CGameNetworkManager::usingAdhocMode()) // if we're in adhoc mode, we can ignore this
#endif
{
pApp->SetAction(iPrimaryPlayer,eAppAction_EthernetDisconnected);
}
}
#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__ )
// 4J-JEV: Need to kick of loading of profile data for sub-sign in players.
for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
{
if( i != iPrimaryPlayer
&& ( uiChangedPlayers & (1<<i) )
&& ( uiSignInData & (1<<i) )
)
{
StorageManager.ReadFromProfile(i);
}
}
#endif
}
m_uiLastSignInData = uiSignInData;
}
else if(iPrimaryPlayer!=-1)
{
// make sure the TMS banned list data is ditched - the player may have gone in to help & options, backed out, and signed out
pApp->InvalidateBannedList(iPrimaryPlayer);
// need to ditch any DLCOffers info
StorageManager.ClearDLCOffers();
pApp->ClearAndResetDLCDownloadQueue();
pApp->ClearDLCInstalled();
}
// Update the guest numbers to the current state
for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
{
if(FAILED(XUserGetSigninInfo(i,XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY,&pApp->m_currentSigninInfo[i])))
{
pApp->m_currentSigninInfo[i].xuid = INVALID_XUID;
pApp->m_currentSigninInfo[i].dwGuestNumber = 0;
}
app.DebugPrintf("Player at index %d has guest number %d\n", i,pApp->m_currentSigninInfo[i].dwGuestNumber );
}
}
void CMinecraftApp::NotificationsCallback(LPVOID pParam,DWORD dwNotification, unsigned int uiParam)
{
CMinecraftApp* pClass = (CMinecraftApp*)pParam;
// push these on to the notifications to be handled in qnet's dowork
PNOTIFICATION pNotification = new NOTIFICATION;
pNotification->dwNotification=dwNotification;
pNotification->uiParam=uiParam;
switch( dwNotification )
{
case XN_SYS_SIGNINCHANGED:
{
pClass->DebugPrintf("Signing changed - %d\n", uiParam );
}
break;
case XN_SYS_INPUTDEVICESCHANGED:
if(app.GetGameStarted() && g_NetworkManager.IsInSession())
{
for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
{
if(!InputManager.IsPadConnected(i) &&
Minecraft::GetInstance()->localplayers[i] != NULL &&
!ui.IsPauseMenuDisplayed(i) && !ui.IsSceneInStack(i, eUIScene_EndPoem) )
{
ui.CloseUIScenes(i);
ui.NavigateToScene(i,eUIScene_PauseMenu);
}
}
}
break;
case XN_LIVE_CONTENT_INSTALLED:
// Need to inform xuis that we've possibly had DLC installed
{
//app.m_dlcManager.SetNeedsUpdated(true);
// Clear the DLC installed flag to cause a GetDLC to run if it's called
app.ClearDLCInstalled();
ui.HandleDLCInstalled(ProfileManager.GetPrimaryPad());
}
break;
case XN_SYS_STORAGEDEVICESCHANGED:
{
#ifdef _XBOX
// If the devices have changed, and we've got a dlc pack with audio selected, and that pack's content device is no longer valid... then pull the plug on
// audio streaming, as if we leave this until later xact gets locked up attempting to destroy the streamed wave bank.
TexturePack *pTexPack=Minecraft::GetInstance()->skins->getSelected();
if(pTexPack->hasAudio())
{
DLCTexturePack *pDLCTexPack=(DLCTexturePack *)pTexPack;
XCONTENTDEVICEID deviceID = pDLCTexPack->GetDLCDeviceID();
if( XContentGetDeviceState( deviceID, NULL ) != ERROR_SUCCESS )
{
// Set texture pack flag so that it is now considered as not having audio - this is critical so that the next playStreaming does what it is meant to do,
// and also so that we don't try and unmount this again, or play any sounds from it in the future
pTexPack->setHasAudio(false);
// need to stop the streaming audio - by playing streaming audio from the default texture pack now
Minecraft::GetInstance()->soundEngine->playStreaming(L"", 0, 0, 0, 0, 0);
if(pDLCTexPack->m_pStreamedWaveBank!=NULL)
{
pDLCTexPack->m_pStreamedWaveBank->Destroy();
}
if(pDLCTexPack->m_pSoundBank!=NULL)
{
pDLCTexPack->m_pSoundBank->Destroy();
}
DWORD result = StorageManager.UnmountInstalledDLC("TPACK");
app.DebugPrintf("Unmount result is %d\n",result);
}
}
#endif
}
break;
}
pClass->m_vNotifications.push_back(pNotification);
}
#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__
int CMinecraftApp::MustSignInFullVersionPurchaseReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
{
if(result==C4JStorage::EMessage_ResultAccept)
{
#ifdef __PS3__
SQRNetworkManager_PS3::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true);
#elif defined __PSVITA__
SQRNetworkManager_Vita::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true);
#else // __PS4__
SQRNetworkManager_Orbis::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true);
#endif
}
return 0;
}
#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__
int CMinecraftApp::MustSignInFullVersionPurchaseReturnedExitTrial(void *pParam,int iPad,C4JStorage::EMessageResult result)
{
if(result==C4JStorage::EMessage_ResultAccept)
{
#ifdef __PS3__
SQRNetworkManager_PS3::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true);
#elif defined __PSVITA__
SQRNetworkManager_Vita::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true);
#else // __PS4__
SQRNetworkManager_Orbis::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true);
#endif
}
//4J-PB - we need to exit the trial, or we'll be in the pause menu with ignore input true
app.SetAction(iPad,eAppAction_ExitWorldTrial);
return 0;
}
#endif
int CMinecraftApp::NowDisplayFullVersionPurchase(void *pParam, bool bContinue, int iPad)
{
app.m_bDisplayFullVersionPurchase=true;
return 0;
}
#endif
void CMinecraftApp::UpsellReturnedCallback(LPVOID pParam, eUpsellType type, eUpsellResponse result, int iUserData)
{
ESen_UpsellID senType;
ESen_UpsellOutcome senResponse;
#ifdef __PS3__
UINT uiIDA[2];
#endif
// Map the eUpsellResponse to the enum we use for sentient
switch(result)
{
case eUpsellResponse_Accepted_NoPurchase:
senResponse = eSen_UpsellOutcome_Went_To_Guide;
break;
case eUpsellResponse_Accepted_Purchase:
senResponse = eSen_UpsellOutcome_Accepted;
break;
#ifdef __PS3__
// special case for people who are not signed in to the PSN while playing the trial game
case eUpsellResponse_UserNotSignedInPSN:
uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT;
uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE;
ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app);
return;
case eUpsellResponse_NotAllowedOnline: // On earning a trophy in the trial version, where the user is underage and can't go online to buy the game, but they selected to buy the game on the trophy upsell
uiIDA[0]=IDS_CONFIRM_OK;
ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad());
break;
#endif
case eUpsellResponse_Declined:
default:
senResponse = eSen_UpsellOutcome_Declined;
break;
};
// Map the eUpsellType to the enum we use for sentient
switch(type)
{
case eUpsellType_Custom:
senType = eSen_UpsellID_Full_Version_Of_Game;
break;
default:
senType = eSen_UpsellID_Undefined;
break;
};
// Always the primary pad that gets an upsell
TelemetryManager->RecordUpsellResponded(ProfileManager.GetPrimaryPad(), eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, senResponse);
}
#ifdef _DEBUG_MENUS_ENABLED
bool CMinecraftApp::DebugArtToolsOn()
{
return DebugSettingsOn() && (GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_ArtTools)) != 0;
}
#endif
void CMinecraftApp::SetDebugSequence(const char *pchSeq)
{
InputManager.SetDebugSequence(pchSeq,&CMinecraftApp::DebugInputCallback,this);
}
int CMinecraftApp::DebugInputCallback(LPVOID pParam)
{
CMinecraftApp* pClass = (CMinecraftApp*)pParam;
//printf("sequence matched\n");
pClass->m_bDebugOptions=!pClass->m_bDebugOptions;
for(int i=0;i<XUSER_MAX_COUNT;i++)
{
if(app.DebugSettingsOn())
{
app.ActionDebugMask(i);
}
else
{
// force debug mask off
app.ActionDebugMask(i,true);
}
}
return 0;
}
int CMinecraftApp::GetLocalPlayerCount(void)
{
int iPlayerC=0;
Minecraft *pMinecraft = Minecraft::GetInstance();
for(int i=0;i<XUSER_MAX_COUNT;i++)
{
if(pMinecraft != NULL && pMinecraft->localplayers[i] != NULL)
{
iPlayerC++;
}
}
return iPlayerC;
}
int CMinecraftApp::MarketplaceCountsCallback(LPVOID pParam,C4JStorage::DLC_TMS_DETAILS *pTMSDetails, int iPad)
{
app.DebugPrintf("Marketplace Counts= New - %d Total - %d\n",pTMSDetails->dwNewOffers,pTMSDetails->dwTotalOffers);
if(pTMSDetails->dwNewOffers>0)
{
app.m_bNewDLCAvailable=true;
app.m_bSeenNewDLCTip=false;
}
else
{
app.m_bNewDLCAvailable=false;
app.m_bSeenNewDLCTip=true;
}
return 0;
}
bool CMinecraftApp::StartInstallDLCProcess(int iPad)
{
app.DebugPrintf("--- CMinecraftApp::StartInstallDLCProcess: pad=%i.\n", iPad);
// If there is already a call to this in progress, then do nothing
// If the app says dlc is installed, then there has been no new system message to tell us there's new DLC since the last call to StartInstallDLCProcess
if((app.DLCInstallProcessCompleted()==false) && (m_bDLCInstallPending==false))
{
app.m_dlcManager.resetUnnamedCorruptCount();
m_bDLCInstallPending = true;
m_iTotalDLC = 0;
m_iTotalDLCInstalled = 0;
app.DebugPrintf("--- CMinecraftApp::StartInstallDLCProcess - StorageManager.GetInstalledDLC\n");
StorageManager.GetInstalledDLC(iPad,&CMinecraftApp::DLCInstalledCallback,this);
return true;
}
else
{
app.DebugPrintf("--- CMinecraftApp::StartInstallDLCProcess - nothing to do\n");
return false;
}
}
// Installed DLC callback
int CMinecraftApp::DLCInstalledCallback(LPVOID pParam,int iInstalledC,int iPad)
{
app.DebugPrintf("--- CMinecraftApp::DLCInstalledCallback: totalDLC=%i, pad=%i.\n", iInstalledC, iPad);
app.m_iTotalDLC = iInstalledC;
app.MountNextDLC(iPad);
return 0;
}
void CMinecraftApp::MountNextDLC(int iPad)
{
app.DebugPrintf("--- CMinecraftApp::MountNextDLC: pad=%i.\n", iPad);
if(m_iTotalDLCInstalled < m_iTotalDLC)
{
// Mount it
// We also need to match the ones the user wants to mount with the installed DLC
// We're supposed to use a generic save game as a cache of these to do this, with XUSER_ANY
if(StorageManager.MountInstalledDLC(iPad,m_iTotalDLCInstalled,&CMinecraftApp::DLCMountedCallback,this)!=ERROR_IO_PENDING )
{
// corrupt DLC
app.DebugPrintf("Failed to mount DLC %d for pad %d\n",m_iTotalDLCInstalled,iPad);
++m_iTotalDLCInstalled;
app.MountNextDLC(iPad);
}
else
{
app.DebugPrintf("StorageManager.MountInstalledDLC ok\n");
}
}
else
{
/* Removed - now loading these on demand instead of as each pack is mounted
if(m_iTotalDLCInstalled > 0)
{
Minecraft *pMinecraft=Minecraft::GetInstance();
pMinecraft->levelRenderer->AddDLCSkinsToMemTextures();
}
*/
m_bDLCInstallPending = false;
m_bDLCInstallProcessCompleted=true;
ui.HandleDLCMountingComplete();
#if defined(_XBOX_ONE) || defined(__ORBIS__)
// Check if the current texture pack is now installed
if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin())
{
TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected();
DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack;
DLCPack *pParentPack=pDLCTexPack->getDLCInfoParentPack();//tPack->getDLCPack();
if(pParentPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" ))
{
StorageManager.SetSaveDisabled(false);
}
}
#endif
#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__
{
TexturePack* currentTPack = Minecraft::GetInstance()->skins->getSelected();
TexturePack* requiredTPack = Minecraft::GetInstance()->skins->getTexturePackById(app.GetRequiredTexturePackID());
if(currentTPack != requiredTPack)
{
Minecraft::GetInstance()->skins->selectTexturePackById(app.GetRequiredTexturePackID());
}
}
#endif
}
}
// 4J-JEV: For the sake of clarity in DLCMountedCallback.
#if defined(_XBOX) || defined(__PS3__) || defined(_WINDOWS64)
#define CONTENT_DATA_DISPLAY_NAME(a) (a.szDisplayName)
#else
#define CONTENT_DATA_DISPLAY_NAME(a) (a.wszDisplayName)
#endif
int CMinecraftApp::DLCMountedCallback(LPVOID pParam,int iPad,DWORD dwErr,DWORD dwLicenceMask)
{
#if defined(_XBOX) || defined(_DURANGO) || defined(__PS3__) || defined(__ORBIS__) || defined(_WINDOWS64) || defined (__PSVITA__) //Chris TODO
app.DebugPrintf("--- CMinecraftApp::DLCMountedCallback\n");
if(dwErr!=ERROR_SUCCESS)
{
// corrupt DLC
app.DebugPrintf("Failed to mount DLC for pad %d: %d\n",iPad,dwErr);
app.m_dlcManager.incrementUnnamedCorruptCount();
}
else
{
XCONTENT_DATA ContentData = StorageManager.GetDLC(app.m_iTotalDLCInstalled);
DLCPack *pack = app.m_dlcManager.getPack( CONTENT_DATA_DISPLAY_NAME(ContentData) );
if( pack != NULL && pack->IsCorrupt() )
{
app.DebugPrintf("Pack '%ls' is corrupt, removing it from the DLC Manager.\n", CONTENT_DATA_DISPLAY_NAME(ContentData));
app.m_dlcManager.removePack(pack);
pack = NULL;
}
if(pack == NULL)
{
app.DebugPrintf("Pack \"%ls\" is not installed, so adding it\n", CONTENT_DATA_DISPLAY_NAME(ContentData));
#if defined(_XBOX) || defined(__PS3__) || defined(_WINDOWS64)
pack = new DLCPack(ContentData.szDisplayName,dwLicenceMask);
#elif defined _XBOX_ONE
pack = new DLCPack(ContentData.wszDisplayName,ContentData.wszProductID,dwLicenceMask);
#else
pack = new DLCPack(ContentData.wszDisplayName,dwLicenceMask);
#endif
pack->SetDLCMountIndex(app.m_iTotalDLCInstalled);
pack->SetDLCDeviceID(ContentData.DeviceID);
app.m_dlcManager.addPack(pack);
app.HandleDLC(pack);
if(pack->getDLCItemsCount(DLCManager::e_DLCType_Texture) > 0)
{
Minecraft::GetInstance()->skins->addTexturePackFromDLC(pack, pack->GetPackId() );
}
}
else
{
app.DebugPrintf("Pack \"%ls\" is already installed. Updating license to %d\n", CONTENT_DATA_DISPLAY_NAME(ContentData), dwLicenceMask);
pack->SetDLCMountIndex(app.m_iTotalDLCInstalled);
pack->SetDLCDeviceID(ContentData.DeviceID);
pack->updateLicenseMask(dwLicenceMask);
}
StorageManager.UnmountInstalledDLC();
}
++app.m_iTotalDLCInstalled;
app.MountNextDLC(iPad);
#endif // __PSVITA__
return 0;
}
#undef CONTENT_DATA_DISPLAY_NAME
// void CMinecraftApp::InstallDefaultCape()
// {
// if(!m_bDefaultCapeInstallAttempted)
// {
// // we only attempt to install the cape once per launch of the game
// m_bDefaultCapeInstallAttempted=true;
//
// wstring wTemp=L"Default_Cape.png";
// bool bRes=app.IsFileInMemoryTextures(wTemp);
// // if the file is not already in the memory textures, then read it from TMS
// if(!bRes)
// {
// BYTE *pBuffer=NULL;
// DWORD dwSize=0;
// // 4J-PB - out for now for DaveK so he doesn't get the birthday cape
// #ifdef _CONTENT_PACKAGE
// C4JStorage::ETMSStatus eTMSStatus;
// eTMSStatus=StorageManager.ReadTMSFile(ProfileManager.GetPrimaryPad(),C4JStorage::eGlobalStorage_Title,C4JStorage::eTMS_FileType_Graphic, L"Default_Cape.png",&pBuffer, &dwSize);
// if(eTMSStatus==C4JStorage::ETMSStatus_Idle)
// {
// app.AddMemoryTextureFile(wTemp,pBuffer,dwSize);
// }
// #endif
// }
// }
// }
void CMinecraftApp::HandleDLC(DLCPack *pack)
{
DWORD dwFilesProcessed = 0;
#ifndef _XBOX
#if defined(__PS3__) || defined(__ORBIS__) || defined(_WINDOWS64) || defined (__PSVITA__)
std::vector<std::string> dlcFilenames;
#elif defined _DURANGO
std::vector<std::wstring> dlcFilenames;
#endif
StorageManager.GetMountedDLCFileList("DLCDrive", dlcFilenames);
#ifdef __ORBIS__
// 4J Stu - I don't know why we handle more than one file here any more, however this doesn't seem to work with the PS4 patches
if(dlcFilenames.size() > 0) m_dlcManager.readDLCDataFile(dwFilesProcessed, dlcFilenames[0], pack);
#else
for(int i=0; i<dlcFilenames.size();i++)
{
m_dlcManager.readDLCDataFile(dwFilesProcessed, dlcFilenames[i], pack);
}
#endif
#else
WIN32_FIND_DATA wfd;
HANDLE hFind;
char szPath[] = "DLCDrive:\\";
char szFullFilename[256];
strcpy(szFullFilename,szPath);
strcat(szFullFilename,"*");
// Start the find and check for failure.
hFind = FindFirstFile( szFullFilename, &wfd );
if( INVALID_HANDLE_VALUE == hFind )
{
app.DebugPrintf( "FindFirstFile failed." );
}
else
{
// Display each file and ask for the next.
do
{
strcpy(szFullFilename,szPath);
strcat(szFullFilename,wfd.cFileName);
if(( GetFileAttributes( szFullFilename ) & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY)
{
#ifdef _XBOX
DWORD dwPackID=m_dlcManager.retrievePackIDFromDLCDataFile(szFullFilename,pack);
// Do we need to override the TexturePack.pck with an updated version in a TU?
wstring wsTemp=getFilePath(dwPackID, wstring(L"TexturePack.pck"),false );
File texturePCKPath(wsTemp );
if(texturePCKPath.exists())
{
app.DebugPrintf("Found a replacement .pck\n");
m_dlcManager.readDLCDataFile(dwFilesProcessed, wsTemp,pack);
}
else
{
m_dlcManager.readDLCDataFile(dwFilesProcessed, szFullFilename,pack);
}
#else
m_dlcManager.readDLCDataFile(dwFilesProcessed, szFullFilename,pack);
#endif
}
}
while( FindNextFile( hFind, &wfd ) );
// Close the find handle.
FindClose( hFind );
}
#endif // __PS3__ || __ORBIS__
if( dwFilesProcessed == 0 ) m_dlcManager.removePack(pack);
}
// int CMinecraftApp::DLCReadCallback(LPVOID pParam,C4JStorage::DLC_FILE_DETAILS *pDLCData)
// {
//
//
// return 0;
// }
//-------------------------------------------------------------------------------------
// Name: InitTime()
// Desc: Initializes the timer variables
//-------------------------------------------------------------------------------------
void CMinecraftApp::InitTime()
{
// Get the frequency of the timer
LARGE_INTEGER qwTicksPerSec;
QueryPerformanceFrequency( &qwTicksPerSec );
m_Time.fSecsPerTick = 1.0f / (float)qwTicksPerSec.QuadPart;
// Save the start time
QueryPerformanceCounter( &m_Time.qwTime );
// Zero out the elapsed and total time
m_Time.qwAppTime.QuadPart = 0;
m_Time.fAppTime = 0.0f;
m_Time.fElapsedTime = 0.0f;
}
//-------------------------------------------------------------------------------------
// Name: UpdateTime()
// Desc: Updates the elapsed time since our last frame.
//-------------------------------------------------------------------------------------
void CMinecraftApp::UpdateTime()
{
LARGE_INTEGER qwNewTime;
LARGE_INTEGER qwDeltaTime;
QueryPerformanceCounter( &qwNewTime );
qwDeltaTime.QuadPart = qwNewTime.QuadPart - m_Time.qwTime.QuadPart;
m_Time.qwAppTime.QuadPart += qwDeltaTime.QuadPart;
m_Time.qwTime.QuadPart = qwNewTime.QuadPart;
m_Time.fElapsedTime = m_Time.fSecsPerTick * ((FLOAT)(qwDeltaTime.QuadPart));
m_Time.fAppTime = m_Time.fSecsPerTick * ((FLOAT)(m_Time.qwAppTime.QuadPart));
}
bool CMinecraftApp::isXuidNotch(PlayerUID xuid)
{
if(m_xuidNotch != INVALID_XUID && xuid != INVALID_XUID)
{
return ProfileManager.AreXUIDSEqual(xuid, m_xuidNotch) == TRUE;
}
return false;
}
bool CMinecraftApp::isXuidDeadmau5(PlayerUID xuid)
{
auto it = MojangData.find(xuid); // 4J Stu - The .at and [] accessors insert elements if they don't exist
if (it != MojangData.end() )
{
MOJANG_DATA *pMojangData=MojangData[xuid];
if(pMojangData && pMojangData->eXuid==eXUID_Deadmau5)
{
return true;
}
}
return false;
}
void CMinecraftApp::AddMemoryTextureFile(const wstring &wName,PBYTE pbData,DWORD dwBytes)
{
EnterCriticalSection(&csMemFilesLock);
// check it's not already in
PMEMDATA pData=NULL;
auto it = m_MEM_Files.find(wName);
if(it != m_MEM_Files.end())
{
#ifndef _CONTENT_PACKAGE
wprintf(L"Incrementing the memory texture file count for %ls\n", wName.c_str());
#endif
pData = (*it).second;
if(pData->dwBytes == 0 && dwBytes != 0)
{
// This should never be NULL if dwBytes is 0
if(pData->pbData!=NULL) delete [] pData->pbData;
pData->pbData=pbData;
pData->dwBytes=dwBytes;
}
++pData->ucRefCount;
LeaveCriticalSection(&csMemFilesLock);
return;
}
#ifndef _CONTENT_PACKAGE
//wprintf(L"Adding the memory texture file data for %ls\n", wName.c_str());
#endif
// this is a texture (png) file
// add this texture to the list of memory texture files - it will then be picked up by the level renderer's AddEntity
pData = (PMEMDATA)new BYTE[sizeof(MEMDATA)];
ZeroMemory( pData, sizeof(MEMDATA) );
pData->pbData=pbData;
pData->dwBytes=dwBytes;
pData->ucRefCount = 1;
// use the xuid to access the skin data
m_MEM_Files[wName]=pData;
LeaveCriticalSection(&csMemFilesLock);
}
void CMinecraftApp::RemoveMemoryTextureFile(const wstring &wName)
{
EnterCriticalSection(&csMemFilesLock);
auto it = m_MEM_Files.find(wName);
if(it != m_MEM_Files.end())
{
#ifndef _CONTENT_PACKAGE
wprintf(L"Decrementing the memory texture file count for %ls\n", wName.c_str());
#endif
PMEMDATA pData = (*it).second;
--pData->ucRefCount;
if(pData->ucRefCount <= 0)
{
#ifndef _CONTENT_PACKAGE
wprintf(L"Erasing the memory texture file data for %ls\n", wName.c_str());
#endif
delete [] pData;
m_MEM_Files.erase(wName);
}
}
LeaveCriticalSection(&csMemFilesLock);
}
bool CMinecraftApp::DefaultCapeExists()
{
wstring wTex=L"Special_Cape.png";
bool val = false;
EnterCriticalSection(&csMemFilesLock);
auto it = m_MEM_Files.find(wTex);
if(it != m_MEM_Files.end()) val = true;
LeaveCriticalSection(&csMemFilesLock);
return val;
}
bool CMinecraftApp::IsFileInMemoryTextures(const wstring &wName)
{
bool val = false;
EnterCriticalSection(&csMemFilesLock);
auto it = m_MEM_Files.find(wName);
if(it != m_MEM_Files.end()) val = true;
LeaveCriticalSection(&csMemFilesLock);
return val;
}
void CMinecraftApp::GetMemFileDetails(const wstring &wName,PBYTE *ppbData,DWORD *pdwBytes)
{
EnterCriticalSection(&csMemFilesLock);
auto it = m_MEM_Files.find(wName);
if(it != m_MEM_Files.end())
{
PMEMDATA pData = (*it).second;
*ppbData=pData->pbData;
*pdwBytes=pData->dwBytes;
}
LeaveCriticalSection(&csMemFilesLock);
}
void CMinecraftApp::AddMemoryTPDFile(int iConfig,PBYTE pbData,DWORD dwBytes)
{
EnterCriticalSection(&csMemTPDLock);
// check it's not already in
PMEMDATA pData=NULL;
auto it = m_MEM_TPD.find(iConfig);
if(it == m_MEM_TPD.end())
{
pData = (PMEMDATA)new BYTE[sizeof(MEMDATA)];
ZeroMemory( pData, sizeof(MEMDATA) );
pData->pbData=pbData;
pData->dwBytes=dwBytes;
pData->ucRefCount = 1;
m_MEM_TPD[iConfig]=pData;
}
LeaveCriticalSection(&csMemTPDLock);
}
void CMinecraftApp::RemoveMemoryTPDFile(int iConfig)
{
EnterCriticalSection(&csMemTPDLock);
// check it's not already in
PMEMDATA pData=NULL;
auto it = m_MEM_TPD.find(iConfig);
if(it != m_MEM_TPD.end())
{
pData=m_MEM_TPD[iConfig];
delete [] pData;
m_MEM_TPD.erase(iConfig);
}
LeaveCriticalSection(&csMemTPDLock);
}
#ifdef _XBOX
int CMinecraftApp::GetTPConfigVal(WCHAR *pwchDataFile)
{
DLC_INFO *pDLCInfo=NULL;
// run through the DLC info to find the right texture pack/mash-up pack
for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i)
{
ULONGLONG ull=app.GetDLCInfoTexturesFullOffer(i);
pDLCInfo=app.GetDLCInfoForFullOfferID(ull);
if(wcscmp(pwchDataFile,pDLCInfo->wchDataFile)==0)
{
return pDLCInfo->iConfig;
}
}
return -1;
}
#elif defined _XBOX_ONE
int CMinecraftApp::GetTPConfigVal(WCHAR *pwchDataFile)
{
DLC_INFO *pDLCInfo=NULL;
// run through the DLC info to find the right texture pack/mash-up pack
for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i)
{
pDLCInfo=app.GetDLCInfoForFullOfferID((WCHAR *)app.GetDLCInfoTexturesFullOffer(i).c_str());
if(wcscmp(pwchDataFile,pDLCInfo->wchDataFile)==0)
{
return pDLCInfo->iConfig;
}
}
return -1;
}
#elif defined _WINDOWS64
int CMinecraftApp::GetTPConfigVal(WCHAR *pwchDataFile)
{
return -1;
}
#endif
bool CMinecraftApp::IsFileInTPD(int iConfig)
{
bool val = false;
EnterCriticalSection(&csMemTPDLock);
auto it = m_MEM_TPD.find(iConfig);
if(it != m_MEM_TPD.end()) val = true;
LeaveCriticalSection(&csMemTPDLock);
return val;
}
void CMinecraftApp::GetTPD(int iConfig,PBYTE *ppbData,DWORD *pdwBytes)
{
EnterCriticalSection(&csMemTPDLock);
auto it = m_MEM_TPD.find(iConfig);
if(it != m_MEM_TPD.end())
{
PMEMDATA pData = (*it).second;
*ppbData=pData->pbData;
*pdwBytes=pData->dwBytes;
}
LeaveCriticalSection(&csMemTPDLock);
}
// bool CMinecraftApp::UploadFileToGlobalStorage(int iQuadrant, C4JStorage::eGlobalStorage eStorageFacility, wstring *wsFile )
// {
// bool bRes=false;
// #ifndef _CONTENT_PACKAGE
// // read the local file
// File gtsFile( wsFile->c_str() );
//
// int64_t fileSize = gtsFile.length();
//
// if(fileSize!=0)
// {
// FileInputStream fis(gtsFile);
// byteArray ba((int)fileSize);
// fis.read(ba);
// fis.close();
//
// bRes=StorageManager.WriteTMSFile(iQuadrant,eStorageFacility,(WCHAR *)wsFile->c_str(),ba.data, ba.length);
//
// }
// #endif
// return bRes;
// }
void CMinecraftApp::StoreLaunchData()
{
}
void CMinecraftApp::ExitGame()
{
}
// Invites
void CMinecraftApp::ProcessInvite(DWORD dwUserIndex, DWORD dwLocalUsersMask, const INVITE_INFO * pInviteInfo)
{
m_InviteData.dwUserIndex=dwUserIndex;
m_InviteData.dwLocalUsersMask=dwLocalUsersMask;
m_InviteData.pInviteInfo=pInviteInfo;
//memcpy(&m_InviteData,pJoinData,sizeof(JoinFromInviteData));
SetAction(dwUserIndex,eAppAction_ExitAndJoinFromInvite);
}
int CMinecraftApp::ExitAndJoinFromInvite(void *pParam,int iPad,C4JStorage::EMessageResult result)
{
CMinecraftApp* pApp = (CMinecraftApp*)pParam;
//Minecraft *pMinecraft=Minecraft::GetInstance();
// buttons are swapped on this menu
if(result==C4JStorage::EMessage_ResultDecline)
{
pApp->SetAction(iPad,eAppAction_ExitAndJoinFromInviteConfirmed);
}
return 0;
}
int CMinecraftApp::ExitAndJoinFromInviteSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
{
CMinecraftApp *pClass = (CMinecraftApp *)pParam;
// Exit with or without saving
// Decline means save in this dialog
if(result==C4JStorage::EMessage_ResultDecline || result==C4JStorage::EMessage_ResultThirdOption)
{
if( result==C4JStorage::EMessage_ResultDecline ) // Save
{
// Check they have the full texture pack if they are using one
// 4J-PB - Is the player trying to save but they are using a trial texturepack ?
if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin())
{
TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected();
DLCPack * pDLCPack=tPack->getDLCPack();
if(!pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" ))
{
// upsell
// get the dlc texture pack
#ifdef _XBOX
DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack;
ULONGLONG ullOfferID_Full;
app.GetDLCFullOfferIDForPackID(pDLCTexPack->getDLCParentPackId(),&ullOfferID_Full);
// tell sentient about the upsell of the full version of the skin pack
TelemetryManager->RecordUpsellPresented(iPad, eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF);
#endif
UINT uiIDA[2];
uiIDA[0]=IDS_CONFIRM_OK;
uiIDA[1]=IDS_CONFIRM_CANCEL;
// Give the player a warning about the trial version of the texture pack
ui.RequestErrorMessage(IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, IDS_WARNING_DLC_TRIALTEXTUREPACK_TEXT, uiIDA, 2, iPad,&CMinecraftApp::WarningTrialTexturePackReturned,pClass);
return S_OK;
}
}
#ifndef _XBOX_ONE
// does the save exist?
bool bSaveExists;
StorageManager.DoesSaveExist(&bSaveExists);
// 4J-PB - we check if the save exists inside the libs
// we need to ask if they are sure they want to overwrite the existing game
if(bSaveExists)
{
UINT uiIDA[2];
uiIDA[0]=IDS_CONFIRM_CANCEL;
uiIDA[1]=IDS_CONFIRM_OK;
ui.RequestErrorMessage(IDS_TITLE_SAVE_GAME, IDS_CONFIRM_SAVE_GAME, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::ExitAndJoinFromInviteAndSaveReturned,pClass);
return 0;
}
else
#endif
{
#if defined(_XBOX_ONE) || defined(__ORBIS__)
StorageManager.SetSaveDisabled(false);
#endif
MinecraftServer::getInstance()->setSaveOnExit( true );
}
}
else
{
// been a few requests for a confirm on exit without saving
UINT uiIDA[2];
uiIDA[0]=IDS_CONFIRM_CANCEL;
uiIDA[1]=IDS_CONFIRM_OK;
ui.RequestErrorMessage(IDS_TITLE_DECLINE_SAVE_GAME, IDS_CONFIRM_DECLINE_SAVE_GAME, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::ExitAndJoinFromInviteDeclineSaveReturned,pClass);
return 0;
}
app.SetAction(ProfileManager.GetPrimaryPad(),eAppAction_ExitAndJoinFromInviteConfirmed);
}
return 0;
}
int CMinecraftApp::WarningTrialTexturePackReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
{
// 4J Stu - I added this in when fixing an X1 bug. We should probably add this as well but I don't have time to test all platforms atm
#if 0 //defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__)
if(result==C4JStorage::EMessage_ResultAccept)
{
if(!ProfileManager.IsSignedInLive(iPad))
{
// you're not signed in to PSN!
}
else
{
// 4J-PB - need to check this user can access the store
bool bContentRestricted;
ProfileManager.GetChatAndContentRestrictions(iPad,true,NULL,&bContentRestricted,NULL);
if(bContentRestricted)
{
UINT uiIDA[1];
uiIDA[0]=IDS_CONFIRM_OK;
ui.RequestAlertMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPad);
}
else
{
// need to get info on the pack to see if the user has already downloaded it
TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected();
DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack;
// retrieve the store name for the skin pack
DLCPack *pDLCPack=pDLCTexPack->getDLCInfoParentPack();//tPack->getDLCPack();
const char *pchPackName=wstringtofilename(pDLCPack->getName());
app.DebugPrintf("Texture Pack - %s\n",pchPackName);
SONYDLC *pSONYDLCInfo=app.GetSONYDLCInfo((char *)pchPackName);
if(pSONYDLCInfo!=NULL)
{
char chName[42];
char chSkuID[SCE_NP_COMMERCE2_SKU_ID_LEN];
memset(chSkuID,0,SCE_NP_COMMERCE2_SKU_ID_LEN);
// find the info on the skin pack
// 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
#ifdef __ORBIS__
sprintf(chName,"%s",pSONYDLCInfo->chDLCKeyname);
#else
sprintf(chName,"%s-%s",app.GetCommerceCategory(),pSONYDLCInfo->chDLCKeyname);
#endif
app.GetDLCSkuIDFromProductList(chName,chSkuID);
// 4J-PB - need to check for an empty store
#if defined __ORBIS__ || defined __PSVITA__ || defined __PS3__
if(app.CheckForEmptyStore(iPad)==false)
#endif
{
if(app.DLCAlreadyPurchased(chSkuID))
{
app.DownloadAlreadyPurchased(chSkuID);
}
else
{
app.Checkout(chSkuID);
}
}
}
}
}
}
#endif //
#ifdef _XBOX_ONE
if(result==C4JStorage::EMessage_ResultAccept)
{
if(ProfileManager.IsSignedIn(iPad))
{
if (ProfileManager.IsSignedInLive(iPad))
{
TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected();
// get the dlc texture pack
DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack;
DLCPack *pDLCPack=pDLCTexPack->getDLCInfoParentPack();
DLC_INFO *pDLCInfo=app.GetDLCInfoForProductName((WCHAR *)pDLCPack->getName().c_str());
StorageManager.InstallOffer(1,(WCHAR *)pDLCInfo->wsProductId.c_str(),NULL,NULL);
// the license change coming in when the offer has been installed will cause this scene to refresh
}
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.
UINT uiIDA[1] = { IDS_CONFIRM_OK };
ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1, iPad);
}
}
}
#endif
#ifdef _XBOX
CMinecraftApp* pClass = (CMinecraftApp*)pParam;
TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected();
// get the dlc texture pack
DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack;
ULONGLONG ullIndexA[1];
// Need to get the parent packs id, since this may be one of many child packs with their own ids
app.GetDLCFullOfferIDForPackID(pDLCTexPack->getDLCParentPackId(),&ullIndexA[0]);
if(result==C4JStorage::EMessage_ResultAccept)
{
if(ProfileManager.IsSignedIn(iPad))
{
// need to allow downloads here, or the player would need to quit the game to let the download of a texture pack happen. This might affect the network traffic, since the download could take all the bandwidth...
XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW);
StorageManager.InstallOffer(1,ullIndexA,NULL,NULL);
}
}
else
{
TelemetryManager->RecordUpsellResponded(iPad, eSet_UpsellID_Texture_DLC, ( ullIndexA[0] & 0xFFFFFFFF ), eSen_UpsellOutcome_Declined);
}
#endif
return 0;
}
int CMinecraftApp::ExitAndJoinFromInviteAndSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
{
//CMinecraftApp* pClass = (CMinecraftApp*)pParam;
// results switched for this dialog
if(result==C4JStorage::EMessage_ResultDecline)
{
INT saveOrCheckpointId = 0;
// Check they have the full texture pack if they are using one
// 4J-PB - Is the player trying to save but they are using a trial texturepack ?
if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin())
{
TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected();
DLCPack * pDLCPack=tPack->getDLCPack();
if(!pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" ))
{
// upsell
// get the dlc texture pack
#ifdef _XBOX
DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack;
ULONGLONG ullOfferID_Full;
app.GetDLCFullOfferIDForPackID(pDLCTexPack->getDLCParentPackId(),&ullOfferID_Full);
// tell sentient about the upsell of the full version of the skin pack
TelemetryManager->RecordUpsellPresented(iPad, eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF);
#endif
UINT uiIDA[2];
uiIDA[0]=IDS_CONFIRM_OK;
uiIDA[1]=IDS_CONFIRM_CANCEL;
// Give the player a warning about the trial version of the texture pack
ui.RequestErrorMessage(IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, IDS_WARNING_DLC_TRIALTEXTUREPACK_TEXT, uiIDA, 2, iPad,&CMinecraftApp::WarningTrialTexturePackReturned,NULL);
return S_OK;
}
}
//bool validSave = StorageManager.GetSaveUniqueNumber(&saveOrCheckpointId);
//SentientManager.RecordLevelSaveOrCheckpoint(ProfileManager.GetPrimaryPad(), saveOrCheckpointId);
MinecraftServer::getInstance()->setSaveOnExit( true );
// flag a app action of exit and join game from invite
app.SetAction(iPad,eAppAction_ExitAndJoinFromInviteConfirmed);
}
return 0;
}
int CMinecraftApp::ExitAndJoinFromInviteDeclineSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
{
// results switched for this dialog
if(result==C4JStorage::EMessage_ResultDecline)
{
#if defined(_XBOX_ONE) || defined(__ORBIS__)
StorageManager.SetSaveDisabled(false);
#endif
MinecraftServer::getInstance()->setSaveOnExit( false );
// flag a app action of exit and join game from invite
app.SetAction(iPad,eAppAction_ExitAndJoinFromInviteConfirmed);
}
return 0;
}
//////////////////////////////////////////////////////////////////////////
//
// FatalLoadError
//
// This is called when we can't load one of the required files at startup
// It tends to mean the files have been corrupted.
// We have to assume that we've not been able to load the text for the game.
//
//////////////////////////////////////////////////////////////////////////
void CMinecraftApp::FatalLoadError()
{
}
TIPSTRUCT CMinecraftApp::m_GameTipA[MAX_TIPS_GAMETIP]=
{
{ 0, IDS_TIPS_GAMETIP_1},
{ 0, IDS_TIPS_GAMETIP_2},
{ 0, IDS_TIPS_GAMETIP_3},
{ 0, IDS_TIPS_GAMETIP_4},
{ 0, IDS_TIPS_GAMETIP_5},
{ 0, IDS_TIPS_GAMETIP_6},
{ 0, IDS_TIPS_GAMETIP_7},
{ 0, IDS_TIPS_GAMETIP_8},
{ 0, IDS_TIPS_GAMETIP_9},
{ 0, IDS_TIPS_GAMETIP_10},
{ 0, IDS_TIPS_GAMETIP_11},
{ 0, IDS_TIPS_GAMETIP_12},
{ 0, IDS_TIPS_GAMETIP_13},
{ 0, IDS_TIPS_GAMETIP_14},
{ 0, IDS_TIPS_GAMETIP_15},
{ 0, IDS_TIPS_GAMETIP_16},
{ 0, IDS_TIPS_GAMETIP_17},
{ 0, IDS_TIPS_GAMETIP_18},
{ 0, IDS_TIPS_GAMETIP_19},
{ 0, IDS_TIPS_GAMETIP_20},
{ 0, IDS_TIPS_GAMETIP_21},
{ 0, IDS_TIPS_GAMETIP_22},
{ 0, IDS_TIPS_GAMETIP_23},
{ 0, IDS_TIPS_GAMETIP_24},
{ 0, IDS_TIPS_GAMETIP_25},
{ 0, IDS_TIPS_GAMETIP_26},
{ 0, IDS_TIPS_GAMETIP_27},
{ 0, IDS_TIPS_GAMETIP_28},
{ 0, IDS_TIPS_GAMETIP_29},
{ 0, IDS_TIPS_GAMETIP_30},
{ 0, IDS_TIPS_GAMETIP_31},
{ 0, IDS_TIPS_GAMETIP_32},
{ 0, IDS_TIPS_GAMETIP_33},
{ 0, IDS_TIPS_GAMETIP_34},
{ 0, IDS_TIPS_GAMETIP_35},
{ 0, IDS_TIPS_GAMETIP_36},
{ 0, IDS_TIPS_GAMETIP_37},
{ 0, IDS_TIPS_GAMETIP_38},
{ 0, IDS_TIPS_GAMETIP_39},
{ 0, IDS_TIPS_GAMETIP_40},
{ 0, IDS_TIPS_GAMETIP_41},
{ 0, IDS_TIPS_GAMETIP_42},
{ 0, IDS_TIPS_GAMETIP_43},
{ 0, IDS_TIPS_GAMETIP_44},
{ 0, IDS_TIPS_GAMETIP_45},
{ 0, IDS_TIPS_GAMETIP_46},
{ 0, IDS_TIPS_GAMETIP_47},
{ 0, IDS_TIPS_GAMETIP_48},
{ 0, IDS_TIPS_GAMETIP_49},
{ 0, IDS_TIPS_GAMETIP_50},
};
TIPSTRUCT CMinecraftApp::m_TriviaTipA[MAX_TIPS_TRIVIATIP]=
{
{ 0, IDS_TIPS_TRIVIA_1},
{ 0, IDS_TIPS_TRIVIA_2},
{ 0, IDS_TIPS_TRIVIA_3},
{ 0, IDS_TIPS_TRIVIA_4},
{ 0, IDS_TIPS_TRIVIA_5},
{ 0, IDS_TIPS_TRIVIA_6},
{ 0, IDS_TIPS_TRIVIA_7},
{ 0, IDS_TIPS_TRIVIA_8},
{ 0, IDS_TIPS_TRIVIA_9},
{ 0, IDS_TIPS_TRIVIA_10},
{ 0, IDS_TIPS_TRIVIA_11},
{ 0, IDS_TIPS_TRIVIA_12},
{ 0, IDS_TIPS_TRIVIA_13},
{ 0, IDS_TIPS_TRIVIA_14},
{ 0, IDS_TIPS_TRIVIA_15},
{ 0, IDS_TIPS_TRIVIA_16},
{ 0, IDS_TIPS_TRIVIA_17},
{ 0, IDS_TIPS_TRIVIA_18},
{ 0, IDS_TIPS_TRIVIA_19},
{ 0, IDS_TIPS_TRIVIA_20},
};
Random *CMinecraftApp::TipRandom = new Random();
int CMinecraftApp::TipsSortFunction(const void* a, const void* b)
{
return ((TIPSTRUCT*)a)->iSortValue - ((TIPSTRUCT*)b)->iSortValue;
}
void CMinecraftApp::InitialiseTips()
{
// We'll randomise the tips at start up based on their priority
ZeroMemory(m_TipIDA,sizeof(UINT)*MAX_TIPS_GAMETIP+MAX_TIPS_TRIVIATIP);
// Make the first tip tell you that you can play splitscreen in HD modes if you are in SD
if(!RenderManager.IsHiDef())
{
m_GameTipA[0].uiStringID=IDS_TIPS_GAMETIP_0;
}
// randomise then quicksort
// going to leave the multiplayer tip so it is always first
// Only randomise the content package build
#ifdef _CONTENT_PACKAGE
for(int i=1;i<MAX_TIPS_GAMETIP;i++)
{
m_GameTipA[i].iSortValue=TipRandom->nextInt();
}
qsort( &m_GameTipA[1], MAX_TIPS_GAMETIP-1, sizeof(TIPSTRUCT), TipsSortFunction );
#endif
for(int i=0;i<MAX_TIPS_TRIVIATIP;i++)
{
m_TriviaTipA[i].iSortValue=TipRandom->nextInt();
}
qsort( m_TriviaTipA, MAX_TIPS_TRIVIATIP, sizeof(TIPSTRUCT), TipsSortFunction );
int iCurrentGameTip=0;
int iCurrentTriviaTip=0;
for(int i=0;i<MAX_TIPS_GAMETIP+MAX_TIPS_TRIVIATIP;i++)
{
// Add a trivia one every third tip (if there are any left)
if((i%3==2) && (iCurrentTriviaTip<MAX_TIPS_TRIVIATIP))
{
// Add a trivia one
m_TipIDA[i]=m_TriviaTipA[iCurrentTriviaTip++].uiStringID;
}
else
{
if(iCurrentGameTip<MAX_TIPS_GAMETIP)
{
// Add a gametip
m_TipIDA[i]=m_GameTipA[iCurrentGameTip++].uiStringID;
}
else
{
// Add a trivia one
m_TipIDA[i]=m_TriviaTipA[iCurrentTriviaTip++].uiStringID;
}
}
if(m_TipIDA[i]==0)
{
// the m_TriviaTipA or the m_GameTipA are out of sync
#ifndef _CONTENT_PACKAGE
__debugbreak();
#endif
}
}
m_uiCurrentTip=0;
}
UINT CMinecraftApp::GetNextTip()
{
static bool bShowSkinDLCTip=true;
// don't display the DLC tip in the trial game
if(ProfileManager.IsFullVersion() && app.GetNewDLCAvailable() && app.DisplayNewDLCTip())
{
return IDS_TIPS_GAMETIP_NEWDLC;
}
else
{
if(bShowSkinDLCTip && ProfileManager.IsFullVersion())
{
bShowSkinDLCTip=false;
if( app.DLCInstallProcessCompleted() )
{
if(app.m_dlcManager.getPackCount(DLCManager::e_DLCType_Skin)==0)
{
return IDS_TIPS_GAMETIP_SKINPACKS;
}
}
else
{
return IDS_TIPS_GAMETIP_SKINPACKS;
}
}
}
if(m_uiCurrentTip==MAX_TIPS_GAMETIP+MAX_TIPS_TRIVIATIP) m_uiCurrentTip=0;
return m_TipIDA[m_uiCurrentTip++];
}
int CMinecraftApp::GetHTMLColour(eMinecraftColour colour)
{
Minecraft *pMinecraft = Minecraft::GetInstance();
return pMinecraft->skins->getSelected()->getColourTable()->getColour(colour);
}
int CMinecraftApp::GetHTMLFontSize(EHTMLFontSize size)
{
return s_iHTMLFontSizesA[size];
}
wstring CMinecraftApp::FormatHTMLString(int iPad, const wstring &desc, int shadowColour /*= 0xFFFFFFFF*/)
{
wstring text(desc);
wchar_t replacements[64];
// We will also insert line breaks here as couldn't figure out how to get them to come through from strings.resx !
text = replaceAll(text, L"{*B*}", L"<br />" );
swprintf(replacements,64,L"<font color=\"#%08x\">", GetHTMLColour(eHTMLColor_T1));
text = replaceAll(text, L"{*T1*}", replacements );
swprintf(replacements,64,L"<font color=\"#%08x\">", GetHTMLColour(eHTMLColor_T2));
text = replaceAll(text, L"{*T2*}", replacements );
swprintf(replacements,64,L"<font color=\"#%08x\">", GetHTMLColour(eHTMLColor_T3));
text = replaceAll(text, L"{*T3*}", replacements ); // for How To Play
swprintf(replacements,64,L"</font><font color=\"#%08x\">", GetHTMLColour(eHTMLColor_Black));
text = replaceAll(text, L"{*ETB*}", replacements );
swprintf(replacements,64,L"</font><font color=\"#%08x\">", GetHTMLColour(eHTMLColor_White));
text = replaceAll(text, L"{*ETW*}", replacements );
text = replaceAll(text, L"{*EF*}", L"</font>" );
swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_0), shadowColour);
text = replaceAll(text, L"{*C0*}", replacements );
swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_1), shadowColour);
text = replaceAll(text, L"{*C1*}", replacements );
swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_2), shadowColour);
text = replaceAll(text, L"{*C2*}", replacements );
swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_3), shadowColour);
text = replaceAll(text, L"{*C3*}", replacements );
swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_4), shadowColour);
text = replaceAll(text, L"{*C4*}", replacements );
swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_5), shadowColour);
text = replaceAll(text, L"{*C5*}", replacements );
swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_6), shadowColour);
text = replaceAll(text, L"{*C6*}", replacements );
swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_7), shadowColour);
text = replaceAll(text, L"{*C7*}", replacements );
swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_8), shadowColour);
text = replaceAll(text, L"{*C8*}", replacements );
swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_9), shadowColour);
text = replaceAll(text, L"{*C9*}", replacements );
swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_a), shadowColour);
text = replaceAll(text, L"{*CA*}", replacements );
swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_b), shadowColour);
text = replaceAll(text, L"{*CB*}", replacements );
swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_c), shadowColour);
text = replaceAll(text, L"{*CC*}", replacements );
swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_d), shadowColour);
text = replaceAll(text, L"{*CD*}", replacements );
swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_e), shadowColour);
text = replaceAll(text, L"{*CE*}", replacements );
swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_f), shadowColour);
text = replaceAll(text, L"{*CF*}", replacements );
// Swap for southpaw.
if ( app.GetGameSettings(iPad,eGameSetting_ControlSouthPaw) )
{
text = replaceAll(text, L"{*CONTROLLER_ACTION_MOVE*}", GetActionReplacement(iPad,MINECRAFT_ACTION_LOOK_RIGHT ) );
text = replaceAll(text, L"{*CONTROLLER_ACTION_LOOK*}", GetActionReplacement(iPad,MINECRAFT_ACTION_RIGHT ) );
text = replaceAll(text, L"{*CONTROLLER_MENU_NAVIGATE*}", GetVKReplacement(VK_PAD_RTHUMB_LEFT) );
}
else // Normal right handed.
{
text = replaceAll(text, L"{*CONTROLLER_ACTION_MOVE*}", GetActionReplacement(iPad,MINECRAFT_ACTION_RIGHT ) );
text = replaceAll(text, L"{*CONTROLLER_ACTION_LOOK*}", GetActionReplacement(iPad,MINECRAFT_ACTION_LOOK_RIGHT ) );
text = replaceAll(text, L"{*CONTROLLER_MENU_NAVIGATE*}", GetVKReplacement(VK_PAD_LTHUMB_LEFT) );
}
text = replaceAll(text, L"{*CONTROLLER_ACTION_JUMP*}", GetActionReplacement(iPad,MINECRAFT_ACTION_JUMP ) );
text = replaceAll(text, L"{*CONTROLLER_ACTION_SNEAK*}", GetActionReplacement(iPad,MINECRAFT_ACTION_SNEAK_TOGGLE ) );
text = replaceAll(text, L"{*CONTROLLER_ACTION_USE*}", GetActionReplacement(iPad,MINECRAFT_ACTION_USE ) );
text = replaceAll(text, L"{*CONTROLLER_ACTION_ACTION*}", GetActionReplacement(iPad,MINECRAFT_ACTION_ACTION ) );
text = replaceAll(text, L"{*CONTROLLER_ACTION_LEFT_SCROLL*}", GetActionReplacement(iPad,MINECRAFT_ACTION_LEFT_SCROLL ) );
text = replaceAll(text, L"{*CONTROLLER_ACTION_RIGHT_SCROLL*}", GetActionReplacement(iPad,MINECRAFT_ACTION_RIGHT_SCROLL ) );
text = replaceAll(text, L"{*CONTROLLER_ACTION_INVENTORY*}", GetActionReplacement(iPad,MINECRAFT_ACTION_INVENTORY ) );
text = replaceAll(text, L"{*CONTROLLER_ACTION_CRAFTING*}", GetActionReplacement(iPad,MINECRAFT_ACTION_CRAFTING ) );
text = replaceAll(text, L"{*CONTROLLER_ACTION_DROP*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DROP ) );
text = replaceAll(text, L"{*CONTROLLER_ACTION_CAMERA*}", GetActionReplacement(iPad,MINECRAFT_ACTION_RENDER_THIRD_PERSON ) );
text = replaceAll(text, L"{*CONTROLLER_ACTION_MENU_PAGEDOWN*}", GetActionReplacement(iPad,ACTION_MENU_PAGEDOWN ) );
text = replaceAll(text, L"{*CONTROLLER_ACTION_DISMOUNT*}", GetActionReplacement(iPad,MINECRAFT_ACTION_SNEAK_TOGGLE ) );
text = replaceAll(text, L"{*CONTROLLER_VK_A*}", GetVKReplacement(VK_PAD_A) );
text = replaceAll(text, L"{*CONTROLLER_VK_B*}", GetVKReplacement(VK_PAD_B) );
text = replaceAll(text, L"{*CONTROLLER_VK_X*}", GetVKReplacement(VK_PAD_X) );
text = replaceAll(text, L"{*CONTROLLER_VK_Y*}", GetVKReplacement(VK_PAD_Y) );
text = replaceAll(text, L"{*CONTROLLER_VK_LB*}", GetVKReplacement(VK_PAD_LSHOULDER) );
text = replaceAll(text, L"{*CONTROLLER_VK_RB*}", GetVKReplacement(VK_PAD_RSHOULDER) );
text = replaceAll(text, L"{*CONTROLLER_VK_LS*}", GetVKReplacement(VK_PAD_LTHUMB_UP) );
text = replaceAll(text, L"{*CONTROLLER_VK_RS*}", GetVKReplacement(VK_PAD_RTHUMB_UP) );
text = replaceAll(text, L"{*CONTROLLER_VK_LT*}", GetVKReplacement(VK_PAD_LTRIGGER) );
text = replaceAll(text, L"{*CONTROLLER_VK_RT*}", GetVKReplacement(VK_PAD_RTRIGGER) );
text = replaceAll(text, L"{*ICON_SHANK_01*}", GetIconReplacement(XZP_ICON_SHANK_01) );
text = replaceAll(text, L"{*ICON_SHANK_03*}", GetIconReplacement(XZP_ICON_SHANK_03) );
text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_UP*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DPAD_UP ) );
text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_DOWN*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DPAD_DOWN ) );
text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_RIGHT*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DPAD_RIGHT ) );
text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_LEFT*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DPAD_LEFT ) );
#if defined _XBOX_ONE || defined __PSVITA__
text = replaceAll(text, L"{*CONTROLLER_VK_START*}", GetVKReplacement(VK_PAD_START ) );
text = replaceAll(text, L"{*CONTROLLER_VK_BACK*}", GetVKReplacement(VK_PAD_BACK ) );
#endif
#ifdef _XBOX
wstring imageRoot = L"";
Minecraft *pMinecraft = Minecraft::GetInstance();
imageRoot = pMinecraft->skins->getSelected()->getXuiRootPath();
text = replaceAll(text, L"{*IMAGEROOT*}", imageRoot);
#endif // _XBOX
// Fix for #8903 - UI: Localization: KOR/JPN/CHT: Button Icons are rendered with padding space, which looks no good
DWORD dwLanguage = XGetLanguage( );
switch(dwLanguage)
{
case XC_LANGUAGE_KOREAN:
case XC_LANGUAGE_JAPANESE:
case XC_LANGUAGE_TCHINESE:
text = replaceAll(text, L"&nbsp;", L"" );
break;
}
return text;
}
wstring CMinecraftApp::GetActionReplacement(int iPad, unsigned char ucAction)
{
unsigned int input = InputManager.GetGameJoypadMaps(InputManager.GetJoypadMapVal(iPad) ,ucAction);
#ifdef _XBOX
switch(input)
{
case _360_JOY_BUTTON_A:
return app.GetString( IDS_CONTROLLER_A );
case _360_JOY_BUTTON_B:
return app.GetString( IDS_CONTROLLER_B );
case _360_JOY_BUTTON_X:
return app.GetString( IDS_CONTROLLER_X );
case _360_JOY_BUTTON_Y:
return app.GetString( IDS_CONTROLLER_Y );
case _360_JOY_BUTTON_LSTICK_UP:
case _360_JOY_BUTTON_LSTICK_DOWN:
case _360_JOY_BUTTON_LSTICK_LEFT:
case _360_JOY_BUTTON_LSTICK_RIGHT:
return app.GetString( IDS_CONTROLLER_LEFT_STICK );
case _360_JOY_BUTTON_RSTICK_LEFT:
case _360_JOY_BUTTON_RSTICK_RIGHT:
case _360_JOY_BUTTON_RSTICK_UP:
case _360_JOY_BUTTON_RSTICK_DOWN:
return app.GetString( IDS_CONTROLLER_RIGHT_STICK );
case _360_JOY_BUTTON_LT:
return app.GetString( IDS_CONTROLLER_LEFT_TRIGGER );
case _360_JOY_BUTTON_RT:
return app.GetString( IDS_CONTROLLER_RIGHT_TRIGGER );
case _360_JOY_BUTTON_RB:
return app.GetString( IDS_CONTROLLER_RIGHT_BUMPER );
case _360_JOY_BUTTON_LB:
return app.GetString( IDS_CONTROLLER_LEFT_BUMPER );
case _360_JOY_BUTTON_BACK:
return app.GetString( IDS_CONTROLLER_BACK );
case _360_JOY_BUTTON_START:
return app.GetString( IDS_CONTROLLER_START );
case _360_JOY_BUTTON_RTHUMB:
return app.GetString( IDS_CONTROLLER_RIGHT_THUMBSTICK );
case _360_JOY_BUTTON_LTHUMB:
return app.GetString( IDS_CONTROLLER_LEFT_THUMBSTICK );
case _360_JOY_BUTTON_DPAD_LEFT:
return app.GetString( IDS_CONTROLLER_DPAD_L );
case _360_JOY_BUTTON_DPAD_RIGHT:
return app.GetString( IDS_CONTROLLER_DPAD_R );
case _360_JOY_BUTTON_DPAD_UP:
return app.GetString( IDS_CONTROLLER_DPAD_U );
case _360_JOY_BUTTON_DPAD_DOWN:
return app.GetString( IDS_CONTROLLER_DPAD_D );
};
return L"";
#else
wstring replacement = L"";
// 4J Stu - Some of our actions can be mapped to multiple physical buttons, so replaces the switch that was here
if (input & _360_JOY_BUTTON_A) replacement = L"ButtonA";
else if(input &_360_JOY_BUTTON_B) replacement = L"ButtonB";
else if(input &_360_JOY_BUTTON_X) replacement = L"ButtonX";
else if(input &_360_JOY_BUTTON_Y) replacement = L"ButtonY";
else if(
(input &_360_JOY_BUTTON_LSTICK_UP) ||
(input &_360_JOY_BUTTON_LSTICK_DOWN) ||
(input &_360_JOY_BUTTON_LSTICK_LEFT) ||
(input &_360_JOY_BUTTON_LSTICK_RIGHT)
)
{
replacement = L"ButtonLeftStick";
}
else if(
(input &_360_JOY_BUTTON_RSTICK_LEFT) ||
(input &_360_JOY_BUTTON_RSTICK_RIGHT) ||
(input &_360_JOY_BUTTON_RSTICK_UP) ||
(input &_360_JOY_BUTTON_RSTICK_DOWN)
)
{
replacement = L"ButtonRightStick";
}
else if(input &_360_JOY_BUTTON_DPAD_LEFT) replacement = L"ButtonDpadL";
else if(input &_360_JOY_BUTTON_DPAD_RIGHT) replacement = L"ButtonDpadR";
else if(input &_360_JOY_BUTTON_DPAD_UP) replacement = L"ButtonDpadU";
else if(input &_360_JOY_BUTTON_DPAD_DOWN) replacement = L"ButtonDpadD";
else if(input &_360_JOY_BUTTON_LT) replacement = L"ButtonLeftTrigger";
else if(input &_360_JOY_BUTTON_RT) replacement = L"ButtonRightTrigger";
else if(input &_360_JOY_BUTTON_RB) replacement = L"ButtonRightBumper";
else if(input &_360_JOY_BUTTON_LB) replacement = L"ButtonLeftBumper";
else if(input &_360_JOY_BUTTON_BACK) replacement = L"ButtonBack";
else if(input &_360_JOY_BUTTON_START) replacement = L"ButtonStart";
else if(input &_360_JOY_BUTTON_RTHUMB) replacement = L"ButtonRS";
else if(input &_360_JOY_BUTTON_LTHUMB) replacement = L"ButtonLS";
wchar_t string[128];
#ifdef __PS3__
int size = 30;
#elif defined _WIN64
int size = 45;
if(ui.getScreenHeight() < 1080) size = 30;
#else
int size = 45;
#endif
swprintf(string,128,L"<img src=\"%ls\" align=\"middle\" height=\"%d\" width=\"%d\"/>", replacement.c_str(), size, size);
return string;
#endif
}
wstring CMinecraftApp::GetVKReplacement(unsigned int uiVKey)
{
#ifdef _XBOX
switch(uiVKey)
{
case VK_PAD_A:
return app.GetString( IDS_CONTROLLER_A );
case VK_PAD_B:
return app.GetString( IDS_CONTROLLER_B );
case VK_PAD_X:
return app.GetString( IDS_CONTROLLER_X );
case VK_PAD_Y:
return app.GetString( IDS_CONTROLLER_Y );
case VK_PAD_LSHOULDER:
return app.GetString( IDS_CONTROLLER_LEFT_BUMPER );
case VK_PAD_RSHOULDER:
return app.GetString( IDS_CONTROLLER_RIGHT_BUMPER );
case VK_PAD_LTRIGGER:
return app.GetString( IDS_CONTROLLER_LEFT_TRIGGER );
case VK_PAD_RTRIGGER:
return app.GetString( IDS_CONTROLLER_RIGHT_TRIGGER );
case VK_PAD_LTHUMB_UP :
case VK_PAD_LTHUMB_DOWN :
case VK_PAD_LTHUMB_RIGHT :
case VK_PAD_LTHUMB_LEFT :
case VK_PAD_LTHUMB_UPLEFT :
case VK_PAD_LTHUMB_UPRIGHT :
case VK_PAD_LTHUMB_DOWNRIGHT:
case VK_PAD_LTHUMB_DOWNLEFT :
return app.GetString( IDS_CONTROLLER_LEFT_STICK );
case VK_PAD_RTHUMB_UP :
case VK_PAD_RTHUMB_DOWN :
case VK_PAD_RTHUMB_RIGHT :
case VK_PAD_RTHUMB_LEFT :
case VK_PAD_RTHUMB_UPLEFT :
case VK_PAD_RTHUMB_UPRIGHT :
case VK_PAD_RTHUMB_DOWNRIGHT:
case VK_PAD_RTHUMB_DOWNLEFT :
return app.GetString( IDS_CONTROLLER_RIGHT_STICK );
default:
break;
}
return NULL;
#else
wstring replacement = L"";
switch(uiVKey)
{
case VK_PAD_A:
#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__)
if( InputManager.IsCircleCrossSwapped() ) replacement = L"ButtonB";
else replacement = L"ButtonA";
#else
replacement = L"ButtonA";
#endif
break;
case VK_PAD_B:
#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__)
if( InputManager.IsCircleCrossSwapped() ) replacement = L"ButtonA";
else replacement = L"ButtonB";
#else
replacement = L"ButtonB";
#endif
break;
case VK_PAD_X:
replacement = L"ButtonX";
break;
case VK_PAD_Y:
replacement = L"ButtonY";
break;
case VK_PAD_LSHOULDER:
replacement = L"ButtonLeftBumper";
break;
case VK_PAD_RSHOULDER:
replacement = L"ButtonRightBumper";
break;
case VK_PAD_LTRIGGER:
replacement = L"ButtonLeftTrigger";
break;
case VK_PAD_RTRIGGER:
replacement = L"ButtonRightTrigger";
break;
case VK_PAD_LTHUMB_UP :
case VK_PAD_LTHUMB_DOWN :
case VK_PAD_LTHUMB_RIGHT :
case VK_PAD_LTHUMB_LEFT :
case VK_PAD_LTHUMB_UPLEFT :
case VK_PAD_LTHUMB_UPRIGHT :
case VK_PAD_LTHUMB_DOWNRIGHT:
case VK_PAD_LTHUMB_DOWNLEFT :
replacement = L"ButtonLeftStick";
break;
case VK_PAD_RTHUMB_UP :
case VK_PAD_RTHUMB_DOWN :
case VK_PAD_RTHUMB_RIGHT :
case VK_PAD_RTHUMB_LEFT :
case VK_PAD_RTHUMB_UPLEFT :
case VK_PAD_RTHUMB_UPRIGHT :
case VK_PAD_RTHUMB_DOWNRIGHT:
case VK_PAD_RTHUMB_DOWNLEFT :
replacement = L"ButtonRightStick";
break;
#if defined _XBOX_ONE || defined __PSVITA__
case VK_PAD_START:
replacement = L"ButtonStart";
break;
case VK_PAD_BACK:
replacement = L"ButtonBack";
break;
#endif
default:
break;
}
wchar_t string[128];
#ifdef __PS3__
int size = 30;
#elif defined _WIN64
int size = 45;
if(ui.getScreenHeight() < 1080) size = 30;
#else
int size = 45;
#endif
swprintf(string,128,L"<img src=\"%ls\" align=\"middle\" height=\"%d\" width=\"%d\"/>", replacement.c_str(), size, size);
return string;
#endif
}
wstring CMinecraftApp::GetIconReplacement(unsigned int uiIcon)
{
#ifdef _XBOX
switch(uiIcon)
{
case XZP_ICON_SHANK_01:
return app.GetString( IDS_ICON_SHANK_01 );
case XZP_ICON_SHANK_03:
return app.GetString( IDS_ICON_SHANK_03 );
default:
break;
}
return NULL;
#else
wchar_t string[128];
#ifdef __PS3__
int size = 22;
#elif defined _WIN64
int size = 33;
if(ui.getScreenHeight() < 1080) size = 22;
#else
int size = 33;
#endif
swprintf(string,128,L"<img src=\"Icon_Shank\" align=\"middle\" height=\"%d\" width=\"%d\"/>", size, size);
wstring result = L"";
switch(uiIcon)
{
case XZP_ICON_SHANK_01:
result = string;
break;
case XZP_ICON_SHANK_03:
result.append(string).append(string).append(string);
break;
default:
break;
}
return result;
#endif
}
#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__)
unordered_map<PlayerUID, MOJANG_DATA *, PlayerUID::Hash> CMinecraftApp::MojangData;
unordered_map<int, char * > CMinecraftApp::DLCTextures_PackID;
unordered_map<string, DLC_INFO * > CMinecraftApp::DLCInfo;
unordered_map<wstring, ULONGLONG > CMinecraftApp::DLCInfo_SkinName;
#elif defined(_DURANGO)
unordered_map<PlayerUID,MOJANG_DATA *, PlayerUID::Hash > CMinecraftApp::MojangData;
unordered_map<int, wstring > CMinecraftApp::DLCTextures_PackID; // for mash-up packs & texture packs
//unordered_map<ULONGLONG,DLC_INFO * > CMinecraftApp::DLCInfo_Trial; // full offerid, dlc_info
unordered_map<wstring,DLC_INFO * > CMinecraftApp::DLCInfo_Full; // full offerid, dlc_info
unordered_map<wstring, wstring > CMinecraftApp::DLCInfo_SkinName; // skin name, full offer id
#else
unordered_map<PlayerUID, MOJANG_DATA *> CMinecraftApp::MojangData;
unordered_map<int, ULONGLONG > CMinecraftApp::DLCTextures_PackID;
unordered_map<ULONGLONG, DLC_INFO * > CMinecraftApp::DLCInfo_Trial;
unordered_map<ULONGLONG, DLC_INFO * > CMinecraftApp::DLCInfo_Full;
unordered_map<wstring, ULONGLONG > CMinecraftApp::DLCInfo_SkinName;
#endif
HRESULT CMinecraftApp::RegisterMojangData(WCHAR *pXuidName, PlayerUID xuid, WCHAR *pSkin, WCHAR *pCape)
{
HRESULT hr=S_OK;
eXUID eTempXuid=eXUID_Undefined;
MOJANG_DATA *pMojangData=NULL;
// ignore the names if we don't recognize them
if(pXuidName!=NULL)
{
if( wcscmp( pXuidName, L"XUID_NOTCH" ) == 0 )
{
eTempXuid = eXUID_Notch; // might be needed for the apple at some point
}
else if( wcscmp( pXuidName, L"XUID_DEADMAU5" ) == 0 )
{
eTempXuid = eXUID_Deadmau5; // Needed for the deadmau5 ears
}
else
{
eTempXuid=eXUID_NoName;
}
}
if(eTempXuid!=eXUID_Undefined)
{
pMojangData = new MOJANG_DATA;
ZeroMemory(pMojangData,sizeof(MOJANG_DATA));
pMojangData->eXuid=eTempXuid;
wcsncpy( pMojangData->wchSkin, pSkin, MAX_CAPENAME_SIZE);
wcsncpy( pMojangData->wchCape, pCape, MAX_CAPENAME_SIZE);
MojangData[xuid]=pMojangData;
}
return hr;
}
MOJANG_DATA *CMinecraftApp::GetMojangDataForXuid(PlayerUID xuid)
{
return MojangData[xuid];
}
HRESULT CMinecraftApp::RegisterConfigValues(WCHAR *pType, int iValue)
{
HRESULT hr=S_OK;
// #ifdef _XBOX
// if(pType!=NULL)
// {
// if(wcscmp(pType,L"XboxOneTransfer")==0)
// {
// if(iValue>0)
// {
// app.m_bTransferSavesToXboxOne=true;
// }
// else
// {
// app.m_bTransferSavesToXboxOne=false;
// }
// }
// else if(wcscmp(pType,L"TransferSlotCount")==0)
// {
// app.m_uiTransferSlotC=iValue;
// }
//
// }
// #endif
return hr;
}
#if (defined _XBOX || defined _WINDOWS64)
HRESULT CMinecraftApp::RegisterDLCData(WCHAR *pType, WCHAR *pBannerName, int iGender, uint64_t ullOfferID_Full, uint64_t ullOfferID_Trial, WCHAR *pFirstSkin, unsigned int uiSortIndex, int iConfig, WCHAR *pDataFile)
{
HRESULT hr=S_OK;
DLC_INFO *pDLCData=new DLC_INFO;
ZeroMemory(pDLCData,sizeof(DLC_INFO));
pDLCData->ullOfferID_Full=ullOfferID_Full;
pDLCData->ullOfferID_Trial=ullOfferID_Trial;
pDLCData->eDLCType=e_DLC_NotDefined;
pDLCData->iGender=iGender;
pDLCData->uiSortIndex=uiSortIndex;
pDLCData->iConfig=iConfig;
#ifndef __ORBIS__
// ignore the names if we don't recognize them
if(pBannerName!=L"")
{
wcsncpy_s( pDLCData->wchBanner, pBannerName, MAX_BANNERNAME_SIZE);
}
if(pDataFile[0]!=0)
{
wcsncpy_s( pDLCData->wchDataFile, pDataFile, MAX_BANNERNAME_SIZE);
}
#endif
if(pType!=NULL)
{
if(wcscmp(pType,L"Skin")==0)
{
pDLCData->eDLCType=e_DLC_SkinPack;
}
else if(wcscmp(pType,L"Gamerpic")==0)
{
pDLCData->eDLCType=e_DLC_Gamerpics;
}
else if(wcscmp(pType,L"Theme")==0)
{
pDLCData->eDLCType=e_DLC_Themes;
}
else if(wcscmp(pType,L"Avatar")==0)
{
pDLCData->eDLCType=e_DLC_AvatarItems;
}
else if(wcscmp(pType,L"MashUpPack")==0)
{
pDLCData->eDLCType=e_DLC_MashupPacks;
DLCTextures_PackID[pDLCData->iConfig]=ullOfferID_Full;
}
else if(wcscmp(pType,L"TexturePack")==0)
{
pDLCData->eDLCType=e_DLC_TexturePacks;
DLCTextures_PackID[pDLCData->iConfig]=ullOfferID_Full;
}
}
if(ullOfferID_Trial!=0ll) DLCInfo_Trial[ullOfferID_Trial]=pDLCData;
if(ullOfferID_Full!=0ll) DLCInfo_Full[ullOfferID_Full]=pDLCData;
if(pFirstSkin[0]!=0) DLCInfo_SkinName[pFirstSkin]=ullOfferID_Full;
return hr;
}
#elif defined _XBOX_ONE
unordered_map<wstring,DLC_INFO * > *CMinecraftApp::GetDLCInfo()
{
return &DLCInfo_Full;
}
HRESULT CMinecraftApp::RegisterDLCData(eDLCContentType eType, WCHAR *pwchBannerName,WCHAR *pwchProductId, WCHAR *pwchProductName, WCHAR *pwchFirstSkin, int iConfig, unsigned int uiSortIndex)
{
HRESULT hr=S_OK;
// 4J-PB - need to convert the product id to uppercase because the catalog calls come back with upper case
WCHAR wchUppercaseProductID[64];
if(pwchProductId[0]!=0)
{
for(int i=0;i<64;i++)
{
wchUppercaseProductID[i]=towupper((wchar_t)pwchProductId[i]);
}
}
// check if we already have this info from the local DLC file
wstring wsTemp=wchUppercaseProductID;
auto it = DLCInfo_Full.find(wsTemp);
if( it == DLCInfo_Full.end() )
{
// Not found
DLC_INFO *pDLCData=new DLC_INFO;
ZeroMemory(pDLCData,sizeof(DLC_INFO));
pDLCData->eDLCType=e_DLC_NotDefined;
pDLCData->uiSortIndex=uiSortIndex;
pDLCData->iConfig=iConfig;
if(pwchProductId[0]!=0)
{
pDLCData->wsProductId=wchUppercaseProductID;
}
// ignore the names if we don't recognize them
if(pwchBannerName!=L"")
{
wcsncpy_s( pDLCData->wchBanner, pwchBannerName, MAX_BANNERNAME_SIZE);
}
if(pwchProductName[0]!=0)
{
pDLCData->wsDisplayName=pwchProductName;
}
pDLCData->eDLCType=eType;
switch(eType)
{
case e_DLC_MashupPacks:
case e_DLC_TexturePacks:
DLCTextures_PackID[iConfig]=pDLCData->wsProductId;
break;
}
if(pwchFirstSkin[0]!=0) DLCInfo_SkinName[pwchFirstSkin]=pDLCData->wsProductId;
#ifdef _XBOX_ONE
// ignore the names, and use the product id instead
DLCInfo_Full[pDLCData->wsProductId]=pDLCData;
#else
DLCInfo_Full[pDLCData->wsDisplayName]=pDLCData;
#endif
}
app.DebugPrintf("DLCInfo - type - %d, productID - %ls, name - %ls , banner - %ls, iconfig - %d, sort index - %d\n",eType,pwchProductId, pwchProductName,pwchBannerName, iConfig, uiSortIndex);
return hr;
}
#else
HRESULT CMinecraftApp::RegisterDLCData(char *pchDLCName, unsigned int uiSortIndex,char *pchImageURL)
{
// on PS3 we get all the required info from the name
char chDLCType[3];
HRESULT hr=S_OK;
DLC_INFO *pDLCData=new DLC_INFO;
ZeroMemory(pDLCData,sizeof(DLC_INFO));
chDLCType[0]=pchDLCName[0];
chDLCType[1]=pchDLCName[1];
chDLCType[2]=0;
pDLCData->iConfig = app.GetiConfigFromName(pchDLCName);
pDLCData->uiSortIndex=uiSortIndex;
pDLCData->eDLCType = app.GetDLCTypeFromName(pchDLCName);
strcpy(pDLCData->chImageURL,pchImageURL);
//bool bIsTrialDLC = app.GetTrialFromName(pchDLCName);
switch(pDLCData->eDLCType)
{
case e_DLC_TexturePacks:
{
char *pchName=(char *)malloc(strlen(pchDLCName)+1);
strcpy(pchName,pchDLCName);
DLCTextures_PackID[pDLCData->iConfig]=pchName;
}
break;
case e_DLC_MashupPacks:
{
char *pchName=(char *)malloc(strlen(pchDLCName)+1);
strcpy(pchName,pchDLCName);
DLCTextures_PackID[pDLCData->iConfig]=pchName;
}
break;
default:
break;
}
app.DebugPrintf(5,"Adding DLC - %s\n",pchDLCName);
DLCInfo[pchDLCName]=pDLCData;
// if(ullOfferID_Trial!=0ll) DLCInfo_Trial[ullOfferID_Trial]=pDLCData;
// if(ullOfferID_Full!=0ll) DLCInfo_Full[ullOfferID_Full]=pDLCData;
// if(pFirstSkin[0]!=0) DLCInfo_SkinName[pFirstSkin]=ullOfferID_Full;
// DLCInfo[ullOfferID_Trial]=pDLCData;
return hr;
}
#endif
#if defined( __PS3__) || defined(__ORBIS__) || defined(__PSVITA__)
bool CMinecraftApp::GetDLCFullOfferIDForSkinID(const wstring &FirstSkin,ULONGLONG *pullVal)
{
auto it = DLCInfo_SkinName.find(FirstSkin);
if( it == DLCInfo_SkinName.end() )
{
return false;
}
else
{
*pullVal=(ULONGLONG)it->second;
return true;
}
}
bool CMinecraftApp::GetDLCNameForPackID(const int iPackID,char **ppchKeyID)
{
auto it = DLCTextures_PackID.find(iPackID);
if( it == DLCTextures_PackID.end() )
{
*ppchKeyID=NULL;
return false;
}
else
{
*ppchKeyID=(char *)it->second;
return true;
}
}
DLC_INFO *CMinecraftApp::GetDLCInfo(char *pchDLCName)
{
string tempString=pchDLCName;
if(DLCInfo.size()>0)
{
auto it = DLCInfo.find(tempString);
if( it == DLCInfo.end() )
{
// nothing for this
return NULL;
}
else
{
return it->second;
}
}
else return NULL;
}
DLC_INFO *CMinecraftApp::GetDLCInfoFromTPackID(int iTPID)
{
unordered_map<string, DLC_INFO *>::iterator it= DLCInfo.begin();
for(int i=0;i<DLCInfo.size();i++)
{
if(((DLC_INFO *)it->second)->iConfig==iTPID)
{
return it->second;
}
++it;
}
return NULL;
}
DLC_INFO *CMinecraftApp::GetDLCInfo(int iIndex)
{
unordered_map<string, DLC_INFO *>::iterator it= DLCInfo.begin();
for(int i=0;i<iIndex;i++)
{
++it;
}
return it->second;
}
char *CMinecraftApp::GetDLCInfoTextures(int iIndex)
{
unordered_map<int, char * >::iterator it= DLCTextures_PackID.begin();
for(int i=0;i<iIndex;i++)
{
++it;
}
return it->second;
}
#elif defined _XBOX_ONE
bool CMinecraftApp::GetDLCFullOfferIDForSkinID(const wstring &FirstSkin,wstring &ProductId)
{
auto it = DLCInfo_SkinName.find(FirstSkin);
if( it == DLCInfo_SkinName.end() )
{
return false;
}
else
{
ProductId=it->second;
return true;
}
}
bool CMinecraftApp::GetDLCFullOfferIDForPackID(const int iPackID,wstring &ProductId)
{
auto it = DLCTextures_PackID.find(iPackID);
if( it == DLCTextures_PackID.end() )
{
return false;
}
else
{
ProductId=it->second;
return true;
}
}
// DLC_INFO *CMinecraftApp::GetDLCInfoForTrialOfferID(wstring &ProductId)
// {
// return NULL;
// }
DLC_INFO *CMinecraftApp::GetDLCInfoTrialOffer(int iIndex)
{
return NULL;
}
DLC_INFO *CMinecraftApp::GetDLCInfoFullOffer(int iIndex)
{
unordered_map<wstring, DLC_INFO *>::iterator it= DLCInfo_Full.begin();
for(int i=0;i<iIndex;i++)
{
++it;
}
return it->second;
}
wstring CMinecraftApp::GetDLCInfoTexturesFullOffer(int iIndex)
{
unordered_map<int, wstring >::iterator it= DLCTextures_PackID.begin();
for(int i=0;i<iIndex;i++)
{
++it;
}
return it->second;
}
#else
bool CMinecraftApp::GetDLCFullOfferIDForSkinID(const wstring &FirstSkin,ULONGLONG *pullVal)
{
auto it = DLCInfo_SkinName.find(FirstSkin);
if( it == DLCInfo_SkinName.end() )
{
return false;
}
else
{
*pullVal=(ULONGLONG)it->second;
return true;
}
}
bool CMinecraftApp::GetDLCFullOfferIDForPackID(const int iPackID,ULONGLONG *pullVal)
{
auto it = DLCTextures_PackID.find(iPackID);
if( it == DLCTextures_PackID.end() )
{
*pullVal=0ULL;
return false;
}
else
{
*pullVal=it->second;
return true;
}
}
DLC_INFO *CMinecraftApp::GetDLCInfoForTrialOfferID(ULONGLONG ullOfferID_Trial)
{
//DLC_INFO *pDLCInfo=NULL;
if(DLCInfo_Trial.size()>0)
{
auto it = DLCInfo_Trial.find(ullOfferID_Trial);
if( it == DLCInfo_Trial.end() )
{
// nothing for this
return NULL;
}
else
{
return it->second;
}
}
else return NULL;
}
DLC_INFO *CMinecraftApp::GetDLCInfoTrialOffer(int iIndex)
{
unordered_map<ULONGLONG, DLC_INFO *>::iterator it= DLCInfo_Trial.begin();
for(int i=0;i<iIndex;i++)
{
++it;
}
return it->second;
}
DLC_INFO *CMinecraftApp::GetDLCInfoFullOffer(int iIndex)
{
unordered_map<ULONGLONG, DLC_INFO *>::iterator it= DLCInfo_Full.begin();
for(int i=0;i<iIndex;i++)
{
++it;
}
return it->second;
}
ULONGLONG CMinecraftApp::GetDLCInfoTexturesFullOffer(int iIndex)
{
unordered_map<int, ULONGLONG >::iterator it= DLCTextures_PackID.begin();
for(int i=0;i<iIndex;i++)
{
++it;
}
return it->second;
}
#endif
#ifdef _XBOX_ONE
DLC_INFO *CMinecraftApp::GetDLCInfoForFullOfferID(WCHAR *pwchProductID)
{
wstring wsTemp = pwchProductID;
if(DLCInfo_Full.size()>0)
{
auto it = DLCInfo_Full.find(wsTemp);
if( it == DLCInfo_Full.end() )
{
// nothing for this
return NULL;
}
else
{
return it->second;
}
}
else return NULL;
}
DLC_INFO *CMinecraftApp::GetDLCInfoForProductName(WCHAR *pwchProductName)
{
unordered_map<wstring, DLC_INFO *>::iterator it= DLCInfo_Full.begin();
wstring wsProductName=pwchProductName;
for(int i=0;i<DLCInfo_Full.size();i++)
{
DLC_INFO *pDLCInfo=(DLC_INFO *)it->second;
if(wsProductName==pDLCInfo->wsDisplayName)
{
return pDLCInfo;
}
++it;
}
return NULL;
}
#elif defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__)
#else
DLC_INFO *CMinecraftApp::GetDLCInfoForFullOfferID(ULONGLONG ullOfferID_Full)
{
if(DLCInfo_Full.size()>0)
{
auto it = DLCInfo_Full.find(ullOfferID_Full);
if( it == DLCInfo_Full.end() )
{
// nothing for this
return NULL;
}
else
{
return it->second;
}
}
else return NULL;
}
#endif
void CMinecraftApp::EnterSaveNotificationSection()
{
EnterCriticalSection(&m_saveNotificationCriticalSection);
if( m_saveNotificationDepth++ == 0 )
{
if(g_NetworkManager.IsInSession()) // this can be triggered from the front end if we're downloading a save
{
MinecraftServer::getInstance()->broadcastStartSavingPacket();
if( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 )
{
app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_PauseServer,(void *)TRUE);
}
}
}
LeaveCriticalSection(&m_saveNotificationCriticalSection);
}
void CMinecraftApp::LeaveSaveNotificationSection()
{
EnterCriticalSection(&m_saveNotificationCriticalSection);
if( --m_saveNotificationDepth == 0 )
{
if(g_NetworkManager.IsInSession()) // this can be triggered from the front end if we're downloading a save
{
MinecraftServer::getInstance()->broadcastStopSavingPacket();
if( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 )
{
app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_PauseServer,(void *)FALSE);
}
}
}
LeaveCriticalSection(&m_saveNotificationCriticalSection);
}
int CMinecraftApp::RemoteSaveThreadProc( void* lpParameter )
{
// The game should be stopped while we are doing this, but the connections ticks may try to create some AABB's or Vec3's
AABB::UseDefaultThreadStorage();
Vec3::UseDefaultThreadStorage();
Compression::UseDefaultThreadStorage();
// 4J-PB - Xbox 360 - 163153 - [CRASH] TU17: Code: Multiplayer: During the Autosave in an online Multiplayer session, the game occasionally crashes for one or more Clients
// callstack - > if(tls->tileId != this->id) updateDefaultShape();
// callstack - > default.exe!WaterlilyTile::getAABB(Level * level, int x, int y, int z) line 38 + 8 bytes C++
// ...
// default.exe!CMinecraftApp::RemoteSaveThreadProc(void * lpParameter) line 6694 C++
// host autosave, and the clients can crash on receiving handleMoveEntity when it's a tile within this thread, so need to do the tls for tiles
Tile::CreateNewThreadStorage();
Minecraft *pMinecraft = Minecraft::GetInstance();
pMinecraft->progressRenderer->progressStartNoAbort( IDS_PROGRESS_HOST_SAVING );
pMinecraft->progressRenderer->progressStage( -1 );
pMinecraft->progressRenderer->progressStagePercentage(0);
while( !app.GetGameStarted() && app.GetXuiAction( ProfileManager.GetPrimaryPad() ) == eAppAction_WaitRemoteServerSaveComplete )
{
// Tick all the games connections
pMinecraft->tickAllConnections();
Sleep( 100 );
}
if( app.GetXuiAction( ProfileManager.GetPrimaryPad() ) != eAppAction_WaitRemoteServerSaveComplete )
{
// Something cancelled us?
return ERROR_CANCELLED;
}
app.SetAction(ProfileManager.GetPrimaryPad(),eAppAction_Idle);
ui.UpdatePlayerBasePositions();
Tile::ReleaseThreadStorage();
return S_OK;
}
void CMinecraftApp::ExitGameFromRemoteSave( LPVOID lpParameter )
{
int primaryPad = ProfileManager.GetPrimaryPad();
UINT uiIDA[3];
uiIDA[0]=IDS_CONFIRM_CANCEL;
uiIDA[1]=IDS_CONFIRM_OK;
ui.RequestAlertMessage(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 2, primaryPad,&CMinecraftApp::ExitGameFromRemoteSaveDialogReturned,NULL);
}
int CMinecraftApp::ExitGameFromRemoteSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
{
//CScene_Pause* pClass = (CScene_Pause*)pParam;
// results switched for this dialog
if(result==C4JStorage::EMessage_ResultDecline)
{
app.SetAction(iPad,eAppAction_ExitWorld);
}
else
{
#ifndef _XBOX
// Inform fullscreen progress scene that it's not being cancelled after all
UIScene_FullscreenProgress *pScene = (UIScene_FullscreenProgress *)ui.FindScene(eUIScene_FullscreenProgress);
#ifdef __PS3__
if(pScene!=NULL)
#else
if (pScene != nullptr)
#endif
{
pScene->SetWasCancelled(false);
}
#else
// Don't have to worry about this on Xbox
#endif
}
return 0;
}
void CMinecraftApp::SetSpecialTutorialCompletionFlag(int iPad, int index)
{
if(index >= 0 && index < 32 && GameSettingsA[iPad] != NULL)
{
GameSettingsA[iPad]->uiSpecialTutorialBitmask |= (1<<index);
}
}
// BANNED LIST FUNCTIONS
void CMinecraftApp::SetUniqueMapName(char *pszUniqueMapName)
{
memcpy(m_pszUniqueMapName,pszUniqueMapName,14);
}
char *CMinecraftApp::GetUniqueMapName(void)
{
return m_pszUniqueMapName;
}
void CMinecraftApp::InvalidateBannedList(int iPad)
{
if(m_bRead_BannedListA[iPad]==true)
{
m_bRead_BannedListA[iPad]=false;
SetBanListCheck(iPad,false);
m_vBannedListA[iPad]->clear();
if(BannedListA[iPad].pBannedList)
{
delete [] BannedListA[iPad].pBannedList;
BannedListA[iPad].pBannedList=NULL;
}
}
}
#ifdef _XBOX_ONE
void CMinecraftApp::AddLevelToBannedLevelList(int iPad, PBANNEDLISTDATA pBannedListData, bool bWriteToTMS)
{
PlayerUID xuid= pBannedListData->wchPlayerUID;
AddLevelToBannedLevelList(iPad,xuid,pBannedListData->pszLevelName,bWriteToTMS);
}
#endif
void CMinecraftApp::AddLevelToBannedLevelList(int iPad, PlayerUID xuid, char *pszLevelName, bool bWriteToTMS)
{
// we will have retrieved the banned level list from TMS, so add this one to it and write it back to TMS
BANNEDLISTDATA *pBannedListData = new BANNEDLISTDATA;
memset(pBannedListData,0,sizeof(BANNEDLISTDATA));
#ifdef _DURANGO
memcpy(&pBannedListData->wchPlayerUID, xuid.toString().c_str(), sizeof(WCHAR)*64);
#else
memcpy(&pBannedListData->xuid, &xuid, sizeof(PlayerUID));
#endif
strcpy(pBannedListData->pszLevelName,pszLevelName);
m_vBannedListA[iPad]->push_back(pBannedListData);
if(bWriteToTMS)
{
DWORD dwDataBytes=(DWORD)(sizeof(BANNEDLISTDATA)*m_vBannedListA[iPad]->size());
PBANNEDLISTDATA pBannedList = (BANNEDLISTDATA *)(new CHAR [dwDataBytes]);
int iCount=0;
for (PBANNEDLISTDATA pData : *m_vBannedListA[iPad] )
{
memcpy(&pBannedList[iCount++],pData,sizeof(BANNEDLISTDATA));
}
// 4J-PB - write to TMS++ now
//bool bRes=StorageManager.WriteTMSFile(iPad,C4JStorage::eGlobalStorage_TitleUser,L"BannedList",(PBYTE)pBannedList, dwDataBytes);
#ifdef _XBOX
StorageManager.TMSPP_WriteFile(iPad,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,C4JStorage::TMS_UGCTYPE_NONE,"BannedList",(PCHAR) pBannedList, dwDataBytes,NULL,NULL, 0);
#elif defined _XBOX_ONE
StorageManager.TMSPP_WriteFile(iPad,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,L"BannedList",(PBYTE) pBannedList, dwDataBytes,NULL,NULL, 0);
#endif
}
// update telemetry too
}
bool CMinecraftApp::IsInBannedLevelList(int iPad, PlayerUID xuid, char *pszLevelName)
{
for( PBANNEDLISTDATA pData : *m_vBannedListA[iPad] )
{
#ifdef _XBOX_ONE
PlayerUID bannedPlayerUID = pData->wchPlayerUID;
if(IsEqualXUID (bannedPlayerUID,xuid) && (strcmp(pData->pszLevelName,pszLevelName)==0))
#else
if(IsEqualXUID (pData->xuid,xuid) && (strcmp(pData->pszLevelName,pszLevelName)==0))
#endif
{
return true;
}
}
return false;
}
void CMinecraftApp::RemoveLevelFromBannedLevelList(int iPad, PlayerUID xuid, char *pszLevelName)
{
//bool bFound=false;
//bool bRes;
// we will have retrieved the banned level list from TMS, so remove this one from it and write it back to TMS
for (auto it = m_vBannedListA[iPad]->begin(); it != m_vBannedListA[iPad]->end(); )
{
PBANNEDLISTDATA pBannedListData = *it;
if(pBannedListData!=NULL)
{
#ifdef _XBOX_ONE
PlayerUID bannedPlayerUID = pBannedListData->wchPlayerUID;
if(IsEqualXUID (bannedPlayerUID,xuid) && (strcmp(pBannedListData->pszLevelName,pszLevelName)==0))
#else
if(IsEqualXUID (pBannedListData->xuid,xuid) && (strcmp(pBannedListData->pszLevelName,pszLevelName)==0))
#endif
{
TelemetryManager->RecordUnBanLevel(iPad);
// match found, so remove this entry
it = m_vBannedListA[iPad]->erase(it);
}
else
{
++it;
}
}
else
{
++it;
}
}
DWORD dwDataBytes=(DWORD)(sizeof(BANNEDLISTDATA)*m_vBannedListA[iPad]->size());
if(dwDataBytes==0)
{
// wipe the file
#ifdef _XBOX
StorageManager.DeleteTMSFile(iPad,C4JStorage::eGlobalStorage_TitleUser,L"BannedList");
#elif defined _XBOX_ONE
StorageManager.TMSPP_DeleteFile(iPad,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,L"BannedList",NULL,NULL, 0);
#endif
}
else
{
PBANNEDLISTDATA pBannedList = (BANNEDLISTDATA *)(new BYTE [dwDataBytes]);
int iSize=(int)m_vBannedListA[iPad]->size();
for(int i=0;i<iSize;i++)
{
PBANNEDLISTDATA pBannedListData =m_vBannedListA[iPad]->at(i);
memcpy(&pBannedList[i],pBannedListData,sizeof(BANNEDLISTDATA));
}
#ifdef _XBOX
StorageManager.WriteTMSFile(iPad,C4JStorage::eGlobalStorage_TitleUser,L"BannedList",(PBYTE)pBannedList, dwDataBytes);
#elif defined _XBOX_ONE
StorageManager.TMSPP_WriteFile(iPad,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,L"BannedList",(PBYTE) pBannedList, dwDataBytes,NULL,NULL, 0);
#endif
delete [] pBannedList;
}
// update telemetry too
}
// function to add credits for the DLC packs
void CMinecraftApp::AddCreditText(LPCWSTR lpStr)
{
DebugPrintf("ADDING CREDIT - %ls\n",lpStr);
// add a string from the DLC to a credits vector
SCreditTextItemDef *pCreditStruct = new SCreditTextItemDef;
pCreditStruct->m_eType=eSmallText;
pCreditStruct->m_iStringID[0]=NO_TRANSLATED_STRING;
pCreditStruct->m_iStringID[1]=NO_TRANSLATED_STRING;
pCreditStruct->m_Text=new WCHAR [wcslen(lpStr)+1];
wcscpy((WCHAR *)pCreditStruct->m_Text,lpStr);
vDLCCredits.push_back(pCreditStruct);
}
bool CMinecraftApp::AlreadySeenCreditText(const wstring &wstemp)
{
for(unsigned int i=0;i<m_vCreditText.size();i++)
{
wstring temp=m_vCreditText.at(i);
// if they are the same, break out of the case
if(temp.compare(wstemp)==0)
{
return true;
}
}
// add this text
m_vCreditText.push_back((WCHAR * )wstemp.c_str());
return false;
}
unsigned int CMinecraftApp::GetDLCCreditsCount()
{
return (unsigned int)vDLCCredits.size();
}
SCreditTextItemDef * CMinecraftApp::GetDLCCredits(int iIndex)
{
return vDLCCredits.at(iIndex);
}
// Game Host options
void CMinecraftApp::SetGameHostOption(eGameHostOption eVal,unsigned int uiVal)
{
SetGameHostOption(m_uiGameHostSettings,eVal,uiVal);
}
void CMinecraftApp::SetGameHostOption(unsigned int &uiHostSettings, eGameHostOption eVal, unsigned int uiVal)
{
switch(eVal)
{
case eGameHostOption_FriendsOfFriends:
if(uiVal!=0)
{
uiHostSettings|=GAME_HOST_OPTION_BITMASK_FRIENDSOFFRIENDS;
}
else
{
// off
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_FRIENDSOFFRIENDS;
}
break;
case eGameHostOption_Difficulty:
// clear the difficulty first
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_DIFFICULTY;
uiHostSettings|=(GAME_HOST_OPTION_BITMASK_DIFFICULTY&uiVal);
break;
case eGameHostOption_Gamertags:
if(uiVal!=0)
{
uiHostSettings|=GAME_HOST_OPTION_BITMASK_GAMERTAGS;
}
else
{
// off
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_GAMERTAGS;
}
break;
case eGameHostOption_GameType:
// clear the game type first
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_GAMETYPE;
uiHostSettings|=(GAME_HOST_OPTION_BITMASK_GAMETYPE&(uiVal<<4));
break;
case eGameHostOption_LevelType:
if(uiVal!=0)
{
uiHostSettings|=GAME_HOST_OPTION_BITMASK_LEVELTYPE;
}
else
{
// off
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_LEVELTYPE;
}
break;
case eGameHostOption_Structures:
if(uiVal!=0)
{
uiHostSettings|=GAME_HOST_OPTION_BITMASK_STRUCTURES;
}
else
{
// off
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_STRUCTURES;
}
break;
case eGameHostOption_BonusChest:
if(uiVal!=0)
{
uiHostSettings|=GAME_HOST_OPTION_BITMASK_BONUSCHEST;
}
else
{
// off
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_BONUSCHEST;
}
break;
case eGameHostOption_HasBeenInCreative:
if(uiVal!=0)
{
uiHostSettings|=GAME_HOST_OPTION_BITMASK_BEENINCREATIVE;
}
else
{
// off
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_BEENINCREATIVE;
}
break;
case eGameHostOption_PvP:
if(uiVal!=0)
{
uiHostSettings|=GAME_HOST_OPTION_BITMASK_PVP;
}
else
{
// off
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_PVP;
}
break;
case eGameHostOption_TrustPlayers:
if(uiVal!=0)
{
uiHostSettings|=GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS;
}
else
{
// off
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS;
}
break;
case eGameHostOption_TNT:
if(uiVal!=0)
{
uiHostSettings|=GAME_HOST_OPTION_BITMASK_TNT;
}
else
{
// off
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_TNT;
}
break;
case eGameHostOption_FireSpreads:
if(uiVal!=0)
{
uiHostSettings|=GAME_HOST_OPTION_BITMASK_FIRESPREADS;
}
else
{
// off
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_FIRESPREADS;
}
break;
case eGameHostOption_CheatsEnabled:
if(uiVal!=0)
{
uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTFLY;
uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTHUNGER;
uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE;
}
else
{
// off
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTFLY;
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTHUNGER;
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE;
}
break;
case eGameHostOption_HostCanFly:
if(uiVal!=0)
{
uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTFLY;
}
else
{
// off
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTFLY;
}
break;
case eGameHostOption_HostCanChangeHunger:
if(uiVal!=0)
{
uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTHUNGER;
}
else
{
// off
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTHUNGER;
}
break;
case eGameHostOption_HostCanBeInvisible:
if(uiVal!=0)
{
uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE;
}
else
{
// off
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE;
}
break;
case eGameHostOption_BedrockFog:
if(uiVal!=0)
{
uiHostSettings|=GAME_HOST_OPTION_BITMASK_BEDROCKFOG;
}
else
{
// off
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_BEDROCKFOG;
}
break;
case eGameHostOption_DisableSaving:
if(uiVal!=0)
{
uiHostSettings|=GAME_HOST_OPTION_BITMASK_DISABLESAVE;
}
else
{
// off
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_DISABLESAVE;
}
break;
case eGameHostOption_WasntSaveOwner:
if(uiVal!=0)
{
uiHostSettings|=GAME_HOST_OPTION_BITMASK_NOTOWNER;
}
else
{
// off
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_NOTOWNER;
}
break;
case eGameHostOption_MobGriefing:
if(uiVal!=1)
{
uiHostSettings |= GAME_HOST_OPTION_BITMASK_MOBGRIEFING;
}
else
{
// off
uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_MOBGRIEFING;
}
break;
case eGameHostOption_KeepInventory:
if(uiVal!=0)
{
uiHostSettings |= GAME_HOST_OPTION_BITMASK_KEEPINVENTORY;
}
else
{
// off
uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_KEEPINVENTORY;
}
break;
case eGameHostOption_DoMobSpawning:
if(uiVal!=1)
{
uiHostSettings |= GAME_HOST_OPTION_BITMASK_DOMOBSPAWNING;
}
else
{
// off
uiHostSettings &=~ GAME_HOST_OPTION_BITMASK_DOMOBSPAWNING;
}
break;
case eGameHostOption_DoMobLoot:
if(uiVal!=1)
{
uiHostSettings |= GAME_HOST_OPTION_BITMASK_DOMOBLOOT;
}
else
{
// off
uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DOMOBLOOT;
}
break;
case eGameHostOption_DoTileDrops:
if(uiVal!=1)
{
uiHostSettings |= GAME_HOST_OPTION_BITMASK_DOTILEDROPS;
}
else
{
// off
uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DOTILEDROPS;
}
break;
case eGameHostOption_NaturalRegeneration:
if(uiVal!=1)
{
uiHostSettings |= GAME_HOST_OPTION_BITMASK_NATURALREGEN;
}
else
{
// off
uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_NATURALREGEN;
}
break;
case eGameHostOption_DoDaylightCycle:
if(uiVal!=1)
{
uiHostSettings |= GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE;
}
else
{
// off
uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE;
}
break;
case eGameHostOption_WorldSize:
// clear the difficulty first
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_WORLDSIZE;
uiHostSettings|=(GAME_HOST_OPTION_BITMASK_WORLDSIZE & (uiVal<<GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT));
break;
case eGameHostOption_All:
uiHostSettings=uiVal;
break;
}
}
unsigned int CMinecraftApp::GetGameHostOption(eGameHostOption eVal)
{
return GetGameHostOption(m_uiGameHostSettings, eVal);
}
unsigned int CMinecraftApp::GetGameHostOption(unsigned int uiHostSettings, eGameHostOption eVal)
{
//unsigned int uiVal=0;
switch(eVal)
{
case eGameHostOption_FriendsOfFriends:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_FRIENDSOFFRIENDS);
break;
case eGameHostOption_Difficulty:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_DIFFICULTY);
break;
case eGameHostOption_Gamertags:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_GAMERTAGS);
break;
case eGameHostOption_GameType:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_GAMETYPE)>>4;
break;
case eGameHostOption_All:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_ALL);
break;
case eGameHostOption_Tutorial:
// special case - tutorial is offline, but we want the gamertag option, and set Easy mode, structures on, fire on, tnt on, pvp on, trust players on
return ((uiHostSettings&GAME_HOST_OPTION_BITMASK_GAMERTAGS)|
GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS|
GAME_HOST_OPTION_BITMASK_FIRESPREADS|
GAME_HOST_OPTION_BITMASK_TNT|
GAME_HOST_OPTION_BITMASK_PVP|
GAME_HOST_OPTION_BITMASK_STRUCTURES|1);
break;
case eGameHostOption_LevelType:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_LEVELTYPE);
break;
case eGameHostOption_Structures:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_STRUCTURES);
break;
case eGameHostOption_BonusChest:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_BONUSCHEST);
break;
case eGameHostOption_HasBeenInCreative:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_BEENINCREATIVE);
break;
case eGameHostOption_PvP:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_PVP);
break;
case eGameHostOption_TrustPlayers:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS);
break;
case eGameHostOption_TNT:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_TNT);
break;
case eGameHostOption_FireSpreads:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_FIRESPREADS);
break;
case eGameHostOption_CheatsEnabled:
return (uiHostSettings&(GAME_HOST_OPTION_BITMASK_HOSTFLY|GAME_HOST_OPTION_BITMASK_HOSTHUNGER|GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE));
break;
case eGameHostOption_HostCanFly:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_HOSTFLY);
break;
case eGameHostOption_HostCanChangeHunger:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_HOSTHUNGER);
break;
case eGameHostOption_HostCanBeInvisible:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE);
break;
case eGameHostOption_BedrockFog:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_BEDROCKFOG);
break;
case eGameHostOption_DisableSaving:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_DISABLESAVE);
break;
case eGameHostOption_WasntSaveOwner:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_NOTOWNER);
case eGameHostOption_WorldSize:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_WORLDSIZE) >> GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT;
case eGameHostOption_MobGriefing:
return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_MOBGRIEFING);
case eGameHostOption_KeepInventory:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_KEEPINVENTORY);
case eGameHostOption_DoMobSpawning:
return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DOMOBSPAWNING);
case eGameHostOption_DoMobLoot:
return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DOMOBLOOT);
case eGameHostOption_DoTileDrops:
return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DOTILEDROPS);
case eGameHostOption_NaturalRegeneration:
return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_NATURALREGEN);
case eGameHostOption_DoDaylightCycle:
return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE);
break;
}
return false;
}
bool CMinecraftApp::CanRecordStatsAndAchievements()
{
bool isTutorial = Minecraft::GetInstance() != NULL && Minecraft::GetInstance()->isTutorial();
// 4J Stu - All of these options give the host player some advantage, so should not allow achievements
return !(app.GetGameHostOption(eGameHostOption_HasBeenInCreative) ||
app.GetGameHostOption(eGameHostOption_HostCanBeInvisible) ||
app.GetGameHostOption(eGameHostOption_HostCanChangeHunger) ||
app.GetGameHostOption(eGameHostOption_HostCanFly) ||
app.GetGameHostOption(eGameHostOption_WasntSaveOwner) ||
!app.GetGameHostOption(eGameHostOption_MobGriefing) ||
app.GetGameHostOption(eGameHostOption_KeepInventory) ||
!app.GetGameHostOption(eGameHostOption_DoMobSpawning) ||
(!app.GetGameHostOption(eGameHostOption_DoDaylightCycle) && !isTutorial )
);
}
void CMinecraftApp::processSchematics(LevelChunk *levelChunk)
{
m_gameRules.processSchematics(levelChunk);
}
void CMinecraftApp::processSchematicsLighting(LevelChunk *levelChunk)
{
m_gameRules.processSchematicsLighting(levelChunk);
}
void CMinecraftApp::loadDefaultGameRules()
{
m_gameRules.loadDefaultGameRules();
}
void CMinecraftApp::setLevelGenerationOptions(LevelGenerationOptions *levelGen)
{
m_gameRules.setLevelGenerationOptions(levelGen);
}
LPCWSTR CMinecraftApp::GetGameRulesString(const wstring &key)
{
return m_gameRules.GetGameRulesString(key);
}
unsigned char CMinecraftApp::m_szPNG[8]=
{
137,80,78,71,13,10,26,10
};
#define PNG_TAG_tEXt 0x74455874
unsigned int CMinecraftApp::FromBigEndian(unsigned int uiValue)
{
#if defined(__PS3__) || defined(_XBOX)
// Keep it in big endian
return uiValue;
#else
unsigned int uiReturn = ( ( uiValue >> 24 ) & 0x000000ff ) |
( ( uiValue >> 8 ) & 0x0000ff00 ) |
( ( uiValue << 8 ) & 0x00ff0000 ) |
( ( uiValue << 24 ) & 0xff000000 );
return uiReturn;
#endif
}
void CMinecraftApp::GetImageTextData(PBYTE pbImageData, DWORD dwImageBytes,unsigned char *pszSeed,unsigned int &uiHostOptions,bool &bHostOptionsRead,DWORD &uiTexturePack)
{
unsigned char *ucPtr=pbImageData;
unsigned int uiCount=0;
unsigned int uiChunkLen;
unsigned int uiChunkType;
unsigned int uiCRC;
char szKeyword[80];
// check it's a png
for(int i=0;i<8;i++)
{
if(m_szPNG[i]!=ucPtr[i]) return;
}
uiCount+=8;
while(uiCount<dwImageBytes)
{
uiChunkLen=*(unsigned int *)&ucPtr[uiCount];
uiChunkLen=FromBigEndian(uiChunkLen);
uiCount+=sizeof(int);
uiChunkType=*(unsigned int *)&ucPtr[uiCount];
uiChunkType=FromBigEndian(uiChunkType);
uiCount+=sizeof(int);
if(uiChunkType==PNG_TAG_tEXt) // tEXt
{
// check that it's the 4J text
unsigned char *pszKeyword=&ucPtr[uiCount];
while(pszKeyword < ucPtr + uiCount + uiChunkLen)
{
ZeroMemory(szKeyword,80);
unsigned int uiKeywordC=0;
while(*pszKeyword!=0)
{
szKeyword[uiKeywordC++]=*pszKeyword;
pszKeyword++;
}
pszKeyword++;
if(strcmp(szKeyword,"4J_SEED")==0)
{
// read the seed value
unsigned int uiValueC=0;
while(*pszKeyword!=0 && (pszKeyword < ucPtr + uiCount + uiChunkLen) )
{
pszSeed[uiValueC++]=*pszKeyword;
pszKeyword++;
}
//memcpy(pszSeed,pszKeyword,uiChunkLen-8);
}
else if(strcmp(szKeyword,"4J_HOSTOPTIONS")==0)
{
bHostOptionsRead = true;
// read the host options value
unsigned int uiValueC=0;
unsigned char pszHostOptions[9]; // Hex representation of unsigned int
ZeroMemory(&pszHostOptions,9);
while(*pszKeyword!=0 && (pszKeyword < ucPtr + uiCount + uiChunkLen) && uiValueC < 8)
{
pszHostOptions[uiValueC++]=*pszKeyword;
pszKeyword++;
}
uiHostOptions = 0;
std::stringstream ss;
ss << pszHostOptions;
ss >> std::hex >> uiHostOptions;
}
else if(strcmp(szKeyword,"4J_TEXTUREPACK")==0)
{
// read the texture pack value
unsigned int uiValueC=0;
unsigned char pszTexturePack[9]; // Hex representation of unsigned int
ZeroMemory(&pszTexturePack,9);
while(*pszKeyword!=0 && (pszKeyword < ucPtr + uiCount + uiChunkLen) && uiValueC < 8)
{
pszTexturePack[uiValueC++]=*pszKeyword;
pszKeyword++;
}
std::stringstream ss;
ss << pszTexturePack;
ss >> std::hex >> uiTexturePack;
}
}
}
uiCount+=uiChunkLen;
uiCRC=*(unsigned int*)&ucPtr[uiCount];
uiCRC=FromBigEndian(uiCRC);
uiCount+=sizeof(int);
}
return;
}
unsigned int CMinecraftApp::CreateImageTextData(PBYTE bTextMetadata, int64_t seed, bool hasSeed, unsigned int uiHostOptions, unsigned int uiTexturePackId)
{
int iTextMetadataBytes = 0;
if(hasSeed)
{
strcpy((char *)bTextMetadata,"4J_SEED");
_i64toa_s(seed,(char *)&bTextMetadata[8],42,10);
// get the length
iTextMetadataBytes+=8;
while(bTextMetadata[iTextMetadataBytes]!=0) iTextMetadataBytes++;
++iTextMetadataBytes; // Add a null terminator at the end of the seed value
}
// Save the host options that this world was last played with
strcpy((char *)&bTextMetadata[iTextMetadataBytes],"4J_HOSTOPTIONS");
_itoa_s(uiHostOptions,(char *)&bTextMetadata[iTextMetadataBytes+15],9,16);
iTextMetadataBytes += 15;
while(bTextMetadata[iTextMetadataBytes]!=0) iTextMetadataBytes++;
++iTextMetadataBytes; // Add a null terminator at the end of the host options value
// Save the texture pack id
strcpy((char *)&bTextMetadata[iTextMetadataBytes],"4J_TEXTUREPACK");
_itoa_s(uiTexturePackId,(char *)&bTextMetadata[iTextMetadataBytes+15],9,16);
iTextMetadataBytes += 15;
while(bTextMetadata[iTextMetadataBytes]!=0) iTextMetadataBytes++;
return iTextMetadataBytes;
}
void CMinecraftApp::AddTerrainFeaturePosition(_eTerrainFeatureType eFeatureType,int x,int z)
{
// check we don't already have this in
for( FEATURE_DATA *pFeatureData : m_vTerrainFeatures )
{
if((pFeatureData->eTerrainFeature==eFeatureType) &&(pFeatureData->x==x) && (pFeatureData->z==z)) return;
}
FEATURE_DATA *pFeatureData= new FEATURE_DATA;
pFeatureData->eTerrainFeature=eFeatureType;
pFeatureData->x=x;
pFeatureData->z=z;
m_vTerrainFeatures.push_back(pFeatureData);
}
_eTerrainFeatureType CMinecraftApp::IsTerrainFeature(int x,int z)
{
for(FEATURE_DATA *pFeatureData : m_vTerrainFeatures )
{
if((pFeatureData->x==x) && (pFeatureData->z==z)) return pFeatureData->eTerrainFeature;
}
return eTerrainFeature_None;
}
bool CMinecraftApp::GetTerrainFeaturePosition(_eTerrainFeatureType eType,int *pX, int *pZ)
{
for ( const FEATURE_DATA *pFeatureData : m_vTerrainFeatures )
{
if(pFeatureData->eTerrainFeature==eType)
{
*pX=pFeatureData->x;
*pZ=pFeatureData->z;
return true;
}
}
return false;
}
void CMinecraftApp::ClearTerrainFeaturePosition()
{
FEATURE_DATA *pFeatureData;
while(m_vTerrainFeatures.size()>0)
{
pFeatureData = m_vTerrainFeatures.back();
m_vTerrainFeatures.pop_back();
delete pFeatureData;
}
}
void CMinecraftApp::UpdatePlayerInfo(BYTE networkSmallId, SHORT playerColourIndex, unsigned int playerGamePrivileges)
{
for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i)
{
if(m_playerColours[i]==networkSmallId)
{
m_playerColours[i] = 0;
m_playerGamePrivileges[i] = 0;
}
}
if(playerColourIndex >=0 && playerColourIndex < MINECRAFT_NET_MAX_PLAYERS)
{
m_playerColours[playerColourIndex] = networkSmallId;
m_playerGamePrivileges[playerColourIndex] = playerGamePrivileges;
}
}
short CMinecraftApp::GetPlayerColour(BYTE networkSmallId)
{
short index = -1;
for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i)
{
if(m_playerColours[i]==networkSmallId)
{
index = i;
break;
}
}
return index;
}
unsigned int CMinecraftApp::GetPlayerPrivileges(BYTE networkSmallId)
{
unsigned int privileges = 0;
for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i)
{
if(m_playerColours[i]==networkSmallId)
{
privileges = m_playerGamePrivileges[i];
break;
}
}
return privileges;
}
wstring CMinecraftApp::getEntityName(eINSTANCEOF type)
{
switch(type)
{
case eTYPE_WOLF:
return app.GetString(IDS_WOLF);
case eTYPE_CREEPER:
return app.GetString(IDS_CREEPER);
case eTYPE_SKELETON:
return app.GetString(IDS_SKELETON);
case eTYPE_SPIDER:
return app.GetString(IDS_SPIDER);
case eTYPE_ZOMBIE:
return app.GetString(IDS_ZOMBIE);
case eTYPE_PIGZOMBIE:
return app.GetString(IDS_PIGZOMBIE);
case eTYPE_ENDERMAN:
return app.GetString(IDS_ENDERMAN);
case eTYPE_SILVERFISH:
return app.GetString(IDS_SILVERFISH);
case eTYPE_CAVESPIDER:
return app.GetString(IDS_CAVE_SPIDER);
case eTYPE_GHAST:
return app.GetString(IDS_GHAST);
case eTYPE_SLIME:
return app.GetString(IDS_SLIME);
case eTYPE_ARROW:
return app.GetString(IDS_ITEM_ARROW);
case eTYPE_ENDERDRAGON:
return app.GetString(IDS_ENDERDRAGON);
case eTYPE_BLAZE:
return app.GetString(IDS_BLAZE);
case eTYPE_LAVASLIME:
return app.GetString(IDS_LAVA_SLIME);
// 4J-PB - fix for #107167 - Customer Encountered: TU12: Content: UI: There is no information what killed Player after being slain by Iron Golem.
case eTYPE_VILLAGERGOLEM:
return app.GetString(IDS_IRONGOLEM);
case eTYPE_HORSE:
return app.GetString(IDS_HORSE);
case eTYPE_WITCH:
return app.GetString(IDS_WITCH);
case eTYPE_WITHERBOSS:
return app.GetString(IDS_WITHER);
case eTYPE_BAT:
return app.GetString(IDS_BAT);
};
return L"";
}
DWORD CMinecraftApp::m_dwContentTypeA[e_Marketplace_MAX]=
{
XMARKETPLACE_OFFERING_TYPE_CONTENT, // e_DLC_SkinPack, e_DLC_TexturePacks, e_DLC_MashupPacks
#ifndef _XBOX_ONE
XMARKETPLACE_OFFERING_TYPE_THEME, // e_DLC_Themes
XMARKETPLACE_OFFERING_TYPE_AVATARITEM, // e_DLC_AvatarItems
XMARKETPLACE_OFFERING_TYPE_TILE, // e_DLC_Gamerpics
#endif
};
unsigned int CMinecraftApp::AddDLCRequest(eDLCMarketplaceType eType, bool bPromote)
{
// lock access
EnterCriticalSection(&csDLCDownloadQueue);
// If it's already in there, promote it to the top of the list
int iPosition=0;
for( DLCRequest *pCurrent : m_DLCDownloadQueue )
{
if(pCurrent->dwType==m_dwContentTypeA[eType])
{
// already got this in the list
if(pCurrent->eState == e_DLC_ContentState_Retrieving || pCurrent->eState == e_DLC_ContentState_Retrieved)
{
// already retrieved this
LeaveCriticalSection(&csDLCDownloadQueue);
return 0;
}
else
{
// promote
if(bPromote)
{
m_DLCDownloadQueue.erase(m_DLCDownloadQueue.begin()+iPosition);
m_DLCDownloadQueue.insert(m_DLCDownloadQueue.begin(),pCurrent);
}
LeaveCriticalSection(&csDLCDownloadQueue);
return 0;
}
}
iPosition++;
}
DLCRequest *pDLCreq = new DLCRequest;
pDLCreq->dwType=m_dwContentTypeA[eType];
pDLCreq->eState=e_DLC_ContentState_Idle;
m_DLCDownloadQueue.push_back(pDLCreq);
m_bAllDLCContentRetrieved=false;
LeaveCriticalSection(&csDLCDownloadQueue);
app.DebugPrintf("[Consoles_App] Added DLC request.\n");
return 1;
}
unsigned int CMinecraftApp::AddTMSPPFileTypeRequest(eDLCContentType eType, bool bPromote)
{
#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__)
// lock access
EnterCriticalSection(&csTMSPPDownloadQueue);
// If it's already in there, promote it to the top of the list
int iPosition=0;
//ignore promoting for now
/*
bool bPromoted=false;
for ( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue )
{
TMSPPRequest *pCurrent = *it;
if(pCurrent->eType==eType)
{
if(!(pCurrent->eState == e_TMS_ContentState_Retrieving || pCurrent->eState == e_TMS_ContentState_Retrieved))
{
// promote
if(bPromote)
{
m_TMSPPDownloadQueue.erase(m_TMSPPDownloadQueue.begin()+iPosition);
m_TMSPPDownloadQueue.insert(m_TMSPPDownloadQueue.begin(),pCurrent);
bPromoted=true;
}
}
}
iPosition++;
}
if(bPromoted)
{
// re-ordered the list, so leave now
LeaveCriticalSection(&csTMSPPDownloadQueue);
return 0;
}
*/
// special case for data files (not image files)
if(eType==e_DLC_TexturePackData)
{
int iCount=GetDLCInfoFullOffersCount();
for(int i=0;i<iCount;i++)
{
DLC_INFO *pDLC=GetDLCInfoFullOffer(i);
if((pDLC->eDLCType==e_DLC_TexturePacks) || (pDLC->eDLCType==e_DLC_MashupPacks))
{
// first check if the image is already in the memory textures, since we might be loading some from the Title Update partition
if(pDLC->wchDataFile[0]!=0)
{
//WCHAR *cString = pDLC->wchDataFile;
// 4J-PB - shouldn't check this here - let the TMS files override it, so if they are on TMS, we'll take them first
//int iIndex = app.GetLocalTMSFileIndex(pDLC->wchDataFile,true);
//if(iIndex!=-1)
{
bool bPresent = app.IsFileInTPD(pDLC->iConfig);
if(!bPresent)
{
// this may already be present in the vector because of a previous trial/full offer
bool bAlreadyInQueue=false;
for( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue )
{
if(wcscmp(pDLC->wchDataFile,pCurrent->wchFilename)==0)
{
bAlreadyInQueue=true;
break;
}
}
if(!bAlreadyInQueue)
{
TMSPPRequest *pTMSPPreq = new TMSPPRequest;
pTMSPPreq->CallbackFunc=&CMinecraftApp::TMSPPFileReturned;
pTMSPPreq->lpCallbackParam=this;
pTMSPPreq->eStorageFacility=C4JStorage::eGlobalStorage_Title;
pTMSPPreq->eFileTypeVal=C4JStorage::TMS_FILETYPE_BINARY;
memcpy(pTMSPPreq->wchFilename,pDLC->wchDataFile,sizeof(WCHAR)*MAX_BANNERNAME_SIZE);
pTMSPPreq->eType=e_DLC_TexturePackData;
pTMSPPreq->eState=e_TMS_ContentState_Queued;
m_bAllTMSContentRetrieved=false;
m_TMSPPDownloadQueue.push_back(pTMSPPreq);
}
}
else
{
app.DebugPrintf("Texture data already present in the TPD\n");
}
}
}
}
}
}
else
{ // for all the files of type eType, add them to the download list
// run through the trial offers first, then the full offers. Any duplicates won't be added to the download queue
int iCount;
#ifdef _XBOX // Only trial offers on Xbox 360
iCount=GetDLCInfoTrialOffersCount();
for(int i=0;i<iCount;i++)
{
DLC_INFO *pDLC=GetDLCInfoTrialOffer(i);
// is this the right type?
if(pDLC->eDLCType==eType)
{
WCHAR *cString = pDLC->wchBanner;
// 4J-PB - shouldn't check this here - let the TMS files override it, so if they are on TMS, we'll take them first
// is the file in the TMS XZP?
//int iIndex = app.GetLocalTMSFileIndex(cString,true);
//if(iIndex!=-1)
{
bool bPresent = app.IsFileInMemoryTextures(cString);
if(!bPresent) // retrieve it from TMSPP
{
bool bAlreadyInQueue=false;
for( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue )
{
if(wcscmp(pDLC->wchBanner,pCurrent->wchFilename)==0)
{
bAlreadyInQueue=true;
break;
}
}
if(!bAlreadyInQueue)
{
TMSPPRequest *pTMSPPreq = new TMSPPRequest;
pTMSPPreq->CallbackFunc=&CMinecraftApp::TMSPPFileReturned;
pTMSPPreq->lpCallbackParam=this;
pTMSPPreq->eStorageFacility=C4JStorage::eGlobalStorage_Title;
pTMSPPreq->eFileTypeVal=C4JStorage::TMS_FILETYPE_BINARY;
//wcstombs(pTMSPPreq->szFilename,pDLC->wchBanner,MAX_TMSFILENAME_SIZE);
memcpy(pTMSPPreq->wchFilename,pDLC->wchBanner,sizeof(WCHAR)*MAX_BANNERNAME_SIZE);
pTMSPPreq->eType=eType;
pTMSPPreq->eState=e_TMS_ContentState_Queued;
m_bAllTMSContentRetrieved=false;
m_TMSPPDownloadQueue.push_back(pTMSPPreq);
app.DebugPrintf("===m_TMSPPDownloadQueue Adding %ls, q size is %d\n",pTMSPPreq->wchFilename,m_TMSPPDownloadQueue.size());
}
}
}
}
}
#endif
// and the full offers
iCount=GetDLCInfoFullOffersCount();
for(int i=0;i<iCount;i++)
{
DLC_INFO *pDLC=GetDLCInfoFullOffer(i);
//if(wcscmp(pDLC->wchType,wchDLCTypeNames[eType])==0)
if(pDLC->eDLCType==eType)
{
// first check if the image is already in the memory textures, since we might be loading some from the Title Update partition
WCHAR *cString = pDLC->wchBanner;
// 4J-PB - shouldn't check this here - let the TMS files override it, so if they are on TMS, we'll take them first
//int iIndex = app.GetLocalTMSFileIndex(cString,true);
//if(iIndex!=-1)
{
bool bPresent = app.IsFileInMemoryTextures(cString);
if(!bPresent)
{
// this may already be present in the vector because of a previous trial/full offer
bool bAlreadyInQueue=false;
for( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue )
{
if(wcscmp(pDLC->wchBanner,pCurrent->wchFilename)==0)
{
bAlreadyInQueue=true;
break;
}
}
if(!bAlreadyInQueue)
{
//app.DebugPrintf("Adding a request to the TMSPP download queue - %ls\n",pDLC->wchBanner);
TMSPPRequest *pTMSPPreq = new TMSPPRequest;
ZeroMemory(pTMSPPreq,sizeof(TMSPPRequest));
pTMSPPreq->CallbackFunc=&CMinecraftApp::TMSPPFileReturned;
pTMSPPreq->lpCallbackParam=this;
// 4J-PB - testing for now
//pTMSPPreq->eStorageFacility=C4JStorage::eGlobalStorage_TitleUser;
pTMSPPreq->eStorageFacility=C4JStorage::eGlobalStorage_Title;
pTMSPPreq->eFileTypeVal=C4JStorage::TMS_FILETYPE_BINARY;
//wcstombs(pTMSPPreq->szFilename,pDLC->wchBanner,MAX_TMSFILENAME_SIZE);
memcpy(pTMSPPreq->wchFilename,pDLC->wchBanner,sizeof(WCHAR)*MAX_BANNERNAME_SIZE);
pTMSPPreq->eType=eType;
pTMSPPreq->eState=e_TMS_ContentState_Queued;
m_bAllTMSContentRetrieved=false;
m_TMSPPDownloadQueue.push_back(pTMSPPreq);
app.DebugPrintf("===m_TMSPPDownloadQueue Adding %ls, q size is %d\n",pTMSPPreq->wchFilename,m_TMSPPDownloadQueue.size());
}
}
}
}
}
}
LeaveCriticalSection(&csTMSPPDownloadQueue);
#endif
return 1;
}
bool CMinecraftApp::CheckTMSDLCCanStop()
{
EnterCriticalSection(&csTMSPPDownloadQueue);
for( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue )
{
if(pCurrent->eState==e_TMS_ContentState_Retrieving)
{
LeaveCriticalSection(&csTMSPPDownloadQueue);
return false;
}
}
LeaveCriticalSection(&csTMSPPDownloadQueue);
return true;
}
bool CMinecraftApp::RetrieveNextDLCContent()
{
// If there's already a retrieve in progress, quit
// we may have re-ordered the list, so need to check every item
// is there a primary player and a network connection?
int primPad = ProfileManager.GetPrimaryPad();
if ( primPad == -1 || !ProfileManager.IsSignedInLive(primPad) )
{
return true; // 4J-JEV: We need to wait until the primary player is online.
}
EnterCriticalSection(&csDLCDownloadQueue);
for( const DLCRequest* pCurrent : m_DLCDownloadQueue )
{
if(pCurrent->eState==e_DLC_ContentState_Retrieving)
{
LeaveCriticalSection(&csDLCDownloadQueue);
return true;
}
}
// Now look for the next retrieval
for( DLCRequest *pCurrent : m_DLCDownloadQueue )
{
if(pCurrent->eState==e_DLC_ContentState_Idle)
{
#ifdef _DEBUG
app.DebugPrintf("RetrieveNextDLCContent - type = %d\n",pCurrent->dwType);
#endif
C4JStorage::EDLCStatus status = StorageManager.GetDLCOffers(ProfileManager.GetPrimaryPad(), &CMinecraftApp::DLCOffersReturned, this, pCurrent->dwType);
if(status==C4JStorage::EDLC_Pending)
{
pCurrent->eState=e_DLC_ContentState_Retrieving;
}
else
{
// no content of this type, or some other problem
app.DebugPrintf("RetrieveNextDLCContent - PROBLEM\n");
pCurrent->eState=e_DLC_ContentState_Retrieved;
}
LeaveCriticalSection(&csDLCDownloadQueue);
return true;
}
}
LeaveCriticalSection(&csDLCDownloadQueue);
app.DebugPrintf("[Consoles_App] Finished downloading dlc content.\n");
return false;
}
#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__)
#ifdef _XBOX_ONE
int CMinecraftApp::TMSPPFileReturned(LPVOID pParam,int iPad,int iUserData,LPVOID lpvData, WCHAR* wchFilename)
{
C4JStorage::PTMSPP_FILEDATA pFileData=(C4JStorage::PTMSPP_FILEDATA)lpvData;
#else
int CMinecraftApp::TMSPPFileReturned(LPVOID pParam,int iPad,int iUserData,C4JStorage::PTMSPP_FILEDATA pFileData, LPCSTR szFilename)
{
#endif
CMinecraftApp* pClass = (CMinecraftApp *) pParam;
// find the right one in the vector
EnterCriticalSection(&pClass->csTMSPPDownloadQueue);
for( TMSPPRequest *pCurrent : pClass->m_TMSPPDownloadQueue )
{
#if defined(_XBOX) || defined(_WINDOWS64)
char szFile[MAX_TMSFILENAME_SIZE];
wcstombs(szFile,pCurrent->wchFilename,MAX_TMSFILENAME_SIZE);
if(strcmp(szFilename,szFile)==0)
#elif _XBOX_ONE
if(wcscmp(wchFilename,pCurrent->wchFilename)==0)
#endif
{
// set this to retrieved whether it found it or not
pCurrent->eState=e_TMS_ContentState_Retrieved;
if(pFileData!=NULL)
{
#ifdef _XBOX_ONE
switch(pCurrent->eType)
{
case e_DLC_TexturePackData:
{
// 4J-PB - we need to allocate memory for the file data and copy into it, since the current data is a reference into the blob download memory
PBYTE pbData = new BYTE [pFileData->dwSize];
memcpy(pbData,pFileData->pbData,pFileData->dwSize);
pClass->m_vTMSPPData.push_back(pbData);
app.DebugPrintf("Got texturepack data\n");
// get the config value for the texture pack
int iConfig=app.GetTPConfigVal(pCurrent->wchFilename);
app.AddMemoryTPDFile(iConfig, pbData, pFileData->dwSize);
}
break;
default:
// 4J-PB - check the data is an image
if(pFileData->pbData[0]==0x89)
{
// 4J-PB - we need to allocate memory for the file data and copy into it, since the current data is a reference into the blob download memory
PBYTE pbData = new BYTE [pFileData->dwSize];
memcpy(pbData,pFileData->pbData,pFileData->dwSize);
pClass->m_vTMSPPData.push_back(pbData);
app.DebugPrintf("Got image data - %ls\n",pCurrent->wchFilename);
app.AddMemoryTextureFile(pCurrent->wchFilename, pbData, pFileData->dwSize);
}
else
{
app.DebugPrintf("Got image data, but it's not a png - %ls\n",pCurrent->wchFilename);
}
break;
}
#else
switch(pCurrent->eType)
{
case e_DLC_TexturePackData:
{
app.DebugPrintf("--- Got texturepack data %ls\n",pCurrent->wchFilename);
// get the config value for the texture pack
int iConfig=app.GetTPConfigVal(pCurrent->wchFilename);
app.AddMemoryTPDFile(iConfig, pFileData->pbData, pFileData->dwSize);
}
break;
default:
app.DebugPrintf("--- Got image data - %ls\n",pCurrent->wchFilename);
app.AddMemoryTextureFile(pCurrent->wchFilename, pFileData->pbData, pFileData->dwSize);
break;
}
#endif
}
else
{
#ifdef _XBOX_ONE
app.DebugPrintf("TMSImageReturned failed (%ls)...\n",wchFilename);
#else
app.DebugPrintf("TMSImageReturned failed (%s)...\n",szFilename);
#endif
}
break;
}
}
LeaveCriticalSection(&pClass->csTMSPPDownloadQueue);
return 0;
}
#endif
bool CMinecraftApp::RetrieveNextTMSPPContent()
{
#if defined _XBOX || defined _XBOX_ONE
// If there's already a retrieve in progress, quit
// we may have re-ordered the list, so need to check every item
// is there a primary player and a network connection?
if(ProfileManager.GetPrimaryPad()==-1) return false;
if(ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad())==false) return false;
for( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue )
{
TMSPPRequest *pCurrent = *it;
if(pCurrent->eState==e_TMS_ContentState_Retrieving)
{
app.DebugPrintf(".");
LeaveCriticalSection(&csTMSPPDownloadQueue);
return true;
}
}
// Now look for the next retrieval
for( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue )
{
TMSPPRequest *pCurrent = *it;
if(pCurrent->eState==e_TMS_ContentState_Queued)
{
// 4J-PB - the file may be in the local TMS files, but try to retrieve it from the remote TMS in case it's been changed. If it's not in the list of TMS files, this will
// return right away with a ETMSStatus_Fail_ReadDetailsNotRetrieved
#ifdef _XBOX
char szFilename[MAX_TMSFILENAME_SIZE];
wcstombs(szFilename,pCurrent->wchFilename,MAX_TMSFILENAME_SIZE);
app.DebugPrintf("\nRetrieveNextTMSPPContent - type = %d, %s\n",pCurrent->eType,szFilename);
C4JStorage::ETMSStatus status=StorageManager.TMSPP_ReadFile(ProfileManager.GetPrimaryPad(),pCurrent->eStorageFacility,pCurrent->eFileTypeVal,szFilename,pCurrent->CallbackFunc,this);
switch(status)
{
case C4JStorage::ETMSStatus_Pending:
pCurrent->eState=e_TMS_ContentState_Retrieving;
break;
case C4JStorage::ETMSStatus_Idle:
pCurrent->eState=e_TMS_ContentState_Retrieved;
break;
case C4JStorage::ETMSStatus_Fail_ReadInProgress:
case C4JStorage::ETMSStatus_ReadInProgress:
pCurrent->eState=e_TMS_ContentState_Retrieving;
if(pCurrent->eState==C4JStorage::ETMSStatus_Fail_ReadInProgress)
{
app.DebugPrintf("TMSPP_ReadFile failed - read in progress\n");
Sleep(50);
LeaveCriticalSection(&csTMSPPDownloadQueue);
return false;
}
break;
default:
pCurrent->eState=e_TMS_ContentState_Retrieved;
break;
}
#else
eTitleStorageState status;
app.DebugPrintf("RetrieveNextTMSPPContent - type = %d, %ls\n",pCurrent->eType,pCurrent->wchFilename);
//eTitleStorageState status=StorageManager.TMSPP_ReadFile(ProfileManager.GetPrimaryPad(),pCurrent->eStorageFacility,pCurrent->eFileTypeVal,pCurrent->wchFilename,pCurrent->CallbackFunc,this,0);
if(0)//wcscmp(pCurrent->wchFilename,L"TP01.png")==0)
{
// TP01 fails because the blob size returned is bigger than the global metadata says it should be
status=eTitleStorage_readerror;
}
else
{
status=StorageManager.TMSPP_ReadFile(ProfileManager.GetPrimaryPad(),pCurrent->eStorageFacility,pCurrent->eFileTypeVal,pCurrent->wchFilename,pCurrent->CallbackFunc,this,0);
}
switch(status)
{
case eTitleStorage_pending:
pCurrent->eState=e_TMS_ContentState_Retrieving;
break;
case eTitleStorage_idle:
pCurrent->eState=e_TMS_ContentState_Retrieved;
break;
case eTitleStorage_busy:
// try again next time
{
app.DebugPrintf("@@@@@@@@@@@@@@@@@ TMSPP_ReadFile failed - busy (probably reading already)\n");
Sleep(50);
LeaveCriticalSection(&csTMSPPDownloadQueue);
return false;
}
break;
default:
pCurrent->eState=e_TMS_ContentState_Retrieved;
break;
}
#endif
LeaveCriticalSection(&csTMSPPDownloadQueue);
return true;
}
}
LeaveCriticalSection(&csTMSPPDownloadQueue);
#endif
return false;
}
void CMinecraftApp::TickDLCOffersRetrieved()
{
if(!m_bAllDLCContentRetrieved)
{
if (!app.RetrieveNextDLCContent())
{
app.DebugPrintf("[Consoles_App] All content retrieved.\n");
m_bAllDLCContentRetrieved=true;
}
}
}
void CMinecraftApp::ClearAndResetDLCDownloadQueue()
{
app.DebugPrintf("[Consoles_App] Clear and reset download queue.\n");
int iPosition=0;
EnterCriticalSection(&csTMSPPDownloadQueue);
for( DLCRequest *pCurrent : m_DLCDownloadQueue )
{
if ( pCurrent )
delete pCurrent;
iPosition++;
}
m_DLCDownloadQueue.clear();
m_bAllDLCContentRetrieved=true;
LeaveCriticalSection(&csTMSPPDownloadQueue);
}
void CMinecraftApp::TickTMSPPFilesRetrieved()
{
if(m_bTickTMSDLCFiles && !m_bAllTMSContentRetrieved)
{
if(app.RetrieveNextTMSPPContent()==false)
{
m_bAllTMSContentRetrieved=true;
}
}
}
void CMinecraftApp::ClearTMSPPFilesRetrieved()
{
int iPosition=0;
EnterCriticalSection(&csTMSPPDownloadQueue);
for ( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue )
{
if ( pCurrent )
delete pCurrent;
iPosition++;
}
m_TMSPPDownloadQueue.clear();
m_bAllTMSContentRetrieved=true;
LeaveCriticalSection(&csTMSPPDownloadQueue);
}
int CMinecraftApp::DLCOffersReturned(void *pParam, int iOfferC, DWORD dwType, int iPad)
{
CMinecraftApp* pClass = (CMinecraftApp *) pParam;
// find the right one in the vector
EnterCriticalSection(&pClass->csTMSPPDownloadQueue);
for( DLCRequest *pCurrent : pClass->m_DLCDownloadQueue )
{
// avatar items are coming back as type Content, so we can't trust the type setting
if(pCurrent->dwType==dwType)
{
pClass->m_iDLCOfferC = iOfferC;
app.DebugPrintf("DLCOffersReturned - type %d, count %d - setting to retrieved\n",dwType,iOfferC);
pCurrent->eState=e_DLC_ContentState_Retrieved;
break;
}
}
LeaveCriticalSection(&pClass->csTMSPPDownloadQueue);
return 0;
}
eDLCContentType CMinecraftApp::Find_eDLCContentType(DWORD dwType)
{
for(int i=0;i<e_DLC_MAX;i++)
{
if(m_dwContentTypeA[i]==dwType)
{
return (eDLCContentType)i;
}
}
return (eDLCContentType)0;
}
bool CMinecraftApp::DLCContentRetrieved(eDLCMarketplaceType eType)
{
// If there's already a retrieve in progress, quit
// we may have re-ordered the list, so need to check every item
EnterCriticalSection(&csDLCDownloadQueue);
for( DLCRequest *pCurrent : m_DLCDownloadQueue )
{
if((pCurrent->dwType==m_dwContentTypeA[eType]) && (pCurrent->eState==e_DLC_ContentState_Retrieved))
{
LeaveCriticalSection(&csDLCDownloadQueue);
return true;
}
}
LeaveCriticalSection(&csDLCDownloadQueue);
return false;
}
void CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, SKIN_BOX *SkinBoxA, DWORD dwSkinBoxC)
{
EntityRenderer *renderer = EntityRenderDispatcher::instance->getRenderer(eTYPE_PLAYER);
Model *pModel = renderer->getModel();
vector<ModelPart *> *pvModelPart = new vector<ModelPart *>;
vector<SKIN_BOX *> *pvSkinBoxes = new vector<SKIN_BOX *>;
EnterCriticalSection( &csAdditionalModelParts );
EnterCriticalSection( &csAdditionalSkinBoxes );
app.DebugPrintf("*** SetAdditionalSkinBoxes - Inserting model parts for skin %d from array of Skin Boxes\n",dwSkinID&0x0FFFFFFF);
// convert the skin boxes into model parts, and add to the humanoid model
for(unsigned int i=0;i<dwSkinBoxC;i++)
{
if(pModel)
{
ModelPart *pModelPart=pModel->AddOrRetrievePart(&SkinBoxA[i]);
pvModelPart->push_back(pModelPart);
pvSkinBoxes->push_back(&SkinBoxA[i]);
}
}
m_AdditionalModelParts.insert( std::pair<DWORD, vector<ModelPart *> *>(dwSkinID, pvModelPart) );
m_AdditionalSkinBoxes.insert( std::pair<DWORD, vector<SKIN_BOX *> *>(dwSkinID, pvSkinBoxes) );
LeaveCriticalSection( &csAdditionalSkinBoxes );
LeaveCriticalSection( &csAdditionalModelParts );
}
vector<ModelPart *> * CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, vector<SKIN_BOX *> *pvSkinBoxA)
{
EntityRenderer *renderer = EntityRenderDispatcher::instance->getRenderer(eTYPE_PLAYER);
Model *pModel = renderer->getModel();
vector<ModelPart *> *pvModelPart = new vector<ModelPart *>;
EnterCriticalSection( &csAdditionalModelParts );
EnterCriticalSection( &csAdditionalSkinBoxes );
app.DebugPrintf("*** SetAdditionalSkinBoxes - Inserting model parts for skin %d from array of Skin Boxes\n",dwSkinID&0x0FFFFFFF);
// convert the skin boxes into model parts, and add to the humanoid model
for( auto& it : *pvSkinBoxA )
{
if(pModel)
{
ModelPart *pModelPart=pModel->AddOrRetrievePart(it);
pvModelPart->push_back(pModelPart);
}
}
m_AdditionalModelParts.emplace(dwSkinID, pvModelPart);
m_AdditionalSkinBoxes.emplace(dwSkinID, pvSkinBoxA);
LeaveCriticalSection( &csAdditionalSkinBoxes );
LeaveCriticalSection( &csAdditionalModelParts );
return pvModelPart;
}
vector<ModelPart *> *CMinecraftApp::GetAdditionalModelParts(DWORD dwSkinID)
{
EnterCriticalSection( &csAdditionalModelParts );
vector<ModelPart *> *pvModelParts=NULL;
if(m_AdditionalModelParts.size()>0)
{
auto it = m_AdditionalModelParts.find(dwSkinID);
if(it!=m_AdditionalModelParts.end())
{
pvModelParts = (*it).second;
}
}
LeaveCriticalSection( &csAdditionalModelParts );
return pvModelParts;
}
vector<SKIN_BOX *> *CMinecraftApp::GetAdditionalSkinBoxes(DWORD dwSkinID)
{
EnterCriticalSection( &csAdditionalSkinBoxes );
vector<SKIN_BOX *> *pvSkinBoxes=NULL;
if(m_AdditionalSkinBoxes.size()>0)
{
auto it = m_AdditionalSkinBoxes.find(dwSkinID);
if(it!=m_AdditionalSkinBoxes.end())
{
pvSkinBoxes = (*it).second;
}
}
LeaveCriticalSection( &csAdditionalSkinBoxes );
return pvSkinBoxes;
}
unsigned int CMinecraftApp::GetAnimOverrideBitmask(DWORD dwSkinID)
{
EnterCriticalSection( &csAnimOverrideBitmask );
unsigned int uiAnimOverrideBitmask=0L;
if(m_AnimOverrides.size()>0)
{
auto it = m_AnimOverrides.find(dwSkinID);
if(it!=m_AnimOverrides.end())
{
uiAnimOverrideBitmask = (*it).second;
}
}
LeaveCriticalSection( &csAnimOverrideBitmask );
return uiAnimOverrideBitmask;
}
void CMinecraftApp::SetAnimOverrideBitmask(DWORD dwSkinID,unsigned int uiAnimOverrideBitmask)
{
// Make thread safe
EnterCriticalSection( &csAnimOverrideBitmask );
if(m_AnimOverrides.size()>0)
{
auto it = m_AnimOverrides.find(dwSkinID);
if(it!=m_AnimOverrides.end())
{
LeaveCriticalSection( &csAnimOverrideBitmask );
return; // already in here
}
}
m_AnimOverrides.insert( std::pair<DWORD, unsigned long>(dwSkinID, uiAnimOverrideBitmask) );
LeaveCriticalSection( &csAnimOverrideBitmask );
}
DWORD CMinecraftApp::getSkinIdFromPath(const wstring &skin)
{
bool dlcSkin = false;
unsigned int skinId = 0;
if(skin.size() >= 14)
{
dlcSkin = skin.substr(0,3).compare(L"dlc") == 0;
wstring skinValue = skin.substr(7,skin.size());
skinValue = skinValue.substr(0,skinValue.find_first_of(L'.'));
std::wstringstream ss;
// 4J Stu - dlc skins are numbered using decimal to make it easier for artists/people to number manually
// Everything else is numbered using hex
if(dlcSkin)
ss << std::dec << skinValue.c_str();
else
ss << std::hex << skinValue.c_str();
ss >> skinId;
skinId = MAKE_SKIN_BITMASK(dlcSkin, skinId);
}
return skinId;
}
wstring CMinecraftApp::getSkinPathFromId(DWORD skinId)
{
// 4J Stu - This function maps the encoded DWORD we store in the player profile
// to a filename that is stored as a memory texture and shared between systems in game
wchar_t chars[256];
if( GET_IS_DLC_SKIN_FROM_BITMASK(skinId) )
{
// 4J Stu - DLC skins are numbered using decimal rather than hex to make it easier to number manually
swprintf(chars, 256, L"dlcskin%08d.png", GET_DLC_SKIN_ID_FROM_BITMASK(skinId));
}
else
{
DWORD ugcSkinIndex = GET_UGC_SKIN_ID_FROM_BITMASK(skinId);
DWORD defaultSkinIndex = GET_DEFAULT_SKIN_ID_FROM_BITMASK(skinId);
if( ugcSkinIndex == 0 )
{
swprintf(chars, 256, L"defskin%08X.png",defaultSkinIndex);
}
else
{
swprintf(chars, 256, L"ugcskin%08X.png",ugcSkinIndex);
}
}
return chars;
}
int CMinecraftApp::TexturePackDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
{
#if defined __PSVITA__ || defined __PS3__ || defined __ORBIS__
if(result==C4JStorage::EMessage_ResultAccept)
{
Minecraft *pMinecraft = Minecraft::GetInstance();
if( pMinecraft->skins->selectTexturePackById(app.GetRequiredTexturePackID()) )
{
// it's been installed already
}
else
{
// we need to enable background downloading for the DLC
XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW);
SONYDLC *pSONYDLCInfo=app.GetSONYDLCInfo(app.GetRequiredTexturePackID());
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);
}
}
}
}
}
else
{
app.DebugPrintf("Continuing without installing texture pack\n");
}
#endif
#ifdef _XBOX
if(result!=C4JStorage::EMessage_Cancelled)
{
if(app.GetRequiredTexturePackID()!=0)
{
// we need to enable background downloading for the DLC
XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW);
ULONGLONG ullOfferID_Full;
ULONGLONG ullIndexA[1];
app.GetDLCFullOfferIDForPackID(app.GetRequiredTexturePackID(),&ullOfferID_Full);
if( result==C4JStorage::EMessage_ResultAccept ) // Full version
{
ullIndexA[0]=ullOfferID_Full;
StorageManager.InstallOffer(1,ullIndexA,NULL,NULL);
}
else // trial version
{
DLC_INFO *pDLCInfo=app.GetDLCInfoForFullOfferID(ullOfferID_Full);
ullIndexA[0]=pDLCInfo->ullOfferID_Trial;
StorageManager.InstallOffer(1,ullIndexA,NULL,NULL);
}
}
}
#endif
return 0;
}
int CMinecraftApp::getArchiveFileSize(const wstring &filename)
{
TexturePack *tPack = NULL;
Minecraft *pMinecraft = Minecraft::GetInstance();
if(pMinecraft && pMinecraft->skins) tPack = pMinecraft->skins->getSelected();
if(tPack && tPack->hasData() && tPack->getArchiveFile() && tPack->getArchiveFile()->hasFile(filename))
{
return tPack->getArchiveFile()->getFileSize(filename);
}
else return m_mediaArchive->getFileSize(filename);
}
bool CMinecraftApp::hasArchiveFile(const wstring &filename)
{
TexturePack *tPack = NULL;
Minecraft *pMinecraft = Minecraft::GetInstance();
if(pMinecraft && pMinecraft->skins) tPack = pMinecraft->skins->getSelected();
if(tPack && tPack->hasData() && tPack->getArchiveFile() && tPack->getArchiveFile()->hasFile(filename)) return true;
else return m_mediaArchive->hasFile(filename);
}
byteArray CMinecraftApp::getArchiveFile(const wstring &filename)
{
TexturePack *tPack = NULL;
Minecraft *pMinecraft = Minecraft::GetInstance();
if(pMinecraft && pMinecraft->skins) tPack = pMinecraft->skins->getSelected();
if(tPack && tPack->hasData() && tPack->getArchiveFile() && tPack->getArchiveFile()->hasFile(filename))
{
return tPack->getArchiveFile()->getFile(filename);
}
else return m_mediaArchive->getFile(filename);
}
// DLC
#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__)
int CMinecraftApp::GetDLCInfoCount()
{
return (int)DLCInfo.size();
}
#elif defined _XBOX_ONE
int CMinecraftApp::GetDLCInfoTrialOffersCount()
{
return 0;
}
int CMinecraftApp::GetDLCInfoFullOffersCount()
{
return (int)DLCInfo_Full.size();
}
#else
int CMinecraftApp::GetDLCInfoTrialOffersCount()
{
return (int)DLCInfo_Trial.size();
}
int CMinecraftApp::GetDLCInfoFullOffersCount()
{
return (int)DLCInfo_Full.size();
}
#endif
int CMinecraftApp::GetDLCInfoTexturesOffersCount()
{
return (int)DLCTextures_PackID.size();
}
// AUTOSAVE
void CMinecraftApp::SetAutosaveTimerTime(void)
{
#if defined(_XBOX_ONE) || defined(__ORBIS__)
m_uiAutosaveTimer= GetTickCount()+1000*60;
#else
m_uiAutosaveTimer= GetTickCount()+GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_Autosave)*1000*60*15;
#endif
}// value x 15 to get mins, x60 for secs
bool CMinecraftApp::AutosaveDue(void)
{
return (GetTickCount()>m_uiAutosaveTimer);
}
unsigned int CMinecraftApp::SecondsToAutosave()
{
return (m_uiAutosaveTimer - GetTickCount() ) / 1000;
}
void CMinecraftApp::SetTrialTimerStart(void)
{
m_fTrialTimerStart=m_Time.fAppTime; mfTrialPausedTime=0.0f;
}
float CMinecraftApp::getTrialTimer(void)
{
return m_Time.fAppTime-m_fTrialTimerStart-mfTrialPausedTime;
}
bool CMinecraftApp::IsLocalMultiplayerAvailable()
{
DWORD connectedControllers = 0;
for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
{
if( InputManager.IsPadConnected(i) || ProfileManager.IsSignedIn(i) ) ++connectedControllers;
}
#ifdef _WINDOWS64
bool available = connectedControllers > 1;
#else
bool available = RenderManager.IsHiDef() && connectedControllers > 1;
#endif
#ifdef __ORBIS__
// Check for remote play
available = available && InputManager.IsLocalMultiplayerAvailable();
#endif
return available;
// Found this in GameNetworkManager?
//#ifdef _DURANGO
// iOtherConnectedControllers = InputManager.GetConnectedGamepadCount();
// if((InputManager.IsPadConnected(userIndex) || ProfileManager.IsSignedIn(userIndex)))
// {
// --iOtherConnectedControllers;
// }
//#else
// for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
// {
// if( (i!=userIndex) && (InputManager.IsPadConnected(i) || ProfileManager.IsSignedIn(i)) )
// {
// iOtherConnectedControllers++;
// }
// }
//#endif
}
// 4J-PB - language and locale function
void CMinecraftApp::getLocale(vector<wstring> &vecWstrLocales)
{
vector<eMCLang> locales;
DWORD dwSystemLanguage = XGetLanguage( );
// 4J-PB - restrict the 360 language until we're ready to have them in
#ifdef _XBOX
switch(dwSystemLanguage)
{
case XC_LANGUAGE_FRENCH :
locales.push_back(eMCLang_frFR);
break;
case XC_LANGUAGE_ITALIAN :
locales.push_back(eMCLang_itIT);
break;
case XC_LANGUAGE_GERMAN :
locales.push_back(eMCLang_deDE);
break;
case XC_LANGUAGE_SPANISH :
locales.push_back(eMCLang_esES);
break;
case XC_LANGUAGE_PORTUGUESE :
if(XGetLocale()==XC_LOCALE_BRAZIL)
{
locales.push_back(eMCLang_ptBR);
}
locales.push_back(eMCLang_ptPT);
break;
case XC_LANGUAGE_JAPANESE :
locales.push_back(eMCLang_jaJP);
break;
case XC_LANGUAGE_KOREAN :
locales.push_back(eMCLang_koKR);
break;
case XC_LANGUAGE_TCHINESE :
locales.push_back(eMCLang_zhCHT);
break;
}
#else
switch(dwSystemLanguage)
{
case XC_LANGUAGE_ENGLISH:
switch(XGetLocale())
{
case XC_LOCALE_AUSTRALIA:
case XC_LOCALE_CANADA:
case XC_LOCALE_CZECH_REPUBLIC:
case XC_LOCALE_GREECE:
case XC_LOCALE_HONG_KONG:
case XC_LOCALE_HUNGARY:
case XC_LOCALE_INDIA:
case XC_LOCALE_IRELAND:
case XC_LOCALE_ISRAEL:
case XC_LOCALE_NEW_ZEALAND:
case XC_LOCALE_SAUDI_ARABIA:
case XC_LOCALE_SINGAPORE:
case XC_LOCALE_SLOVAK_REPUBLIC:
case XC_LOCALE_SOUTH_AFRICA:
case XC_LOCALE_UNITED_ARAB_EMIRATES:
case XC_LOCALE_GREAT_BRITAIN:
locales.push_back(eMCLang_enGB);
break;
default: //XC_LOCALE_UNITED_STATES
break;
}
break;
case XC_LANGUAGE_JAPANESE :
locales.push_back(eMCLang_jaJP);
break;
case XC_LANGUAGE_GERMAN :
switch(XGetLocale())
{
case XC_LOCALE_AUSTRIA:
locales.push_back(eMCLang_deAT);
break;
case XC_LOCALE_SWITZERLAND:
locales.push_back(eMCLang_deCH);
break;
default:// XC_LOCALE_GERMANY:
break;
}
locales.push_back(eMCLang_deDE);
break;
case XC_LANGUAGE_FRENCH :
switch(XGetLocale())
{
case XC_LOCALE_BELGIUM:
locales.push_back(eMCLang_frBE);
break;
case XC_LOCALE_CANADA:
locales.push_back(eMCLang_frCA);
break;
case XC_LOCALE_SWITZERLAND:
locales.push_back(eMCLang_frCH);
break;
default:// XC_LOCALE_FRANCE:
break;
}
locales.push_back(eMCLang_frFR);
break;
case XC_LANGUAGE_SPANISH :
switch(XGetLocale())
{
case XC_LOCALE_MEXICO:
case XC_LOCALE_ARGENTINA:
case XC_LOCALE_CHILE:
case XC_LOCALE_COLOMBIA:
case XC_LOCALE_UNITED_STATES:
case XC_LOCALE_LATIN_AMERICA:
locales.push_back(eMCLang_laLAS);
locales.push_back(eMCLang_esMX);
break;
default://XC_LOCALE_SPAIN
break;
}
locales.push_back(eMCLang_esES);
break;
case XC_LANGUAGE_ITALIAN :
locales.push_back(eMCLang_itIT);
break;
case XC_LANGUAGE_KOREAN :
locales.push_back(eMCLang_koKR);
break;
case XC_LANGUAGE_TCHINESE :
switch(XGetLocale())
{
case XC_LOCALE_HONG_KONG:
locales.push_back(eMCLang_zhHK);
locales.push_back(eMCLang_zhTW);
break;
case XC_LOCALE_TAIWAN:
locales.push_back(eMCLang_zhTW);
locales.push_back(eMCLang_zhHK);
default:
break;
}
locales.push_back(eMCLang_hant);
locales.push_back(eMCLang_zhCHT);
break;
case XC_LANGUAGE_PORTUGUESE :
if(XGetLocale()==XC_LOCALE_BRAZIL)
{
locales.push_back(eMCLang_ptBR);
}
locales.push_back(eMCLang_ptPT);
break;
case XC_LANGUAGE_POLISH :
locales.push_back(eMCLang_plPL);
break;
case XC_LANGUAGE_RUSSIAN :
locales.push_back(eMCLang_ruRU);
break;
case XC_LANGUAGE_SWEDISH :
locales.push_back(eMCLang_svSV);
locales.push_back(eMCLang_svSE);
break;
case XC_LANGUAGE_TURKISH :
locales.push_back(eMCLang_trTR);
break;
case XC_LANGUAGE_BNORWEGIAN :
locales.push_back(eMCLang_nbNO);
locales.push_back(eMCLang_noNO);
locales.push_back(eMCLang_nnNO);
break;
case XC_LANGUAGE_DUTCH :
switch(XGetLocale())
{
case XC_LOCALE_BELGIUM:
locales.push_back(eMCLang_nlBE);
break;
default:
break;
}
locales.push_back(eMCLang_nlNL);
break;
case XC_LANGUAGE_SCHINESE :
switch(XGetLocale())
{
case XC_LOCALE_SINGAPORE:
locales.push_back(eMCLang_zhSG);
break;
default:
break;
}
locales.push_back(eMCLang_hans);
locales.push_back(eMCLang_csCS);
locales.push_back(eMCLang_zhCN);
break;
#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ || defined _DURANGO
case XC_LANGUAGE_DANISH:
locales.push_back(eMCLang_daDA);
locales.push_back(eMCLang_daDK);
break;
case XC_LANGUAGE_FINISH :
locales.push_back(eMCLang_fiFI);
break;
case XC_LANGUAGE_CZECH :
locales.push_back(eMCLang_csCZ);
locales.push_back(eMCLang_enCZ);
break;
case XC_LANGUAGE_SLOVAK :
locales.push_back(eMCLang_skSK);
locales.push_back(eMCLang_enSK);
break;
case XC_LANGUAGE_GREEK :
locales.push_back(eMCLang_elEL);
locales.push_back(eMCLang_elGR);
locales.push_back(eMCLang_enGR);
locales.push_back(eMCLang_enGB);
break;
#endif
}
#endif
locales.push_back(eMCLang_enUS);
locales.push_back(eMCLang_null);
for (int i=0; i<locales.size(); i++)
{
eMCLang lang = locales.at(i);
vecWstrLocales.push_back( m_localeA[lang] );
}
}
DWORD CMinecraftApp::get_eMCLang(WCHAR *pwchLocale)
{
return m_eMCLangA[pwchLocale];
}
DWORD CMinecraftApp::get_xcLang(WCHAR *pwchLocale)
{
return m_xcLangA[pwchLocale];
}
void CMinecraftApp::LocaleAndLanguageInit()
{
m_localeA[eMCLang_zhCHT] =L"zh-CHT";
m_localeA[eMCLang_csCS] =L"cs-CS";
m_localeA[eMCLang_laLAS] =L"la-LAS";
m_localeA[eMCLang_null] =L"en-EN";
m_localeA[eMCLang_enUS] =L"en-US";
m_localeA[eMCLang_enGB] =L"en-GB";
m_localeA[eMCLang_enIE] =L"en-IE";
m_localeA[eMCLang_enAU] =L"en-AU";
m_localeA[eMCLang_enNZ] =L"en-NZ";
m_localeA[eMCLang_enCA] =L"en-CA";
m_localeA[eMCLang_jaJP] =L"ja-JP";
m_localeA[eMCLang_deDE] =L"de-DE";
m_localeA[eMCLang_deAT] =L"de-AT";
m_localeA[eMCLang_frFR] =L"fr-FR";
m_localeA[eMCLang_frCA] =L"fr-CA";
m_localeA[eMCLang_esES] =L"es-ES";
m_localeA[eMCLang_esMX] =L"es-MX";
m_localeA[eMCLang_itIT] =L"it-IT";
m_localeA[eMCLang_koKR] =L"ko-KR";
m_localeA[eMCLang_ptPT] =L"pt-PT";
m_localeA[eMCLang_ptBR] =L"pt-BR";
m_localeA[eMCLang_ruRU] =L"ru-RU";
m_localeA[eMCLang_nlNL] =L"nl-NL";
m_localeA[eMCLang_fiFI] =L"fi-FI";
m_localeA[eMCLang_svSV] =L"sv-SV";
m_localeA[eMCLang_daDA] =L"da-DA";
m_localeA[eMCLang_noNO] =L"no-NO";
m_localeA[eMCLang_plPL] =L"pl-PL";
m_localeA[eMCLang_trTR] =L"tr-TR";
m_localeA[eMCLang_elEL] =L"el-EL";
m_localeA[eMCLang_zhSG] =L"zh-SG";
m_localeA[eMCLang_zhCN] =L"zh-CN";
m_localeA[eMCLang_zhHK] =L"zh-HK";
m_localeA[eMCLang_zhTW] =L"zh-TW";
m_localeA[eMCLang_nlBE] =L"nl-BE";
m_localeA[eMCLang_daDK] =L"da-DK";
m_localeA[eMCLang_frBE] =L"fr-BE";
m_localeA[eMCLang_frCH] =L"fr-CH";
m_localeA[eMCLang_deCH] =L"de-CH";
m_localeA[eMCLang_nbNO] =L"nb-NO";
m_localeA[eMCLang_enGR] =L"en-GR";
m_localeA[eMCLang_enHK] =L"en-HK";
m_localeA[eMCLang_enSA] =L"en-SA";
m_localeA[eMCLang_enHU] =L"en-HU";
m_localeA[eMCLang_enIN] =L"en-IN";
m_localeA[eMCLang_enIL] =L"en-IL";
m_localeA[eMCLang_enSG] =L"en-SG";
m_localeA[eMCLang_enSK] =L"en-SK";
m_localeA[eMCLang_enZA] =L"en-ZA";
m_localeA[eMCLang_enCZ] =L"en-CZ";
m_localeA[eMCLang_enAE] =L"en-AE";
m_localeA[eMCLang_esAR] =L"es-AR";
m_localeA[eMCLang_esCL] =L"es-CL";
m_localeA[eMCLang_esCO] =L"es-CO";
m_localeA[eMCLang_esUS] =L"es-US";
m_localeA[eMCLang_svSE] =L"sv-SE";
m_localeA[eMCLang_csCZ] =L"cs-CZ";
m_localeA[eMCLang_elGR] =L"el-GR";
m_localeA[eMCLang_nnNO] =L"nn-NO";
m_localeA[eMCLang_skSK] =L"sk-SK";
m_localeA[eMCLang_hans] =L"zh-HANS";
m_localeA[eMCLang_hant] =L"zh-HANT";
m_eMCLangA[L"zh-CHT"] =eMCLang_zhCHT;
m_eMCLangA[L"cs-CS"] =eMCLang_csCS;
m_eMCLangA[L"la-LAS"] =eMCLang_laLAS;
m_eMCLangA[L"en-EN"] =eMCLang_null;
m_eMCLangA[L"en-US"] =eMCLang_enUS;
m_eMCLangA[L"en-GB"] =eMCLang_enGB;
m_eMCLangA[L"en-IE"] =eMCLang_enIE;
m_eMCLangA[L"en-AU"] =eMCLang_enAU;
m_eMCLangA[L"en-NZ"] =eMCLang_enNZ;
m_eMCLangA[L"en-CA"] =eMCLang_enCA;
m_eMCLangA[L"ja-JP"] =eMCLang_jaJP;
m_eMCLangA[L"de-DE"] =eMCLang_deDE;
m_eMCLangA[L"de-AT"] =eMCLang_deAT;
m_eMCLangA[L"fr-FR"] =eMCLang_frFR;
m_eMCLangA[L"fr-CA"] =eMCLang_frCA;
m_eMCLangA[L"es-ES"] =eMCLang_esES;
m_eMCLangA[L"es-MX"] =eMCLang_esMX;
m_eMCLangA[L"it-IT"] =eMCLang_itIT;
m_eMCLangA[L"ko-KR"] =eMCLang_koKR;
m_eMCLangA[L"pt-PT"] =eMCLang_ptPT;
m_eMCLangA[L"pt-BR"] =eMCLang_ptBR;
m_eMCLangA[L"ru-RU"] =eMCLang_ruRU;
m_eMCLangA[L"nl-NL"] =eMCLang_nlNL;
m_eMCLangA[L"fi-FI"] =eMCLang_fiFI;
m_eMCLangA[L"sv-SV"] =eMCLang_svSV;
m_eMCLangA[L"da-DA"] =eMCLang_daDA;
m_eMCLangA[L"no-NO"] =eMCLang_noNO;
m_eMCLangA[L"pl-PL"] =eMCLang_plPL;
m_eMCLangA[L"tr-TR"] =eMCLang_trTR;
m_eMCLangA[L"el-EL"] =eMCLang_elEL;
m_eMCLangA[L"zh-SG"] =eMCLang_zhSG;
m_eMCLangA[L"zh-CN"] =eMCLang_zhCN;
m_eMCLangA[L"zh-HK"] =eMCLang_zhHK;
m_eMCLangA[L"zh-TW"] =eMCLang_zhTW;
m_eMCLangA[L"nl-BE"] =eMCLang_nlBE;
m_eMCLangA[L"da-DK"] =eMCLang_daDK;
m_eMCLangA[L"fr-BE"] =eMCLang_frBE;
m_eMCLangA[L"fr-CH"] =eMCLang_frCH;
m_eMCLangA[L"de-CH"] =eMCLang_deCH;
m_eMCLangA[L"nb-NO"] =eMCLang_nbNO;
m_eMCLangA[L"en-GR"] =eMCLang_enGR;
m_eMCLangA[L"en-HK"] =eMCLang_enHK;
m_eMCLangA[L"en-SA"] =eMCLang_enSA;
m_eMCLangA[L"en-HU"] =eMCLang_enHU;
m_eMCLangA[L"en-IN"] =eMCLang_enIN;
m_eMCLangA[L"en-IL"] =eMCLang_enIL;
m_eMCLangA[L"en-SG"] =eMCLang_enSG;
m_eMCLangA[L"en-SK"] =eMCLang_enSK;
m_eMCLangA[L"en-ZA"] =eMCLang_enZA;
m_eMCLangA[L"en-CZ"] =eMCLang_enCZ;
m_eMCLangA[L"en-AE"] =eMCLang_enAE;
m_eMCLangA[L"es-AR"] =eMCLang_esAR;
m_eMCLangA[L"es-CL"] =eMCLang_esCL;
m_eMCLangA[L"es-CO"] =eMCLang_esCO;
m_eMCLangA[L"es-US"] =eMCLang_esUS;
m_eMCLangA[L"sv-SE"] =eMCLang_svSE;
m_eMCLangA[L"cs-CZ"] =eMCLang_csCZ;
m_eMCLangA[L"el-GR"] =eMCLang_elGR;
m_eMCLangA[L"nn-NO"] =eMCLang_nnNO;
m_eMCLangA[L"sk-SK"] =eMCLang_skSK;
m_eMCLangA[L"zh-HANS"] =eMCLang_hans;
m_eMCLangA[L"zh-HANT"] =eMCLang_hant;
m_xcLangA[L"zh-CHT"] =XC_LOCALE_CHINA;
m_xcLangA[L"cs-CS"] =XC_LOCALE_CHINA;
m_xcLangA[L"en-EN"] =XC_LOCALE_UNITED_STATES;
m_xcLangA[L"en-US"] =XC_LOCALE_UNITED_STATES;
m_xcLangA[L"en-GB"] =XC_LOCALE_GREAT_BRITAIN;
m_xcLangA[L"en-IE"] =XC_LOCALE_IRELAND;
m_xcLangA[L"en-AU"] =XC_LOCALE_AUSTRALIA;
m_xcLangA[L"en-NZ"] =XC_LOCALE_NEW_ZEALAND;
m_xcLangA[L"en-CA"] =XC_LOCALE_CANADA;
m_xcLangA[L"ja-JP"] =XC_LOCALE_JAPAN;
m_xcLangA[L"de-DE"] =XC_LOCALE_GERMANY;
m_xcLangA[L"de-AT"] =XC_LOCALE_AUSTRIA;
m_xcLangA[L"fr-FR"] =XC_LOCALE_FRANCE;
m_xcLangA[L"fr-CA"] =XC_LOCALE_CANADA;
m_xcLangA[L"es-ES"] =XC_LOCALE_SPAIN;
m_xcLangA[L"es-MX"] =XC_LOCALE_MEXICO;
m_xcLangA[L"it-IT"] =XC_LOCALE_ITALY;
m_xcLangA[L"ko-KR"] =XC_LOCALE_KOREA;
m_xcLangA[L"pt-PT"] =XC_LOCALE_PORTUGAL;
m_xcLangA[L"pt-BR"] =XC_LOCALE_BRAZIL;
m_xcLangA[L"ru-RU"] =XC_LOCALE_RUSSIAN_FEDERATION;
m_xcLangA[L"nl-NL"] =XC_LOCALE_NETHERLANDS;
m_xcLangA[L"fi-FI"] =XC_LOCALE_FINLAND;
m_xcLangA[L"sv-SV"] =XC_LOCALE_SWEDEN;
m_xcLangA[L"da-DA"] =XC_LOCALE_DENMARK;
m_xcLangA[L"no-NO"] =XC_LOCALE_NORWAY;
m_xcLangA[L"pl-PL"] =XC_LOCALE_POLAND;
m_xcLangA[L"tr-TR"] =XC_LOCALE_TURKEY;
m_xcLangA[L"el-EL"] =XC_LOCALE_GREECE;
#ifndef _XBOX
m_xcLangA[L"la-LAS"] =XC_LOCALE_LATIN_AMERICA;
#endif
// New ones for Xbox One
m_xcLangA[L"zh-SG"] =XC_LOCALE_SINGAPORE;
m_xcLangA[L"Zh-CN"] =XC_LOCALE_CHINA;
m_xcLangA[L"zh-HK"] =XC_LOCALE_HONG_KONG;
m_xcLangA[L"zh-TW"] =XC_LOCALE_TAIWAN;
m_xcLangA[L"nl-BE"] =XC_LOCALE_BELGIUM;
m_xcLangA[L"da-DK"] =XC_LOCALE_DENMARK;
m_xcLangA[L"fr-BE"] =XC_LOCALE_BELGIUM;
m_xcLangA[L"fr-CH"] =XC_LOCALE_SWITZERLAND;
m_xcLangA[L"de-CH"] =XC_LOCALE_SWITZERLAND;
m_xcLangA[L"nb-NO"] =XC_LOCALE_NORWAY;
m_xcLangA[L"en-GR"] =XC_LOCALE_GREECE;
m_xcLangA[L"en-HK"] =XC_LOCALE_HONG_KONG;
m_xcLangA[L"en-SA"] =XC_LOCALE_SAUDI_ARABIA;
m_xcLangA[L"en-HU"] =XC_LOCALE_HUNGARY;
m_xcLangA[L"en-IN"] =XC_LOCALE_INDIA;
m_xcLangA[L"en-IL"] =XC_LOCALE_ISRAEL;
m_xcLangA[L"en-SG"] =XC_LOCALE_SINGAPORE;
m_xcLangA[L"en-SK"] =XC_LOCALE_SLOVAK_REPUBLIC;
m_xcLangA[L"en-ZA"] =XC_LOCALE_SOUTH_AFRICA;
m_xcLangA[L"en-CZ"] =XC_LOCALE_CZECH_REPUBLIC;
m_xcLangA[L"en-AE"] =XC_LOCALE_UNITED_ARAB_EMIRATES;
m_xcLangA[L"ja-IP"] =XC_LOCALE_JAPAN;
m_xcLangA[L"es-AR"] =XC_LOCALE_ARGENTINA;
m_xcLangA[L"es-CL"] =XC_LOCALE_CHILE;
m_xcLangA[L"es-CO"] =XC_LOCALE_COLOMBIA;
m_xcLangA[L"es-US"] =XC_LOCALE_UNITED_STATES;
m_xcLangA[L"sv-SE"] =XC_LOCALE_SWEDEN;
m_xcLangA[L"cs-CZ"] =XC_LOCALE_CZECH_REPUBLIC;
m_xcLangA[L"el-GR"] =XC_LOCALE_GREECE;
m_xcLangA[L"sk-SK"] =XC_LOCALE_SLOVAK_REPUBLIC;
m_xcLangA[L"zh-HANS"] =XC_LOCALE_CHINA;
m_xcLangA[L"zh-HANT"] =XC_LOCALE_CHINA;
}
void CMinecraftApp::SetTickTMSDLCFiles(bool bVal)
{
// 4J-PB - we need to stop the retrieval of minecraft store images from TMS when we aren't in the DLC, since going in to Play Game will change the title id group
m_bTickTMSDLCFiles=bVal;
}
wstring CMinecraftApp::getFilePath(DWORD packId, wstring filename, bool bAddDataFolder, wstring mountPoint)
{
wstring path = getRootPath(packId, true, bAddDataFolder, mountPoint) + filename;
File f(path);
if(f.exists())
{
return path;
}
return getRootPath(packId, false, true, mountPoint) + filename;
}
#ifdef _XBOX
// Texture packs that have their data in the TU data
enum ETitleUpdateTexturePacks
{
eTUTP_MassEffect = 0x400,
eTUTP_Skyrim = 0x401,
eTUTP_Halo = 0x402,
eTUTP_Festive = 0x405,
eTUTP_Plastic = 0x801,
eTUTP_Candy = 0x802,
eTUTP_Fantasy = 0x803,
eTUTP_Halloween = 0x804,
eTUTP_Natural = 0x805,
eTUTP_City = 0x01000806, // 4J Stu - The released City pack had a sub-pack ID
eTUTP_Cartoon = 0x807,
eTUTP_Steampunk = 0x01000808, // 4J Stu - The released Steampunk pack had a sub-pack ID
};
#ifdef _TU_BUILD
wstring titleUpdateTexturePackRoot = L"UPDATE:\\res\\DLC\\";
#else
wstring titleUpdateTexturePackRoot = L"GAME:\\res\\TitleUpdate\\DLC\\";
#endif
#else
enum ETitleUpdateTexturePacks
{
//eTUTP_MassEffect = 0x400,
//eTUTP_Skyrim = 0x401,
//eTUTP_Halo = 0x402,
//eTUTP_Festive = 0x405,
//eTUTP_Plastic = 0x801,
//eTUTP_Candy = 0x802,
//eTUTP_Fantasy = 0x803,
eTUTP_Halloween = 0x804,
//eTUTP_Natural = 0x805,
//eTUTP_City = 0x01000806, // 4J Stu - The released City pack had a sub-pack ID
//eTUTP_Cartoon = 0x807,
//eTUTP_Steampunk = 0x01000808, // 4J Stu - The released Steampunk pack had a sub-pack ID
};
#ifdef _WINDOWS64
wstring titleUpdateTexturePackRoot = L"Windows64\\DLC\\";
#elif defined(__ORBIS__)
wstring titleUpdateTexturePackRoot = L"/app0/orbis/CU/DLC/";
#elif defined(__PSVITA__)
wstring titleUpdateTexturePackRoot = L"PSVita/CU/DLC/";
#elif defined(__PS3__)
wstring titleUpdateTexturePackRoot = L"PS3/CU/DLC/";
#else
wstring titleUpdateTexturePackRoot = L"CU\\DLC\\";
#endif
#endif
wstring CMinecraftApp::getRootPath(DWORD packId, bool allowOverride, bool bAddDataFolder, wstring mountPoint)
{
wstring path = mountPoint;
#ifdef _XBOX
if(allowOverride)
{
switch(packId)
{
case eTUTP_MassEffect:
path = titleUpdateTexturePackRoot + L"MassEffect";
break;
case eTUTP_Skyrim:
path = titleUpdateTexturePackRoot + L"Skyrim";
break;
case eTUTP_Halo:
path = titleUpdateTexturePackRoot + L"Halo";
break;
case eTUTP_Festive:
path = titleUpdateTexturePackRoot + L"Festive";
break;
case eTUTP_Plastic:
path = titleUpdateTexturePackRoot + L"Plastic";
break;
case eTUTP_Candy:
path = titleUpdateTexturePackRoot + L"Candy";
break;
case eTUTP_Fantasy:
path = titleUpdateTexturePackRoot + L"Fantasy";
break;
case eTUTP_Halloween:
path = titleUpdateTexturePackRoot + L"Halloween";
break;
case eTUTP_Natural:
path = titleUpdateTexturePackRoot + L"Natural";
break;
case eTUTP_City:
path = titleUpdateTexturePackRoot + L"City";
break;
case eTUTP_Cartoon:
path = titleUpdateTexturePackRoot + L"Cartoon";
break;
case eTUTP_Steampunk:
path = titleUpdateTexturePackRoot + L"Steampunk";
break;
};
File folder(path);
if(!folder.exists())
{
path = mountPoint;
}
}
#else
if(allowOverride)
{
switch(packId)
{
case eTUTP_Halloween:
path = titleUpdateTexturePackRoot + L"Halloween Texture Pack";
break;
};
File folder(path);
if(!folder.exists())
{
path = mountPoint;
}
}
#endif
if(bAddDataFolder)
{
return path + L"\\Data\\";
}
else
{
return path + L"\\";
}
}
#ifdef _XBOX_ONE
void CMinecraftApp::SetReachedMainMenu()
{
m_hasReachedMainMenu = true;
}
bool CMinecraftApp::HasReachedMainMenu()
{
return m_hasReachedMainMenu;
}
#endif