aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/Common/XUI/XUI_PauseMenu.cpp
diff options
context:
space:
mode:
authordaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
committerdaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
commitb691c43c44ff180d10e7d4a9afc83b98551ff586 (patch)
tree3e9849222cbc6ba49f2f1fc6e5fe7179632c7390 /Minecraft.Client/Common/XUI/XUI_PauseMenu.cpp
parentdef8cb415354ac390b7e89052a50605285f1aca9 (diff)
Initial commit
Diffstat (limited to 'Minecraft.Client/Common/XUI/XUI_PauseMenu.cpp')
-rw-r--r--Minecraft.Client/Common/XUI/XUI_PauseMenu.cpp1219
1 files changed, 1219 insertions, 0 deletions
diff --git a/Minecraft.Client/Common/XUI/XUI_PauseMenu.cpp b/Minecraft.Client/Common/XUI/XUI_PauseMenu.cpp
new file mode 100644
index 00000000..4de74d1f
--- /dev/null
+++ b/Minecraft.Client/Common/XUI/XUI_PauseMenu.cpp
@@ -0,0 +1,1219 @@
+// Minecraft.cpp : Defines the entry point for the application.
+//
+
+#include "stdafx.h"
+
+#include <assert.h>
+#include "..\..\..\Minecraft.World\AABB.h"
+#include "..\..\..\Minecraft.World\Vec3.h"
+#include "..\..\..\Minecraft.World\net.minecraft.stats.h"
+#include "..\..\..\Minecraft.Client\StatsCounter.h"
+#include "..\..\..\Minecraft.World\Entity.h"
+#include "..\..\..\Minecraft.World\Level.h"
+#include "..\..\..\Minecraft.Client\MultiplayerLocalPlayer.h"
+#include "..\..\MinecraftServer.h"
+#include "..\..\MultiPlayerLevel.h"
+#include "..\..\ProgressRenderer.h"
+#include "..\..\..\Minecraft.World\DisconnectPacket.h"
+#include "..\..\Minecraft.h"
+#include "..\..\Options.h"
+#include "..\..\..\Minecraft.World\compression.h"
+#include "..\..\TexturePackRepository.h"
+#include "..\..\TexturePack.h"
+#include "..\..\DLCTexturePack.h"
+
+#define IGNORE_KEYPRESS_TIMERID 0
+#define IGNORE_KEYPRESS_TIME 100
+
+//----------------------------------------------------------------------------------
+// Performs initialization tasks - retrieves controls.
+//----------------------------------------------------------------------------------
+HRESULT UIScene_PauseMenu::OnInit( XUIMessageInit* pInitData, BOOL& bHandled )
+{
+ m_bIgnoreInput=true;
+ m_iPad = *(int *)pInitData->pvInitData;
+ bool bUserisClientSide = ProfileManager.IsSignedInLive(m_iPad);
+
+ app.DebugPrintf("PAUSE PRESS PROCESSING - ipad = %d, UIScene_PauseMenu::OnInit\n",m_iPad);
+
+ bool bIsisPrimaryHost=g_NetworkManager.IsHost() && (ProfileManager.GetPrimaryPad()==m_iPad);
+ bool bDisplayBanTip = !g_NetworkManager.IsLocalGame() && !bIsisPrimaryHost && !ProfileManager.IsGuest(m_iPad);
+
+ MapChildControls();
+
+ XuiControlSetText(m_Buttons[BUTTON_PAUSE_RESUMEGAME],app.GetString(IDS_RESUME_GAME));
+ XuiControlSetText(m_Buttons[BUTTON_PAUSE_HELPANDOPTIONS],app.GetString(IDS_HELP_AND_OPTIONS));
+ XuiControlSetText(m_Buttons[BUTTON_PAUSE_LEADERBOARDS],app.GetString(IDS_LEADERBOARDS));
+ XuiControlSetText(m_Buttons[BUTTON_PAUSE_ACHIEVEMENTS],app.GetString(IDS_ACHIEVEMENTS));
+ XuiControlSetText(m_Buttons[BUTTON_PAUSE_SAVEGAME],app.GetString(IDS_SAVE_GAME));
+ XuiControlSetText(m_Buttons[BUTTON_PAUSE_EXITGAME],app.GetString(IDS_EXIT_GAME));
+
+ if(app.GetLocalPlayerCount()>1)
+ {
+ m_bSplitscreen = true;
+ app.AdjustSplitscreenScene(m_hObj,&m_OriginalPosition,m_iPad,false);
+ CXuiSceneBase::ShowLogo( m_iPad, FALSE );
+ }
+ else
+ {
+ m_bSplitscreen = false;
+ CXuiSceneBase::ShowLogo( m_iPad, TRUE );
+ }
+
+ // test award the theme
+ //ProfileManager.Award( ProfileManager.GetPrimaryPad(), eAward_socialPost );
+ // Display the tooltips, we are only allowed to display "SHARE" if we have the capability (TCR).
+
+ if(!ProfileManager.IsFullVersion())
+ {
+ ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK);
+ // hide the trial timer
+ CXuiSceneBase::ShowTrialTimer(FALSE);
+ }
+ else if(StorageManager.GetSaveDisabled())
+ {
+ if( CSocialManager::Instance()->IsTitleAllowedToPostImages() && CSocialManager::Instance()->AreAllUsersAllowedToPostImages() && bUserisClientSide )
+ {
+ ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,bIsisPrimaryHost?IDS_TOOLTIPS_SELECTDEVICE:-1,IDS_TOOLTIPS_SHARE, -1,-1,-1,bDisplayBanTip?IDS_TOOLTIPS_BANLEVEL:-1);
+ }
+ else
+ {
+ ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,bIsisPrimaryHost?IDS_TOOLTIPS_SELECTDEVICE:-1,-1,-1,-1,-1,bDisplayBanTip?IDS_TOOLTIPS_BANLEVEL:-1);
+ }
+ }
+ else
+ {
+ if( CSocialManager::Instance()->IsTitleAllowedToPostImages() && CSocialManager::Instance()->AreAllUsersAllowedToPostImages() && bUserisClientSide)
+ {
+ ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,bIsisPrimaryHost?IDS_TOOLTIPS_CHANGEDEVICE:-1,IDS_TOOLTIPS_SHARE, -1,-1,-1,bDisplayBanTip?IDS_TOOLTIPS_BANLEVEL:-1);
+ }
+ else
+ {
+ ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,bIsisPrimaryHost?IDS_TOOLTIPS_CHANGEDEVICE:-1,-1, -1,-1,-1,bDisplayBanTip?IDS_TOOLTIPS_BANLEVEL:-1);
+ }
+ }
+
+ CXuiSceneBase::ShowDarkOverlay( m_iPad, TRUE );
+
+ // are we the primary player?
+ // 4J-PB - fix for 7844 & 7845 -
+ // TCR # 128: XLA Pause Menu: When in a multiplayer game as a client the Pause Menu does not have a Leaderboards option.
+ // TCR # 128: XLA Pause Menu: When in a multiplayer game as a client the Pause Menu does not have an Achievements option.
+ if(ProfileManager.GetPrimaryPad()==m_iPad) // && g_NetworkManager.IsHost())
+ {
+ // are we in splitscreen?
+ // how many local players do we have?
+
+ D3DXVECTOR3 vPos;
+ if( app.GetLocalPlayerCount()>1 )
+ {
+ m_Buttons[BUTTON_PAUSE_LEADERBOARDS].GetPosition(&vPos);
+ m_Buttons[BUTTON_PAUSE_SAVEGAME].SetPosition(&vPos);
+ m_Buttons[BUTTON_PAUSE_ACHIEVEMENTS].GetPosition(&vPos);
+ m_Buttons[BUTTON_PAUSE_EXITGAME].SetPosition(&vPos);
+ // Hide the BUTTON_PAUSE_LEADERBOARDS and BUTTON_PAUSE_ACHIEVEMENTS
+ XuiElementSetShow(m_Buttons[BUTTON_PAUSE_LEADERBOARDS],FALSE);
+ XuiElementSetShow(m_Buttons[BUTTON_PAUSE_ACHIEVEMENTS],FALSE);
+ }
+
+ if( !g_NetworkManager.IsHost() )
+ {
+ m_Buttons[BUTTON_PAUSE_SAVEGAME].GetPosition(&vPos);
+ m_Buttons[BUTTON_PAUSE_EXITGAME].SetPosition(&vPos);
+ // Hide the BUTTON_PAUSE_SAVEGAME
+ XuiElementSetShow(m_Buttons[BUTTON_PAUSE_SAVEGAME],FALSE);
+ }
+ }
+ else
+ {
+ D3DXVECTOR3 vPos;
+ m_Buttons[BUTTON_PAUSE_LEADERBOARDS].GetPosition(&vPos);
+ m_Buttons[BUTTON_PAUSE_EXITGAME].SetPosition(&vPos);
+ // Hide the BUTTON_PAUSE_LEADERBOARDS, BUTTON_PAUSE_ACHIEVEMENTS and BUTTON_PAUSE_SAVEGAME
+ XuiElementSetShow(m_Buttons[BUTTON_PAUSE_LEADERBOARDS],FALSE);
+ XuiElementSetShow(m_Buttons[BUTTON_PAUSE_ACHIEVEMENTS],FALSE);
+ XuiElementSetShow(m_Buttons[BUTTON_PAUSE_SAVEGAME],FALSE);
+ }
+
+ // is saving disabled?
+ if(StorageManager.GetSaveDisabled())
+ {
+ // disable save button
+ m_Buttons[BUTTON_PAUSE_SAVEGAME].SetEnable(FALSE);
+ m_Buttons[BUTTON_PAUSE_SAVEGAME].EnableInput(FALSE);
+ }
+
+ m_iLastButtonPressed=0;
+
+ // get rid of the quadrant display if it's on
+ CXuiSceneBase::HidePressStart();
+
+ XuiSetTimer(m_hObj,IGNORE_KEYPRESS_TIMERID,IGNORE_KEYPRESS_TIME);
+
+ if( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 )
+ {
+ app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_PauseServer,(void *)TRUE);
+ }
+
+ TelemetryManager->RecordMenuShown(m_iPad, eUIScene_PauseMenu, 0);
+ TelemetryManager->RecordPauseOrInactive(m_iPad);
+
+ return S_OK;
+}
+
+//----------------------------------------------------------------------------------
+// Handler for the button press message.
+//----------------------------------------------------------------------------------
+HRESULT UIScene_PauseMenu::OnNotifyPressEx(HXUIOBJ hObjPressed, XUINotifyPress* pNotifyPressData, BOOL& rfHandled)
+{
+ if(m_bIgnoreInput) return S_OK;
+
+ // This assumes all buttons can only be pressed with the A button
+ ui.AnimateKeyPress(pNotifyPressData->UserIndex, VK_PAD_A);
+
+ unsigned int uiButtonCounter=0;
+
+ while((uiButtonCounter<BUTTONS_PAUSE_MAX) && (m_Buttons[uiButtonCounter]!=hObjPressed)) uiButtonCounter++;
+
+ Minecraft *pMinecraft=Minecraft::GetInstance();
+
+ // ignore buttons not from this user
+ //if(pNotifyPressData->UserIndex!=pMinecraft->player->GetXboxPad()) return S_OK;
+
+ // Determine which button was pressed,
+ // and call the appropriate function.
+
+ // store the last button pressed, so on a nav back we can set the focus properly
+ m_iLastButtonPressed=uiButtonCounter;
+ switch(uiButtonCounter)
+ {
+ case BUTTON_PAUSE_RESUMEGAME:
+ if( m_iPad == ProfileManager.GetPrimaryPad() && g_NetworkManager.IsLocalGame() )
+ {
+ app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_PauseServer,(void *)FALSE);
+ }
+ app.CloseXuiScenes(pNotifyPressData->UserIndex);
+ break;
+
+ case BUTTON_PAUSE_LEADERBOARDS:
+ {
+ UINT uiIDA[1];
+ uiIDA[0]=IDS_OK;
+
+ //4J Gordon: Being used for the leaderboards proper now
+ // guests can't look at leaderboards
+ if(ProfileManager.IsGuest(pNotifyPressData->UserIndex))
+ {
+ StorageManager.RequestMessageBox(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1);
+ }
+ else if(!ProfileManager.IsSignedInLive(pNotifyPressData->UserIndex))
+ {
+ StorageManager.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1);
+ }
+ else
+ {
+ app.NavigateToScene(pNotifyPressData->UserIndex, eUIScene_LeaderboardsMenu);
+ }
+ }
+ break;
+ case BUTTON_PAUSE_ACHIEVEMENTS:
+ // guests can't look at achievements
+ if(ProfileManager.IsGuest(pNotifyPressData->UserIndex))
+ {
+ UINT uiIDA[1];
+ uiIDA[0]=IDS_OK;
+ StorageManager.RequestMessageBox(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1);
+ }
+ else
+ {
+ XShowAchievementsUI( pNotifyPressData->UserIndex );
+ }
+
+ break;
+ case BUTTON_PAUSE_HELPANDOPTIONS:
+ if(app.GetLocalPlayerCount()>1)
+ {
+ app.NavigateToScene(pNotifyPressData->UserIndex,eUIScene_HelpAndOptionsMenu);
+ }
+ else
+ {
+ app.NavigateToScene(pNotifyPressData->UserIndex,eUIScene_HelpAndOptionsMenu);
+ }
+ break;
+
+ case BUTTON_PAUSE_SAVEGAME:
+ {
+ // 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();
+ DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack;
+
+ m_pDLCPack=pDLCTexPack->getDLCInfoParentPack();//tPack->getDLCPack();
+
+ if(!m_pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" ))
+ {
+ // upsell
+ ULONGLONG ullOfferID_Full;
+ // get the dlc texture pack
+ DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack;
+
+ app.GetDLCFullOfferIDForPackID(pDLCTexPack->getDLCParentPackId(),&ullOfferID_Full);
+
+ // tell sentient about the upsell of the full version of the texture pack
+ TelemetryManager->RecordUpsellPresented(pNotifyPressData->UserIndex, eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF);
+
+ 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
+ StorageManager.RequestMessageBox(IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, IDS_WARNING_DLC_TRIALTEXTUREPACK_TEXT, uiIDA, 2, pNotifyPressData->UserIndex,&UIScene_PauseMenu::WarningTrialTexturePackReturned,this,app.GetStringTable());
+
+ return S_OK;
+ }
+ }
+
+ // does the save exist?
+ bool bSaveExists;
+ C4JStorage::ELoadGameStatus result=StorageManager.DoesSaveExist(&bSaveExists);
+
+ if(result == C4JStorage::ELoadGame_DeviceRemoved)
+ {
+ // this will be a tester trying to be clever
+ UINT uiIDA[2];
+ uiIDA[0]=IDS_SELECTANEWDEVICE;
+ uiIDA[1]=IDS_NODEVICE_DECLINE;
+
+ StorageManager.RequestMessageBox(IDS_STORAGEDEVICEPROBLEM_TITLE, IDS_FAILED_TO_LOADSAVE_TEXT, uiIDA, 2, pNotifyPressData->UserIndex,&UIScene_PauseMenu::DeviceRemovedDialogReturned,this);
+ }
+ else
+ {
+ // 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;
+ StorageManager.RequestMessageBox(IDS_TITLE_SAVE_GAME, IDS_CONFIRM_SAVE_GAME, uiIDA, 2, pNotifyPressData->UserIndex,&UIScene_PauseMenu::SaveGameDialogReturned,this, app.GetStringTable());
+ }
+ else
+ {
+ // flag a app action of save game
+ app.SetAction(pNotifyPressData->UserIndex,eAppAction_SaveGame);
+ }
+ }
+ }
+
+ break;
+ case BUTTON_PAUSE_EXITGAME:
+ {
+ // Check if it's the trial version
+ if(ProfileManager.IsFullVersion())
+ {
+ UINT uiIDA[3];
+
+ // is it the primary player exiting?
+ if(pNotifyPressData->UserIndex==ProfileManager.GetPrimaryPad())
+ {
+ int playTime = -1;
+ if( pMinecraft->localplayers[pNotifyPressData->UserIndex] != NULL )
+ {
+ playTime = (int)pMinecraft->localplayers[pNotifyPressData->UserIndex]->getSessionTimer();
+ }
+
+ if(StorageManager.GetSaveDisabled())
+ {
+ uiIDA[0]=IDS_CONFIRM_CANCEL;
+ uiIDA[1]=IDS_CONFIRM_OK;
+ StorageManager.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME_PROGRESS_LOST, uiIDA, 2, pNotifyPressData->UserIndex,&UIScene_PauseMenu::ExitGameDialogReturned,this, app.GetStringTable());
+ }
+ else
+ {
+ if( g_NetworkManager.IsHost() )
+ {
+ uiIDA[0]=IDS_CONFIRM_CANCEL;
+ uiIDA[1]=IDS_EXIT_GAME_SAVE;
+ uiIDA[2]=IDS_EXIT_GAME_NO_SAVE;
+
+ if(g_NetworkManager.GetPlayerCount()>1)
+ {
+ StorageManager.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME_CONFIRM_DISCONNECT_SAVE, uiIDA, 3, pNotifyPressData->UserIndex,&UIScene_PauseMenu::ExitGameSaveDialogReturned,this, app.GetStringTable());
+ }
+ else
+ {
+ StorageManager.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 3, pNotifyPressData->UserIndex,&UIScene_PauseMenu::ExitGameSaveDialogReturned,this, app.GetStringTable());
+ }
+ }
+ else
+ {
+ uiIDA[0]=IDS_CONFIRM_CANCEL;
+ uiIDA[1]=IDS_CONFIRM_OK;
+
+ StorageManager.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 2, pNotifyPressData->UserIndex,&UIScene_PauseMenu::ExitGameDialogReturned,this, app.GetStringTable());
+ }
+ }
+ }
+ else
+ {
+ int playTime = -1;
+ if( pMinecraft->localplayers[pNotifyPressData->UserIndex] != NULL )
+ {
+ playTime = (int)pMinecraft->localplayers[pNotifyPressData->UserIndex]->getSessionTimer();
+ }
+
+ TelemetryManager->RecordLevelExit(pNotifyPressData->UserIndex, eSen_LevelExitStatus_Exited);
+
+
+ // just exit the player
+ app.SetAction(pNotifyPressData->UserIndex,eAppAction_ExitPlayer);
+ }
+ }
+ else
+ {
+ // is it the primary player exiting?
+ if(pNotifyPressData->UserIndex==ProfileManager.GetPrimaryPad())
+ {
+ int playTime = -1;
+ if( pMinecraft->localplayers[pNotifyPressData->UserIndex] != NULL )
+ {
+ playTime = (int)pMinecraft->localplayers[pNotifyPressData->UserIndex]->getSessionTimer();
+ }
+
+ // adjust the trial time played
+ CXuiSceneBase::ReduceTrialTimerValue();
+
+ // exit the level
+ UINT uiIDA[2];
+ uiIDA[0]=IDS_CONFIRM_CANCEL;
+ uiIDA[1]=IDS_CONFIRM_OK;
+ StorageManager.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME_PROGRESS_LOST, uiIDA, 2, pNotifyPressData->UserIndex,&UIScene_PauseMenu::ExitGameDialogReturned,this, app.GetStringTable());
+ }
+ else
+ {
+ int playTime = -1;
+ if( pMinecraft->localplayers[pNotifyPressData->UserIndex] != NULL )
+ {
+ playTime = (int)pMinecraft->localplayers[pNotifyPressData->UserIndex]->getSessionTimer();
+ }
+
+ TelemetryManager->RecordLevelExit(pNotifyPressData->UserIndex, eSen_LevelExitStatus_Exited);
+
+ // just exit the player
+ app.SetAction(pNotifyPressData->UserIndex,eAppAction_ExitPlayer);
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return S_OK;
+}
+
+HRESULT UIScene_PauseMenu::OnKeyDown(XUIMessageInput* pInputData, BOOL& rfHandled)
+{
+ if(m_bIgnoreInput) return S_OK;
+ // ignore repeated start presses to avoid the scene closing before it's opened
+ if((pInputData->dwKeyCode==VK_PAD_START) &&(pInputData->dwFlags&XUI_INPUT_FLAG_REPEAT ))
+ {
+ rfHandled = TRUE;
+ return S_OK;
+ }
+
+ bool bIsisPrimaryHost=g_NetworkManager.IsHost() && (ProfileManager.GetPrimaryPad()==m_iPad);
+ bool bDisplayBanTip = !g_NetworkManager.IsLocalGame() && !bIsisPrimaryHost && !ProfileManager.IsGuest(m_iPad);
+ bool bUserisClientSide = ProfileManager.IsSignedInLive(m_iPad);
+
+ ui.AnimateKeyPress(pInputData->UserIndex, pInputData->dwKeyCode);
+
+ app.DebugPrintf("PAUSE- Keydown in the xui %d flags = %d\n",pInputData->dwKeyCode,pInputData->dwFlags);
+
+
+ switch(pInputData->dwKeyCode)
+ {
+
+ case VK_PAD_B:
+ case VK_PAD_START:
+ case VK_ESCAPE:
+ app.DebugPrintf("PAUSE PRESS PROCESSING - ipad = %d, UIScene_PauseMenu::OnKeyDown - LEAVING PAUSE MENU\n",m_iPad);
+
+ if( m_iPad == ProfileManager.GetPrimaryPad() && g_NetworkManager.IsLocalGame() )
+ {
+ app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_PauseServer,(void *)FALSE);
+ }
+
+ CXuiSceneBase::PlayUISFX(eSFX_Back);
+ app.CloseXuiScenes(pInputData->UserIndex);
+ if(!ProfileManager.IsFullVersion())
+ {
+ CXuiSceneBase::ShowTrialTimer(TRUE);
+ }
+ rfHandled = TRUE;
+
+ break;
+
+ case VK_PAD_X:
+ // Change device
+ if(bIsisPrimaryHost)
+ {
+ // we need a function to deal with the return from this - if it changes, we need to update the pause menu and tooltips
+ // Fix for #12531 - TCR 001: BAS Game Stability: When a player selects to change a storage
+ // device, and repeatedly backs out of the SD screen, disconnects from LIVE, and then selects a SD, the title crashes.
+ m_bIgnoreInput=true;
+
+ StorageManager.SetSaveDevice(&UIScene_PauseMenu::DeviceSelectReturned,this,true);
+ }
+ rfHandled = TRUE;
+ break;
+
+
+ case VK_PAD_Y:
+ {
+ if(bUserisClientSide)
+ {
+ // 4J Stu - Added check in 1.8.2 bug fix (TU6) to stop repeat key presses
+ bool bCanScreenshot = true;
+ for(int j=0; j < XUSER_MAX_COUNT;++j)
+ {
+ if(app.GetXuiAction(j) == eAppAction_SocialPostScreenshot)
+ {
+ bCanScreenshot = false;
+ break;
+ }
+ }
+ if(bCanScreenshot) app.SetAction(pInputData->UserIndex,eAppAction_SocialPost);
+ }
+ rfHandled = TRUE;
+ }
+ break;
+
+ case VK_PAD_RSHOULDER:
+ if( bDisplayBanTip )
+ {
+ UINT uiIDA[2];
+ uiIDA[0]=IDS_CONFIRM_CANCEL;
+ uiIDA[1]=IDS_CONFIRM_OK;
+ StorageManager.RequestMessageBox(IDS_ACTION_BAN_LEVEL_TITLE, IDS_ACTION_BAN_LEVEL_DESCRIPTION, uiIDA, 2, pInputData->UserIndex,&UIScene_PauseMenu::BanGameDialogReturned,this, app.GetStringTable());
+
+ rfHandled = TRUE;
+ }
+ break;
+
+ // handle a keyboard Return specifically, because we've turned off the VK_A_OR_START for the pause menu, since this should exit the menu, rather than cause the button to be activated
+ case VK_RETURN:
+ // call OnNotifyPressEx directly to trigger the button press action
+
+ HXUIOBJ hObjPressed=TreeGetFocus();
+ XUINotifyPress NotifyPressData;
+ BOOL rfHandled=FALSE;
+
+ NotifyPressData.UserIndex=pInputData->UserIndex;
+ OnNotifyPressEx(hObjPressed,&NotifyPressData,rfHandled);
+
+ break;
+ }
+
+ return S_OK;
+}
+
+HRESULT UIScene_PauseMenu::OnNavReturn(HXUIOBJ hObj,BOOL& rfHandled)
+{
+ bool bIsisPrimaryHost=g_NetworkManager.IsHost() && (ProfileManager.GetPrimaryPad()==m_iPad);
+ bool bDisplayBanTip = !g_NetworkManager.IsLocalGame() && !bIsisPrimaryHost && !ProfileManager.IsGuest(m_iPad);
+ bool bUserisClientSide = ProfileManager.IsSignedInLive(m_iPad);
+
+ // Display the tooltips, we are only allowed to display "SHARE" if we have the capability (TCR).
+ if(StorageManager.GetSaveDisabled())
+ {
+ if( ProfileManager.IsFullVersion() && CSocialManager::Instance()->IsTitleAllowedToPostImages() && CSocialManager::Instance()->AreAllUsersAllowedToPostImages() && bUserisClientSide)
+ {
+ ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,bIsisPrimaryHost?IDS_TOOLTIPS_SELECTDEVICE:-1,IDS_TOOLTIPS_SHARE, -1,-1,-1,bDisplayBanTip?IDS_TOOLTIPS_BANLEVEL:-1);
+ }
+ else
+ {
+ ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,-1,-1, -1,-1,-1,bDisplayBanTip?IDS_TOOLTIPS_BANLEVEL:-1);
+ }
+ }
+ else
+ {
+ if( CSocialManager::Instance()->IsTitleAllowedToPostImages() && CSocialManager::Instance()->AreAllUsersAllowedToPostImages() && bUserisClientSide)
+ {
+ ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,bIsisPrimaryHost?IDS_TOOLTIPS_CHANGEDEVICE:-1,IDS_TOOLTIPS_SHARE, -1,-1,-1,bDisplayBanTip?IDS_TOOLTIPS_BANLEVEL:-1);
+
+ }
+ else
+ {
+ ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,bIsisPrimaryHost?IDS_TOOLTIPS_CHANGEDEVICE:-1,-1, -1,-1,-1,bDisplayBanTip?IDS_TOOLTIPS_BANLEVEL:-1);
+ }
+ }
+
+ // set the focus to the last button we were on
+ XuiElementSetUserFocus(m_Buttons[m_iLastButtonPressed],m_iPad);
+
+ CXuiSceneBase::ShowBackground( m_iPad, FALSE );
+ CXuiSceneBase::ShowDarkOverlay( m_iPad, TRUE );
+
+ bool isWrongSize = false;
+ if(app.GetLocalPlayerCount()==1)
+ {
+ // If we were created as a splitscreen scene, then it's now going to be in the wrong place. Get rid of this scene.
+ if(m_bSplitscreen)
+ {
+ CXuiSceneBase::ShowLogo( m_iPad, FALSE );
+ isWrongSize = true;
+ }
+ else
+ {
+ CXuiSceneBase::ShowLogo( m_iPad, TRUE );
+ }
+ }
+ else
+ {
+ CXuiSceneBase::ShowLogo( m_iPad, FALSE );
+ if(!m_bSplitscreen) isWrongSize = true;
+ }
+
+ if(isWrongSize)
+ {
+ if( m_iPad == ProfileManager.GetPrimaryPad() && g_NetworkManager.IsLocalGame() )
+ {
+ app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_PauseServer,(void *)FALSE);
+ }
+
+ app.CloseXuiScenes(m_iPad);
+ if(!ProfileManager.IsFullVersion())
+ {
+ CXuiSceneBase::ShowTrialTimer(TRUE);
+ }
+ }
+
+ return S_OK;
+}
+
+HRESULT UIScene_PauseMenu::OnControlNavigate(XUIMessageControlNavigate *pControlNavigateData, BOOL& bHandled)
+{
+ pControlNavigateData->hObjDest=XuiControlGetNavigation(pControlNavigateData->hObjSource,pControlNavigateData->nControlNavigate,TRUE,TRUE);
+
+ if(pControlNavigateData->hObjDest!=NULL)
+ {
+ bHandled=TRUE;
+ }
+
+ return S_OK;
+}
+
+int UIScene_PauseMenu::BanGameDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
+{
+ // results switched for this dialog
+ if(result==C4JStorage::EMessage_ResultDecline)
+ {
+ // 4J Stu - Only do this if we are currently idle, don't want the (relatively) low priority ban task overriding something else
+ if(app.GetXuiAction(iPad) == eAppAction_Idle) app.SetAction(iPad,eAppAction_BanLevel);
+ }
+ return 0;
+}
+
+int UIScene_PauseMenu::DeviceSelectReturned(void *pParam,bool bContinue)
+{
+ // Has someone pulled the ethernet cable and caused the pause menu to be closed before this callback returns?
+ if(!app.IsPauseMenuDisplayed(ProfileManager.GetPrimaryPad()))
+ {
+ return 0;
+ }
+
+ UIScene_PauseMenu* pClass = (UIScene_PauseMenu*)pParam;
+ bool bIsisPrimaryHost=g_NetworkManager.IsHost() && (ProfileManager.GetPrimaryPad()==pClass->m_iPad);
+ bool bDisplayBanTip = !g_NetworkManager.IsLocalGame() && !bIsisPrimaryHost && !ProfileManager.IsGuest(pClass->m_iPad);
+ bool bUserisClientSide = ProfileManager.IsSignedInLive(pClass->m_iPad);
+
+ //Whatever happen, we need to update the pause menu and the tooltips
+ // Display the tooltips, we are only allowed to display "SHARE" if we have the capability (TCR).
+ if(StorageManager.GetSaveDisabled())
+ {
+ if( ProfileManager.IsFullVersion() && CSocialManager::Instance()->IsTitleAllowedToPostImages() && CSocialManager::Instance()->AreAllUsersAllowedToPostImages() && bUserisClientSide)
+ {
+ ui.SetTooltips( pClass->m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,bIsisPrimaryHost?IDS_TOOLTIPS_SELECTDEVICE:-1,IDS_TOOLTIPS_SHARE, -1,-1,-1,bDisplayBanTip?IDS_TOOLTIPS_BANLEVEL:-1);
+ }
+ else
+ {
+ ui.SetTooltips( pClass->m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,-1,-1, -1,-1,-1,bDisplayBanTip?IDS_TOOLTIPS_BANLEVEL:-1);
+ }
+ // disable save button
+ // set the focus on to another button
+ pClass->m_Buttons[BUTTON_PAUSE_SAVEGAME].SetEnable(FALSE);
+ pClass->m_Buttons[BUTTON_PAUSE_SAVEGAME].EnableInput(FALSE);
+
+ pClass->m_Buttons[BUTTON_PAUSE_RESUMEGAME].InitFocus(pClass->m_iPad);
+ }
+ else
+ {
+ if( CSocialManager::Instance()->IsTitleAllowedToPostImages() && CSocialManager::Instance()->AreAllUsersAllowedToPostImages() && bUserisClientSide)
+ {
+ ui.SetTooltips(pClass->m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,bIsisPrimaryHost?IDS_TOOLTIPS_CHANGEDEVICE:-1,IDS_TOOLTIPS_SHARE, -1,-1,-1,bDisplayBanTip?IDS_TOOLTIPS_BANLEVEL:-1);
+ }
+ else
+ {
+ ui.SetTooltips( pClass->m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK,bIsisPrimaryHost?IDS_TOOLTIPS_CHANGEDEVICE:-1,-1, -1,-1,-1,bDisplayBanTip?IDS_TOOLTIPS_BANLEVEL:-1);
+ }
+ // enable save button
+ pClass->m_Buttons[BUTTON_PAUSE_SAVEGAME].SetEnable(TRUE);
+ pClass->m_Buttons[BUTTON_PAUSE_SAVEGAME].EnableInput(TRUE);
+
+ }
+
+ pClass->m_bIgnoreInput=false;
+ return 0;
+}
+
+HRESULT UIScene_PauseMenu::OnCustomMessage_Splitscreenplayer(bool bJoining, BOOL& bHandled)
+{
+ bHandled=true;
+ return app.AdjustSplitscreenScene_PlayerChanged(m_hObj,&m_OriginalPosition,m_iPad,bJoining,false);
+}
+
+HRESULT UIScene_PauseMenu::OnTimer(XUIMessageTimer *pData,BOOL& rfHandled)
+{
+ if(pData->nId==IGNORE_KEYPRESS_TIMERID)
+ {
+ XuiKillTimer(m_hObj,IGNORE_KEYPRESS_TIMERID);
+
+ // block input if we're waiting for DLC to install, and wipe the saves list. The end of dlc mounting custom message will fill the list again
+ if(app.StartInstallDLCProcess(m_iPad)==true)
+ {
+ // not doing a mount, so enable input
+ m_bIgnoreInput=true;
+ }
+ else
+ {
+ m_bIgnoreInput=false;
+ }
+ }
+
+ return S_OK;
+}
+
+
+HRESULT UIScene_PauseMenu::OnDestroy()
+{
+ //XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_AUTO);
+ TelemetryManager->RecordUnpauseOrActive(m_iPad);
+
+ if( m_iPad == ProfileManager.GetPrimaryPad() && g_NetworkManager.IsLocalGame() )
+ {
+ app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_PauseServer,(void *)FALSE);
+ }
+
+ return S_OK;
+}
+
+int UIScene_PauseMenu::DeviceRemovedDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
+{
+
+ // results switched for this dialog
+ if(result==C4JStorage::EMessage_ResultDecline)
+ {
+ // continue without saving
+ StorageManager.SetSaveDisabled(true);
+ StorageManager.SetSaveDeviceSelected(ProfileManager.GetPrimaryPad(),false);
+
+ // Has someone pulled the ethernet cable and caused the pause menu to be closed before this callback returns?
+ if(app.IsPauseMenuDisplayed(ProfileManager.GetPrimaryPad()))
+ {
+ UIScene_PauseMenu* pClass = (UIScene_PauseMenu*)pParam;
+
+ // use the device select returned function to wipe the saves list and change the tooltip
+ pClass->DeviceSelectReturned(pClass,true);
+ }
+ }
+ else
+ {
+ // Change device
+ if(app.IsPauseMenuDisplayed(ProfileManager.GetPrimaryPad()))
+ {
+ UIScene_PauseMenu* pClass = (UIScene_PauseMenu*)pParam;
+ StorageManager.SetSaveDevice(&UIScene_PauseMenu::DeviceSelectReturned,pClass,true);
+ }
+ }
+ return 0;
+}
+
+HRESULT UIScene_PauseMenu::OnCustomMessage_DLCInstalled()
+{
+ // mounted DLC may have changed
+ if(app.StartInstallDLCProcess(m_iPad)==false)
+ {
+ // not doing a mount, so re-enable input
+ m_bIgnoreInput=false;
+ }
+ else
+ {
+ m_bIgnoreInput=true;
+ }
+ // this will send a CustomMessage_DLCMountingComplete when done
+ return S_OK;
+}
+
+HRESULT UIScene_PauseMenu::OnCustomMessage_DLCMountingComplete()
+{
+ m_bIgnoreInput=false;
+ app.m_dlcManager.checkForCorruptDLCAndAlert();
+ XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_AUTO);
+ return S_OK;
+}
+
+void UIScene_PauseMenu::ShowScene(bool show)
+{
+ SetShow(show?TRUE:FALSE);
+}
+
+int UIScene_PauseMenu::WarningTrialTexturePackReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
+{
+ UIScene_PauseMenu* pScene = (UIScene_PauseMenu*)pParam;
+
+ //pScene->m_bIgnoreInput = false;
+ pScene->ShowScene( true );
+ if(result==C4JStorage::EMessage_ResultAccept)
+ {
+ if(ProfileManager.IsSignedIn(iPad))
+ {
+ ULONGLONG ullIndexA[1];
+
+ TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected();
+ // get the dlc texture pack
+ DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack;
+
+ // 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]);
+
+ // 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, ( pScene->m_pDLCPack->getPurchaseOfferId() & 0xFFFFFFFF ), eSen_UpsellOutcome_Declined);
+ }
+
+
+ return 0;
+}
+
+int UIScene_PauseMenu::ExitGameSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
+{
+ UIScene_PauseMenu *pClass = (UIScene_PauseMenu *)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
+ {
+ // 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();
+ DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack;
+
+ DLCPack *pDLCPack=pDLCTexPack->getDLCInfoParentPack();//tPack->getDLCPack();
+ if(!pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" ))
+ {
+#ifdef _XBOX
+ // upsell
+ ULONGLONG ullOfferID_Full;
+ // get the dlc texture pack
+ DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack;
+
+ 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.RequestMessageBox(IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, IDS_WARNING_DLC_TRIALTEXTUREPACK_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad() ,&UIScene_PauseMenu::WarningTrialTexturePackReturned,pClass,app.GetStringTable());
+
+ return S_OK;
+ }
+ }
+
+ // 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.RequestMessageBox(IDS_TITLE_SAVE_GAME, IDS_CONFIRM_SAVE_GAME, uiIDA, 2, ProfileManager.GetPrimaryPad(),&UIScene_PauseMenu::ExitGameAndSaveReturned,pClass, app.GetStringTable());
+ return 0;
+ }
+ else
+ {
+ 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.RequestMessageBox(IDS_TITLE_DECLINE_SAVE_GAME, IDS_CONFIRM_DECLINE_SAVE_GAME, uiIDA, 2, ProfileManager.GetPrimaryPad(),&UIScene_PauseMenu::ExitGameDeclineSaveReturned, dynamic_cast<IUIScene_PauseMenu*>(pClass), app.GetStringTable());
+ return 0;
+ }
+
+ app.SetAction(iPad,eAppAction_ExitWorld);
+ }
+ return 0;
+}
+
+int UIScene_PauseMenu::ExitGameDeclineSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
+{
+ // results switched for this dialog
+ if(result==C4JStorage::EMessage_ResultDecline)
+ {
+ MinecraftServer::getInstance()->setSaveOnExit( false );
+ // flag a app action of exit game
+ app.SetAction(iPad,eAppAction_ExitWorld);
+ }
+ else
+ {
+ // has someone disconnected the ethernet here, causing the pause menu to shut?
+ if(ui.IsPauseMenuDisplayed(ProfileManager.GetPrimaryPad()))
+ {
+ IUIScene_PauseMenu* pClass = (IUIScene_PauseMenu*)pParam;
+ UINT uiIDA[3];
+ // you cancelled the save on exit after choosing exit and save? You go back to the Exit choices then.
+ uiIDA[0]=IDS_CONFIRM_CANCEL;
+ uiIDA[1]=IDS_EXIT_GAME_SAVE;
+ uiIDA[2]=IDS_EXIT_GAME_NO_SAVE;
+
+ if(g_NetworkManager.GetPlayerCount()>1)
+ {
+ ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME_CONFIRM_DISCONNECT_SAVE, uiIDA, 3, ProfileManager.GetPrimaryPad(),&UIScene_PauseMenu::ExitGameSaveDialogReturned,pClass, app.GetStringTable(), 0, 0, false);
+ }
+ else
+ {
+ ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 3, ProfileManager.GetPrimaryPad(),&UIScene_PauseMenu::ExitGameSaveDialogReturned,pClass, app.GetStringTable(), 0, 0, false);
+ }
+ }
+
+ }
+ return 0;
+}
+
+int UIScene_PauseMenu::ExitGameAndSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
+{
+ // 4J-PB - we won't come in here if we have a trial texture pack
+
+ // results switched for this dialog
+ if(result==C4JStorage::EMessage_ResultDecline)
+ {
+ MinecraftServer::getInstance()->setSaveOnExit( true );
+ // flag a app action of exit game
+ app.SetAction(iPad,eAppAction_ExitWorld);
+ }
+ else
+ {
+ // has someone disconnected the ethernet here, causing the pause menu to shut?
+ if(ui.IsPauseMenuDisplayed(ProfileManager.GetPrimaryPad()))
+ {
+ UIScene_PauseMenu* pClass = (UIScene_PauseMenu*)pParam;
+ UINT uiIDA[3];
+ // you cancelled the save on exit after choosing exit and save? You go back to the Exit choices then.
+ uiIDA[0]=IDS_CONFIRM_CANCEL;
+ uiIDA[1]=IDS_EXIT_GAME_SAVE;
+ uiIDA[2]=IDS_EXIT_GAME_NO_SAVE;
+
+ if(g_NetworkManager.GetPlayerCount()>1)
+ {
+ ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME_CONFIRM_DISCONNECT_SAVE, uiIDA, 3, ProfileManager.GetPrimaryPad(),&UIScene_PauseMenu::ExitGameSaveDialogReturned,pClass, app.GetStringTable(), 0, 0, false);
+ }
+ else
+ {
+ ui.RequestMessageBox(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 3, ProfileManager.GetPrimaryPad(),&UIScene_PauseMenu::ExitGameSaveDialogReturned,pClass, app.GetStringTable(), 0, 0, false);
+ }
+ }
+
+ }
+ return 0;
+}
+
+int UIScene_PauseMenu::SaveGameDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
+{
+ // results switched for this dialog
+ if(result==C4JStorage::EMessage_ResultDecline)
+ {
+ // flag a app action of save game
+ app.SetAction(iPad,eAppAction_SaveGame);
+ }
+ return 0;
+}
+
+int UIScene_PauseMenu::ExitGameDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
+{
+ // results switched for this dialog
+ if(result==C4JStorage::EMessage_ResultDecline)
+ {
+ app.SetAction(iPad,eAppAction_ExitWorld);
+ }
+ return 0;
+}
+
+int UIScene_PauseMenu::SaveWorldThreadProc( LPVOID lpParameter )
+{
+ bool bAutosave=(bool)lpParameter;
+ if(bAutosave)
+ {
+ app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_AutoSaveGame);
+ }
+ else
+ {
+ app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_SaveGame);
+ }
+
+ // 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();
+
+ Minecraft *pMinecraft=Minecraft::GetInstance();
+
+ //wprintf(L"Loading world on thread\n");
+
+ if(ProfileManager.IsFullVersion())
+ {
+ app.SetGameStarted(false);
+
+ while( app.GetXuiServerAction(ProfileManager.GetPrimaryPad() ) != eXuiServerAction_Idle && !MinecraftServer::serverHalted() )
+ {
+ Sleep(10);
+ }
+
+ if(!MinecraftServer::serverHalted() && !app.GetChangingSessionType() ) app.SetGameStarted(true);
+ }
+
+ HRESULT hr = S_OK;
+ if(app.GetChangingSessionType())
+ {
+ // 4J Stu - This causes the fullscreenprogress scene to ignore the action it was given
+ hr = ERROR_CANCELLED;
+ }
+ return hr;
+}
+
+int UIScene_PauseMenu::ExitWorldThreadProc( 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);
+
+ _ExitWorld(lpParameter);
+
+ return S_OK;
+}
+
+// This function performs the meat of exiting from a level. It should be called from a thread other than the main thread.
+void UIScene_PauseMenu::_ExitWorld(LPVOID lpParameter)
+{
+ Minecraft *pMinecraft=Minecraft::GetInstance();
+
+ int exitReasonStringId = pMinecraft->progressRenderer->getCurrentTitle();
+ int exitReasonTitleId = IDS_CONNECTION_LOST;
+
+ bool saveStats = true;
+ if (pMinecraft->isClientSide() || g_NetworkManager.IsInSession())
+ {
+ if(lpParameter != NULL )
+ {
+ // 4J-PB - check if we have lost connection to Live
+ if(ProfileManager.GetLiveConnectionStatus()!=XONLINE_S_LOGON_CONNECTION_ESTABLISHED )
+ {
+ exitReasonStringId = IDS_CONNECTION_LOST_LIVE;
+ }
+ else
+ {
+ 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;
+ exitReasonTitleId = IDS_CONNECTION_FAILED;
+ break;
+ case DisconnectPacket::eDisconnect_NoUGC_Single_Local:
+ exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL;
+ exitReasonTitleId = IDS_CONNECTION_FAILED;
+ break;
+#ifdef _XBOX
+ case DisconnectPacket::eDisconnect_NoUGC_Remote:
+ exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_REMOTE;
+ exitReasonTitleId = IDS_CONNECTION_FAILED;
+ break;
+#endif
+ case DisconnectPacket::eDisconnect_NoFlying:
+ exitReasonStringId = IDS_DISCONNECTED_FLYING;
+ break;
+ case DisconnectPacket::eDisconnect_Quitting:
+ exitReasonStringId = IDS_DISCONNECTED_SERVER_QUIT;
+ break;
+ case DisconnectPacket::eDisconnect_NoFriendsInGame:
+ exitReasonStringId = IDS_DISCONNECTED_NO_FRIENDS_IN_GAME;
+ exitReasonTitleId = IDS_CANTJOIN_TITLE;
+ break;
+ case DisconnectPacket::eDisconnect_Banned:
+ exitReasonStringId = IDS_DISCONNECTED_BANNED;
+ exitReasonTitleId = IDS_CANTJOIN_TITLE;
+ break;
+ case DisconnectPacket::eDisconnect_NotFriendsWithHost:
+ exitReasonStringId = IDS_NOTALLOWED_FRIENDSOFFRIENDS;
+ exitReasonTitleId = IDS_CANTJOIN_TITLE;
+ break;
+ case DisconnectPacket::eDisconnect_OutdatedServer:
+ exitReasonStringId = IDS_DISCONNECTED_SERVER_OLD;
+ exitReasonTitleId = IDS_CANTJOIN_TITLE;
+ break;
+ case DisconnectPacket::eDisconnect_OutdatedClient:
+ exitReasonStringId = IDS_DISCONNECTED_CLIENT_OLD;
+ exitReasonTitleId = IDS_CANTJOIN_TITLE;
+ break;
+ case DisconnectPacket::eDisconnect_ServerFull:
+ exitReasonStringId = IDS_DISCONNECTED_SERVER_FULL;
+ exitReasonTitleId = IDS_CANTJOIN_TITLE;
+ break;
+ default:
+ exitReasonStringId = IDS_CONNECTION_LOST_SERVER;
+ }
+ }
+ //pMinecraft->progressRenderer->progressStartNoAbort( exitReasonStringId );
+
+ UINT uiIDA[1];
+ uiIDA[0]=IDS_CONFIRM_OK;
+ // 4J Stu - Fix for #48669 - TU5: Code: Compliance: TCR #15: Incorrect/misleading messages after signing out a profile during online game session.
+ // If the primary player is signed out, then that is most likely the cause of the disconnection so don't display a message box. This will allow the message box requested by the libraries to be brought up
+ if( ProfileManager.IsSignedIn(ProfileManager.GetPrimaryPad())) ui.RequestMessageBox( exitReasonTitleId, exitReasonStringId, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable());
+ exitReasonStringId = -1;
+
+ // 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);
+ if( pMinecraft->levels[2] != NULL ) pMinecraft->levels[2]->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();
+ if( pMinecraft->levels[2] != NULL ) pMinecraft->levels[2]->disconnect();
+ }
+
+ // 4J Stu - This only does something if we actually have a server, so don't need to do any other checks
+ MinecraftServer::HaltServer();
+
+ // We need to call the stats & leaderboards save before we exit the session
+ // 4J We need to do this in a QNet callback where it is safe
+ //pMinecraft->forceStatsSave();
+ saveStats = false;
+
+ // 4J Stu - Leave the session once the disconnect packet has been sent
+ g_NetworkManager.LeaveGame(FALSE);
+ }
+ else
+ {
+ if(lpParameter != NULL && ProfileManager.IsSignedIn(ProfileManager.GetPrimaryPad()) )
+ {
+ 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;
+ exitReasonTitleId = IDS_CONNECTION_FAILED;
+ break;
+ case DisconnectPacket::eDisconnect_NoUGC_Single_Local:
+ exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL;
+ exitReasonTitleId = IDS_CONNECTION_FAILED;
+ break;
+#ifdef _XBOX
+ case DisconnectPacket::eDisconnect_NoUGC_Remote:
+ exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_REMOTE;
+ exitReasonTitleId = IDS_CONNECTION_FAILED;
+ break;
+#endif
+ case DisconnectPacket::eDisconnect_Quitting:
+ exitReasonStringId = IDS_DISCONNECTED_SERVER_QUIT;
+ break;
+ case DisconnectPacket::eDisconnect_NoMultiplayerPrivilegesJoin:
+ exitReasonStringId = IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT;
+ break;
+ case DisconnectPacket::eDisconnect_OutdatedServer:
+ exitReasonStringId = IDS_DISCONNECTED_SERVER_OLD;
+ exitReasonTitleId = IDS_CANTJOIN_TITLE;
+ break;
+ case DisconnectPacket::eDisconnect_OutdatedClient:
+ exitReasonStringId = IDS_DISCONNECTED_CLIENT_OLD;
+ exitReasonTitleId = IDS_CANTJOIN_TITLE;
+ break;
+ case DisconnectPacket::eDisconnect_ServerFull:
+ exitReasonStringId = IDS_DISCONNECTED_SERVER_FULL;
+ exitReasonTitleId = IDS_CANTJOIN_TITLE;
+ break;
+ default:
+ exitReasonStringId = IDS_DISCONNECTED;
+ }
+ //pMinecraft->progressRenderer->progressStartNoAbort( exitReasonStringId );
+
+ UINT uiIDA[1];
+ uiIDA[0]=IDS_CONFIRM_OK;
+ ui.RequestMessageBox( exitReasonTitleId, exitReasonStringId, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable());
+ exitReasonStringId = -1;
+ }
+ }
+ // Fix for #93148 - TCR 001: BAS Game Stability: Title will crash for the multiplayer client if host of the game will exit during the clients loading to created world.
+ while( g_NetworkManager.IsNetworkThreadRunning() )
+ {
+ Sleep(1);
+ }
+ pMinecraft->setLevel(NULL,exitReasonStringId,nullptr,saveStats);
+
+ TelemetryManager->Flush();
+
+ app.m_gameRules.unloadCurrentGameRules();
+ //app.m_Audio.unloadCurrentAudioDetails();
+
+ MinecraftServer::resetFlags();
+
+ // Fix for #48385 - BLACK OPS :TU5: Functional: Client becomes pseudo soft-locked when returned to the main menu after a remote disconnect
+ // Make sure there is text explaining why the player is waiting
+ pMinecraft->progressRenderer->progressStart(IDS_EXITING_GAME);
+
+ // Fix for #13259 - CRASH: Gameplay: loading process is halted when player loads saved data
+ // 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);
+ }
+
+ app.SetChangingSessionType(false);
+ app.SetReallyChangingSessionType(false);
+}
+
+void UIScene_PauseMenu::SetIgnoreInput(bool ignoreInput)
+{
+ m_bIgnoreInput = ignoreInput;
+} \ No newline at end of file