the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
1
2#include "stdafx.h"
3#include "..\..\Minecraft.World\net.minecraft.world.entity.item.h"
4#include "..\..\Minecraft.World\net.minecraft.world.entity.player.h"
5#include "..\..\Minecraft.World\net.minecraft.world.level.tile.entity.h"
6#include "..\..\Minecraft.World\net.minecraft.world.phys.h"
7#include "..\..\Minecraft.World\InputOutputStream.h"
8#include "..\..\Minecraft.World\compression.h"
9#include "..\Options.h"
10#include "..\MinecraftServer.h"
11#include "..\MultiPlayerLevel.h"
12#include "..\GameRenderer.h"
13#include "..\ProgressRenderer.h"
14#include "..\LevelRenderer.h"
15#include "..\MobSkinMemTextureProcessor.h"
16#include "..\Minecraft.h"
17#include "..\ClientConnection.h"
18#include "..\MultiPlayerLocalPlayer.h"
19#include "..\LocalPlayer.h"
20#include "..\..\Minecraft.World\Player.h"
21#include "..\..\Minecraft.World\Inventory.h"
22#include "..\..\Minecraft.World\Level.h"
23#include "..\..\Minecraft.World\FurnaceTileEntity.h"
24#include "..\..\Minecraft.World\Container.h"
25#include "..\..\Minecraft.World\DispenserTileEntity.h"
26#include "..\..\Minecraft.World\SignTileEntity.h"
27#include "..\StatsCounter.h"
28#include "..\GameMode.h"
29#include "..\Xbox\Social\SocialManager.h"
30#include "Tutorial\TutorialMode.h"
31#if defined _XBOX || defined _WINDOWS64
32#include "..\Xbox\XML\ATGXmlParser.h"
33#include "..\Xbox\XML\xmlFilesCallback.h"
34#endif
35#include "Minecraft_Macros.h"
36#include "..\PlayerList.h"
37#include "..\ServerPlayer.h"
38#include "GameRules\ConsoleGameRules.h"
39#include "GameRules\ConsoleSchematicFile.h"
40#include "..\User.h"
41#include "..\..\Minecraft.World\LevelData.h"
42#include "..\..\Minecraft.World\net.minecraft.world.entity.player.h"
43#include "..\EntityRenderDispatcher.h"
44#include "..\..\Minecraft.World\compression.h"
45#include "..\TexturePackRepository.h"
46#include "..\DLCTexturePack.h"
47#include "DLC\DLCPack.h"
48#include "..\StringTable.h"
49#ifndef _XBOX
50#include "..\ArchiveFile.h"
51#endif
52#include "..\Minecraft.h"
53#ifdef _XBOX
54#include "..\Xbox\GameConfig\Minecraft.spa.h"
55#include "..\Xbox\Network\NetworkPlayerXbox.h"
56#include "XUI\XUI_TextEntry.h"
57#include "XUI\XUI_XZP_Icons.h"
58#include "XUI\XUI_PauseMenu.h"
59#else
60#include "UI\UI.h"
61#include "UI\UIScene_PauseMenu.h"
62#endif
63#ifdef __PS3__
64#include <sys/tty.h>
65#endif
66#ifdef __ORBIS__
67#include <save_data_dialog.h>
68#endif
69
70#include "..\Common\Leaderboards\LeaderboardManager.h"
71
72//CMinecraftApp app;
73unsigned int CMinecraftApp::m_uiLastSignInData = 0;
74
75const float CMinecraftApp::fSafeZoneX = 64.0f; // 5% of 1280
76const float CMinecraftApp::fSafeZoneY = 36.0f; // 5% of 720
77
78int CMinecraftApp::s_iHTMLFontSizesA[eHTMLSize_COUNT] =
79{
80#ifdef _XBOX
81 14,12,14,24
82#else
83 //20,15,20,24
84 20,13,20,26
85#endif
86};
87
88
89CMinecraftApp::CMinecraftApp()
90{
91 if(GAME_SETTINGS_PROFILE_DATA_BYTES != sizeof(GAME_SETTINGS))
92 {
93 // 4J Stu - See comment for GAME_SETTINGS_PROFILE_DATA_BYTES in Xbox_App.h
94 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);
95#ifndef _CONTENT_PACKAGE
96 __debugbreak();
97#endif
98 }
99
100 for(int i=0;i<XUSER_MAX_COUNT;i++)
101 {
102 m_eTMSAction[i]=eTMSAction_Idle;
103 m_eXuiAction[i]=eAppAction_Idle;
104 m_eXuiActionParam[i] = NULL;
105 //m_dwAdditionalModelParts[i] = 0;
106
107 if(FAILED(XUserGetSigninInfo(i,XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY ,&m_currentSigninInfo[i])))
108 {
109 m_currentSigninInfo[i].xuid = INVALID_XUID;
110 m_currentSigninInfo[i].dwGuestNumber = 0;
111 }
112 DebugPrintf("Player at index %d has guest number %d\n", i,m_currentSigninInfo[i].dwGuestNumber );
113
114 m_bRead_BannedListA[i]=false;
115 SetBanListCheck(i,false);
116
117 m_uiOpacityCountDown[i]=0;
118
119 }
120 m_eGlobalXuiAction=eAppAction_Idle;
121 m_eGlobalXuiServerAction=eXuiServerAction_Idle;
122
123 m_bResourcesLoaded=false;
124 m_bGameStarted=false;
125 m_bIsAppPaused=false;
126 //m_bSplitScreenEnabled = false;
127
128
129 m_bIntroRunning=false;
130 m_eGameMode=eMode_Singleplayer;
131 m_bLoadSavesFromFolderEnabled = false;
132 m_bWriteSavesToFolderEnabled = false;
133 //m_bInterfaceRenderingOff = false;
134 //m_bHandRenderingOff = false;
135 m_bTutorialMode = false;
136 m_disconnectReason = DisconnectPacket::eDisconnect_None;
137 m_bLiveLinkRequired = false;
138 m_bChangingSessionType = false;
139 m_bReallyChangingSessionType = false;
140
141#ifdef _DEBUG_MENUS_ENABLED
142
143#ifdef _CONTENT_PACKAGE
144 m_bDebugOptions=false; // make them off by default in a content package build
145#else
146 m_bDebugOptions=true;
147#endif
148#else
149 m_bDebugOptions=false;
150#endif
151
152 //ZeroMemory(m_PreviewBuffer,sizeof(XSOCIAL_PREVIEWIMAGE)*XUSER_MAX_COUNT);
153
154 m_xuidNotch = INVALID_XUID;
155
156 ZeroMemory(&m_InviteData,sizeof(JoinFromInviteData) );
157
158 // m_bRead_TMS_XUIDS_XML=false;
159 // m_bRead_TMS_DLCINFO_XML=false;
160
161 m_pDLCFileBuffer=NULL;
162 m_dwDLCFileSize=0;
163 m_pBannedListFileBuffer=NULL;
164 m_dwBannedListFileSize=0;
165
166 m_bDefaultCapeInstallAttempted=false;
167 m_bDLCInstallProcessCompleted=false;
168 m_bDLCInstallPending=false;
169 m_iTotalDLC = 0;
170 m_iTotalDLCInstalled = 0;
171 mfTrialPausedTime=0.0f;
172 m_uiAutosaveTimer=0;
173 ZeroMemory(m_pszUniqueMapName,14);
174
175
176 m_bNewDLCAvailable=false;
177 m_bSeenNewDLCTip=false;
178
179 m_uiGameHostSettings=0;
180
181#ifdef _LARGE_WORLDS
182 m_GameNewWorldSize = 0;
183 m_bGameNewWorldSizeUseMoat = false;
184 m_GameNewHellScale = 0;
185#endif
186
187 ZeroMemory(m_playerColours,MINECRAFT_NET_MAX_PLAYERS);
188
189 m_iDLCOfferC=0;
190 m_bAllDLCContentRetrieved=true;
191 InitializeCriticalSection(&csDLCDownloadQueue);
192 m_bAllTMSContentRetrieved=true;
193 m_bTickTMSDLCFiles=true;
194 InitializeCriticalSection(&csTMSPPDownloadQueue);
195 InitializeCriticalSection(&csAdditionalModelParts);
196 InitializeCriticalSection(&csAdditionalSkinBoxes);
197 InitializeCriticalSection(&csAnimOverrideBitmask);
198 InitializeCriticalSection(&csMemFilesLock);
199 InitializeCriticalSection(&csMemTPDLock);
200
201 InitializeCriticalSection(&m_saveNotificationCriticalSection);
202 m_saveNotificationDepth = 0;
203
204 m_dwRequiredTexturePackID=0;
205
206 m_bResetNether=false;
207
208#ifdef _XBOX
209 // m_bTransferSavesToXboxOne=false;
210 // m_uiTransferSlotC=5;
211#endif
212
213#if (defined _CONTENT_PACAKGE) || (defined _XBOX)
214 m_bUseDPadForDebug = false;
215#else
216 m_bUseDPadForDebug = true;
217#endif
218
219#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
220 for(int i=0;i<XUSER_MAX_COUNT;i++)
221 {
222 m_eOptionsStatusA[i]=C4JStorage::eOptions_Callback_Idle;
223 }
224#endif
225
226 for(int i=0;i<XUSER_MAX_COUNT;i++)
227 {
228 m_vBannedListA[i] = new vector<PBANNEDLISTDATA>;
229 }
230
231 LocaleAndLanguageInit();
232
233#ifdef _XBOX_ONE
234 m_hasReachedMainMenu = false;
235#endif
236}
237
238
239
240void CMinecraftApp::DebugPrintf(const char *szFormat, ...)
241{
242
243#ifndef _FINAL_BUILD
244 char buf[1024];
245 va_list ap;
246 va_start(ap, szFormat);
247 vsnprintf(buf, sizeof(buf), szFormat, ap);
248 va_end(ap);
249 OutputDebugStringA(buf);
250#endif
251
252}
253
254void CMinecraftApp::DebugPrintf(int user, const char *szFormat, ...)
255{
256#ifndef _FINAL_BUILD
257 if(user == USER_NONE)
258 return;
259 char buf[1024];
260 va_list ap;
261 va_start(ap, szFormat);
262 vsnprintf(buf, sizeof(buf), szFormat, ap);
263 va_end(ap);
264#ifdef __PS3__
265 unsigned int writelen;
266 sys_tty_write(SYS_TTYP_USER1 + ( user - 1 ), buf, strlen(buf), &writelen );
267#elif defined __PSVITA__
268 switch(user)
269 {
270 case 0:
271 {
272 SceUID tty2 = sceIoOpen("tty2:", SCE_O_WRONLY, 0);
273 if(tty2>=0)
274 {
275 std::string string1(buf);
276 sceIoWrite(tty2, string1.c_str(), string1.length());
277 sceIoClose(tty2);
278 }
279 }
280 break;
281 case 1:
282 {
283 SceUID tty3 = sceIoOpen("tty3:", SCE_O_WRONLY, 0);
284 if(tty3>=0)
285 {
286 std::string string1(buf);
287 sceIoWrite(tty3, string1.c_str(), string1.length());
288 sceIoClose(tty3);
289 }
290 }
291 break;
292 default:
293 OutputDebugStringA(buf);
294 break;
295 }
296#else
297 OutputDebugStringA(buf);
298#endif
299#ifndef _XBOX
300 if(user == USER_UI)
301 {
302 ui.logDebugString(buf);
303 }
304#endif
305#endif
306}
307
308LPCWSTR CMinecraftApp::GetString(int iID)
309{
310 //return L"Değişiklikler ve Yenilikler";
311 //return L"ÕÕÕÕÖÖÖÖ";
312 return app.m_stringTable->getString(iID);
313}
314
315void CMinecraftApp::SetAction(int iPad, eXuiAction action, LPVOID param)
316{
317 if( ( m_eXuiAction[iPad] == eAppAction_ReloadTexturePack ) && ( action == eAppAction_EthernetDisconnected ) )
318 {
319 app.DebugPrintf("Invalid change of App action for pad %d from %d to %d, ignoring\n", iPad, m_eXuiAction[iPad], action);
320 }
321 else if( ( m_eXuiAction[iPad] == eAppAction_ReloadTexturePack ) && ( action == eAppAction_ExitWorld ) )
322 {
323 app.DebugPrintf("Invalid change of App action for pad %d from %d to %d, ignoring\n", iPad, m_eXuiAction[iPad], action);
324 }
325 else if(m_eXuiAction[iPad] == eAppAction_ExitWorldCapturedThumbnail && action != eAppAction_Idle)
326 {
327 app.DebugPrintf("Invalid change of App action for pad %d from %d to %d, ignoring\n", iPad, m_eXuiAction[iPad], action);
328 }
329 else
330 {
331 app.DebugPrintf("Changing App action for pad %d from %d to %d\n", iPad, m_eXuiAction[iPad], action);
332 m_eXuiAction[iPad]=action;
333 m_eXuiActionParam[iPad] = param;
334 }
335}
336
337bool CMinecraftApp::IsAppPaused()
338{
339#if defined(_XBOX_ONE) || defined(__ORBIS__)
340 bool paused = m_bIsAppPaused;
341 EnterCriticalSection(&m_saveNotificationCriticalSection);
342 if( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 )
343 {
344 paused |= m_saveNotificationDepth > 0;
345 }
346 LeaveCriticalSection(&m_saveNotificationCriticalSection);
347 return paused;
348#else
349 return m_bIsAppPaused;
350#endif
351}
352
353void CMinecraftApp::SetAppPaused(bool val)
354{
355 m_bIsAppPaused = val;
356}
357
358void CMinecraftApp::HandleButtonPresses()
359{
360 for(int i=0;i<4;i++)
361 {
362 HandleButtonPresses(i);
363 }
364}
365
366void CMinecraftApp::HandleButtonPresses(int iPad)
367{
368
369 // // test an update of the profile data
370 // void *pData=ProfileManager.GetGameDefinedProfileData(iPad);
371 //
372 // unsigned char *pchData= (unsigned char *)pData;
373 // int iCount=0;
374 // for(int i=0;i<GAME_DEFINED_PROFILE_DATA_BYTES;i++)
375 // {
376 // pchData[i]=0xBC;
377 // //if(iCount==255) iCount = 0;
378 // }
379 // ProfileManager.WriteToProfile(iPad,true);
380}
381
382bool CMinecraftApp::LoadInventoryMenu(int iPad,shared_ptr<LocalPlayer> player,bool bNavigateBack)
383{
384 bool success = true;
385
386 InventoryScreenInput* initData = new InventoryScreenInput();
387 initData->player = player;
388 initData->bNavigateBack=bNavigateBack;
389 initData->iPad = iPad;
390
391 if(app.GetLocalPlayerCount()>1)
392 {
393 initData->bSplitscreen=true;
394 success = ui.NavigateToScene(iPad,eUIScene_InventoryMenu,initData);
395 }
396 else
397 {
398 initData->bSplitscreen=false;
399 success = ui.NavigateToScene(iPad,eUIScene_InventoryMenu,initData);
400 }
401
402 return success;
403}
404
405bool CMinecraftApp::LoadCreativeMenu(int iPad,shared_ptr<LocalPlayer> player,bool bNavigateBack)
406{
407 bool success = true;
408
409 InventoryScreenInput* initData = new InventoryScreenInput();
410 initData->player = player;
411 initData->bNavigateBack=bNavigateBack;
412 initData->iPad = iPad;
413
414 if(app.GetLocalPlayerCount()>1)
415 {
416 initData->bSplitscreen=true;
417 success = ui.NavigateToScene(iPad,eUIScene_CreativeMenu,initData);
418 }
419 else
420 {
421 initData->bSplitscreen=false;
422 success = ui.NavigateToScene(iPad,eUIScene_CreativeMenu,initData);
423 }
424
425 return success;
426}
427
428bool CMinecraftApp::LoadCrafting2x2Menu(int iPad,shared_ptr<LocalPlayer> player)
429{
430 bool success = true;
431
432 CraftingPanelScreenInput* initData = new CraftingPanelScreenInput();
433 initData->player = player;
434 initData->iContainerType=RECIPE_TYPE_2x2;
435 initData->iPad = iPad;
436 initData->x = 0;
437 initData->y = 0;
438 initData->z = 0;
439
440 if(app.GetLocalPlayerCount()>1)
441 {
442 initData->bSplitscreen=true;
443 success = ui.NavigateToScene(iPad,eUIScene_Crafting2x2Menu, initData);
444 }
445 else
446 {
447 initData->bSplitscreen=false;
448 success = ui.NavigateToScene(iPad,eUIScene_Crafting2x2Menu, initData);
449 }
450
451 return success;
452}
453
454bool CMinecraftApp::LoadCrafting3x3Menu(int iPad,shared_ptr<LocalPlayer> player, int x, int y, int z)
455{
456 bool success = true;
457
458 CraftingPanelScreenInput* initData = new CraftingPanelScreenInput();
459 initData->player = player;
460 initData->iContainerType=RECIPE_TYPE_3x3;
461 initData->iPad = iPad;
462 initData->x = x;
463 initData->y = y;
464 initData->z = z;
465
466 if(app.GetLocalPlayerCount()>1)
467 {
468 initData->bSplitscreen=true;
469 success = ui.NavigateToScene(iPad,eUIScene_Crafting3x3Menu, initData);
470 }
471 else
472 {
473 initData->bSplitscreen=false;
474 success = ui.NavigateToScene(iPad,eUIScene_Crafting3x3Menu, initData);
475 }
476
477 return success;
478}
479
480bool CMinecraftApp::LoadFireworksMenu(int iPad,shared_ptr<LocalPlayer> player, int x, int y, int z)
481{
482 bool success = true;
483
484 FireworksScreenInput* initData = new FireworksScreenInput();
485 initData->player = player;
486 initData->iPad = iPad;
487 initData->x = x;
488 initData->y = y;
489 initData->z = z;
490
491 if(app.GetLocalPlayerCount()>1)
492 {
493 initData->bSplitscreen=true;
494 success = ui.NavigateToScene(iPad,eUIScene_FireworksMenu, initData);
495 }
496 else
497 {
498 initData->bSplitscreen=false;
499 success = ui.NavigateToScene(iPad,eUIScene_FireworksMenu, initData);
500 }
501
502 return success;
503}
504
505bool CMinecraftApp::LoadEnchantingMenu(int iPad,shared_ptr<Inventory> inventory, int x, int y, int z, Level *level, const wstring &name)
506{
507 bool success = true;
508
509 EnchantingScreenInput* initData = new EnchantingScreenInput();
510 initData->inventory = inventory;
511 initData->level = level;
512 initData->x = x;
513 initData->y = y;
514 initData->z = z;
515 initData->iPad = iPad;
516 initData->name = name;
517
518 if(app.GetLocalPlayerCount()>1)
519 {
520 initData->bSplitscreen=true;
521 success = ui.NavigateToScene(iPad,eUIScene_EnchantingMenu, initData);
522 }
523 else
524 {
525 initData->bSplitscreen=false;
526 success = ui.NavigateToScene(iPad,eUIScene_EnchantingMenu, initData);
527 }
528
529 return success;
530}
531
532bool CMinecraftApp::LoadFurnaceMenu(int iPad,shared_ptr<Inventory> inventory, shared_ptr<FurnaceTileEntity> furnace)
533{
534 bool success = true;
535
536 FurnaceScreenInput* initData = new FurnaceScreenInput();
537
538 initData->furnace = furnace;
539 initData->inventory = inventory;
540 initData->iPad = iPad;
541
542 // Load the scene.
543 if(app.GetLocalPlayerCount()>1)
544 {
545 initData->bSplitscreen=true;
546 success = ui.NavigateToScene(iPad,eUIScene_FurnaceMenu, initData);
547 }
548 else
549 {
550 initData->bSplitscreen=false;
551 success = ui.NavigateToScene(iPad,eUIScene_FurnaceMenu, initData);
552 }
553
554 return success;
555}
556
557bool CMinecraftApp::LoadBrewingStandMenu(int iPad,shared_ptr<Inventory> inventory, shared_ptr<BrewingStandTileEntity> brewingStand)
558{
559 bool success = true;
560
561 BrewingScreenInput* initData = new BrewingScreenInput();
562
563 initData->brewingStand = brewingStand;
564 initData->inventory = inventory;
565 initData->iPad = iPad;
566
567 // Load the scene.
568 if(app.GetLocalPlayerCount()>1)
569 {
570 initData->bSplitscreen=true;
571 success = ui.NavigateToScene(iPad,eUIScene_BrewingStandMenu, initData);
572 }
573 else
574 {
575 initData->bSplitscreen=false;
576 success = ui.NavigateToScene(iPad,eUIScene_BrewingStandMenu, initData);
577 }
578
579 return success;
580}
581
582
583bool CMinecraftApp::LoadContainerMenu(int iPad,shared_ptr<Container> inventory, shared_ptr<Container> container)
584{
585 bool success = true;
586
587 ContainerScreenInput* initData = new ContainerScreenInput();
588
589 initData->inventory = inventory;
590 initData->container = container;
591 initData->iPad = iPad;
592
593 // Load the scene.
594 if(app.GetLocalPlayerCount()>1)
595 {
596 initData->bSplitscreen=true;
597
598 bool bLargeChest = (initData->container->getContainerSize() > 3*9)?true:false;
599 if(bLargeChest)
600 {
601 success = ui.NavigateToScene(iPad,eUIScene_LargeContainerMenu,initData);
602 }
603 else
604 {
605 success = ui.NavigateToScene(iPad,eUIScene_ContainerMenu,initData);
606 }
607 }
608 else
609 {
610 initData->bSplitscreen=false;
611 success = ui.NavigateToScene(iPad,eUIScene_ContainerMenu,initData);
612 }
613
614 return success;
615}
616
617bool CMinecraftApp::LoadTrapMenu(int iPad,shared_ptr<Container> inventory, shared_ptr<DispenserTileEntity> trap)
618{
619 bool success = true;
620
621 TrapScreenInput* initData = new TrapScreenInput();
622
623 initData->inventory = inventory;
624 initData->trap = trap;
625 initData->iPad = iPad;
626
627 // Load the scene.
628 if(app.GetLocalPlayerCount()>1)
629 {
630 initData->bSplitscreen=true;
631 success = ui.NavigateToScene(iPad,eUIScene_DispenserMenu, initData);
632 }
633 else
634 {
635 initData->bSplitscreen=false;
636 success = ui.NavigateToScene(iPad,eUIScene_DispenserMenu, initData);
637 }
638
639 return success;
640}
641
642bool CMinecraftApp::LoadSignEntryMenu(int iPad,shared_ptr<SignTileEntity> sign)
643{
644 bool success = true;
645
646 SignEntryScreenInput* initData = new SignEntryScreenInput();
647
648 initData->sign = sign;
649 initData->iPad = iPad;
650
651 success = ui.NavigateToScene(iPad,eUIScene_SignEntryMenu, initData);
652
653 delete initData;
654
655 return success;
656}
657
658bool CMinecraftApp::LoadRepairingMenu(int iPad,shared_ptr<Inventory> inventory, Level *level, int x, int y, int z)
659{
660 bool success = true;
661
662 AnvilScreenInput *initData = new AnvilScreenInput();
663 initData->inventory = inventory;
664 initData->level = level;
665 initData->x = x;
666 initData->y = y;
667 initData->z = z;
668 initData->iPad = iPad;
669 if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true;
670 else initData->bSplitscreen=false;
671
672 success = ui.NavigateToScene(iPad,eUIScene_AnvilMenu, initData);
673
674 return success;
675}
676
677bool CMinecraftApp::LoadTradingMenu(int iPad, shared_ptr<Inventory> inventory, shared_ptr<Merchant> trader, Level *level, const wstring &name)
678{
679 bool success = true;
680
681 TradingScreenInput *initData = new TradingScreenInput();
682 initData->inventory = inventory;
683 initData->trader = trader;
684 initData->level = level;
685 initData->iPad = iPad;
686 if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true;
687 else initData->bSplitscreen=false;
688
689 success = ui.NavigateToScene(iPad,eUIScene_TradingMenu, initData);
690
691 return success;
692}
693
694bool CMinecraftApp::LoadHopperMenu(int iPad ,shared_ptr<Inventory> inventory, shared_ptr<HopperTileEntity> hopper)
695{
696 bool success = true;
697
698 HopperScreenInput *initData = new HopperScreenInput();
699 initData->inventory = inventory;
700 initData->hopper = hopper;
701 initData->iPad = iPad;
702 if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true;
703 else initData->bSplitscreen=false;
704
705 success = ui.NavigateToScene(iPad,eUIScene_HopperMenu, initData);
706
707 return success;
708}
709
710bool CMinecraftApp::LoadHopperMenu(int iPad ,shared_ptr<Inventory> inventory, shared_ptr<MinecartHopper> hopper)
711{
712 bool success = true;
713
714 HopperScreenInput *initData = new HopperScreenInput();
715 initData->inventory = inventory;
716 initData->hopper = dynamic_pointer_cast<Container>(hopper);
717 initData->iPad = iPad;
718 if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true;
719 else initData->bSplitscreen=false;
720
721 success = ui.NavigateToScene(iPad,eUIScene_HopperMenu, initData);
722
723 return success;
724}
725
726
727bool CMinecraftApp::LoadHorseMenu(int iPad ,shared_ptr<Inventory> inventory, shared_ptr<Container> container, shared_ptr<EntityHorse> horse)
728{
729 bool success = true;
730
731 HorseScreenInput *initData = new HorseScreenInput();
732 initData->inventory = inventory;
733 initData->container = container;
734 initData->horse = horse;
735 initData->iPad = iPad;
736 if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true;
737 else initData->bSplitscreen=false;
738
739 success = ui.NavigateToScene(iPad,eUIScene_HorseMenu, initData);
740
741 return success;
742}
743
744bool CMinecraftApp::LoadBeaconMenu(int iPad ,shared_ptr<Inventory> inventory, shared_ptr<BeaconTileEntity> beacon)
745{
746 bool success = true;
747
748 BeaconScreenInput *initData = new BeaconScreenInput();
749 initData->inventory = inventory;
750 initData->beacon = beacon;
751 initData->iPad = iPad;
752 if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true;
753 else initData->bSplitscreen=false;
754
755 success = ui.NavigateToScene(iPad,eUIScene_BeaconMenu, initData);
756
757 return success;
758}
759
760//////////////////////////////////////////////
761// GAME SETTINGS
762//////////////////////////////////////////////
763
764#ifdef _WINDOWS64
765static void Win64_GetSettingsPath(char *outPath, DWORD size)
766{
767 GetModuleFileNameA(NULL, outPath, size);
768 char *lastSlash = strrchr(outPath, '\\');
769 if (lastSlash) *(lastSlash + 1) = '\0';
770 strncat_s(outPath, size, "settings.dat", _TRUNCATE);
771}
772static void Win64_SaveSettings(GAME_SETTINGS *gs)
773{
774 if (!gs) return;
775 char filePath[MAX_PATH] = {};
776 Win64_GetSettingsPath(filePath, MAX_PATH);
777 FILE *f = NULL;
778 if (fopen_s(&f, filePath, "wb") == 0 && f)
779 {
780 fwrite(gs, sizeof(GAME_SETTINGS), 1, f);
781 fclose(f);
782 }
783}
784static void Win64_LoadSettings(GAME_SETTINGS *gs)
785{
786 if (!gs) return;
787 char filePath[MAX_PATH] = {};
788 Win64_GetSettingsPath(filePath, MAX_PATH);
789 FILE *f = NULL;
790 if (fopen_s(&f, filePath, "rb") == 0 && f)
791 {
792 GAME_SETTINGS temp = {};
793 if (fread(&temp, sizeof(GAME_SETTINGS), 1, f) == 1)
794 memcpy(gs, &temp, sizeof(GAME_SETTINGS));
795 fclose(f);
796 }
797}
798#endif
799
800void CMinecraftApp::InitGameSettings()
801{
802 for(int i=0;i<XUSER_MAX_COUNT;i++)
803 {
804#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
805 GameSettingsA[i]=(GAME_SETTINGS *)StorageManager.GetGameDefinedProfileData(i);
806#else
807 GameSettingsA[i]=(GAME_SETTINGS *)ProfileManager.GetGameDefinedProfileData(i);
808#endif
809 // clear the flag to say the settings have changed
810 GameSettingsA[i]->bSettingsChanged=false;
811
812 //SetDefaultGameSettings(i); - done on a callback from the profile manager
813
814 // 4J-PB - adding in for Windows & PS3 to set the defaults for the joypad
815#if defined _WINDOWS64// || defined __PSVITA__
816 C_4JProfile::PROFILESETTINGS *pProfileSettings=ProfileManager.GetDashboardProfileSettings(i);
817 // clear this for now - it will come from reading the system values
818 memset(pProfileSettings,0,sizeof(C_4JProfile::PROFILESETTINGS));
819 SetDefaultOptions(pProfileSettings,i);
820 Win64_LoadSettings(GameSettingsA[i]);
821 ApplyGameSettingsChanged(i);
822#elif defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__
823 C4JStorage::PROFILESETTINGS *pProfileSettings=StorageManager.GetDashboardProfileSettings(i);
824 // 4J-PB - don't cause an options write to happen here
825 SetDefaultOptions(pProfileSettings,i,false);
826
827#endif
828 }
829}
830
831#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
832int CMinecraftApp::SetDefaultOptions(C4JStorage::PROFILESETTINGS *pSettings,const int iPad,bool bWriteProfile)
833#else
834int CMinecraftApp::SetDefaultOptions(C_4JProfile::PROFILESETTINGS *pSettings,const int iPad)
835#endif
836{
837 SetGameSettings(iPad,eGameSetting_MusicVolume,DEFAULT_VOLUME_LEVEL);
838 SetGameSettings(iPad,eGameSetting_SoundFXVolume,DEFAULT_VOLUME_LEVEL);
839 SetGameSettings(iPad,eGameSetting_Gamma,50);
840
841 // 4J-PB - Don't reset the difficult level if we're in-game
842 if(Minecraft::GetInstance()->level==NULL)
843 {
844 app.DebugPrintf("SetDefaultOptions - Difficulty = 1\n");
845 SetGameSettings(iPad,eGameSetting_Difficulty,1);
846 }
847 SetGameSettings(iPad,eGameSetting_Sensitivity_InGame,100);
848 SetGameSettings(iPad,eGameSetting_ViewBob,1);
849 SetGameSettings(iPad,eGameSetting_ControlScheme,0);
850 SetGameSettings(iPad,eGameSetting_ControlInvertLook,(pSettings->iYAxisInversion!=0)?1:0);
851 SetGameSettings(iPad,eGameSetting_ControlSouthPaw,pSettings->bSwapSticks?1:0);
852 SetGameSettings(iPad,eGameSetting_SplitScreenVertical,0);
853 SetGameSettings(iPad,eGameSetting_GamertagsVisible,1);
854
855 // Interim TU 1.6.6
856 SetGameSettings(iPad,eGameSetting_Sensitivity_InMenu,100);
857 SetGameSettings(iPad,eGameSetting_DisplaySplitscreenGamertags,1);
858 SetGameSettings(iPad,eGameSetting_Hints,1);
859 SetGameSettings(iPad,eGameSetting_Autosave,2);
860 SetGameSettings(iPad,eGameSetting_Tooltips,1);
861 SetGameSettings(iPad,eGameSetting_InterfaceOpacity,80);
862
863 // TU 5
864 SetGameSettings(iPad,eGameSetting_Clouds,1);
865 SetGameSettings(iPad,eGameSetting_Online,1);
866 SetGameSettings(iPad,eGameSetting_InviteOnly,0);
867 SetGameSettings(iPad,eGameSetting_FriendsOfFriends,1);
868
869 // default the update changes message to zero
870 // 4J-PB - We'll only display the message if the profile is pre-TU5
871 //SetGameSettings(iPad,eGameSetting_DisplayUpdateMessage,0);
872
873 // TU 6
874 SetGameSettings(iPad,eGameSetting_BedrockFog,0);
875 SetGameSettings(iPad,eGameSetting_DisplayHUD,1);
876 SetGameSettings(iPad,eGameSetting_DisplayHand,1);
877
878 // TU 7
879 SetGameSettings(iPad,eGameSetting_CustomSkinAnim,1);
880
881 // TU 9
882 SetGameSettings(iPad,eGameSetting_DeathMessages,1);
883 SetGameSettings(iPad,eGameSetting_UISize,1);
884 SetGameSettings(iPad,eGameSetting_UISizeSplitscreen,2);
885 SetGameSettings(iPad,eGameSetting_AnimatedCharacter,1);
886
887 // TU 12
888 GameSettingsA[iPad]->ucCurrentFavoriteSkinPos=0;
889 for(int i=0;i<MAX_FAVORITE_SKINS;i++)
890 {
891 GameSettingsA[iPad]->uiFavoriteSkinA[i]=0xFFFFFFFF;
892 }
893
894 // TU 13
895 GameSettingsA[iPad]->uiMashUpPackWorldsDisplay=0xFFFFFFFF;
896
897 // 1.6.4
898 app.SetGameHostOption(eGameHostOption_MobGriefing, 1);
899 app.SetGameHostOption(eGameHostOption_KeepInventory, 0);
900 app.SetGameHostOption(eGameHostOption_DoMobSpawning, 1 );
901 app.SetGameHostOption(eGameHostOption_DoMobLoot, 1 );
902 app.SetGameHostOption(eGameHostOption_DoTileDrops, 1 );
903 app.SetGameHostOption(eGameHostOption_NaturalRegeneration, 1 );
904 app.SetGameHostOption(eGameHostOption_DoDaylightCycle, 1 );
905
906 // 4J-PB - leave these in, or remove from everywhere they are referenced!
907 // Although probably best to leave in unless we split the profile settings into platform specific classes - having different meaning per platform for the same bitmask could get confusing
908 //#ifdef __PS3__
909 // PS3DEC13
910 SetGameSettings(iPad,eGameSetting_PS3_EULA_Read,0); // EULA not read
911
912 // PS3 1.05 - added Greek
913
914 // 4J-JEV: We cannot change these in-game, as they could affect localised strings and font.
915 // XB1: Fix for #172947 - Content: Gameplay: While playing in language different form system default one and resetting options to their defaults in active gameplay causes in-game language to change and HUD to disappear
916 if (!app.GetGameStarted())
917 {
918 GameSettingsA[iPad]->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
919 GameSettingsA[iPad]->ucLocale = MINECRAFT_LANGUAGE_DEFAULT; // use the system locale
920 }
921
922 //#endif
923
924#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
925 GameSettingsA[iPad]->bSettingsChanged=bWriteProfile;
926#endif
927
928 return 0;
929}
930
931#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
932int CMinecraftApp::DefaultOptionsCallback(LPVOID pParam,C4JStorage::PROFILESETTINGS *pSettings, const int iPad)
933#else
934int CMinecraftApp::DefaultOptionsCallback(LPVOID pParam,C_4JProfile::PROFILESETTINGS *pSettings, const int iPad)
935#endif
936{
937 CMinecraftApp *pApp=(CMinecraftApp *)pParam;
938
939 // flag the default options to be set
940
941 pApp->DebugPrintf("Setting default options for player %d", iPad);
942 pApp->SetAction(iPad,eAppAction_SetDefaultOptions, (LPVOID)pSettings);
943 //pApp->SetDefaultOptions(pSettings,iPad);
944
945 // if the profile data has been changed, then force a profile write
946 // It seems we're allowed to break the 5 minute rule if it's the result of a user action
947 //pApp->CheckGameSettingsChanged();
948
949 return 0;
950}
951
952#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
953
954wstring CMinecraftApp::toStringOptionsStatus(const C4JStorage::eOptionsCallback &eStatus)
955{
956#ifndef _CONTENT_PACKAGE
957 switch(eStatus)
958 {
959 case C4JStorage::eOptions_Callback_Idle: return L"Idle";
960 case C4JStorage::eOptions_Callback_Write: return L"Write";
961 case C4JStorage::eOptions_Callback_Write_Fail_NoSpace: return L"Write_Fail_NoSpace";
962 case C4JStorage::eOptions_Callback_Write_Fail: return L"Write_Fail";
963 case C4JStorage::eOptions_Callback_Read: return L"Read";
964 case C4JStorage::eOptions_Callback_Read_Fail: return L"Read_Fail";
965 case C4JStorage::eOptions_Callback_Read_FileNotFound: return L"Read_FileNotFound";
966 case C4JStorage::eOptions_Callback_Read_Corrupt: return L"Read_Corrupt";
967 case C4JStorage::eOptions_Callback_Read_CorruptDeletePending: return L"Read_CorruptDeletePending";
968 case C4JStorage::eOptions_Callback_Read_CorruptDeleted: return L"Read_CorruptDeleted";
969 default: return L"[UNRECOGNISED_OPTIONS_STATUS]";
970 }
971#else
972 return L"";
973#endif
974}
975
976#ifdef __ORBIS__
977int CMinecraftApp::OptionsDataCallback(LPVOID pParam,int iPad,unsigned short usVersion,C4JStorage::eOptionsCallback eStatus,int iBlocksRequired)
978{
979 CMinecraftApp *pApp=(CMinecraftApp *)pParam;
980 pApp->m_eOptionsStatusA[iPad]=eStatus;
981 pApp->m_eOptionsBlocksRequiredA[iPad]=iBlocksRequired;
982 return 0;
983}
984
985int CMinecraftApp::GetOptionsBlocksRequired(int iPad)
986{
987 return m_eOptionsBlocksRequiredA[iPad];
988}
989
990#else
991int CMinecraftApp::OptionsDataCallback(LPVOID pParam,int iPad,unsigned short usVersion,C4JStorage::eOptionsCallback eStatus)
992{
993 CMinecraftApp *pApp=(CMinecraftApp *)pParam;
994
995#ifndef _CONTENT_PACKAGE
996 pApp->DebugPrintf("[OptionsDataCallback] Pad_%i: new status == %ls(%i).\n", iPad, pApp->toStringOptionsStatus(eStatus).c_str(), (int) eStatus);
997#endif
998
999 pApp->m_eOptionsStatusA[iPad] = eStatus;
1000
1001 return 0;
1002}
1003#endif
1004
1005C4JStorage::eOptionsCallback CMinecraftApp::GetOptionsCallbackStatus(int iPad)
1006{
1007 return m_eOptionsStatusA[iPad];
1008}
1009
1010void CMinecraftApp::SetOptionsCallbackStatus(int iPad, C4JStorage::eOptionsCallback eStatus)
1011{
1012 m_eOptionsStatusA[iPad]=eStatus;
1013}
1014#endif
1015
1016int CMinecraftApp::OldProfileVersionCallback(LPVOID pParam,unsigned char *pucData, const unsigned short usVersion, const int iPad)
1017{
1018 // check what needs to be done with this version to update to the current one
1019
1020 switch(usVersion)
1021 {
1022#ifdef _XBOX
1023 case PROFILE_VERSION_1:
1024 case PROFILE_VERSION_2:
1025 // need to fill in values for the new profile data. No need to save the profile - that'll happen if they get changed, or if the auto save for the profile kicks in
1026 {
1027 GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
1028 pGameSettings->ucMenuSensitivity=100; //eGameSetting_Sensitivity_InMenu
1029 pGameSettings->ucInterfaceOpacity=80; //eGameSetting_Sensitivity_InMenu
1030 pGameSettings->usBitmaskValues|=0x0200; //eGameSetting_DisplaySplitscreenGamertags - on
1031 pGameSettings->usBitmaskValues|=0x0400; //eGameSetting_Hints - on
1032 pGameSettings->usBitmaskValues|=0x1000; //eGameSetting_Autosave - 2
1033 pGameSettings->usBitmaskValues|=0x8000; //eGameSetting_Tooltips - on
1034
1035 // 4J-PB - Let's also award all the achievements they have again because of the profile bug that seemed to stop the awards of some
1036 // Changing this to check the system achievements at sign-in and award any that the game says we have and the system says we haven't
1037 //ProfileManager.ReAwardAchievements(iPad);
1038
1039 pGameSettings->uiBitmaskValues=0L; // reset
1040 pGameSettings->uiBitmaskValues|=GAMESETTING_CLOUDS; //eGameSetting_Clouds - on
1041 pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on
1042 //eGameSetting_GameSetting_Invite - off
1043 pGameSettings->uiBitmaskValues|=GAMESETTING_FRIENDSOFFRIENDS; //eGameSetting_GameSetting_FriendsOfFriends - on
1044 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
1045 // TU6
1046 pGameSettings->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG; //eGameSetting_BedrockFog - off
1047 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHUD; //eGameSetting_DisplayHUD - on
1048 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHAND; //eGameSetting_DisplayHand - on
1049 // TU7
1050 pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on
1051 // TU9
1052 pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on
1053 pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2
1054 pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3
1055 pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on
1056 // TU12
1057 // favorite skins added, but only set in TU12 - set to FFs
1058 for(int i=0;i<MAX_FAVORITE_SKINS;i++)
1059 {
1060 pGameSettings->uiFavoriteSkinA[i]=0xFFFFFFFF;
1061 }
1062 pGameSettings->ucCurrentFavoriteSkinPos=0;
1063 // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list
1064 pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF;
1065
1066 // PS3 1.05 - added Greek
1067 pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
1068 }
1069 break;
1070 case PROFILE_VERSION_3:
1071
1072 {
1073 GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
1074 pGameSettings->uiBitmaskValues=0L; // reset
1075 pGameSettings->uiBitmaskValues|=GAMESETTING_CLOUDS; //eGameSetting_Clouds - on
1076 pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on
1077 //eGameSetting_GameSetting_Invite - off
1078 pGameSettings->uiBitmaskValues|=GAMESETTING_FRIENDSOFFRIENDS; //eGameSetting_GameSetting_FriendsOfFriends - on
1079 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
1080 // TU6
1081 pGameSettings->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG; //eGameSetting_BedrockFog - off
1082 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHUD; //eGameSetting_DisplayHUD - on
1083 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHAND; //eGameSetting_DisplayHand - on
1084 // TU7
1085 pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on
1086 // TU9
1087 pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on
1088 pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2
1089 pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3
1090 pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on
1091 // TU12
1092 // favorite skins added, but only set in TU12 - set to FFs
1093 for(int i=0;i<MAX_FAVORITE_SKINS;i++)
1094 {
1095 pGameSettings->uiFavoriteSkinA[i]=0xFFFFFFFF;
1096 }
1097 pGameSettings->ucCurrentFavoriteSkinPos=0;
1098 // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list
1099 pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF;
1100
1101 // PS3 1.05 - added Greek
1102 pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
1103
1104 }
1105 break;
1106 case PROFILE_VERSION_4:
1107 {
1108 GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
1109
1110 pGameSettings->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG; //eGameSetting_BedrockFog - off
1111 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHUD; //eGameSetting_DisplayHUD - on
1112 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHAND; //eGameSetting_DisplayHand - on
1113 // TU7
1114 pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on
1115 // TU9
1116 pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on
1117 pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2
1118 pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3
1119 pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on
1120
1121 // Set the online flag to on, so it's not saved if a game starts offline when the user didn't change it to be offline (xbox disconnected from LIVE)
1122 pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on
1123 // TU12
1124 // favorite skins added, but only set in TU12 - set to FFs
1125 for(int i=0;i<MAX_FAVORITE_SKINS;i++)
1126 {
1127 pGameSettings->uiFavoriteSkinA[i]=0xFFFFFFFF;
1128 }
1129 pGameSettings->ucCurrentFavoriteSkinPos=0;
1130 // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list
1131 pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF;
1132
1133 // PS3 1.05 - added Greek
1134 pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
1135
1136 }
1137
1138 break;
1139 case PROFILE_VERSION_5:
1140 {
1141 GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
1142
1143 // reset the display new message counter
1144 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
1145 // TU7
1146 pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on
1147 // TU9
1148 pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on
1149 pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2
1150 pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3
1151 pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on
1152 // Set the online flag to on, so it's not saved if a game starts offline when the user didn't change it to be offline (xbox disconnected from LIVE)
1153 pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on
1154 // TU12
1155 // favorite skins added, but only set in TU12 - set to FFs
1156 for(int i=0;i<MAX_FAVORITE_SKINS;i++)
1157 {
1158 pGameSettings->uiFavoriteSkinA[i]=0xFFFFFFFF;
1159 }
1160 pGameSettings->ucCurrentFavoriteSkinPos=0;
1161 // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list
1162 pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF;
1163
1164 // PS3 1.05 - added Greek
1165 pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
1166
1167
1168 }
1169
1170 break;
1171 case PROFILE_VERSION_6:
1172 {
1173 GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
1174
1175 // Added gui size for splitscreen and fullscreen
1176 // Added death messages toggle
1177
1178 // reset the display new message counter
1179 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
1180 // TU9
1181 pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on
1182 pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2
1183 pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3
1184 pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on
1185 // Set the online flag to on, so it's not saved if a game starts offline when the user didn't change it to be offline (xbox disconnected from LIVE)
1186 pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on
1187 // TU12
1188 // favorite skins added, but only set in TU12 - set to FFs
1189 for(int i=0;i<MAX_FAVORITE_SKINS;i++)
1190 {
1191 pGameSettings->uiFavoriteSkinA[i]=0xFFFFFFFF;
1192 }
1193 pGameSettings->ucCurrentFavoriteSkinPos=0;
1194 // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list
1195 pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF;
1196
1197 // PS3 1.05 - added Greek
1198 pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
1199
1200
1201 }
1202
1203 break;
1204
1205 case PROFILE_VERSION_7:
1206 {
1207 GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
1208 // reset the display new message counter
1209 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
1210
1211 // TU12
1212 // favorite skins added, but only set in TU12 - set to FFs
1213 for(int i=0;i<MAX_FAVORITE_SKINS;i++)
1214 {
1215 pGameSettings->uiFavoriteSkinA[i]=0xFFFFFFFF;
1216 }
1217 pGameSettings->ucCurrentFavoriteSkinPos=0;
1218 // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list
1219 pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF;
1220
1221 // PS3 1.05 - added Greek
1222 pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
1223
1224
1225 }
1226 break;
1227#endif
1228 case PROFILE_VERSION_8:
1229 {
1230 GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
1231 // reset the display new message counter
1232 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
1233
1234 // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list
1235 pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF;
1236
1237 // PS3DEC13
1238 pGameSettings->uiBitmaskValues&=~GAMESETTING_PS3EULAREAD; //eGameSetting_PS3_EULA_Read - off
1239
1240 // PS3 1.05 - added Greek
1241 pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
1242
1243 }
1244 break;
1245 case PROFILE_VERSION_9:
1246 // PS3DEC13
1247 {
1248 GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
1249 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
1250 pGameSettings->uiBitmaskValues&=~GAMESETTING_PS3EULAREAD; //eGameSetting_PS3_EULA_Read - off
1251
1252 // PS3 1.05 - added Greek
1253 pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
1254
1255 }
1256 break;
1257 case PROFILE_VERSION_10:
1258 {
1259 GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
1260 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
1261 pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
1262 }
1263 break;
1264 case PROFILE_VERSION_11:
1265 {
1266 GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
1267 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
1268 }
1269 break;
1270 case PROFILE_VERSION_12:
1271 {
1272 GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
1273 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
1274 }
1275 break;
1276 default:
1277 {
1278 // This might be from a version during testing of new profile updates
1279 app.DebugPrintf("Don't know what to do with this profile version!\n");
1280#ifndef _CONTENT_PACKAGE
1281 // __debugbreak();
1282#endif
1283
1284 GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData;
1285 pGameSettings->ucMenuSensitivity=100; //eGameSetting_Sensitivity_InMenu
1286 pGameSettings->ucInterfaceOpacity=80; //eGameSetting_Sensitivity_InMenu
1287 pGameSettings->usBitmaskValues|=0x0200; //eGameSetting_DisplaySplitscreenGamertags - on
1288 pGameSettings->usBitmaskValues|=0x0400; //eGameSetting_Hints - on
1289 pGameSettings->usBitmaskValues|=0x1000; //eGameSetting_Autosave - 2
1290 pGameSettings->usBitmaskValues|=0x8000; //eGameSetting_Tooltips - on
1291
1292 pGameSettings->uiBitmaskValues=0L; // reset
1293 pGameSettings->uiBitmaskValues|=GAMESETTING_CLOUDS; //eGameSetting_Clouds - on
1294 pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on
1295 //eGameSetting_GameSetting_Invite - off
1296 pGameSettings->uiBitmaskValues|=GAMESETTING_FRIENDSOFFRIENDS; //eGameSetting_GameSetting_FriendsOfFriends - on
1297 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter)
1298 pGameSettings->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG; //eGameSetting_BedrockFog - off
1299 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHUD; //eGameSetting_DisplayHUD - on
1300 pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHAND; //eGameSetting_DisplayHand - on
1301 pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on
1302 pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on
1303 pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2
1304 pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3
1305 pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on
1306 // TU12
1307 // favorite skins added, but only set in TU12 - set to FFs
1308 for(int i=0;i<MAX_FAVORITE_SKINS;i++)
1309 {
1310 pGameSettings->uiFavoriteSkinA[i]=0xFFFFFFFF;
1311 }
1312 pGameSettings->ucCurrentFavoriteSkinPos=0;
1313 // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list
1314 pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF;
1315
1316 // PS3DEC13
1317 pGameSettings->uiBitmaskValues&=~GAMESETTING_PS3EULAREAD; //eGameSetting_PS3_EULA_Read - off
1318
1319 // PS3 1.05 - added Greek
1320 pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
1321
1322 }
1323 break;
1324 }
1325
1326 return 0;
1327}
1328
1329void CMinecraftApp::ApplyGameSettingsChanged(int iPad)
1330{
1331 ActionGameSettings(iPad,eGameSetting_MusicVolume );
1332 ActionGameSettings(iPad,eGameSetting_SoundFXVolume );
1333 ActionGameSettings(iPad,eGameSetting_Gamma );
1334 ActionGameSettings(iPad,eGameSetting_Difficulty );
1335 ActionGameSettings(iPad,eGameSetting_Sensitivity_InGame );
1336 ActionGameSettings(iPad,eGameSetting_ViewBob );
1337 ActionGameSettings(iPad,eGameSetting_ControlScheme );
1338 ActionGameSettings(iPad,eGameSetting_ControlInvertLook);
1339 ActionGameSettings(iPad,eGameSetting_ControlSouthPaw);
1340 ActionGameSettings(iPad,eGameSetting_SplitScreenVertical);
1341 ActionGameSettings(iPad,eGameSetting_GamertagsVisible);
1342
1343 // Interim TU 1.6.6
1344 ActionGameSettings(iPad,eGameSetting_Sensitivity_InMenu );
1345 ActionGameSettings(iPad,eGameSetting_DisplaySplitscreenGamertags);
1346 ActionGameSettings(iPad,eGameSetting_Hints);
1347 ActionGameSettings(iPad,eGameSetting_InterfaceOpacity);
1348 ActionGameSettings(iPad,eGameSetting_Tooltips);
1349
1350 ActionGameSettings(iPad,eGameSetting_Clouds);
1351 ActionGameSettings(iPad,eGameSetting_BedrockFog);
1352 ActionGameSettings(iPad,eGameSetting_DisplayHUD);
1353 ActionGameSettings(iPad,eGameSetting_DisplayHand);
1354 ActionGameSettings(iPad,eGameSetting_CustomSkinAnim);
1355 ActionGameSettings(iPad,eGameSetting_DeathMessages);
1356 ActionGameSettings(iPad,eGameSetting_UISize);
1357 ActionGameSettings(iPad,eGameSetting_UISizeSplitscreen);
1358 ActionGameSettings(iPad,eGameSetting_AnimatedCharacter);
1359
1360 ActionGameSettings(iPad,eGameSetting_PS3_EULA_Read);
1361
1362}
1363
1364void CMinecraftApp::ActionGameSettings(int iPad,eGameSetting eVal)
1365{
1366 Minecraft *pMinecraft=Minecraft::GetInstance();
1367 switch(eVal)
1368 {
1369 case eGameSetting_MusicVolume:
1370 if(iPad==ProfileManager.GetPrimaryPad())
1371 {
1372 pMinecraft->options->set(Options::Option::MUSIC,((float)GameSettingsA[iPad]->ucMusicVolume)/100.0f);
1373 }
1374 break;
1375 case eGameSetting_SoundFXVolume:
1376 if(iPad==ProfileManager.GetPrimaryPad())
1377 {
1378 pMinecraft->options->set(Options::Option::SOUND,((float)GameSettingsA[iPad]->ucSoundFXVolume)/100.0f);
1379 }
1380 break;
1381 case eGameSetting_Gamma:
1382 if(iPad==ProfileManager.GetPrimaryPad())
1383 {
1384#if defined(_WIN64) || defined(_WINDOWS64)
1385 pMinecraft->options->set(Options::Option::GAMMA, ((float)GameSettingsA[iPad]->ucGamma) / 100.0f);
1386#else
1387 // ucGamma range is 0-100, UpdateGamma is 0 - 32768
1388 float fVal=((float)GameSettingsA[iPad]->ucGamma)*327.68f;
1389 RenderManager.UpdateGamma((unsigned short)fVal);
1390#endif
1391 }
1392
1393 break;
1394 case eGameSetting_Difficulty:
1395 if(iPad==ProfileManager.GetPrimaryPad())
1396 {
1397 pMinecraft->options->toggle(Options::Option::DIFFICULTY,GameSettingsA[iPad]->usBitmaskValues&0x03);
1398 app.DebugPrintf("Difficulty toggle to %d\n",GameSettingsA[iPad]->usBitmaskValues&0x03);
1399
1400 // Update the Game Host setting
1401 app.SetGameHostOption(eGameHostOption_Difficulty,pMinecraft->options->difficulty);
1402
1403 // send this to the other players if we are in-game
1404 bool bInGame=pMinecraft->level!=NULL;
1405
1406 // Game Host only (and for now we can't change the diff while in game, so this shouldn't happen)
1407 if(bInGame && g_NetworkManager.IsHost() && (iPad==ProfileManager.GetPrimaryPad()))
1408 {
1409 app.SetXuiServerAction(iPad,eXuiServerAction_ServerSettingChanged_Difficulty);
1410 }
1411 }
1412 else
1413 {
1414 app.DebugPrintf("NOT ACTIONING DIFFICULTY - Primary pad is %d, This pad is %d\n",ProfileManager.GetPrimaryPad(),iPad);
1415 }
1416
1417 break;
1418 case eGameSetting_Sensitivity_InGame:
1419 // 4J-PB - we don't use the options value
1420 // tell the input that we've changed the sensitivity - range of the slider is 0 to 200, default is 100
1421 pMinecraft->options->set(Options::Option::SENSITIVITY,((float)GameSettingsA[iPad]->ucSensitivity)/100.0f);
1422 //InputManager.SetJoypadSensitivity(iPad,((float)GameSettingsA[iPad]->ucSensitivity)/100.0f);
1423
1424 break;
1425 case eGameSetting_ViewBob:
1426 // 4J-PB - not handled here any more - it's read from the gamesettings per player
1427 //pMinecraft->options->toggle(Options::Option::VIEW_BOBBING,GameSettingsA[iPad]->usBitmaskValues&0x04);
1428 break;
1429 case eGameSetting_ControlScheme:
1430 InputManager.SetJoypadMapVal(iPad,(GameSettingsA[iPad]->usBitmaskValues&0x30)>>4);
1431 break;
1432
1433 case eGameSetting_ControlInvertLook:
1434 // Nothing specific to do for this setting.
1435 break;
1436
1437 case eGameSetting_ControlSouthPaw:
1438 // What is the setting?
1439 if ( GameSettingsA[iPad]->usBitmaskValues & 0x80 )
1440 {
1441 // Southpaw.
1442 InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_LX, AXIS_MAP_RX );
1443 InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_LY, AXIS_MAP_RY );
1444 InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_RX, AXIS_MAP_LX );
1445 InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_RY, AXIS_MAP_LY );
1446 InputManager.SetJoypadStickTriggerMap( iPad, TRIGGER_MAP_0, TRIGGER_MAP_1 );
1447 InputManager.SetJoypadStickTriggerMap( iPad, TRIGGER_MAP_1, TRIGGER_MAP_0 );
1448 }
1449 else
1450 {
1451 // Right handed.
1452 InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_LX, AXIS_MAP_LX );
1453 InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_LY, AXIS_MAP_LY );
1454 InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_RX, AXIS_MAP_RX );
1455 InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_RY, AXIS_MAP_RY );
1456 InputManager.SetJoypadStickTriggerMap( iPad, TRIGGER_MAP_0, TRIGGER_MAP_0 );
1457 InputManager.SetJoypadStickTriggerMap( iPad, TRIGGER_MAP_1, TRIGGER_MAP_1 );
1458 }
1459 break;
1460 case eGameSetting_SplitScreenVertical:
1461 if(iPad==ProfileManager.GetPrimaryPad())
1462 {
1463 pMinecraft->updatePlayerViewportAssignments();
1464 }
1465 break;
1466 case eGameSetting_GamertagsVisible:
1467 {
1468 bool bInGame=pMinecraft->level!=NULL;
1469
1470 // Game Host only
1471 if(bInGame && g_NetworkManager.IsHost() && (iPad==ProfileManager.GetPrimaryPad()))
1472 {
1473 // Update the Game Host setting if you are the host and you are in-game
1474 app.SetGameHostOption(eGameHostOption_Gamertags,((GameSettingsA[iPad]->usBitmaskValues&0x0008)!=0)?1:0);
1475 app.SetXuiServerAction(iPad,eXuiServerAction_ServerSettingChanged_Gamertags);
1476
1477 PlayerList *players = MinecraftServer::getInstance()->getPlayerList();
1478 for(AUTO_VAR(it3, players->players.begin()); it3 != players->players.end(); ++it3)
1479 {
1480 shared_ptr<ServerPlayer> decorationPlayer = *it3;
1481 decorationPlayer->setShowOnMaps((app.GetGameHostOption(eGameHostOption_Gamertags)!=0)?true:false);
1482 }
1483 }
1484 }
1485 break;
1486 // Interim TU 1.6.6
1487 case eGameSetting_Sensitivity_InMenu:
1488 // 4J-PB - we don't use the options value
1489 // tell the input that we've changed the sensitivity - range of the slider is 0 to 200, default is 100
1490 //pMinecraft->options->set(Options::Option::SENSITIVITY,((float)GameSettingsA[iPad]->ucSensitivity)/100.0f);
1491 //InputManager.SetJoypadSensitivity(iPad,((float)GameSettingsA[iPad]->ucSensitivity)/100.0f);
1492
1493 break;
1494
1495 case eGameSetting_DisplaySplitscreenGamertags:
1496 for( BYTE idx = 0; idx < XUSER_MAX_COUNT; ++idx)
1497 {
1498 if(pMinecraft->localplayers[idx] != NULL)
1499 {
1500 if(pMinecraft->localplayers[idx]->m_iScreenSection==C4JRender::VIEWPORT_TYPE_FULLSCREEN)
1501 {
1502 ui.DisplayGamertag(idx,false);
1503 }
1504 else
1505 {
1506 ui.DisplayGamertag(idx,true);
1507 }
1508 }
1509 }
1510
1511 break;
1512 case eGameSetting_InterfaceOpacity:
1513 // update the tooltips display
1514 ui.RefreshTooltips( iPad);
1515
1516 break;
1517 case eGameSetting_Hints:
1518 //nothing to do here
1519 break;
1520 case eGameSetting_Tooltips:
1521 if((GameSettingsA[iPad]->usBitmaskValues&0x8000)!=0)
1522 {
1523 ui.SetEnableTooltips(iPad,TRUE);
1524 }
1525 else
1526 {
1527 ui.SetEnableTooltips(iPad,FALSE);
1528 }
1529 break;
1530 case eGameSetting_Clouds:
1531 //nothing to do here
1532 break;
1533 case eGameSetting_Online:
1534 //nothing to do here
1535 break;
1536 case eGameSetting_InviteOnly:
1537 //nothing to do here
1538 break;
1539 case eGameSetting_FriendsOfFriends:
1540 //nothing to do here
1541 break;
1542 case eGameSetting_BedrockFog:
1543 {
1544 bool bInGame=pMinecraft->level!=NULL;
1545
1546 // Game Host only
1547 if(bInGame && g_NetworkManager.IsHost() && (iPad==ProfileManager.GetPrimaryPad()))
1548 {
1549 // Update the Game Host setting if you are the host and you are in-game
1550 app.SetGameHostOption(eGameHostOption_BedrockFog,GetGameSettings(iPad,eGameSetting_BedrockFog)?1:0);
1551 app.SetXuiServerAction(iPad,eXuiServerAction_ServerSettingChanged_BedrockFog);
1552 }
1553 }
1554 break;
1555 case eGameSetting_DisplayHUD:
1556 //nothing to do here
1557 break;
1558 case eGameSetting_DisplayHand:
1559 //nothing to do here
1560 break;
1561 case eGameSetting_CustomSkinAnim:
1562 //nothing to do here
1563 break;
1564 case eGameSetting_DeathMessages:
1565 //nothing to do here
1566 break;
1567 case eGameSetting_UISize:
1568 //nothing to do here
1569 break;
1570 case eGameSetting_UISizeSplitscreen:
1571 //nothing to do here
1572 break;
1573 case eGameSetting_AnimatedCharacter:
1574 //nothing to do here
1575 break;
1576 case eGameSetting_PS3_EULA_Read:
1577 //nothing to do here
1578 break;
1579 case eGameSetting_PSVita_NetworkModeAdhoc:
1580 //nothing to do here
1581 break;
1582 }
1583}
1584
1585void CMinecraftApp::SetPlayerSkin(int iPad,const wstring &name)
1586{
1587 DWORD skinId = app.getSkinIdFromPath(name);
1588
1589 SetPlayerSkin(iPad,skinId);
1590}
1591
1592void CMinecraftApp::SetPlayerSkin(int iPad,DWORD dwSkinId)
1593{
1594 DebugPrintf("Setting skin for %d to %08X\n", iPad, dwSkinId);
1595
1596 GameSettingsA[iPad]->dwSelectedSkin = dwSkinId;
1597 GameSettingsA[iPad]->bSettingsChanged = true;
1598
1599 TelemetryManager->RecordSkinChanged(iPad, GameSettingsA[iPad]->dwSelectedSkin);
1600
1601 if(Minecraft::GetInstance()->localplayers[iPad]!=NULL) Minecraft::GetInstance()->localplayers[iPad]->setAndBroadcastCustomSkin(dwSkinId);
1602}
1603
1604
1605wstring CMinecraftApp::GetPlayerSkinName(int iPad)
1606{
1607 return app.getSkinPathFromId(GameSettingsA[iPad]->dwSelectedSkin);
1608}
1609
1610DWORD CMinecraftApp::GetPlayerSkinId(int iPad)
1611{
1612 // 4J-PB -check the user has rights to use this skin - they may have had at some point but the entitlement has been removed.
1613 DLCPack *Pack=NULL;
1614 DLCSkinFile *skinFile=NULL;
1615 DWORD dwSkin=GameSettingsA[iPad]->dwSelectedSkin;
1616 wchar_t chars[256];
1617
1618 if( GET_IS_DLC_SKIN_FROM_BITMASK(dwSkin) )
1619 {
1620 // 4J Stu - DLC skins are numbered using decimal rather than hex to make it easier to number manually
1621 swprintf(chars, 256, L"dlcskin%08d.png", GET_DLC_SKIN_ID_FROM_BITMASK(dwSkin));
1622
1623 Pack=app.m_dlcManager.getPackContainingSkin(chars);
1624
1625 if(Pack)
1626 {
1627 skinFile = Pack->getSkinFile(chars);
1628
1629 bool bSkinIsFree = skinFile->getParameterAsBool( DLCManager::e_DLCParamType_Free );
1630 bool bLicensed = Pack->hasPurchasedFile( DLCManager::e_DLCType_Skin, skinFile->getPath() );
1631
1632 if(bSkinIsFree || bLicensed)
1633 {
1634 return dwSkin;
1635 }
1636 else
1637 {
1638 return 0;
1639 }
1640 }
1641 }
1642
1643
1644 return dwSkin;
1645}
1646
1647DWORD CMinecraftApp::GetAdditionalModelParts(int iPad)
1648{
1649 return m_dwAdditionalModelParts[iPad];
1650}
1651
1652
1653void CMinecraftApp::SetPlayerCape(int iPad,const wstring &name)
1654{
1655 DWORD capeId = Player::getCapeIdFromPath(name);
1656
1657 SetPlayerCape(iPad,capeId);
1658}
1659
1660void CMinecraftApp::SetPlayerCape(int iPad,DWORD dwCapeId)
1661{
1662 DebugPrintf("Setting cape for %d to %08X\n", iPad, dwCapeId);
1663
1664 GameSettingsA[iPad]->dwSelectedCape = dwCapeId;
1665 GameSettingsA[iPad]->bSettingsChanged = true;
1666
1667 //SentientManager.RecordSkinChanged(iPad, GameSettingsA[iPad]->dwSelectedSkin);
1668
1669 if(Minecraft::GetInstance()->localplayers[iPad]!=NULL) Minecraft::GetInstance()->localplayers[iPad]->setAndBroadcastCustomCape(dwCapeId);
1670}
1671
1672wstring CMinecraftApp::GetPlayerCapeName(int iPad)
1673{
1674 return Player::getCapePathFromId(GameSettingsA[iPad]->dwSelectedCape);
1675}
1676
1677DWORD CMinecraftApp::GetPlayerCapeId(int iPad)
1678{
1679 return GameSettingsA[iPad]->dwSelectedCape;
1680}
1681
1682void CMinecraftApp::SetPlayerFavoriteSkin(int iPad, int iIndex,unsigned int uiSkinID)
1683{
1684 DebugPrintf("Setting favorite skin for %d to %08X\n", iPad, uiSkinID);
1685
1686 GameSettingsA[iPad]->uiFavoriteSkinA[iIndex] = uiSkinID;
1687 GameSettingsA[iPad]->bSettingsChanged = true;
1688}
1689
1690unsigned int CMinecraftApp::GetPlayerFavoriteSkin(int iPad,int iIndex)
1691{
1692 return GameSettingsA[iPad]->uiFavoriteSkinA[iIndex];
1693}
1694
1695unsigned char CMinecraftApp::GetPlayerFavoriteSkinsPos(int iPad)
1696{
1697 return GameSettingsA[iPad]->ucCurrentFavoriteSkinPos;
1698}
1699
1700void CMinecraftApp::SetPlayerFavoriteSkinsPos(int iPad, int iPos)
1701{
1702 GameSettingsA[iPad]->ucCurrentFavoriteSkinPos=(unsigned char)iPos;
1703 GameSettingsA[iPad]->bSettingsChanged = true;
1704}
1705
1706unsigned int CMinecraftApp::GetPlayerFavoriteSkinsCount(int iPad)
1707{
1708 unsigned int uiCount=0;
1709 for(int i=0;i<MAX_FAVORITE_SKINS;i++)
1710 {
1711 if(GameSettingsA[iPad]->uiFavoriteSkinA[i]!=0xFFFFFFFF)
1712 {
1713 uiCount++;
1714 }
1715 else
1716 {
1717 break;
1718 }
1719 }
1720 return uiCount;
1721}
1722
1723void CMinecraftApp::ValidateFavoriteSkins(int iPad)
1724{
1725 unsigned int uiCount=GetPlayerFavoriteSkinsCount(iPad);
1726
1727 // remove invalid skins
1728 unsigned int uiValidSkin=0;
1729 wchar_t chars[256];
1730
1731 for(unsigned int i=0;i<uiCount;i++)
1732 {
1733 // get the pack number from the skin id
1734 swprintf(chars, 256, L"dlcskin%08d.png", app.GetPlayerFavoriteSkin(iPad,i));
1735
1736 // Also check they haven't reverted to a trial pack
1737 DLCPack *pDLCPack=app.m_dlcManager.getPackContainingSkin(chars);
1738
1739 if(pDLCPack!=NULL)
1740 {
1741 // 4J-PB - We should let players add the free skins to their favourites as well!
1742 //DLCFile *pDLCFile=pDLCPack->getFile(DLCManager::e_DLCType_Skin,chars);
1743 DLCSkinFile *pSkinFile = pDLCPack->getSkinFile(chars);
1744
1745 if( pDLCPack->hasPurchasedFile(DLCManager::e_DLCType_Skin, L"") || (pSkinFile && pSkinFile->isFree()))
1746 {
1747 GameSettingsA[iPad]->uiFavoriteSkinA[uiValidSkin++]=GameSettingsA[iPad]->uiFavoriteSkinA[i];
1748 }
1749 }
1750 }
1751
1752 for(unsigned int i=uiValidSkin;i<MAX_FAVORITE_SKINS;i++)
1753 {
1754 GameSettingsA[iPad]->uiFavoriteSkinA[i]=0xFFFFFFFF;
1755 }
1756}
1757
1758// Mash-up pack worlds
1759void CMinecraftApp::HideMashupPackWorld(int iPad, unsigned int iMashupPackID)
1760{
1761 unsigned int uiPackID=iMashupPackID - 1024; // mash-up ids start at 1024
1762 GameSettingsA[iPad]->uiMashUpPackWorldsDisplay&=~(1<<uiPackID);
1763 GameSettingsA[iPad]->bSettingsChanged = true;
1764}
1765
1766void CMinecraftApp::EnableMashupPackWorlds(int iPad)
1767{
1768 GameSettingsA[iPad]->uiMashUpPackWorldsDisplay=0xFFFFFFFF;
1769 GameSettingsA[iPad]->bSettingsChanged = true;
1770}
1771
1772unsigned int CMinecraftApp::GetMashupPackWorlds(int iPad)
1773{
1774 return GameSettingsA[iPad]->uiMashUpPackWorldsDisplay;
1775}
1776
1777void CMinecraftApp::SetMinecraftLanguage(int iPad, unsigned char ucLanguage)
1778{
1779 GameSettingsA[iPad]->ucLanguage = ucLanguage;
1780 GameSettingsA[iPad]->bSettingsChanged = true;
1781}
1782
1783unsigned char CMinecraftApp::GetMinecraftLanguage(int iPad)
1784{
1785 // if there are no game settings read yet, return the default language
1786 if(GameSettingsA[iPad]==NULL)
1787 {
1788 return 0;
1789 }
1790 else
1791 {
1792 return GameSettingsA[iPad]->ucLanguage;
1793 }
1794}
1795
1796void CMinecraftApp::SetMinecraftLocale(int iPad, unsigned char ucLocale)
1797{
1798 GameSettingsA[iPad]->ucLocale = ucLocale;
1799 GameSettingsA[iPad]->bSettingsChanged = true;
1800}
1801
1802unsigned char CMinecraftApp::GetMinecraftLocale(int iPad)
1803{
1804 // if there are no game settings read yet, return the default language
1805 if(GameSettingsA[iPad]==NULL)
1806 {
1807 return 0;
1808 }
1809 else
1810 {
1811 return GameSettingsA[iPad]->ucLocale;
1812 }
1813}
1814
1815void CMinecraftApp::SetGameSettings(int iPad,eGameSetting eVal,unsigned char ucVal)
1816{
1817 //Minecraft *pMinecraft=Minecraft::GetInstance();
1818
1819 switch(eVal)
1820 {
1821 case eGameSetting_MusicVolume:
1822 if(GameSettingsA[iPad]->ucMusicVolume!=ucVal)
1823 {
1824 GameSettingsA[iPad]->ucMusicVolume=ucVal;
1825 if(iPad==ProfileManager.GetPrimaryPad())
1826 {
1827 ActionGameSettings(iPad,eVal);
1828 }
1829 GameSettingsA[iPad]->bSettingsChanged=true;
1830 }
1831 break;
1832 case eGameSetting_SoundFXVolume:
1833 if(GameSettingsA[iPad]->ucSoundFXVolume!=ucVal)
1834 {
1835 GameSettingsA[iPad]->ucSoundFXVolume=ucVal;
1836 if(iPad==ProfileManager.GetPrimaryPad())
1837 {
1838 ActionGameSettings(iPad,eVal);
1839 }
1840 GameSettingsA[iPad]->bSettingsChanged=true;
1841 }
1842 break;
1843 case eGameSetting_Gamma:
1844 if(GameSettingsA[iPad]->ucGamma!=ucVal)
1845 {
1846 GameSettingsA[iPad]->ucGamma=ucVal;
1847 if(iPad==ProfileManager.GetPrimaryPad())
1848 {
1849 ActionGameSettings(iPad,eVal);
1850 }
1851 GameSettingsA[iPad]->bSettingsChanged=true;
1852 }
1853 break;
1854 case eGameSetting_Difficulty:
1855 if((GameSettingsA[iPad]->usBitmaskValues&0x03)!=(ucVal&0x03))
1856 {
1857 GameSettingsA[iPad]->usBitmaskValues&=~0x03;
1858 GameSettingsA[iPad]->usBitmaskValues|=ucVal&0x03;
1859 if(iPad==ProfileManager.GetPrimaryPad())
1860 {
1861 ActionGameSettings(iPad,eVal);
1862 }
1863 GameSettingsA[iPad]->bSettingsChanged=true;
1864 }
1865 break;
1866 case eGameSetting_Sensitivity_InGame:
1867 if(GameSettingsA[iPad]->ucSensitivity!=ucVal)
1868 {
1869 GameSettingsA[iPad]->ucSensitivity=ucVal;
1870 ActionGameSettings(iPad,eVal);
1871 GameSettingsA[iPad]->bSettingsChanged=true;
1872 }
1873 break;
1874 case eGameSetting_ViewBob:
1875 if((GameSettingsA[iPad]->usBitmaskValues&0x0004)!=((ucVal&0x01)<<2))
1876 {
1877 if(ucVal!=0)
1878 {
1879 GameSettingsA[iPad]->usBitmaskValues|=0x0004;
1880 }
1881 else
1882 {
1883 GameSettingsA[iPad]->usBitmaskValues&=~0x0004;
1884 }
1885 ActionGameSettings(iPad,eVal);
1886 GameSettingsA[iPad]->bSettingsChanged=true;
1887 }
1888 break;
1889 case eGameSetting_ControlScheme: // bits 5 and 6
1890 if((GameSettingsA[iPad]->usBitmaskValues&0x30)!=((ucVal&0x03)<<4))
1891 {
1892 GameSettingsA[iPad]->usBitmaskValues&=~0x0030;
1893 if(ucVal!=0)
1894 {
1895 GameSettingsA[iPad]->usBitmaskValues|=(ucVal&0x03)<<4;
1896 }
1897 ActionGameSettings(iPad,eVal);
1898 GameSettingsA[iPad]->bSettingsChanged=true;
1899 }
1900 break;
1901
1902 case eGameSetting_ControlInvertLook:
1903 if((GameSettingsA[iPad]->usBitmaskValues&0x0040)!=((ucVal&0x01)<<6))
1904 {
1905 if(ucVal!=0)
1906 {
1907 GameSettingsA[iPad]->usBitmaskValues|=0x0040;
1908 }
1909 else
1910 {
1911 GameSettingsA[iPad]->usBitmaskValues&=~0x0040;
1912 }
1913 ActionGameSettings(iPad,eVal);
1914 GameSettingsA[iPad]->bSettingsChanged=true;
1915 }
1916 break;
1917
1918 case eGameSetting_ControlSouthPaw:
1919 if((GameSettingsA[iPad]->usBitmaskValues&0x0080)!=((ucVal&0x01)<<7))
1920 {
1921 if(ucVal!=0)
1922 {
1923 GameSettingsA[iPad]->usBitmaskValues|=0x0080;
1924 }
1925 else
1926 {
1927 GameSettingsA[iPad]->usBitmaskValues&=~0x0080;
1928 }
1929 ActionGameSettings(iPad,eVal);
1930 GameSettingsA[iPad]->bSettingsChanged=true;
1931 }
1932 break;
1933 case eGameSetting_SplitScreenVertical:
1934 if((GameSettingsA[iPad]->usBitmaskValues&0x0100)!=((ucVal&0x01)<<8))
1935 {
1936 if(ucVal!=0)
1937 {
1938 GameSettingsA[iPad]->usBitmaskValues|=0x0100;
1939 }
1940 else
1941 {
1942 GameSettingsA[iPad]->usBitmaskValues&=~0x0100;
1943 }
1944 ActionGameSettings(iPad,eVal);
1945 GameSettingsA[iPad]->bSettingsChanged=true;
1946 }
1947 break;
1948 case eGameSetting_GamertagsVisible:
1949 if((GameSettingsA[iPad]->usBitmaskValues&0x0008)!=((ucVal&0x01)<<3))
1950 {
1951 if(ucVal!=0)
1952 {
1953 GameSettingsA[iPad]->usBitmaskValues|=0x0008;
1954 }
1955 else
1956 {
1957 GameSettingsA[iPad]->usBitmaskValues&=~0x0008;
1958 }
1959 ActionGameSettings(iPad,eVal);
1960 GameSettingsA[iPad]->bSettingsChanged=true;
1961 }
1962 break;
1963
1964 // 4J-PB - Added for Interim TU for 1.6.6
1965 case eGameSetting_Sensitivity_InMenu:
1966 if(GameSettingsA[iPad]->ucMenuSensitivity!=ucVal)
1967 {
1968 GameSettingsA[iPad]->ucMenuSensitivity=ucVal;
1969 ActionGameSettings(iPad,eVal);
1970 GameSettingsA[iPad]->bSettingsChanged=true;
1971 }
1972 break;
1973 case eGameSetting_DisplaySplitscreenGamertags:
1974 if((GameSettingsA[iPad]->usBitmaskValues&0x0200)!=((ucVal&0x01)<<9))
1975 {
1976 if(ucVal!=0)
1977 {
1978 GameSettingsA[iPad]->usBitmaskValues|=0x0200;
1979 }
1980 else
1981 {
1982 GameSettingsA[iPad]->usBitmaskValues&=~0x0200;
1983 }
1984 ActionGameSettings(iPad,eVal);
1985 GameSettingsA[iPad]->bSettingsChanged=true;
1986 }
1987 break;
1988 case eGameSetting_Hints:
1989 if((GameSettingsA[iPad]->usBitmaskValues&0x0400)!=((ucVal&0x01)<<10))
1990 {
1991 if(ucVal!=0)
1992 {
1993 GameSettingsA[iPad]->usBitmaskValues|=0x0400;
1994 }
1995 else
1996 {
1997 GameSettingsA[iPad]->usBitmaskValues&=~0x0400;
1998 }
1999 ActionGameSettings(iPad,eVal);
2000 GameSettingsA[iPad]->bSettingsChanged=true;
2001 }
2002 break;
2003 case eGameSetting_Autosave:
2004 if((GameSettingsA[iPad]->usBitmaskValues&0x7800)!=((ucVal&0x0F)<<11))
2005 {
2006 GameSettingsA[iPad]->usBitmaskValues&=~0x7800;
2007 if(ucVal!=0)
2008 {
2009 GameSettingsA[iPad]->usBitmaskValues|=(ucVal&0x0F)<<11;
2010 }
2011 ActionGameSettings(iPad,eVal);
2012 GameSettingsA[iPad]->bSettingsChanged=true;
2013 }
2014 break;
2015
2016 case eGameSetting_Tooltips:
2017 if((GameSettingsA[iPad]->usBitmaskValues&0x8000)!=((ucVal&0x01)<<15))
2018 {
2019 if(ucVal!=0)
2020 {
2021 GameSettingsA[iPad]->usBitmaskValues|=0x8000;
2022 }
2023 else
2024 {
2025 GameSettingsA[iPad]->usBitmaskValues&=~0x8000;
2026 }
2027 ActionGameSettings(iPad,eVal);
2028 GameSettingsA[iPad]->bSettingsChanged=true;
2029 }
2030 break;
2031 case eGameSetting_InterfaceOpacity:
2032 if(GameSettingsA[iPad]->ucInterfaceOpacity!=ucVal)
2033 {
2034 GameSettingsA[iPad]->ucInterfaceOpacity=ucVal;
2035 ActionGameSettings(iPad,eVal);
2036 GameSettingsA[iPad]->bSettingsChanged=true;
2037 }
2038
2039 break;
2040 case eGameSetting_Clouds:
2041 if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_CLOUDS)!=(ucVal&0x01))
2042 {
2043 if(ucVal==1)
2044 {
2045 GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_CLOUDS;
2046 }
2047 else
2048 {
2049 GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_CLOUDS;
2050 }
2051 ActionGameSettings(iPad,eVal);
2052 GameSettingsA[iPad]->bSettingsChanged=true;
2053 }
2054
2055 break;
2056
2057 case eGameSetting_Online:
2058 if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_ONLINE)!=(ucVal&0x01)<<1)
2059 {
2060 if(ucVal==1)
2061 {
2062 GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_ONLINE;
2063 }
2064 else
2065 {
2066 GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_ONLINE;
2067 }
2068 ActionGameSettings(iPad,eVal);
2069 GameSettingsA[iPad]->bSettingsChanged=true;
2070 }
2071
2072 break;
2073 case eGameSetting_InviteOnly:
2074 if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_INVITEONLY)!=(ucVal&0x01)<<2)
2075 {
2076 if(ucVal==1)
2077 {
2078 GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_INVITEONLY;
2079 }
2080 else
2081 {
2082 GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_INVITEONLY;
2083 }
2084 ActionGameSettings(iPad,eVal);
2085 GameSettingsA[iPad]->bSettingsChanged=true;
2086 }
2087
2088 break;
2089 case eGameSetting_FriendsOfFriends:
2090 if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_FRIENDSOFFRIENDS)!=(ucVal&0x01)<<3)
2091 {
2092 if(ucVal==1)
2093 {
2094 GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_FRIENDSOFFRIENDS;
2095 }
2096 else
2097 {
2098 GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_FRIENDSOFFRIENDS;
2099 }
2100 ActionGameSettings(iPad,eVal);
2101 GameSettingsA[iPad]->bSettingsChanged=true;
2102 }
2103
2104 break;
2105 case eGameSetting_DisplayUpdateMessage:
2106 if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYUPDATEMSG)!=(ucVal&0x03)<<4)
2107 {
2108 GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_DISPLAYUPDATEMSG;
2109 if(ucVal>0)
2110 {
2111 GameSettingsA[iPad]->uiBitmaskValues|=(ucVal&0x03)<<4;
2112 }
2113
2114 ActionGameSettings(iPad,eVal);
2115 GameSettingsA[iPad]->bSettingsChanged=true;
2116 }
2117
2118 break;
2119
2120 case eGameSetting_BedrockFog:
2121 if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_BEDROCKFOG)!=(ucVal&0x01)<<6)
2122 {
2123 if(ucVal==1)
2124 {
2125 GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_BEDROCKFOG;
2126 }
2127 else
2128 {
2129 GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG;
2130 }
2131 ActionGameSettings(iPad,eVal);
2132 GameSettingsA[iPad]->bSettingsChanged=true;
2133 }
2134
2135 break;
2136 case eGameSetting_DisplayHUD:
2137 if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYHUD)!=(ucVal&0x01)<<7)
2138 {
2139 if(ucVal==1)
2140 {
2141 GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_DISPLAYHUD;
2142 }
2143 else
2144 {
2145 GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_DISPLAYHUD;
2146 }
2147 ActionGameSettings(iPad,eVal);
2148 GameSettingsA[iPad]->bSettingsChanged=true;
2149 }
2150
2151 break;
2152 case eGameSetting_DisplayHand:
2153 if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYHAND)!=(ucVal&0x01)<<8)
2154 {
2155 if(ucVal==1)
2156 {
2157 GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_DISPLAYHAND;
2158 }
2159 else
2160 {
2161 GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_DISPLAYHAND;
2162 }
2163 ActionGameSettings(iPad,eVal);
2164 GameSettingsA[iPad]->bSettingsChanged=true;
2165 }
2166
2167 break;
2168
2169 case eGameSetting_CustomSkinAnim:
2170 if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_CUSTOMSKINANIM)!=(ucVal&0x01)<<9)
2171 {
2172 if(ucVal==1)
2173 {
2174 GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM;
2175 }
2176 else
2177 {
2178 GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_CUSTOMSKINANIM;
2179 }
2180 ActionGameSettings(iPad,eVal);
2181 GameSettingsA[iPad]->bSettingsChanged=true;
2182 }
2183
2184 break;
2185 // TU9
2186 case eGameSetting_DeathMessages:
2187 if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DEATHMESSAGES)!=(ucVal&0x01)<<10)
2188 {
2189 if(ucVal==1)
2190 {
2191 GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES;
2192 }
2193 else
2194 {
2195 GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_DEATHMESSAGES;
2196 }
2197 ActionGameSettings(iPad,eVal);
2198 GameSettingsA[iPad]->bSettingsChanged=true;
2199 }
2200 break;
2201 case eGameSetting_UISize:
2202 if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_UISIZE)!=((ucVal&0x03)<<11))
2203 {
2204 GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_UISIZE;
2205 if(ucVal!=0)
2206 {
2207 GameSettingsA[iPad]->uiBitmaskValues|=(ucVal&0x03)<<11;
2208 }
2209 ActionGameSettings(iPad,eVal);
2210 GameSettingsA[iPad]->bSettingsChanged=true;
2211 }
2212 break;
2213 case eGameSetting_UISizeSplitscreen:
2214 if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_UISIZE_SPLITSCREEN)!=((ucVal&0x03)<<13))
2215 {
2216 GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_UISIZE_SPLITSCREEN;
2217 if(ucVal!=0)
2218 {
2219 GameSettingsA[iPad]->uiBitmaskValues|=(ucVal&0x03)<<13;
2220 }
2221 ActionGameSettings(iPad,eVal);
2222 GameSettingsA[iPad]->bSettingsChanged=true;
2223 }
2224 break;
2225 case eGameSetting_AnimatedCharacter:
2226 if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_ANIMATEDCHARACTER)!=(ucVal&0x01)<<15)
2227 {
2228 if(ucVal==1)
2229 {
2230 GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER;
2231 }
2232 else
2233 {
2234 GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_ANIMATEDCHARACTER;
2235 }
2236 ActionGameSettings(iPad,eVal);
2237 GameSettingsA[iPad]->bSettingsChanged=true;
2238 }
2239 break;
2240 case eGameSetting_PS3_EULA_Read:
2241 if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PS3EULAREAD)!=(ucVal&0x01)<<16)
2242 {
2243 if(ucVal==1)
2244 {
2245 GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_PS3EULAREAD;
2246 }
2247 else
2248 {
2249 GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_PS3EULAREAD;
2250 }
2251 ActionGameSettings(iPad,eVal);
2252 GameSettingsA[iPad]->bSettingsChanged=true;
2253 }
2254 break;
2255 case eGameSetting_PSVita_NetworkModeAdhoc:
2256 if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PSVITANETWORKMODEADHOC)!=(ucVal&0x01)<<17)
2257 {
2258 if(ucVal==1)
2259 {
2260 GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_PSVITANETWORKMODEADHOC;
2261 }
2262 else
2263 {
2264 GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_PSVITANETWORKMODEADHOC;
2265 }
2266 ActionGameSettings(iPad,eVal);
2267 GameSettingsA[iPad]->bSettingsChanged=true;
2268 }
2269 break;
2270
2271 }
2272}
2273
2274unsigned char CMinecraftApp::GetGameSettings(eGameSetting eVal)
2275{
2276 int iPad=ProfileManager.GetPrimaryPad();
2277
2278 return GetGameSettings(iPad,eVal);
2279}
2280
2281unsigned char CMinecraftApp::GetGameSettings(int iPad,eGameSetting eVal)
2282{
2283 switch(eVal)
2284 {
2285 case eGameSetting_MusicVolume:
2286 return GameSettingsA[iPad]->ucMusicVolume;
2287 break;
2288 case eGameSetting_SoundFXVolume:
2289 return GameSettingsA[iPad]->ucSoundFXVolume;
2290 break;
2291 case eGameSetting_Gamma:
2292 return GameSettingsA[iPad]->ucGamma;
2293 break;
2294 case eGameSetting_Difficulty:
2295 return GameSettingsA[iPad]->usBitmaskValues&0x0003;
2296 break;
2297 case eGameSetting_Sensitivity_InGame:
2298 return GameSettingsA[iPad]->ucSensitivity;
2299 break;
2300 case eGameSetting_ViewBob:
2301 return ((GameSettingsA[iPad]->usBitmaskValues&0x0004)>>2);
2302 break;
2303 case eGameSetting_GamertagsVisible:
2304 return ((GameSettingsA[iPad]->usBitmaskValues&0x0008)>>3);
2305 break;
2306 case eGameSetting_ControlScheme:
2307 return ((GameSettingsA[iPad]->usBitmaskValues&0x0030)>>4); // 2 bits
2308 break;
2309 case eGameSetting_ControlInvertLook:
2310 return ((GameSettingsA[iPad]->usBitmaskValues&0x0040)>>6);
2311 break;
2312 case eGameSetting_ControlSouthPaw:
2313 return ((GameSettingsA[iPad]->usBitmaskValues&0x0080)>>7);
2314 break;
2315 case eGameSetting_SplitScreenVertical:
2316 return ((GameSettingsA[iPad]->usBitmaskValues&0x0100)>>8);
2317 break;
2318 // 4J-PB - Added for Interim TU for 1.6.6
2319 case eGameSetting_Sensitivity_InMenu:
2320 return GameSettingsA[iPad]->ucMenuSensitivity;
2321 break;
2322
2323 case eGameSetting_DisplaySplitscreenGamertags:
2324 return ((GameSettingsA[iPad]->usBitmaskValues&0x0200)>>9);
2325 break;
2326
2327 case eGameSetting_Hints:
2328 return ((GameSettingsA[iPad]->usBitmaskValues&0x0400)>>10);
2329 break;
2330 case eGameSetting_Autosave:
2331 {
2332 unsigned char ucVal=(GameSettingsA[iPad]->usBitmaskValues&0x7800)>>11;
2333 return ucVal;
2334 }
2335 break;
2336 case eGameSetting_Tooltips:
2337 return ((GameSettingsA[iPad]->usBitmaskValues&0x8000)>>15);
2338 break;
2339
2340 case eGameSetting_InterfaceOpacity:
2341 return GameSettingsA[iPad]->ucInterfaceOpacity;
2342 break;
2343
2344 case eGameSetting_Clouds:
2345 return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_CLOUDS);
2346 break;
2347 case eGameSetting_Online:
2348 return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_ONLINE)>>1;
2349 break;
2350 case eGameSetting_InviteOnly:
2351 return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_INVITEONLY)>>2;
2352 break;
2353 case eGameSetting_FriendsOfFriends:
2354 return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_FRIENDSOFFRIENDS)>>3;
2355 break;
2356 case eGameSetting_DisplayUpdateMessage:
2357 return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYUPDATEMSG)>>4;
2358 break;
2359 case eGameSetting_BedrockFog:
2360 return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_BEDROCKFOG)>>6;
2361 break;
2362 case eGameSetting_DisplayHUD:
2363 return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYHUD)>>7;
2364 break;
2365 case eGameSetting_DisplayHand:
2366 return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYHAND)>>8;
2367 break;
2368 case eGameSetting_CustomSkinAnim:
2369 return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_CUSTOMSKINANIM)>>9;
2370 break;
2371 // TU9
2372 case eGameSetting_DeathMessages:
2373 return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DEATHMESSAGES)>>10;
2374 break;
2375 case eGameSetting_UISize:
2376 {
2377 unsigned char ucVal=(GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_UISIZE)>>11;
2378 return ucVal;
2379 }
2380 break;
2381 case eGameSetting_UISizeSplitscreen:
2382 {
2383 unsigned char ucVal=(GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_UISIZE_SPLITSCREEN)>>13;
2384 return ucVal;
2385 }
2386 break;
2387 case eGameSetting_AnimatedCharacter:
2388 return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_ANIMATEDCHARACTER)>>15;
2389
2390 case eGameSetting_PS3_EULA_Read:
2391 return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PS3EULAREAD)>>16;
2392
2393 case eGameSetting_PSVita_NetworkModeAdhoc:
2394 return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PSVITANETWORKMODEADHOC)>>17;
2395
2396 }
2397 return 0;
2398}
2399
2400void CMinecraftApp::CheckGameSettingsChanged(bool bOverride5MinuteTimer, int iPad)
2401{
2402 // If the settings have changed, write them to the profile
2403
2404 if(iPad==XUSER_INDEX_ANY)
2405 {
2406 for(int i=0;i<XUSER_MAX_COUNT;i++)
2407 {
2408 if(GameSettingsA[i]->bSettingsChanged)
2409 {
2410#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__ )
2411 StorageManager.WriteToProfile(i,true, bOverride5MinuteTimer);
2412#else
2413 ProfileManager.WriteToProfile(i,true, bOverride5MinuteTimer);
2414#ifdef _WINDOWS64
2415 Win64_SaveSettings(GameSettingsA[i]);
2416#endif
2417#endif
2418 GameSettingsA[i]->bSettingsChanged=false;
2419 }
2420 }
2421 }
2422 else
2423 {
2424 if(GameSettingsA[iPad]->bSettingsChanged)
2425 {
2426#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
2427 StorageManager.WriteToProfile(iPad,true, bOverride5MinuteTimer);
2428#else
2429 ProfileManager.WriteToProfile(iPad,true, bOverride5MinuteTimer);
2430#ifdef _WINDOWS64
2431 Win64_SaveSettings(GameSettingsA[iPad]);
2432#endif
2433#endif
2434 GameSettingsA[iPad]->bSettingsChanged=false;
2435 }
2436 }
2437}
2438
2439void CMinecraftApp::ClearGameSettingsChangedFlag(int iPad)
2440{
2441 GameSettingsA[iPad]->bSettingsChanged=false;
2442}
2443
2444///////////////////////////
2445//
2446// Remove the debug settings in the content package build
2447//
2448////////////////////////////
2449#ifndef _DEBUG_MENUS_ENABLED
2450unsigned int CMinecraftApp::GetGameSettingsDebugMask(int iPad,bool bOverridePlayer) //bOverridePlayer is to force the send for the server to get the read options
2451{
2452 return 0;
2453}
2454
2455void CMinecraftApp::SetGameSettingsDebugMask(int iPad, unsigned int uiVal)
2456{
2457}
2458
2459void CMinecraftApp::ActionDebugMask(int iPad,bool bSetAllClear)
2460{
2461}
2462
2463#else
2464
2465unsigned int CMinecraftApp::GetGameSettingsDebugMask(int iPad,bool bOverridePlayer) //bOverridePlayer is to force the send for the server to get the read options
2466{
2467 if(iPad==-1)
2468 {
2469 iPad=ProfileManager.GetPrimaryPad();
2470 }
2471 if(iPad < 0) iPad = 0;
2472
2473 shared_ptr<Player> player = Minecraft::GetInstance()->localplayers[iPad];
2474
2475 if(bOverridePlayer || player==NULL)
2476 {
2477 return GameSettingsA[iPad]->uiDebugBitmask;
2478 }
2479 else
2480 {
2481 return player->GetDebugOptions();
2482 }
2483}
2484
2485
2486void CMinecraftApp::SetGameSettingsDebugMask(int iPad, unsigned int uiVal)
2487{
2488#ifndef _CONTENT_PACKAGE
2489 GameSettingsA[iPad]->bSettingsChanged=true;
2490 GameSettingsA[iPad]->uiDebugBitmask=uiVal;
2491
2492 // update the value so the network server can use it
2493 shared_ptr<Player> player = Minecraft::GetInstance()->localplayers[iPad];
2494
2495 if(player)
2496 {
2497 Minecraft::GetInstance()->localgameModes[iPad]->handleDebugOptions(uiVal,player);
2498 }
2499#endif
2500}
2501
2502void CMinecraftApp::ActionDebugMask(int iPad,bool bSetAllClear)
2503{
2504 unsigned int ulBitmask=app.GetGameSettingsDebugMask(iPad);
2505
2506 if(bSetAllClear) ulBitmask=0L;
2507
2508
2509
2510 // these settings should only be actioned for the primary player
2511 if(ProfileManager.GetPrimaryPad()!=iPad) return;
2512
2513 for(int i=0;i<eDebugSetting_Max;i++)
2514 {
2515 switch(i)
2516 {
2517 case eDebugSetting_LoadSavesFromDisk:
2518 if(ulBitmask&(1<<i))
2519 {
2520 app.SetLoadSavesFromFolderEnabled(true);
2521 }
2522 else
2523 {
2524 app.SetLoadSavesFromFolderEnabled(false);
2525 }
2526 break;
2527
2528 case eDebugSetting_WriteSavesToDisk:
2529 if(ulBitmask&(1<<i))
2530 {
2531 app.SetWriteSavesToFolderEnabled(true);
2532 }
2533 else
2534 {
2535 app.SetWriteSavesToFolderEnabled(false);
2536 }
2537 break;
2538
2539 case eDebugSetting_FreezePlayers: //eDebugSetting_InterfaceOff:
2540 if(ulBitmask&(1<<i))
2541 {
2542 app.SetFreezePlayers(true);
2543
2544 // Turn off interface rendering.
2545 //app.SetInterfaceRenderingOff( true );
2546 }
2547 else
2548 {
2549 app.SetFreezePlayers(false);
2550
2551 // Turn on interface rendering.
2552 //app.SetInterfaceRenderingOff( false );
2553 }
2554 break;
2555 case eDebugSetting_Safearea:
2556 if(ulBitmask&(1<<i))
2557 {
2558 app.ShowSafeArea( TRUE );
2559 }
2560 else
2561 {
2562 app.ShowSafeArea( FALSE );
2563 }
2564 break;
2565
2566 //case eDebugSetting_HandRenderingOff:
2567 // if(ulBitmask&(1<<i))
2568 // {
2569 // // Turn off hand rendering.
2570 // //app.SetHandRenderingOff( true );
2571 // }
2572 // else
2573 // {
2574 // // Turn on hand rendering.
2575 // //app.SetHandRenderingOff( false );
2576 // }
2577 // break;
2578
2579 case eDebugSetting_ShowUIConsole:
2580 if(ulBitmask&(1<<i))
2581 {
2582 ui.ShowUIDebugConsole(true);
2583 }
2584 else
2585 {
2586 ui.ShowUIDebugConsole(false);
2587 }
2588 break;
2589
2590 case eDebugSetting_ShowUIMarketingGuide:
2591 if(ulBitmask&(1<<i))
2592 {
2593 ui.ShowUIDebugMarketingGuide(true);
2594 }
2595 else
2596 {
2597 ui.ShowUIDebugMarketingGuide(false);
2598 }
2599 break;
2600
2601 case eDebugSetting_MobsDontAttack:
2602 if(ulBitmask&(1<<i))
2603 {
2604 app.SetMobsDontAttackEnabled(true);
2605 }
2606 else
2607 {
2608 app.SetMobsDontAttackEnabled(false);
2609 }
2610 break;
2611
2612 case eDebugSetting_UseDpadForDebug:
2613 if(ulBitmask&(1<<i))
2614 {
2615 app.SetUseDPadForDebug(true);
2616 }
2617 else
2618 {
2619 app.SetUseDPadForDebug(false);
2620 }
2621 break;
2622 case eDebugSetting_MobsDontTick:
2623 if(ulBitmask&(1<<i))
2624 {
2625 app.SetMobsDontTickEnabled(true);
2626 }
2627 else
2628 {
2629 app.SetMobsDontTickEnabled(false);
2630 }
2631 break;
2632
2633 }
2634 }
2635}
2636#endif
2637
2638int CMinecraftApp::DisplaySavingMessage(void *pParam, C4JStorage::ESavingMessage eVal, int iPad)
2639{
2640 //CMinecraftApp* pClass = (CMinecraftApp*)pParam;
2641
2642 ui.ShowSavingMessage(iPad, eVal);
2643
2644 return 0;
2645}
2646
2647void CMinecraftApp::SetActionConfirmed(LPVOID param)
2648{
2649 XuiActionParam *actionInfo = (XuiActionParam *)param;
2650 app.SetAction(actionInfo->iPad, actionInfo->action);
2651}
2652
2653
2654void CMinecraftApp::HandleXuiActions(void)
2655{
2656 eXuiAction eAction;
2657 eTMSAction eTMS;
2658 LPVOID param;
2659 Minecraft *pMinecraft=Minecraft::GetInstance();
2660 shared_ptr<MultiplayerLocalPlayer> player;
2661
2662 // are there any global actions to deal with?
2663 eAction = app.GetGlobalXuiAction();
2664 if(eAction!=eAppAction_Idle)
2665 {
2666 switch(eAction)
2667 {
2668 case eAppAction_DisplayLavaMessage:
2669 // Display a warning about placing lava in the spawn area
2670 {
2671 UINT uiIDA[1];
2672 uiIDA[0]=IDS_CONFIRM_OK;
2673 C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_CANT_PLACE_NEAR_SPAWN_TITLE, IDS_CANT_PLACE_NEAR_SPAWN_TEXT, uiIDA,1,XUSER_INDEX_ANY);
2674 if(result != C4JStorage::EMessage_Busy) SetGlobalXuiAction(eAppAction_Idle);
2675
2676 }
2677 break;
2678 default:
2679 break;
2680 }
2681 }
2682
2683 // are there any app actions to deal with?
2684 for(int i=0;i<XUSER_MAX_COUNT;i++)
2685 {
2686 eAction = app.GetXuiAction(i);
2687 param = m_eXuiActionParam[i];
2688
2689 if(eAction!=eAppAction_Idle)
2690 {
2691 switch(eAction)
2692 {
2693 // the renderer will capture a screenshot
2694 case eAppAction_SocialPost:
2695 if(ProfileManager.IsFullVersion())
2696 {
2697 // Facebook Share
2698 if( CSocialManager::Instance()->IsTitleAllowedToPostImages() && CSocialManager::Instance()->AreAllUsersAllowedToPostImages() )
2699 {
2700 // disable character name tags for the shot
2701 //m_bwasHidingGui = pMinecraft->options->hideGui; // 4J Stu - Removed 1.8.2 bug fix (TU6) as don't need this
2702 pMinecraft->options->hideGui = true;
2703
2704 SetAction(i,eAppAction_SocialPostScreenshot);
2705 }
2706 else
2707 {
2708 SetAction(i,eAppAction_Idle);
2709 }
2710 }
2711 else
2712 {
2713 SetAction(i,eAppAction_Idle);
2714 }
2715 break;
2716 case eAppAction_SocialPostScreenshot:
2717 {
2718 SetAction(i,eAppAction_Idle);
2719 bool bKeepHiding = false;
2720 for(int j=0; j < XUSER_MAX_COUNT;++j)
2721 {
2722 if(app.GetXuiAction(j) == eAppAction_SocialPostScreenshot)
2723 {
2724 bKeepHiding = true;
2725 break;
2726 }
2727 }
2728 pMinecraft->options->hideGui=bKeepHiding;
2729
2730 // Facebook Share
2731
2732 if(app.GetLocalPlayerCount()>1)
2733 {
2734 ui.NavigateToScene(i,eUIScene_SocialPost);
2735 }
2736 else
2737 {
2738 ui.NavigateToScene(i,eUIScene_SocialPost);
2739 }
2740 }
2741 break;
2742 case eAppAction_SaveGame:
2743 SetAction(i,eAppAction_Idle);
2744 if(!GetChangingSessionType())
2745 {
2746 // If this is the trial game, do an upsell
2747 if(ProfileManager.IsFullVersion())
2748 {
2749
2750 // flag the render to capture the screenshot for the save
2751 SetAction(i,eAppAction_SaveGameCapturedThumbnail);
2752 }
2753 else
2754 {
2755 // ask the player if they would like to upgrade, or they'll lose the level
2756
2757 UINT uiIDA[2];
2758 uiIDA[0]=IDS_CONFIRM_OK;
2759 uiIDA[1]=IDS_CONFIRM_CANCEL;
2760 ui.RequestErrorMessage(IDS_UNLOCK_TITLE, IDS_UNLOCK_TOSAVE_TEXT, uiIDA, 2,i,&CMinecraftApp::UnlockFullSaveReturned,this);
2761 }
2762 }
2763
2764 break;
2765 case eAppAction_AutosaveSaveGame:
2766 {
2767 // 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
2768 bool bSaveExists;
2769 StorageManager.DoesSaveExist(&bSaveExists);
2770
2771 SetAction(i,eAppAction_Idle);
2772 if(!GetChangingSessionType())
2773 {
2774
2775 // flag the render to capture the screenshot for the save
2776 SetAction(i,eAppAction_AutosaveSaveGameCapturedThumbnail);
2777 }
2778 }
2779
2780 break;
2781
2782 case eAppAction_SaveGameCapturedThumbnail:
2783 // reset the autosave timer
2784 app.SetAutosaveTimerTime();
2785 SetAction(i,eAppAction_Idle);
2786 // 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
2787 /*if(StorageManager.GetSaveName()==NULL)
2788 {
2789 app.NavigateToScene(i,eUIScene_SaveWorld);
2790 }
2791 else*/
2792 {
2793 // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
2794 ui.HideAllGameUIElements();
2795
2796 // Hide the other players scenes
2797 ui.ShowOtherPlayersBaseScene(ProfileManager.GetPrimaryPad(), false);
2798
2799 //INT saveOrCheckpointId = 0;
2800 //bool validSave = StorageManager.GetSaveUniqueNumber(&saveOrCheckpointId);
2801 //SentientManager.RecordLevelSaveOrCheckpoint(ProfileManager.GetPrimaryPad(), saveOrCheckpointId);
2802
2803 LoadingInputParams *loadingParams = new LoadingInputParams();
2804 loadingParams->func = &UIScene_PauseMenu::SaveWorldThreadProc;
2805 loadingParams->lpParam = (LPVOID)false;
2806
2807 // 4J-JEV - PS4: Fix for #5708 - [ONLINE] - If the user pulls their network cable out while saving the title will hang.
2808 loadingParams->waitForThreadToDelete = true;
2809
2810 UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
2811 completionData->bShowBackground=TRUE;
2812 completionData->bShowLogo=TRUE;
2813 completionData->type = e_ProgressCompletion_NavigateBackToScene;
2814 completionData->iPad = ProfileManager.GetPrimaryPad();
2815
2816 if( ui.IsSceneInStack( ProfileManager.GetPrimaryPad(), eUIScene_EndPoem ) )
2817 {
2818 completionData->scene = eUIScene_EndPoem;
2819 }
2820 else
2821 {
2822 completionData->scene = eUIScene_PauseMenu;
2823 }
2824
2825 loadingParams->completionData = completionData;
2826
2827 // 4J Stu - Xbox only
2828#ifdef _XBOX
2829 // Temporarily make this scene fullscreen
2830 CXuiSceneBase::SetPlayerBaseScenePosition( ProfileManager.GetPrimaryPad(), CXuiSceneBase::e_BaseScene_Fullscreen );
2831#endif
2832
2833 ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams , eUILayer_Fullscreen, eUIGroup_Fullscreen);
2834
2835 }
2836 break;
2837 case eAppAction_AutosaveSaveGameCapturedThumbnail:
2838
2839 {
2840 app.SetAutosaveTimerTime();
2841 SetAction(i,eAppAction_Idle);
2842
2843#if defined(_XBOX_ONE) || defined(__ORBIS__)
2844 app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_AutoSaveGame);
2845
2846 if(app.GetGameHostOption(eGameHostOption_DisableSaving)) StorageManager.SetSaveDisabled(true);
2847#else
2848 // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
2849 ui.HideAllGameUIElements();
2850
2851 //app.CloseAllPlayersXuiScenes();
2852 // Hide the other players scenes
2853 ui.ShowOtherPlayersBaseScene(ProfileManager.GetPrimaryPad(), false);
2854
2855 // This just allows it to be shown
2856 if(pMinecraft->localgameModes[ProfileManager.GetPrimaryPad()] != NULL) pMinecraft->localgameModes[ProfileManager.GetPrimaryPad()]->getTutorial()->showTutorialPopup(false);
2857
2858 //INT saveOrCheckpointId = 0;
2859 //bool validSave = StorageManager.GetSaveUniqueNumber(&saveOrCheckpointId);
2860 //SentientManager.RecordLevelSaveOrCheckpoint(ProfileManager.GetPrimaryPad(), saveOrCheckpointId);
2861
2862
2863 LoadingInputParams *loadingParams = new LoadingInputParams();
2864 loadingParams->func = &UIScene_PauseMenu::SaveWorldThreadProc;
2865
2866 loadingParams->lpParam = (LPVOID)true;
2867
2868 UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
2869 completionData->bShowBackground=TRUE;
2870 completionData->bShowLogo=TRUE;
2871 completionData->type = e_ProgressCompletion_AutosaveNavigateBack;
2872 completionData->iPad = ProfileManager.GetPrimaryPad();
2873 //completionData->bAutosaveWasMenuDisplayed=ui.GetMenuDisplayed(ProfileManager.GetPrimaryPad());
2874 loadingParams->completionData = completionData;
2875
2876 // 4J Stu - Xbox only
2877#ifdef _XBOX
2878 // Temporarily make this scene fullscreen
2879 CXuiSceneBase::SetPlayerBaseScenePosition( ProfileManager.GetPrimaryPad(), CXuiSceneBase::e_BaseScene_Fullscreen );
2880#endif
2881
2882 ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams , eUILayer_Fullscreen, eUIGroup_Fullscreen);
2883#endif
2884 }
2885 break;
2886 case eAppAction_ExitPlayer:
2887 // a secondary player has chosen to quit
2888 {
2889 int iPlayerC=g_NetworkManager.GetPlayerCount();
2890
2891 // Since the player is exiting, let's flush any profile writes for them, and hope we're not breaking TCR 136...
2892#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
2893 StorageManager.ForceQueuedProfileWrites(i);
2894 LeaderboardManager::Instance()->OpenSession();
2895 for (int j = 0; j < XUSER_MAX_COUNT; j++)
2896 {
2897 if( ProfileManager.IsSignedIn(j) )
2898 {
2899 app.DebugPrintf("Stats save for an offline game for the player at index %d\n", 0);
2900 Minecraft::GetInstance()->forceStatsSave(j);
2901 }
2902 }
2903 LeaderboardManager::Instance()->CloseSession();
2904#else
2905 ProfileManager.ForceQueuedProfileWrites(i);
2906#endif
2907
2908 // not required - it's done within the removeLocalPlayerIdx
2909 // if(pMinecraft->level->isClientSide)
2910 // {
2911 // // 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
2912 // g_NetworkManager.NotifyPlayerLeaving(g_NetworkManager.GetLocalPlayerByUserIndex(i));
2913 // }
2914
2915 // if there are any tips showing, we need to close them
2916
2917 pMinecraft->gui->clearMessages(i);
2918
2919 // Make sure we've not got this player selected as current - this shouldn't be the case anyway
2920 pMinecraft->setLocalPlayerIdx(ProfileManager.GetPrimaryPad());
2921 pMinecraft->removeLocalPlayerIdx(i);
2922
2923#ifdef _XBOX
2924 // tell the xui scenes a splitscreen player left - has to come after removeLocalPlayerIdx which calls updatePlayerViewportAssignments
2925 XUIMessage xuiMsg;
2926 CustomMessage_Splitscreenplayer_Struct myMsgData;
2927 CustomMessage_Splitscreenplayer( &xuiMsg, &myMsgData, false);
2928
2929 // send the message
2930 for(int idx=0;idx<XUSER_MAX_COUNT;idx++)
2931 {
2932 if((i!=idx) && (pMinecraft->localplayers[idx]!=NULL))
2933 {
2934 XuiBroadcastMessage( CXuiSceneBase::GetPlayerBaseScene(idx), &xuiMsg );
2935 }
2936 }
2937#endif
2938
2939#ifndef _XBOX
2940 // Wipe out the tooltips
2941 ui.SetTooltips(i, -1);
2942#endif
2943
2944 // Change the presence info
2945 // Are we offline or online, and how many players are there
2946 if(iPlayerC>2) // one player is about to leave here - they'll be set to idle in the qnet manager player leave
2947 {
2948 for(int iPlayer=0;iPlayer<XUSER_MAX_COUNT;iPlayer++)
2949 {
2950 if((iPlayer!=i) && pMinecraft->localplayers[iPlayer])
2951 {
2952 if(g_NetworkManager.IsLocalGame())
2953 {
2954 ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false);
2955 }
2956 else
2957 {
2958 ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER,false);
2959 }
2960 }
2961 }
2962 }
2963 else
2964 {
2965 for(int iPlayer=0;iPlayer<XUSER_MAX_COUNT;iPlayer++)
2966 {
2967 if((iPlayer!=i) && pMinecraft->localplayers[iPlayer])
2968 {
2969 if(g_NetworkManager.IsLocalGame())
2970 {
2971 ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE,false);
2972 }
2973 else
2974 {
2975 ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER_1P,false);
2976 }
2977 }
2978 }
2979 }
2980
2981#ifdef _DURANGO
2982 ProfileManager.RemoveGamepadFromGame(i);
2983#endif
2984
2985 SetAction(i,eAppAction_Idle);
2986 }
2987 break;
2988 case eAppAction_ExitPlayerPreLogin:
2989 {
2990 int iPlayerC=g_NetworkManager.GetPlayerCount();
2991 // Since the player is exiting, let's flush any profile writes for them, and hope we're not breaking TCR 136...
2992#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
2993 StorageManager.ForceQueuedProfileWrites(i);
2994#else
2995 ProfileManager.ForceQueuedProfileWrites(i);
2996#endif
2997 // if there are any tips showing, we need to close them
2998
2999 pMinecraft->gui->clearMessages(i);
3000
3001 // Make sure we've not got this player selected as current - this shouldn't be the case anyway
3002 pMinecraft->setLocalPlayerIdx(ProfileManager.GetPrimaryPad());
3003 pMinecraft->removeLocalPlayerIdx(i);
3004
3005#ifdef _XBOX
3006 // tell the xui scenes a splitscreen player left - has to come after removeLocalPlayerIdx which calls updatePlayerViewportAssignments
3007 XUIMessage xuiMsg;
3008 CustomMessage_Splitscreenplayer_Struct myMsgData;
3009 CustomMessage_Splitscreenplayer( &xuiMsg, &myMsgData, false);
3010
3011 // send the message
3012 for(int idx=0;idx<XUSER_MAX_COUNT;idx++)
3013 {
3014 if((i!=idx) && (pMinecraft->localplayers[idx]!=NULL))
3015 {
3016 XuiBroadcastMessage( CXuiSceneBase::GetPlayerBaseScene(idx), &xuiMsg );
3017 }
3018 }
3019#endif
3020
3021#ifndef _XBOX
3022 // Wipe out the tooltips
3023 ui.SetTooltips(i, -1);
3024#endif
3025
3026 // Change the presence info
3027 // Are we offline or online, and how many players are there
3028 if(iPlayerC>2) // one player is about to leave here - they'll be set to idle in the qnet manager player leave
3029 {
3030 for(int iPlayer=0;iPlayer<XUSER_MAX_COUNT;iPlayer++)
3031 {
3032 if((iPlayer!=i) && pMinecraft->localplayers[iPlayer])
3033 {
3034 if(g_NetworkManager.IsLocalGame())
3035 {
3036 ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false);
3037 }
3038 else
3039 {
3040 ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER,false);
3041 }
3042 }
3043 }
3044 }
3045 else
3046 {
3047 for(int iPlayer=0;iPlayer<XUSER_MAX_COUNT;iPlayer++)
3048 {
3049 if((iPlayer!=i) && pMinecraft->localplayers[iPlayer])
3050 {
3051 if(g_NetworkManager.IsLocalGame())
3052 {
3053 ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE,false);
3054 }
3055 else
3056 {
3057 ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER_1P,false);
3058 }
3059 }
3060 }
3061 }
3062 SetAction(i,eAppAction_Idle);
3063 }
3064 break;
3065
3066#ifdef __ORBIS__
3067 case eAppAction_OptionsSaveNoSpace:
3068 {
3069 SetAction(i,eAppAction_Idle);
3070
3071 SceSaveDataDialogParam param;
3072 SceSaveDataDialogSystemMessageParam sysParam;
3073 SceSaveDataDialogItems items;
3074 SceSaveDataDirName dirName;
3075
3076 sceSaveDataDialogParamInitialize(¶m);
3077 param.mode = SCE_SAVE_DATA_DIALOG_MODE_SYSTEM_MSG;
3078 param.dispType = SCE_SAVE_DATA_DIALOG_TYPE_SAVE;
3079 memset(&sysParam,0,sizeof(sysParam));
3080 param.sysMsgParam = &sysParam;
3081 param.sysMsgParam->sysMsgType = SCE_SAVE_DATA_DIALOG_SYSMSG_TYPE_NOSPACE_CONTINUABLE;
3082 param.sysMsgParam->value = app.GetOptionsBlocksRequired(i);
3083 memset(&items, 0, sizeof(items));
3084 param.items = &items;
3085 param.items->userId = ProfileManager.getUserID(i);
3086
3087 int ret = sceSaveDataDialogInitialize();
3088 ret = sceSaveDataDialogOpen(¶m);
3089
3090 app.SetOptionsSaveDataDialogRunning(true);//m_bOptionsSaveDataDialogRunning = true;
3091 //pClass->m_eSaveIncompleteType = saveIncompleteType;
3092
3093 //StorageManager.SetSaveDisabled(true);
3094 //pClass->EnterSaveNotificationSection();
3095
3096 }
3097 break;
3098#endif
3099
3100 case eAppAction_ExitWorld:
3101
3102 SetAction(i,eAppAction_Idle);
3103
3104 // If we're already leaving don't exit
3105 if (g_NetworkManager.IsLeavingGame())
3106 {
3107 break;
3108 }
3109
3110 pMinecraft->gui->clearMessages();
3111
3112 // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
3113 ui.HideAllGameUIElements();
3114
3115 // reset the flag stopping new dlc message being shown if you've seen the message before
3116 DisplayNewDLCTipAgain();
3117
3118 // clear the autosave timer that might be on screen
3119 ui.ShowAutosaveCountdownTimer(false);
3120
3121 // Hide the selected item text
3122 ui.HideAllGameUIElements();
3123
3124 // Since the player forced the exit, let's flush any profile writes, and hope we're not breaking TCR 136...
3125#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
3126 StorageManager.ForceQueuedProfileWrites();
3127 LeaderboardManager::Instance()->OpenSession();
3128 for (int j = 0; j < XUSER_MAX_COUNT; j++)
3129 {
3130 if( ProfileManager.IsSignedIn(j) )
3131 {
3132 app.DebugPrintf("Stats save for an offline game for the player at index %d\n", 0);
3133 Minecraft::GetInstance()->forceStatsSave(j);
3134 }
3135 }
3136 LeaderboardManager::Instance()->CloseSession();
3137#elif (defined _XBOX)
3138 ProfileManager.ForceQueuedProfileWrites();
3139#endif
3140
3141 // 4J-PB - cancel any possible string verifications queued with LIVE
3142 //InputManager.CancelAllVerifyInProgress();
3143
3144 if(ProfileManager.IsFullVersion())
3145 {
3146
3147 // In a split screen, only the primary player actually quits the game, others just remove their players
3148 if( i != ProfileManager.GetPrimaryPad() )
3149 {
3150 // Make sure we've not got this player selected as current - this shouldn't be the case anyway
3151 pMinecraft->setLocalPlayerIdx(ProfileManager.GetPrimaryPad());
3152 pMinecraft->removeLocalPlayerIdx(i);
3153
3154#ifdef _DURANGO
3155 ProfileManager.RemoveGamepadFromGame(i);
3156#endif
3157 SetAction(i,eAppAction_Idle);
3158 return;
3159 }
3160 // flag to capture the save thumbnail
3161 SetAction(i,eAppAction_ExitWorldCapturedThumbnail, param);
3162 }
3163 else
3164 {
3165 // ask the player if they would like to upgrade, or they'll lose the level
3166 UINT uiIDA[2];
3167 uiIDA[0]=IDS_CONFIRM_OK;
3168 uiIDA[1]=IDS_CONFIRM_CANCEL;
3169 ui.RequestErrorMessage(IDS_UNLOCK_TITLE, IDS_UNLOCK_TOSAVE_TEXT, uiIDA, 2, i,&CMinecraftApp::UnlockFullExitReturned,this);
3170 }
3171
3172 // Change the presence info
3173 // Are we offline or online, and how many players are there
3174
3175 if(g_NetworkManager.GetPlayerCount()>1)
3176 {
3177 for(int j=0;j<XUSER_MAX_COUNT;j++)
3178 {
3179 if(pMinecraft->localplayers[j])
3180 {
3181 if(g_NetworkManager.IsLocalGame())
3182 {
3183 app.SetRichPresenceContext(j,CONTEXT_GAME_STATE_BLANK);
3184 ProfileManager.SetCurrentGameActivity(j,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false);
3185 }
3186 else
3187 {
3188 app.SetRichPresenceContext(j,CONTEXT_GAME_STATE_BLANK);
3189 ProfileManager.SetCurrentGameActivity(j,CONTEXT_PRESENCE_MULTIPLAYER,false);
3190 }
3191 TelemetryManager->RecordLevelExit(j, eSen_LevelExitStatus_Exited);
3192 }
3193 }
3194 }
3195 else
3196 {
3197 app.SetRichPresenceContext(i,CONTEXT_GAME_STATE_BLANK);
3198 if(g_NetworkManager.IsLocalGame())
3199 {
3200 ProfileManager.SetCurrentGameActivity(i,CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE,false);
3201 }
3202 else
3203 {
3204 ProfileManager.SetCurrentGameActivity(i,CONTEXT_PRESENCE_MULTIPLAYER_1P,false);
3205 }
3206 TelemetryManager->RecordLevelExit(i, eSen_LevelExitStatus_Exited);
3207 }
3208 break;
3209 case eAppAction_ExitWorldCapturedThumbnail:
3210 {
3211 SetAction(i,eAppAction_Idle);
3212 // Stop app running
3213 SetGameStarted(false);
3214 SetChangingSessionType(true); // Added to stop handling ethernet disconnects
3215
3216 ui.CloseAllPlayersScenes();
3217
3218 // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
3219 ui.HideAllGameUIElements();
3220
3221 // 4J Stu - Fix for #12368 - Crash: Game crashes when saving then exiting and selecting to save
3222 for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
3223 {
3224#ifdef _XBOX
3225 app.TutorialSceneNavigateBack(idx,true);
3226#endif
3227
3228 // 4J Stu - Fix for #13257 - CRASH: Gameplay: Title crashed after exiting the tutorial
3229 // It doesn't matter if they were in the tutorial already
3230 pMinecraft->playerLeftTutorial( idx );
3231 }
3232
3233 LoadingInputParams *loadingParams = new LoadingInputParams();
3234 loadingParams->func = &UIScene_PauseMenu::ExitWorldThreadProc;
3235 loadingParams->lpParam = param;
3236
3237 UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
3238 // If param is non-null then this is a forced exit by the server, so make sure the player knows why
3239 // 4J Stu - Changed - Don't use the FullScreenProgressScreen for action, use a dialog instead
3240 completionData->bRequiresUserAction = FALSE;//(param != NULL) ? TRUE : FALSE;
3241 completionData->bShowTips = (param != NULL) ? FALSE : TRUE;
3242 completionData->bShowBackground=TRUE;
3243 completionData->bShowLogo=TRUE;
3244 completionData->type = e_ProgressCompletion_NavigateToHomeMenu;
3245 completionData->iPad = DEFAULT_XUI_MENU_USER;
3246 loadingParams->completionData = completionData;
3247
3248 ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);
3249 }
3250 break;
3251 case eAppAction_ExitWorldTrial:
3252 {
3253 SetAction(i,eAppAction_Idle);
3254
3255 pMinecraft->gui->clearMessages();
3256
3257 // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
3258 ui.HideAllGameUIElements();
3259
3260 // Stop app running
3261 SetGameStarted(false);
3262
3263 ui.CloseAllPlayersScenes();
3264
3265 // 4J Stu - Fix for #12368 - Crash: Game crashes when saving then exiting and selecting to save
3266 for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
3267 {
3268#ifdef _XBOX
3269 app.TutorialSceneNavigateBack(idx,true);
3270#endif
3271
3272 // 4J Stu - Fix for #13257 - CRASH: Gameplay: Title crashed after exiting the tutorial
3273 // It doesn't matter if they were in the tutorial already
3274 pMinecraft->playerLeftTutorial( idx );
3275 }
3276
3277 LoadingInputParams *loadingParams = new LoadingInputParams();
3278 loadingParams->func = &UIScene_PauseMenu::ExitWorldThreadProc;
3279 loadingParams->lpParam = param;
3280
3281 UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
3282 completionData->bShowBackground=TRUE;
3283 completionData->bShowLogo=TRUE;
3284 completionData->type = e_ProgressCompletion_NavigateToHomeMenu;
3285 completionData->iPad = DEFAULT_XUI_MENU_USER;
3286 loadingParams->completionData = completionData;
3287
3288 ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);
3289 }
3290
3291 break;
3292 case eAppAction_ExitTrial:
3293 //XLaunchNewImage(XLAUNCH_KEYWORD_DASH_ARCADE, 0);
3294 ExitGame();
3295 break;
3296
3297 case eAppAction_Respawn:
3298 {
3299 ConnectionProgressParams *param = new ConnectionProgressParams();
3300 param->iPad = i;
3301 param->stringId = IDS_PROGRESS_RESPAWNING;
3302 param->showTooltips = false;
3303 param->setFailTimer = false;
3304 ui.NavigateToScene(i,eUIScene_ConnectingProgress, param);
3305
3306 // Need to reset this incase the player has already died and respawned
3307 pMinecraft->localplayers[i]->SetPlayerRespawned(false);
3308
3309 SetAction(i,eAppAction_WaitForRespawnComplete);
3310 if( app.GetLocalPlayerCount()>1 )
3311 {
3312 // In split screen mode, we don't want to do any async loading or flushing of the cache, just a simple respawn
3313 pMinecraft->localplayers[i]->respawn();
3314
3315 // If the respawn requires a dimension change then the action will have changed
3316 //if(app.GetXuiAction(i) == eAppAction_Respawn)
3317 //{
3318 // SetAction(i,eAppAction_Idle);
3319 // CloseXuiScenes(i);
3320 //}
3321 }
3322 else
3323 {
3324 //SetAction(i,eAppAction_WaitForRespawnComplete);
3325
3326 //LoadingInputParams *loadingParams = new LoadingInputParams();
3327 //loadingParams->func = &CScene_Death::RespawnThreadProc;
3328 //loadingParams->lpParam = (LPVOID)i;
3329
3330 // Disable game & update thread whilst we do any of this
3331 //app.SetGameStarted(false);
3332 pMinecraft->gameRenderer->DisableUpdateThread();
3333
3334 // 4J Stu - We don't need this on a thread in multiplayer as respawning is asynchronous.
3335 pMinecraft->localplayers[i]->respawn();
3336
3337 //app.SetGameStarted(true);
3338 pMinecraft->gameRenderer->EnableUpdateThread();
3339
3340 //UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
3341 //completionData->bShowBackground=TRUE;
3342 //completionData->bShowLogo=TRUE;
3343 //completionData->type = e_ProgressCompletion_CloseUIScenes;
3344 //completionData->iPad = i;
3345 //loadingParams->completionData = completionData;
3346
3347 //app.NavigateToScene(i,eUIScene_FullscreenProgress, loadingParams, true);
3348 }
3349 }
3350 break;
3351 case eAppAction_WaitForRespawnComplete:
3352 player = pMinecraft->localplayers[i];
3353 if(player != NULL && player->GetPlayerRespawned())
3354 {
3355 SetAction(i,eAppAction_Idle);
3356
3357 if(ui.IsSceneInStack(i, eUIScene_EndPoem))
3358 {
3359 ui.NavigateBack(i,false,eUIScene_EndPoem);
3360 }
3361 else
3362 {
3363 ui.CloseUIScenes(i);
3364 }
3365
3366 // clear the progress messages
3367
3368 // pMinecraft->progressRenderer->progressStart(-1);
3369 // pMinecraft->progressRenderer->progressStage(-1);
3370 }
3371 else if(!g_NetworkManager.IsInGameplay())
3372 {
3373 SetAction(i,eAppAction_Idle);
3374 }
3375 break;
3376 case eAppAction_WaitForDimensionChangeComplete:
3377 player = pMinecraft->localplayers[i];
3378 if(player != NULL && player->connection && player->connection->isStarted())
3379 {
3380 SetAction(i,eAppAction_Idle);
3381 ui.CloseUIScenes(i);
3382 }
3383 else if(!g_NetworkManager.IsInGameplay())
3384 {
3385 SetAction(i,eAppAction_Idle);
3386 }
3387 break;
3388 case eAppAction_PrimaryPlayerSignedOut:
3389 {
3390 //SetAction(i,eAppAction_Idle);
3391
3392 // clear the autosavetimer that might be displayed
3393 ui.ShowAutosaveCountdownTimer(false);
3394
3395 // If the player signs out before the game started the server can be killed a bit earlier to stop
3396 // the loading or saving of a new game continuing running while the UI/Guide is up
3397 if(!app.GetGameStarted()) MinecraftServer::HaltServer(true);
3398
3399 // inform the player they are being returned to the menus because they signed out
3400 StorageManager.SetSaveDeviceSelected(i,false);
3401 // need to clear the player stats - can't assume it'll be done in setlevel - we may not be in the game
3402 StatsCounter* pStats = Minecraft::GetInstance()->stats[ i ];
3403 pStats->clear();
3404
3405 // 4J-PB - the libs will display the Returned to Title screen
3406 // UINT uiIDA[1];
3407 // uiIDA[0]=IDS_CONFIRM_OK;
3408 //
3409 // ui.RequestMessageBox(IDS_RETURNEDTOMENU_TITLE, IDS_RETURNEDTOTITLESCREEN_TEXT, uiIDA, 1, i,&CMinecraftApp::PrimaryPlayerSignedOutReturned,this,app.GetStringTable());
3410 if( g_NetworkManager.IsInSession() )
3411 {
3412 app.SetAction(i,eAppAction_PrimaryPlayerSignedOutReturned);
3413 }
3414 else
3415 {
3416 app.SetAction(i,eAppAction_PrimaryPlayerSignedOutReturned_Menus);
3417 MinecraftServer::resetFlags();
3418 }
3419 }
3420 break;
3421 case eAppAction_EthernetDisconnected:
3422 {
3423 app.DebugPrintf("Handling eAppAction_EthernetDisconnected\n");
3424 SetAction(i,eAppAction_Idle);
3425
3426 // 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.
3427 if(!g_NetworkManager.IsLeavingGame())
3428 {
3429 app.DebugPrintf("Handling eAppAction_EthernetDisconnected - Not leaving game\n");
3430 // 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.
3431 if( g_NetworkManager.IsHost() )
3432 {
3433 app.DebugPrintf("Handling eAppAction_EthernetDisconnected - Is Host\n");
3434 // If it's already a local game, then an ethernet disconnect should have no effect
3435 if( !g_NetworkManager.IsLocalGame() && g_NetworkManager.IsInGameplay() )
3436 {
3437 // Change the session to an offline session
3438 SetAction(i,eAppAction_ChangeSessionType);
3439 }
3440 else if(!g_NetworkManager.IsLocalGame() && !g_NetworkManager.IsInGameplay() )
3441 {
3442 // There are two cases here, either:
3443 // 1. We're early enough in the create/load game that we can do a really minimal shutdown or
3444 // 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
3445
3446 // If there's a non-null level then, for our purposes, the game has started
3447 bool gameStarted = false;
3448 for(int j = 0; j < pMinecraft->levels.length; j++)
3449 {
3450 if (pMinecraft->levels.data[i] != nullptr)
3451 {
3452 gameStarted = true;
3453 break;
3454 }
3455 }
3456
3457 if (!gameStarted)
3458 {
3459 // 1. Exit
3460 MinecraftServer::HaltServer();
3461
3462 // 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.
3463 // 4J Stu - Leave the session
3464 g_NetworkManager.LeaveGame(FALSE);
3465
3466 // need to clear the player stats - can't assume it'll be done in setlevel - we may not be in the game
3467 StatsCounter* pStats = Minecraft::GetInstance()->stats[ i ];
3468 pStats->clear();
3469 UINT uiIDA[1];
3470 uiIDA[0]=IDS_CONFIRM_OK;
3471
3472 ui.RequestErrorMessage(g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST), g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE), uiIDA, 1, i,&CMinecraftApp::EthernetDisconnectReturned,this);
3473 }
3474 else
3475 {
3476 // 2. Switch to offline
3477 SetAction(i,eAppAction_ChangeSessionType);
3478 }
3479 }
3480 }
3481 else
3482 {
3483#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__
3484 if(UIScene_LoadOrJoinMenu::isSaveTransferRunning())
3485 {
3486 // the save transfer is still in progress, delay jumping back to the main menu until we've cleaned up
3487 SetAction(i,eAppAction_EthernetDisconnected);
3488 }
3489 else
3490#endif
3491 {
3492 app.DebugPrintf("Handling eAppAction_EthernetDisconnected - Not host\n");
3493 // need to clear the player stats - can't assume it'll be done in setlevel - we may not be in the game
3494 StatsCounter* pStats = Minecraft::GetInstance()->stats[ i ];
3495 pStats->clear();
3496 UINT uiIDA[1];
3497 uiIDA[0]=IDS_CONFIRM_OK;
3498
3499 ui.RequestErrorMessage(g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST), g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE), uiIDA, 1, i,&CMinecraftApp::EthernetDisconnectReturned,this);
3500
3501 }
3502 }
3503 }
3504 }
3505 break;
3506 // We currently handle both these returns the same way.
3507 case eAppAction_EthernetDisconnectedReturned:
3508 case eAppAction_PrimaryPlayerSignedOutReturned:
3509 {
3510 SetAction(i,eAppAction_Idle);
3511
3512 pMinecraft->gui->clearMessages();
3513
3514 // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
3515 ui.HideAllGameUIElements();
3516
3517 // set the state back to pre-game
3518 ProfileManager.ResetProfileProcessState();
3519
3520
3521 if( g_NetworkManager.IsLeavingGame() )
3522 {
3523 // 4J Stu - If we are already leaving the game, then we just need to signal that the player signed out to stop saves
3524 pMinecraft->progressRenderer->progressStartNoAbort( IDS_EXITING_GAME );
3525 pMinecraft->progressRenderer->progressStage(-1);
3526 // This has no effect on client machines
3527 MinecraftServer::HaltServer(true);
3528 }
3529 else
3530 {
3531 // Stop app running
3532 SetGameStarted(false);
3533
3534 // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
3535 ui.HideAllGameUIElements();
3536
3537 ui.CloseAllPlayersScenes();
3538
3539 // 4J Stu - Fix for #12368 - Crash: Game crashes when saving then exiting and selecting to save
3540 for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
3541 {
3542#ifdef _XBOX
3543 app.TutorialSceneNavigateBack(idx,true);
3544#endif
3545
3546 // 4J Stu - Fix for #13257 - CRASH: Gameplay: Title crashed after exiting the tutorial
3547 // It doesn't matter if they were in the tutorial already
3548 pMinecraft->playerLeftTutorial( idx );
3549 }
3550
3551 LoadingInputParams *loadingParams = new LoadingInputParams();
3552 loadingParams->func = &CMinecraftApp::SignoutExitWorldThreadProc;
3553
3554 UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
3555 completionData->bShowBackground=TRUE;
3556 completionData->bShowLogo=TRUE;
3557 completionData->iPad=DEFAULT_XUI_MENU_USER;
3558 completionData->type = e_ProgressCompletion_NavigateToHomeMenu;
3559 loadingParams->completionData = completionData;
3560
3561 ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);
3562 }
3563 }
3564 break;
3565 case eAppAction_PrimaryPlayerSignedOutReturned_Menus:
3566 SetAction(i,eAppAction_Idle);
3567 // set the state back to pre-game
3568 ProfileManager.ResetProfileProcessState();
3569 // clear the save device
3570 StorageManager.SetSaveDeviceSelected(i,false);
3571
3572 ui.UpdatePlayerBasePositions();
3573 // there are multiple layers in the help menu, so a navigate back isn't enough
3574 ui.NavigateToHomeMenu();
3575
3576 break;
3577 case eAppAction_EthernetDisconnectedReturned_Menus:
3578 SetAction(i,eAppAction_Idle);
3579 // set the state back to pre-game
3580 ProfileManager.ResetProfileProcessState();
3581
3582 ui.UpdatePlayerBasePositions();
3583
3584 // there are multiple layers in the help menu, so a navigate back isn't enough
3585 ui.NavigateToHomeMenu();
3586
3587 break;
3588
3589 case eAppAction_TrialOver:
3590 {
3591 SetAction(i,eAppAction_Idle);
3592 UINT uiIDA[2];
3593 uiIDA[0]=IDS_UNLOCK_TITLE;
3594 uiIDA[1]=IDS_EXIT_GAME;
3595
3596 ui.RequestErrorMessage(IDS_TRIALOVER_TITLE, IDS_TRIALOVER_TEXT, uiIDA, 2, i,&CMinecraftApp::TrialOverReturned,this);
3597 }
3598 break;
3599
3600 // INVITES
3601 case eAppAction_DashboardTrialJoinFromInvite:
3602 {
3603 TelemetryManager->RecordUpsellPresented(i, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID);
3604
3605 SetAction(i,eAppAction_Idle);
3606 UINT uiIDA[2];
3607 uiIDA[0]=IDS_CONFIRM_OK;
3608 uiIDA[1]=IDS_CONFIRM_CANCEL;
3609
3610 ui.RequestErrorMessage(IDS_UNLOCK_TITLE, IDS_UNLOCK_ACCEPT_INVITE, uiIDA, 2, i,&CMinecraftApp::UnlockFullInviteReturned,this);
3611 }
3612 break;
3613 case eAppAction_ExitAndJoinFromInvite:
3614 {
3615 UINT uiIDA[3];
3616
3617 SetAction(i,eAppAction_Idle);
3618 // Check the player really wants to do this
3619
3620#if defined(_XBOX_ONE) || defined(__ORBIS__)
3621 // Show save option is saves ARE disabled
3622 if(ProfileManager.IsFullVersion() && StorageManager.GetSaveDisabled() && i==ProfileManager.GetPrimaryPad() && g_NetworkManager.IsHost() && GetGameStarted() )
3623 {
3624 uiIDA[0]=IDS_CONFIRM_CANCEL;
3625 uiIDA[1]=IDS_EXIT_GAME_SAVE;
3626 uiIDA[2]=IDS_EXIT_GAME_NO_SAVE;
3627
3628 ui.RequestAlertMessage(IDS_EXIT_GAME, IDS_CONFIRM_LEAVE_VIA_INVITE, uiIDA, 3, i,&CMinecraftApp::ExitAndJoinFromInviteSaveDialogReturned,this);
3629 }
3630 else
3631#else
3632 if(ProfileManager.IsFullVersion() && !StorageManager.GetSaveDisabled() && i==ProfileManager.GetPrimaryPad() && g_NetworkManager.IsHost() && GetGameStarted() )
3633 {
3634 uiIDA[0]=IDS_CONFIRM_CANCEL;
3635 uiIDA[1]=IDS_EXIT_GAME_SAVE;
3636 uiIDA[2]=IDS_EXIT_GAME_NO_SAVE;
3637
3638 ui.RequestAlertMessage(IDS_EXIT_GAME, IDS_CONFIRM_LEAVE_VIA_INVITE, uiIDA, 3, i,&CMinecraftApp::ExitAndJoinFromInviteSaveDialogReturned,this);
3639 }
3640 else
3641#endif
3642 {
3643 if(!ProfileManager.IsFullVersion())
3644 {
3645 TelemetryManager->RecordUpsellPresented(i, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID);
3646
3647 // upsell
3648 uiIDA[0]=IDS_CONFIRM_OK;
3649 uiIDA[1]=IDS_CONFIRM_CANCEL;
3650 ui.RequestErrorMessage(IDS_UNLOCK_TITLE, IDS_UNLOCK_ACCEPT_INVITE, uiIDA, 2, i,&CMinecraftApp::UnlockFullInviteReturned,this);
3651 }
3652 else
3653 {
3654 uiIDA[0]=IDS_CONFIRM_CANCEL;
3655 uiIDA[1]=IDS_CONFIRM_OK;
3656 ui.RequestAlertMessage(IDS_EXIT_GAME, IDS_CONFIRM_LEAVE_VIA_INVITE, uiIDA, 2,i,&CMinecraftApp::ExitAndJoinFromInvite,this);
3657 }
3658 }
3659 }
3660 break;
3661 case eAppAction_ExitAndJoinFromInviteConfirmed:
3662 {
3663 SetAction(i,eAppAction_Idle);
3664
3665 pMinecraft->gui->clearMessages();
3666
3667 // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
3668 ui.HideAllGameUIElements();
3669
3670 // Stop app running
3671 SetGameStarted(false);
3672
3673 ui.CloseAllPlayersScenes();
3674
3675 // 4J Stu - Fix for #12368 - Crash: Game crashes when saving then exiting and selecting to save
3676 for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
3677 {
3678#ifdef _XBOX
3679 app.TutorialSceneNavigateBack(idx,true);
3680#endif
3681
3682 // 4J Stu - Fix for #13257 - CRASH: Gameplay: Title crashed after exiting the tutorial
3683 // It doesn't matter if they were in the tutorial already
3684 pMinecraft->playerLeftTutorial( idx );
3685 }
3686
3687 // 4J-PB - may have been using a texture pack with audio , so clean up anything texture pack related here
3688
3689 // unload any texture pack audio
3690 // if there is audio in use, clear out the audio, and unmount the pack
3691 TexturePack *pTexPack=Minecraft::GetInstance()->skins->getSelected();
3692 DLCTexturePack *pDLCTexPack=NULL;
3693
3694 if(pTexPack->hasAudio())
3695 {
3696 // get the dlc texture pack, and store it
3697 pDLCTexPack=(DLCTexturePack *)pTexPack;
3698 }
3699
3700 // change to the default texture pack
3701 pMinecraft->skins->selectTexturePackById(TexturePackRepository::DEFAULT_TEXTURE_PACK_ID);
3702
3703 if(pTexPack->hasAudio())
3704 {
3705 // need to stop the streaming audio - by playing streaming audio from the default texture pack now
3706 // reset the streaming sounds back to the normal ones
3707#ifndef _XBOX
3708 pMinecraft->soundEngine->SetStreamingSounds(eStream_Overworld_Calm1,eStream_Overworld_piano3,
3709 eStream_Nether1,eStream_Nether4,
3710 eStream_end_dragon,eStream_end_end,
3711 eStream_CD_1);
3712#endif
3713 pMinecraft->soundEngine->playStreaming(L"", 0, 0, 0, 1, 1);
3714
3715#ifdef _XBOX
3716 if(pDLCTexPack->m_pStreamedWaveBank!=NULL)
3717 {
3718 pDLCTexPack->m_pStreamedWaveBank->Destroy();
3719 }
3720 if(pDLCTexPack->m_pSoundBank!=NULL)
3721 {
3722 pDLCTexPack->m_pSoundBank->Destroy();
3723 }
3724#endif
3725#ifdef _DURANGO
3726 DWORD result = StorageManager.UnmountInstalledDLC(L"TPACK");
3727#else
3728 DWORD result = StorageManager.UnmountInstalledDLC("TPACK");
3729#endif
3730 app.DebugPrintf("Unmount result is %d\n",result);
3731 }
3732
3733#ifdef _XBOX_ONE
3734 // 4J Stu - It's possible that we can sign in/remove players between the mask initially being set and this point
3735 m_InviteData.dwLocalUsersMask = 0;
3736 for(unsigned int index = 0; index < XUSER_MAX_COUNT; ++index)
3737 {
3738 if(ProfileManager.IsSignedIn(index) )
3739 {
3740 if(index==i || pMinecraft->localplayers[index]!=NULL )
3741 {
3742 m_InviteData.dwLocalUsersMask |= g_NetworkManager.GetLocalPlayerMask( index );
3743 }
3744 }
3745 }
3746#endif
3747
3748 LoadingInputParams *loadingParams = new LoadingInputParams();
3749 loadingParams->func = &CGameNetworkManager::ExitAndJoinFromInviteThreadProc;
3750 loadingParams->lpParam = (LPVOID)&m_InviteData;
3751
3752 UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
3753 completionData->bShowBackground=TRUE;
3754 completionData->bShowLogo=TRUE;
3755 completionData->iPad=DEFAULT_XUI_MENU_USER;
3756 completionData->type = e_ProgressCompletion_NoAction;
3757 loadingParams->completionData = completionData;
3758
3759 ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);
3760 }
3761
3762 break;
3763 case eAppAction_JoinFromInvite:
3764 {
3765 SetAction(i,eAppAction_Idle);
3766
3767 // 4J Stu - Move this state block from CPlatformNetworkManager::ExitAndJoinFromInviteThreadProc, as g_NetworkManager.JoinGameFromInviteInfo ultimately can call NavigateToScene,
3768 /// and we should only be calling that from the main thread
3769 app.SetTutorialMode( false );
3770
3771 g_NetworkManager.SetLocalGame(false);
3772
3773 JoinFromInviteData *inviteData = (JoinFromInviteData *)param;
3774 // 4J-PB - clear any previous connection errors
3775 Minecraft::GetInstance()->clearConnectionFailed();
3776
3777 app.DebugPrintf( "Changing Primary Pad on an invite accept - pad was %d, and is now %d\n", ProfileManager.GetPrimaryPad(), inviteData->dwUserIndex );
3778 ProfileManager.SetLockedProfile(inviteData->dwUserIndex);
3779 ProfileManager.SetPrimaryPad(inviteData->dwUserIndex);
3780
3781#ifdef _XBOX_ONE
3782 // 4J Stu - If a player is signed in (i.e. locked) but not in the mask, unlock them
3783 for(unsigned int index = 0; index < XUSER_MAX_COUNT; ++index)
3784 {
3785 if( index != inviteData->dwUserIndex && ProfileManager.IsSignedIn(index) )
3786 {
3787 if( (m_InviteData.dwLocalUsersMask & g_NetworkManager.GetLocalPlayerMask( index ) ) == 0 )
3788 {
3789 ProfileManager.RemoveGamepadFromGame(index);
3790 }
3791 }
3792 }
3793#endif
3794
3795 // change the minecraft player name
3796 Minecraft::GetInstance()->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad()));
3797
3798 bool success = g_NetworkManager.JoinGameFromInviteInfo(
3799 inviteData->dwUserIndex, // dwUserIndex
3800 inviteData->dwLocalUsersMask, // dwUserMask
3801 inviteData->pInviteInfo ); // pInviteInfo
3802
3803 if( !success )
3804 {
3805 app.DebugPrintf( "Failed joining game from invite\n" );
3806 //return hr;
3807
3808 // 4J Stu - Copied this from XUI_FullScreenProgress to properly handle the fail case, as the thread will no longer be failing
3809 UINT uiIDA[1];
3810 uiIDA[0]=IDS_CONFIRM_OK;
3811 ui.RequestErrorMessage( IDS_CONNECTION_FAILED, IDS_CONNECTION_LOST_SERVER, uiIDA,1,ProfileManager.GetPrimaryPad());
3812
3813 ui.NavigateToHomeMenu();
3814 ui.UpdatePlayerBasePositions();
3815 }
3816 }
3817 break;
3818 case eAppAction_ChangeSessionType:
3819 {
3820 // If we are not in gameplay yet, then wait until the server is setup before changing the session type
3821 if( g_NetworkManager.IsInGameplay() )
3822 {
3823 // 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
3824
3825 SetAction(i,eAppAction_Idle);
3826
3827 if( !GetChangingSessionType() && !g_NetworkManager.IsLocalGame() )
3828 {
3829 SetGameStarted(false);
3830 SetChangingSessionType(true);
3831 SetReallyChangingSessionType(true);
3832
3833 // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
3834 ui.HideAllGameUIElements();
3835
3836 if( !ui.IsSceneInStack( ProfileManager.GetPrimaryPad(), eUIScene_EndPoem ) )
3837 {
3838 ui.CloseAllPlayersScenes();
3839 }
3840 ui.ShowOtherPlayersBaseScene(ProfileManager.GetPrimaryPad(), true);
3841
3842 // Remove this line to fix:
3843 // #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.
3844 //app.NavigateToScene(0,eUIScene_Main);
3845
3846 LoadingInputParams *loadingParams = new LoadingInputParams();
3847 loadingParams->func = &CGameNetworkManager::ChangeSessionTypeThreadProc;
3848 loadingParams->lpParam = NULL;
3849
3850 UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
3851#ifdef __PS3__
3852 completionData->bRequiresUserAction=FALSE;
3853#else
3854 completionData->bRequiresUserAction=TRUE;
3855#endif
3856 completionData->bShowBackground=TRUE;
3857 completionData->bShowLogo=TRUE;
3858 completionData->iPad=DEFAULT_XUI_MENU_USER;
3859 if( ui.IsSceneInStack( ProfileManager.GetPrimaryPad(), eUIScene_EndPoem ) )
3860 {
3861 completionData->type = e_ProgressCompletion_NavigateBackToScene;
3862 completionData->scene = eUIScene_EndPoem;
3863 }
3864 else
3865 {
3866 completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes;
3867 }
3868 loadingParams->completionData = completionData;
3869
3870 ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);
3871 }
3872 }
3873 else if( g_NetworkManager.IsLeavingGame() )
3874 {
3875 // If we are leaving the game, then ignore the state change
3876 SetAction(i,eAppAction_Idle);
3877 }
3878#if 0
3879 // 4J-HG - Took this out since ChangeSessionType is only set in two places (both in EthernetDisconnected) and this case is handled there, plus this breaks
3880 // this if statements original purpose (to allow us to wait for IsInGameplay before actioning switching to offline
3881
3882 // QNet must do this kind of thing automatically by itself, but on PS3 at least, we need the disconnection to definitely end up with us out of the game one way or another,
3883 // and the other two cases above don't catch the case where we are just starting the game and get a disconnection during the loading/creation
3884 else
3885 {
3886 if( g_NetworkManager.IsInSession() )
3887 {
3888 g_NetworkManager._LeaveGame();
3889 }
3890 }
3891#endif
3892 }
3893 break;
3894 case eAppAction_SetDefaultOptions:
3895 SetAction(i,eAppAction_Idle);
3896#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
3897 SetDefaultOptions((C4JStorage::PROFILESETTINGS *)param,i);
3898#else
3899 SetDefaultOptions((C_4JProfile::PROFILESETTINGS *)param,i);
3900#endif
3901
3902 // if the profile data has been changed, then force a profile write
3903 // It seems we're allowed to break the 5 minute rule if it's the result of a user action
3904 CheckGameSettingsChanged(true,i);
3905
3906 break;
3907
3908 case eAppAction_RemoteServerSave:
3909 {
3910 // If the remote server save has already finished, don't complete the action
3911 if (GetGameStarted())
3912 {
3913 SetAction(ProfileManager.GetPrimaryPad(), eAppAction_Idle);
3914 break;
3915 }
3916
3917 SetAction(i,eAppAction_WaitRemoteServerSaveComplete);
3918
3919 for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
3920 {
3921 ui.CloseUIScenes(i, true);
3922 }
3923
3924 // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen
3925 ui.HideAllGameUIElements();
3926
3927 LoadingInputParams *loadingParams = new LoadingInputParams();
3928 loadingParams->func = &CMinecraftApp::RemoteSaveThreadProc;
3929 loadingParams->lpParam = NULL;
3930
3931 UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData();
3932 completionData->bRequiresUserAction=FALSE;
3933 completionData->bShowBackground=TRUE;
3934 completionData->bShowLogo=TRUE;
3935 completionData->iPad=DEFAULT_XUI_MENU_USER;
3936 if( ui.IsSceneInStack( ProfileManager.GetPrimaryPad(), eUIScene_EndPoem ) )
3937 {
3938 completionData->type = e_ProgressCompletion_NavigateBackToScene;
3939 completionData->scene = eUIScene_EndPoem;
3940 }
3941 else
3942 {
3943 completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes;
3944 }
3945 loadingParams->completionData = completionData;
3946
3947 loadingParams->cancelFunc = &CMinecraftApp::ExitGameFromRemoteSave;
3948 loadingParams->cancelText = IDS_TOOLTIPS_EXIT;
3949
3950 ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams);
3951 }
3952 break;
3953 case eAppAction_WaitRemoteServerSaveComplete:
3954 // Do nothing
3955 break;
3956 case eAppAction_FailedToJoinNoPrivileges:
3957 {
3958 UINT uiIDA[1];
3959 uiIDA[0]=IDS_CONFIRM_OK;
3960 C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad());
3961 if(result != C4JStorage::EMessage_Busy) SetAction(i,eAppAction_Idle);
3962 }
3963 break;
3964 case eAppAction_ProfileReadError:
3965 // Return player to the main menu - code largely copied from that for handling
3966 // eAppAction_PrimaryPlayerSignedOut, although I don't think we should have got as
3967 // far as needing to halt the server, or running the game, before returning to the menu
3968 if(!app.GetGameStarted()) MinecraftServer::HaltServer(true);
3969
3970 if( g_NetworkManager.IsInSession() )
3971 {
3972 app.SetAction(i,eAppAction_PrimaryPlayerSignedOutReturned);
3973 }
3974 else
3975 {
3976 app.SetAction(i,eAppAction_PrimaryPlayerSignedOutReturned_Menus);
3977 MinecraftServer::resetFlags();
3978 }
3979 break;
3980
3981 case eAppAction_BanLevel:
3982 {
3983 // 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
3984 if(g_NetworkManager.IsInGameplay() && !g_NetworkManager.IsLeavingGame())
3985 {
3986 TelemetryManager->RecordBanLevel(i);
3987
3988#if defined _XBOX
3989 INetworkPlayer *pHost=g_NetworkManager.GetHostPlayer();
3990 // write the level to the banned level list, and exit the world
3991 AddLevelToBannedLevelList(i,((NetworkPlayerXbox *)pHost)->GetUID(),GetUniqueMapName(),true);
3992#elif defined _XBOX_ONE
3993 INetworkPlayer *pHost=g_NetworkManager.GetHostPlayer();
3994 AddLevelToBannedLevelList(i,pHost->GetUID(),GetUniqueMapName(),true);
3995#endif
3996 // primary player would exit the world, secondary would exit the player
3997 if(ProfileManager.GetPrimaryPad()==i)
3998 {
3999 SetAction(i,eAppAction_ExitWorld);
4000 }
4001 else
4002 {
4003 SetAction(i,eAppAction_ExitPlayer);
4004 }
4005 }
4006 }
4007 break;
4008 case eAppAction_LevelInBanLevelList:
4009 {
4010 UINT uiIDA[2];
4011 uiIDA[0]=IDS_BUTTON_REMOVE_FROM_BAN_LIST;
4012 uiIDA[1]=IDS_EXIT_GAME;
4013
4014 // pass in the gamertag format string
4015 WCHAR wchFormat[40];
4016 INetworkPlayer *player = g_NetworkManager.GetLocalPlayerByUserIndex(i);
4017
4018 // If not the primary player, but the primary player has banned this level and decided not to unban
4019 // then we may have left the game by now
4020 if(player)
4021 {
4022 swprintf(wchFormat, 40, L"%ls\n\n%%ls",player->GetOnlineName());
4023
4024 C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_BANNED_LEVEL_TITLE, IDS_PLAYER_BANNED_LEVEL, uiIDA,2,i,&CMinecraftApp::BannedLevelDialogReturned,this, wchFormat);
4025 if(result != C4JStorage::EMessage_Busy) SetAction(i,eAppAction_Idle);
4026 }
4027 else
4028 {
4029 SetAction(i,eAppAction_Idle);
4030 }
4031 }
4032 break;
4033 case eAppAction_DebugText:
4034 // launch the xui for text entry
4035 {
4036#ifdef _XBOX
4037 CScene_TextEntry::XuiTextInputParams *pDebugTextParams= new CScene_TextEntry::XuiTextInputParams;
4038 pDebugTextParams->iPad=i;
4039 pDebugTextParams->wch=(WCHAR)param;
4040
4041 app.NavigateToScene(i,eUIScene_TextEntry,pDebugTextParams);
4042#endif
4043 SetAction(i,eAppAction_Idle);
4044 }
4045 break;
4046
4047 case eAppAction_ReloadTexturePack:
4048 {
4049 SetAction(i,eAppAction_Idle);
4050 Minecraft *pMinecraft = Minecraft::GetInstance();
4051 pMinecraft->textures->reloadAll();
4052 pMinecraft->skins->updateUI();
4053
4054 if(!pMinecraft->skins->isUsingDefaultSkin())
4055 {
4056 TexturePack *pTexturePack = pMinecraft->skins->getSelected();
4057
4058 DLCPack *pDLCPack=pTexturePack->getDLCPack();
4059
4060 bool purchased = false;
4061 // do we have a license?
4062 if(pDLCPack && pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" ))
4063 {
4064 purchased = true;
4065 }
4066#ifdef _XBOX
4067 TelemetryManager->RecordTexturePackLoaded(i, pTexturePack->getId(), purchased?1:0);
4068#endif
4069 }
4070
4071 // 4J-PB - If the texture pack has audio, we need to switch to this
4072 if(pMinecraft->skins->getSelected()->hasAudio())
4073 {
4074 Minecraft::GetInstance()->soundEngine->playStreaming(L"", 0, 0, 0, 1, 1);
4075 }
4076 }
4077 break;
4078
4079 case eAppAction_ReloadFont:
4080 {
4081#ifndef _XBOX
4082 app.DebugPrintf(
4083 "[Consoles_App] eAppAction_ReloadFont, ingame='%s'.\n",
4084 app.GetGameStarted() ? "Yes" : "No" );
4085
4086 SetAction(i,eAppAction_Idle);
4087
4088 ui.SetTooltips(i, -1);
4089
4090 ui.ReloadSkin();
4091 ui.StartReloadSkinThread();
4092
4093 ui.setCleanupOnReload();
4094#endif
4095 }
4096 break;
4097
4098 case eAppAction_TexturePackRequired:
4099 {
4100#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__
4101 UINT uiIDA[2];
4102 uiIDA[0]=IDS_TEXTUREPACK_FULLVERSION;
4103 uiIDA[1]=IDS_CONFIRM_CANCEL; // let them continue without the texture pack here (as this is only really for r
4104 // Give the player a warning about the texture pack missing
4105 ui.RequestErrorMessage(IDS_DLC_TEXTUREPACK_NOT_PRESENT_TITLE, IDS_DLC_TEXTUREPACK_NOT_PRESENT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::TexturePackDialogReturned,this);
4106 SetAction(i,eAppAction_Idle);
4107#else
4108#ifdef _XBOX
4109 ULONGLONG ullOfferID_Full;
4110 app.GetDLCFullOfferIDForPackID(app.GetRequiredTexturePackID(),&ullOfferID_Full);
4111
4112 TelemetryManager->RecordUpsellPresented(ProfileManager.GetPrimaryPad(), eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF);
4113#endif
4114 UINT uiIDA[2];
4115
4116 uiIDA[0]=IDS_TEXTUREPACK_FULLVERSION;
4117 uiIDA[1]=IDS_TEXTURE_PACK_TRIALVERSION;
4118
4119 // Give the player a warning about the texture pack missing
4120 ui.RequestErrorMessage(IDS_DLC_TEXTUREPACK_NOT_PRESENT_TITLE, IDS_DLC_TEXTUREPACK_NOT_PRESENT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::TexturePackDialogReturned,this);
4121 SetAction(i,eAppAction_Idle);
4122#endif
4123 }
4124
4125 break;
4126 }
4127 }
4128
4129 // Any TMS actions?
4130
4131 eTMS = app.GetTMSAction(i);
4132
4133 if(eTMS!=eTMSAction_Idle)
4134 {
4135 switch(eTMS)
4136 {
4137 // TMS++ actions
4138 case eTMSAction_TMSPP_RetrieveFiles_CreateLoad_SignInReturned:
4139 case eTMSAction_TMSPP_RetrieveFiles_RunPlayGame:
4140#ifdef _XBOX
4141 app.TMSPP_SetTitleGroupID(GROUP_ID);
4142 SetTMSAction(i,eTMSAction_TMSPP_GlobalFileList);
4143#elif defined _XBOX_ONE
4144 SetTMSAction(i,eTMSAction_TMSPP_GlobalFileList_Waiting);
4145 app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_Title,eTMSAction_TMSPP_UserFileList);
4146#else
4147 SetTMSAction(i,eTMSAction_TMSPP_UserFileList);
4148#endif
4149 break;
4150
4151#ifdef _XBOX
4152 case eTMSAction_TMSPP_GlobalFileList:
4153 SetTMSAction(i,eTMSAction_TMSPP_GlobalFileList_Waiting);
4154 app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_Title,"\\",eTMSAction_TMSPP_UserFileList);
4155 break;
4156#endif
4157 case eTMSAction_TMSPP_UserFileList:
4158 // retrieve the file list first
4159#if defined _XBOX
4160 SetTMSAction(i,eTMSAction_TMSPP_UserFileList_Waiting);
4161 app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_TitleUser,"\\",eTMSAction_TMSPP_XUIDSFile);
4162#elif defined _XBOX_ONE
4163 SetTMSAction(i,eTMSAction_TMSPP_UserFileList_Waiting);
4164 app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_TitleUser,eTMSAction_TMSPP_DLCFile);
4165#else
4166 SetTMSAction(i,eTMSAction_TMSPP_XUIDSFile);
4167#endif
4168 break;
4169 case eTMSAction_TMSPP_XUIDSFile:
4170#ifdef _XBOX
4171 SetTMSAction(i,eTMSAction_TMSPP_XUIDSFile_Waiting);
4172 // pass in the next app action on the call or callback completing
4173 app.TMSPP_ReadXuidsFile(i,eTMSAction_TMSPP_DLCFile);
4174#else
4175 SetTMSAction(i,eTMSAction_TMSPP_DLCFile);
4176#endif
4177
4178 break;
4179 case eTMSAction_TMSPP_DLCFile:
4180#if defined _XBOX || defined _XBOX_ONE
4181 SetTMSAction(i,eTMSAction_TMSPP_DLCFile_Waiting);
4182 // pass in the next app action on the call or callback completing
4183 app.TMSPP_ReadDLCFile(i,eTMSAction_TMSPP_BannedListFile);
4184#else
4185 SetTMSAction(i,eTMSAction_TMSPP_BannedListFile);
4186#endif
4187 break;
4188 case eTMSAction_TMSPP_BannedListFile:
4189 // If we have one in TMSPP, then we can assume we can ignore TMS
4190#if defined _XBOX
4191 SetTMSAction(i,eTMSAction_TMSPP_BannedListFile_Waiting);
4192 // pass in the next app action on the call or callback completing
4193 if(app.TMSPP_ReadBannedList(i,eTMSAction_TMS_RetrieveFiles_Complete)==false)
4194 {
4195 // we don't have a banned list in TMSPP, so we should check TMS
4196 app.ReadBannedList(i, eTMSAction_TMS_RetrieveFiles_Complete,true);
4197 }
4198#elif defined _XBOX_ONE
4199 SetTMSAction(i,eTMSAction_TMSPP_BannedListFile_Waiting);
4200 // pass in the next app action on the call or callback completing
4201 app.TMSPP_ReadBannedList(i,eTMSAction_TMS_RetrieveFiles_Complete);
4202
4203#else
4204 SetTMSAction(i,eTMSAction_TMS_RetrieveFiles_Complete);
4205#endif
4206 break;
4207
4208 // SPECIAL CASE - where the user goes directly in to Help & Options from the main menu
4209 case eTMSAction_TMSPP_RetrieveFiles_HelpAndOptions:
4210 case eTMSAction_TMSPP_RetrieveFiles_DLCMain:
4211 // retrieve the file list first
4212#if defined _XBOX
4213 // pass in the next app action on the call or callback completing
4214 SetTMSAction(i,eTMSAction_TMSPP_XUIDSFile_Waiting);
4215 app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_Title,"\\",eTMSAction_TMSPP_DLCFileOnly);
4216#elif defined _XBOX_ONE
4217 SetTMSAction(i,eTMSAction_TMSPP_GlobalFileList_Waiting);
4218 app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_Title,eTMSAction_TMSPP_RetrieveUserFilelist_DLCFileOnly);
4219#else
4220 SetTMSAction(i,eTMSAction_TMSPP_DLCFileOnly);
4221#endif
4222 break;
4223 case eTMSAction_TMSPP_RetrieveUserFilelist_DLCFileOnly:
4224#if defined _XBOX
4225 SetTMSAction(i,eTMSAction_TMSPP_UserFileList_Waiting);
4226 app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_TitleUser,"\\",eTMSAction_TMSPP_XUIDSFile);
4227#elif defined _XBOX_ONE
4228 //StorageManager.TMSPP_DeleteFile(i,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,L"TP06.png",NULL,NULL, 0);
4229 SetTMSAction(i,eTMSAction_TMSPP_UserFileList_Waiting);
4230 app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_TitleUser,eTMSAction_TMSPP_DLCFileOnly);
4231#else
4232 SetTMSAction(i,eTMSAction_TMSPP_DLCFileOnly);
4233#endif
4234
4235 break;
4236
4237 case eTMSAction_TMSPP_DLCFileOnly:
4238#if defined _XBOX || defined _XBOX_ONE
4239 SetTMSAction(i,eTMSAction_TMSPP_DLCFile_Waiting);
4240 // pass in the next app action on the call or callback completing
4241 app.TMSPP_ReadDLCFile(i,eTMSAction_TMSPP_RetrieveFiles_Complete);
4242#else
4243 SetTMSAction(i,eTMSAction_TMSPP_RetrieveFiles_Complete);
4244#endif
4245 break;
4246
4247
4248 case eTMSAction_TMSPP_RetrieveFiles_Complete:
4249 SetTMSAction(i,eTMSAction_Idle);
4250 break;
4251
4252
4253 // TMS files
4254 /* case eTMSAction_TMS_RetrieveFiles_CreateLoad_SignInReturned:
4255 case eTMSAction_TMS_RetrieveFiles_RunPlayGame:
4256 #ifdef _XBOX
4257 SetTMSAction(i,eTMSAction_TMS_XUIDSFile_Waiting);
4258 // pass in the next app action on the call or callback completing
4259 app.ReadXuidsFileFromTMS(i,eTMSAction_TMS_DLCFile,true);
4260 #else
4261 SetTMSAction(i,eTMSAction_TMS_DLCFile);
4262 #endif
4263 break;
4264
4265 case eTMSAction_TMS_DLCFile:
4266 #ifdef _XBOX
4267 SetTMSAction(i,eTMSAction_TMS_DLCFile_Waiting);
4268 // pass in the next app action on the call or callback completing
4269 app.ReadDLCFileFromTMS(i,eTMSAction_TMS_BannedListFile,true);
4270 #else
4271 SetTMSAction(i,eTMSAction_TMS_BannedListFile);
4272 #endif
4273
4274 break;
4275
4276 case eTMSAction_TMS_RetrieveFiles_HelpAndOptions:
4277 case eTMSAction_TMS_RetrieveFiles_DLCMain:
4278 #ifdef _XBOX
4279 SetTMSAction(i,eTMSAction_TMS_DLCFile_Waiting);
4280 // pass in the next app action on the call or callback completing
4281 app.ReadDLCFileFromTMS(i,eTMSAction_Idle,true);
4282 #else
4283 SetTMSAction(i,eTMSAction_Idle);
4284 #endif
4285
4286 break;
4287 case eTMSAction_TMS_BannedListFile:
4288 #ifdef _XBOX
4289 SetTMSAction(i,eTMSAction_TMS_BannedListFile_Waiting);
4290 // pass in the next app action on the call or callback completing
4291 app.ReadBannedList(i, eTMSAction_TMS_RetrieveFiles_Complete,true);
4292 #else
4293 SetTMSAction(i,eTMSAction_TMS_RetrieveFiles_Complete);
4294 #endif
4295
4296 break;
4297
4298 */
4299 case eTMSAction_TMS_RetrieveFiles_Complete:
4300 SetTMSAction(i,eTMSAction_Idle);
4301 // if(StorageManager.SetSaveDevice(&CScene_Main::DeviceSelectReturned,pClass))
4302 // {
4303 // // save device already selected
4304 // // ensure we've applied this player's settings
4305 // app.ApplyGameSettingsChanged(ProfileManager.GetPrimaryPad());
4306 // app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_MultiGameJoinLoad);
4307 // }
4308 break;
4309 }
4310 }
4311
4312 }
4313}
4314
4315int CMinecraftApp::BannedLevelDialogReturned(void *pParam,int iPad,const C4JStorage::EMessageResult result)
4316{
4317 CMinecraftApp* pApp = (CMinecraftApp*)pParam;
4318 //Minecraft *pMinecraft=Minecraft::GetInstance();
4319
4320 if(result==C4JStorage::EMessage_ResultAccept)
4321 {
4322#if defined _XBOX || defined _XBOX_ONE
4323 INetworkPlayer *pHost = g_NetworkManager.GetHostPlayer();
4324 // unban the level
4325 if (pHost != NULL)
4326 {
4327#if defined _XBOX
4328 pApp->RemoveLevelFromBannedLevelList(iPad,((NetworkPlayerXbox *)pHost)->GetUID(),pApp->GetUniqueMapName());
4329#else
4330 pApp->RemoveLevelFromBannedLevelList(iPad,pHost->GetUID(),pApp->GetUniqueMapName());
4331#endif
4332 }
4333#endif
4334 }
4335 else
4336 {
4337 if( iPad == ProfileManager.GetPrimaryPad() )
4338 {
4339 pApp->SetAction(iPad,eAppAction_ExitWorld);
4340 }
4341 else
4342 {
4343 pApp->SetAction(iPad,eAppAction_ExitPlayer);
4344 }
4345 }
4346
4347 return 0;
4348}
4349
4350void CMinecraftApp::loadMediaArchive()
4351{
4352 wstring mediapath = L"";
4353
4354#ifdef __PS3__
4355 mediapath = L"Common\\Media\\MediaPS3.arc";
4356#elif _WINDOWS64
4357 mediapath = L"Common\\Media\\MediaWindows64.arc";
4358#elif __ORBIS__
4359 mediapath = L"Common\\Media\\MediaOrbis.arc";
4360#elif _DURANGO
4361 mediapath = L"Common\\Media\\MediaDurango.arc";
4362#elif __PSVITA__
4363 mediapath = L"Common\\Media\\MediaPSVita.arc";
4364#endif
4365
4366 if (!mediapath.empty())
4367 {
4368 m_mediaArchive = new ArchiveFile( File(mediapath) );
4369 }
4370#if 0
4371 string path = "Common\\media.arc";
4372 HANDLE hFile = CreateFile( path.c_str(),
4373 GENERIC_READ,
4374 FILE_SHARE_READ,
4375 NULL,
4376 OPEN_EXISTING,
4377 FILE_FLAG_SEQUENTIAL_SCAN,
4378 NULL );
4379
4380 if( hFile != INVALID_HANDLE_VALUE )
4381 {
4382 File fileHelper(convStringToWstring(path));
4383 DWORD dwFileSize = fileHelper.length();
4384
4385 // Initialize memory.
4386 PBYTE m_fBody = new BYTE[ dwFileSize ];
4387 ZeroMemory(m_fBody, dwFileSize);
4388
4389 DWORD m_fSize = 0;
4390 BOOL hr = ReadFile( hFile,
4391 m_fBody,
4392 dwFileSize,
4393 &m_fSize,
4394 NULL );
4395
4396 assert( m_fSize == dwFileSize );
4397
4398 CloseHandle( hFile );
4399
4400 m_mediaArchive = new ArchiveFile(m_fBody, m_fSize);
4401 }
4402 else
4403 {
4404 assert( false );
4405 // AHHHHHHHHHHHH
4406 m_mediaArchive = NULL;
4407 }
4408#endif
4409}
4410
4411void CMinecraftApp::loadStringTable()
4412{
4413#ifndef _XBOX
4414
4415 if(m_stringTable!=NULL)
4416 {
4417 // we need to unload the current string table, this is a reload
4418 delete m_stringTable;
4419 }
4420 wstring localisationFile = L"languages.loc";
4421 if (m_mediaArchive->hasFile(localisationFile))
4422 {
4423 byteArray locFile = m_mediaArchive->getFile(localisationFile);
4424 m_stringTable = new StringTable(locFile.data, locFile.length);
4425 delete locFile.data;
4426 }
4427 else
4428 {
4429 m_stringTable = NULL;
4430 assert(false);
4431 // AHHHHHHHHH.
4432 }
4433#endif
4434}
4435
4436int CMinecraftApp::PrimaryPlayerSignedOutReturned(void *pParam,int iPad,const C4JStorage::EMessageResult)
4437{
4438 //CMinecraftApp* pApp = (CMinecraftApp*)pParam;
4439 //Minecraft *pMinecraft=Minecraft::GetInstance();
4440
4441 // if the player is null, we're in the menus
4442 //if(Minecraft::GetInstance()->player!=NULL)
4443
4444 // We always create a session before kicking of any of the game code, so even though we may still be joining/creating a game
4445 // at this point we want to handle it differently from just being in a menu
4446 if( g_NetworkManager.IsInSession() )
4447 {
4448 app.SetAction(iPad,eAppAction_PrimaryPlayerSignedOutReturned);
4449 }
4450 else
4451 {
4452 app.SetAction(iPad,eAppAction_PrimaryPlayerSignedOutReturned_Menus);
4453 }
4454 return 0;
4455}
4456
4457int CMinecraftApp::EthernetDisconnectReturned(void *pParam,int iPad,const C4JStorage::EMessageResult)
4458{
4459 //CMinecraftApp* pApp = (CMinecraftApp*)pParam;
4460 Minecraft *pMinecraft=Minecraft::GetInstance();
4461
4462 // if the player is null, we're in the menus
4463 if(Minecraft::GetInstance()->player!=NULL)
4464 {
4465 app.SetAction(pMinecraft->player->GetXboxPad(),eAppAction_EthernetDisconnectedReturned);
4466 }
4467 else
4468 {
4469 // 4J-PB - turn off the PSN store icon just in case this happened when we were in one of the DLC menus
4470#if defined __ORBIS__ || defined __PSVITA__
4471 app.GetCommerce()->HidePsStoreIcon();
4472#endif
4473 app.SetAction(iPad,eAppAction_EthernetDisconnectedReturned_Menus);
4474 }
4475 return 0;
4476}
4477
4478int CMinecraftApp::SignoutExitWorldThreadProc( void* lpParameter )
4479{
4480
4481 // 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
4482 AABB::UseDefaultThreadStorage();
4483 Vec3::UseDefaultThreadStorage();
4484 Compression::UseDefaultThreadStorage();
4485
4486 //app.SetGameStarted(false);
4487
4488 Minecraft *pMinecraft=Minecraft::GetInstance();
4489
4490 int exitReasonStringId = -1;
4491
4492 bool saveStats = false;
4493 if (pMinecraft->isClientSide() || g_NetworkManager.IsInSession() )
4494 {
4495 if(lpParameter != NULL )
4496 {
4497 switch( app.GetDisconnectReason() )
4498 {
4499 case DisconnectPacket::eDisconnect_Kicked:
4500 exitReasonStringId = IDS_DISCONNECTED_KICKED;
4501 break;
4502 case DisconnectPacket::eDisconnect_NoUGC_AllLocal:
4503 exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL;
4504 break;
4505 case DisconnectPacket::eDisconnect_NoUGC_Single_Local:
4506 exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL;
4507 break;
4508#ifdef _XBOX
4509 case DisconnectPacket::eDisconnect_NoUGC_Remote:
4510 exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_REMOTE;
4511 break;
4512#endif
4513 case DisconnectPacket::eDisconnect_NoFlying:
4514 exitReasonStringId = IDS_DISCONNECTED_FLYING;
4515 break;
4516 case DisconnectPacket::eDisconnect_OutdatedServer:
4517 exitReasonStringId = IDS_DISCONNECTED_SERVER_OLD;
4518 break;
4519 case DisconnectPacket::eDisconnect_OutdatedClient:
4520 exitReasonStringId = IDS_DISCONNECTED_CLIENT_OLD;
4521 break;
4522 default:
4523 exitReasonStringId = IDS_DISCONNECTED;
4524 }
4525 pMinecraft->progressRenderer->progressStartNoAbort( exitReasonStringId );
4526 // 4J - Force a disconnection, this handles the situation that the server has already disconnected
4527 if( pMinecraft->levels[0] != NULL ) pMinecraft->levels[0]->disconnect(false);
4528 if( pMinecraft->levels[1] != NULL ) pMinecraft->levels[1]->disconnect(false);
4529 }
4530 else
4531 {
4532 exitReasonStringId = IDS_EXITING_GAME;
4533 pMinecraft->progressRenderer->progressStartNoAbort( IDS_EXITING_GAME );
4534
4535 if( pMinecraft->levels[0] != NULL ) pMinecraft->levels[0]->disconnect();
4536 if( pMinecraft->levels[1] != NULL ) pMinecraft->levels[1]->disconnect();
4537 }
4538
4539 // 4J Stu - This only does something if we actually have a server, so don't need to do any other checks
4540 MinecraftServer::HaltServer(true);
4541
4542 // We need to call the stats & leaderboards save before we exit the session
4543 //pMinecraft->forceStatsSave();
4544 saveStats = false;
4545
4546 // 4J Stu - Leave the session once the disconnect packet has been sent
4547 g_NetworkManager.LeaveGame(FALSE);
4548 }
4549 else
4550 {
4551 if(lpParameter != NULL )
4552 {
4553 switch( app.GetDisconnectReason() )
4554 {
4555 case DisconnectPacket::eDisconnect_Kicked:
4556 exitReasonStringId = IDS_DISCONNECTED_KICKED;
4557 break;
4558 case DisconnectPacket::eDisconnect_NoUGC_AllLocal:
4559 exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL;
4560 break;
4561 case DisconnectPacket::eDisconnect_NoUGC_Single_Local:
4562 exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL;
4563 break;
4564#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__)
4565 case DisconnectPacket::eDisconnect_ContentRestricted_AllLocal:
4566 exitReasonStringId = IDS_CONTENT_RESTRICTION_MULTIPLAYER;
4567 break;
4568 case DisconnectPacket::eDisconnect_ContentRestricted_Single_Local:
4569 exitReasonStringId = IDS_CONTENT_RESTRICTION;
4570 break;
4571#endif
4572#ifdef _XBOX
4573 case DisconnectPacket::eDisconnect_NoUGC_Remote:
4574 exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_REMOTE;
4575 break;
4576#endif
4577 case DisconnectPacket::eDisconnect_OutdatedServer:
4578 exitReasonStringId = IDS_DISCONNECTED_SERVER_OLD;
4579 break;
4580 case DisconnectPacket::eDisconnect_OutdatedClient:
4581 exitReasonStringId = IDS_DISCONNECTED_CLIENT_OLD;
4582 default:
4583 exitReasonStringId = IDS_DISCONNECTED;
4584 }
4585 pMinecraft->progressRenderer->progressStartNoAbort( exitReasonStringId );
4586 }
4587 }
4588 pMinecraft->setLevel(NULL,exitReasonStringId,nullptr,saveStats,true);
4589
4590 // 4J-JEV: Fix for #106402 - TCR #014 BAS Debug Output:
4591 // TU12: Mass Effect Mash-UP: Save file "Default_DisplayName" is created on all storage devices after signing out from a re-launched pre-generated world
4592 app.m_gameRules.unloadCurrentGameRules(); //
4593
4594 MinecraftServer::resetFlags();
4595
4596 // We can't start/join a new game until the session is destroyed, so wait for it to be idle again
4597 while( g_NetworkManager.IsInSession() )
4598 {
4599 Sleep(1);
4600 }
4601
4602 return S_OK;
4603}
4604
4605int CMinecraftApp::UnlockFullInviteReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
4606{
4607 //CMinecraftApp* pApp = (CMinecraftApp*)pParam;
4608 Minecraft *pMinecraft=Minecraft::GetInstance();
4609 bool bNoPlayer;
4610
4611 // bug 11285 - TCR 001: BAS Game Stability: CRASH - When trying to join a full version game with a trial version, the trial crashes
4612 // 4J-PB - we may be in the main menus here, and we don't have a pMinecraft->player
4613
4614 if(pMinecraft->player==NULL)
4615 {
4616 bNoPlayer=true;
4617 }
4618
4619 if(result==C4JStorage::EMessage_ResultAccept)
4620 {
4621 if(ProfileManager.IsSignedInLive(iPad))
4622 {
4623 // 4J-PB - need to check this user can access the store
4624#if defined(__PS3__) || defined(__PSVITA__)
4625 bool bContentRestricted;
4626 ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,NULL,&bContentRestricted,NULL);
4627 if(bContentRestricted)
4628 {
4629 UINT uiIDA[1];
4630 uiIDA[0]=IDS_CONFIRM_OK;
4631 ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad());
4632 }
4633 else
4634#endif
4635 {
4636 ProfileManager.DisplayFullVersionPurchase(false,iPad,eSen_UpsellID_Full_Version_Of_Game);
4637 }
4638 }
4639#if defined(__PS3__)
4640 else
4641 {
4642 // you're not signed in to PSN!
4643 UINT uiIDA[2];
4644 uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT;
4645 uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE;
4646 ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app);
4647
4648 }
4649#endif
4650 }
4651 else
4652 {
4653 TelemetryManager->RecordUpsellResponded(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, eSen_UpsellOutcome_Declined);
4654 }
4655
4656 return 0;
4657}
4658
4659int CMinecraftApp::UnlockFullSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
4660{
4661 //CMinecraftApp* pApp = (CMinecraftApp*)pParam;
4662 Minecraft *pMinecraft=Minecraft::GetInstance();
4663
4664 if(result==C4JStorage::EMessage_ResultAccept)
4665 {
4666 if(ProfileManager.IsSignedInLive(pMinecraft->player->GetXboxPad()))
4667 {
4668 // 4J-PB - need to check this user can access the store
4669#if defined(__PS3__) || defined(__PSVITA__)
4670 bool bContentRestricted;
4671 ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,NULL,&bContentRestricted,NULL);
4672 if(bContentRestricted)
4673 {
4674 UINT uiIDA[1];
4675 uiIDA[0]=IDS_CONFIRM_OK;
4676 ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad());
4677 }
4678 else
4679#endif
4680 {
4681 ProfileManager.DisplayFullVersionPurchase(false,pMinecraft->player->GetXboxPad(),eSen_UpsellID_Full_Version_Of_Game);
4682 }
4683 }
4684#if defined(__PS3__)
4685 else
4686 {
4687 // you're not signed in to PSN!
4688 UINT uiIDA[2];
4689 uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT;
4690 uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE;
4691 ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app);
4692 }
4693#elif defined(__ORBIS__)
4694 else
4695 {
4696 // Determine why they're not "signed in live"
4697 if (ProfileManager.isSignedInPSN(iPad))
4698 {
4699 // Signed in to PSN but not connected (no internet access)
4700 assert(!ProfileManager.isConnectedToPSN(iPad));
4701
4702 UINT uiIDA[1];
4703 uiIDA[0] = IDS_OK;
4704 ui.RequestErrorMessage( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad);
4705 }
4706 else
4707 {
4708 // Not signed in to PSN
4709 UINT uiIDA[1];
4710 uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT;
4711 ui.RequestAlertMessage( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, iPad, &CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app);
4712 }
4713 }
4714#endif
4715 }
4716 else
4717 {
4718 TelemetryManager->RecordUpsellResponded(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, eSen_UpsellOutcome_Declined);
4719 }
4720
4721 return 0;
4722}
4723
4724int CMinecraftApp::UnlockFullExitReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
4725{
4726 CMinecraftApp* pApp = (CMinecraftApp*)pParam;
4727 Minecraft *pMinecraft=Minecraft::GetInstance();
4728
4729 if(result==C4JStorage::EMessage_ResultAccept)
4730 {
4731 if(ProfileManager.IsSignedInLive(pMinecraft->player->GetXboxPad()))
4732 {
4733 // 4J-PB - need to check this user can access the store
4734#if defined(__PS3__) || defined(__PSVITA__)
4735 bool bContentRestricted;
4736 ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,NULL,&bContentRestricted,NULL);
4737 if(bContentRestricted)
4738 {
4739 UINT uiIDA[1];
4740 uiIDA[0]=IDS_CONFIRM_OK;
4741 ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad());
4742 }
4743 else
4744#endif
4745 {
4746 ProfileManager.DisplayFullVersionPurchase(false,pMinecraft->player->GetXboxPad(),eSen_UpsellID_Full_Version_Of_Game);
4747#if defined __ORBIS__ || defined __PS3__ || defined __PSVITA__
4748 // still need to exit the trial or we'll be in the Pause menu with input ignored
4749 pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial);
4750#endif
4751 }
4752 }
4753#if defined(__PS3__) || defined __PSVITA__
4754 else
4755 {
4756 // you're not signed in to PSN!
4757 UINT uiIDA[2];
4758 uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT;
4759 uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE;
4760 ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturnedExitTrial,&app);
4761 }
4762#elif defined(__ORBIS__)
4763 else
4764 {
4765 // Determine why they're not "signed in live"
4766 if (ProfileManager.isSignedInPSN(iPad))
4767 {
4768 // Signed in to PSN but not connected (no internet access)
4769 assert(!ProfileManager.isConnectedToPSN(iPad));
4770
4771 UINT uiIDA[1];
4772 uiIDA[0] = IDS_OK;
4773 ui.RequestErrorMessage( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad);
4774 // still need to exit the trial or we'll be in the Pause menu with input ignored
4775 pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial);
4776 }
4777 else
4778 {
4779 // Not signed in to PSN
4780 UINT uiIDA[1];
4781 uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT;
4782 ui.RequestAlertMessage( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, iPad, &CMinecraftApp::MustSignInFullVersionPurchaseReturnedExitTrial,&app);
4783 }
4784 }
4785#endif
4786 }
4787 else
4788 {
4789 TelemetryManager->RecordUpsellResponded(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, eSen_UpsellOutcome_Declined);
4790 pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial);
4791 }
4792
4793 return 0;
4794}
4795
4796int CMinecraftApp::TrialOverReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
4797{
4798 CMinecraftApp* pApp = (CMinecraftApp*)pParam;
4799 Minecraft *pMinecraft=Minecraft::GetInstance();
4800
4801 if(result==C4JStorage::EMessage_ResultAccept)
4802 {
4803 // we need a signed in user for the unlock
4804 if(ProfileManager.IsSignedInLive(pMinecraft->player->GetXboxPad()))
4805 {
4806 // 4J-PB - need to check this user can access the store
4807#if defined(__PS3__) || defined(__PSVITA__)
4808 bool bContentRestricted;
4809 ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,NULL,&bContentRestricted,NULL);
4810 if(bContentRestricted)
4811 {
4812 UINT uiIDA[1];
4813 uiIDA[0]=IDS_CONFIRM_OK;
4814 ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad());
4815 }
4816 else
4817#endif
4818 {
4819 ProfileManager.DisplayFullVersionPurchase(false,pMinecraft->player->GetXboxPad(),eSen_UpsellID_Full_Version_Of_Game);
4820 }
4821 }
4822 else
4823 {
4824#if defined(__PS3__)
4825
4826 // you're not signed in to PSN!
4827 UINT uiIDA[2];
4828 uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT;
4829 uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE;
4830 ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app);
4831
4832 // 4J Stu - We can't actually exit the game, so just exit back to the main menu
4833 //pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial);
4834#else
4835 pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitTrial);
4836#endif
4837 }
4838 }
4839 else
4840 {
4841 TelemetryManager->RecordUpsellResponded(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, eSen_UpsellOutcome_Declined);
4842
4843#if defined(__PS3__) || defined(__ORBIS__)
4844 // 4J Stu - We can't actually exit the game, so just exit back to the main menu
4845 pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial);
4846#else
4847 pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitTrial);
4848#endif
4849 }
4850
4851 return 0;
4852}
4853
4854void CMinecraftApp::ProfileReadErrorCallback(void *pParam)
4855{
4856 CMinecraftApp *pApp=(CMinecraftApp *)pParam;
4857 int iPrimaryPlayer=ProfileManager.GetPrimaryPad();
4858 pApp->SetAction(iPrimaryPlayer, eAppAction_ProfileReadError);
4859}
4860
4861void CMinecraftApp::ClearSignInChangeUsersMask()
4862{
4863 // 4J-PB - When in the main menu, the user is on pad 0, and any change they make to their profile will be to pad 0 data
4864 // If they then go in as a secondary player to a splitscreen game, their profile will not be read again on pad 1 if they were previously in a splitscreen game
4865 // This is because m_uiLastSignInData remembers they were in previously, and doesn't read the profile data for them again
4866 // Fix this by resetting the m_uiLastSignInData on pressing play game for secondary users. The Primary user does a read profile on play game anyway
4867 int iPrimaryPlayer=ProfileManager.GetPrimaryPad();
4868
4869 if(m_uiLastSignInData!=0)
4870 {
4871 if(iPrimaryPlayer>=0)
4872 {
4873 m_uiLastSignInData=1<<iPrimaryPlayer;
4874 }
4875 else
4876 {
4877 m_uiLastSignInData=0;
4878 }
4879 }
4880}
4881void CMinecraftApp::SignInChangeCallback(LPVOID pParam,bool bPrimaryPlayerChanged,unsigned int uiSignInData)
4882{
4883#ifdef __PS3__
4884 // this is normally set in the main menu, but we can go online in the create world screens, and the primary player name isn't updated
4885 Minecraft::GetInstance()->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad()));
4886#endif
4887
4888 CMinecraftApp *pApp=(CMinecraftApp *)pParam;
4889 // check if the primary player signed out
4890 int iPrimaryPlayer=ProfileManager.GetPrimaryPad();
4891
4892 if((ProfileManager.GetLockedProfile()!=-1) && iPrimaryPlayer!=-1)
4893 {
4894 if ( ((uiSignInData & (1<<iPrimaryPlayer)) == 0) || bPrimaryPlayerChanged )
4895 {
4896 // Primary Player gone or there's been a sign out and sign in of the primary player, so kick them out
4897 pApp->SetAction(iPrimaryPlayer,eAppAction_PrimaryPlayerSignedOut);
4898
4899 // 4J-PB - invalidate their banned level list
4900 pApp->InvalidateBannedList(iPrimaryPlayer);
4901
4902 // need to ditch any DLCOffers info
4903 StorageManager.ClearDLCOffers();
4904 pApp->ClearAndResetDLCDownloadQueue();
4905 pApp->ClearDLCInstalled();
4906 }
4907 else
4908 {
4909 unsigned int uiChangedPlayers = uiSignInData ^ m_uiLastSignInData;
4910
4911 if( g_NetworkManager.IsInSession() )
4912 {
4913 bool hasGuestIdChanged = false;
4914 for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
4915 {
4916 DWORD guestNumber = 0;
4917 if(ProfileManager.IsSignedIn(i))
4918 {
4919 XUSER_SIGNIN_INFO info;
4920 XUserGetSigninInfo(i,XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY ,&info);
4921 pApp->DebugPrintf("Player at index %d has guest number %d\n", i,info.dwGuestNumber );
4922 guestNumber = info.dwGuestNumber;
4923 }
4924 if( pApp->m_currentSigninInfo[i].dwGuestNumber != 0 && guestNumber != 0 && pApp->m_currentSigninInfo[i].dwGuestNumber != guestNumber )
4925 {
4926 hasGuestIdChanged = true;
4927 }
4928 }
4929
4930 if( hasGuestIdChanged )
4931 {
4932 UINT uiIDA[1];
4933 uiIDA[0]=IDS_CONFIRM_OK;
4934 ui.RequestErrorMessage(IDS_GUEST_ORDER_CHANGED_TITLE, IDS_GUEST_ORDER_CHANGED_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad());
4935 }
4936
4937 // 4J Stu - On PS4 we can also cause to exit players if they are signed out here, but we shouldn't do that if
4938 // we are going to switch to an offline game as it will likely crash due to incompatible parallel processes
4939 bool switchToOffline = false;
4940 // If it's an online game, and the primary profile is no longer signed into LIVE then we act as if disconnected
4941 if( !ProfileManager.IsSignedInLive( ProfileManager.GetLockedProfile() ) && !g_NetworkManager.IsLocalGame() )
4942 {
4943 switchToOffline = true;
4944 }
4945
4946 //printf("Old: %x, New: %x, Changed: %x\n", m_ulLastSignInData, ulSignInData, changedPlayers);
4947 for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
4948 {
4949 // Primary player shouldn't be subjected to these checks, and shouldn't call ExitPlayer
4950 if(i == iPrimaryPlayer) continue;
4951
4952 // A guest a signed in or out, out of order which invalidates all the guest players we have in the game
4953 if(hasGuestIdChanged && pApp->m_currentSigninInfo[i].dwGuestNumber != 0 && g_NetworkManager.GetLocalPlayerByUserIndex(i)!=NULL)
4954 {
4955 pApp->DebugPrintf("Recommending removal of player at index %d because their guest id changed\n",i);
4956 pApp->SetAction(i, eAppAction_ExitPlayer);
4957 }
4958 else
4959 {
4960 XUSER_SIGNIN_INFO info;
4961 XUserGetSigninInfo(i,XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY ,&info);
4962 // 4J Stu - Also need to detect the case where the sign in mask is the same, but the player has swapped users (eg still signed in but xuid different)
4963 // Fix for #48451 - TU5: Code: UI: Splitscreen: Title crashes when switching to a profile previously signed out via splitscreen profile selection
4964
4965 // 4J-PB - compiler complained about if below ('&&' within '||') - making it easier to read
4966 bool bPlayerChanged=(uiChangedPlayers&(1<<i))==(1<<i);
4967 bool bPlayerSignedIn=((uiSignInData&(1<<i))!=0);
4968
4969 if( bPlayerChanged && (!bPlayerSignedIn || (bPlayerSignedIn && !ProfileManager.AreXUIDSEqual(pApp->m_currentSigninInfo[i].xuid, info.xuid) ) ))
4970 {
4971 // 4J-PB - invalidate their banned level list
4972 pApp->DebugPrintf("Player at index %d Left - invalidating their banned list\n",i);
4973 pApp->InvalidateBannedList(i);
4974
4975 // 4J-HG: If either the player is in the network manager or in the game, need to exit player
4976 // TODO: Do we need to check the network manager?
4977 if (g_NetworkManager.GetLocalPlayerByUserIndex(i) != NULL || Minecraft::GetInstance()->localplayers[i] != NULL)
4978 {
4979 pApp->DebugPrintf("Player %d signed out\n", i);
4980 pApp->SetAction(i, eAppAction_ExitPlayer);
4981 }
4982 }
4983 }
4984#ifdef __ORBIS__
4985 // check if any of the addition players have signed out of PSN (primary player is handled below)
4986 if(!switchToOffline && i != ProfileManager.GetLockedProfile() && !g_NetworkManager.IsLocalGame())
4987 {
4988 if(g_NetworkManager.GetLocalPlayerByUserIndex(i)!=NULL)
4989 {
4990 if(ProfileManager.IsSignedInLive(i) == false)
4991 {
4992 pApp->DebugPrintf("Recommending removal of player at index %d because they're no longer signed into PSNd\n",i);
4993 pApp->SetAction(i,eAppAction_ExitPlayer);
4994 }
4995 }
4996 }
4997#endif
4998 }
4999
5000 // If it's an online game, and the primary profile is no longer signed into LIVE then we act as if disconnected
5001 if( switchToOffline )
5002 {
5003 pApp->SetAction(iPrimaryPlayer,eAppAction_EthernetDisconnected);
5004 }
5005
5006
5007 g_NetworkManager.HandleSignInChange();
5008 }
5009 // Some menus require the player to be signed in to live, so if this callback happens and the primary player is
5010 // no longer signed in then nav back
5011 else if ( pApp->GetLiveLinkRequired() && !ProfileManager.IsSignedInLive( ProfileManager.GetLockedProfile() ) )
5012 {
5013#ifdef __PSVITA__
5014 if(!CGameNetworkManager::usingAdhocMode()) // if we're in adhoc mode, we can ignore this
5015#endif
5016 {
5017 pApp->SetAction(iPrimaryPlayer,eAppAction_EthernetDisconnected);
5018 }
5019 }
5020
5021#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__ )
5022 // 4J-JEV: Need to kick of loading of profile data for sub-sign in players.
5023 for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
5024 {
5025 if( i != iPrimaryPlayer
5026 && ( uiChangedPlayers & (1<<i) )
5027 && ( uiSignInData & (1<<i) )
5028 )
5029 {
5030 StorageManager.ReadFromProfile(i);
5031 }
5032 }
5033#endif
5034 }
5035 m_uiLastSignInData = uiSignInData;
5036 }
5037 else if(iPrimaryPlayer!=-1)
5038 {
5039 // make sure the TMS banned list data is ditched - the player may have gone in to help & options, backed out, and signed out
5040 pApp->InvalidateBannedList(iPrimaryPlayer);
5041
5042 // need to ditch any DLCOffers info
5043 StorageManager.ClearDLCOffers();
5044 pApp->ClearAndResetDLCDownloadQueue();
5045 pApp->ClearDLCInstalled();
5046
5047 }
5048
5049 // Update the guest numbers to the current state
5050 for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
5051 {
5052 if(FAILED(XUserGetSigninInfo(i,XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY,&pApp->m_currentSigninInfo[i])))
5053 {
5054 pApp->m_currentSigninInfo[i].xuid = INVALID_XUID;
5055 pApp->m_currentSigninInfo[i].dwGuestNumber = 0;
5056 }
5057 app.DebugPrintf("Player at index %d has guest number %d\n", i,pApp->m_currentSigninInfo[i].dwGuestNumber );
5058 }
5059}
5060
5061void CMinecraftApp::NotificationsCallback(LPVOID pParam,DWORD dwNotification, unsigned int uiParam)
5062{
5063 CMinecraftApp* pClass = (CMinecraftApp*)pParam;
5064
5065 // push these on to the notifications to be handled in qnet's dowork
5066
5067 PNOTIFICATION pNotification = new NOTIFICATION;
5068
5069 pNotification->dwNotification=dwNotification;
5070 pNotification->uiParam=uiParam;
5071
5072 switch( dwNotification )
5073 {
5074 case XN_SYS_SIGNINCHANGED:
5075 {
5076 pClass->DebugPrintf("Signing changed - %d\n", uiParam );
5077 }
5078 break;
5079 case XN_SYS_INPUTDEVICESCHANGED:
5080 if(app.GetGameStarted() && g_NetworkManager.IsInSession())
5081 {
5082 for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
5083 {
5084 if(!InputManager.IsPadConnected(i) &&
5085 Minecraft::GetInstance()->localplayers[i] != NULL &&
5086 !ui.IsPauseMenuDisplayed(i) && !ui.IsSceneInStack(i, eUIScene_EndPoem) )
5087 {
5088 ui.CloseUIScenes(i);
5089 ui.NavigateToScene(i,eUIScene_PauseMenu);
5090 }
5091 }
5092 }
5093 break;
5094 case XN_LIVE_CONTENT_INSTALLED:
5095 // Need to inform xuis that we've possibly had DLC installed
5096 {
5097 //app.m_dlcManager.SetNeedsUpdated(true);
5098 // Clear the DLC installed flag to cause a GetDLC to run if it's called
5099 app.ClearDLCInstalled();
5100
5101 ui.HandleDLCInstalled(ProfileManager.GetPrimaryPad());
5102 }
5103 break;
5104 case XN_SYS_STORAGEDEVICESCHANGED:
5105 {
5106#ifdef _XBOX
5107 // If the devices have changed, and we've got a dlc pack with audio selected, and that pack's content device is no longer valid... then pull the plug on
5108 // audio streaming, as if we leave this until later xact gets locked up attempting to destroy the streamed wave bank.
5109 TexturePack *pTexPack=Minecraft::GetInstance()->skins->getSelected();
5110 if(pTexPack->hasAudio())
5111 {
5112 DLCTexturePack *pDLCTexPack=(DLCTexturePack *)pTexPack;
5113 XCONTENTDEVICEID deviceID = pDLCTexPack->GetDLCDeviceID();
5114 if( XContentGetDeviceState( deviceID, NULL ) != ERROR_SUCCESS )
5115 {
5116 // Set texture pack flag so that it is now considered as not having audio - this is critical so that the next playStreaming does what it is meant to do,
5117 // and also so that we don't try and unmount this again, or play any sounds from it in the future
5118 pTexPack->setHasAudio(false);
5119 // need to stop the streaming audio - by playing streaming audio from the default texture pack now
5120 Minecraft::GetInstance()->soundEngine->playStreaming(L"", 0, 0, 0, 0, 0);
5121
5122 if(pDLCTexPack->m_pStreamedWaveBank!=NULL)
5123 {
5124 pDLCTexPack->m_pStreamedWaveBank->Destroy();
5125 }
5126 if(pDLCTexPack->m_pSoundBank!=NULL)
5127 {
5128 pDLCTexPack->m_pSoundBank->Destroy();
5129 }
5130 DWORD result = StorageManager.UnmountInstalledDLC("TPACK");
5131 app.DebugPrintf("Unmount result is %d\n",result);
5132 }
5133 }
5134#endif
5135 }
5136 break;
5137 }
5138
5139 pClass->m_vNotifications.push_back(pNotification);
5140}
5141
5142#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__
5143int CMinecraftApp::MustSignInFullVersionPurchaseReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
5144{
5145 if(result==C4JStorage::EMessage_ResultAccept)
5146 {
5147#ifdef __PS3__
5148 SQRNetworkManager_PS3::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true);
5149#elif defined __PSVITA__
5150 SQRNetworkManager_Vita::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true);
5151#else // __PS4__
5152 SQRNetworkManager_Orbis::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true);
5153#endif
5154 }
5155
5156 return 0;
5157}
5158
5159#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__
5160int CMinecraftApp::MustSignInFullVersionPurchaseReturnedExitTrial(void *pParam,int iPad,C4JStorage::EMessageResult result)
5161{
5162 if(result==C4JStorage::EMessage_ResultAccept)
5163 {
5164#ifdef __PS3__
5165 SQRNetworkManager_PS3::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true);
5166#elif defined __PSVITA__
5167 SQRNetworkManager_Vita::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true);
5168#else // __PS4__
5169 SQRNetworkManager_Orbis::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true);
5170#endif
5171 }
5172
5173 //4J-PB - we need to exit the trial, or we'll be in the pause menu with ignore input true
5174 app.SetAction(iPad,eAppAction_ExitWorldTrial);
5175
5176 return 0;
5177}
5178#endif
5179
5180int CMinecraftApp::NowDisplayFullVersionPurchase(void *pParam, bool bContinue, int iPad)
5181{
5182 app.m_bDisplayFullVersionPurchase=true;
5183 return 0;
5184}
5185#endif
5186void CMinecraftApp::UpsellReturnedCallback(LPVOID pParam, eUpsellType type, eUpsellResponse result, int iUserData)
5187{
5188 ESen_UpsellID senType;
5189 ESen_UpsellOutcome senResponse;
5190#ifdef __PS3__
5191 UINT uiIDA[2];
5192#endif
5193
5194 // Map the eUpsellResponse to the enum we use for sentient
5195 switch(result)
5196 {
5197 case eUpsellResponse_Accepted_NoPurchase:
5198 senResponse = eSen_UpsellOutcome_Went_To_Guide;
5199 break;
5200 case eUpsellResponse_Accepted_Purchase:
5201 senResponse = eSen_UpsellOutcome_Accepted;
5202 break;
5203#ifdef __PS3__
5204 // special case for people who are not signed in to the PSN while playing the trial game
5205 case eUpsellResponse_UserNotSignedInPSN:
5206
5207 uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT;
5208 uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE;
5209 ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app);
5210
5211 return;
5212
5213 case eUpsellResponse_NotAllowedOnline: // On earning a trophy in the trial version, where the user is underage and can't go online to buy the game, but they selected to buy the game on the trophy upsell
5214 uiIDA[0]=IDS_CONFIRM_OK;
5215 ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad());
5216 break;
5217#endif
5218 case eUpsellResponse_Declined:
5219 default:
5220 senResponse = eSen_UpsellOutcome_Declined;
5221 break;
5222 };
5223
5224 // Map the eUpsellType to the enum we use for sentient
5225 switch(type)
5226 {
5227 case eUpsellType_Custom:
5228 senType = eSen_UpsellID_Full_Version_Of_Game;
5229 break;
5230 default:
5231 senType = eSen_UpsellID_Undefined;
5232 break;
5233 };
5234
5235 // Always the primary pad that gets an upsell
5236 TelemetryManager->RecordUpsellResponded(ProfileManager.GetPrimaryPad(), eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, senResponse);
5237}
5238
5239#ifdef _DEBUG_MENUS_ENABLED
5240bool CMinecraftApp::DebugArtToolsOn()
5241{
5242 return DebugSettingsOn() && (GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_ArtTools)) != 0;
5243}
5244#endif
5245
5246void CMinecraftApp::SetDebugSequence(const char *pchSeq)
5247{
5248 InputManager.SetDebugSequence(pchSeq,&CMinecraftApp::DebugInputCallback,this);
5249}
5250int CMinecraftApp::DebugInputCallback(LPVOID pParam)
5251{
5252 CMinecraftApp* pClass = (CMinecraftApp*)pParam;
5253 //printf("sequence matched\n");
5254 pClass->m_bDebugOptions=!pClass->m_bDebugOptions;
5255
5256 for(int i=0;i<XUSER_MAX_COUNT;i++)
5257 {
5258 if(app.DebugSettingsOn())
5259 {
5260 app.ActionDebugMask(i);
5261 }
5262 else
5263 {
5264 // force debug mask off
5265 app.ActionDebugMask(i,true);
5266 }
5267 }
5268
5269 return 0;
5270}
5271
5272int CMinecraftApp::GetLocalPlayerCount(void)
5273{
5274 int iPlayerC=0;
5275 Minecraft *pMinecraft = Minecraft::GetInstance();
5276 for(int i=0;i<XUSER_MAX_COUNT;i++)
5277 {
5278 if(pMinecraft != NULL && pMinecraft->localplayers[i] != NULL)
5279 {
5280 iPlayerC++;
5281 }
5282 }
5283
5284 return iPlayerC;
5285}
5286
5287int CMinecraftApp::MarketplaceCountsCallback(LPVOID pParam,C4JStorage::DLC_TMS_DETAILS *pTMSDetails, int iPad)
5288{
5289 app.DebugPrintf("Marketplace Counts= New - %d Total - %d\n",pTMSDetails->dwNewOffers,pTMSDetails->dwTotalOffers);
5290
5291 if(pTMSDetails->dwNewOffers>0)
5292 {
5293 app.m_bNewDLCAvailable=true;
5294 app.m_bSeenNewDLCTip=false;
5295 }
5296 else
5297 {
5298 app.m_bNewDLCAvailable=false;
5299 app.m_bSeenNewDLCTip=true;
5300 }
5301
5302 return 0;
5303}
5304
5305bool CMinecraftApp::StartInstallDLCProcess(int iPad)
5306{
5307 app.DebugPrintf("--- CMinecraftApp::StartInstallDLCProcess: pad=%i.\n", iPad);
5308
5309 // If there is already a call to this in progress, then do nothing
5310 // If the app says dlc is installed, then there has been no new system message to tell us there's new DLC since the last call to StartInstallDLCProcess
5311 if((app.DLCInstallProcessCompleted()==false) && (m_bDLCInstallPending==false))
5312 {
5313 app.m_dlcManager.resetUnnamedCorruptCount();
5314 m_bDLCInstallPending = true;
5315 m_iTotalDLC = 0;
5316 m_iTotalDLCInstalled = 0;
5317 app.DebugPrintf("--- CMinecraftApp::StartInstallDLCProcess - StorageManager.GetInstalledDLC\n");
5318
5319 StorageManager.GetInstalledDLC(iPad,&CMinecraftApp::DLCInstalledCallback,this);
5320 return true;
5321 }
5322 else
5323 {
5324 app.DebugPrintf("--- CMinecraftApp::StartInstallDLCProcess - nothing to do\n");
5325
5326 return false;
5327 }
5328
5329}
5330
5331// Installed DLC callback
5332int CMinecraftApp::DLCInstalledCallback(LPVOID pParam,int iInstalledC,int iPad)
5333{
5334 app.DebugPrintf("--- CMinecraftApp::DLCInstalledCallback: totalDLC=%i, pad=%i.\n", iInstalledC, iPad);
5335 app.m_iTotalDLC = iInstalledC;
5336 app.MountNextDLC(iPad);
5337 return 0;
5338}
5339
5340void CMinecraftApp::MountNextDLC(int iPad)
5341{
5342 app.DebugPrintf("--- CMinecraftApp::MountNextDLC: pad=%i.\n", iPad);
5343 if(m_iTotalDLCInstalled < m_iTotalDLC)
5344 {
5345 // Mount it
5346 // We also need to match the ones the user wants to mount with the installed DLC
5347 // We're supposed to use a generic save game as a cache of these to do this, with XUSER_ANY
5348
5349 if(StorageManager.MountInstalledDLC(iPad,m_iTotalDLCInstalled,&CMinecraftApp::DLCMountedCallback,this)!=ERROR_IO_PENDING )
5350 {
5351 // corrupt DLC
5352 app.DebugPrintf("Failed to mount DLC %d for pad %d\n",m_iTotalDLCInstalled,iPad);
5353 ++m_iTotalDLCInstalled;
5354 app.MountNextDLC(iPad);
5355 }
5356 else
5357 {
5358 app.DebugPrintf("StorageManager.MountInstalledDLC ok\n");
5359 }
5360 }
5361 else
5362 {
5363 /* Removed - now loading these on demand instead of as each pack is mounted
5364 if(m_iTotalDLCInstalled > 0)
5365 {
5366 Minecraft *pMinecraft=Minecraft::GetInstance();
5367 pMinecraft->levelRenderer->AddDLCSkinsToMemTextures();
5368 }
5369 */
5370
5371 m_bDLCInstallPending = false;
5372 m_bDLCInstallProcessCompleted=true;
5373
5374 ui.HandleDLCMountingComplete();
5375
5376#if defined(_XBOX_ONE) || defined(__ORBIS__)
5377 // Check if the current texture pack is now installed
5378 if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin())
5379 {
5380 TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected();
5381 DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack;
5382
5383 DLCPack *pParentPack=pDLCTexPack->getDLCInfoParentPack();//tPack->getDLCPack();
5384
5385 if(pParentPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" ))
5386 {
5387 StorageManager.SetSaveDisabled(false);
5388 }
5389 }
5390#endif
5391#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__
5392 {
5393 TexturePack* currentTPack = Minecraft::GetInstance()->skins->getSelected();
5394 TexturePack* requiredTPack = Minecraft::GetInstance()->skins->getTexturePackById(app.GetRequiredTexturePackID());
5395 if(currentTPack != requiredTPack)
5396 {
5397 Minecraft::GetInstance()->skins->selectTexturePackById(app.GetRequiredTexturePackID());
5398 }
5399 }
5400#endif
5401 }
5402}
5403
5404// 4J-JEV: For the sake of clarity in DLCMountedCallback.
5405#if defined(_XBOX) || defined(__PS3__) || defined(_WINDOWS64)
5406#define CONTENT_DATA_DISPLAY_NAME(a) (a.szDisplayName)
5407#else
5408#define CONTENT_DATA_DISPLAY_NAME(a) (a.wszDisplayName)
5409#endif
5410
5411int CMinecraftApp::DLCMountedCallback(LPVOID pParam,int iPad,DWORD dwErr,DWORD dwLicenceMask)
5412{
5413#if defined(_XBOX) || defined(_DURANGO) || defined(__PS3__) || defined(__ORBIS__) || defined(_WINDOWS64) || defined (__PSVITA__) //Chris TODO
5414 app.DebugPrintf("--- CMinecraftApp::DLCMountedCallback\n");
5415
5416 if(dwErr!=ERROR_SUCCESS)
5417 {
5418 // corrupt DLC
5419 app.DebugPrintf("Failed to mount DLC for pad %d: %d\n",iPad,dwErr);
5420 app.m_dlcManager.incrementUnnamedCorruptCount();
5421 }
5422 else
5423 {
5424 XCONTENT_DATA ContentData = StorageManager.GetDLC(app.m_iTotalDLCInstalled);
5425
5426 DLCPack *pack = app.m_dlcManager.getPack( CONTENT_DATA_DISPLAY_NAME(ContentData) );
5427
5428 if( pack != NULL && pack->IsCorrupt() )
5429 {
5430 app.DebugPrintf("Pack '%ls' is corrupt, removing it from the DLC Manager.\n", CONTENT_DATA_DISPLAY_NAME(ContentData));
5431
5432 app.m_dlcManager.removePack(pack);
5433 pack = NULL;
5434 }
5435
5436 if(pack == NULL)
5437 {
5438 app.DebugPrintf("Pack \"%ls\" is not installed, so adding it\n", CONTENT_DATA_DISPLAY_NAME(ContentData));
5439
5440#if defined(_XBOX) || defined(__PS3__) || defined(_WINDOWS64)
5441 pack = new DLCPack(ContentData.szDisplayName,dwLicenceMask);
5442#elif defined _XBOX_ONE
5443 pack = new DLCPack(ContentData.wszDisplayName,ContentData.wszProductID,dwLicenceMask);
5444#else
5445 pack = new DLCPack(ContentData.wszDisplayName,dwLicenceMask);
5446#endif
5447 pack->SetDLCMountIndex(app.m_iTotalDLCInstalled);
5448 pack->SetDLCDeviceID(ContentData.DeviceID);
5449 app.m_dlcManager.addPack(pack);
5450
5451 app.HandleDLC(pack);
5452
5453 if(pack->getDLCItemsCount(DLCManager::e_DLCType_Texture) > 0)
5454 {
5455 Minecraft::GetInstance()->skins->addTexturePackFromDLC(pack, pack->GetPackId() );
5456 }
5457 }
5458 else
5459 {
5460 app.DebugPrintf("Pack \"%ls\" is already installed. Updating license to %d\n", CONTENT_DATA_DISPLAY_NAME(ContentData), dwLicenceMask);
5461
5462 pack->SetDLCMountIndex(app.m_iTotalDLCInstalled);
5463 pack->SetDLCDeviceID(ContentData.DeviceID);
5464 pack->updateLicenseMask(dwLicenceMask);
5465 }
5466
5467 StorageManager.UnmountInstalledDLC();
5468 }
5469 ++app.m_iTotalDLCInstalled;
5470 app.MountNextDLC(iPad);
5471
5472#endif // __PSVITA__
5473 return 0;
5474}
5475#undef CONTENT_DATA_DISPLAY_NAME
5476
5477// void CMinecraftApp::InstallDefaultCape()
5478// {
5479// if(!m_bDefaultCapeInstallAttempted)
5480// {
5481// // we only attempt to install the cape once per launch of the game
5482// m_bDefaultCapeInstallAttempted=true;
5483//
5484// wstring wTemp=L"Default_Cape.png";
5485// bool bRes=app.IsFileInMemoryTextures(wTemp);
5486// // if the file is not already in the memory textures, then read it from TMS
5487// if(!bRes)
5488// {
5489// BYTE *pBuffer=NULL;
5490// DWORD dwSize=0;
5491// // 4J-PB - out for now for DaveK so he doesn't get the birthday cape
5492// #ifdef _CONTENT_PACKAGE
5493// C4JStorage::ETMSStatus eTMSStatus;
5494// eTMSStatus=StorageManager.ReadTMSFile(ProfileManager.GetPrimaryPad(),C4JStorage::eGlobalStorage_Title,C4JStorage::eTMS_FileType_Graphic, L"Default_Cape.png",&pBuffer, &dwSize);
5495// if(eTMSStatus==C4JStorage::ETMSStatus_Idle)
5496// {
5497// app.AddMemoryTextureFile(wTemp,pBuffer,dwSize);
5498// }
5499// #endif
5500// }
5501// }
5502// }
5503
5504void CMinecraftApp::HandleDLC(DLCPack *pack)
5505{
5506 DWORD dwFilesProcessed = 0;
5507#ifndef _XBOX
5508#if defined(__PS3__) || defined(__ORBIS__) || defined(_WINDOWS64) || defined (__PSVITA__)
5509 std::vector<std::string> dlcFilenames;
5510#elif defined _DURANGO
5511 std::vector<std::wstring> dlcFilenames;
5512#endif
5513 StorageManager.GetMountedDLCFileList("DLCDrive", dlcFilenames);
5514#ifdef __ORBIS__
5515 // 4J Stu - I don't know why we handle more than one file here any more, however this doesn't seem to work with the PS4 patches
5516 if(dlcFilenames.size() > 0) m_dlcManager.readDLCDataFile(dwFilesProcessed, dlcFilenames[0], pack);
5517#else
5518 for(int i=0; i<dlcFilenames.size();i++)
5519 {
5520 m_dlcManager.readDLCDataFile(dwFilesProcessed, dlcFilenames[i], pack);
5521 }
5522#endif
5523#else
5524 WIN32_FIND_DATA wfd;
5525 HANDLE hFind;
5526
5527 char szPath[] = "DLCDrive:\\";
5528 char szFullFilename[256];
5529 strcpy(szFullFilename,szPath);
5530 strcat(szFullFilename,"*");
5531
5532 // Start the find and check for failure.
5533 hFind = FindFirstFile( szFullFilename, &wfd );
5534
5535 if( INVALID_HANDLE_VALUE == hFind )
5536 {
5537 app.DebugPrintf( "FindFirstFile failed." );
5538 }
5539 else
5540 {
5541 // Display each file and ask for the next.
5542 do
5543 {
5544 strcpy(szFullFilename,szPath);
5545 strcat(szFullFilename,wfd.cFileName);
5546
5547 if(( GetFileAttributes( szFullFilename ) & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY)
5548 {
5549#ifdef _XBOX
5550 DWORD dwPackID=m_dlcManager.retrievePackIDFromDLCDataFile(szFullFilename,pack);
5551
5552 // Do we need to override the TexturePack.pck with an updated version in a TU?
5553 wstring wsTemp=getFilePath(dwPackID, wstring(L"TexturePack.pck"),false );
5554 File texturePCKPath(wsTemp );
5555 if(texturePCKPath.exists())
5556 {
5557 app.DebugPrintf("Found a replacement .pck\n");
5558 m_dlcManager.readDLCDataFile(dwFilesProcessed, wsTemp,pack);
5559 }
5560 else
5561 {
5562 m_dlcManager.readDLCDataFile(dwFilesProcessed, szFullFilename,pack);
5563 }
5564#else
5565 m_dlcManager.readDLCDataFile(dwFilesProcessed, szFullFilename,pack);
5566
5567#endif
5568 }
5569 }
5570 while( FindNextFile( hFind, &wfd ) );
5571
5572 // Close the find handle.
5573 FindClose( hFind );
5574 }
5575#endif // __PS3__ || __ORBIS__
5576
5577 if( dwFilesProcessed == 0 ) m_dlcManager.removePack(pack);
5578}
5579
5580// int CMinecraftApp::DLCReadCallback(LPVOID pParam,C4JStorage::DLC_FILE_DETAILS *pDLCData)
5581// {
5582//
5583//
5584// return 0;
5585// }
5586
5587//-------------------------------------------------------------------------------------
5588// Name: InitTime()
5589// Desc: Initializes the timer variables
5590//-------------------------------------------------------------------------------------
5591void CMinecraftApp::InitTime()
5592{
5593
5594 // Get the frequency of the timer
5595 LARGE_INTEGER qwTicksPerSec;
5596 QueryPerformanceFrequency( &qwTicksPerSec );
5597 m_Time.fSecsPerTick = 1.0f / (float)qwTicksPerSec.QuadPart;
5598
5599 // Save the start time
5600 QueryPerformanceCounter( &m_Time.qwTime );
5601
5602 // Zero out the elapsed and total time
5603 m_Time.qwAppTime.QuadPart = 0;
5604 m_Time.fAppTime = 0.0f;
5605 m_Time.fElapsedTime = 0.0f;
5606}
5607
5608//-------------------------------------------------------------------------------------
5609// Name: UpdateTime()
5610// Desc: Updates the elapsed time since our last frame.
5611//-------------------------------------------------------------------------------------
5612void CMinecraftApp::UpdateTime()
5613{
5614 LARGE_INTEGER qwNewTime;
5615 LARGE_INTEGER qwDeltaTime;
5616
5617 QueryPerformanceCounter( &qwNewTime );
5618 qwDeltaTime.QuadPart = qwNewTime.QuadPart - m_Time.qwTime.QuadPart;
5619
5620 m_Time.qwAppTime.QuadPart += qwDeltaTime.QuadPart;
5621 m_Time.qwTime.QuadPart = qwNewTime.QuadPart;
5622
5623 m_Time.fElapsedTime = m_Time.fSecsPerTick * ((FLOAT)(qwDeltaTime.QuadPart));
5624 m_Time.fAppTime = m_Time.fSecsPerTick * ((FLOAT)(m_Time.qwAppTime.QuadPart));
5625}
5626
5627
5628
5629
5630
5631
5632
5633bool CMinecraftApp::isXuidNotch(PlayerUID xuid)
5634{
5635 if(m_xuidNotch != INVALID_XUID && xuid != INVALID_XUID)
5636 {
5637 return ProfileManager.AreXUIDSEqual(xuid, m_xuidNotch) == TRUE;
5638 }
5639 return false;
5640}
5641
5642bool CMinecraftApp::isXuidDeadmau5(PlayerUID xuid)
5643{
5644 AUTO_VAR(it, MojangData.find( xuid )); // 4J Stu - The .at and [] accessors insert elements if they don't exist
5645 if (it != MojangData.end() )
5646 {
5647 MOJANG_DATA *pMojangData=MojangData[xuid];
5648 if(pMojangData && pMojangData->eXuid==eXUID_Deadmau5)
5649 {
5650 return true;
5651 }
5652 }
5653
5654 return false;
5655}
5656
5657void CMinecraftApp::AddMemoryTextureFile(const wstring &wName,PBYTE pbData,DWORD dwBytes)
5658{
5659 EnterCriticalSection(&csMemFilesLock);
5660 // check it's not already in
5661 PMEMDATA pData=NULL;
5662 AUTO_VAR(it, m_MEM_Files.find(wName));
5663 if(it != m_MEM_Files.end())
5664 {
5665#ifndef _CONTENT_PACKAGE
5666 wprintf(L"Incrementing the memory texture file count for %ls\n", wName.c_str());
5667#endif
5668 pData = (*it).second;
5669
5670 if(pData->dwBytes == 0 && dwBytes != 0)
5671 {
5672 // This should never be NULL if dwBytes is 0
5673 if(pData->pbData!=NULL) delete [] pData->pbData;
5674
5675 pData->pbData=pbData;
5676 pData->dwBytes=dwBytes;
5677 }
5678
5679 ++pData->ucRefCount;
5680 LeaveCriticalSection(&csMemFilesLock);
5681 return;
5682 }
5683
5684#ifndef _CONTENT_PACKAGE
5685 //wprintf(L"Adding the memory texture file data for %ls\n", wName.c_str());
5686#endif
5687 // this is a texture (png) file
5688
5689 // add this texture to the list of memory texture files - it will then be picked up by the level renderer's AddEntity
5690
5691 pData = (PMEMDATA)new BYTE[sizeof(MEMDATA)];
5692 ZeroMemory( pData, sizeof(MEMDATA) );
5693 pData->pbData=pbData;
5694 pData->dwBytes=dwBytes;
5695 pData->ucRefCount = 1;
5696
5697 // use the xuid to access the skin data
5698 m_MEM_Files[wName]=pData;
5699
5700 LeaveCriticalSection(&csMemFilesLock);
5701}
5702
5703void CMinecraftApp::RemoveMemoryTextureFile(const wstring &wName)
5704{
5705 EnterCriticalSection(&csMemFilesLock);
5706
5707 AUTO_VAR(it, m_MEM_Files.find(wName));
5708 if(it != m_MEM_Files.end())
5709 {
5710#ifndef _CONTENT_PACKAGE
5711 wprintf(L"Decrementing the memory texture file count for %ls\n", wName.c_str());
5712#endif
5713 PMEMDATA pData = (*it).second;
5714 --pData->ucRefCount;
5715 if(pData->ucRefCount <= 0)
5716 {
5717#ifndef _CONTENT_PACKAGE
5718 wprintf(L"Erasing the memory texture file data for %ls\n", wName.c_str());
5719#endif
5720 delete [] pData;
5721 m_MEM_Files.erase(wName);
5722 }
5723 }
5724 LeaveCriticalSection(&csMemFilesLock);
5725}
5726
5727bool CMinecraftApp::DefaultCapeExists()
5728{
5729 wstring wTex=L"Special_Cape.png";
5730 bool val = false;
5731
5732 EnterCriticalSection(&csMemFilesLock);
5733 AUTO_VAR(it, m_MEM_Files.find(wTex));
5734 if(it != m_MEM_Files.end()) val = true;
5735 LeaveCriticalSection(&csMemFilesLock);
5736
5737 return val;
5738}
5739
5740bool CMinecraftApp::IsFileInMemoryTextures(const wstring &wName)
5741{
5742 bool val = false;
5743
5744 EnterCriticalSection(&csMemFilesLock);
5745 AUTO_VAR(it, m_MEM_Files.find(wName));
5746 if(it != m_MEM_Files.end()) val = true;
5747 LeaveCriticalSection(&csMemFilesLock);
5748
5749 return val;
5750}
5751
5752void CMinecraftApp::GetMemFileDetails(const wstring &wName,PBYTE *ppbData,DWORD *pdwBytes)
5753{
5754 EnterCriticalSection(&csMemFilesLock);
5755 AUTO_VAR(it, m_MEM_Files.find(wName));
5756 if(it != m_MEM_Files.end())
5757 {
5758 PMEMDATA pData = (*it).second;
5759 *ppbData=pData->pbData;
5760 *pdwBytes=pData->dwBytes;
5761 }
5762 LeaveCriticalSection(&csMemFilesLock);
5763}
5764
5765void CMinecraftApp::AddMemoryTPDFile(int iConfig,PBYTE pbData,DWORD dwBytes)
5766{
5767 EnterCriticalSection(&csMemTPDLock);
5768 // check it's not already in
5769 PMEMDATA pData=NULL;
5770 AUTO_VAR(it, m_MEM_TPD.find(iConfig));
5771 if(it == m_MEM_TPD.end())
5772 {
5773 pData = (PMEMDATA)new BYTE[sizeof(MEMDATA)];
5774 ZeroMemory( pData, sizeof(MEMDATA) );
5775 pData->pbData=pbData;
5776 pData->dwBytes=dwBytes;
5777 pData->ucRefCount = 1;
5778
5779 m_MEM_TPD[iConfig]=pData;
5780 }
5781
5782 LeaveCriticalSection(&csMemTPDLock);
5783}
5784
5785void CMinecraftApp::RemoveMemoryTPDFile(int iConfig)
5786{
5787 EnterCriticalSection(&csMemTPDLock);
5788 // check it's not already in
5789 PMEMDATA pData=NULL;
5790 AUTO_VAR(it, m_MEM_TPD.find(iConfig));
5791 if(it != m_MEM_TPD.end())
5792 {
5793 pData=m_MEM_TPD[iConfig];
5794 delete [] pData;
5795 m_MEM_TPD.erase(iConfig);
5796 }
5797
5798 LeaveCriticalSection(&csMemTPDLock);
5799}
5800
5801#ifdef _XBOX
5802int CMinecraftApp::GetTPConfigVal(WCHAR *pwchDataFile)
5803{
5804 DLC_INFO *pDLCInfo=NULL;
5805 // run through the DLC info to find the right texture pack/mash-up pack
5806 for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i)
5807 {
5808 ULONGLONG ull=app.GetDLCInfoTexturesFullOffer(i);
5809 pDLCInfo=app.GetDLCInfoForFullOfferID(ull);
5810
5811 if(wcscmp(pwchDataFile,pDLCInfo->wchDataFile)==0)
5812 {
5813 return pDLCInfo->iConfig;
5814 }
5815 }
5816
5817 return -1;
5818}
5819#elif defined _XBOX_ONE
5820int CMinecraftApp::GetTPConfigVal(WCHAR *pwchDataFile)
5821{
5822 DLC_INFO *pDLCInfo=NULL;
5823 // run through the DLC info to find the right texture pack/mash-up pack
5824 for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i)
5825 {
5826 pDLCInfo=app.GetDLCInfoForFullOfferID((WCHAR *)app.GetDLCInfoTexturesFullOffer(i).c_str());
5827
5828 if(wcscmp(pwchDataFile,pDLCInfo->wchDataFile)==0)
5829 {
5830 return pDLCInfo->iConfig;
5831 }
5832 }
5833
5834 return -1;
5835}
5836#elif defined _WINDOWS64
5837int CMinecraftApp::GetTPConfigVal(WCHAR *pwchDataFile)
5838{
5839 return -1;
5840}
5841#endif
5842bool CMinecraftApp::IsFileInTPD(int iConfig)
5843{
5844 bool val = false;
5845
5846 EnterCriticalSection(&csMemTPDLock);
5847 AUTO_VAR(it, m_MEM_TPD.find(iConfig));
5848 if(it != m_MEM_TPD.end()) val = true;
5849 LeaveCriticalSection(&csMemTPDLock);
5850
5851 return val;
5852}
5853
5854void CMinecraftApp::GetTPD(int iConfig,PBYTE *ppbData,DWORD *pdwBytes)
5855{
5856 EnterCriticalSection(&csMemTPDLock);
5857 AUTO_VAR(it, m_MEM_TPD.find(iConfig));
5858 if(it != m_MEM_TPD.end())
5859 {
5860 PMEMDATA pData = (*it).second;
5861 *ppbData=pData->pbData;
5862 *pdwBytes=pData->dwBytes;
5863 }
5864 LeaveCriticalSection(&csMemTPDLock);
5865}
5866
5867
5868// bool CMinecraftApp::UploadFileToGlobalStorage(int iQuadrant, C4JStorage::eGlobalStorage eStorageFacility, wstring *wsFile )
5869// {
5870// bool bRes=false;
5871// #ifndef _CONTENT_PACKAGE
5872// // read the local file
5873// File gtsFile( wsFile->c_str() );
5874//
5875// __int64 fileSize = gtsFile.length();
5876//
5877// if(fileSize!=0)
5878// {
5879// FileInputStream fis(gtsFile);
5880// byteArray ba((int)fileSize);
5881// fis.read(ba);
5882// fis.close();
5883//
5884// bRes=StorageManager.WriteTMSFile(iQuadrant,eStorageFacility,(WCHAR *)wsFile->c_str(),ba.data, ba.length);
5885//
5886// }
5887// #endif
5888// return bRes;
5889// }
5890
5891
5892
5893
5894
5895
5896void CMinecraftApp::StoreLaunchData()
5897{
5898
5899}
5900
5901void CMinecraftApp::ExitGame()
5902{
5903}
5904
5905// Invites
5906
5907void CMinecraftApp::ProcessInvite(DWORD dwUserIndex, DWORD dwLocalUsersMask, const INVITE_INFO * pInviteInfo)
5908{
5909 m_InviteData.dwUserIndex=dwUserIndex;
5910 m_InviteData.dwLocalUsersMask=dwLocalUsersMask;
5911 m_InviteData.pInviteInfo=pInviteInfo;
5912 //memcpy(&m_InviteData,pJoinData,sizeof(JoinFromInviteData));
5913 SetAction(dwUserIndex,eAppAction_ExitAndJoinFromInvite);
5914}
5915
5916int CMinecraftApp::ExitAndJoinFromInvite(void *pParam,int iPad,C4JStorage::EMessageResult result)
5917{
5918 CMinecraftApp* pApp = (CMinecraftApp*)pParam;
5919 //Minecraft *pMinecraft=Minecraft::GetInstance();
5920
5921 // buttons are swapped on this menu
5922 if(result==C4JStorage::EMessage_ResultDecline)
5923 {
5924 pApp->SetAction(iPad,eAppAction_ExitAndJoinFromInviteConfirmed);
5925 }
5926
5927 return 0;
5928}
5929
5930int CMinecraftApp::ExitAndJoinFromInviteSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
5931{
5932 CMinecraftApp *pClass = (CMinecraftApp *)pParam;
5933 // Exit with or without saving
5934 // Decline means save in this dialog
5935 if(result==C4JStorage::EMessage_ResultDecline || result==C4JStorage::EMessage_ResultThirdOption)
5936 {
5937 if( result==C4JStorage::EMessage_ResultDecline ) // Save
5938 {
5939 // Check they have the full texture pack if they are using one
5940 // 4J-PB - Is the player trying to save but they are using a trial texturepack ?
5941 if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin())
5942 {
5943 TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected();
5944
5945 DLCPack * pDLCPack=tPack->getDLCPack();
5946 if(!pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" ))
5947 {
5948 // upsell
5949 // get the dlc texture pack
5950
5951#ifdef _XBOX
5952 DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack;
5953 ULONGLONG ullOfferID_Full;
5954 app.GetDLCFullOfferIDForPackID(pDLCTexPack->getDLCParentPackId(),&ullOfferID_Full);
5955
5956 // tell sentient about the upsell of the full version of the skin pack
5957 TelemetryManager->RecordUpsellPresented(iPad, eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF);
5958#endif
5959
5960 UINT uiIDA[2];
5961 uiIDA[0]=IDS_CONFIRM_OK;
5962 uiIDA[1]=IDS_CONFIRM_CANCEL;
5963
5964 // Give the player a warning about the trial version of the texture pack
5965 ui.RequestErrorMessage(IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, IDS_WARNING_DLC_TRIALTEXTUREPACK_TEXT, uiIDA, 2, iPad,&CMinecraftApp::WarningTrialTexturePackReturned,pClass);
5966
5967 return S_OK;
5968 }
5969 }
5970#ifndef _XBOX_ONE
5971 // does the save exist?
5972 bool bSaveExists;
5973 StorageManager.DoesSaveExist(&bSaveExists);
5974 // 4J-PB - we check if the save exists inside the libs
5975 // we need to ask if they are sure they want to overwrite the existing game
5976 if(bSaveExists)
5977 {
5978 UINT uiIDA[2];
5979 uiIDA[0]=IDS_CONFIRM_CANCEL;
5980 uiIDA[1]=IDS_CONFIRM_OK;
5981 ui.RequestErrorMessage(IDS_TITLE_SAVE_GAME, IDS_CONFIRM_SAVE_GAME, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::ExitAndJoinFromInviteAndSaveReturned,pClass);
5982 return 0;
5983 }
5984 else
5985#endif
5986 {
5987#if defined(_XBOX_ONE) || defined(__ORBIS__)
5988 StorageManager.SetSaveDisabled(false);
5989#endif
5990 MinecraftServer::getInstance()->setSaveOnExit( true );
5991 }
5992 }
5993 else
5994 {
5995 // been a few requests for a confirm on exit without saving
5996 UINT uiIDA[2];
5997 uiIDA[0]=IDS_CONFIRM_CANCEL;
5998 uiIDA[1]=IDS_CONFIRM_OK;
5999 ui.RequestErrorMessage(IDS_TITLE_DECLINE_SAVE_GAME, IDS_CONFIRM_DECLINE_SAVE_GAME, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::ExitAndJoinFromInviteDeclineSaveReturned,pClass);
6000 return 0;
6001 }
6002
6003 app.SetAction(ProfileManager.GetPrimaryPad(),eAppAction_ExitAndJoinFromInviteConfirmed);
6004 }
6005 return 0;
6006}
6007
6008int CMinecraftApp::WarningTrialTexturePackReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
6009{
6010 // 4J Stu - I added this in when fixing an X1 bug. We should probably add this as well but I don't have time to test all platforms atm
6011#if 0 //defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__)
6012 if(result==C4JStorage::EMessage_ResultAccept)
6013 {
6014 if(!ProfileManager.IsSignedInLive(iPad))
6015 {
6016 // you're not signed in to PSN!
6017
6018 }
6019 else
6020 {
6021 // 4J-PB - need to check this user can access the store
6022 bool bContentRestricted;
6023 ProfileManager.GetChatAndContentRestrictions(iPad,true,NULL,&bContentRestricted,NULL);
6024 if(bContentRestricted)
6025 {
6026 UINT uiIDA[1];
6027 uiIDA[0]=IDS_CONFIRM_OK;
6028 ui.RequestAlertMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPad);
6029 }
6030 else
6031 {
6032 // need to get info on the pack to see if the user has already downloaded it
6033 TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected();
6034 DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack;
6035
6036 // retrieve the store name for the skin pack
6037 DLCPack *pDLCPack=pDLCTexPack->getDLCInfoParentPack();//tPack->getDLCPack();
6038 const char *pchPackName=wstringtofilename(pDLCPack->getName());
6039 app.DebugPrintf("Texture Pack - %s\n",pchPackName);
6040 SONYDLC *pSONYDLCInfo=app.GetSONYDLCInfo((char *)pchPackName);
6041
6042 if(pSONYDLCInfo!=NULL)
6043 {
6044 char chName[42];
6045 char chSkuID[SCE_NP_COMMERCE2_SKU_ID_LEN];
6046
6047 memset(chSkuID,0,SCE_NP_COMMERCE2_SKU_ID_LEN);
6048 // find the info on the skin pack
6049 // we have to retrieve the skuid from the store info, it can't be hardcoded since Sony may change it.
6050 // So we assume the first sku for the product is the one we want
6051#ifdef __ORBIS__
6052 sprintf(chName,"%s",pSONYDLCInfo->chDLCKeyname);
6053#else
6054 sprintf(chName,"%s-%s",app.GetCommerceCategory(),pSONYDLCInfo->chDLCKeyname);
6055#endif
6056 app.GetDLCSkuIDFromProductList(chName,chSkuID);
6057 // 4J-PB - need to check for an empty store
6058#if defined __ORBIS__ || defined __PSVITA__ || defined __PS3__
6059 if(app.CheckForEmptyStore(iPad)==false)
6060#endif
6061 {
6062 if(app.DLCAlreadyPurchased(chSkuID))
6063 {
6064 app.DownloadAlreadyPurchased(chSkuID);
6065 }
6066 else
6067 {
6068 app.Checkout(chSkuID);
6069 }
6070 }
6071 }
6072 }
6073 }
6074 }
6075#endif //
6076
6077#ifdef _XBOX_ONE
6078 if(result==C4JStorage::EMessage_ResultAccept)
6079 {
6080 if(ProfileManager.IsSignedIn(iPad))
6081 {
6082 if (ProfileManager.IsSignedInLive(iPad))
6083 {
6084 TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected();
6085 // get the dlc texture pack
6086 DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack;
6087
6088 DLCPack *pDLCPack=pDLCTexPack->getDLCInfoParentPack();
6089
6090 DLC_INFO *pDLCInfo=app.GetDLCInfoForProductName((WCHAR *)pDLCPack->getName().c_str());
6091
6092 StorageManager.InstallOffer(1,(WCHAR *)pDLCInfo->wsProductId.c_str(),NULL,NULL);
6093
6094 // the license change coming in when the offer has been installed will cause this scene to refresh
6095 }
6096 else
6097 {
6098 // 4J-JEV: Fix for XB1: #165863 - XR-074: Compliance: With no active network connection user is unable to convert from Trial to Full texture pack and is not messaged why.
6099 UINT uiIDA[1] = { IDS_CONFIRM_OK };
6100 ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1, iPad);
6101 }
6102 }
6103 }
6104
6105#endif
6106#ifdef _XBOX
6107
6108 CMinecraftApp* pClass = (CMinecraftApp*)pParam;
6109
6110 TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected();
6111 // get the dlc texture pack
6112 DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack;
6113 ULONGLONG ullIndexA[1];
6114
6115 // Need to get the parent packs id, since this may be one of many child packs with their own ids
6116 app.GetDLCFullOfferIDForPackID(pDLCTexPack->getDLCParentPackId(),&ullIndexA[0]);
6117
6118 if(result==C4JStorage::EMessage_ResultAccept)
6119 {
6120 if(ProfileManager.IsSignedIn(iPad))
6121 {
6122 // 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...
6123 XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW);
6124
6125 StorageManager.InstallOffer(1,ullIndexA,NULL,NULL);
6126 }
6127 }
6128 else
6129 {
6130 TelemetryManager->RecordUpsellResponded(iPad, eSet_UpsellID_Texture_DLC, ( ullIndexA[0] & 0xFFFFFFFF ), eSen_UpsellOutcome_Declined);
6131 }
6132#endif
6133 return 0;
6134}
6135
6136int CMinecraftApp::ExitAndJoinFromInviteAndSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
6137{
6138 //CMinecraftApp* pClass = (CMinecraftApp*)pParam;
6139
6140 // results switched for this dialog
6141 if(result==C4JStorage::EMessage_ResultDecline)
6142 {
6143 INT saveOrCheckpointId = 0;
6144
6145 // Check they have the full texture pack if they are using one
6146 // 4J-PB - Is the player trying to save but they are using a trial texturepack ?
6147 if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin())
6148 {
6149 TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected();
6150
6151 DLCPack * pDLCPack=tPack->getDLCPack();
6152 if(!pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" ))
6153 {
6154 // upsell
6155 // get the dlc texture pack
6156
6157#ifdef _XBOX
6158 DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack;
6159 ULONGLONG ullOfferID_Full;
6160 app.GetDLCFullOfferIDForPackID(pDLCTexPack->getDLCParentPackId(),&ullOfferID_Full);
6161
6162 // tell sentient about the upsell of the full version of the skin pack
6163 TelemetryManager->RecordUpsellPresented(iPad, eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF);
6164#endif
6165
6166 UINT uiIDA[2];
6167 uiIDA[0]=IDS_CONFIRM_OK;
6168 uiIDA[1]=IDS_CONFIRM_CANCEL;
6169
6170 // Give the player a warning about the trial version of the texture pack
6171 ui.RequestErrorMessage(IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, IDS_WARNING_DLC_TRIALTEXTUREPACK_TEXT, uiIDA, 2, iPad,&CMinecraftApp::WarningTrialTexturePackReturned,NULL);
6172
6173 return S_OK;
6174 }
6175 }
6176 //bool validSave = StorageManager.GetSaveUniqueNumber(&saveOrCheckpointId);
6177 //SentientManager.RecordLevelSaveOrCheckpoint(ProfileManager.GetPrimaryPad(), saveOrCheckpointId);
6178 MinecraftServer::getInstance()->setSaveOnExit( true );
6179 // flag a app action of exit and join game from invite
6180 app.SetAction(iPad,eAppAction_ExitAndJoinFromInviteConfirmed);
6181 }
6182 return 0;
6183}
6184
6185int CMinecraftApp::ExitAndJoinFromInviteDeclineSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
6186{
6187 // results switched for this dialog
6188 if(result==C4JStorage::EMessage_ResultDecline)
6189 {
6190#if defined(_XBOX_ONE) || defined(__ORBIS__)
6191 StorageManager.SetSaveDisabled(false);
6192#endif
6193 MinecraftServer::getInstance()->setSaveOnExit( false );
6194 // flag a app action of exit and join game from invite
6195 app.SetAction(iPad,eAppAction_ExitAndJoinFromInviteConfirmed);
6196 }
6197 return 0;
6198}
6199
6200//////////////////////////////////////////////////////////////////////////
6201//
6202// FatalLoadError
6203//
6204// This is called when we can't load one of the required files at startup
6205// It tends to mean the files have been corrupted.
6206// We have to assume that we've not been able to load the text for the game.
6207//
6208//////////////////////////////////////////////////////////////////////////
6209void CMinecraftApp::FatalLoadError()
6210{
6211
6212}
6213
6214TIPSTRUCT CMinecraftApp::m_GameTipA[MAX_TIPS_GAMETIP]=
6215{
6216 { 0, IDS_TIPS_GAMETIP_1},
6217 { 0, IDS_TIPS_GAMETIP_2},
6218 { 0, IDS_TIPS_GAMETIP_3},
6219 { 0, IDS_TIPS_GAMETIP_4},
6220 { 0, IDS_TIPS_GAMETIP_5},
6221 { 0, IDS_TIPS_GAMETIP_6},
6222 { 0, IDS_TIPS_GAMETIP_7},
6223 { 0, IDS_TIPS_GAMETIP_8},
6224 { 0, IDS_TIPS_GAMETIP_9},
6225 { 0, IDS_TIPS_GAMETIP_10},
6226 { 0, IDS_TIPS_GAMETIP_11},
6227 { 0, IDS_TIPS_GAMETIP_12},
6228 { 0, IDS_TIPS_GAMETIP_13},
6229 { 0, IDS_TIPS_GAMETIP_14},
6230 { 0, IDS_TIPS_GAMETIP_15},
6231 { 0, IDS_TIPS_GAMETIP_16},
6232 { 0, IDS_TIPS_GAMETIP_17},
6233 { 0, IDS_TIPS_GAMETIP_18},
6234 { 0, IDS_TIPS_GAMETIP_19},
6235 { 0, IDS_TIPS_GAMETIP_20},
6236 { 0, IDS_TIPS_GAMETIP_21},
6237 { 0, IDS_TIPS_GAMETIP_22},
6238 { 0, IDS_TIPS_GAMETIP_23},
6239 { 0, IDS_TIPS_GAMETIP_24},
6240 { 0, IDS_TIPS_GAMETIP_25},
6241 { 0, IDS_TIPS_GAMETIP_26},
6242 { 0, IDS_TIPS_GAMETIP_27},
6243 { 0, IDS_TIPS_GAMETIP_28},
6244 { 0, IDS_TIPS_GAMETIP_29},
6245 { 0, IDS_TIPS_GAMETIP_30},
6246 { 0, IDS_TIPS_GAMETIP_31},
6247 { 0, IDS_TIPS_GAMETIP_32},
6248 { 0, IDS_TIPS_GAMETIP_33},
6249 { 0, IDS_TIPS_GAMETIP_34},
6250 { 0, IDS_TIPS_GAMETIP_35},
6251 { 0, IDS_TIPS_GAMETIP_36},
6252 { 0, IDS_TIPS_GAMETIP_37},
6253 { 0, IDS_TIPS_GAMETIP_38},
6254 { 0, IDS_TIPS_GAMETIP_39},
6255 { 0, IDS_TIPS_GAMETIP_40},
6256 { 0, IDS_TIPS_GAMETIP_41},
6257 { 0, IDS_TIPS_GAMETIP_42},
6258 { 0, IDS_TIPS_GAMETIP_43},
6259 { 0, IDS_TIPS_GAMETIP_44},
6260 { 0, IDS_TIPS_GAMETIP_45},
6261 { 0, IDS_TIPS_GAMETIP_46},
6262 { 0, IDS_TIPS_GAMETIP_47},
6263 { 0, IDS_TIPS_GAMETIP_48},
6264 { 0, IDS_TIPS_GAMETIP_49},
6265 { 0, IDS_TIPS_GAMETIP_50},
6266};
6267
6268TIPSTRUCT CMinecraftApp::m_TriviaTipA[MAX_TIPS_TRIVIATIP]=
6269{
6270 { 0, IDS_TIPS_TRIVIA_1},
6271 { 0, IDS_TIPS_TRIVIA_2},
6272 { 0, IDS_TIPS_TRIVIA_3},
6273 { 0, IDS_TIPS_TRIVIA_4},
6274 { 0, IDS_TIPS_TRIVIA_5},
6275 { 0, IDS_TIPS_TRIVIA_6},
6276 { 0, IDS_TIPS_TRIVIA_7},
6277 { 0, IDS_TIPS_TRIVIA_8},
6278 { 0, IDS_TIPS_TRIVIA_9},
6279 { 0, IDS_TIPS_TRIVIA_10},
6280 { 0, IDS_TIPS_TRIVIA_11},
6281 { 0, IDS_TIPS_TRIVIA_12},
6282 { 0, IDS_TIPS_TRIVIA_13},
6283 { 0, IDS_TIPS_TRIVIA_14},
6284 { 0, IDS_TIPS_TRIVIA_15},
6285 { 0, IDS_TIPS_TRIVIA_16},
6286 { 0, IDS_TIPS_TRIVIA_17},
6287 { 0, IDS_TIPS_TRIVIA_18},
6288 { 0, IDS_TIPS_TRIVIA_19},
6289 { 0, IDS_TIPS_TRIVIA_20},
6290};
6291
6292Random *CMinecraftApp::TipRandom = new Random();
6293
6294int CMinecraftApp::TipsSortFunction(const void* a, const void* b)
6295{
6296 return ((TIPSTRUCT*)a)->iSortValue - ((TIPSTRUCT*)b)->iSortValue;
6297}
6298
6299void CMinecraftApp::InitialiseTips()
6300{
6301 // We'll randomise the tips at start up based on their priority
6302
6303 ZeroMemory(m_TipIDA,sizeof(UINT)*MAX_TIPS_GAMETIP+MAX_TIPS_TRIVIATIP);
6304
6305 // Make the first tip tell you that you can play splitscreen in HD modes if you are in SD
6306 if(!RenderManager.IsHiDef())
6307 {
6308 m_GameTipA[0].uiStringID=IDS_TIPS_GAMETIP_0;
6309 }
6310 // randomise then quicksort
6311 // going to leave the multiplayer tip so it is always first
6312
6313 // Only randomise the content package build
6314#ifdef _CONTENT_PACKAGE
6315
6316 for(int i=1;i<MAX_TIPS_GAMETIP;i++)
6317 {
6318 m_GameTipA[i].iSortValue=TipRandom->nextInt();
6319 }
6320 qsort( &m_GameTipA[1], MAX_TIPS_GAMETIP-1, sizeof(TIPSTRUCT), TipsSortFunction );
6321#endif
6322
6323 for(int i=0;i<MAX_TIPS_TRIVIATIP;i++)
6324 {
6325 m_TriviaTipA[i].iSortValue=TipRandom->nextInt();
6326 }
6327 qsort( m_TriviaTipA, MAX_TIPS_TRIVIATIP, sizeof(TIPSTRUCT), TipsSortFunction );
6328
6329
6330 int iCurrentGameTip=0;
6331 int iCurrentTriviaTip=0;
6332
6333 for(int i=0;i<MAX_TIPS_GAMETIP+MAX_TIPS_TRIVIATIP;i++)
6334 {
6335 // Add a trivia one every third tip (if there are any left)
6336 if((i%3==2) && (iCurrentTriviaTip<MAX_TIPS_TRIVIATIP))
6337 {
6338 // Add a trivia one
6339 m_TipIDA[i]=m_TriviaTipA[iCurrentTriviaTip++].uiStringID;
6340 }
6341 else
6342 {
6343 if(iCurrentGameTip<MAX_TIPS_GAMETIP)
6344 {
6345 // Add a gametip
6346 m_TipIDA[i]=m_GameTipA[iCurrentGameTip++].uiStringID;
6347 }
6348 else
6349 {
6350 // Add a trivia one
6351 m_TipIDA[i]=m_TriviaTipA[iCurrentTriviaTip++].uiStringID;
6352 }
6353 }
6354
6355 if(m_TipIDA[i]==0)
6356 {
6357 // the m_TriviaTipA or the m_GameTipA are out of sync
6358#ifndef _CONTENT_PACKAGE
6359 __debugbreak();
6360#endif
6361 }
6362 }
6363
6364 m_uiCurrentTip=0;
6365}
6366
6367UINT CMinecraftApp::GetNextTip()
6368{
6369 static bool bShowSkinDLCTip=true;
6370 // don't display the DLC tip in the trial game
6371 if(ProfileManager.IsFullVersion() && app.GetNewDLCAvailable() && app.DisplayNewDLCTip())
6372 {
6373 return IDS_TIPS_GAMETIP_NEWDLC;
6374 }
6375 else
6376 {
6377 if(bShowSkinDLCTip && ProfileManager.IsFullVersion())
6378 {
6379 bShowSkinDLCTip=false;
6380 if( app.DLCInstallProcessCompleted() )
6381 {
6382 if(app.m_dlcManager.getPackCount(DLCManager::e_DLCType_Skin)==0)
6383 {
6384 return IDS_TIPS_GAMETIP_SKINPACKS;
6385 }
6386 }
6387 else
6388 {
6389 return IDS_TIPS_GAMETIP_SKINPACKS;
6390 }
6391 }
6392 }
6393
6394 if(m_uiCurrentTip==MAX_TIPS_GAMETIP+MAX_TIPS_TRIVIATIP) m_uiCurrentTip=0;
6395
6396 return m_TipIDA[m_uiCurrentTip++];
6397}
6398
6399int CMinecraftApp::GetHTMLColour(eMinecraftColour colour)
6400{
6401 Minecraft *pMinecraft = Minecraft::GetInstance();
6402 return pMinecraft->skins->getSelected()->getColourTable()->getColour(colour);
6403}
6404
6405int CMinecraftApp::GetHTMLFontSize(EHTMLFontSize size)
6406{
6407 return s_iHTMLFontSizesA[size];
6408}
6409
6410wstring CMinecraftApp::FormatHTMLString(int iPad, const wstring &desc, int shadowColour /*= 0xFFFFFFFF*/)
6411{
6412 wstring text(desc);
6413
6414 wchar_t replacements[64];
6415 // We will also insert line breaks here as couldn't figure out how to get them to come through from strings.resx !
6416 text = replaceAll(text, L"{*B*}", L"<br />" );
6417 swprintf(replacements,64,L"<font color=\"#%08x\">", GetHTMLColour(eHTMLColor_T1));
6418 text = replaceAll(text, L"{*T1*}", replacements );
6419 swprintf(replacements,64,L"<font color=\"#%08x\">", GetHTMLColour(eHTMLColor_T2));
6420 text = replaceAll(text, L"{*T2*}", replacements );
6421 swprintf(replacements,64,L"<font color=\"#%08x\">", GetHTMLColour(eHTMLColor_T3));
6422 text = replaceAll(text, L"{*T3*}", replacements ); // for How To Play
6423 swprintf(replacements,64,L"</font><font color=\"#%08x\">", GetHTMLColour(eHTMLColor_Black));
6424 text = replaceAll(text, L"{*ETB*}", replacements );
6425 swprintf(replacements,64,L"</font><font color=\"#%08x\">", GetHTMLColour(eHTMLColor_White));
6426 text = replaceAll(text, L"{*ETW*}", replacements );
6427 text = replaceAll(text, L"{*EF*}", L"</font>" );
6428
6429 swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_0), shadowColour);
6430 text = replaceAll(text, L"{*C0*}", replacements );
6431 swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_1), shadowColour);
6432 text = replaceAll(text, L"{*C1*}", replacements );
6433 swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_2), shadowColour);
6434 text = replaceAll(text, L"{*C2*}", replacements );
6435 swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_3), shadowColour);
6436 text = replaceAll(text, L"{*C3*}", replacements );
6437 swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_4), shadowColour);
6438 text = replaceAll(text, L"{*C4*}", replacements );
6439 swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_5), shadowColour);
6440 text = replaceAll(text, L"{*C5*}", replacements );
6441 swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_6), shadowColour);
6442 text = replaceAll(text, L"{*C6*}", replacements );
6443 swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_7), shadowColour);
6444 text = replaceAll(text, L"{*C7*}", replacements );
6445 swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_8), shadowColour);
6446 text = replaceAll(text, L"{*C8*}", replacements );
6447 swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_9), shadowColour);
6448 text = replaceAll(text, L"{*C9*}", replacements );
6449 swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_a), shadowColour);
6450 text = replaceAll(text, L"{*CA*}", replacements );
6451 swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_b), shadowColour);
6452 text = replaceAll(text, L"{*CB*}", replacements );
6453 swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_c), shadowColour);
6454 text = replaceAll(text, L"{*CC*}", replacements );
6455 swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_d), shadowColour);
6456 text = replaceAll(text, L"{*CD*}", replacements );
6457 swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_e), shadowColour);
6458 text = replaceAll(text, L"{*CE*}", replacements );
6459 swprintf(replacements,64,L"<font color=\"#%08x\" shadowcolor=\"#%08x\">", GetHTMLColour(eHTMLColor_f), shadowColour);
6460 text = replaceAll(text, L"{*CF*}", replacements );
6461
6462 // Swap for southpaw.
6463 if ( app.GetGameSettings(iPad,eGameSetting_ControlSouthPaw) )
6464 {
6465 text = replaceAll(text, L"{*CONTROLLER_ACTION_MOVE*}", GetActionReplacement(iPad,MINECRAFT_ACTION_LOOK_RIGHT ) );
6466 text = replaceAll(text, L"{*CONTROLLER_ACTION_LOOK*}", GetActionReplacement(iPad,MINECRAFT_ACTION_RIGHT ) );
6467
6468 text = replaceAll(text, L"{*CONTROLLER_MENU_NAVIGATE*}", GetVKReplacement(VK_PAD_RTHUMB_LEFT) );
6469 }
6470 else // Normal right handed.
6471 {
6472 text = replaceAll(text, L"{*CONTROLLER_ACTION_MOVE*}", GetActionReplacement(iPad,MINECRAFT_ACTION_RIGHT ) );
6473 text = replaceAll(text, L"{*CONTROLLER_ACTION_LOOK*}", GetActionReplacement(iPad,MINECRAFT_ACTION_LOOK_RIGHT ) );
6474
6475 text = replaceAll(text, L"{*CONTROLLER_MENU_NAVIGATE*}", GetVKReplacement(VK_PAD_LTHUMB_LEFT) );
6476 }
6477
6478 text = replaceAll(text, L"{*CONTROLLER_ACTION_JUMP*}", GetActionReplacement(iPad,MINECRAFT_ACTION_JUMP ) );
6479 text = replaceAll(text, L"{*CONTROLLER_ACTION_SNEAK*}", GetActionReplacement(iPad,MINECRAFT_ACTION_SNEAK_TOGGLE ) );
6480 text = replaceAll(text, L"{*CONTROLLER_ACTION_USE*}", GetActionReplacement(iPad,MINECRAFT_ACTION_USE ) );
6481 text = replaceAll(text, L"{*CONTROLLER_ACTION_ACTION*}", GetActionReplacement(iPad,MINECRAFT_ACTION_ACTION ) );
6482 text = replaceAll(text, L"{*CONTROLLER_ACTION_LEFT_SCROLL*}", GetActionReplacement(iPad,MINECRAFT_ACTION_LEFT_SCROLL ) );
6483 text = replaceAll(text, L"{*CONTROLLER_ACTION_RIGHT_SCROLL*}", GetActionReplacement(iPad,MINECRAFT_ACTION_RIGHT_SCROLL ) );
6484 text = replaceAll(text, L"{*CONTROLLER_ACTION_INVENTORY*}", GetActionReplacement(iPad,MINECRAFT_ACTION_INVENTORY ) );
6485 text = replaceAll(text, L"{*CONTROLLER_ACTION_CRAFTING*}", GetActionReplacement(iPad,MINECRAFT_ACTION_CRAFTING ) );
6486 text = replaceAll(text, L"{*CONTROLLER_ACTION_DROP*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DROP ) );
6487 text = replaceAll(text, L"{*CONTROLLER_ACTION_CAMERA*}", GetActionReplacement(iPad,MINECRAFT_ACTION_RENDER_THIRD_PERSON ) );
6488 text = replaceAll(text, L"{*CONTROLLER_ACTION_MENU_PAGEDOWN*}", GetActionReplacement(iPad,ACTION_MENU_PAGEDOWN ) );
6489 text = replaceAll(text, L"{*CONTROLLER_ACTION_DISMOUNT*}", GetActionReplacement(iPad,MINECRAFT_ACTION_SNEAK_TOGGLE ) );
6490 text = replaceAll(text, L"{*CONTROLLER_VK_A*}", GetVKReplacement(VK_PAD_A) );
6491 text = replaceAll(text, L"{*CONTROLLER_VK_B*}", GetVKReplacement(VK_PAD_B) );
6492 text = replaceAll(text, L"{*CONTROLLER_VK_X*}", GetVKReplacement(VK_PAD_X) );
6493 text = replaceAll(text, L"{*CONTROLLER_VK_Y*}", GetVKReplacement(VK_PAD_Y) );
6494 text = replaceAll(text, L"{*CONTROLLER_VK_LB*}", GetVKReplacement(VK_PAD_LSHOULDER) );
6495 text = replaceAll(text, L"{*CONTROLLER_VK_RB*}", GetVKReplacement(VK_PAD_RSHOULDER) );
6496 text = replaceAll(text, L"{*CONTROLLER_VK_LS*}", GetVKReplacement(VK_PAD_LTHUMB_UP) );
6497 text = replaceAll(text, L"{*CONTROLLER_VK_RS*}", GetVKReplacement(VK_PAD_RTHUMB_UP) );
6498 text = replaceAll(text, L"{*CONTROLLER_VK_LT*}", GetVKReplacement(VK_PAD_LTRIGGER) );
6499 text = replaceAll(text, L"{*CONTROLLER_VK_RT*}", GetVKReplacement(VK_PAD_RTRIGGER) );
6500 text = replaceAll(text, L"{*ICON_SHANK_01*}", GetIconReplacement(XZP_ICON_SHANK_01) );
6501 text = replaceAll(text, L"{*ICON_SHANK_03*}", GetIconReplacement(XZP_ICON_SHANK_03) );
6502 text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_UP*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DPAD_UP ) );
6503 text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_DOWN*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DPAD_DOWN ) );
6504 text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_RIGHT*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DPAD_RIGHT ) );
6505 text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_LEFT*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DPAD_LEFT ) );
6506#if defined _XBOX_ONE || defined __PSVITA__
6507 text = replaceAll(text, L"{*CONTROLLER_VK_START*}", GetVKReplacement(VK_PAD_START ) );
6508 text = replaceAll(text, L"{*CONTROLLER_VK_BACK*}", GetVKReplacement(VK_PAD_BACK ) );
6509#endif
6510
6511#ifdef _XBOX
6512 wstring imageRoot = L"";
6513
6514 Minecraft *pMinecraft = Minecraft::GetInstance();
6515 imageRoot = pMinecraft->skins->getSelected()->getXuiRootPath();
6516
6517 text = replaceAll(text, L"{*IMAGEROOT*}", imageRoot);
6518#endif // _XBOX
6519
6520 // Fix for #8903 - UI: Localization: KOR/JPN/CHT: Button Icons are rendered with padding space, which looks no good
6521 DWORD dwLanguage = XGetLanguage( );
6522 switch(dwLanguage)
6523 {
6524 case XC_LANGUAGE_KOREAN:
6525 case XC_LANGUAGE_JAPANESE:
6526 case XC_LANGUAGE_TCHINESE:
6527 text = replaceAll(text, L" ", L"" );
6528 break;
6529 }
6530
6531 return text;
6532}
6533
6534wstring CMinecraftApp::GetActionReplacement(int iPad, unsigned char ucAction)
6535{
6536 unsigned int input = InputManager.GetGameJoypadMaps(InputManager.GetJoypadMapVal(iPad) ,ucAction);
6537
6538#ifdef _XBOX
6539 switch(input)
6540 {
6541 case _360_JOY_BUTTON_A:
6542 return app.GetString( IDS_CONTROLLER_A );
6543 case _360_JOY_BUTTON_B:
6544 return app.GetString( IDS_CONTROLLER_B );
6545 case _360_JOY_BUTTON_X:
6546 return app.GetString( IDS_CONTROLLER_X );
6547 case _360_JOY_BUTTON_Y:
6548 return app.GetString( IDS_CONTROLLER_Y );
6549 case _360_JOY_BUTTON_LSTICK_UP:
6550 case _360_JOY_BUTTON_LSTICK_DOWN:
6551 case _360_JOY_BUTTON_LSTICK_LEFT:
6552 case _360_JOY_BUTTON_LSTICK_RIGHT:
6553 return app.GetString( IDS_CONTROLLER_LEFT_STICK );
6554 case _360_JOY_BUTTON_RSTICK_LEFT:
6555 case _360_JOY_BUTTON_RSTICK_RIGHT:
6556 case _360_JOY_BUTTON_RSTICK_UP:
6557 case _360_JOY_BUTTON_RSTICK_DOWN:
6558 return app.GetString( IDS_CONTROLLER_RIGHT_STICK );
6559 case _360_JOY_BUTTON_LT:
6560 return app.GetString( IDS_CONTROLLER_LEFT_TRIGGER );
6561 case _360_JOY_BUTTON_RT:
6562 return app.GetString( IDS_CONTROLLER_RIGHT_TRIGGER );
6563 case _360_JOY_BUTTON_RB:
6564 return app.GetString( IDS_CONTROLLER_RIGHT_BUMPER );
6565 case _360_JOY_BUTTON_LB:
6566 return app.GetString( IDS_CONTROLLER_LEFT_BUMPER );
6567 case _360_JOY_BUTTON_BACK:
6568 return app.GetString( IDS_CONTROLLER_BACK );
6569 case _360_JOY_BUTTON_START:
6570 return app.GetString( IDS_CONTROLLER_START );
6571 case _360_JOY_BUTTON_RTHUMB:
6572 return app.GetString( IDS_CONTROLLER_RIGHT_THUMBSTICK );
6573 case _360_JOY_BUTTON_LTHUMB:
6574 return app.GetString( IDS_CONTROLLER_LEFT_THUMBSTICK );
6575 case _360_JOY_BUTTON_DPAD_LEFT:
6576 return app.GetString( IDS_CONTROLLER_DPAD_L );
6577 case _360_JOY_BUTTON_DPAD_RIGHT:
6578 return app.GetString( IDS_CONTROLLER_DPAD_R );
6579 case _360_JOY_BUTTON_DPAD_UP:
6580 return app.GetString( IDS_CONTROLLER_DPAD_U );
6581 case _360_JOY_BUTTON_DPAD_DOWN:
6582 return app.GetString( IDS_CONTROLLER_DPAD_D );
6583 };
6584 return L"";
6585#else
6586 wstring replacement = L"";
6587
6588 // 4J Stu - Some of our actions can be mapped to multiple physical buttons, so replaces the switch that was here
6589 if (input & _360_JOY_BUTTON_A) replacement = L"ButtonA";
6590 else if(input &_360_JOY_BUTTON_B) replacement = L"ButtonB";
6591 else if(input &_360_JOY_BUTTON_X) replacement = L"ButtonX";
6592 else if(input &_360_JOY_BUTTON_Y) replacement = L"ButtonY";
6593 else if(
6594 (input &_360_JOY_BUTTON_LSTICK_UP) ||
6595 (input &_360_JOY_BUTTON_LSTICK_DOWN) ||
6596 (input &_360_JOY_BUTTON_LSTICK_LEFT) ||
6597 (input &_360_JOY_BUTTON_LSTICK_RIGHT)
6598 )
6599 {
6600 replacement = L"ButtonLeftStick";
6601 }
6602 else if(
6603 (input &_360_JOY_BUTTON_RSTICK_LEFT) ||
6604 (input &_360_JOY_BUTTON_RSTICK_RIGHT) ||
6605 (input &_360_JOY_BUTTON_RSTICK_UP) ||
6606 (input &_360_JOY_BUTTON_RSTICK_DOWN)
6607 )
6608 {
6609 replacement = L"ButtonRightStick";
6610 }
6611 else if(input &_360_JOY_BUTTON_DPAD_LEFT) replacement = L"ButtonDpadL";
6612 else if(input &_360_JOY_BUTTON_DPAD_RIGHT) replacement = L"ButtonDpadR";
6613 else if(input &_360_JOY_BUTTON_DPAD_UP) replacement = L"ButtonDpadU";
6614 else if(input &_360_JOY_BUTTON_DPAD_DOWN) replacement = L"ButtonDpadD";
6615 else if(input &_360_JOY_BUTTON_LT) replacement = L"ButtonLeftTrigger";
6616 else if(input &_360_JOY_BUTTON_RT) replacement = L"ButtonRightTrigger";
6617 else if(input &_360_JOY_BUTTON_RB) replacement = L"ButtonRightBumper";
6618 else if(input &_360_JOY_BUTTON_LB) replacement = L"ButtonLeftBumper";
6619 else if(input &_360_JOY_BUTTON_BACK) replacement = L"ButtonBack";
6620 else if(input &_360_JOY_BUTTON_START) replacement = L"ButtonStart";
6621 else if(input &_360_JOY_BUTTON_RTHUMB) replacement = L"ButtonRS";
6622 else if(input &_360_JOY_BUTTON_LTHUMB) replacement = L"ButtonLS";
6623
6624 wchar_t string[128];
6625
6626#ifdef __PS3__
6627 int size = 30;
6628#elif defined _WIN64
6629 int size = 45;
6630 if(ui.getScreenHeight() < 1080) size = 30;
6631#else
6632 int size = 45;
6633#endif
6634
6635 swprintf(string,128,L"<img src=\"%ls\" align=\"middle\" height=\"%d\" width=\"%d\"/>", replacement.c_str(), size, size);
6636
6637 return string;
6638#endif
6639}
6640
6641wstring CMinecraftApp::GetVKReplacement(unsigned int uiVKey)
6642{
6643#ifdef _XBOX
6644 switch(uiVKey)
6645 {
6646 case VK_PAD_A:
6647 return app.GetString( IDS_CONTROLLER_A );
6648 case VK_PAD_B:
6649 return app.GetString( IDS_CONTROLLER_B );
6650 case VK_PAD_X:
6651 return app.GetString( IDS_CONTROLLER_X );
6652 case VK_PAD_Y:
6653 return app.GetString( IDS_CONTROLLER_Y );
6654 case VK_PAD_LSHOULDER:
6655 return app.GetString( IDS_CONTROLLER_LEFT_BUMPER );
6656 case VK_PAD_RSHOULDER:
6657 return app.GetString( IDS_CONTROLLER_RIGHT_BUMPER );
6658 case VK_PAD_LTRIGGER:
6659 return app.GetString( IDS_CONTROLLER_LEFT_TRIGGER );
6660 case VK_PAD_RTRIGGER:
6661 return app.GetString( IDS_CONTROLLER_RIGHT_TRIGGER );
6662 case VK_PAD_LTHUMB_UP :
6663 case VK_PAD_LTHUMB_DOWN :
6664 case VK_PAD_LTHUMB_RIGHT :
6665 case VK_PAD_LTHUMB_LEFT :
6666 case VK_PAD_LTHUMB_UPLEFT :
6667 case VK_PAD_LTHUMB_UPRIGHT :
6668 case VK_PAD_LTHUMB_DOWNRIGHT:
6669 case VK_PAD_LTHUMB_DOWNLEFT :
6670 return app.GetString( IDS_CONTROLLER_LEFT_STICK );
6671 case VK_PAD_RTHUMB_UP :
6672 case VK_PAD_RTHUMB_DOWN :
6673 case VK_PAD_RTHUMB_RIGHT :
6674 case VK_PAD_RTHUMB_LEFT :
6675 case VK_PAD_RTHUMB_UPLEFT :
6676 case VK_PAD_RTHUMB_UPRIGHT :
6677 case VK_PAD_RTHUMB_DOWNRIGHT:
6678 case VK_PAD_RTHUMB_DOWNLEFT :
6679 return app.GetString( IDS_CONTROLLER_RIGHT_STICK );
6680 default:
6681 break;
6682 }
6683 return NULL;
6684#else
6685 wstring replacement = L"";
6686 switch(uiVKey)
6687 {
6688 case VK_PAD_A:
6689#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__)
6690 if( InputManager.IsCircleCrossSwapped() ) replacement = L"ButtonB";
6691 else replacement = L"ButtonA";
6692#else
6693 replacement = L"ButtonA";
6694#endif
6695 break;
6696 case VK_PAD_B:
6697#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__)
6698 if( InputManager.IsCircleCrossSwapped() ) replacement = L"ButtonA";
6699 else replacement = L"ButtonB";
6700#else
6701 replacement = L"ButtonB";
6702#endif
6703 break;
6704 case VK_PAD_X:
6705 replacement = L"ButtonX";
6706 break;
6707 case VK_PAD_Y:
6708 replacement = L"ButtonY";
6709 break;
6710 case VK_PAD_LSHOULDER:
6711 replacement = L"ButtonLeftBumper";
6712 break;
6713 case VK_PAD_RSHOULDER:
6714 replacement = L"ButtonRightBumper";
6715 break;
6716 case VK_PAD_LTRIGGER:
6717 replacement = L"ButtonLeftTrigger";
6718 break;
6719 case VK_PAD_RTRIGGER:
6720 replacement = L"ButtonRightTrigger";
6721 break;
6722 case VK_PAD_LTHUMB_UP :
6723 case VK_PAD_LTHUMB_DOWN :
6724 case VK_PAD_LTHUMB_RIGHT :
6725 case VK_PAD_LTHUMB_LEFT :
6726 case VK_PAD_LTHUMB_UPLEFT :
6727 case VK_PAD_LTHUMB_UPRIGHT :
6728 case VK_PAD_LTHUMB_DOWNRIGHT:
6729 case VK_PAD_LTHUMB_DOWNLEFT :
6730 replacement = L"ButtonLeftStick";
6731 break;
6732 case VK_PAD_RTHUMB_UP :
6733 case VK_PAD_RTHUMB_DOWN :
6734 case VK_PAD_RTHUMB_RIGHT :
6735 case VK_PAD_RTHUMB_LEFT :
6736 case VK_PAD_RTHUMB_UPLEFT :
6737 case VK_PAD_RTHUMB_UPRIGHT :
6738 case VK_PAD_RTHUMB_DOWNRIGHT:
6739 case VK_PAD_RTHUMB_DOWNLEFT :
6740 replacement = L"ButtonRightStick";
6741 break;
6742#if defined _XBOX_ONE || defined __PSVITA__
6743 case VK_PAD_START:
6744 replacement = L"ButtonStart";
6745 break;
6746 case VK_PAD_BACK:
6747 replacement = L"ButtonBack";
6748 break;
6749#endif
6750 default:
6751 break;
6752 }
6753 wchar_t string[128];
6754
6755#ifdef __PS3__
6756 int size = 30;
6757#elif defined _WIN64
6758 int size = 45;
6759 if(ui.getScreenHeight() < 1080) size = 30;
6760#else
6761 int size = 45;
6762#endif
6763
6764 swprintf(string,128,L"<img src=\"%ls\" align=\"middle\" height=\"%d\" width=\"%d\"/>", replacement.c_str(), size, size);
6765
6766 return string;
6767#endif
6768}
6769
6770wstring CMinecraftApp::GetIconReplacement(unsigned int uiIcon)
6771{
6772#ifdef _XBOX
6773 switch(uiIcon)
6774 {
6775 case XZP_ICON_SHANK_01:
6776 return app.GetString( IDS_ICON_SHANK_01 );
6777 case XZP_ICON_SHANK_03:
6778 return app.GetString( IDS_ICON_SHANK_03 );
6779 default:
6780 break;
6781 }
6782 return NULL;
6783#else
6784 wchar_t string[128];
6785
6786#ifdef __PS3__
6787 int size = 22;
6788#elif defined _WIN64
6789 int size = 33;
6790 if(ui.getScreenHeight() < 1080) size = 22;
6791#else
6792 int size = 33;
6793#endif
6794
6795 swprintf(string,128,L"<img src=\"Icon_Shank\" align=\"middle\" height=\"%d\" width=\"%d\"/>", size, size);
6796 wstring result = L"";
6797 switch(uiIcon)
6798 {
6799 case XZP_ICON_SHANK_01:
6800 result = string;
6801 break;
6802 case XZP_ICON_SHANK_03:
6803 result.append(string).append(string).append(string);
6804 break;
6805 default:
6806 break;
6807 }
6808 return result;
6809#endif
6810}
6811
6812#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__)
6813unordered_map<PlayerUID, MOJANG_DATA *, PlayerUID::Hash> CMinecraftApp::MojangData;
6814unordered_map<int, char * > CMinecraftApp::DLCTextures_PackID;
6815unordered_map<string, DLC_INFO * > CMinecraftApp::DLCInfo;
6816unordered_map<wstring, ULONGLONG > CMinecraftApp::DLCInfo_SkinName;
6817#elif defined(_DURANGO)
6818unordered_map<PlayerUID,MOJANG_DATA *, PlayerUID::Hash > CMinecraftApp::MojangData;
6819unordered_map<int, wstring > CMinecraftApp::DLCTextures_PackID; // for mash-up packs & texture packs
6820//unordered_map<ULONGLONG,DLC_INFO * > CMinecraftApp::DLCInfo_Trial; // full offerid, dlc_info
6821unordered_map<wstring,DLC_INFO * > CMinecraftApp::DLCInfo_Full; // full offerid, dlc_info
6822unordered_map<wstring, wstring > CMinecraftApp::DLCInfo_SkinName; // skin name, full offer id
6823#else
6824unordered_map<PlayerUID, MOJANG_DATA *> CMinecraftApp::MojangData;
6825unordered_map<int, ULONGLONG > CMinecraftApp::DLCTextures_PackID;
6826unordered_map<ULONGLONG, DLC_INFO * > CMinecraftApp::DLCInfo_Trial;
6827unordered_map<ULONGLONG, DLC_INFO * > CMinecraftApp::DLCInfo_Full;
6828unordered_map<wstring, ULONGLONG > CMinecraftApp::DLCInfo_SkinName;
6829#endif
6830
6831
6832
6833HRESULT CMinecraftApp::RegisterMojangData(WCHAR *pXuidName, PlayerUID xuid, WCHAR *pSkin, WCHAR *pCape)
6834{
6835 HRESULT hr=S_OK;
6836 eXUID eTempXuid=eXUID_Undefined;
6837 MOJANG_DATA *pMojangData=NULL;
6838
6839 // ignore the names if we don't recognize them
6840 if(pXuidName!=NULL)
6841 {
6842 if( wcscmp( pXuidName, L"XUID_NOTCH" ) == 0 )
6843 {
6844 eTempXuid = eXUID_Notch; // might be needed for the apple at some point
6845 }
6846 else if( wcscmp( pXuidName, L"XUID_DEADMAU5" ) == 0 )
6847 {
6848 eTempXuid = eXUID_Deadmau5; // Needed for the deadmau5 ears
6849 }
6850 else
6851 {
6852 eTempXuid=eXUID_NoName;
6853 }
6854 }
6855
6856 if(eTempXuid!=eXUID_Undefined)
6857 {
6858 pMojangData = new MOJANG_DATA;
6859 ZeroMemory(pMojangData,sizeof(MOJANG_DATA));
6860 pMojangData->eXuid=eTempXuid;
6861
6862 wcsncpy( pMojangData->wchSkin, pSkin, MAX_CAPENAME_SIZE);
6863 wcsncpy( pMojangData->wchCape, pCape, MAX_CAPENAME_SIZE);
6864 MojangData[xuid]=pMojangData;
6865 }
6866
6867 return hr;
6868}
6869
6870MOJANG_DATA *CMinecraftApp::GetMojangDataForXuid(PlayerUID xuid)
6871{
6872 return MojangData[xuid];
6873}
6874
6875HRESULT CMinecraftApp::RegisterConfigValues(WCHAR *pType, int iValue)
6876{
6877 HRESULT hr=S_OK;
6878
6879 // #ifdef _XBOX
6880 // if(pType!=NULL)
6881 // {
6882 // if(wcscmp(pType,L"XboxOneTransfer")==0)
6883 // {
6884 // if(iValue>0)
6885 // {
6886 // app.m_bTransferSavesToXboxOne=true;
6887 // }
6888 // else
6889 // {
6890 // app.m_bTransferSavesToXboxOne=false;
6891 // }
6892 // }
6893 // else if(wcscmp(pType,L"TransferSlotCount")==0)
6894 // {
6895 // app.m_uiTransferSlotC=iValue;
6896 // }
6897 //
6898 // }
6899 // #endif
6900
6901
6902 return hr;
6903}
6904
6905#if (defined _XBOX || defined _WINDOWS64)
6906HRESULT CMinecraftApp::RegisterDLCData(WCHAR *pType, WCHAR *pBannerName, int iGender, __uint64 ullOfferID_Full, __uint64 ullOfferID_Trial, WCHAR *pFirstSkin, unsigned int uiSortIndex, int iConfig, WCHAR *pDataFile)
6907{
6908 HRESULT hr=S_OK;
6909 DLC_INFO *pDLCData=new DLC_INFO;
6910 ZeroMemory(pDLCData,sizeof(DLC_INFO));
6911 pDLCData->ullOfferID_Full=ullOfferID_Full;
6912 pDLCData->ullOfferID_Trial=ullOfferID_Trial;
6913 pDLCData->eDLCType=e_DLC_NotDefined;
6914 pDLCData->iGender=iGender;
6915 pDLCData->uiSortIndex=uiSortIndex;
6916 pDLCData->iConfig=iConfig;
6917
6918#ifndef __ORBIS__
6919 // ignore the names if we don't recognize them
6920 if(pBannerName!=L"")
6921 {
6922 wcsncpy_s( pDLCData->wchBanner, pBannerName, MAX_BANNERNAME_SIZE);
6923 }
6924
6925 if(pDataFile[0]!=0)
6926 {
6927 wcsncpy_s( pDLCData->wchDataFile, pDataFile, MAX_BANNERNAME_SIZE);
6928 }
6929#endif
6930
6931 if(pType!=NULL)
6932 {
6933 if(wcscmp(pType,L"Skin")==0)
6934 {
6935 pDLCData->eDLCType=e_DLC_SkinPack;
6936 }
6937 else if(wcscmp(pType,L"Gamerpic")==0)
6938 {
6939 pDLCData->eDLCType=e_DLC_Gamerpics;
6940 }
6941 else if(wcscmp(pType,L"Theme")==0)
6942 {
6943 pDLCData->eDLCType=e_DLC_Themes;
6944 }
6945 else if(wcscmp(pType,L"Avatar")==0)
6946 {
6947 pDLCData->eDLCType=e_DLC_AvatarItems;
6948 }
6949 else if(wcscmp(pType,L"MashUpPack")==0)
6950 {
6951 pDLCData->eDLCType=e_DLC_MashupPacks;
6952 DLCTextures_PackID[pDLCData->iConfig]=ullOfferID_Full;
6953 }
6954 else if(wcscmp(pType,L"TexturePack")==0)
6955 {
6956 pDLCData->eDLCType=e_DLC_TexturePacks;
6957 DLCTextures_PackID[pDLCData->iConfig]=ullOfferID_Full;
6958 }
6959
6960
6961 }
6962
6963 if(ullOfferID_Trial!=0ll) DLCInfo_Trial[ullOfferID_Trial]=pDLCData;
6964 if(ullOfferID_Full!=0ll) DLCInfo_Full[ullOfferID_Full]=pDLCData;
6965 if(pFirstSkin[0]!=0) DLCInfo_SkinName[pFirstSkin]=ullOfferID_Full;
6966
6967 return hr;
6968}
6969#elif defined _XBOX_ONE
6970
6971unordered_map<wstring,DLC_INFO * > *CMinecraftApp::GetDLCInfo()
6972{
6973 return &DLCInfo_Full;
6974}
6975
6976HRESULT CMinecraftApp::RegisterDLCData(eDLCContentType eType, WCHAR *pwchBannerName,WCHAR *pwchProductId, WCHAR *pwchProductName, WCHAR *pwchFirstSkin, int iConfig, unsigned int uiSortIndex)
6977{
6978 HRESULT hr=S_OK;
6979 // 4J-PB - need to convert the product id to uppercase because the catalog calls come back with upper case
6980 WCHAR wchUppercaseProductID[64];
6981 if(pwchProductId[0]!=0)
6982 {
6983 for(int i=0;i<64;i++)
6984 {
6985 wchUppercaseProductID[i]=towupper((wchar_t)pwchProductId[i]);
6986 }
6987 }
6988
6989 // check if we already have this info from the local DLC file
6990 wstring wsTemp=wchUppercaseProductID;
6991
6992 AUTO_VAR(it, DLCInfo_Full.find(wsTemp));
6993 if( it == DLCInfo_Full.end() )
6994 {
6995 // Not found
6996
6997 DLC_INFO *pDLCData=new DLC_INFO;
6998 ZeroMemory(pDLCData,sizeof(DLC_INFO));
6999
7000 pDLCData->eDLCType=e_DLC_NotDefined;
7001 pDLCData->uiSortIndex=uiSortIndex;
7002 pDLCData->iConfig=iConfig;
7003
7004 if(pwchProductId[0]!=0)
7005 {
7006 pDLCData->wsProductId=wchUppercaseProductID;
7007 }
7008
7009 // ignore the names if we don't recognize them
7010 if(pwchBannerName!=L"")
7011 {
7012 wcsncpy_s( pDLCData->wchBanner, pwchBannerName, MAX_BANNERNAME_SIZE);
7013 }
7014
7015 if(pwchProductName[0]!=0)
7016 {
7017 pDLCData->wsDisplayName=pwchProductName;
7018 }
7019
7020 pDLCData->eDLCType=eType;
7021
7022 switch(eType)
7023 {
7024 case e_DLC_MashupPacks:
7025 case e_DLC_TexturePacks:
7026 DLCTextures_PackID[iConfig]=pDLCData->wsProductId;
7027 break;
7028 }
7029
7030 if(pwchFirstSkin[0]!=0) DLCInfo_SkinName[pwchFirstSkin]=pDLCData->wsProductId;
7031
7032#ifdef _XBOX_ONE
7033 // ignore the names, and use the product id instead
7034 DLCInfo_Full[pDLCData->wsProductId]=pDLCData;
7035#else
7036 DLCInfo_Full[pDLCData->wsDisplayName]=pDLCData;
7037#endif
7038 }
7039 app.DebugPrintf("DLCInfo - type - %d, productID - %ls, name - %ls , banner - %ls, iconfig - %d, sort index - %d\n",eType,pwchProductId, pwchProductName,pwchBannerName, iConfig, uiSortIndex);
7040 return hr;
7041}
7042#else
7043
7044HRESULT CMinecraftApp::RegisterDLCData(char *pchDLCName, unsigned int uiSortIndex,char *pchImageURL)
7045{
7046 // on PS3 we get all the required info from the name
7047 char chDLCType[3];
7048 HRESULT hr=S_OK;
7049 DLC_INFO *pDLCData=new DLC_INFO;
7050 ZeroMemory(pDLCData,sizeof(DLC_INFO));
7051
7052 chDLCType[0]=pchDLCName[0];
7053 chDLCType[1]=pchDLCName[1];
7054 chDLCType[2]=0;
7055
7056 pDLCData->iConfig = app.GetiConfigFromName(pchDLCName);
7057 pDLCData->uiSortIndex=uiSortIndex;
7058 pDLCData->eDLCType = app.GetDLCTypeFromName(pchDLCName);
7059 strcpy(pDLCData->chImageURL,pchImageURL);
7060 //bool bIsTrialDLC = app.GetTrialFromName(pchDLCName);
7061
7062 switch(pDLCData->eDLCType)
7063 {
7064 case e_DLC_TexturePacks:
7065 {
7066 char *pchName=(char *)malloc(strlen(pchDLCName)+1);
7067 strcpy(pchName,pchDLCName);
7068 DLCTextures_PackID[pDLCData->iConfig]=pchName;
7069 }
7070 break;
7071 case e_DLC_MashupPacks:
7072 {
7073 char *pchName=(char *)malloc(strlen(pchDLCName)+1);
7074 strcpy(pchName,pchDLCName);
7075 DLCTextures_PackID[pDLCData->iConfig]=pchName;
7076 }
7077 break;
7078 default:
7079 break;
7080 }
7081
7082 app.DebugPrintf(5,"Adding DLC - %s\n",pchDLCName);
7083 DLCInfo[pchDLCName]=pDLCData;
7084
7085 // if(ullOfferID_Trial!=0ll) DLCInfo_Trial[ullOfferID_Trial]=pDLCData;
7086 // if(ullOfferID_Full!=0ll) DLCInfo_Full[ullOfferID_Full]=pDLCData;
7087 // if(pFirstSkin[0]!=0) DLCInfo_SkinName[pFirstSkin]=ullOfferID_Full;
7088
7089 // DLCInfo[ullOfferID_Trial]=pDLCData;
7090
7091 return hr;
7092}
7093#endif
7094
7095
7096
7097#if defined( __PS3__) || defined(__ORBIS__) || defined(__PSVITA__)
7098bool CMinecraftApp::GetDLCFullOfferIDForSkinID(const wstring &FirstSkin,ULONGLONG *pullVal)
7099{
7100 AUTO_VAR(it, DLCInfo_SkinName.find(FirstSkin));
7101 if( it == DLCInfo_SkinName.end() )
7102 {
7103 return false;
7104 }
7105 else
7106 {
7107 *pullVal=(ULONGLONG)it->second;
7108 return true;
7109 }
7110}
7111bool CMinecraftApp::GetDLCNameForPackID(const int iPackID,char **ppchKeyID)
7112{
7113 AUTO_VAR(it, DLCTextures_PackID.find(iPackID));
7114 if( it == DLCTextures_PackID.end() )
7115 {
7116 *ppchKeyID=NULL;
7117 return false;
7118 }
7119 else
7120 {
7121 *ppchKeyID=(char *)it->second;
7122 return true;
7123 }
7124}
7125DLC_INFO *CMinecraftApp::GetDLCInfo(char *pchDLCName)
7126{
7127 string tempString=pchDLCName;
7128
7129 if(DLCInfo.size()>0)
7130 {
7131 AUTO_VAR(it, DLCInfo.find(tempString));
7132
7133 if( it == DLCInfo.end() )
7134 {
7135 // nothing for this
7136 return NULL;
7137 }
7138 else
7139 {
7140 return it->second;
7141 }
7142 }
7143 else return NULL;
7144}
7145
7146DLC_INFO *CMinecraftApp::GetDLCInfoFromTPackID(int iTPID)
7147{
7148 unordered_map<string, DLC_INFO *>::iterator it= DLCInfo.begin();
7149
7150 for(int i=0;i<DLCInfo.size();i++)
7151 {
7152 if(((DLC_INFO *)it->second)->iConfig==iTPID)
7153 {
7154 return it->second;
7155 }
7156 ++it;
7157 }
7158 return NULL;
7159}
7160
7161DLC_INFO *CMinecraftApp::GetDLCInfo(int iIndex)
7162{
7163 unordered_map<string, DLC_INFO *>::iterator it= DLCInfo.begin();
7164
7165 for(int i=0;i<iIndex;i++)
7166 {
7167 ++it;
7168 }
7169
7170 return it->second;
7171}
7172
7173char *CMinecraftApp::GetDLCInfoTextures(int iIndex)
7174{
7175 unordered_map<int, char * >::iterator it= DLCTextures_PackID.begin();
7176
7177 for(int i=0;i<iIndex;i++)
7178 {
7179 ++it;
7180 }
7181
7182 return it->second;
7183}
7184
7185#elif defined _XBOX_ONE
7186bool CMinecraftApp::GetDLCFullOfferIDForSkinID(const wstring &FirstSkin,wstring &ProductId)
7187{
7188 AUTO_VAR(it, DLCInfo_SkinName.find(FirstSkin));
7189 if( it == DLCInfo_SkinName.end() )
7190 {
7191 return false;
7192 }
7193 else
7194 {
7195 ProductId=it->second;
7196 return true;
7197 }
7198}
7199bool CMinecraftApp::GetDLCFullOfferIDForPackID(const int iPackID,wstring &ProductId)
7200{
7201 AUTO_VAR(it, DLCTextures_PackID.find(iPackID));
7202 if( it == DLCTextures_PackID.end() )
7203 {
7204 return false;
7205 }
7206 else
7207 {
7208 ProductId=it->second;
7209 return true;
7210 }
7211}
7212// DLC_INFO *CMinecraftApp::GetDLCInfoForTrialOfferID(wstring &ProductId)
7213// {
7214// return NULL;
7215// }
7216
7217DLC_INFO *CMinecraftApp::GetDLCInfoTrialOffer(int iIndex)
7218{
7219 return NULL;
7220}
7221DLC_INFO *CMinecraftApp::GetDLCInfoFullOffer(int iIndex)
7222{
7223 unordered_map<wstring, DLC_INFO *>::iterator it= DLCInfo_Full.begin();
7224
7225 for(int i=0;i<iIndex;i++)
7226 {
7227 ++it;
7228 }
7229
7230 return it->second;
7231}
7232wstring CMinecraftApp::GetDLCInfoTexturesFullOffer(int iIndex)
7233{
7234 unordered_map<int, wstring >::iterator it= DLCTextures_PackID.begin();
7235
7236 for(int i=0;i<iIndex;i++)
7237 {
7238 ++it;
7239 }
7240
7241 return it->second;
7242}
7243#else
7244bool CMinecraftApp::GetDLCFullOfferIDForSkinID(const wstring &FirstSkin,ULONGLONG *pullVal)
7245{
7246 AUTO_VAR(it, DLCInfo_SkinName.find(FirstSkin));
7247 if( it == DLCInfo_SkinName.end() )
7248 {
7249 return false;
7250 }
7251 else
7252 {
7253 *pullVal=(ULONGLONG)it->second;
7254 return true;
7255 }
7256}
7257bool CMinecraftApp::GetDLCFullOfferIDForPackID(const int iPackID,ULONGLONG *pullVal)
7258{
7259 AUTO_VAR(it, DLCTextures_PackID.find(iPackID));
7260 if( it == DLCTextures_PackID.end() )
7261 {
7262 *pullVal=(ULONGLONG)0;
7263 return false;
7264 }
7265 else
7266 {
7267 *pullVal=(ULONGLONG)it->second;
7268 return true;
7269 }
7270}
7271DLC_INFO *CMinecraftApp::GetDLCInfoForTrialOfferID(ULONGLONG ullOfferID_Trial)
7272{
7273 //DLC_INFO *pDLCInfo=NULL;
7274 if(DLCInfo_Trial.size()>0)
7275 {
7276 AUTO_VAR(it, DLCInfo_Trial.find(ullOfferID_Trial));
7277
7278 if( it == DLCInfo_Trial.end() )
7279 {
7280 // nothing for this
7281 return NULL;
7282 }
7283 else
7284 {
7285 return it->second;
7286 }
7287 }
7288 else return NULL;
7289}
7290
7291DLC_INFO *CMinecraftApp::GetDLCInfoTrialOffer(int iIndex)
7292{
7293 unordered_map<ULONGLONG, DLC_INFO *>::iterator it= DLCInfo_Trial.begin();
7294
7295 for(int i=0;i<iIndex;i++)
7296 {
7297 ++it;
7298 }
7299
7300 return it->second;
7301}
7302DLC_INFO *CMinecraftApp::GetDLCInfoFullOffer(int iIndex)
7303{
7304 unordered_map<ULONGLONG, DLC_INFO *>::iterator it= DLCInfo_Full.begin();
7305
7306 for(int i=0;i<iIndex;i++)
7307 {
7308 ++it;
7309 }
7310
7311 return it->second;
7312}
7313ULONGLONG CMinecraftApp::GetDLCInfoTexturesFullOffer(int iIndex)
7314{
7315 unordered_map<int, ULONGLONG >::iterator it= DLCTextures_PackID.begin();
7316
7317 for(int i=0;i<iIndex;i++)
7318 {
7319 ++it;
7320 }
7321
7322 return it->second;
7323}
7324#endif
7325
7326#ifdef _XBOX_ONE
7327
7328DLC_INFO *CMinecraftApp::GetDLCInfoForFullOfferID(WCHAR *pwchProductID)
7329{
7330 wstring wsTemp = pwchProductID;
7331 if(DLCInfo_Full.size()>0)
7332 {
7333 AUTO_VAR(it, DLCInfo_Full.find(wsTemp));
7334
7335 if( it == DLCInfo_Full.end() )
7336 {
7337 // nothing for this
7338 return NULL;
7339 }
7340 else
7341 {
7342 return it->second;
7343 }
7344 }
7345 else return NULL;
7346}
7347DLC_INFO *CMinecraftApp::GetDLCInfoForProductName(WCHAR *pwchProductName)
7348{
7349 unordered_map<wstring, DLC_INFO *>::iterator it= DLCInfo_Full.begin();
7350 wstring wsProductName=pwchProductName;
7351
7352 for(int i=0;i<DLCInfo_Full.size();i++)
7353 {
7354 DLC_INFO *pDLCInfo=(DLC_INFO *)it->second;
7355 if(wsProductName==pDLCInfo->wsDisplayName)
7356 {
7357 return pDLCInfo;
7358 }
7359 ++it;
7360 }
7361
7362 return NULL;
7363}
7364
7365#elif defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__)
7366#else
7367
7368DLC_INFO *CMinecraftApp::GetDLCInfoForFullOfferID(ULONGLONG ullOfferID_Full)
7369{
7370
7371 if(DLCInfo_Full.size()>0)
7372 {
7373 AUTO_VAR(it, DLCInfo_Full.find(ullOfferID_Full));
7374
7375 if( it == DLCInfo_Full.end() )
7376 {
7377 // nothing for this
7378 return NULL;
7379 }
7380 else
7381 {
7382 return it->second;
7383 }
7384 }
7385 else return NULL;
7386}
7387#endif
7388
7389void CMinecraftApp::EnterSaveNotificationSection()
7390{
7391 EnterCriticalSection(&m_saveNotificationCriticalSection);
7392 if( m_saveNotificationDepth++ == 0 )
7393 {
7394 if(g_NetworkManager.IsInSession()) // this can be triggered from the front end if we're downloading a save
7395 {
7396 MinecraftServer::getInstance()->broadcastStartSavingPacket();
7397
7398 if( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 )
7399 {
7400 app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_PauseServer,(void *)TRUE);
7401 }
7402 }
7403 }
7404 LeaveCriticalSection(&m_saveNotificationCriticalSection);
7405}
7406
7407void CMinecraftApp::LeaveSaveNotificationSection()
7408{
7409 EnterCriticalSection(&m_saveNotificationCriticalSection);
7410 if( --m_saveNotificationDepth == 0 )
7411 {
7412 if(g_NetworkManager.IsInSession()) // this can be triggered from the front end if we're downloading a save
7413 {
7414 MinecraftServer::getInstance()->broadcastStopSavingPacket();
7415
7416 if( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 )
7417 {
7418 app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_PauseServer,(void *)FALSE);
7419 }
7420 }
7421 }
7422 LeaveCriticalSection(&m_saveNotificationCriticalSection);
7423}
7424
7425
7426int CMinecraftApp::RemoteSaveThreadProc( void* lpParameter )
7427{
7428 // The game should be stopped while we are doing this, but the connections ticks may try to create some AABB's or Vec3's
7429 AABB::UseDefaultThreadStorage();
7430 Vec3::UseDefaultThreadStorage();
7431 Compression::UseDefaultThreadStorage();
7432
7433 // 4J-PB - Xbox 360 - 163153 - [CRASH] TU17: Code: Multiplayer: During the Autosave in an online Multiplayer session, the game occasionally crashes for one or more Clients
7434 // callstack - > if(tls->tileId != this->id) updateDefaultShape();
7435 // callstack - > default.exe!WaterlilyTile::getAABB(Level * level, int x, int y, int z) line 38 + 8 bytes C++
7436 // ...
7437 // default.exe!CMinecraftApp::RemoteSaveThreadProc(void * lpParameter) line 6694 C++
7438 // host autosave, and the clients can crash on receiving handleMoveEntity when it's a tile within this thread, so need to do the tls for tiles
7439 Tile::CreateNewThreadStorage();
7440
7441 Minecraft *pMinecraft = Minecraft::GetInstance();
7442
7443 pMinecraft->progressRenderer->progressStartNoAbort( IDS_PROGRESS_HOST_SAVING );
7444 pMinecraft->progressRenderer->progressStage( -1 );
7445 pMinecraft->progressRenderer->progressStagePercentage(0);
7446
7447 while( !app.GetGameStarted() && app.GetXuiAction( ProfileManager.GetPrimaryPad() ) == eAppAction_WaitRemoteServerSaveComplete )
7448 {
7449 // Tick all the games connections
7450 pMinecraft->tickAllConnections();
7451 Sleep( 100 );
7452 }
7453
7454 if( app.GetXuiAction( ProfileManager.GetPrimaryPad() ) != eAppAction_WaitRemoteServerSaveComplete )
7455 {
7456 // Something cancelled us?
7457 return ERROR_CANCELLED;
7458 }
7459 app.SetAction(ProfileManager.GetPrimaryPad(),eAppAction_Idle);
7460
7461 ui.UpdatePlayerBasePositions();
7462
7463 Tile::ReleaseThreadStorage();
7464
7465 return S_OK;
7466}
7467
7468void CMinecraftApp::ExitGameFromRemoteSave( LPVOID lpParameter )
7469{
7470 int primaryPad = ProfileManager.GetPrimaryPad();
7471
7472 UINT uiIDA[3];
7473 uiIDA[0]=IDS_CONFIRM_CANCEL;
7474 uiIDA[1]=IDS_CONFIRM_OK;
7475
7476 ui.RequestAlertMessage(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 2, primaryPad,&CMinecraftApp::ExitGameFromRemoteSaveDialogReturned,NULL);
7477}
7478
7479int CMinecraftApp::ExitGameFromRemoteSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
7480{
7481 //CScene_Pause* pClass = (CScene_Pause*)pParam;
7482
7483 // results switched for this dialog
7484 if(result==C4JStorage::EMessage_ResultDecline)
7485 {
7486 app.SetAction(iPad,eAppAction_ExitWorld);
7487 }
7488 else
7489 {
7490#ifndef _XBOX
7491 // Inform fullscreen progress scene that it's not being cancelled after all
7492 UIScene_FullscreenProgress *pScene = (UIScene_FullscreenProgress *)ui.FindScene(eUIScene_FullscreenProgress);
7493#ifdef __PS3__
7494 if(pScene!=NULL)
7495#else
7496 if (pScene != nullptr)
7497#endif
7498 {
7499 pScene->SetWasCancelled(false);
7500 }
7501#else
7502 // Don't have to worry about this on Xbox
7503#endif
7504 }
7505 return 0;
7506}
7507
7508void CMinecraftApp::SetSpecialTutorialCompletionFlag(int iPad, int index)
7509{
7510 if(index >= 0 && index < 32 && GameSettingsA[iPad] != NULL)
7511 {
7512 GameSettingsA[iPad]->uiSpecialTutorialBitmask |= (1<<index);
7513 }
7514}
7515
7516// BANNED LIST FUNCTIONS
7517
7518void CMinecraftApp::SetUniqueMapName(char *pszUniqueMapName)
7519{
7520 memcpy(m_pszUniqueMapName,pszUniqueMapName,14);
7521}
7522
7523char *CMinecraftApp::GetUniqueMapName(void)
7524{
7525 return m_pszUniqueMapName;
7526}
7527
7528void CMinecraftApp::InvalidateBannedList(int iPad)
7529{
7530 if(m_bRead_BannedListA[iPad]==true)
7531 {
7532 m_bRead_BannedListA[iPad]=false;
7533 SetBanListCheck(iPad,false);
7534 m_vBannedListA[iPad]->clear();
7535
7536 if(BannedListA[iPad].pBannedList)
7537 {
7538 delete [] BannedListA[iPad].pBannedList;
7539 BannedListA[iPad].pBannedList=NULL;
7540 }
7541 }
7542}
7543
7544#ifdef _XBOX_ONE
7545void CMinecraftApp::AddLevelToBannedLevelList(int iPad, PBANNEDLISTDATA pBannedListData, bool bWriteToTMS)
7546{
7547 PlayerUID xuid= pBannedListData->wchPlayerUID;
7548
7549 AddLevelToBannedLevelList(iPad,xuid,pBannedListData->pszLevelName,bWriteToTMS);
7550}
7551#endif
7552
7553void CMinecraftApp::AddLevelToBannedLevelList(int iPad, PlayerUID xuid, char *pszLevelName, bool bWriteToTMS)
7554{
7555 // we will have retrieved the banned level list from TMS, so add this one to it and write it back to TMS
7556
7557 BANNEDLISTDATA *pBannedListData = new BANNEDLISTDATA;
7558 memset(pBannedListData,0,sizeof(BANNEDLISTDATA));
7559
7560#ifdef _DURANGO
7561 memcpy(&pBannedListData->wchPlayerUID, xuid.toString().c_str(), sizeof(WCHAR)*64);
7562#else
7563 memcpy(&pBannedListData->xuid, &xuid, sizeof(PlayerUID));
7564#endif
7565 strcpy(pBannedListData->pszLevelName,pszLevelName);
7566 m_vBannedListA[iPad]->push_back(pBannedListData);
7567
7568 if(bWriteToTMS)
7569 {
7570 DWORD dwDataBytes=(DWORD)(sizeof(BANNEDLISTDATA)*m_vBannedListA[iPad]->size());
7571 PBANNEDLISTDATA pBannedList = (BANNEDLISTDATA *)(new CHAR [dwDataBytes]);
7572 int iCount=0;
7573 for(AUTO_VAR(it, m_vBannedListA[iPad]->begin()); it != m_vBannedListA[iPad]->end(); ++it)
7574 {
7575 PBANNEDLISTDATA pData=*it;
7576 memcpy(&pBannedList[iCount++],pData,sizeof(BANNEDLISTDATA));
7577 }
7578
7579 // 4J-PB - write to TMS++ now
7580
7581 //bool bRes=StorageManager.WriteTMSFile(iPad,C4JStorage::eGlobalStorage_TitleUser,L"BannedList",(PBYTE)pBannedList, dwDataBytes);
7582#ifdef _XBOX
7583 StorageManager.TMSPP_WriteFile(iPad,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,C4JStorage::TMS_UGCTYPE_NONE,"BannedList",(PCHAR) pBannedList, dwDataBytes,NULL,NULL, 0);
7584#elif defined _XBOX_ONE
7585 StorageManager.TMSPP_WriteFile(iPad,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,L"BannedList",(PBYTE) pBannedList, dwDataBytes,NULL,NULL, 0);
7586#endif
7587 }
7588 // update telemetry too
7589}
7590
7591bool CMinecraftApp::IsInBannedLevelList(int iPad, PlayerUID xuid, char *pszLevelName)
7592{
7593 for(AUTO_VAR(it, m_vBannedListA[iPad]->begin()); it != m_vBannedListA[iPad]->end(); ++it)
7594 {
7595 PBANNEDLISTDATA pData=*it;
7596#ifdef _XBOX_ONE
7597 PlayerUID bannedPlayerUID = pData->wchPlayerUID;
7598 if(IsEqualXUID (bannedPlayerUID,xuid) && (strcmp(pData->pszLevelName,pszLevelName)==0))
7599#else
7600 if(IsEqualXUID (pData->xuid,xuid) && (strcmp(pData->pszLevelName,pszLevelName)==0))
7601#endif
7602 {
7603 return true;
7604 }
7605 }
7606
7607 return false;
7608}
7609
7610void CMinecraftApp::RemoveLevelFromBannedLevelList(int iPad, PlayerUID xuid, char *pszLevelName)
7611{
7612 //bool bFound=false;
7613 //bool bRes;
7614
7615 // we will have retrieved the banned level list from TMS, so remove this one from it and write it back to TMS
7616 for(AUTO_VAR(it, m_vBannedListA[iPad]->begin()); it != m_vBannedListA[iPad]->end(); )
7617 {
7618 PBANNEDLISTDATA pBannedListData = *it;
7619
7620 if(pBannedListData!=NULL)
7621 {
7622#ifdef _XBOX_ONE
7623 PlayerUID bannedPlayerUID = pBannedListData->wchPlayerUID;
7624 if(IsEqualXUID (bannedPlayerUID,xuid) && (strcmp(pBannedListData->pszLevelName,pszLevelName)==0))
7625#else
7626 if(IsEqualXUID (pBannedListData->xuid,xuid) && (strcmp(pBannedListData->pszLevelName,pszLevelName)==0))
7627#endif
7628 {
7629 TelemetryManager->RecordUnBanLevel(iPad);
7630
7631 // match found, so remove this entry
7632 it = m_vBannedListA[iPad]->erase(it);
7633 }
7634 else
7635 {
7636 ++it;
7637 }
7638 }
7639 else
7640 {
7641 ++it;
7642 }
7643 }
7644
7645 DWORD dwDataBytes=(DWORD)(sizeof(BANNEDLISTDATA)*m_vBannedListA[iPad]->size());
7646 if(dwDataBytes==0)
7647 {
7648 // wipe the file
7649#ifdef _XBOX
7650 StorageManager.DeleteTMSFile(iPad,C4JStorage::eGlobalStorage_TitleUser,L"BannedList");
7651#elif defined _XBOX_ONE
7652 StorageManager.TMSPP_DeleteFile(iPad,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,L"BannedList",NULL,NULL, 0);
7653#endif
7654 }
7655 else
7656 {
7657 PBANNEDLISTDATA pBannedList = (BANNEDLISTDATA *)(new BYTE [dwDataBytes]);
7658
7659 int iSize=(int)m_vBannedListA[iPad]->size();
7660 for(int i=0;i<iSize;i++)
7661 {
7662 PBANNEDLISTDATA pBannedListData =m_vBannedListA[iPad]->at(i);
7663
7664 memcpy(&pBannedList[i],pBannedListData,sizeof(BANNEDLISTDATA));
7665 }
7666#ifdef _XBOX
7667 StorageManager.WriteTMSFile(iPad,C4JStorage::eGlobalStorage_TitleUser,L"BannedList",(PBYTE)pBannedList, dwDataBytes);
7668#elif defined _XBOX_ONE
7669 StorageManager.TMSPP_WriteFile(iPad,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,L"BannedList",(PBYTE) pBannedList, dwDataBytes,NULL,NULL, 0);
7670#endif
7671 delete [] pBannedList;
7672 }
7673
7674 // update telemetry too
7675}
7676
7677// function to add credits for the DLC packs
7678void CMinecraftApp::AddCreditText(LPCWSTR lpStr)
7679{
7680 DebugPrintf("ADDING CREDIT - %ls\n",lpStr);
7681 // add a string from the DLC to a credits vector
7682 SCreditTextItemDef *pCreditStruct = new SCreditTextItemDef;
7683 pCreditStruct->m_eType=eSmallText;
7684 pCreditStruct->m_iStringID[0]=NO_TRANSLATED_STRING;
7685 pCreditStruct->m_iStringID[1]=NO_TRANSLATED_STRING;
7686 pCreditStruct->m_Text=new WCHAR [wcslen(lpStr)+1];
7687 wcscpy((WCHAR *)pCreditStruct->m_Text,lpStr);
7688
7689 vDLCCredits.push_back(pCreditStruct);
7690}
7691
7692bool CMinecraftApp::AlreadySeenCreditText(const wstring &wstemp)
7693{
7694
7695 for(unsigned int i=0;i<m_vCreditText.size();i++)
7696 {
7697 wstring temp=m_vCreditText.at(i);
7698
7699 // if they are the same, break out of the case
7700 if(temp.compare(wstemp)==0)
7701 {
7702 return true;
7703 }
7704 }
7705
7706 // add this text
7707 m_vCreditText.push_back((WCHAR * )wstemp.c_str());
7708 return false;
7709}
7710
7711unsigned int CMinecraftApp::GetDLCCreditsCount()
7712{
7713 return (unsigned int)vDLCCredits.size();
7714}
7715
7716SCreditTextItemDef * CMinecraftApp::GetDLCCredits(int iIndex)
7717{
7718 return vDLCCredits.at(iIndex);
7719}
7720
7721// Game Host options
7722
7723void CMinecraftApp::SetGameHostOption(eGameHostOption eVal,unsigned int uiVal)
7724{
7725 SetGameHostOption(m_uiGameHostSettings,eVal,uiVal);
7726}
7727
7728
7729void CMinecraftApp::SetGameHostOption(unsigned int &uiHostSettings, eGameHostOption eVal, unsigned int uiVal)
7730{
7731 switch(eVal)
7732 {
7733 case eGameHostOption_FriendsOfFriends:
7734 if(uiVal!=0)
7735 {
7736 uiHostSettings|=GAME_HOST_OPTION_BITMASK_FRIENDSOFFRIENDS;
7737 }
7738 else
7739 {
7740 // off
7741 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_FRIENDSOFFRIENDS;
7742 }
7743 break;
7744 case eGameHostOption_Difficulty:
7745 // clear the difficulty first
7746 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_DIFFICULTY;
7747 uiHostSettings|=(GAME_HOST_OPTION_BITMASK_DIFFICULTY&uiVal);
7748 break;
7749 case eGameHostOption_Gamertags:
7750 if(uiVal!=0)
7751 {
7752 uiHostSettings|=GAME_HOST_OPTION_BITMASK_GAMERTAGS;
7753 }
7754 else
7755 {
7756 // off
7757 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_GAMERTAGS;
7758 }
7759
7760 break;
7761 case eGameHostOption_GameType:
7762 // clear the game type first
7763 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_GAMETYPE;
7764 uiHostSettings|=(GAME_HOST_OPTION_BITMASK_GAMETYPE&(uiVal<<4));
7765 break;
7766 case eGameHostOption_LevelType:
7767 if(uiVal!=0)
7768 {
7769 uiHostSettings|=GAME_HOST_OPTION_BITMASK_LEVELTYPE;
7770 }
7771 else
7772 {
7773 // off
7774 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_LEVELTYPE;
7775 }
7776
7777 break;
7778 case eGameHostOption_Structures:
7779 if(uiVal!=0)
7780 {
7781 uiHostSettings|=GAME_HOST_OPTION_BITMASK_STRUCTURES;
7782 }
7783 else
7784 {
7785 // off
7786 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_STRUCTURES;
7787 }
7788
7789 break;
7790 case eGameHostOption_BonusChest:
7791 if(uiVal!=0)
7792 {
7793 uiHostSettings|=GAME_HOST_OPTION_BITMASK_BONUSCHEST;
7794 }
7795 else
7796 {
7797 // off
7798 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_BONUSCHEST;
7799 }
7800
7801 break;
7802 case eGameHostOption_HasBeenInCreative:
7803 if(uiVal!=0)
7804 {
7805 uiHostSettings|=GAME_HOST_OPTION_BITMASK_BEENINCREATIVE;
7806 }
7807 else
7808 {
7809 // off
7810 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_BEENINCREATIVE;
7811 }
7812
7813 break;
7814 case eGameHostOption_PvP:
7815 if(uiVal!=0)
7816 {
7817 uiHostSettings|=GAME_HOST_OPTION_BITMASK_PVP;
7818 }
7819 else
7820 {
7821 // off
7822 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_PVP;
7823 }
7824
7825 break;
7826 case eGameHostOption_TrustPlayers:
7827 if(uiVal!=0)
7828 {
7829 uiHostSettings|=GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS;
7830 }
7831 else
7832 {
7833 // off
7834 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS;
7835 }
7836
7837 break;
7838 case eGameHostOption_TNT:
7839 if(uiVal!=0)
7840 {
7841 uiHostSettings|=GAME_HOST_OPTION_BITMASK_TNT;
7842 }
7843 else
7844 {
7845 // off
7846 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_TNT;
7847 }
7848
7849 break;
7850 case eGameHostOption_FireSpreads:
7851 if(uiVal!=0)
7852 {
7853 uiHostSettings|=GAME_HOST_OPTION_BITMASK_FIRESPREADS;
7854 }
7855 else
7856 {
7857 // off
7858 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_FIRESPREADS;
7859 }
7860 break;
7861 case eGameHostOption_CheatsEnabled:
7862 if(uiVal!=0)
7863 {
7864 uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTFLY;
7865 uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTHUNGER;
7866 uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE;
7867 }
7868 else
7869 {
7870 // off
7871 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTFLY;
7872 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTHUNGER;
7873 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE;
7874 }
7875 break;
7876 case eGameHostOption_HostCanFly:
7877 if(uiVal!=0)
7878 {
7879 uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTFLY;
7880 }
7881 else
7882 {
7883 // off
7884 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTFLY;
7885 }
7886 break;
7887 case eGameHostOption_HostCanChangeHunger:
7888 if(uiVal!=0)
7889 {
7890 uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTHUNGER;
7891 }
7892 else
7893 {
7894 // off
7895 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTHUNGER;
7896 }
7897 break;
7898 case eGameHostOption_HostCanBeInvisible:
7899 if(uiVal!=0)
7900 {
7901 uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE;
7902 }
7903 else
7904 {
7905 // off
7906 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE;
7907 }
7908 break;
7909
7910 case eGameHostOption_BedrockFog:
7911 if(uiVal!=0)
7912 {
7913 uiHostSettings|=GAME_HOST_OPTION_BITMASK_BEDROCKFOG;
7914 }
7915 else
7916 {
7917 // off
7918 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_BEDROCKFOG;
7919 }
7920 break;
7921 case eGameHostOption_DisableSaving:
7922 if(uiVal!=0)
7923 {
7924 uiHostSettings|=GAME_HOST_OPTION_BITMASK_DISABLESAVE;
7925 }
7926 else
7927 {
7928 // off
7929 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_DISABLESAVE;
7930 }
7931 break;
7932 case eGameHostOption_WasntSaveOwner:
7933 if(uiVal!=0)
7934 {
7935 uiHostSettings|=GAME_HOST_OPTION_BITMASK_NOTOWNER;
7936 }
7937 else
7938 {
7939 // off
7940 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_NOTOWNER;
7941 }
7942 break;
7943 case eGameHostOption_MobGriefing:
7944 if(uiVal!=1)
7945 {
7946 uiHostSettings |= GAME_HOST_OPTION_BITMASK_MOBGRIEFING;
7947 }
7948 else
7949 {
7950 // off
7951 uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_MOBGRIEFING;
7952 }
7953 break;
7954 case eGameHostOption_KeepInventory:
7955 if(uiVal!=0)
7956 {
7957 uiHostSettings |= GAME_HOST_OPTION_BITMASK_KEEPINVENTORY;
7958 }
7959 else
7960 {
7961 // off
7962 uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_KEEPINVENTORY;
7963 }
7964 break;
7965 case eGameHostOption_DoMobSpawning:
7966 if(uiVal!=1)
7967 {
7968 uiHostSettings |= GAME_HOST_OPTION_BITMASK_DOMOBSPAWNING;
7969 }
7970 else
7971 {
7972 // off
7973 uiHostSettings &=~ GAME_HOST_OPTION_BITMASK_DOMOBSPAWNING;
7974 }
7975 break;
7976 case eGameHostOption_DoMobLoot:
7977 if(uiVal!=1)
7978 {
7979 uiHostSettings |= GAME_HOST_OPTION_BITMASK_DOMOBLOOT;
7980 }
7981 else
7982 {
7983 // off
7984 uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DOMOBLOOT;
7985 }
7986 break;
7987 case eGameHostOption_DoTileDrops:
7988 if(uiVal!=1)
7989 {
7990 uiHostSettings |= GAME_HOST_OPTION_BITMASK_DOTILEDROPS;
7991 }
7992 else
7993 {
7994 // off
7995 uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DOTILEDROPS;
7996 }
7997 break;
7998 case eGameHostOption_NaturalRegeneration:
7999 if(uiVal!=1)
8000 {
8001 uiHostSettings |= GAME_HOST_OPTION_BITMASK_NATURALREGEN;
8002 }
8003 else
8004 {
8005 // off
8006 uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_NATURALREGEN;
8007 }
8008 break;
8009 case eGameHostOption_DoDaylightCycle:
8010 if(uiVal!=1)
8011 {
8012 uiHostSettings |= GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE;
8013 }
8014 else
8015 {
8016 // off
8017 uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE;
8018 }
8019 break;
8020 case eGameHostOption_WorldSize:
8021 // clear the difficulty first
8022 uiHostSettings&=~GAME_HOST_OPTION_BITMASK_WORLDSIZE;
8023 uiHostSettings|=(GAME_HOST_OPTION_BITMASK_WORLDSIZE & (uiVal<<GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT));
8024 break;
8025 case eGameHostOption_All:
8026 uiHostSettings=uiVal;
8027 break;
8028 }
8029}
8030
8031unsigned int CMinecraftApp::GetGameHostOption(eGameHostOption eVal)
8032{
8033 return GetGameHostOption(m_uiGameHostSettings, eVal);
8034}
8035
8036unsigned int CMinecraftApp::GetGameHostOption(unsigned int uiHostSettings, eGameHostOption eVal)
8037{
8038 //unsigned int uiVal=0;
8039 switch(eVal)
8040 {
8041 case eGameHostOption_FriendsOfFriends:
8042 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_FRIENDSOFFRIENDS);
8043 break;
8044 case eGameHostOption_Difficulty:
8045 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_DIFFICULTY);
8046 break;
8047 case eGameHostOption_Gamertags:
8048 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_GAMERTAGS);
8049 break;
8050 case eGameHostOption_GameType:
8051 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_GAMETYPE)>>4;
8052 break;
8053 case eGameHostOption_All:
8054 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_ALL);
8055 break;
8056 case eGameHostOption_Tutorial:
8057 // special case - tutorial is offline, but we want the gamertag option, and set Easy mode, structures on, fire on, tnt on, pvp on, trust players on
8058 return ((uiHostSettings&GAME_HOST_OPTION_BITMASK_GAMERTAGS)|
8059 GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS|
8060 GAME_HOST_OPTION_BITMASK_FIRESPREADS|
8061 GAME_HOST_OPTION_BITMASK_TNT|
8062 GAME_HOST_OPTION_BITMASK_PVP|
8063 GAME_HOST_OPTION_BITMASK_STRUCTURES|1);
8064 break;
8065 case eGameHostOption_LevelType:
8066 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_LEVELTYPE);
8067 break;
8068 case eGameHostOption_Structures:
8069 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_STRUCTURES);
8070 break;
8071 case eGameHostOption_BonusChest:
8072 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_BONUSCHEST);
8073 break;
8074 case eGameHostOption_HasBeenInCreative:
8075 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_BEENINCREATIVE);
8076 break;
8077 case eGameHostOption_PvP:
8078 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_PVP);
8079 break;
8080 case eGameHostOption_TrustPlayers:
8081 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS);
8082 break;
8083 case eGameHostOption_TNT:
8084 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_TNT);
8085 break;
8086 case eGameHostOption_FireSpreads:
8087 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_FIRESPREADS);
8088 break;
8089 case eGameHostOption_CheatsEnabled:
8090 return (uiHostSettings&(GAME_HOST_OPTION_BITMASK_HOSTFLY|GAME_HOST_OPTION_BITMASK_HOSTHUNGER|GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE));
8091 break;
8092 case eGameHostOption_HostCanFly:
8093 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_HOSTFLY);
8094 break;
8095 case eGameHostOption_HostCanChangeHunger:
8096 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_HOSTHUNGER);
8097 break;
8098 case eGameHostOption_HostCanBeInvisible:
8099 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE);
8100 break;
8101 case eGameHostOption_BedrockFog:
8102 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_BEDROCKFOG);
8103 break;
8104 case eGameHostOption_DisableSaving:
8105 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_DISABLESAVE);
8106 break;
8107 case eGameHostOption_WasntSaveOwner:
8108 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_NOTOWNER);
8109 case eGameHostOption_WorldSize:
8110 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_WORLDSIZE) >> GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT;
8111 case eGameHostOption_MobGriefing:
8112 return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_MOBGRIEFING);
8113 case eGameHostOption_KeepInventory:
8114 return (uiHostSettings&GAME_HOST_OPTION_BITMASK_KEEPINVENTORY);
8115 case eGameHostOption_DoMobSpawning:
8116 return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DOMOBSPAWNING);
8117 case eGameHostOption_DoMobLoot:
8118 return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DOMOBLOOT);
8119 case eGameHostOption_DoTileDrops:
8120 return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DOTILEDROPS);
8121 case eGameHostOption_NaturalRegeneration:
8122 return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_NATURALREGEN);
8123 case eGameHostOption_DoDaylightCycle:
8124 return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE);
8125 break;
8126 }
8127
8128 return false;
8129}
8130
8131bool CMinecraftApp::CanRecordStatsAndAchievements()
8132{
8133 bool isTutorial = Minecraft::GetInstance() != NULL && Minecraft::GetInstance()->isTutorial();
8134 // 4J Stu - All of these options give the host player some advantage, so should not allow achievements
8135 return !(app.GetGameHostOption(eGameHostOption_HasBeenInCreative) ||
8136 app.GetGameHostOption(eGameHostOption_HostCanBeInvisible) ||
8137 app.GetGameHostOption(eGameHostOption_HostCanChangeHunger) ||
8138 app.GetGameHostOption(eGameHostOption_HostCanFly) ||
8139 app.GetGameHostOption(eGameHostOption_WasntSaveOwner) ||
8140 !app.GetGameHostOption(eGameHostOption_MobGriefing) ||
8141 app.GetGameHostOption(eGameHostOption_KeepInventory) ||
8142 !app.GetGameHostOption(eGameHostOption_DoMobSpawning) ||
8143 (!app.GetGameHostOption(eGameHostOption_DoDaylightCycle) && !isTutorial )
8144 );
8145}
8146
8147void CMinecraftApp::processSchematics(LevelChunk *levelChunk)
8148{
8149 m_gameRules.processSchematics(levelChunk);
8150}
8151
8152void CMinecraftApp::processSchematicsLighting(LevelChunk *levelChunk)
8153{
8154 m_gameRules.processSchematicsLighting(levelChunk);
8155}
8156
8157void CMinecraftApp::loadDefaultGameRules()
8158{
8159 m_gameRules.loadDefaultGameRules();
8160}
8161
8162void CMinecraftApp::setLevelGenerationOptions(LevelGenerationOptions *levelGen)
8163{
8164 m_gameRules.setLevelGenerationOptions(levelGen);
8165}
8166
8167LPCWSTR CMinecraftApp::GetGameRulesString(const wstring &key)
8168{
8169 return m_gameRules.GetGameRulesString(key);
8170}
8171
8172unsigned char CMinecraftApp::m_szPNG[8]=
8173{
8174 137,80,78,71,13,10,26,10
8175};
8176
8177#define PNG_TAG_tEXt 0x74455874
8178
8179unsigned int CMinecraftApp::FromBigEndian(unsigned int uiValue)
8180{
8181#if defined(__PS3__) || defined(_XBOX)
8182 // Keep it in big endian
8183 return uiValue;
8184#else
8185 unsigned int uiReturn = ( ( uiValue >> 24 ) & 0x000000ff ) |
8186 ( ( uiValue >> 8 ) & 0x0000ff00 ) |
8187 ( ( uiValue << 8 ) & 0x00ff0000 ) |
8188 ( ( uiValue << 24 ) & 0xff000000 );
8189 return uiReturn;
8190#endif
8191}
8192
8193void CMinecraftApp::GetImageTextData(PBYTE pbImageData, DWORD dwImageBytes,unsigned char *pszSeed,unsigned int &uiHostOptions,bool &bHostOptionsRead,DWORD &uiTexturePack)
8194{
8195 unsigned char *ucPtr=pbImageData;
8196 unsigned int uiCount=0;
8197 unsigned int uiChunkLen;
8198 unsigned int uiChunkType;
8199 unsigned int uiCRC;
8200 char szKeyword[80];
8201
8202 // check it's a png
8203 for(int i=0;i<8;i++)
8204 {
8205 if(m_szPNG[i]!=ucPtr[i]) return;
8206 }
8207
8208 uiCount+=8;
8209
8210 while(uiCount<dwImageBytes)
8211 {
8212 uiChunkLen=*(unsigned int *)&ucPtr[uiCount];
8213 uiChunkLen=FromBigEndian(uiChunkLen);
8214 uiCount+=sizeof(int);
8215 uiChunkType=*(unsigned int *)&ucPtr[uiCount];
8216 uiChunkType=FromBigEndian(uiChunkType);
8217 uiCount+=sizeof(int);
8218
8219 if(uiChunkType==PNG_TAG_tEXt) // tEXt
8220 {
8221 // check that it's the 4J text
8222 unsigned char *pszKeyword=&ucPtr[uiCount];
8223 while(pszKeyword < ucPtr + uiCount + uiChunkLen)
8224 {
8225 ZeroMemory(szKeyword,80);
8226 unsigned int uiKeywordC=0;
8227 while(*pszKeyword!=0)
8228 {
8229 szKeyword[uiKeywordC++]=*pszKeyword;
8230 pszKeyword++;
8231 }
8232 pszKeyword++;
8233 if(strcmp(szKeyword,"4J_SEED")==0)
8234 {
8235 // read the seed value
8236 unsigned int uiValueC=0;
8237 while(*pszKeyword!=0 && (pszKeyword < ucPtr + uiCount + uiChunkLen) )
8238 {
8239 pszSeed[uiValueC++]=*pszKeyword;
8240 pszKeyword++;
8241 }
8242 //memcpy(pszSeed,pszKeyword,uiChunkLen-8);
8243 }
8244 else if(strcmp(szKeyword,"4J_HOSTOPTIONS")==0)
8245 {
8246 bHostOptionsRead = true;
8247 // read the host options value
8248 unsigned int uiValueC=0;
8249 unsigned char pszHostOptions[9]; // Hex representation of unsigned int
8250 ZeroMemory(&pszHostOptions,9);
8251 while(*pszKeyword!=0 && (pszKeyword < ucPtr + uiCount + uiChunkLen) && uiValueC < 8)
8252 {
8253 pszHostOptions[uiValueC++]=*pszKeyword;
8254 pszKeyword++;
8255 }
8256
8257 uiHostOptions = 0;
8258 std::stringstream ss;
8259 ss << pszHostOptions;
8260 ss >> std::hex >> uiHostOptions;
8261 }
8262 else if(strcmp(szKeyword,"4J_TEXTUREPACK")==0)
8263 {
8264 // read the texture pack value
8265 unsigned int uiValueC=0;
8266 unsigned char pszTexturePack[9]; // Hex representation of unsigned int
8267 ZeroMemory(&pszTexturePack,9);
8268 while(*pszKeyword!=0 && (pszKeyword < ucPtr + uiCount + uiChunkLen) && uiValueC < 8)
8269 {
8270 pszTexturePack[uiValueC++]=*pszKeyword;
8271 pszKeyword++;
8272 }
8273
8274 std::stringstream ss;
8275 ss << pszTexturePack;
8276 ss >> std::hex >> uiTexturePack;
8277 }
8278 }
8279 }
8280 uiCount+=uiChunkLen;
8281 uiCRC=*(unsigned int*)&ucPtr[uiCount];
8282 uiCRC=FromBigEndian(uiCRC);
8283 uiCount+=sizeof(int);
8284 }
8285
8286 return;
8287}
8288
8289unsigned int CMinecraftApp::CreateImageTextData(PBYTE bTextMetadata, __int64 seed, bool hasSeed, unsigned int uiHostOptions, unsigned int uiTexturePackId)
8290{
8291 int iTextMetadataBytes = 0;
8292 if(hasSeed)
8293 {
8294 strcpy((char *)bTextMetadata,"4J_SEED");
8295 _i64toa_s(seed,(char *)&bTextMetadata[8],42,10);
8296
8297 // get the length
8298 iTextMetadataBytes+=8;
8299 while(bTextMetadata[iTextMetadataBytes]!=0) iTextMetadataBytes++;
8300 ++iTextMetadataBytes; // Add a null terminator at the end of the seed value
8301 }
8302
8303 // Save the host options that this world was last played with
8304 strcpy((char *)&bTextMetadata[iTextMetadataBytes],"4J_HOSTOPTIONS");
8305 _itoa_s(uiHostOptions,(char *)&bTextMetadata[iTextMetadataBytes+15],9,16);
8306
8307 iTextMetadataBytes += 15;
8308 while(bTextMetadata[iTextMetadataBytes]!=0) iTextMetadataBytes++;
8309 ++iTextMetadataBytes; // Add a null terminator at the end of the host options value
8310
8311 // Save the texture pack id
8312 strcpy((char *)&bTextMetadata[iTextMetadataBytes],"4J_TEXTUREPACK");
8313 _itoa_s(uiTexturePackId,(char *)&bTextMetadata[iTextMetadataBytes+15],9,16);
8314
8315 iTextMetadataBytes += 15;
8316 while(bTextMetadata[iTextMetadataBytes]!=0) iTextMetadataBytes++;
8317
8318 return iTextMetadataBytes;
8319}
8320
8321void CMinecraftApp::AddTerrainFeaturePosition(_eTerrainFeatureType eFeatureType,int x,int z)
8322{
8323 // check we don't already have this in
8324 for(AUTO_VAR(it, m_vTerrainFeatures.begin()); it < m_vTerrainFeatures.end(); ++it)
8325 {
8326 FEATURE_DATA *pFeatureData=*it;
8327
8328 if((pFeatureData->eTerrainFeature==eFeatureType) &&(pFeatureData->x==x) && (pFeatureData->z==z)) return;
8329 }
8330
8331 FEATURE_DATA *pFeatureData= new FEATURE_DATA;
8332 pFeatureData->eTerrainFeature=eFeatureType;
8333 pFeatureData->x=x;
8334 pFeatureData->z=z;
8335
8336 m_vTerrainFeatures.push_back(pFeatureData);
8337}
8338
8339_eTerrainFeatureType CMinecraftApp::IsTerrainFeature(int x,int z)
8340{
8341 for(AUTO_VAR(it, m_vTerrainFeatures.begin()); it < m_vTerrainFeatures.end(); ++it)
8342 {
8343 FEATURE_DATA *pFeatureData=*it;
8344
8345 if((pFeatureData->x==x) && (pFeatureData->z==z)) return pFeatureData->eTerrainFeature;
8346 }
8347
8348 return eTerrainFeature_None;
8349}
8350
8351bool CMinecraftApp::GetTerrainFeaturePosition(_eTerrainFeatureType eType,int *pX, int *pZ)
8352{
8353 for(AUTO_VAR(it, m_vTerrainFeatures.begin()); it < m_vTerrainFeatures.end(); ++it)
8354 {
8355 FEATURE_DATA *pFeatureData=*it;
8356
8357 if(pFeatureData->eTerrainFeature==eType)
8358 {
8359 *pX=pFeatureData->x;
8360 *pZ=pFeatureData->z;
8361 return true;
8362 }
8363 }
8364
8365 return false;
8366}
8367
8368void CMinecraftApp::ClearTerrainFeaturePosition()
8369{
8370 FEATURE_DATA *pFeatureData;
8371 while(m_vTerrainFeatures.size()>0)
8372 {
8373 pFeatureData = m_vTerrainFeatures.back();
8374 m_vTerrainFeatures.pop_back();
8375 delete pFeatureData;
8376 }
8377}
8378
8379void CMinecraftApp::UpdatePlayerInfo(BYTE networkSmallId, SHORT playerColourIndex, unsigned int playerGamePrivileges)
8380{
8381 for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i)
8382 {
8383 if(m_playerColours[i]==networkSmallId)
8384 {
8385 m_playerColours[i] = 0;
8386 m_playerGamePrivileges[i] = 0;
8387 }
8388 }
8389 if(playerColourIndex >=0 && playerColourIndex < MINECRAFT_NET_MAX_PLAYERS)
8390 {
8391 m_playerColours[playerColourIndex] = networkSmallId;
8392 m_playerGamePrivileges[playerColourIndex] = playerGamePrivileges;
8393 }
8394}
8395
8396short CMinecraftApp::GetPlayerColour(BYTE networkSmallId)
8397{
8398 short index = -1;
8399 for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i)
8400 {
8401 if(m_playerColours[i]==networkSmallId)
8402 {
8403 index = i;
8404 break;
8405 }
8406 }
8407 return index;
8408}
8409
8410
8411unsigned int CMinecraftApp::GetPlayerPrivileges(BYTE networkSmallId)
8412{
8413 unsigned int privileges = 0;
8414 for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i)
8415 {
8416 if(m_playerColours[i]==networkSmallId)
8417 {
8418 privileges = m_playerGamePrivileges[i];
8419 break;
8420 }
8421 }
8422 return privileges;
8423}
8424
8425wstring CMinecraftApp::getEntityName(eINSTANCEOF type)
8426{
8427 switch(type)
8428 {
8429 case eTYPE_WOLF:
8430 return app.GetString(IDS_WOLF);
8431 case eTYPE_CREEPER:
8432 return app.GetString(IDS_CREEPER);
8433 case eTYPE_SKELETON:
8434 return app.GetString(IDS_SKELETON);
8435 case eTYPE_SPIDER:
8436 return app.GetString(IDS_SPIDER);
8437 case eTYPE_ZOMBIE:
8438 return app.GetString(IDS_ZOMBIE);
8439 case eTYPE_PIGZOMBIE:
8440 return app.GetString(IDS_PIGZOMBIE);
8441 case eTYPE_ENDERMAN:
8442 return app.GetString(IDS_ENDERMAN);
8443 case eTYPE_SILVERFISH:
8444 return app.GetString(IDS_SILVERFISH);
8445 case eTYPE_CAVESPIDER:
8446 return app.GetString(IDS_CAVE_SPIDER);
8447 case eTYPE_GHAST:
8448 return app.GetString(IDS_GHAST);
8449 case eTYPE_SLIME:
8450 return app.GetString(IDS_SLIME);
8451 case eTYPE_ARROW:
8452 return app.GetString(IDS_ITEM_ARROW);
8453 case eTYPE_ENDERDRAGON:
8454 return app.GetString(IDS_ENDERDRAGON);
8455 case eTYPE_BLAZE:
8456 return app.GetString(IDS_BLAZE);
8457 case eTYPE_LAVASLIME:
8458 return app.GetString(IDS_LAVA_SLIME);
8459 // 4J-PB - fix for #107167 - Customer Encountered: TU12: Content: UI: There is no information what killed Player after being slain by Iron Golem.
8460 case eTYPE_VILLAGERGOLEM:
8461 return app.GetString(IDS_IRONGOLEM);
8462 case eTYPE_HORSE:
8463 return app.GetString(IDS_HORSE);
8464 case eTYPE_WITCH:
8465 return app.GetString(IDS_WITCH);
8466 case eTYPE_WITHERBOSS:
8467 return app.GetString(IDS_WITHER);
8468 case eTYPE_BAT:
8469 return app.GetString(IDS_BAT);
8470 };
8471
8472 return L"";
8473}
8474
8475DWORD CMinecraftApp::m_dwContentTypeA[e_Marketplace_MAX]=
8476{
8477 XMARKETPLACE_OFFERING_TYPE_CONTENT, // e_DLC_SkinPack, e_DLC_TexturePacks, e_DLC_MashupPacks
8478#ifndef _XBOX_ONE
8479 XMARKETPLACE_OFFERING_TYPE_THEME, // e_DLC_Themes
8480 XMARKETPLACE_OFFERING_TYPE_AVATARITEM, // e_DLC_AvatarItems
8481 XMARKETPLACE_OFFERING_TYPE_TILE, // e_DLC_Gamerpics
8482#endif
8483};
8484
8485unsigned int CMinecraftApp::AddDLCRequest(eDLCMarketplaceType eType, bool bPromote)
8486{
8487 // lock access
8488 EnterCriticalSection(&csDLCDownloadQueue);
8489
8490 // If it's already in there, promote it to the top of the list
8491 int iPosition=0;
8492 for(AUTO_VAR(it, m_DLCDownloadQueue.begin()); it != m_DLCDownloadQueue.end(); ++it)
8493 {
8494 DLCRequest *pCurrent = *it;
8495
8496 if(pCurrent->dwType==m_dwContentTypeA[eType])
8497 {
8498 // already got this in the list
8499 if(pCurrent->eState == e_DLC_ContentState_Retrieving || pCurrent->eState == e_DLC_ContentState_Retrieved)
8500 {
8501 // already retrieved this
8502 LeaveCriticalSection(&csDLCDownloadQueue);
8503 return 0;
8504 }
8505 else
8506 {
8507 // promote
8508 if(bPromote)
8509 {
8510 m_DLCDownloadQueue.erase(m_DLCDownloadQueue.begin()+iPosition);
8511 m_DLCDownloadQueue.insert(m_DLCDownloadQueue.begin(),pCurrent);
8512 }
8513 LeaveCriticalSection(&csDLCDownloadQueue);
8514 return 0;
8515 }
8516 }
8517 iPosition++;
8518 }
8519
8520 DLCRequest *pDLCreq = new DLCRequest;
8521 pDLCreq->dwType=m_dwContentTypeA[eType];
8522 pDLCreq->eState=e_DLC_ContentState_Idle;
8523
8524 m_DLCDownloadQueue.push_back(pDLCreq);
8525
8526 m_bAllDLCContentRetrieved=false;
8527 LeaveCriticalSection(&csDLCDownloadQueue);
8528
8529 app.DebugPrintf("[Consoles_App] Added DLC request.\n");
8530 return 1;
8531}
8532
8533unsigned int CMinecraftApp::AddTMSPPFileTypeRequest(eDLCContentType eType, bool bPromote)
8534{
8535#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__)
8536 // lock access
8537 EnterCriticalSection(&csTMSPPDownloadQueue);
8538
8539 // If it's already in there, promote it to the top of the list
8540 int iPosition=0;
8541 //ignore promoting for now
8542 /*
8543 bool bPromoted=false;
8544
8545
8546 for(AUTO_VAR(it, m_TMSPPDownloadQueue.begin()); it != m_TMSPPDownloadQueue.end(); ++it)
8547 {
8548 TMSPPRequest *pCurrent = *it;
8549
8550 if(pCurrent->eType==eType)
8551 {
8552 if(!(pCurrent->eState == e_TMS_ContentState_Retrieving || pCurrent->eState == e_TMS_ContentState_Retrieved))
8553 {
8554 // promote
8555 if(bPromote)
8556 {
8557 m_TMSPPDownloadQueue.erase(m_TMSPPDownloadQueue.begin()+iPosition);
8558 m_TMSPPDownloadQueue.insert(m_TMSPPDownloadQueue.begin(),pCurrent);
8559 bPromoted=true;
8560 }
8561 }
8562 }
8563 iPosition++;
8564 }
8565
8566 if(bPromoted)
8567 {
8568 // re-ordered the list, so leave now
8569 LeaveCriticalSection(&csTMSPPDownloadQueue);
8570 return 0;
8571 }
8572 */
8573
8574 // special case for data files (not image files)
8575 if(eType==e_DLC_TexturePackData)
8576 {
8577
8578
8579 int iCount=GetDLCInfoFullOffersCount();
8580
8581 for(int i=0;i<iCount;i++)
8582 {
8583
8584 DLC_INFO *pDLC=GetDLCInfoFullOffer(i);
8585
8586 if((pDLC->eDLCType==e_DLC_TexturePacks) || (pDLC->eDLCType==e_DLC_MashupPacks))
8587 {
8588 // first check if the image is already in the memory textures, since we might be loading some from the Title Update partition
8589 if(pDLC->wchDataFile[0]!=0)
8590 {
8591 //WCHAR *cString = pDLC->wchDataFile;
8592 // 4J-PB - shouldn't check this here - let the TMS files override it, so if they are on TMS, we'll take them first
8593 //int iIndex = app.GetLocalTMSFileIndex(pDLC->wchDataFile,true);
8594
8595 //if(iIndex!=-1)
8596 {
8597 bool bPresent = app.IsFileInTPD(pDLC->iConfig);
8598
8599 if(!bPresent)
8600 {
8601 // this may already be present in the vector because of a previous trial/full offer
8602
8603 bool bAlreadyInQueue=false;
8604 for(AUTO_VAR(it, m_TMSPPDownloadQueue.begin()); it != m_TMSPPDownloadQueue.end(); ++it)
8605 {
8606 TMSPPRequest *pCurrent = *it;
8607
8608 if(wcscmp(pDLC->wchDataFile,pCurrent->wchFilename)==0)
8609 {
8610 bAlreadyInQueue=true;
8611 break;
8612 }
8613 }
8614
8615 if(!bAlreadyInQueue)
8616 {
8617 TMSPPRequest *pTMSPPreq = new TMSPPRequest;
8618
8619 pTMSPPreq->CallbackFunc=&CMinecraftApp::TMSPPFileReturned;
8620 pTMSPPreq->lpCallbackParam=this;
8621 pTMSPPreq->eStorageFacility=C4JStorage::eGlobalStorage_Title;
8622 pTMSPPreq->eFileTypeVal=C4JStorage::TMS_FILETYPE_BINARY;
8623 memcpy(pTMSPPreq->wchFilename,pDLC->wchDataFile,sizeof(WCHAR)*MAX_BANNERNAME_SIZE);
8624 pTMSPPreq->eType=e_DLC_TexturePackData;
8625 pTMSPPreq->eState=e_TMS_ContentState_Queued;
8626 m_bAllTMSContentRetrieved=false;
8627 m_TMSPPDownloadQueue.push_back(pTMSPPreq);
8628 }
8629 }
8630 else
8631 {
8632 app.DebugPrintf("Texture data already present in the TPD\n");
8633 }
8634 }
8635 }
8636 }
8637 }
8638 }
8639 else
8640 { // for all the files of type eType, add them to the download list
8641
8642 // run through the trial offers first, then the full offers. Any duplicates won't be added to the download queue
8643 int iCount;
8644#ifdef _XBOX // Only trial offers on Xbox 360
8645 iCount=GetDLCInfoTrialOffersCount();
8646 for(int i=0;i<iCount;i++)
8647 {
8648 DLC_INFO *pDLC=GetDLCInfoTrialOffer(i);
8649
8650 // is this the right type?
8651 if(pDLC->eDLCType==eType)
8652 {
8653
8654 WCHAR *cString = pDLC->wchBanner;
8655
8656 // 4J-PB - shouldn't check this here - let the TMS files override it, so if they are on TMS, we'll take them first
8657 // is the file in the TMS XZP?
8658 //int iIndex = app.GetLocalTMSFileIndex(cString,true);
8659
8660 //if(iIndex!=-1)
8661 {
8662 bool bPresent = app.IsFileInMemoryTextures(cString);
8663
8664 if(!bPresent) // retrieve it from TMSPP
8665 {
8666 bool bAlreadyInQueue=false;
8667 for(AUTO_VAR(it, m_TMSPPDownloadQueue.begin()); it != m_TMSPPDownloadQueue.end(); ++it)
8668 {
8669 TMSPPRequest *pCurrent = *it;
8670
8671 if(wcscmp(pDLC->wchBanner,pCurrent->wchFilename)==0)
8672 {
8673 bAlreadyInQueue=true;
8674 break;
8675 }
8676 }
8677
8678 if(!bAlreadyInQueue)
8679 {
8680 TMSPPRequest *pTMSPPreq = new TMSPPRequest;
8681
8682 pTMSPPreq->CallbackFunc=&CMinecraftApp::TMSPPFileReturned;
8683 pTMSPPreq->lpCallbackParam=this;
8684 pTMSPPreq->eStorageFacility=C4JStorage::eGlobalStorage_Title;
8685 pTMSPPreq->eFileTypeVal=C4JStorage::TMS_FILETYPE_BINARY;
8686 //wcstombs(pTMSPPreq->szFilename,pDLC->wchBanner,MAX_TMSFILENAME_SIZE);
8687 memcpy(pTMSPPreq->wchFilename,pDLC->wchBanner,sizeof(WCHAR)*MAX_BANNERNAME_SIZE);
8688 pTMSPPreq->eType=eType;
8689 pTMSPPreq->eState=e_TMS_ContentState_Queued;
8690
8691 m_bAllTMSContentRetrieved=false;
8692 m_TMSPPDownloadQueue.push_back(pTMSPPreq);
8693 app.DebugPrintf("===m_TMSPPDownloadQueue Adding %ls, q size is %d\n",pTMSPPreq->wchFilename,m_TMSPPDownloadQueue.size());
8694 }
8695 }
8696 }
8697 }
8698 }
8699#endif
8700 // and the full offers
8701
8702 iCount=GetDLCInfoFullOffersCount();
8703 for(int i=0;i<iCount;i++)
8704 {
8705 DLC_INFO *pDLC=GetDLCInfoFullOffer(i);
8706 //if(wcscmp(pDLC->wchType,wchDLCTypeNames[eType])==0)
8707 if(pDLC->eDLCType==eType)
8708 {
8709 // first check if the image is already in the memory textures, since we might be loading some from the Title Update partition
8710
8711 WCHAR *cString = pDLC->wchBanner;
8712 // 4J-PB - shouldn't check this here - let the TMS files override it, so if they are on TMS, we'll take them first
8713 //int iIndex = app.GetLocalTMSFileIndex(cString,true);
8714
8715 //if(iIndex!=-1)
8716 {
8717 bool bPresent = app.IsFileInMemoryTextures(cString);
8718
8719 if(!bPresent)
8720 {
8721 // this may already be present in the vector because of a previous trial/full offer
8722
8723 bool bAlreadyInQueue=false;
8724 for(AUTO_VAR(it, m_TMSPPDownloadQueue.begin()); it != m_TMSPPDownloadQueue.end(); ++it)
8725 {
8726 TMSPPRequest *pCurrent = *it;
8727
8728 if(wcscmp(pDLC->wchBanner,pCurrent->wchFilename)==0)
8729 {
8730 bAlreadyInQueue=true;
8731 break;
8732 }
8733 }
8734
8735 if(!bAlreadyInQueue)
8736 {
8737 //app.DebugPrintf("Adding a request to the TMSPP download queue - %ls\n",pDLC->wchBanner);
8738 TMSPPRequest *pTMSPPreq = new TMSPPRequest;
8739 ZeroMemory(pTMSPPreq,sizeof(TMSPPRequest));
8740
8741 pTMSPPreq->CallbackFunc=&CMinecraftApp::TMSPPFileReturned;
8742 pTMSPPreq->lpCallbackParam=this;
8743 // 4J-PB - testing for now
8744 //pTMSPPreq->eStorageFacility=C4JStorage::eGlobalStorage_TitleUser;
8745 pTMSPPreq->eStorageFacility=C4JStorage::eGlobalStorage_Title;
8746 pTMSPPreq->eFileTypeVal=C4JStorage::TMS_FILETYPE_BINARY;
8747 //wcstombs(pTMSPPreq->szFilename,pDLC->wchBanner,MAX_TMSFILENAME_SIZE);
8748
8749 memcpy(pTMSPPreq->wchFilename,pDLC->wchBanner,sizeof(WCHAR)*MAX_BANNERNAME_SIZE);
8750 pTMSPPreq->eType=eType;
8751 pTMSPPreq->eState=e_TMS_ContentState_Queued;
8752 m_bAllTMSContentRetrieved=false;
8753 m_TMSPPDownloadQueue.push_back(pTMSPPreq);
8754 app.DebugPrintf("===m_TMSPPDownloadQueue Adding %ls, q size is %d\n",pTMSPPreq->wchFilename,m_TMSPPDownloadQueue.size());
8755 }
8756 }
8757 }
8758 }
8759 }
8760 }
8761
8762 LeaveCriticalSection(&csTMSPPDownloadQueue);
8763#endif
8764 return 1;
8765}
8766
8767bool CMinecraftApp::CheckTMSDLCCanStop()
8768{
8769 EnterCriticalSection(&csTMSPPDownloadQueue);
8770 for(AUTO_VAR(it, m_TMSPPDownloadQueue.begin()); it != m_TMSPPDownloadQueue.end(); ++it)
8771 {
8772 TMSPPRequest *pCurrent = *it;
8773
8774 if(pCurrent->eState==e_TMS_ContentState_Retrieving)
8775 {
8776 LeaveCriticalSection(&csTMSPPDownloadQueue);
8777 return false;
8778 }
8779 }
8780 LeaveCriticalSection(&csTMSPPDownloadQueue);
8781
8782 return true;
8783}
8784
8785
8786bool CMinecraftApp::RetrieveNextDLCContent()
8787{
8788 // If there's already a retrieve in progress, quit
8789 // we may have re-ordered the list, so need to check every item
8790
8791 // is there a primary player and a network connection?
8792 int primPad = ProfileManager.GetPrimaryPad();
8793 if ( primPad == -1 || !ProfileManager.IsSignedInLive(primPad) )
8794 {
8795 return true; // 4J-JEV: We need to wait until the primary player is online.
8796 }
8797
8798 EnterCriticalSection(&csDLCDownloadQueue);
8799 for(AUTO_VAR(it, m_DLCDownloadQueue.begin()); it != m_DLCDownloadQueue.end(); ++it)
8800 {
8801 DLCRequest *pCurrent = *it;
8802
8803 if(pCurrent->eState==e_DLC_ContentState_Retrieving)
8804 {
8805 LeaveCriticalSection(&csDLCDownloadQueue);
8806 return true;
8807 }
8808 }
8809
8810 // Now look for the next retrieval
8811 for(AUTO_VAR(it, m_DLCDownloadQueue.begin()); it != m_DLCDownloadQueue.end(); ++it)
8812 {
8813 DLCRequest *pCurrent = *it;
8814
8815 if(pCurrent->eState==e_DLC_ContentState_Idle)
8816 {
8817#ifdef _DEBUG
8818 app.DebugPrintf("RetrieveNextDLCContent - type = %d\n",pCurrent->dwType);
8819#endif
8820
8821 C4JStorage::EDLCStatus status = StorageManager.GetDLCOffers(ProfileManager.GetPrimaryPad(), &CMinecraftApp::DLCOffersReturned, this, pCurrent->dwType);
8822 if(status==C4JStorage::EDLC_Pending)
8823 {
8824 pCurrent->eState=e_DLC_ContentState_Retrieving;
8825 }
8826 else
8827 {
8828 // no content of this type, or some other problem
8829 app.DebugPrintf("RetrieveNextDLCContent - PROBLEM\n");
8830 pCurrent->eState=e_DLC_ContentState_Retrieved;
8831 }
8832 LeaveCriticalSection(&csDLCDownloadQueue);
8833 return true;
8834 }
8835 }
8836 LeaveCriticalSection(&csDLCDownloadQueue);
8837
8838 app.DebugPrintf("[Consoles_App] Finished downloading dlc content.\n");
8839 return false;
8840}
8841
8842#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__)
8843#ifdef _XBOX_ONE
8844int CMinecraftApp::TMSPPFileReturned(LPVOID pParam,int iPad,int iUserData,LPVOID lpvData, WCHAR* wchFilename)
8845{
8846 C4JStorage::PTMSPP_FILEDATA pFileData=(C4JStorage::PTMSPP_FILEDATA)lpvData;
8847#else
8848int CMinecraftApp::TMSPPFileReturned(LPVOID pParam,int iPad,int iUserData,C4JStorage::PTMSPP_FILEDATA pFileData, LPCSTR szFilename)
8849{
8850#endif
8851
8852 CMinecraftApp* pClass = (CMinecraftApp *) pParam;
8853
8854 // find the right one in the vector
8855 EnterCriticalSection(&pClass->csTMSPPDownloadQueue);
8856 for(AUTO_VAR(it, pClass->m_TMSPPDownloadQueue.begin()); it != pClass->m_TMSPPDownloadQueue.end(); ++it)
8857 {
8858 TMSPPRequest *pCurrent = *it;
8859#if defined(_XBOX) || defined(_WINDOWS64)
8860 char szFile[MAX_TMSFILENAME_SIZE];
8861 wcstombs(szFile,pCurrent->wchFilename,MAX_TMSFILENAME_SIZE);
8862
8863
8864 if(strcmp(szFilename,szFile)==0)
8865#elif _XBOX_ONE
8866 if(wcscmp(wchFilename,pCurrent->wchFilename)==0)
8867#endif
8868 {
8869 // set this to retrieved whether it found it or not
8870 pCurrent->eState=e_TMS_ContentState_Retrieved;
8871
8872 if(pFileData!=NULL)
8873 {
8874
8875#ifdef _XBOX_ONE
8876
8877
8878 switch(pCurrent->eType)
8879 {
8880 case e_DLC_TexturePackData:
8881 {
8882 // 4J-PB - we need to allocate memory for the file data and copy into it, since the current data is a reference into the blob download memory
8883 PBYTE pbData = new BYTE [pFileData->dwSize];
8884 memcpy(pbData,pFileData->pbData,pFileData->dwSize);
8885
8886 pClass->m_vTMSPPData.push_back(pbData);
8887 app.DebugPrintf("Got texturepack data\n");
8888 // get the config value for the texture pack
8889 int iConfig=app.GetTPConfigVal(pCurrent->wchFilename);
8890 app.AddMemoryTPDFile(iConfig, pbData, pFileData->dwSize);
8891 }
8892 break;
8893 default:
8894 // 4J-PB - check the data is an image
8895 if(pFileData->pbData[0]==0x89)
8896 {
8897 // 4J-PB - we need to allocate memory for the file data and copy into it, since the current data is a reference into the blob download memory
8898 PBYTE pbData = new BYTE [pFileData->dwSize];
8899 memcpy(pbData,pFileData->pbData,pFileData->dwSize);
8900
8901 pClass->m_vTMSPPData.push_back(pbData);
8902 app.DebugPrintf("Got image data - %ls\n",pCurrent->wchFilename);
8903 app.AddMemoryTextureFile(pCurrent->wchFilename, pbData, pFileData->dwSize);
8904 }
8905 else
8906 {
8907 app.DebugPrintf("Got image data, but it's not a png - %ls\n",pCurrent->wchFilename);
8908 }
8909 break;
8910 }
8911
8912#else
8913 switch(pCurrent->eType)
8914 {
8915 case e_DLC_TexturePackData:
8916 {
8917 app.DebugPrintf("--- Got texturepack data %ls\n",pCurrent->wchFilename);
8918 // get the config value for the texture pack
8919 int iConfig=app.GetTPConfigVal(pCurrent->wchFilename);
8920 app.AddMemoryTPDFile(iConfig, pFileData->pbData, pFileData->dwSize);
8921 }
8922 break;
8923 default:
8924 app.DebugPrintf("--- Got image data - %ls\n",pCurrent->wchFilename);
8925 app.AddMemoryTextureFile(pCurrent->wchFilename, pFileData->pbData, pFileData->dwSize);
8926 break;
8927 }
8928#endif
8929 }
8930 else
8931 {
8932#ifdef _XBOX_ONE
8933 app.DebugPrintf("TMSImageReturned failed (%ls)...\n",wchFilename);
8934#else
8935 app.DebugPrintf("TMSImageReturned failed (%s)...\n",szFilename);
8936#endif
8937 }
8938 break;
8939 }
8940
8941 }
8942 LeaveCriticalSection(&pClass->csTMSPPDownloadQueue);
8943
8944 return 0;
8945}
8946#endif
8947
8948bool CMinecraftApp::RetrieveNextTMSPPContent()
8949{
8950#if defined _XBOX || defined _XBOX_ONE
8951 // If there's already a retrieve in progress, quit
8952 // we may have re-ordered the list, so need to check every item
8953
8954 // is there a primary player and a network connection?
8955 if(ProfileManager.GetPrimaryPad()==-1) return false;
8956
8957 if(ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad())==false) return false;
8958
8959 EnterCriticalSection(&csTMSPPDownloadQueue);
8960 for(AUTO_VAR(it, m_TMSPPDownloadQueue.begin()); it != m_TMSPPDownloadQueue.end(); ++it)
8961 {
8962 TMSPPRequest *pCurrent = *it;
8963
8964 if(pCurrent->eState==e_TMS_ContentState_Retrieving)
8965 {
8966 app.DebugPrintf(".");
8967 LeaveCriticalSection(&csTMSPPDownloadQueue);
8968 return true;
8969 }
8970 }
8971
8972 // Now look for the next retrieval
8973 for(AUTO_VAR(it, m_TMSPPDownloadQueue.begin()); it != m_TMSPPDownloadQueue.end(); ++it)
8974 {
8975 TMSPPRequest *pCurrent = *it;
8976
8977 if(pCurrent->eState==e_TMS_ContentState_Queued)
8978 {
8979 // 4J-PB - the file may be in the local TMS files, but try to retrieve it from the remote TMS in case it's been changed. If it's not in the list of TMS files, this will
8980 // return right away with a ETMSStatus_Fail_ReadDetailsNotRetrieved
8981#ifdef _XBOX
8982 char szFilename[MAX_TMSFILENAME_SIZE];
8983 wcstombs(szFilename,pCurrent->wchFilename,MAX_TMSFILENAME_SIZE);
8984
8985 app.DebugPrintf("\nRetrieveNextTMSPPContent - type = %d, %s\n",pCurrent->eType,szFilename);
8986
8987 C4JStorage::ETMSStatus status=StorageManager.TMSPP_ReadFile(ProfileManager.GetPrimaryPad(),pCurrent->eStorageFacility,pCurrent->eFileTypeVal,szFilename,pCurrent->CallbackFunc,this);
8988 switch(status)
8989 {
8990 case C4JStorage::ETMSStatus_Pending:
8991 pCurrent->eState=e_TMS_ContentState_Retrieving;
8992 break;
8993 case C4JStorage::ETMSStatus_Idle:
8994 pCurrent->eState=e_TMS_ContentState_Retrieved;
8995 break;
8996 case C4JStorage::ETMSStatus_Fail_ReadInProgress:
8997 case C4JStorage::ETMSStatus_ReadInProgress:
8998 pCurrent->eState=e_TMS_ContentState_Retrieving;
8999 if(pCurrent->eState==C4JStorage::ETMSStatus_Fail_ReadInProgress)
9000 {
9001 app.DebugPrintf("TMSPP_ReadFile failed - read in progress\n");
9002 Sleep(50);
9003 LeaveCriticalSection(&csTMSPPDownloadQueue);
9004 return false;
9005 }
9006 break;
9007 default:
9008 pCurrent->eState=e_TMS_ContentState_Retrieved;
9009 break;
9010 }
9011#else
9012 eTitleStorageState status;
9013 app.DebugPrintf("RetrieveNextTMSPPContent - type = %d, %ls\n",pCurrent->eType,pCurrent->wchFilename);
9014 //eTitleStorageState status=StorageManager.TMSPP_ReadFile(ProfileManager.GetPrimaryPad(),pCurrent->eStorageFacility,pCurrent->eFileTypeVal,pCurrent->wchFilename,pCurrent->CallbackFunc,this,0);
9015 if(0)//wcscmp(pCurrent->wchFilename,L"TP01.png")==0)
9016 {
9017 // TP01 fails because the blob size returned is bigger than the global metadata says it should be
9018 status=eTitleStorage_readerror;
9019 }
9020 else
9021 {
9022 status=StorageManager.TMSPP_ReadFile(ProfileManager.GetPrimaryPad(),pCurrent->eStorageFacility,pCurrent->eFileTypeVal,pCurrent->wchFilename,pCurrent->CallbackFunc,this,0);
9023 }
9024 switch(status)
9025 {
9026 case eTitleStorage_pending:
9027 pCurrent->eState=e_TMS_ContentState_Retrieving;
9028 break;
9029 case eTitleStorage_idle:
9030 pCurrent->eState=e_TMS_ContentState_Retrieved;
9031 break;
9032 case eTitleStorage_busy:
9033 // try again next time
9034 {
9035 app.DebugPrintf("@@@@@@@@@@@@@@@@@ TMSPP_ReadFile failed - busy (probably reading already)\n");
9036 Sleep(50);
9037 LeaveCriticalSection(&csTMSPPDownloadQueue);
9038 return false;
9039 }
9040 break;
9041 default:
9042 pCurrent->eState=e_TMS_ContentState_Retrieved;
9043 break;
9044 }
9045#endif
9046
9047
9048
9049 LeaveCriticalSection(&csTMSPPDownloadQueue);
9050 return true;
9051 }
9052 }
9053
9054 LeaveCriticalSection(&csTMSPPDownloadQueue);
9055
9056#endif
9057 return false;
9058}
9059
9060void CMinecraftApp::TickDLCOffersRetrieved()
9061{
9062 if(!m_bAllDLCContentRetrieved)
9063 {
9064 if (!app.RetrieveNextDLCContent())
9065 {
9066 app.DebugPrintf("[Consoles_App] All content retrieved.\n");
9067 m_bAllDLCContentRetrieved=true;
9068 }
9069 }
9070}
9071void CMinecraftApp::ClearAndResetDLCDownloadQueue()
9072{
9073 app.DebugPrintf("[Consoles_App] Clear and reset download queue.\n");
9074
9075 int iPosition=0;
9076 EnterCriticalSection(&csTMSPPDownloadQueue);
9077 for(AUTO_VAR(it, m_DLCDownloadQueue.begin()); it != m_DLCDownloadQueue.end(); ++it)
9078 {
9079 DLCRequest *pCurrent = *it;
9080
9081 delete pCurrent;
9082 iPosition++;
9083 }
9084 m_DLCDownloadQueue.clear();
9085 m_bAllDLCContentRetrieved=true;
9086 LeaveCriticalSection(&csTMSPPDownloadQueue);
9087}
9088
9089void CMinecraftApp::TickTMSPPFilesRetrieved()
9090{
9091 if(m_bTickTMSDLCFiles && !m_bAllTMSContentRetrieved)
9092 {
9093 if(app.RetrieveNextTMSPPContent()==false)
9094 {
9095 m_bAllTMSContentRetrieved=true;
9096 }
9097 }
9098}
9099void CMinecraftApp::ClearTMSPPFilesRetrieved()
9100{
9101 int iPosition=0;
9102 EnterCriticalSection(&csTMSPPDownloadQueue);
9103 for(AUTO_VAR(it, m_TMSPPDownloadQueue.begin()); it != m_TMSPPDownloadQueue.end(); ++it)
9104 {
9105 TMSPPRequest *pCurrent = *it;
9106
9107 delete pCurrent;
9108 iPosition++;
9109 }
9110 m_TMSPPDownloadQueue.clear();
9111 m_bAllTMSContentRetrieved=true;
9112 LeaveCriticalSection(&csTMSPPDownloadQueue);
9113}
9114
9115int CMinecraftApp::DLCOffersReturned(void *pParam, int iOfferC, DWORD dwType, int iPad)
9116{
9117 CMinecraftApp* pClass = (CMinecraftApp *) pParam;
9118
9119 // find the right one in the vector
9120 EnterCriticalSection(&pClass->csTMSPPDownloadQueue);
9121 for(AUTO_VAR(it, pClass->m_DLCDownloadQueue.begin()); it != pClass->m_DLCDownloadQueue.end(); ++it)
9122 {
9123 DLCRequest *pCurrent = *it;
9124
9125 // avatar items are coming back as type Content, so we can't trust the type setting
9126 if(pCurrent->dwType==dwType)
9127 {
9128 pClass->m_iDLCOfferC = iOfferC;
9129 app.DebugPrintf("DLCOffersReturned - type %d, count %d - setting to retrieved\n",dwType,iOfferC);
9130 pCurrent->eState=e_DLC_ContentState_Retrieved;
9131 break;
9132 }
9133 }
9134 LeaveCriticalSection(&pClass->csTMSPPDownloadQueue);
9135 return 0;
9136}
9137
9138eDLCContentType CMinecraftApp::Find_eDLCContentType(DWORD dwType)
9139{
9140 for(int i=0;i<e_DLC_MAX;i++)
9141 {
9142 if(m_dwContentTypeA[i]==dwType)
9143 {
9144 return (eDLCContentType)i;
9145 }
9146 }
9147 return (eDLCContentType)0;
9148}
9149bool CMinecraftApp::DLCContentRetrieved(eDLCMarketplaceType eType)
9150{
9151 // If there's already a retrieve in progress, quit
9152 // we may have re-ordered the list, so need to check every item
9153 EnterCriticalSection(&csDLCDownloadQueue);
9154 for(AUTO_VAR(it, m_DLCDownloadQueue.begin()); it != m_DLCDownloadQueue.end(); ++it)
9155 {
9156 DLCRequest *pCurrent = *it;
9157
9158 if((pCurrent->dwType==m_dwContentTypeA[eType]) && (pCurrent->eState==e_DLC_ContentState_Retrieved))
9159 {
9160 LeaveCriticalSection(&csDLCDownloadQueue);
9161 return true;
9162 }
9163 }
9164 LeaveCriticalSection(&csDLCDownloadQueue);
9165 return false;
9166}
9167
9168void CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, SKIN_BOX *SkinBoxA, DWORD dwSkinBoxC)
9169{
9170 EntityRenderer *renderer = EntityRenderDispatcher::instance->getRenderer(eTYPE_PLAYER);
9171 Model *pModel = renderer->getModel();
9172 vector<ModelPart *> *pvModelPart = new vector<ModelPart *>;
9173 vector<SKIN_BOX *> *pvSkinBoxes = new vector<SKIN_BOX *>;
9174
9175 EnterCriticalSection( &csAdditionalModelParts );
9176 EnterCriticalSection( &csAdditionalSkinBoxes );
9177
9178 app.DebugPrintf("*** SetAdditionalSkinBoxes - Inserting model parts for skin %d from array of Skin Boxes\n",dwSkinID&0x0FFFFFFF);
9179
9180 // convert the skin boxes into model parts, and add to the humanoid model
9181 for(unsigned int i=0;i<dwSkinBoxC;i++)
9182 {
9183 if(pModel)
9184 {
9185 ModelPart *pModelPart=pModel->AddOrRetrievePart(&SkinBoxA[i]);
9186 pvModelPart->push_back(pModelPart);
9187 pvSkinBoxes->push_back(&SkinBoxA[i]);
9188 }
9189 }
9190
9191
9192 m_AdditionalModelParts.insert( std::pair<DWORD, vector<ModelPart *> *>(dwSkinID, pvModelPart) );
9193 m_AdditionalSkinBoxes.insert( std::pair<DWORD, vector<SKIN_BOX *> *>(dwSkinID, pvSkinBoxes) );
9194
9195 LeaveCriticalSection( &csAdditionalSkinBoxes );
9196 LeaveCriticalSection( &csAdditionalModelParts );
9197
9198}
9199
9200vector<ModelPart *> * CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, vector<SKIN_BOX *> *pvSkinBoxA)
9201{
9202 EntityRenderer *renderer = EntityRenderDispatcher::instance->getRenderer(eTYPE_PLAYER);
9203 Model *pModel = renderer->getModel();
9204 vector<ModelPart *> *pvModelPart = new vector<ModelPart *>;
9205
9206 EnterCriticalSection( &csAdditionalModelParts );
9207 EnterCriticalSection( &csAdditionalSkinBoxes );
9208 app.DebugPrintf("*** SetAdditionalSkinBoxes - Inserting model parts for skin %d from array of Skin Boxes\n",dwSkinID&0x0FFFFFFF);
9209
9210 // convert the skin boxes into model parts, and add to the humanoid model
9211 for(AUTO_VAR(it, pvSkinBoxA->begin());it != pvSkinBoxA->end(); ++it)
9212 {
9213 if(pModel)
9214 {
9215 ModelPart *pModelPart=pModel->AddOrRetrievePart(*it);
9216 pvModelPart->push_back(pModelPart);
9217 }
9218 }
9219
9220 m_AdditionalModelParts.insert( std::pair<DWORD, vector<ModelPart *> *>(dwSkinID, pvModelPart) );
9221 m_AdditionalSkinBoxes.insert( std::pair<DWORD, vector<SKIN_BOX *> *>(dwSkinID, pvSkinBoxA) );
9222
9223 LeaveCriticalSection( &csAdditionalSkinBoxes );
9224 LeaveCriticalSection( &csAdditionalModelParts );
9225 return pvModelPart;
9226}
9227
9228
9229vector<ModelPart *> *CMinecraftApp::GetAdditionalModelParts(DWORD dwSkinID)
9230{
9231 EnterCriticalSection( &csAdditionalModelParts );
9232 vector<ModelPart *> *pvModelParts=NULL;
9233 if(m_AdditionalModelParts.size()>0)
9234 {
9235 AUTO_VAR(it, m_AdditionalModelParts.find(dwSkinID));
9236 if(it!=m_AdditionalModelParts.end())
9237 {
9238 pvModelParts = (*it).second;
9239 }
9240 }
9241
9242 LeaveCriticalSection( &csAdditionalModelParts );
9243 return pvModelParts;
9244}
9245
9246vector<SKIN_BOX *> *CMinecraftApp::GetAdditionalSkinBoxes(DWORD dwSkinID)
9247{
9248 EnterCriticalSection( &csAdditionalSkinBoxes );
9249 vector<SKIN_BOX *> *pvSkinBoxes=NULL;
9250 if(m_AdditionalSkinBoxes.size()>0)
9251 {
9252 AUTO_VAR(it,m_AdditionalSkinBoxes.find(dwSkinID));
9253 if(it!=m_AdditionalSkinBoxes.end())
9254 {
9255 pvSkinBoxes = (*it).second;
9256 }
9257 }
9258
9259 LeaveCriticalSection( &csAdditionalSkinBoxes );
9260 return pvSkinBoxes;
9261}
9262
9263unsigned int CMinecraftApp::GetAnimOverrideBitmask(DWORD dwSkinID)
9264{
9265 EnterCriticalSection( &csAnimOverrideBitmask );
9266 unsigned int uiAnimOverrideBitmask=0L;
9267
9268 if(m_AnimOverrides.size()>0)
9269 {
9270 AUTO_VAR(it, m_AnimOverrides.find(dwSkinID));
9271 if(it!=m_AnimOverrides.end())
9272 {
9273 uiAnimOverrideBitmask = (*it).second;
9274 }
9275 }
9276
9277 LeaveCriticalSection( &csAnimOverrideBitmask );
9278 return uiAnimOverrideBitmask;
9279}
9280
9281void CMinecraftApp::SetAnimOverrideBitmask(DWORD dwSkinID,unsigned int uiAnimOverrideBitmask)
9282{
9283 // Make thread safe
9284 EnterCriticalSection( &csAnimOverrideBitmask );
9285
9286 if(m_AnimOverrides.size()>0)
9287 {
9288 AUTO_VAR(it, m_AnimOverrides.find(dwSkinID));
9289 if(it!=m_AnimOverrides.end())
9290 {
9291 LeaveCriticalSection( &csAnimOverrideBitmask );
9292 return; // already in here
9293 }
9294 }
9295 m_AnimOverrides.insert( std::pair<DWORD, unsigned long>(dwSkinID, uiAnimOverrideBitmask) );
9296 LeaveCriticalSection( &csAnimOverrideBitmask );
9297}
9298
9299DWORD CMinecraftApp::getSkinIdFromPath(const wstring &skin)
9300{
9301 bool dlcSkin = false;
9302 unsigned int skinId = 0;
9303
9304 if(skin.size() >= 14)
9305 {
9306 dlcSkin = skin.substr(0,3).compare(L"dlc") == 0;
9307
9308 wstring skinValue = skin.substr(7,skin.size());
9309 skinValue = skinValue.substr(0,skinValue.find_first_of(L'.'));
9310
9311 std::wstringstream ss;
9312 // 4J Stu - dlc skins are numbered using decimal to make it easier for artists/people to number manually
9313 // Everything else is numbered using hex
9314 if(dlcSkin)
9315 ss << std::dec << skinValue.c_str();
9316 else
9317 ss << std::hex << skinValue.c_str();
9318 ss >> skinId;
9319
9320 skinId = MAKE_SKIN_BITMASK(dlcSkin, skinId);
9321 }
9322 return skinId;
9323}
9324
9325wstring CMinecraftApp::getSkinPathFromId(DWORD skinId)
9326{
9327 // 4J Stu - This function maps the encoded DWORD we store in the player profile
9328 // to a filename that is stored as a memory texture and shared between systems in game
9329 wchar_t chars[256];
9330 if( GET_IS_DLC_SKIN_FROM_BITMASK(skinId) )
9331 {
9332 // 4J Stu - DLC skins are numbered using decimal rather than hex to make it easier to number manually
9333 swprintf(chars, 256, L"dlcskin%08d.png", GET_DLC_SKIN_ID_FROM_BITMASK(skinId));
9334
9335 }
9336 else
9337 {
9338 DWORD ugcSkinIndex = GET_UGC_SKIN_ID_FROM_BITMASK(skinId);
9339 DWORD defaultSkinIndex = GET_DEFAULT_SKIN_ID_FROM_BITMASK(skinId);
9340 if( ugcSkinIndex == 0 )
9341 {
9342 swprintf(chars, 256, L"defskin%08X.png",defaultSkinIndex);
9343 }
9344 else
9345 {
9346 swprintf(chars, 256, L"ugcskin%08X.png",ugcSkinIndex);
9347 }
9348 }
9349 return chars;
9350}
9351
9352
9353int CMinecraftApp::TexturePackDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result)
9354{
9355
9356
9357#if defined __PSVITA__ || defined __PS3__ || defined __ORBIS__
9358 if(result==C4JStorage::EMessage_ResultAccept)
9359 {
9360 Minecraft *pMinecraft = Minecraft::GetInstance();
9361 if( pMinecraft->skins->selectTexturePackById(app.GetRequiredTexturePackID()) )
9362 {
9363 // it's been installed already
9364 }
9365 else
9366 {
9367 // we need to enable background downloading for the DLC
9368 XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW);
9369 SONYDLC *pSONYDLCInfo=app.GetSONYDLCInfo(app.GetRequiredTexturePackID());
9370 if(pSONYDLCInfo!=NULL)
9371 {
9372 char chName[42];
9373 char chKeyName[20];
9374 char chSkuID[SCE_NP_COMMERCE2_SKU_ID_LEN];
9375
9376 memset(chSkuID,0,SCE_NP_COMMERCE2_SKU_ID_LEN);
9377 // we have to retrieve the skuid from the store info, it can't be hardcoded since Sony may change it.
9378 // So we assume the first sku for the product is the one we want
9379 // MGH - keyname in the DLC file is 16 chars long, but there's no space for a NULL terminating char
9380 memset(chKeyName, 0, sizeof(chKeyName));
9381 strncpy(chKeyName, pSONYDLCInfo->chDLCKeyname, 16);
9382
9383 #ifdef __ORBIS__
9384 strcpy(chName, chKeyName);
9385 #else
9386 sprintf(chName,"%s-%s",app.GetCommerceCategory(),chKeyName);
9387 #endif
9388 app.GetDLCSkuIDFromProductList(chName,chSkuID);
9389 // 4J-PB - need to check for an empty store
9390 if(app.CheckForEmptyStore(iPad)==false)
9391 {
9392 if(app.DLCAlreadyPurchased(chSkuID))
9393 {
9394 app.DownloadAlreadyPurchased(chSkuID);
9395 }
9396 else
9397 {
9398 app.Checkout(chSkuID);
9399 }
9400 }
9401 }
9402 }
9403 }
9404 else
9405 {
9406 app.DebugPrintf("Continuing without installing texture pack\n");
9407 }
9408#endif
9409
9410#ifdef _XBOX
9411 if(result!=C4JStorage::EMessage_Cancelled)
9412 {
9413 if(app.GetRequiredTexturePackID()!=0)
9414 {
9415 // we need to enable background downloading for the DLC
9416 XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW);
9417
9418 ULONGLONG ullOfferID_Full;
9419 ULONGLONG ullIndexA[1];
9420 app.GetDLCFullOfferIDForPackID(app.GetRequiredTexturePackID(),&ullOfferID_Full);
9421
9422 if( result==C4JStorage::EMessage_ResultAccept ) // Full version
9423 {
9424 ullIndexA[0]=ullOfferID_Full;
9425 StorageManager.InstallOffer(1,ullIndexA,NULL,NULL);
9426 }
9427 else // trial version
9428 {
9429 DLC_INFO *pDLCInfo=app.GetDLCInfoForFullOfferID(ullOfferID_Full);
9430 ullIndexA[0]=pDLCInfo->ullOfferID_Trial;
9431 StorageManager.InstallOffer(1,ullIndexA,NULL,NULL);
9432 }
9433 }
9434 }
9435#endif
9436 return 0;
9437}
9438
9439int CMinecraftApp::getArchiveFileSize(const wstring &filename)
9440{
9441 TexturePack *tPack = NULL;
9442 Minecraft *pMinecraft = Minecraft::GetInstance();
9443 if(pMinecraft && pMinecraft->skins) tPack = pMinecraft->skins->getSelected();
9444 if(tPack && tPack->hasData() && tPack->getArchiveFile() && tPack->getArchiveFile()->hasFile(filename))
9445 {
9446 return tPack->getArchiveFile()->getFileSize(filename);
9447 }
9448 else return m_mediaArchive->getFileSize(filename);
9449}
9450
9451bool CMinecraftApp::hasArchiveFile(const wstring &filename)
9452{
9453 TexturePack *tPack = NULL;
9454 Minecraft *pMinecraft = Minecraft::GetInstance();
9455 if(pMinecraft && pMinecraft->skins) tPack = pMinecraft->skins->getSelected();
9456 if(tPack && tPack->hasData() && tPack->getArchiveFile() && tPack->getArchiveFile()->hasFile(filename)) return true;
9457 else return m_mediaArchive->hasFile(filename);
9458}
9459
9460byteArray CMinecraftApp::getArchiveFile(const wstring &filename)
9461{
9462 TexturePack *tPack = NULL;
9463 Minecraft *pMinecraft = Minecraft::GetInstance();
9464 if(pMinecraft && pMinecraft->skins) tPack = pMinecraft->skins->getSelected();
9465 if(tPack && tPack->hasData() && tPack->getArchiveFile() && tPack->getArchiveFile()->hasFile(filename))
9466 {
9467 return tPack->getArchiveFile()->getFile(filename);
9468 }
9469 else return m_mediaArchive->getFile(filename);
9470}
9471
9472// DLC
9473
9474#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__)
9475int CMinecraftApp::GetDLCInfoCount()
9476{
9477 return (int)DLCInfo.size();
9478}
9479#elif defined _XBOX_ONE
9480int CMinecraftApp::GetDLCInfoTrialOffersCount()
9481{
9482 return 0;
9483}
9484
9485int CMinecraftApp::GetDLCInfoFullOffersCount()
9486{
9487 return (int)DLCInfo_Full.size();
9488}
9489#else
9490int CMinecraftApp::GetDLCInfoTrialOffersCount()
9491{
9492 return (int)DLCInfo_Trial.size();
9493}
9494
9495int CMinecraftApp::GetDLCInfoFullOffersCount()
9496{
9497 return (int)DLCInfo_Full.size();
9498}
9499#endif
9500
9501int CMinecraftApp::GetDLCInfoTexturesOffersCount()
9502{
9503 return (int)DLCTextures_PackID.size();
9504}
9505
9506// AUTOSAVE
9507void CMinecraftApp::SetAutosaveTimerTime(void)
9508{
9509#if defined(_XBOX_ONE) || defined(__ORBIS__)
9510 m_uiAutosaveTimer= GetTickCount()+1000*60;
9511#else
9512 m_uiAutosaveTimer= GetTickCount()+GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_Autosave)*1000*60*15;
9513#endif
9514}// value x 15 to get mins, x60 for secs
9515
9516bool CMinecraftApp::AutosaveDue(void)
9517{
9518 return (GetTickCount()>m_uiAutosaveTimer);
9519}
9520
9521unsigned int CMinecraftApp::SecondsToAutosave()
9522{
9523 return (m_uiAutosaveTimer - GetTickCount() ) / 1000;
9524}
9525
9526void CMinecraftApp::SetTrialTimerStart(void)
9527{
9528 m_fTrialTimerStart=m_Time.fAppTime; mfTrialPausedTime=0.0f;
9529}
9530
9531float CMinecraftApp::getTrialTimer(void)
9532{
9533 return m_Time.fAppTime-m_fTrialTimerStart-mfTrialPausedTime;
9534}
9535
9536bool CMinecraftApp::IsLocalMultiplayerAvailable()
9537{
9538 DWORD connectedControllers = 0;
9539 for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
9540 {
9541 if( InputManager.IsPadConnected(i) || ProfileManager.IsSignedIn(i) ) ++connectedControllers;
9542 }
9543
9544#ifdef _WINDOWS64
9545 bool available = connectedControllers > 1;
9546#else
9547 bool available = RenderManager.IsHiDef() && connectedControllers > 1;
9548#endif
9549
9550#ifdef __ORBIS__
9551 // Check for remote play
9552 available = available && InputManager.IsLocalMultiplayerAvailable();
9553#endif
9554
9555 return available;
9556
9557 // Found this in GameNetworkManager?
9558 //#ifdef _DURANGO
9559 // iOtherConnectedControllers = InputManager.GetConnectedGamepadCount();
9560 // if((InputManager.IsPadConnected(userIndex) || ProfileManager.IsSignedIn(userIndex)))
9561 // {
9562 // --iOtherConnectedControllers;
9563 // }
9564 //#else
9565 // for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
9566 // {
9567 // if( (i!=userIndex) && (InputManager.IsPadConnected(i) || ProfileManager.IsSignedIn(i)) )
9568 // {
9569 // iOtherConnectedControllers++;
9570 // }
9571 // }
9572 //#endif
9573}
9574
9575
9576// 4J-PB - language and locale function
9577
9578void CMinecraftApp::getLocale(vector<wstring> &vecWstrLocales)
9579{
9580 vector<eMCLang> locales;
9581
9582 DWORD dwSystemLanguage = XGetLanguage( );
9583
9584 // 4J-PB - restrict the 360 language until we're ready to have them in
9585
9586#ifdef _XBOX
9587 switch(dwSystemLanguage)
9588 {
9589 case XC_LANGUAGE_FRENCH :
9590 locales.push_back(eMCLang_frFR);
9591 break;
9592 case XC_LANGUAGE_ITALIAN :
9593 locales.push_back(eMCLang_itIT);
9594 break;
9595 case XC_LANGUAGE_GERMAN :
9596 locales.push_back(eMCLang_deDE);
9597 break;
9598 case XC_LANGUAGE_SPANISH :
9599 locales.push_back(eMCLang_esES);
9600 break;
9601 case XC_LANGUAGE_PORTUGUESE :
9602 if(XGetLocale()==XC_LOCALE_BRAZIL)
9603 {
9604 locales.push_back(eMCLang_ptBR);
9605 }
9606 locales.push_back(eMCLang_ptPT);
9607 break;
9608 case XC_LANGUAGE_JAPANESE :
9609 locales.push_back(eMCLang_jaJP);
9610 break;
9611 case XC_LANGUAGE_KOREAN :
9612 locales.push_back(eMCLang_koKR);
9613 break;
9614 case XC_LANGUAGE_TCHINESE :
9615 locales.push_back(eMCLang_zhCHT);
9616 break;
9617 }
9618#else
9619 switch(dwSystemLanguage)
9620 {
9621
9622 case XC_LANGUAGE_ENGLISH:
9623 switch(XGetLocale())
9624 {
9625 case XC_LOCALE_AUSTRALIA:
9626 case XC_LOCALE_CANADA:
9627 case XC_LOCALE_CZECH_REPUBLIC:
9628 case XC_LOCALE_GREECE:
9629 case XC_LOCALE_HONG_KONG:
9630 case XC_LOCALE_HUNGARY:
9631 case XC_LOCALE_INDIA:
9632 case XC_LOCALE_IRELAND:
9633 case XC_LOCALE_ISRAEL:
9634 case XC_LOCALE_NEW_ZEALAND:
9635 case XC_LOCALE_SAUDI_ARABIA:
9636 case XC_LOCALE_SINGAPORE:
9637 case XC_LOCALE_SLOVAK_REPUBLIC:
9638 case XC_LOCALE_SOUTH_AFRICA:
9639 case XC_LOCALE_UNITED_ARAB_EMIRATES:
9640 case XC_LOCALE_GREAT_BRITAIN:
9641 locales.push_back(eMCLang_enGB);
9642 break;
9643 default: //XC_LOCALE_UNITED_STATES
9644 break;
9645 }
9646 break;
9647 case XC_LANGUAGE_JAPANESE :
9648 locales.push_back(eMCLang_jaJP);
9649 break;
9650 case XC_LANGUAGE_GERMAN :
9651 switch(XGetLocale())
9652 {
9653 case XC_LOCALE_AUSTRIA:
9654 locales.push_back(eMCLang_deAT);
9655 break;
9656 case XC_LOCALE_SWITZERLAND:
9657 locales.push_back(eMCLang_deCH);
9658 break;
9659 default:// XC_LOCALE_GERMANY:
9660 break;
9661 }
9662 locales.push_back(eMCLang_deDE);
9663 break;
9664 case XC_LANGUAGE_FRENCH :
9665 switch(XGetLocale())
9666 {
9667 case XC_LOCALE_BELGIUM:
9668 locales.push_back(eMCLang_frBE);
9669 break;
9670 case XC_LOCALE_CANADA:
9671 locales.push_back(eMCLang_frCA);
9672 break;
9673 case XC_LOCALE_SWITZERLAND:
9674 locales.push_back(eMCLang_frCH);
9675 break;
9676 default:// XC_LOCALE_FRANCE:
9677 break;
9678 }
9679 locales.push_back(eMCLang_frFR);
9680 break;
9681 case XC_LANGUAGE_SPANISH :
9682 switch(XGetLocale())
9683 {
9684 case XC_LOCALE_MEXICO:
9685 case XC_LOCALE_ARGENTINA:
9686 case XC_LOCALE_CHILE:
9687 case XC_LOCALE_COLOMBIA:
9688 case XC_LOCALE_UNITED_STATES:
9689 case XC_LOCALE_LATIN_AMERICA:
9690 locales.push_back(eMCLang_laLAS);
9691 locales.push_back(eMCLang_esMX);
9692 break;
9693 default://XC_LOCALE_SPAIN
9694 break;
9695 }
9696 locales.push_back(eMCLang_esES);
9697 break;
9698 case XC_LANGUAGE_ITALIAN :
9699 locales.push_back(eMCLang_itIT);
9700 break;
9701 case XC_LANGUAGE_KOREAN :
9702 locales.push_back(eMCLang_koKR);
9703 break;
9704 case XC_LANGUAGE_TCHINESE :
9705 switch(XGetLocale())
9706 {
9707 case XC_LOCALE_HONG_KONG:
9708 locales.push_back(eMCLang_zhHK);
9709 locales.push_back(eMCLang_zhTW);
9710 break;
9711 case XC_LOCALE_TAIWAN:
9712 locales.push_back(eMCLang_zhTW);
9713 locales.push_back(eMCLang_zhHK);
9714 default:
9715 break;
9716 }
9717 locales.push_back(eMCLang_hant);
9718 locales.push_back(eMCLang_zhCHT);
9719 break;
9720 case XC_LANGUAGE_PORTUGUESE :
9721 if(XGetLocale()==XC_LOCALE_BRAZIL)
9722 {
9723 locales.push_back(eMCLang_ptBR);
9724 }
9725 locales.push_back(eMCLang_ptPT);
9726 break;
9727 case XC_LANGUAGE_POLISH :
9728 locales.push_back(eMCLang_plPL);
9729 break;
9730 case XC_LANGUAGE_RUSSIAN :
9731 locales.push_back(eMCLang_ruRU);
9732 break;
9733 case XC_LANGUAGE_SWEDISH :
9734 locales.push_back(eMCLang_svSV);
9735 locales.push_back(eMCLang_svSE);
9736 break;
9737 case XC_LANGUAGE_TURKISH :
9738 locales.push_back(eMCLang_trTR);
9739 break;
9740 case XC_LANGUAGE_BNORWEGIAN :
9741 locales.push_back(eMCLang_nbNO);
9742 locales.push_back(eMCLang_noNO);
9743 locales.push_back(eMCLang_nnNO);
9744 break;
9745 case XC_LANGUAGE_DUTCH :
9746 switch(XGetLocale())
9747 {
9748 case XC_LOCALE_BELGIUM:
9749 locales.push_back(eMCLang_nlBE);
9750 break;
9751 default:
9752 break;
9753 }
9754 locales.push_back(eMCLang_nlNL);
9755 break;
9756 case XC_LANGUAGE_SCHINESE :
9757 switch(XGetLocale())
9758 {
9759 case XC_LOCALE_SINGAPORE:
9760 locales.push_back(eMCLang_zhSG);
9761 break;
9762 default:
9763 break;
9764 }
9765 locales.push_back(eMCLang_hans);
9766 locales.push_back(eMCLang_csCS);
9767 locales.push_back(eMCLang_zhCN);
9768 break;
9769
9770#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ || defined _DURANGO
9771 case XC_LANGUAGE_DANISH:
9772 locales.push_back(eMCLang_daDA);
9773 locales.push_back(eMCLang_daDK);
9774 break;
9775
9776 case XC_LANGUAGE_FINISH :
9777 locales.push_back(eMCLang_fiFI);
9778 break;
9779
9780 case XC_LANGUAGE_CZECH :
9781 locales.push_back(eMCLang_csCZ);
9782 locales.push_back(eMCLang_enCZ);
9783 break;
9784
9785 case XC_LANGUAGE_SLOVAK :
9786 locales.push_back(eMCLang_skSK);
9787 locales.push_back(eMCLang_enSK);
9788 break;
9789
9790 case XC_LANGUAGE_GREEK :
9791 locales.push_back(eMCLang_elEL);
9792 locales.push_back(eMCLang_elGR);
9793 locales.push_back(eMCLang_enGR);
9794 locales.push_back(eMCLang_enGB);
9795 break;
9796#endif
9797 }
9798#endif
9799
9800 locales.push_back(eMCLang_enUS);
9801 locales.push_back(eMCLang_null);
9802
9803 for (int i=0; i<locales.size(); i++)
9804 {
9805 eMCLang lang = locales.at(i);
9806 vecWstrLocales.push_back( m_localeA[lang] );
9807 }
9808}
9809
9810DWORD CMinecraftApp::get_eMCLang(WCHAR *pwchLocale)
9811{
9812 return m_eMCLangA[pwchLocale];
9813}
9814
9815
9816DWORD CMinecraftApp::get_xcLang(WCHAR *pwchLocale)
9817{
9818 return m_xcLangA[pwchLocale];
9819}
9820
9821void CMinecraftApp::LocaleAndLanguageInit()
9822{
9823 m_localeA[eMCLang_zhCHT] =L"zh-CHT";
9824 m_localeA[eMCLang_csCS] =L"cs-CS";
9825 m_localeA[eMCLang_laLAS] =L"la-LAS";
9826 m_localeA[eMCLang_null] =L"en-EN";
9827 m_localeA[eMCLang_enUS] =L"en-US";
9828 m_localeA[eMCLang_enGB] =L"en-GB";
9829 m_localeA[eMCLang_enIE] =L"en-IE";
9830 m_localeA[eMCLang_enAU] =L"en-AU";
9831 m_localeA[eMCLang_enNZ] =L"en-NZ";
9832 m_localeA[eMCLang_enCA] =L"en-CA";
9833 m_localeA[eMCLang_jaJP] =L"ja-JP";
9834 m_localeA[eMCLang_deDE] =L"de-DE";
9835 m_localeA[eMCLang_deAT] =L"de-AT";
9836 m_localeA[eMCLang_frFR] =L"fr-FR";
9837 m_localeA[eMCLang_frCA] =L"fr-CA";
9838 m_localeA[eMCLang_esES] =L"es-ES";
9839 m_localeA[eMCLang_esMX] =L"es-MX";
9840 m_localeA[eMCLang_itIT] =L"it-IT";
9841 m_localeA[eMCLang_koKR] =L"ko-KR";
9842 m_localeA[eMCLang_ptPT] =L"pt-PT";
9843 m_localeA[eMCLang_ptBR] =L"pt-BR";
9844 m_localeA[eMCLang_ruRU] =L"ru-RU";
9845 m_localeA[eMCLang_nlNL] =L"nl-NL";
9846 m_localeA[eMCLang_fiFI] =L"fi-FI";
9847 m_localeA[eMCLang_svSV] =L"sv-SV";
9848 m_localeA[eMCLang_daDA] =L"da-DA";
9849 m_localeA[eMCLang_noNO] =L"no-NO";
9850 m_localeA[eMCLang_plPL] =L"pl-PL";
9851 m_localeA[eMCLang_trTR] =L"tr-TR";
9852 m_localeA[eMCLang_elEL] =L"el-EL";
9853
9854 m_localeA[eMCLang_zhSG] =L"zh-SG";
9855 m_localeA[eMCLang_zhCN] =L"zh-CN";
9856 m_localeA[eMCLang_zhHK] =L"zh-HK";
9857 m_localeA[eMCLang_zhTW] =L"zh-TW";
9858 m_localeA[eMCLang_nlBE] =L"nl-BE";
9859 m_localeA[eMCLang_daDK] =L"da-DK";
9860 m_localeA[eMCLang_frBE] =L"fr-BE";
9861 m_localeA[eMCLang_frCH] =L"fr-CH";
9862 m_localeA[eMCLang_deCH] =L"de-CH";
9863 m_localeA[eMCLang_nbNO] =L"nb-NO";
9864 m_localeA[eMCLang_enGR] =L"en-GR";
9865 m_localeA[eMCLang_enHK] =L"en-HK";
9866 m_localeA[eMCLang_enSA] =L"en-SA";
9867 m_localeA[eMCLang_enHU] =L"en-HU";
9868 m_localeA[eMCLang_enIN] =L"en-IN";
9869 m_localeA[eMCLang_enIL] =L"en-IL";
9870 m_localeA[eMCLang_enSG] =L"en-SG";
9871 m_localeA[eMCLang_enSK] =L"en-SK";
9872 m_localeA[eMCLang_enZA] =L"en-ZA";
9873 m_localeA[eMCLang_enCZ] =L"en-CZ";
9874 m_localeA[eMCLang_enAE] =L"en-AE";
9875 m_localeA[eMCLang_esAR] =L"es-AR";
9876 m_localeA[eMCLang_esCL] =L"es-CL";
9877 m_localeA[eMCLang_esCO] =L"es-CO";
9878 m_localeA[eMCLang_esUS] =L"es-US";
9879 m_localeA[eMCLang_svSE] =L"sv-SE";
9880
9881 m_localeA[eMCLang_csCZ] =L"cs-CZ";
9882 m_localeA[eMCLang_elGR] =L"el-GR";
9883 m_localeA[eMCLang_nnNO] =L"nn-NO";
9884 m_localeA[eMCLang_skSK] =L"sk-SK";
9885
9886 m_localeA[eMCLang_hans] =L"zh-HANS";
9887 m_localeA[eMCLang_hant] =L"zh-HANT";
9888
9889 m_eMCLangA[L"zh-CHT"] =eMCLang_zhCHT;
9890 m_eMCLangA[L"cs-CS"] =eMCLang_csCS;
9891 m_eMCLangA[L"la-LAS"] =eMCLang_laLAS;
9892 m_eMCLangA[L"en-EN"] =eMCLang_null;
9893 m_eMCLangA[L"en-US"] =eMCLang_enUS;
9894 m_eMCLangA[L"en-GB"] =eMCLang_enGB;
9895 m_eMCLangA[L"en-IE"] =eMCLang_enIE;
9896 m_eMCLangA[L"en-AU"] =eMCLang_enAU;
9897 m_eMCLangA[L"en-NZ"] =eMCLang_enNZ;
9898 m_eMCLangA[L"en-CA"] =eMCLang_enCA;
9899 m_eMCLangA[L"ja-JP"] =eMCLang_jaJP;
9900 m_eMCLangA[L"de-DE"] =eMCLang_deDE;
9901 m_eMCLangA[L"de-AT"] =eMCLang_deAT;
9902 m_eMCLangA[L"fr-FR"] =eMCLang_frFR;
9903 m_eMCLangA[L"fr-CA"] =eMCLang_frCA;
9904 m_eMCLangA[L"es-ES"] =eMCLang_esES;
9905 m_eMCLangA[L"es-MX"] =eMCLang_esMX;
9906 m_eMCLangA[L"it-IT"] =eMCLang_itIT;
9907 m_eMCLangA[L"ko-KR"] =eMCLang_koKR;
9908 m_eMCLangA[L"pt-PT"] =eMCLang_ptPT;
9909 m_eMCLangA[L"pt-BR"] =eMCLang_ptBR;
9910 m_eMCLangA[L"ru-RU"] =eMCLang_ruRU;
9911 m_eMCLangA[L"nl-NL"] =eMCLang_nlNL;
9912 m_eMCLangA[L"fi-FI"] =eMCLang_fiFI;
9913 m_eMCLangA[L"sv-SV"] =eMCLang_svSV;
9914 m_eMCLangA[L"da-DA"] =eMCLang_daDA;
9915 m_eMCLangA[L"no-NO"] =eMCLang_noNO;
9916 m_eMCLangA[L"pl-PL"] =eMCLang_plPL;
9917 m_eMCLangA[L"tr-TR"] =eMCLang_trTR;
9918 m_eMCLangA[L"el-EL"] =eMCLang_elEL;
9919
9920 m_eMCLangA[L"zh-SG"] =eMCLang_zhSG;
9921 m_eMCLangA[L"zh-CN"] =eMCLang_zhCN;
9922 m_eMCLangA[L"zh-HK"] =eMCLang_zhHK;
9923 m_eMCLangA[L"zh-TW"] =eMCLang_zhTW;
9924 m_eMCLangA[L"nl-BE"] =eMCLang_nlBE;
9925 m_eMCLangA[L"da-DK"] =eMCLang_daDK;
9926 m_eMCLangA[L"fr-BE"] =eMCLang_frBE;
9927 m_eMCLangA[L"fr-CH"] =eMCLang_frCH;
9928 m_eMCLangA[L"de-CH"] =eMCLang_deCH;
9929 m_eMCLangA[L"nb-NO"] =eMCLang_nbNO;
9930 m_eMCLangA[L"en-GR"] =eMCLang_enGR;
9931 m_eMCLangA[L"en-HK"] =eMCLang_enHK;
9932 m_eMCLangA[L"en-SA"] =eMCLang_enSA;
9933 m_eMCLangA[L"en-HU"] =eMCLang_enHU;
9934 m_eMCLangA[L"en-IN"] =eMCLang_enIN;
9935 m_eMCLangA[L"en-IL"] =eMCLang_enIL;
9936 m_eMCLangA[L"en-SG"] =eMCLang_enSG;
9937 m_eMCLangA[L"en-SK"] =eMCLang_enSK;
9938 m_eMCLangA[L"en-ZA"] =eMCLang_enZA;
9939 m_eMCLangA[L"en-CZ"] =eMCLang_enCZ;
9940 m_eMCLangA[L"en-AE"] =eMCLang_enAE;
9941 m_eMCLangA[L"es-AR"] =eMCLang_esAR;
9942 m_eMCLangA[L"es-CL"] =eMCLang_esCL;
9943 m_eMCLangA[L"es-CO"] =eMCLang_esCO;
9944 m_eMCLangA[L"es-US"] =eMCLang_esUS;
9945 m_eMCLangA[L"sv-SE"] =eMCLang_svSE;
9946
9947 m_eMCLangA[L"cs-CZ"] =eMCLang_csCZ;
9948 m_eMCLangA[L"el-GR"] =eMCLang_elGR;
9949 m_eMCLangA[L"nn-NO"] =eMCLang_nnNO;
9950 m_eMCLangA[L"sk-SK"] =eMCLang_skSK;
9951
9952 m_eMCLangA[L"zh-HANS"] =eMCLang_hans;
9953 m_eMCLangA[L"zh-HANT"] =eMCLang_hant;
9954
9955 m_xcLangA[L"zh-CHT"] =XC_LOCALE_CHINA;
9956 m_xcLangA[L"cs-CS"] =XC_LOCALE_CHINA;
9957 m_xcLangA[L"en-EN"] =XC_LOCALE_UNITED_STATES;
9958 m_xcLangA[L"en-US"] =XC_LOCALE_UNITED_STATES;
9959 m_xcLangA[L"en-GB"] =XC_LOCALE_GREAT_BRITAIN;
9960 m_xcLangA[L"en-IE"] =XC_LOCALE_IRELAND;
9961 m_xcLangA[L"en-AU"] =XC_LOCALE_AUSTRALIA;
9962 m_xcLangA[L"en-NZ"] =XC_LOCALE_NEW_ZEALAND;
9963 m_xcLangA[L"en-CA"] =XC_LOCALE_CANADA;
9964 m_xcLangA[L"ja-JP"] =XC_LOCALE_JAPAN;
9965 m_xcLangA[L"de-DE"] =XC_LOCALE_GERMANY;
9966 m_xcLangA[L"de-AT"] =XC_LOCALE_AUSTRIA;
9967 m_xcLangA[L"fr-FR"] =XC_LOCALE_FRANCE;
9968 m_xcLangA[L"fr-CA"] =XC_LOCALE_CANADA;
9969 m_xcLangA[L"es-ES"] =XC_LOCALE_SPAIN;
9970 m_xcLangA[L"es-MX"] =XC_LOCALE_MEXICO;
9971 m_xcLangA[L"it-IT"] =XC_LOCALE_ITALY;
9972 m_xcLangA[L"ko-KR"] =XC_LOCALE_KOREA;
9973 m_xcLangA[L"pt-PT"] =XC_LOCALE_PORTUGAL;
9974 m_xcLangA[L"pt-BR"] =XC_LOCALE_BRAZIL;
9975 m_xcLangA[L"ru-RU"] =XC_LOCALE_RUSSIAN_FEDERATION;
9976 m_xcLangA[L"nl-NL"] =XC_LOCALE_NETHERLANDS;
9977 m_xcLangA[L"fi-FI"] =XC_LOCALE_FINLAND;
9978 m_xcLangA[L"sv-SV"] =XC_LOCALE_SWEDEN;
9979 m_xcLangA[L"da-DA"] =XC_LOCALE_DENMARK;
9980 m_xcLangA[L"no-NO"] =XC_LOCALE_NORWAY;
9981 m_xcLangA[L"pl-PL"] =XC_LOCALE_POLAND;
9982 m_xcLangA[L"tr-TR"] =XC_LOCALE_TURKEY;
9983 m_xcLangA[L"el-EL"] =XC_LOCALE_GREECE;
9984#ifndef _XBOX
9985 m_xcLangA[L"la-LAS"] =XC_LOCALE_LATIN_AMERICA;
9986#endif
9987
9988 // New ones for Xbox One
9989 m_xcLangA[L"zh-SG"] =XC_LOCALE_SINGAPORE;
9990 m_xcLangA[L"Zh-CN"] =XC_LOCALE_CHINA;
9991 m_xcLangA[L"zh-HK"] =XC_LOCALE_HONG_KONG;
9992 m_xcLangA[L"zh-TW"] =XC_LOCALE_TAIWAN;
9993 m_xcLangA[L"nl-BE"] =XC_LOCALE_BELGIUM;
9994 m_xcLangA[L"da-DK"] =XC_LOCALE_DENMARK;
9995 m_xcLangA[L"fr-BE"] =XC_LOCALE_BELGIUM;
9996 m_xcLangA[L"fr-CH"] =XC_LOCALE_SWITZERLAND;
9997 m_xcLangA[L"de-CH"] =XC_LOCALE_SWITZERLAND;
9998 m_xcLangA[L"nb-NO"] =XC_LOCALE_NORWAY;
9999 m_xcLangA[L"en-GR"] =XC_LOCALE_GREECE;
10000 m_xcLangA[L"en-HK"] =XC_LOCALE_HONG_KONG;
10001 m_xcLangA[L"en-SA"] =XC_LOCALE_SAUDI_ARABIA;
10002 m_xcLangA[L"en-HU"] =XC_LOCALE_HUNGARY;
10003 m_xcLangA[L"en-IN"] =XC_LOCALE_INDIA;
10004 m_xcLangA[L"en-IL"] =XC_LOCALE_ISRAEL;
10005 m_xcLangA[L"en-SG"] =XC_LOCALE_SINGAPORE;
10006 m_xcLangA[L"en-SK"] =XC_LOCALE_SLOVAK_REPUBLIC;
10007 m_xcLangA[L"en-ZA"] =XC_LOCALE_SOUTH_AFRICA;
10008 m_xcLangA[L"en-CZ"] =XC_LOCALE_CZECH_REPUBLIC;
10009 m_xcLangA[L"en-AE"] =XC_LOCALE_UNITED_ARAB_EMIRATES;
10010 m_xcLangA[L"ja-IP"] =XC_LOCALE_JAPAN;
10011 m_xcLangA[L"es-AR"] =XC_LOCALE_ARGENTINA;
10012 m_xcLangA[L"es-CL"] =XC_LOCALE_CHILE;
10013 m_xcLangA[L"es-CO"] =XC_LOCALE_COLOMBIA;
10014 m_xcLangA[L"es-US"] =XC_LOCALE_UNITED_STATES;
10015 m_xcLangA[L"sv-SE"] =XC_LOCALE_SWEDEN;
10016
10017 m_xcLangA[L"cs-CZ"] =XC_LOCALE_CZECH_REPUBLIC;
10018 m_xcLangA[L"el-GR"] =XC_LOCALE_GREECE;
10019 m_xcLangA[L"sk-SK"] =XC_LOCALE_SLOVAK_REPUBLIC;
10020
10021 m_xcLangA[L"zh-HANS"] =XC_LOCALE_CHINA;
10022 m_xcLangA[L"zh-HANT"] =XC_LOCALE_CHINA;
10023}
10024
10025void CMinecraftApp::SetTickTMSDLCFiles(bool bVal)
10026{
10027 // 4J-PB - we need to stop the retrieval of minecraft store images from TMS when we aren't in the DLC, since going in to Play Game will change the title id group
10028 m_bTickTMSDLCFiles=bVal;
10029}
10030
10031wstring CMinecraftApp::getFilePath(DWORD packId, wstring filename, bool bAddDataFolder, wstring mountPoint)
10032{
10033 wstring path = getRootPath(packId, true, bAddDataFolder, mountPoint) + filename;
10034 File f(path);
10035 if(f.exists())
10036 {
10037 return path;
10038 }
10039 return getRootPath(packId, false, true, mountPoint) + filename;
10040}
10041
10042#ifdef _XBOX
10043// Texture packs that have their data in the TU data
10044enum ETitleUpdateTexturePacks
10045{
10046 eTUTP_MassEffect = 0x400,
10047 eTUTP_Skyrim = 0x401,
10048 eTUTP_Halo = 0x402,
10049 eTUTP_Festive = 0x405,
10050
10051 eTUTP_Plastic = 0x801,
10052 eTUTP_Candy = 0x802,
10053 eTUTP_Fantasy = 0x803,
10054 eTUTP_Halloween = 0x804,
10055 eTUTP_Natural = 0x805,
10056 eTUTP_City = 0x01000806, // 4J Stu - The released City pack had a sub-pack ID
10057 eTUTP_Cartoon = 0x807,
10058 eTUTP_Steampunk = 0x01000808, // 4J Stu - The released Steampunk pack had a sub-pack ID
10059};
10060
10061#ifdef _TU_BUILD
10062wstring titleUpdateTexturePackRoot = L"UPDATE:\\res\\DLC\\";
10063#else
10064wstring titleUpdateTexturePackRoot = L"GAME:\\res\\TitleUpdate\\DLC\\";
10065#endif
10066#else
10067enum ETitleUpdateTexturePacks
10068{
10069 //eTUTP_MassEffect = 0x400,
10070 //eTUTP_Skyrim = 0x401,
10071 //eTUTP_Halo = 0x402,
10072 //eTUTP_Festive = 0x405,
10073
10074 //eTUTP_Plastic = 0x801,
10075 //eTUTP_Candy = 0x802,
10076 //eTUTP_Fantasy = 0x803,
10077 eTUTP_Halloween = 0x804,
10078 //eTUTP_Natural = 0x805,
10079 //eTUTP_City = 0x01000806, // 4J Stu - The released City pack had a sub-pack ID
10080 //eTUTP_Cartoon = 0x807,
10081 //eTUTP_Steampunk = 0x01000808, // 4J Stu - The released Steampunk pack had a sub-pack ID
10082};
10083
10084#ifdef _WINDOWS64
10085wstring titleUpdateTexturePackRoot = L"Windows64\\DLC\\";
10086#elif defined(__ORBIS__)
10087wstring titleUpdateTexturePackRoot = L"/app0/orbis/CU/DLC/";
10088#elif defined(__PSVITA__)
10089wstring titleUpdateTexturePackRoot = L"PSVita/CU/DLC/";
10090#elif defined(__PS3__)
10091wstring titleUpdateTexturePackRoot = L"PS3/CU/DLC/";
10092#else
10093wstring titleUpdateTexturePackRoot = L"CU\\DLC\\";
10094#endif
10095
10096#endif
10097
10098wstring CMinecraftApp::getRootPath(DWORD packId, bool allowOverride, bool bAddDataFolder, wstring mountPoint)
10099{
10100 wstring path = mountPoint;
10101#ifdef _XBOX
10102 if(allowOverride)
10103 {
10104 switch(packId)
10105 {
10106 case eTUTP_MassEffect:
10107 path = titleUpdateTexturePackRoot + L"MassEffect";
10108 break;
10109 case eTUTP_Skyrim:
10110 path = titleUpdateTexturePackRoot + L"Skyrim";
10111 break;
10112 case eTUTP_Halo:
10113 path = titleUpdateTexturePackRoot + L"Halo";
10114 break;
10115 case eTUTP_Festive:
10116 path = titleUpdateTexturePackRoot + L"Festive";
10117 break;
10118 case eTUTP_Plastic:
10119 path = titleUpdateTexturePackRoot + L"Plastic";
10120 break;
10121 case eTUTP_Candy:
10122 path = titleUpdateTexturePackRoot + L"Candy";
10123 break;
10124 case eTUTP_Fantasy:
10125 path = titleUpdateTexturePackRoot + L"Fantasy";
10126 break;
10127 case eTUTP_Halloween:
10128 path = titleUpdateTexturePackRoot + L"Halloween";
10129 break;
10130 case eTUTP_Natural:
10131 path = titleUpdateTexturePackRoot + L"Natural";
10132 break;
10133 case eTUTP_City:
10134 path = titleUpdateTexturePackRoot + L"City";
10135 break;
10136 case eTUTP_Cartoon:
10137 path = titleUpdateTexturePackRoot + L"Cartoon";
10138 break;
10139 case eTUTP_Steampunk:
10140 path = titleUpdateTexturePackRoot + L"Steampunk";
10141 break;
10142 };
10143 File folder(path);
10144 if(!folder.exists())
10145 {
10146 path = mountPoint;
10147 }
10148 }
10149#else
10150 if(allowOverride)
10151 {
10152 switch(packId)
10153 {
10154 case eTUTP_Halloween:
10155 path = titleUpdateTexturePackRoot + L"Halloween Texture Pack";
10156 break;
10157 };
10158 File folder(path);
10159 if(!folder.exists())
10160 {
10161 path = mountPoint;
10162 }
10163 }
10164#endif
10165
10166 if(bAddDataFolder)
10167 {
10168 return path + L"\\Data\\";
10169 }
10170 else
10171 {
10172 return path + L"\\";
10173 }
10174
10175}
10176
10177#ifdef _XBOX_ONE
10178void CMinecraftApp::SetReachedMainMenu()
10179{
10180 m_hasReachedMainMenu = true;
10181}
10182
10183bool CMinecraftApp::HasReachedMainMenu()
10184{
10185 return m_hasReachedMainMenu;
10186}
10187#endif