#include "minecraft/GameHostOptions.h" #include "app/common/Game.h" #include "platform/PlatformTypes.h" #include "platform/InputActions.h" #include "platform/sdl2/Profile.h" #include "platform/sdl2/Render.h" #include "platform/sdl2/Storage.h" #include "app/common/App_Defines.h" #include "app/common/App_enums.h" #include "app/common/App_structs.h" #include "app/common/Console_Debug_enum.h" #include "app/common/DLC/DLCManager.h" #include "app/common/DLC/DLCSkinFile.h" #include "app/common/GameRules/GameRuleManager.h" #include "app/common/Network/GameNetworkManager.h" #include "app/common/Network/NetworkPlayerInterface.h" #include "app/common/Tutorial/Tutorial.h" #include "app/common/UI/All Platforms/UIEnums.h" #include "app/common/UI/All Platforms/UIStructs.h" #include "app/common/UI/Scenes/UIScene_FullscreenProgress.h" #include "app/linux/LinuxGame.h" #include "app/linux/Linux_UIController.h" #include "app/linux/Stubs/winapi_stubs.h" #include "platform/NetTypes.h" #include "minecraft/client/SkinBox.h" #include "platform/XboxStubs.h" #include "platform/PlatformServices.h" #include "java/Class.h" #include "java/File.h" #include "java/Random.h" #include "minecraft/client/Minecraft.h" #include "minecraft/client/Options.h" #include "minecraft/client/ProgressRenderer.h" #include "minecraft/client/model/geom/Model.h" #include "minecraft/client/multiplayer/ClientConnection.h" #include "minecraft/client/multiplayer/MultiPlayerGameMode.h" #include "minecraft/client/multiplayer/MultiPlayerLevel.h" #include "minecraft/client/multiplayer/MultiPlayerLocalPlayer.h" #include "minecraft/client/renderer/GameRenderer.h" #include "minecraft/client/renderer/Textures.h" #include "minecraft/client/renderer/entity/EntityRenderer.h" #include "minecraft/client/skins/TexturePack.h" #include "minecraft/network/packet/DisconnectPacket.h" #include "minecraft/server/MinecraftServer.h" #include "minecraft/stats/StatsCounter.h" #include "minecraft/world/Container.h" #include "minecraft/world/entity/item/MinecartHopper.h" #include "minecraft/world/entity/player/Player.h" #include "minecraft/world/item/crafting/Recipy.h" #include "minecraft/world/level/tile/Tile.h" #include "minecraft/world/level/tile/entity/HopperTileEntity.h" #include "strings.h" #if defined(_WINDOWS64) #include "app/windows/XML/ATGXmlParser.h" #include "app/windows/XML/xmlFilesCallback.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "platform/sdl2/Input.h" #include "app/common/Audio/SoundEngine.h" #include "app/common/Colours/ColourTable.h" #include "app/common/DLC/DLCPack.h" #include "app/common/Localisation/StringTable.h" #include "app/common/UI/All Platforms/ArchiveFile.h" #include "app/common/UI/Scenes/In-Game Menu Screens/UIScene_PauseMenu.h" #include "Minecraft_Macros.h" #include "util/Timer.h" #include "util/StringHelpers.h" #include "minecraft/world/level/storage/ConsoleSaveFileIO/compression.h" #include "minecraft/client/User.h" #include "minecraft/client/gui/Gui.h" #include "minecraft/client/renderer/entity/EntityRenderDispatcher.h" #include "minecraft/client/skins/DLCTexturePack.h" #include "minecraft/client/skins/TexturePackRepository.h" #include "minecraft/server/PlayerList.h" #include "minecraft/server/level/ServerPlayer.h" class BeaconTileEntity; class BrewingStandTileEntity; class DispenserTileEntity; class EntityHorse; class FurnaceTileEntity; class INVITE_INFO; class Inventory; class Level; class LevelChunk; class LevelGenerationOptions; class LocalPlayer; class Merchant; class ModelPart; class SignTileEntity; // Game app; const float Game::fSafeZoneX = 64.0f; // 5% of 1280 const float Game::fSafeZoneY = 36.0f; // 5% of 720 Game::Game() { GameHostOptions::init(&m_uiGameHostSettings); if (GAME_SETTINGS_PROFILE_DATA_BYTES != sizeof(GAME_SETTINGS)) { 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); #if !defined(_CONTENT_PACKAGE) __debugbreak(); #endif } for (int i = 0; i < XUSER_MAX_COUNT; i++) { DebugPrintf("Player at index %d has guest number %d\n", i, m_networkController.m_currentSigninInfo[i].dwGuestNumber); } m_bResourcesLoaded = false; m_bGameStarted = false; m_bIsAppPaused = false; m_bIntroRunning = false; m_eGameMode = eMode_Singleplayer; m_bTutorialMode = false; mfTrialPausedTime = 0.0f; #if defined(_LARGE_WORLDS) m_GameNewWorldSize = 0; m_bGameNewWorldSizeUseMoat = false; m_GameNewHellScale = 0; #endif m_bResetNether = false; LocaleAndLanguageInit(); } void Game::DebugPrintf(const char* szFormat, ...) { #if !defined(_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 Game::DebugPrintf(int user, const char* szFormat, ...) { #if !defined(_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); OutputDebugStringA(buf); if (user == USER_UI) { ui.logDebugString(buf); } #endif } const wchar_t* Game::GetString(int iID) { // return L"Değişiklikler ve Yenilikler"; // return L"ÕÕÕÕÖÖÖÖ"; return app.m_localizationManager.getString(iID); } // SetAction moved to MenuController // HandleButtonPresses moved to GameSettingsManager bool Game::IsAppPaused() { return m_bIsAppPaused; } void Game::SetAppPaused(bool val) { m_bIsAppPaused = val; } // Load*Menu methods moved to MenuController ////////////////////////////////////////////// // GAME SETTINGS ////////////////////////////////////////////// // Skin/Cape/FavoriteSkin methods moved to SkinManager // Mash-up pack worlds /////////////////////////// // // Remove the debug settings in the content package build // //////////////////////////// #if !defined(_DEBUG_MENUS_ENABLED) #else #endif void Game::HandleXuiActions(void) { eXuiAction eAction; eTMSAction eTMS; void* param; Minecraft* pMinecraft = Minecraft::GetInstance(); std::shared_ptr 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 { unsigned int 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_menuController.getXuiActionParam(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()) { // flag the render to capture the screenshot for the // save SetAction(i, eAppAction_SaveGameCapturedThumbnail); } 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()==nullptr) { 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 = (void*)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 ui.NavigateToScene(ProfileManager.GetPrimaryPad(), eUIScene_FullscreenProgress, loadingParams, eUILayer_Fullscreen, eUIGroup_Fullscreen); } break; case eAppAction_AutosaveSaveGameCapturedThumbnail: { app.SetAutosaveTimerTime(); SetAction(i, eAppAction_Idle); // 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()] != nullptr) 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 = (void*)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 ui.NavigateToScene(ProfileManager.GetPrimaryPad(), eUIScene_FullscreenProgress, loadingParams, eUILayer_Fullscreen, eUIGroup_Fullscreen); } 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... ProfileManager.ForceQueuedProfileWrites(i); // 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); // Wipe out the tooltips ui.SetTooltips(i, -1); // 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; 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... ProfileManager.ForceQueuedProfileWrites(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); // Wipe out the tooltips ui.SetTooltips(i, -1); // 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; case eAppAction_ExitWorld: pMinecraft->exitingWorldRightNow = true; 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... // 4J-PB - cancel any possible std::string verifications // queued with LIVE // InputManager.CancelAllVerifyInProgress(); // 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); SetAction(i, eAppAction_Idle); return; } // flag to capture the save thumbnail SetAction(i, eAppAction_ExitWorldCapturedThumbnail, param); // 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); } } } } 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); } } 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) { // 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 != nullptr) ? true : false; completionData->bShowTips = (param != nullptr) ? 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) { // 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 = (void*)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 != nullptr && 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 != nullptr && 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 unsigned int // uiIDA[1]; uiIDA[0]=IDS_CONFIRM_OK; // // ui.RequestMessageBox(IDS_RETURNEDTOMENU_TITLE, // IDS_RETURNEDTOTITLESCREEN_TEXT, uiIDA, 1, // i,&Game::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.size(); j++) { if (pMinecraft->levels.data()[j] != 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(); unsigned int 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, &Game:: EthernetDisconnectReturned, this); } else { // 2. Switch to offline SetAction(i, eAppAction_ChangeSessionType); } } } else { { 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(); unsigned int 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, &Game::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) { // 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 = &Game::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); unsigned int uiIDA[2]; uiIDA[0] = IDS_UNLOCK_TITLE; uiIDA[1] = IDS_EXIT_GAME; ui.RequestErrorMessage( IDS_TRIALOVER_TITLE, IDS_TRIALOVER_TEXT, uiIDA, 2, i, &Game::TrialOverReturned, this); } break; // INVITES case eAppAction_DashboardTrialJoinFromInvite: { SetAction(i, eAppAction_Idle); unsigned int uiIDA[2]; uiIDA[0] = IDS_CONFIRM_OK; uiIDA[1] = IDS_CONFIRM_CANCEL; ui.RequestErrorMessage( IDS_UNLOCK_TITLE, IDS_UNLOCK_ACCEPT_INVITE, uiIDA, 2, i, &Game::UnlockFullInviteReturned, this); } break; case eAppAction_ExitAndJoinFromInvite: { unsigned int uiIDA[3]; SetAction(i, eAppAction_Idle); // Check the player really wants to do this if (!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, &Game:: ExitAndJoinFromInviteSaveDialogReturned, 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, &Game::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) { // 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 = nullptr; 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 pMinecraft->soundEngine->SetStreamingSounds( eStream_Overworld_Calm1, eStream_Overworld_piano3, eStream_Nether1, eStream_Nether4, eStream_end_dragon, eStream_end_end, eStream_CD_1); pMinecraft->soundEngine->playStreaming(L"", 0, 0, 0, 1, 1); const unsigned int result = StorageManager.UnmountInstalledDLC("TPACK"); app.DebugPrintf("Unmount result is %d\n", result); } LoadingInputParams* loadingParams = new LoadingInputParams(); loadingParams->func = &CGameNetworkManager::ExitAndJoinFromInviteThreadProc; loadingParams->lpParam = (void*)&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 // IPlatformNetwork::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); // 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 unsigned int 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 = nullptr; UIFullscreenProgressCompletionData* completionData = new UIFullscreenProgressCompletionData(); completionData->bRequiresUserAction = true; 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); } } break; case eAppAction_SetDefaultOptions: SetAction(i, eAppAction_Idle); SetDefaultOptions((C_4JProfile::PROFILESETTINGS*)param, i); // 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 = &Game::RemoteSaveThreadProc; loadingParams->lpParam = nullptr; 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 = &Game::ExitGameFromRemoteSave; loadingParams->cancelText = IDS_TOOLTIPS_EXIT; ui.NavigateToScene(ProfileManager.GetPrimaryPad(), eUIScene_FullscreenProgress, loadingParams); } break; case eAppAction_WaitRemoteServerSaveComplete: // Do nothing break; case eAppAction_FailedToJoinNoPrivileges: { unsigned int 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()) { // 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: { unsigned int uiIDA[2]; uiIDA[0] = IDS_BUTTON_REMOVE_FROM_BAN_LIST; uiIDA[1] = IDS_EXIT_GAME; // pass in the gamertag format std::string wchar_t 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, &Game::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 { 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; } } // 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: { 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(); } break; case eAppAction_TexturePackRequired: { unsigned int 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(), &Game::TexturePackDialogReturned, this); SetAction(i, eAppAction_Idle); } break; default: 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: SetTMSAction(i, eTMSAction_TMSPP_UserFileList); break; case eTMSAction_TMSPP_UserFileList: // retrieve the file list first SetTMSAction(i, eTMSAction_TMSPP_XUIDSFile); break; case eTMSAction_TMSPP_XUIDSFile: SetTMSAction(i, eTMSAction_TMSPP_DLCFile); break; case eTMSAction_TMSPP_DLCFile: SetTMSAction(i, eTMSAction_TMSPP_BannedListFile); break; case eTMSAction_TMSPP_BannedListFile: // If we have one in TMSPP, then we can assume we can ignore // TMS SetTMSAction(i, eTMSAction_TMS_RetrieveFiles_Complete); 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 SetTMSAction(i, eTMSAction_TMSPP_DLCFileOnly); break; case eTMSAction_TMSPP_RetrieveUserFilelist_DLCFileOnly: SetTMSAction(i, eTMSAction_TMSPP_DLCFileOnly); break; case eTMSAction_TMSPP_DLCFileOnly: SetTMSAction(i, eTMSAction_TMSPP_RetrieveFiles_Complete); 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 0 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: SetTMSAction(i,eTMSAction_TMS_BannedListFile); break; case eTMSAction_TMS_RetrieveFiles_HelpAndOptions: case eTMSAction_TMS_RetrieveFiles_DLCMain: SetTMSAction(i,eTMSAction_Idle); break; case eTMSAction_TMS_BannedListFile: 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; default: break; } } } } // loadMediaArchive and loadStringTable moved to ArchiveManager/LocalizationManager int Game::BannedLevelDialogReturned( void* pParam, int iPad, const C4JStorage::EMessageResult result) { Game* pApp = (Game*)pParam; if (result == C4JStorage::EMessage_ResultAccept) { } else { if (iPad == ProfileManager.GetPrimaryPad()) { pApp->SetAction(iPad, eAppAction_ExitWorld); } else { pApp->SetAction(iPad, eAppAction_ExitPlayer); } } return 0; } #if defined(_DEBUG_MENUS_ENABLED) bool Game::DebugArtToolsOn() { return m_debugOptions.debugArtToolsOn( GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())); } #endif void Game::SetDebugSequence(const char* pchSeq) { InputManager.SetDebugSequence(pchSeq, [this]() -> int { // printf("sequence matched\n"); m_debugOptions.setDebugOptions(!m_debugOptions.settingsOn()); 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 Game::GetLocalPlayerCount(void) { int iPlayerC = 0; Minecraft* pMinecraft = Minecraft::GetInstance(); for (int i = 0; i < XUSER_MAX_COUNT; i++) { if (pMinecraft != nullptr && pMinecraft->localplayers[i] != nullptr) { iPlayerC++; } } return iPlayerC; } // Installed DLC callback // 4J-JEV: For the sake of clarity in DLCMountedCallback. #if defined(_WINDOWS64) #define CONTENT_DATA_DISPLAY_NAME(a) (a.szDisplayName) #else #define CONTENT_DATA_DISPLAY_NAME(a) (a.wszDisplayName) #endif #undef CONTENT_DATA_DISPLAY_NAME // void Game::InstallDefaultCape() // { // if(!m_bDefaultCapeInstallAttempted) // { // // we only attempt to install the cape once per launch of the // game m_bDefaultCapeInstallAttempted=true; // // std::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) // { // std::uint8_t *pBuffer=nullptr; // std::uint32_t 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 // } // } // } // int Game::DLCReadCallback(void* // pParam,C4JStorage::DLC_FILE_DETAILS *pDLCData) // { // // // return 0; // } //------------------------------------------------------------------------------------- // Name: InitTime() // Desc: Initializes the timer variables //------------------------------------------------------------------------------------- void Game::InitTime() { // Save the start time m_Time.qwTime = time_util::clock::now(); // Zero out the elapsed and total time m_Time.qwAppTime = {}; m_Time.fAppTime = 0.0f; m_Time.fElapsedTime = 0.0f; } //------------------------------------------------------------------------------------- // Name: UpdateTime() // Desc: Updates the elapsed time since our last frame. //------------------------------------------------------------------------------------- void Game::UpdateTime() { auto qwNewTime = time_util::clock::now(); auto qwDeltaTime = qwNewTime - m_Time.qwTime; m_Time.qwAppTime += qwDeltaTime; m_Time.qwTime = qwNewTime; m_Time.fElapsedTime = std::chrono::duration(qwDeltaTime).count(); m_Time.fAppTime = std::chrono::duration(m_Time.qwAppTime).count(); } bool Game::isXuidDeadmau5(PlayerUID xuid) { auto it = DLCController::MojangData.find(xuid); // 4J Stu - The .at and [] accessors // insert elements if they don't exist if (it != DLCController::MojangData.end()) { MOJANG_DATA* pMojangData = DLCController::MojangData[xuid]; if (pMojangData && pMojangData->eXuid == eXUID_Deadmau5) { return true; } } return false; } void Game::StoreLaunchData() {} void Game::ExitGame() {} // Invites ////////////////////////////////////////////////////////////////////////// // // 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 Game::FatalLoadError() {} // Game Host options void Game::SetGameHostOption(eGameHostOption eVal, unsigned int uiVal) { GameHostOptions::set(eVal, uiVal); } unsigned int Game::GetGameHostOption(eGameHostOption eVal) { return GameHostOptions::get(eVal); } void Game::processSchematics(LevelChunk* levelChunk) { m_gameRules.processSchematics(levelChunk); } void Game::processSchematicsLighting(LevelChunk* levelChunk) { m_gameRules.processSchematicsLighting(levelChunk); } void Game::loadDefaultGameRules() { m_gameRules.loadDefaultGameRules(); } void Game::setLevelGenerationOptions( LevelGenerationOptions* levelGen) { m_gameRules.setLevelGenerationOptions(levelGen); } const wchar_t* Game::GetGameRulesString(const std::wstring& key) { return m_gameRules.GetGameRulesString(key); } // PNG_TAG_tEXt, FromBigEndian, GetImageTextData, CreateImageTextData moved to MenuController std::wstring Game::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); default: break; }; return L""; } // m_dwContentTypeA moved to DLCController int32_t Game::RegisterMojangData(wchar_t* pXuidName, PlayerUID xuid, wchar_t* pSkin, wchar_t* pCape) { int32_t hr = 0; eXUID eTempXuid = eXUID_Undefined; MOJANG_DATA* pMojangData = nullptr; // ignore the names if we don't recognize them if (pXuidName != nullptr) { 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; memset(pMojangData, 0, sizeof(MOJANG_DATA)); pMojangData->eXuid = eTempXuid; wcsncpy(pMojangData->wchSkin, pSkin, MAX_CAPENAME_SIZE); wcsncpy(pMojangData->wchCape, pCape, MAX_CAPENAME_SIZE); DLCController::MojangData[xuid] = pMojangData; } return hr; } MOJANG_DATA* Game::GetMojangDataForXuid(PlayerUID xuid) { return DLCController::MojangData[xuid]; } int32_t Game::RegisterConfigValues(wchar_t* pType, int iValue) { int32_t hr = 0; // #ifdef 0 // if(pType!=nullptr) // { // 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(_WINDOWS64) #elif defined(__linux__) #else #endif // DLC // AUTOSAVE void Game::SetAutosaveTimerTime(void) { int settingValue = GetGameSettings(ProfileManager.GetPrimaryPad(), eGameSetting_Autosave); m_saveManager.setAutosaveTimerTime(settingValue); } void Game::SetTrialTimerStart(void) { m_fTrialTimerStart = m_Time.fAppTime; mfTrialPausedTime = 0.0f; } float Game::getTrialTimer(void) { return m_Time.fAppTime - m_fTrialTimerStart - mfTrialPausedTime; } bool Game::IsLocalMultiplayerAvailable() { unsigned int connectedControllers = 0; for (unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) { if (InputManager.IsPadConnected(i) || ProfileManager.IsSignedIn(i)) ++connectedControllers; } bool available = RenderManager.IsHiDef() && connectedControllers > 1; return available; // Found this in GameNetworkManager? // #ifdef 0 // 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 // (moved to manager class) std::wstring Game::getFilePath(std::uint32_t packId, std::wstring filename, bool bAddDataFolder, std::wstring mountPoint) { std::wstring path = getRootPath(packId, true, bAddDataFolder, mountPoint) + filename; File f(path); if (f.exists()) { return path; } return getRootPath(packId, false, true, mountPoint) + filename; } 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 }; #if defined(_WINDOWS64) std::wstring titleUpdateTexturePackRoot = L"Windows64\\DLC\\"; #else std::wstring titleUpdateTexturePackRoot = L"CU\\DLC\\"; #endif std::wstring Game::getRootPath(std::uint32_t packId, bool allowOverride, bool bAddDataFolder, std::wstring mountPoint) { std::wstring path = mountPoint; if (allowOverride) { switch (packId) { case eTUTP_Halloween: path = titleUpdateTexturePackRoot + L"Halloween Texture Pack"; break; }; File folder(path); if (!folder.exists()) { path = mountPoint; } } if (bAddDataFolder) { return path + L"\\Data\\"; } else { return path + L"\\"; } }