diff --git a/Minecraft.Client/Common/App_Defines.h b/Minecraft.Client/Common/App_Defines.h index aad6bbcf..28b02191 100644 --- a/Minecraft.Client/Common/App_Defines.h +++ b/Minecraft.Client/Common/App_Defines.h @@ -111,6 +111,8 @@ enum EGameHostOptionWorldSize #define GAMESETTING_CAVESOUNDS 0x08000000 #define GAMESETTING_MINECARTSOUNDS 0x10000000 #define GAMESETTING_HIDESAVESIZEBAR 0x20000000 +#define GAMESETTING_SAFECAM 0x40000000 +#define GAMESETTING_SWAP 0x80000000 // defines for languages diff --git a/Minecraft.Client/Common/App_enums.h b/Minecraft.Client/Common/App_enums.h index a6951e98..f546a289 100644 --- a/Minecraft.Client/Common/App_enums.h +++ b/Minecraft.Client/Common/App_enums.h @@ -1,981 +1,985 @@ -#pragma once - -enum eFileExtensionType -{ - eFileExtensionType_PNG=0, - eFileExtensionType_INF, - eFileExtensionType_DAT, -}; - -enum eTMSFileType -{ - eTMSFileType_MinecraftStore=0, - eTMSFileType_TexturePack, - eTMSFileType_All -}; - -enum eTPDFileType -{ - eTPDFileType_Loc=0, - eTPDFileType_Icon, -// eTPDFileType_Banner, - eTPDFileType_Comparison, -}; - -enum eFont -{ - eFont_European=0, - eFont_Korean, - eFont_Japanese, - eFont_Chinese, - eFont_None, // to fallback to nothing -}; - -enum eXuiAction -{ - eAppAction_Idle=0, - eAppAction_SaveGame, - eAppAction_SaveGameCapturedThumbnail, - eAppAction_ExitWorld, - eAppAction_ExitWorldCapturedThumbnail, - eAppAction_ExitWorldTrial, - //eAppAction_ExitGameFatalLoadError, - eAppAction_Respawn, - eAppAction_WaitForRespawnComplete, - eAppAction_PrimaryPlayerSignedOut, - eAppAction_PrimaryPlayerSignedOutReturned, - eAppAction_PrimaryPlayerSignedOutReturned_Menus, - eAppAction_ExitPlayer, // secondary player - eAppAction_ExitPlayerPreLogin, - eAppAction_TrialOver, - eAppAction_ExitTrial, - eAppAction_WaitForDimensionChangeComplete, - eAppAction_SocialPost, - eAppAction_SocialPostScreenshot, - eAppAction_EthernetDisconnected, - eAppAction_EthernetDisconnectedReturned, - eAppAction_EthernetDisconnectedReturned_Menus, - eAppAction_ExitAndJoinFromInvite, - eAppAction_DashboardTrialJoinFromInvite, - eAppAction_ExitAndJoinFromInviteConfirmed, - eAppAction_JoinFromInvite, - eAppAction_ChangeSessionType, - eAppAction_SetDefaultOptions, - eAppAction_LocalPlayerJoined, - eAppAction_RemoteServerSave, - eAppAction_WaitRemoteServerSaveComplete, - eAppAction_FailedToJoinNoPrivileges, - eAppAction_AutosaveSaveGame, - eAppAction_AutosaveSaveGameCapturedThumbnail, - eAppAction_ProfileReadError, - eAppAction_DisplayLavaMessage, - eAppAction_BanLevel, - eAppAction_LevelInBanLevelList, - - eAppAction_ReloadTexturePack, - eAppAction_ReloadFont, - eAppAction_TexturePackRequired, // when the user has joined from invite, but doesn't have the texture pack - -#ifdef __ORBIS__ - eAppAction_OptionsSaveNoSpace, -#endif - eAppAction_DebugText, - -}; - - - -enum eTMSAction -{ - eTMSAction_Idle=0, - eTMSAction_TMS_RetrieveFiles_Complete, - eTMSAction_TMSPP_RetrieveFiles_CreateLoad_SignInReturned, - eTMSAction_TMSPP_RetrieveFiles_RunPlayGame, - eTMSAction_TMSPP_RetrieveFiles_HelpAndOptions, - eTMSAction_TMSPP_RetrieveFiles_DLCMain, - eTMSAction_TMSPP_GlobalFileList, - eTMSAction_TMSPP_GlobalFileList_Waiting, -// eTMSAction_TMSPP_ConfigFile, -// eTMSAction_TMSPP_ConfigFile_Waiting, - eTMSAction_TMSPP_UserFileList, - eTMSAction_TMSPP_UserFileList_Waiting, - eTMSAction_TMSPP_XUIDSFile, - eTMSAction_TMSPP_XUIDSFile_Waiting, - eTMSAction_TMSPP_DLCFile, - eTMSAction_TMSPP_DLCFile_Waiting, - eTMSAction_TMSPP_BannedListFile, - eTMSAction_TMSPP_BannedListFile_Waiting, - eTMSAction_TMSPP_RetrieveFiles_Complete, - eTMSAction_TMSPP_DLCFileOnly, - eTMSAction_TMSPP_RetrieveUserFilelist_DLCFileOnly, -}; - -// The server runs on its own thread, so we need to call its actions there rather than where all other Xui actions are performed -// In general these are debugging options -enum eXuiServerAction -{ - eXuiServerAction_Idle=0, - eXuiServerAction_DropItem, // Debug - eXuiServerAction_SaveGame, - eXuiServerAction_AutoSaveGame, - eXuiServerAction_SpawnMob, // Debug - eXuiServerAction_PauseServer, - eXuiServerAction_ToggleRain, // Debug - eXuiServerAction_ToggleThunder, // Debug - eXuiServerAction_ServerSettingChanged_Gamertags, - eXuiServerAction_ServerSettingChanged_Difficulty, - eXuiServerAction_ExportSchematic, //Debug - eXuiServerAction_ServerSettingChanged_BedrockFog, - eXuiServerAction_SetCameraLocation, //Debug -}; - -enum eGameSetting -{ - eGameSetting_MusicVolume=0, - eGameSetting_SoundFXVolume, - eGameSetting_RenderDistance, - eGameSetting_Gamma, - eGameSetting_FOV, - eGameSetting_Difficulty, - eGameSetting_Sensitivity_InGame, - eGameSetting_Sensitivity_InMenu, - eGameSetting_ViewBob, - eGameSetting_ControlScheme, - eGameSetting_ControlInvertLook, - eGameSetting_ControlSouthPaw, - eGameSetting_SplitScreenVertical, - eGameSetting_GamertagsVisible, - // Interim TU 1.6.6 - eGameSetting_Autosave, - eGameSetting_DisplaySplitscreenGamertags, - eGameSetting_Hints, - eGameSetting_InterfaceOpacity, - eGameSetting_Tooltips, - // TU5 - eGameSetting_Clouds, - eGameSetting_Online, - eGameSetting_InviteOnly, - eGameSetting_FriendsOfFriends, - eGameSetting_DisplayUpdateMessage, - - // TU6 - eGameSetting_BedrockFog, - eGameSetting_DisplayHUD, - eGameSetting_DisplayHand, - - // TU7 - eGameSetting_CustomSkinAnim, - - // TU9 - eGameSetting_DeathMessages, - eGameSetting_UISize, - eGameSetting_UISizeSplitscreen, - eGameSetting_AnimatedCharacter, - - // PS3 - eGameSetting_PS3_EULA_Read, - - // PSVita - eGameSetting_PSVita_NetworkModeAdhoc, - - // PC - eGameSetting_VSync, - eGameSetting_ExclusiveFullscreen, - - //TU25 - eGameSetting_ClassicCrafting, - eGameSetting_CaveSounds, - eGameSetting_MinecartSounds, - eGameSetting_ControlType, - // if enabled hides the save size bar in loadcreatejoinmenu (load tab) - eGameSetting_HideSaveSizeBar, -}; - - - -enum eGameMode -{ - eMode_Singleplayer, - eMode_Multiplayer -}; - - -enum eMinecraftColour -{ - eMinecraftColour_NOT_SET, - - eMinecraftColour_Foliage_Evergreen, - eMinecraftColour_Foliage_Birch, - eMinecraftColour_Foliage_Default, - eMinecraftColour_Foliage_Common, - eMinecraftColour_Foliage_Ocean, - eMinecraftColour_Foliage_Plains, - eMinecraftColour_Foliage_Desert, - eMinecraftColour_Foliage_ExtremeHills, - eMinecraftColour_Foliage_Forest, - eMinecraftColour_Foliage_Taiga, - eMinecraftColour_Foliage_Swampland, - eMinecraftColour_Foliage_River, - eMinecraftColour_Foliage_Hell, - eMinecraftColour_Foliage_Sky, - eMinecraftColour_Foliage_FrozenOcean, - eMinecraftColour_Foliage_FrozenRiver, - eMinecraftColour_Foliage_IcePlains, - eMinecraftColour_Foliage_IceMountains, - eMinecraftColour_Foliage_MushroomIsland, - eMinecraftColour_Foliage_MushroomIslandShore, - eMinecraftColour_Foliage_Beach, - eMinecraftColour_Foliage_DesertHills, - eMinecraftColour_Foliage_ForestHills, - eMinecraftColour_Foliage_TaigaHills, - eMinecraftColour_Foliage_ExtremeHillsEdge, - eMinecraftColour_Foliage_Jungle, - eMinecraftColour_Foliage_JungleHills, - eMinecraftColour_Foliage_Savanna, - eMinecraftColour_Foliage_RoofedForest, - eMinecraftColour_Foliage_Mesa, - - eMinecraftColour_Grass_Common, - eMinecraftColour_Grass_Ocean, - eMinecraftColour_Grass_Plains, - eMinecraftColour_Grass_Desert, - eMinecraftColour_Grass_ExtremeHills, - eMinecraftColour_Grass_Forest, - eMinecraftColour_Grass_Taiga, - eMinecraftColour_Grass_Swampland, - eMinecraftColour_Grass_River, - eMinecraftColour_Grass_Hell, - eMinecraftColour_Grass_Sky, - eMinecraftColour_Grass_FrozenOcean, - eMinecraftColour_Grass_FrozenRiver, - eMinecraftColour_Grass_IcePlains, - eMinecraftColour_Grass_IceMountains, - eMinecraftColour_Grass_MushroomIsland, - eMinecraftColour_Grass_MushroomIslandShore, - eMinecraftColour_Grass_Beach, - eMinecraftColour_Grass_DesertHills, - eMinecraftColour_Grass_ForestHills, - eMinecraftColour_Grass_TaigaHills, - eMinecraftColour_Grass_ExtremeHillsEdge, - eMinecraftColour_Grass_Jungle, - eMinecraftColour_Grass_JungleHills, - eMinecraftColour_Grass_Savanna, - eMinecraftColour_Grass_RoofedForest, - eMinecraftColour_Grass_Mesa, - - eMinecraftColour_Water_Ocean, - eMinecraftColour_Water_Plains, - eMinecraftColour_Water_Desert, - eMinecraftColour_Water_ExtremeHills, - eMinecraftColour_Water_Forest, - eMinecraftColour_Water_Taiga, - eMinecraftColour_Water_Swampland, - eMinecraftColour_Water_River, - eMinecraftColour_Water_Hell, - eMinecraftColour_Water_Sky, - eMinecraftColour_Water_FrozenOcean, - eMinecraftColour_Water_FrozenRiver, - eMinecraftColour_Water_IcePlains, - eMinecraftColour_Water_IceMountains, - eMinecraftColour_Water_MushroomIsland, - eMinecraftColour_Water_MushroomIslandShore, - eMinecraftColour_Water_Beach, - eMinecraftColour_Water_DesertHills, - eMinecraftColour_Water_ForestHills, - eMinecraftColour_Water_TaigaHills, - eMinecraftColour_Water_ExtremeHillsEdge, - eMinecraftColour_Water_Jungle, - eMinecraftColour_Water_JungleHills, - eMinecraftColour_Water_JungleEdge, - eMinecraftColour_Water_Mesa, - - eMinecraftColour_Sky_Ocean, - eMinecraftColour_Sky_Plains, - eMinecraftColour_Sky_Desert, - eMinecraftColour_Sky_ExtremeHills, - eMinecraftColour_Sky_Forest, - eMinecraftColour_Sky_Taiga, - eMinecraftColour_Sky_Swampland, - eMinecraftColour_Sky_River, - eMinecraftColour_Sky_Hell, - eMinecraftColour_Sky_Sky, - eMinecraftColour_Sky_FrozenOcean, - eMinecraftColour_Sky_FrozenRiver, - eMinecraftColour_Sky_IcePlains, - eMinecraftColour_Sky_IceMountains, - eMinecraftColour_Sky_MushroomIsland, - eMinecraftColour_Sky_MushroomIslandShore, - eMinecraftColour_Sky_Beach, - eMinecraftColour_Sky_DesertHills, - eMinecraftColour_Sky_ForestHills, - eMinecraftColour_Sky_TaigaHills, - eMinecraftColour_Sky_ExtremeHillsEdge, - eMinecraftColour_Sky_Jungle, - eMinecraftColour_Sky_JungleHills, - eMinecraftColour_Sky_JungleEdge, - - eMinecraftColour_Tile_RedstoneDust, - eMinecraftColour_Tile_RedstoneDustUnlit, - eMinecraftColour_Tile_RedstoneDustLitMin, - eMinecraftColour_Tile_RedstoneDustLitMax, - eMinecraftColour_Tile_StemMin, - eMinecraftColour_Tile_StemMax, - eMinecraftColour_Tile_WaterLily, - - eMinecraftColour_Sky_Dawn_Dark, - eMinecraftColour_Sky_Dawn_Bright, - - eMinecraftColour_Material_None, - eMinecraftColour_Material_Grass, - eMinecraftColour_Material_Sand, - eMinecraftColour_Material_Cloth, - eMinecraftColour_Material_Fire, - eMinecraftColour_Material_Ice, - eMinecraftColour_Material_Metal, - eMinecraftColour_Material_Plant, - eMinecraftColour_Material_Snow, - eMinecraftColour_Material_Clay, - eMinecraftColour_Material_Dirt, - eMinecraftColour_Material_Stone, - eMinecraftColour_Material_Water, - eMinecraftColour_Material_Wood, - eMinecraftColour_Material_Emerald, - - eMinecraftColour_Particle_Note_00, - eMinecraftColour_Particle_Note_01, - eMinecraftColour_Particle_Note_02, - eMinecraftColour_Particle_Note_03, - eMinecraftColour_Particle_Note_04, - eMinecraftColour_Particle_Note_05, - eMinecraftColour_Particle_Note_06, - eMinecraftColour_Particle_Note_07, - eMinecraftColour_Particle_Note_08, - eMinecraftColour_Particle_Note_09, - eMinecraftColour_Particle_Note_10, - eMinecraftColour_Particle_Note_11, - eMinecraftColour_Particle_Note_12, - eMinecraftColour_Particle_Note_13, - eMinecraftColour_Particle_Note_14, - eMinecraftColour_Particle_Note_15, - eMinecraftColour_Particle_Note_16, - eMinecraftColour_Particle_Note_17, - eMinecraftColour_Particle_Note_18, - eMinecraftColour_Particle_Note_19, - eMinecraftColour_Particle_Note_20, - eMinecraftColour_Particle_Note_21, - eMinecraftColour_Particle_Note_22, - eMinecraftColour_Particle_Note_23, - eMinecraftColour_Particle_Note_24, - - eMinecraftColour_Particle_NetherPortal, - eMinecraftColour_Particle_EnderPortal, - eMinecraftColour_Particle_Smoke, - eMinecraftColour_Particle_Ender, - eMinecraftColour_Particle_Explode, - eMinecraftColour_Particle_HugeExplosion, - eMinecraftColour_Particle_DripWater, - eMinecraftColour_Particle_DripLavaStart, - eMinecraftColour_Particle_DripLavaEnd, - eMinecraftColour_Particle_EnchantmentTable, - eMinecraftColour_Particle_DragonBreathMin, - eMinecraftColour_Particle_DragonBreathMax, - eMinecraftColour_Particle_Suspend, - eMinecraftColour_Particle_CritStart, - eMinecraftColour_Particle_CritEnd, - - eMinecraftColour_Effect_MovementSpeed, - eMinecraftColour_Effect_MovementSlowDown, - eMinecraftColour_Effect_DigSpeed, - eMinecraftColour_Effect_DigSlowdown, - eMinecraftColour_Effect_DamageBoost, - eMinecraftColour_Effect_Heal, - eMinecraftColour_Effect_Harm, - eMinecraftColour_Effect_Jump, - eMinecraftColour_Effect_Confusion, - eMinecraftColour_Effect_Regeneration, - eMinecraftColour_Effect_DamageResistance, - eMinecraftColour_Effect_FireResistance, - eMinecraftColour_Effect_WaterBreathing, - eMinecraftColour_Effect_Invisiblity, - eMinecraftColour_Effect_Blindness, - eMinecraftColour_Effect_NightVision, - eMinecraftColour_Effect_Hunger, - eMinecraftColour_Effect_Weakness, - eMinecraftColour_Effect_Poison, - eMinecraftColour_Effect_Wither, - eMinecraftColour_Effect_HealthBoost, - eMinecraftColour_Effect_Absoprtion, - eMinecraftColour_Effect_Saturation, - - eMinecraftColour_Potion_BaseColour, - - eMinecraftColour_Mob_Creeper_Colour1, - eMinecraftColour_Mob_Creeper_Colour2, - eMinecraftColour_Mob_Skeleton_Colour1, - eMinecraftColour_Mob_Skeleton_Colour2, - eMinecraftColour_Mob_Spider_Colour1, - eMinecraftColour_Mob_Spider_Colour2, - eMinecraftColour_Mob_Zombie_Colour1, - eMinecraftColour_Mob_Zombie_Colour2, - eMinecraftColour_Mob_Slime_Colour1, - eMinecraftColour_Mob_Slime_Colour2, - eMinecraftColour_Mob_Ghast_Colour1, - eMinecraftColour_Mob_Ghast_Colour2, - eMinecraftColour_Mob_PigZombie_Colour1, - eMinecraftColour_Mob_PigZombie_Colour2, - eMinecraftColour_Mob_Enderman_Colour1, - eMinecraftColour_Mob_Enderman_Colour2, - eMinecraftColour_Mob_CaveSpider_Colour1, - eMinecraftColour_Mob_CaveSpider_Colour2, - eMinecraftColour_Mob_Silverfish_Colour1, - eMinecraftColour_Mob_Silverfish_Colour2, - eMinecraftColour_Mob_Blaze_Colour1, - eMinecraftColour_Mob_Blaze_Colour2, - eMinecraftColour_Mob_LavaSlime_Colour1, - eMinecraftColour_Mob_LavaSlime_Colour2, - eMinecraftColour_Mob_Pig_Colour1, - eMinecraftColour_Mob_Pig_Colour2, - eMinecraftColour_Mob_Sheep_Colour1, - eMinecraftColour_Mob_Sheep_Colour2, - eMinecraftColour_Mob_Cow_Colour1, - eMinecraftColour_Mob_Cow_Colour2, - eMinecraftColour_Mob_Chicken_Colour1, - eMinecraftColour_Mob_Chicken_Colour2, - eMinecraftColour_Mob_Squid_Colour1, - eMinecraftColour_Mob_Squid_Colour2, - eMinecraftColour_Mob_Wolf_Colour1, - eMinecraftColour_Mob_Wolf_Colour2, - eMinecraftColour_Mob_MushroomCow_Colour1, - eMinecraftColour_Mob_MushroomCow_Colour2, - eMinecraftColour_Mob_Ocelot_Colour1, - eMinecraftColour_Mob_Ocelot_Colour2, - eMinecraftColour_Mob_Villager_Colour1, - eMinecraftColour_Mob_Villager_Colour2, - eMinecraftColour_Mob_Bat_Colour1, - eMinecraftColour_Mob_Bat_Colour2, - eMinecraftColour_Mob_Witch_Colour1, - eMinecraftColour_Mob_Witch_Colour2, - eMinecraftColour_Mob_Horse_Colour1, - eMinecraftColour_Mob_Horse_Colour2, - eMinecraftColour_Mob_Rabbit_Colour1, - eMinecraftColour_Mob_Rabbit_Colour2, - eMinecraftColour_Mob_Endermite_Colour1, - eMinecraftColour_Mob_Endermite_Colour2, - eMinecraftColour_Mob_Guardian_Colour1, - eMinecraftColour_Mob_Guardian_Colour2, - eMinecraftColour_Mob_ElderGuardian_Colour1, - eMinecraftColour_Mob_ElderGuardian_Colour2, - - eMinecraftColour_Armour_Default_Leather_Colour, - - eMinecraftColour_Under_Water_Clear_Colour, - eMinecraftColour_Under_Lava_Clear_Colour, - eMinecraftColour_In_Cloud_Base_Colour, - - eMinecraftColour_Under_Water_Fog_Colour, - eMinecraftColour_Under_Lava_Fog_Colour, - eMinecraftColour_In_Cloud_Fog_Colour, - - eMinecraftColour_Default_Fog_Colour, - eMinecraftColour_Nether_Fog_Colour, - eMinecraftColour_End_Fog_Colour, - - eMinecraftColour_Sign_Text, - eMinecraftColour_Map_Text, - - eMinecraftColour_Leash_Light_Colour, - eMinecraftColour_Leash_Dark_Colour, - - eMinecraftColour_Fire_Overlay, - - eHTMLColor_0, - eHTMLColor_1, - eHTMLColor_2, - eHTMLColor_3, - eHTMLColor_4, - eHTMLColor_5, - eHTMLColor_6, - eHTMLColor_7, - eHTMLColor_8, - eHTMLColor_9, - eHTMLColor_a, - eHTMLColor_b, - eHTMLColor_c, - eHTMLColor_d, - eHTMLColor_e, - eHTMLColor_f, - eHTMLColor_0_dark, - eHTMLColor_1_dark, - eHTMLColor_2_dark, - eHTMLColor_3_dark, - eHTMLColor_4_dark, - eHTMLColor_5_dark, - eHTMLColor_6_dark, - eHTMLColor_7_dark, - eHTMLColor_8_dark, - eHTMLColor_9_dark, - eHTMLColor_a_dark, - eHTMLColor_b_dark, - eHTMLColor_c_dark, - eHTMLColor_d_dark, - eHTMLColor_e_dark, - eHTMLColor_f_dark, - eHTMLColor_T1, - eHTMLColor_T2, - eHTMLColor_T3, - eHTMLColor_Black, - eHTMLColor_White, - - eTextColor_Enchant, - eTextColor_EnchantFocus, - eTextColor_EnchantDisabled, - eTextColor_RenamedItemTitle, - - //eHTMLColor_0 = 0x000000, //r:0 , g: 0, b: 0, i: 0 - //eHTMLColor_1 = 0x0000aa, //r:0 , g: 0, b: aa, i: 1 // blue, quite dark - //eHTMLColor_2 = 0x109e10, // Changed by request of Dave //0x00aa00, //r:0 , g: aa, b: 0, i: 2 // green - //eHTMLColor_3 = 0x109e9e, // Changed by request of Dave //0x00aaaa, //r:0 , g: aa, b: aa, i: 3 // cyan - //eHTMLColor_4 = 0xaa0000, //r:aa , g: 0, b: 0, i: 4 // red - //eHTMLColor_5 = 0xaa00aa, //r:aa , g: 0, b: aa, i: 5 // purple - //eHTMLColor_6 = 0xffaa00, //r:ff , g: aa, b: 0, i: 6 // orange - //eHTMLColor_7 = 0xaaaaaa, //r:aa , g: aa, b: aa, i: 7 // light gray - //eHTMLColor_8 = 0x555555, //r:55 , g: 55, b: 55, i: 8 // gray - //eHTMLColor_9 = 0x5555ff, //r:55 , g: 55, b: ff, i: 9 // blue - //eHTMLColor_a = 0x55ff55, //r:55 , g: ff, b: 55, i: a // green - //eHTMLColor_b = 0x55ffff, //r:55 , g: ff, b: ff, i: b // cyan - //eHTMLColor_c = 0xff5555, //r:ff , g: 55, b: 55, i: c // red pink - //eHTMLColor_d = 0xff55ff, //r:ff , g: 55, b: ff, i: d // bright pink - //eHTMLColor_e = 0xffff55, //r:ff , g: ff, b: 55, i: e // yellow - //eHTMLColor_f = 0xffffff, //r:ff , g: ff, b: ff, i: f - //eHTMLColor_0_dark = 0x000000, //r:0 , g: 0, b: 0, i: 10 - //eHTMLColor_1_dark = 0x00002a, //r:0 , g: 0, b: 2a, i: 11 - //eHTMLColor_2_dark = 0x002a00, //r:0 , g: 2a, b: 0, i: 12 - //eHTMLColor_3_dark = 0x002a2a, //r:0 , g: 2a, b: 2a, i: 13 - //eHTMLColor_4_dark = 0x2a0000, //r:2a , g: 0, b: 0, i: 14 - //eHTMLColor_5_dark = 0x2a002a, //r:2a , g: 0, b: 2a, i: 15 - //eHTMLColor_6_dark = 0x2a2a00, //r:2a , g: 2a, b: 0, i: 16 - //eHTMLColor_7_dark = 0x2a2a2a, //r:2a , g: 2a, b: 2a, i: 17 // dark gray - //eHTMLColor_8_dark = 0x151515, //r:15 , g: 15, b: 15, i: 18 - //eHTMLColor_9_dark = 0x15153f, //r:15 , g: 15, b: 3f, i: 19 - //eHTMLColor_a_dark = 0x153f15, //r:15 , g: 3f, b: 15, i: 1a - //eHTMLColor_b_dark = 0x153f3f, //r:15 , g: 3f, b: 3f, i: 1b - //eHTMLColor_c_dark = 0x3f1515, //r:3f , g: 15, b: 15, i: 1c // brown - //eHTMLColor_d_dark = 0x3f153f, //r:3f , g: 15, b: 3f, i: 1d - //eHTMLColor_e_dark = 0x3f3f15, //r:3f , g: 3f, b: 15, i: 1e - //eHTMLColor_f_dark = 0x3f3f3f, //r:3f , g: 3f, b: 3f, i: 1f - - eMinecraftColour_COUNT, -}; - -enum eDLCContentType -{ - e_DLC_SkinPack=0, - e_DLC_TexturePacks, - e_DLC_MashupPacks, - e_DLC_Themes, - e_DLC_AvatarItems, - e_DLC_Gamerpics, - e_DLC_MAX_MinecraftStore, - e_DLC_TexturePackData, // for the icon, banner and text - e_DLC_MAX, - e_DLC_NotDefined, -}; - -enum eDLCMarketplaceType -{ - e_Marketplace_Content=0, // skins, texture packs and mashup packs - e_Marketplace_Themes, - e_Marketplace_AvatarItems, - e_Marketplace_Gamerpics, - e_Marketplace_MAX, - e_Marketplace_NotDefined, -}; - -enum eDLCContentState -{ - e_DLC_ContentState_Idle = 0, - e_DLC_ContentState_Retrieving, - e_DLC_ContentState_Retrieved -}; - -enum eTMSContentState -{ - e_TMS_ContentState_Idle = 0, - e_TMS_ContentState_Queued, - e_TMS_ContentState_Retrieving, - e_TMS_ContentState_Retrieved -}; - -enum eXUID -{ - eXUID_Undefined=0, - eXUID_NoName, // name not needed - eXUID_Notch, - eXUID_Carl, - eXUID_Daniel, - eXUID_Deadmau5, - eXUID_DannyBStyle, - eXUID_JulianClark, - eXUID_Millionth, - eXUID_4JPaddy, - eXUID_4JStuart, - eXUID_4JDavid, - eXUID_4JRichard, - eXUID_4JSteven, -}; - - -enum _eTerrainFeatureType -{ - eTerrainFeature_None=0, - eTerrainFeature_Stronghold, - eTerrainFeature_Mineshaft, - eTerrainFeature_Village, - eTerrainFeature_Ravine, - eTerrainFeature_NetherFortress, - eTerrainFeature_StrongholdEndPortal, - eTerrainFeature_OceanMonument, - eTerrainFeature_Count -}; - -// 4J Stu - Whend adding new options you should consider whether having them on should disable achievements, and if so add them to the CanRecordStatsAndAchievements function -// 4J Stu - These options are now saved in save data, so new options can ONLY be added to the end -enum eGameHostOption -{ - eGameHostOption_Difficulty=0, - eGameHostOption_OnlineGame, // Unused - eGameHostOption_InviteOnly, // Unused - eGameHostOption_FriendsOfFriends, - eGameHostOption_Gamertags, - eGameHostOption_Tutorial, // special case - eGameHostOption_GameType, - eGameHostOption_LevelType, // flat or default - eGameHostOption_Structures, - eGameHostOption_BonusChest, - eGameHostOption_HasBeenInCreative, - eGameHostOption_PvP, - eGameHostOption_TrustPlayers, - eGameHostOption_TNT, - eGameHostOption_FireSpreads, - eGameHostOption_CheatsEnabled, // special case - eGameHostOption_HostCanFly, - eGameHostOption_HostCanChangeHunger, - eGameHostOption_HostCanBeInvisible, - eGameHostOption_BedrockFog, - eGameHostOption_NoHUD, - eGameHostOption_WorldSize, - eGameHostOption_All, - - eGameHostOption_DisableSaving, - eGameHostOption_WasntSaveOwner, // Added for PS3 save transfer, so we can add a nice message in the future instead of the creative mode one - - eGameHostOption_MobGriefing, - eGameHostOption_KeepInventory, - eGameHostOption_DoMobSpawning, - eGameHostOption_DoMobLoot, - eGameHostOption_DoTileDrops, - eGameHostOption_NaturalRegeneration, - eGameHostOption_DoDaylightCycle, - eGameHostOption_Hardcore, // 4J Added - for hardcore mode -}; - -// 4J-PB - If any new DLC items are added to the TMSFiles, this array needs updated -#ifdef _XBOX -enum _TMSFILES -{ - TMS_SP1=0, - TMS_SP2, - TMS_SP3, - TMS_SP4, - TMS_SP5, - TMS_SP6, - TMS_SPF, - TMS_SPB, - TMS_SPC, - TMS_SPZ, - TMS_SPM, - TMS_SPI, - TMS_SPG, - TMS_SPD1, - TMS_SPSW1, - - TMS_THST, - TMS_THIR, - TMS_THGO, - TMS_THDI, - TMS_THAW, - - TMS_GPAN, - TMS_GPCO, - TMS_GPEN, - TMS_GPFO, - TMS_GPTO, - TMS_GPBA, - TMS_GPFA, - TMS_GPME, - TMS_GPMF, - TMS_GPMM, - TMS_GPSE, - TMS_GPOr, - TMS_GPMi, - TMS_GPMB, - TMS_GPBr, - TMS_GPM1, - TMS_GPM2, - TMS_GPM3, - - TMS_AH_0001, - TMS_AH_0002, - TMS_AH_0003, - TMS_AH_0004, - TMS_AH_0005, - TMS_AH_0006, - TMS_AH_0007, - TMS_AH_0008, - TMS_AH_0009, - TMS_AH_0010, - TMS_AH_0011, - TMS_AH_0012, - TMS_AH_0013, - - TMS_AT_0001, - TMS_AT_0002, - TMS_AT_0003, - TMS_AT_0004, - TMS_AT_0005, - TMS_AT_0006, - TMS_AT_0007, - TMS_AT_0008, - TMS_AT_0009, - TMS_AT_0010, - TMS_AT_0011, - TMS_AT_0012, - TMS_AT_0013, - TMS_AT_0014, - TMS_AT_0015, - TMS_AT_0016, - TMS_AT_0017, - TMS_AT_0018, - TMS_AT_0019, - TMS_AT_0020, - TMS_AT_0021, - TMS_AT_0022, - TMS_AT_0023, - TMS_AT_0024, - TMS_AT_0025, - TMS_AT_0026, - - TMS_AP_0001, - TMS_AP_0002, - TMS_AP_0003, - TMS_AP_0004, - TMS_AP_0005, - TMS_AP_0006, - TMS_AP_0007, - TMS_AP_0009, - TMS_AP_0010, - TMS_AP_0011, - TMS_AP_0012, - TMS_AP_0013, - TMS_AP_0014, - TMS_AP_0015, - TMS_AP_0016, - TMS_AP_0017, - TMS_AP_0018, - - TMS_AP_0019, - TMS_AP_0020, - TMS_AP_0021, - TMS_AP_0022, - TMS_AP_0023, - TMS_AP_0024, - TMS_AP_0025, - TMS_AP_0026, - TMS_AP_0027, - TMS_AP_0028, - TMS_AP_0029, - TMS_AP_0030, - TMS_AP_0031, - TMS_AP_0032, - TMS_AP_0033, - - TMS_AA_0001, - - TMS_MPMA, - TMS_MPMA_DAT, - TMS_MPSR, - TMS_MPSR_DAT, - TMS_MPHA, - TMS_MPHA_DAT, - TMS_MPFE, - TMS_MPFE_DAT, - - TMS_TP01, - TMS_TP01_DAT, - TMS_TP02, - TMS_TP02_DAT, - TMS_TP04, - TMS_TP04_DAT, - TMS_TP05, - TMS_TP05_DAT, - TMS_TP06, - TMS_TP06_DAT, - TMS_TP07, - TMS_TP07_DAT, - TMS_TP08, - TMS_TP08_DAT, - - TMS_COUNT -}; -#endif - -enum EHTMLFontSize -{ - eHTMLSize_Normal, - eHTMLSize_Splitscreen, - eHTMLSize_Tutorial, - eHTMLSize_EndPoem, - - eHTMLSize_COUNT, -}; - -enum EControllerActions -{ - ACTION_MENU_A, - ACTION_MENU_B, - ACTION_MENU_X, - ACTION_MENU_Y, - ACTION_MENU_UP, - ACTION_MENU_DOWN, - ACTION_MENU_RIGHT, - ACTION_MENU_LEFT, - ACTION_MENU_PAGEUP, - ACTION_MENU_PAGEDOWN, - ACTION_MENU_RIGHT_SCROLL, - ACTION_MENU_LEFT_SCROLL, - ACTION_MENU_STICK_PRESS, - ACTION_MENU_OTHER_STICK_PRESS, - ACTION_MENU_OTHER_STICK_UP, - ACTION_MENU_OTHER_STICK_DOWN, - ACTION_MENU_OTHER_STICK_LEFT, - ACTION_MENU_OTHER_STICK_RIGHT, - ACTION_MENU_PAUSEMENU, - ACTION_MENU_QUICK_MOVE, - -#ifdef _DURANGO - ACTION_MENU_GTC_PAUSE, - ACTION_MENU_GTC_RESUME, -#endif - -#ifdef __ORBIS__ - ACTION_MENU_TOUCHPAD_PRESS, -#endif - - ACTION_MENU_OK, - ACTION_MENU_CANCEL, - ACTION_MAX_MENU = ACTION_MENU_CANCEL, - - MINECRAFT_ACTION_JUMP, - MINECRAFT_ACTION_FORWARD, - MINECRAFT_ACTION_BACKWARD, - MINECRAFT_ACTION_LEFT, - MINECRAFT_ACTION_RIGHT, - MINECRAFT_ACTION_LOOK_LEFT, - MINECRAFT_ACTION_LOOK_RIGHT, - MINECRAFT_ACTION_LOOK_UP, - MINECRAFT_ACTION_LOOK_DOWN, - MINECRAFT_ACTION_USE, - MINECRAFT_ACTION_ACTION, - MINECRAFT_ACTION_LEFT_SCROLL, - MINECRAFT_ACTION_RIGHT_SCROLL, - MINECRAFT_ACTION_INVENTORY, - MINECRAFT_ACTION_PAUSEMENU, - MINECRAFT_ACTION_DROP, - MINECRAFT_ACTION_SNEAK_TOGGLE, - MINECRAFT_ACTION_CRAFTING, - MINECRAFT_ACTION_RENDER_THIRD_PERSON, - MINECRAFT_ACTION_GAME_INFO, - MINECRAFT_ACTION_DPAD_LEFT, - MINECRAFT_ACTION_DPAD_RIGHT, - MINECRAFT_ACTION_DPAD_UP, - MINECRAFT_ACTION_DPAD_DOWN, - - MINECRAFT_ACTION_MAX, - - // These 4 aren't mapped to the input manager directly but are created from the dpad controls if required in Minecraft::run_middle - // Don't use them with the input manager directly, just through LocalPlayer::ullButtonsPressed - MINECRAFT_ACTION_SPAWN_CREEPER, - MINECRAFT_ACTION_CHANGE_SKIN, - MINECRAFT_ACTION_FLY_TOGGLE, - MINECRAFT_ACTION_RENDER_DEBUG, - MINECRAFT_ACTION_SCREENSHOT -}; - -enum eMCLang -{ - eMCLang_null=0, - eMCLang_enUS, - eMCLang_enGB, - eMCLang_enIE, - eMCLang_enAU, - eMCLang_enNZ, - eMCLang_enCA, - eMCLang_jaJP, - eMCLang_deDE, - eMCLang_deAT, - eMCLang_frFR, - eMCLang_frCA, - eMCLang_esES, - eMCLang_esMX, - eMCLang_itIT, - eMCLang_koKR, - eMCLang_ptPT, - eMCLang_ptBR, - eMCLang_ruRU, - eMCLang_nlNL, - eMCLang_fiFI, - eMCLang_svSV, - eMCLang_daDA, - eMCLang_noNO, - eMCLang_plPL, - eMCLang_trTR, - eMCLang_elEL, - eMCLang_csCS, - eMCLang_zhCHT, - eMCLang_laLAS, - - eMCLang_zhSG, - eMCLang_zhCN, - eMCLang_zhHK, - eMCLang_zhTW, - eMCLang_nlBE, - eMCLang_daDK, - eMCLang_frBE, - eMCLang_frCH, - eMCLang_deCH, - eMCLang_nbNO, - eMCLang_enGR, - eMCLang_enHK, - eMCLang_enSA, - eMCLang_enHU, - eMCLang_enIN, - eMCLang_enIL, - eMCLang_enSG, - eMCLang_enSK, - eMCLang_enZA, - eMCLang_enCZ, - eMCLang_enAE, - eMCLang_esAR, - eMCLang_esCL, - eMCLang_esCO, - eMCLang_esUS, - eMCLang_svSE, - - eMCLang_csCZ, - eMCLang_elGR, - eMCLang_nnNO, - eMCLang_skSK, - - eMCLang_hans, - eMCLang_hant, -}; +#pragma once + +enum eFileExtensionType +{ + eFileExtensionType_PNG=0, + eFileExtensionType_INF, + eFileExtensionType_DAT, +}; + +enum eTMSFileType +{ + eTMSFileType_MinecraftStore=0, + eTMSFileType_TexturePack, + eTMSFileType_All +}; + +enum eTPDFileType +{ + eTPDFileType_Loc=0, + eTPDFileType_Icon, +// eTPDFileType_Banner, + eTPDFileType_Comparison, +}; + +enum eFont +{ + eFont_European=0, + eFont_Korean, + eFont_Japanese, + eFont_Chinese, + eFont_None, // to fallback to nothing +}; + +enum eXuiAction +{ + eAppAction_Idle=0, + eAppAction_SaveGame, + eAppAction_SaveGameCapturedThumbnail, + eAppAction_ExitWorld, + eAppAction_ExitWorldCapturedThumbnail, + eAppAction_ExitWorldTrial, + //eAppAction_ExitGameFatalLoadError, + eAppAction_Respawn, + eAppAction_WaitForRespawnComplete, + eAppAction_PrimaryPlayerSignedOut, + eAppAction_PrimaryPlayerSignedOutReturned, + eAppAction_PrimaryPlayerSignedOutReturned_Menus, + eAppAction_ExitPlayer, // secondary player + eAppAction_ExitPlayerPreLogin, + eAppAction_TrialOver, + eAppAction_ExitTrial, + eAppAction_WaitForDimensionChangeComplete, + eAppAction_SocialPost, + eAppAction_SocialPostScreenshot, + eAppAction_EthernetDisconnected, + eAppAction_EthernetDisconnectedReturned, + eAppAction_EthernetDisconnectedReturned_Menus, + eAppAction_ExitAndJoinFromInvite, + eAppAction_DashboardTrialJoinFromInvite, + eAppAction_ExitAndJoinFromInviteConfirmed, + eAppAction_JoinFromInvite, + eAppAction_ChangeSessionType, + eAppAction_SetDefaultOptions, + eAppAction_LocalPlayerJoined, + eAppAction_RemoteServerSave, + eAppAction_WaitRemoteServerSaveComplete, + eAppAction_FailedToJoinNoPrivileges, + eAppAction_AutosaveSaveGame, + eAppAction_AutosaveSaveGameCapturedThumbnail, + eAppAction_ProfileReadError, + eAppAction_DisplayLavaMessage, + eAppAction_BanLevel, + eAppAction_LevelInBanLevelList, + + eAppAction_ReloadTexturePack, + eAppAction_ReloadFont, + eAppAction_TexturePackRequired, // when the user has joined from invite, but doesn't have the texture pack + +#ifdef __ORBIS__ + eAppAction_OptionsSaveNoSpace, +#endif + eAppAction_DebugText, + +}; + + + +enum eTMSAction +{ + eTMSAction_Idle=0, + eTMSAction_TMS_RetrieveFiles_Complete, + eTMSAction_TMSPP_RetrieveFiles_CreateLoad_SignInReturned, + eTMSAction_TMSPP_RetrieveFiles_RunPlayGame, + eTMSAction_TMSPP_RetrieveFiles_HelpAndOptions, + eTMSAction_TMSPP_RetrieveFiles_DLCMain, + eTMSAction_TMSPP_GlobalFileList, + eTMSAction_TMSPP_GlobalFileList_Waiting, +// eTMSAction_TMSPP_ConfigFile, +// eTMSAction_TMSPP_ConfigFile_Waiting, + eTMSAction_TMSPP_UserFileList, + eTMSAction_TMSPP_UserFileList_Waiting, + eTMSAction_TMSPP_XUIDSFile, + eTMSAction_TMSPP_XUIDSFile_Waiting, + eTMSAction_TMSPP_DLCFile, + eTMSAction_TMSPP_DLCFile_Waiting, + eTMSAction_TMSPP_BannedListFile, + eTMSAction_TMSPP_BannedListFile_Waiting, + eTMSAction_TMSPP_RetrieveFiles_Complete, + eTMSAction_TMSPP_DLCFileOnly, + eTMSAction_TMSPP_RetrieveUserFilelist_DLCFileOnly, +}; + +// The server runs on its own thread, so we need to call its actions there rather than where all other Xui actions are performed +// In general these are debugging options +enum eXuiServerAction +{ + eXuiServerAction_Idle=0, + eXuiServerAction_DropItem, // Debug + eXuiServerAction_SaveGame, + eXuiServerAction_AutoSaveGame, + eXuiServerAction_SpawnMob, // Debug + eXuiServerAction_PauseServer, + eXuiServerAction_ToggleRain, // Debug + eXuiServerAction_ToggleThunder, // Debug + eXuiServerAction_ServerSettingChanged_Gamertags, + eXuiServerAction_ServerSettingChanged_Difficulty, + eXuiServerAction_ExportSchematic, //Debug + eXuiServerAction_ServerSettingChanged_BedrockFog, + eXuiServerAction_SetCameraLocation, //Debug +}; + +enum eGameSetting +{ + eGameSetting_MusicVolume=0, + eGameSetting_SoundFXVolume, + eGameSetting_RenderDistance, + eGameSetting_Gamma, + eGameSetting_FOV, + eGameSetting_Difficulty, + eGameSetting_Sensitivity_InGame, + eGameSetting_Sensitivity_InMenu, + eGameSetting_ViewBob, + eGameSetting_ControlScheme, + eGameSetting_ControlInvertLook, + eGameSetting_ControlSouthPaw, + eGameSetting_SplitScreenVertical, + eGameSetting_GamertagsVisible, + // Interim TU 1.6.6 + eGameSetting_Autosave, + eGameSetting_DisplaySplitscreenGamertags, + eGameSetting_Hints, + eGameSetting_InterfaceOpacity, + eGameSetting_Tooltips, + // TU5 + eGameSetting_Clouds, + eGameSetting_Online, + eGameSetting_InviteOnly, + eGameSetting_FriendsOfFriends, + eGameSetting_DisplayUpdateMessage, + + // TU6 + eGameSetting_BedrockFog, + eGameSetting_DisplayHUD, + eGameSetting_DisplayHand, + + // TU7 + eGameSetting_CustomSkinAnim, + + // TU9 + eGameSetting_DeathMessages, + eGameSetting_UISize, + eGameSetting_UISizeSplitscreen, + eGameSetting_AnimatedCharacter, + + // PS3 + eGameSetting_PS3_EULA_Read, + + // PSVita + eGameSetting_PSVita_NetworkModeAdhoc, + + // PC + eGameSetting_VSync, + eGameSetting_ExclusiveFullscreen, + + //TU25 + eGameSetting_ClassicCrafting, + eGameSetting_CaveSounds, + eGameSetting_MinecartSounds, + eGameSetting_ControlType, + // if enabled hides the save size bar in loadcreatejoinmenu (load tab) + eGameSetting_HideSaveSizeBar, + // TU31 + eGameSetting_SafeCam, //safe cam is safe sprint + eGameSetting_Swap, + eGameSetting_GameChat, +}; + + + +enum eGameMode +{ + eMode_Singleplayer, + eMode_Multiplayer +}; + + +enum eMinecraftColour +{ + eMinecraftColour_NOT_SET, + + eMinecraftColour_Foliage_Evergreen, + eMinecraftColour_Foliage_Birch, + eMinecraftColour_Foliage_Default, + eMinecraftColour_Foliage_Common, + eMinecraftColour_Foliage_Ocean, + eMinecraftColour_Foliage_Plains, + eMinecraftColour_Foliage_Desert, + eMinecraftColour_Foliage_ExtremeHills, + eMinecraftColour_Foliage_Forest, + eMinecraftColour_Foliage_Taiga, + eMinecraftColour_Foliage_Swampland, + eMinecraftColour_Foliage_River, + eMinecraftColour_Foliage_Hell, + eMinecraftColour_Foliage_Sky, + eMinecraftColour_Foliage_FrozenOcean, + eMinecraftColour_Foliage_FrozenRiver, + eMinecraftColour_Foliage_IcePlains, + eMinecraftColour_Foliage_IceMountains, + eMinecraftColour_Foliage_MushroomIsland, + eMinecraftColour_Foliage_MushroomIslandShore, + eMinecraftColour_Foliage_Beach, + eMinecraftColour_Foliage_DesertHills, + eMinecraftColour_Foliage_ForestHills, + eMinecraftColour_Foliage_TaigaHills, + eMinecraftColour_Foliage_ExtremeHillsEdge, + eMinecraftColour_Foliage_Jungle, + eMinecraftColour_Foliage_JungleHills, + eMinecraftColour_Foliage_Savanna, + eMinecraftColour_Foliage_RoofedForest, + eMinecraftColour_Foliage_Mesa, + + eMinecraftColour_Grass_Common, + eMinecraftColour_Grass_Ocean, + eMinecraftColour_Grass_Plains, + eMinecraftColour_Grass_Desert, + eMinecraftColour_Grass_ExtremeHills, + eMinecraftColour_Grass_Forest, + eMinecraftColour_Grass_Taiga, + eMinecraftColour_Grass_Swampland, + eMinecraftColour_Grass_River, + eMinecraftColour_Grass_Hell, + eMinecraftColour_Grass_Sky, + eMinecraftColour_Grass_FrozenOcean, + eMinecraftColour_Grass_FrozenRiver, + eMinecraftColour_Grass_IcePlains, + eMinecraftColour_Grass_IceMountains, + eMinecraftColour_Grass_MushroomIsland, + eMinecraftColour_Grass_MushroomIslandShore, + eMinecraftColour_Grass_Beach, + eMinecraftColour_Grass_DesertHills, + eMinecraftColour_Grass_ForestHills, + eMinecraftColour_Grass_TaigaHills, + eMinecraftColour_Grass_ExtremeHillsEdge, + eMinecraftColour_Grass_Jungle, + eMinecraftColour_Grass_JungleHills, + eMinecraftColour_Grass_Savanna, + eMinecraftColour_Grass_RoofedForest, + eMinecraftColour_Grass_Mesa, + + eMinecraftColour_Water_Ocean, + eMinecraftColour_Water_Plains, + eMinecraftColour_Water_Desert, + eMinecraftColour_Water_ExtremeHills, + eMinecraftColour_Water_Forest, + eMinecraftColour_Water_Taiga, + eMinecraftColour_Water_Swampland, + eMinecraftColour_Water_River, + eMinecraftColour_Water_Hell, + eMinecraftColour_Water_Sky, + eMinecraftColour_Water_FrozenOcean, + eMinecraftColour_Water_FrozenRiver, + eMinecraftColour_Water_IcePlains, + eMinecraftColour_Water_IceMountains, + eMinecraftColour_Water_MushroomIsland, + eMinecraftColour_Water_MushroomIslandShore, + eMinecraftColour_Water_Beach, + eMinecraftColour_Water_DesertHills, + eMinecraftColour_Water_ForestHills, + eMinecraftColour_Water_TaigaHills, + eMinecraftColour_Water_ExtremeHillsEdge, + eMinecraftColour_Water_Jungle, + eMinecraftColour_Water_JungleHills, + eMinecraftColour_Water_JungleEdge, + eMinecraftColour_Water_Mesa, + + eMinecraftColour_Sky_Ocean, + eMinecraftColour_Sky_Plains, + eMinecraftColour_Sky_Desert, + eMinecraftColour_Sky_ExtremeHills, + eMinecraftColour_Sky_Forest, + eMinecraftColour_Sky_Taiga, + eMinecraftColour_Sky_Swampland, + eMinecraftColour_Sky_River, + eMinecraftColour_Sky_Hell, + eMinecraftColour_Sky_Sky, + eMinecraftColour_Sky_FrozenOcean, + eMinecraftColour_Sky_FrozenRiver, + eMinecraftColour_Sky_IcePlains, + eMinecraftColour_Sky_IceMountains, + eMinecraftColour_Sky_MushroomIsland, + eMinecraftColour_Sky_MushroomIslandShore, + eMinecraftColour_Sky_Beach, + eMinecraftColour_Sky_DesertHills, + eMinecraftColour_Sky_ForestHills, + eMinecraftColour_Sky_TaigaHills, + eMinecraftColour_Sky_ExtremeHillsEdge, + eMinecraftColour_Sky_Jungle, + eMinecraftColour_Sky_JungleHills, + eMinecraftColour_Sky_JungleEdge, + + eMinecraftColour_Tile_RedstoneDust, + eMinecraftColour_Tile_RedstoneDustUnlit, + eMinecraftColour_Tile_RedstoneDustLitMin, + eMinecraftColour_Tile_RedstoneDustLitMax, + eMinecraftColour_Tile_StemMin, + eMinecraftColour_Tile_StemMax, + eMinecraftColour_Tile_WaterLily, + + eMinecraftColour_Sky_Dawn_Dark, + eMinecraftColour_Sky_Dawn_Bright, + + eMinecraftColour_Material_None, + eMinecraftColour_Material_Grass, + eMinecraftColour_Material_Sand, + eMinecraftColour_Material_Cloth, + eMinecraftColour_Material_Fire, + eMinecraftColour_Material_Ice, + eMinecraftColour_Material_Metal, + eMinecraftColour_Material_Plant, + eMinecraftColour_Material_Snow, + eMinecraftColour_Material_Clay, + eMinecraftColour_Material_Dirt, + eMinecraftColour_Material_Stone, + eMinecraftColour_Material_Water, + eMinecraftColour_Material_Wood, + eMinecraftColour_Material_Emerald, + + eMinecraftColour_Particle_Note_00, + eMinecraftColour_Particle_Note_01, + eMinecraftColour_Particle_Note_02, + eMinecraftColour_Particle_Note_03, + eMinecraftColour_Particle_Note_04, + eMinecraftColour_Particle_Note_05, + eMinecraftColour_Particle_Note_06, + eMinecraftColour_Particle_Note_07, + eMinecraftColour_Particle_Note_08, + eMinecraftColour_Particle_Note_09, + eMinecraftColour_Particle_Note_10, + eMinecraftColour_Particle_Note_11, + eMinecraftColour_Particle_Note_12, + eMinecraftColour_Particle_Note_13, + eMinecraftColour_Particle_Note_14, + eMinecraftColour_Particle_Note_15, + eMinecraftColour_Particle_Note_16, + eMinecraftColour_Particle_Note_17, + eMinecraftColour_Particle_Note_18, + eMinecraftColour_Particle_Note_19, + eMinecraftColour_Particle_Note_20, + eMinecraftColour_Particle_Note_21, + eMinecraftColour_Particle_Note_22, + eMinecraftColour_Particle_Note_23, + eMinecraftColour_Particle_Note_24, + + eMinecraftColour_Particle_NetherPortal, + eMinecraftColour_Particle_EnderPortal, + eMinecraftColour_Particle_Smoke, + eMinecraftColour_Particle_Ender, + eMinecraftColour_Particle_Explode, + eMinecraftColour_Particle_HugeExplosion, + eMinecraftColour_Particle_DripWater, + eMinecraftColour_Particle_DripLavaStart, + eMinecraftColour_Particle_DripLavaEnd, + eMinecraftColour_Particle_EnchantmentTable, + eMinecraftColour_Particle_DragonBreathMin, + eMinecraftColour_Particle_DragonBreathMax, + eMinecraftColour_Particle_Suspend, + eMinecraftColour_Particle_CritStart, + eMinecraftColour_Particle_CritEnd, + + eMinecraftColour_Effect_MovementSpeed, + eMinecraftColour_Effect_MovementSlowDown, + eMinecraftColour_Effect_DigSpeed, + eMinecraftColour_Effect_DigSlowdown, + eMinecraftColour_Effect_DamageBoost, + eMinecraftColour_Effect_Heal, + eMinecraftColour_Effect_Harm, + eMinecraftColour_Effect_Jump, + eMinecraftColour_Effect_Confusion, + eMinecraftColour_Effect_Regeneration, + eMinecraftColour_Effect_DamageResistance, + eMinecraftColour_Effect_FireResistance, + eMinecraftColour_Effect_WaterBreathing, + eMinecraftColour_Effect_Invisiblity, + eMinecraftColour_Effect_Blindness, + eMinecraftColour_Effect_NightVision, + eMinecraftColour_Effect_Hunger, + eMinecraftColour_Effect_Weakness, + eMinecraftColour_Effect_Poison, + eMinecraftColour_Effect_Wither, + eMinecraftColour_Effect_HealthBoost, + eMinecraftColour_Effect_Absoprtion, + eMinecraftColour_Effect_Saturation, + + eMinecraftColour_Potion_BaseColour, + + eMinecraftColour_Mob_Creeper_Colour1, + eMinecraftColour_Mob_Creeper_Colour2, + eMinecraftColour_Mob_Skeleton_Colour1, + eMinecraftColour_Mob_Skeleton_Colour2, + eMinecraftColour_Mob_Spider_Colour1, + eMinecraftColour_Mob_Spider_Colour2, + eMinecraftColour_Mob_Zombie_Colour1, + eMinecraftColour_Mob_Zombie_Colour2, + eMinecraftColour_Mob_Slime_Colour1, + eMinecraftColour_Mob_Slime_Colour2, + eMinecraftColour_Mob_Ghast_Colour1, + eMinecraftColour_Mob_Ghast_Colour2, + eMinecraftColour_Mob_PigZombie_Colour1, + eMinecraftColour_Mob_PigZombie_Colour2, + eMinecraftColour_Mob_Enderman_Colour1, + eMinecraftColour_Mob_Enderman_Colour2, + eMinecraftColour_Mob_CaveSpider_Colour1, + eMinecraftColour_Mob_CaveSpider_Colour2, + eMinecraftColour_Mob_Silverfish_Colour1, + eMinecraftColour_Mob_Silverfish_Colour2, + eMinecraftColour_Mob_Blaze_Colour1, + eMinecraftColour_Mob_Blaze_Colour2, + eMinecraftColour_Mob_LavaSlime_Colour1, + eMinecraftColour_Mob_LavaSlime_Colour2, + eMinecraftColour_Mob_Pig_Colour1, + eMinecraftColour_Mob_Pig_Colour2, + eMinecraftColour_Mob_Sheep_Colour1, + eMinecraftColour_Mob_Sheep_Colour2, + eMinecraftColour_Mob_Cow_Colour1, + eMinecraftColour_Mob_Cow_Colour2, + eMinecraftColour_Mob_Chicken_Colour1, + eMinecraftColour_Mob_Chicken_Colour2, + eMinecraftColour_Mob_Squid_Colour1, + eMinecraftColour_Mob_Squid_Colour2, + eMinecraftColour_Mob_Wolf_Colour1, + eMinecraftColour_Mob_Wolf_Colour2, + eMinecraftColour_Mob_MushroomCow_Colour1, + eMinecraftColour_Mob_MushroomCow_Colour2, + eMinecraftColour_Mob_Ocelot_Colour1, + eMinecraftColour_Mob_Ocelot_Colour2, + eMinecraftColour_Mob_Villager_Colour1, + eMinecraftColour_Mob_Villager_Colour2, + eMinecraftColour_Mob_Bat_Colour1, + eMinecraftColour_Mob_Bat_Colour2, + eMinecraftColour_Mob_Witch_Colour1, + eMinecraftColour_Mob_Witch_Colour2, + eMinecraftColour_Mob_Horse_Colour1, + eMinecraftColour_Mob_Horse_Colour2, + eMinecraftColour_Mob_Rabbit_Colour1, + eMinecraftColour_Mob_Rabbit_Colour2, + eMinecraftColour_Mob_Endermite_Colour1, + eMinecraftColour_Mob_Endermite_Colour2, + eMinecraftColour_Mob_Guardian_Colour1, + eMinecraftColour_Mob_Guardian_Colour2, + eMinecraftColour_Mob_ElderGuardian_Colour1, + eMinecraftColour_Mob_ElderGuardian_Colour2, + + eMinecraftColour_Armour_Default_Leather_Colour, + + eMinecraftColour_Under_Water_Clear_Colour, + eMinecraftColour_Under_Lava_Clear_Colour, + eMinecraftColour_In_Cloud_Base_Colour, + + eMinecraftColour_Under_Water_Fog_Colour, + eMinecraftColour_Under_Lava_Fog_Colour, + eMinecraftColour_In_Cloud_Fog_Colour, + + eMinecraftColour_Default_Fog_Colour, + eMinecraftColour_Nether_Fog_Colour, + eMinecraftColour_End_Fog_Colour, + + eMinecraftColour_Sign_Text, + eMinecraftColour_Map_Text, + + eMinecraftColour_Leash_Light_Colour, + eMinecraftColour_Leash_Dark_Colour, + + eMinecraftColour_Fire_Overlay, + + eHTMLColor_0, + eHTMLColor_1, + eHTMLColor_2, + eHTMLColor_3, + eHTMLColor_4, + eHTMLColor_5, + eHTMLColor_6, + eHTMLColor_7, + eHTMLColor_8, + eHTMLColor_9, + eHTMLColor_a, + eHTMLColor_b, + eHTMLColor_c, + eHTMLColor_d, + eHTMLColor_e, + eHTMLColor_f, + eHTMLColor_0_dark, + eHTMLColor_1_dark, + eHTMLColor_2_dark, + eHTMLColor_3_dark, + eHTMLColor_4_dark, + eHTMLColor_5_dark, + eHTMLColor_6_dark, + eHTMLColor_7_dark, + eHTMLColor_8_dark, + eHTMLColor_9_dark, + eHTMLColor_a_dark, + eHTMLColor_b_dark, + eHTMLColor_c_dark, + eHTMLColor_d_dark, + eHTMLColor_e_dark, + eHTMLColor_f_dark, + eHTMLColor_T1, + eHTMLColor_T2, + eHTMLColor_T3, + eHTMLColor_Black, + eHTMLColor_White, + + eTextColor_Enchant, + eTextColor_EnchantFocus, + eTextColor_EnchantDisabled, + eTextColor_RenamedItemTitle, + + //eHTMLColor_0 = 0x000000, //r:0 , g: 0, b: 0, i: 0 + //eHTMLColor_1 = 0x0000aa, //r:0 , g: 0, b: aa, i: 1 // blue, quite dark + //eHTMLColor_2 = 0x109e10, // Changed by request of Dave //0x00aa00, //r:0 , g: aa, b: 0, i: 2 // green + //eHTMLColor_3 = 0x109e9e, // Changed by request of Dave //0x00aaaa, //r:0 , g: aa, b: aa, i: 3 // cyan + //eHTMLColor_4 = 0xaa0000, //r:aa , g: 0, b: 0, i: 4 // red + //eHTMLColor_5 = 0xaa00aa, //r:aa , g: 0, b: aa, i: 5 // purple + //eHTMLColor_6 = 0xffaa00, //r:ff , g: aa, b: 0, i: 6 // orange + //eHTMLColor_7 = 0xaaaaaa, //r:aa , g: aa, b: aa, i: 7 // light gray + //eHTMLColor_8 = 0x555555, //r:55 , g: 55, b: 55, i: 8 // gray + //eHTMLColor_9 = 0x5555ff, //r:55 , g: 55, b: ff, i: 9 // blue + //eHTMLColor_a = 0x55ff55, //r:55 , g: ff, b: 55, i: a // green + //eHTMLColor_b = 0x55ffff, //r:55 , g: ff, b: ff, i: b // cyan + //eHTMLColor_c = 0xff5555, //r:ff , g: 55, b: 55, i: c // red pink + //eHTMLColor_d = 0xff55ff, //r:ff , g: 55, b: ff, i: d // bright pink + //eHTMLColor_e = 0xffff55, //r:ff , g: ff, b: 55, i: e // yellow + //eHTMLColor_f = 0xffffff, //r:ff , g: ff, b: ff, i: f + //eHTMLColor_0_dark = 0x000000, //r:0 , g: 0, b: 0, i: 10 + //eHTMLColor_1_dark = 0x00002a, //r:0 , g: 0, b: 2a, i: 11 + //eHTMLColor_2_dark = 0x002a00, //r:0 , g: 2a, b: 0, i: 12 + //eHTMLColor_3_dark = 0x002a2a, //r:0 , g: 2a, b: 2a, i: 13 + //eHTMLColor_4_dark = 0x2a0000, //r:2a , g: 0, b: 0, i: 14 + //eHTMLColor_5_dark = 0x2a002a, //r:2a , g: 0, b: 2a, i: 15 + //eHTMLColor_6_dark = 0x2a2a00, //r:2a , g: 2a, b: 0, i: 16 + //eHTMLColor_7_dark = 0x2a2a2a, //r:2a , g: 2a, b: 2a, i: 17 // dark gray + //eHTMLColor_8_dark = 0x151515, //r:15 , g: 15, b: 15, i: 18 + //eHTMLColor_9_dark = 0x15153f, //r:15 , g: 15, b: 3f, i: 19 + //eHTMLColor_a_dark = 0x153f15, //r:15 , g: 3f, b: 15, i: 1a + //eHTMLColor_b_dark = 0x153f3f, //r:15 , g: 3f, b: 3f, i: 1b + //eHTMLColor_c_dark = 0x3f1515, //r:3f , g: 15, b: 15, i: 1c // brown + //eHTMLColor_d_dark = 0x3f153f, //r:3f , g: 15, b: 3f, i: 1d + //eHTMLColor_e_dark = 0x3f3f15, //r:3f , g: 3f, b: 15, i: 1e + //eHTMLColor_f_dark = 0x3f3f3f, //r:3f , g: 3f, b: 3f, i: 1f + + eMinecraftColour_COUNT, +}; + +enum eDLCContentType +{ + e_DLC_SkinPack=0, + e_DLC_TexturePacks, + e_DLC_MashupPacks, + e_DLC_Themes, + e_DLC_AvatarItems, + e_DLC_Gamerpics, + e_DLC_MAX_MinecraftStore, + e_DLC_TexturePackData, // for the icon, banner and text + e_DLC_MAX, + e_DLC_NotDefined, +}; + +enum eDLCMarketplaceType +{ + e_Marketplace_Content=0, // skins, texture packs and mashup packs + e_Marketplace_Themes, + e_Marketplace_AvatarItems, + e_Marketplace_Gamerpics, + e_Marketplace_MAX, + e_Marketplace_NotDefined, +}; + +enum eDLCContentState +{ + e_DLC_ContentState_Idle = 0, + e_DLC_ContentState_Retrieving, + e_DLC_ContentState_Retrieved +}; + +enum eTMSContentState +{ + e_TMS_ContentState_Idle = 0, + e_TMS_ContentState_Queued, + e_TMS_ContentState_Retrieving, + e_TMS_ContentState_Retrieved +}; + +enum eXUID +{ + eXUID_Undefined=0, + eXUID_NoName, // name not needed + eXUID_Notch, + eXUID_Carl, + eXUID_Daniel, + eXUID_Deadmau5, + eXUID_DannyBStyle, + eXUID_JulianClark, + eXUID_Millionth, + eXUID_4JPaddy, + eXUID_4JStuart, + eXUID_4JDavid, + eXUID_4JRichard, + eXUID_4JSteven, +}; + + +enum _eTerrainFeatureType +{ + eTerrainFeature_None=0, + eTerrainFeature_Stronghold, + eTerrainFeature_Mineshaft, + eTerrainFeature_Village, + eTerrainFeature_Ravine, + eTerrainFeature_NetherFortress, + eTerrainFeature_StrongholdEndPortal, + eTerrainFeature_OceanMonument, + eTerrainFeature_Count +}; + +// 4J Stu - Whend adding new options you should consider whether having them on should disable achievements, and if so add them to the CanRecordStatsAndAchievements function +// 4J Stu - These options are now saved in save data, so new options can ONLY be added to the end +enum eGameHostOption +{ + eGameHostOption_Difficulty=0, + eGameHostOption_OnlineGame, // Unused + eGameHostOption_InviteOnly, // Unused + eGameHostOption_FriendsOfFriends, + eGameHostOption_Gamertags, + eGameHostOption_Tutorial, // special case + eGameHostOption_GameType, + eGameHostOption_LevelType, // flat or default + eGameHostOption_Structures, + eGameHostOption_BonusChest, + eGameHostOption_HasBeenInCreative, + eGameHostOption_PvP, + eGameHostOption_TrustPlayers, + eGameHostOption_TNT, + eGameHostOption_FireSpreads, + eGameHostOption_CheatsEnabled, // special case + eGameHostOption_HostCanFly, + eGameHostOption_HostCanChangeHunger, + eGameHostOption_HostCanBeInvisible, + eGameHostOption_BedrockFog, + eGameHostOption_NoHUD, + eGameHostOption_WorldSize, + eGameHostOption_All, + + eGameHostOption_DisableSaving, + eGameHostOption_WasntSaveOwner, // Added for PS3 save transfer, so we can add a nice message in the future instead of the creative mode one + + eGameHostOption_MobGriefing, + eGameHostOption_KeepInventory, + eGameHostOption_DoMobSpawning, + eGameHostOption_DoMobLoot, + eGameHostOption_DoTileDrops, + eGameHostOption_NaturalRegeneration, + eGameHostOption_DoDaylightCycle, + eGameHostOption_Hardcore, // 4J Added - for hardcore mode +}; + +// 4J-PB - If any new DLC items are added to the TMSFiles, this array needs updated +#ifdef _XBOX +enum _TMSFILES +{ + TMS_SP1=0, + TMS_SP2, + TMS_SP3, + TMS_SP4, + TMS_SP5, + TMS_SP6, + TMS_SPF, + TMS_SPB, + TMS_SPC, + TMS_SPZ, + TMS_SPM, + TMS_SPI, + TMS_SPG, + TMS_SPD1, + TMS_SPSW1, + + TMS_THST, + TMS_THIR, + TMS_THGO, + TMS_THDI, + TMS_THAW, + + TMS_GPAN, + TMS_GPCO, + TMS_GPEN, + TMS_GPFO, + TMS_GPTO, + TMS_GPBA, + TMS_GPFA, + TMS_GPME, + TMS_GPMF, + TMS_GPMM, + TMS_GPSE, + TMS_GPOr, + TMS_GPMi, + TMS_GPMB, + TMS_GPBr, + TMS_GPM1, + TMS_GPM2, + TMS_GPM3, + + TMS_AH_0001, + TMS_AH_0002, + TMS_AH_0003, + TMS_AH_0004, + TMS_AH_0005, + TMS_AH_0006, + TMS_AH_0007, + TMS_AH_0008, + TMS_AH_0009, + TMS_AH_0010, + TMS_AH_0011, + TMS_AH_0012, + TMS_AH_0013, + + TMS_AT_0001, + TMS_AT_0002, + TMS_AT_0003, + TMS_AT_0004, + TMS_AT_0005, + TMS_AT_0006, + TMS_AT_0007, + TMS_AT_0008, + TMS_AT_0009, + TMS_AT_0010, + TMS_AT_0011, + TMS_AT_0012, + TMS_AT_0013, + TMS_AT_0014, + TMS_AT_0015, + TMS_AT_0016, + TMS_AT_0017, + TMS_AT_0018, + TMS_AT_0019, + TMS_AT_0020, + TMS_AT_0021, + TMS_AT_0022, + TMS_AT_0023, + TMS_AT_0024, + TMS_AT_0025, + TMS_AT_0026, + + TMS_AP_0001, + TMS_AP_0002, + TMS_AP_0003, + TMS_AP_0004, + TMS_AP_0005, + TMS_AP_0006, + TMS_AP_0007, + TMS_AP_0009, + TMS_AP_0010, + TMS_AP_0011, + TMS_AP_0012, + TMS_AP_0013, + TMS_AP_0014, + TMS_AP_0015, + TMS_AP_0016, + TMS_AP_0017, + TMS_AP_0018, + + TMS_AP_0019, + TMS_AP_0020, + TMS_AP_0021, + TMS_AP_0022, + TMS_AP_0023, + TMS_AP_0024, + TMS_AP_0025, + TMS_AP_0026, + TMS_AP_0027, + TMS_AP_0028, + TMS_AP_0029, + TMS_AP_0030, + TMS_AP_0031, + TMS_AP_0032, + TMS_AP_0033, + + TMS_AA_0001, + + TMS_MPMA, + TMS_MPMA_DAT, + TMS_MPSR, + TMS_MPSR_DAT, + TMS_MPHA, + TMS_MPHA_DAT, + TMS_MPFE, + TMS_MPFE_DAT, + + TMS_TP01, + TMS_TP01_DAT, + TMS_TP02, + TMS_TP02_DAT, + TMS_TP04, + TMS_TP04_DAT, + TMS_TP05, + TMS_TP05_DAT, + TMS_TP06, + TMS_TP06_DAT, + TMS_TP07, + TMS_TP07_DAT, + TMS_TP08, + TMS_TP08_DAT, + + TMS_COUNT +}; +#endif + +enum EHTMLFontSize +{ + eHTMLSize_Normal, + eHTMLSize_Splitscreen, + eHTMLSize_Tutorial, + eHTMLSize_EndPoem, + + eHTMLSize_COUNT, +}; + +enum EControllerActions +{ + ACTION_MENU_A, + ACTION_MENU_B, + ACTION_MENU_X, + ACTION_MENU_Y, + ACTION_MENU_UP, + ACTION_MENU_DOWN, + ACTION_MENU_RIGHT, + ACTION_MENU_LEFT, + ACTION_MENU_PAGEUP, + ACTION_MENU_PAGEDOWN, + ACTION_MENU_RIGHT_SCROLL, + ACTION_MENU_LEFT_SCROLL, + ACTION_MENU_STICK_PRESS, + ACTION_MENU_OTHER_STICK_PRESS, + ACTION_MENU_OTHER_STICK_UP, + ACTION_MENU_OTHER_STICK_DOWN, + ACTION_MENU_OTHER_STICK_LEFT, + ACTION_MENU_OTHER_STICK_RIGHT, + ACTION_MENU_PAUSEMENU, + ACTION_MENU_QUICK_MOVE, + +#ifdef _DURANGO + ACTION_MENU_GTC_PAUSE, + ACTION_MENU_GTC_RESUME, +#endif + +#ifdef __ORBIS__ + ACTION_MENU_TOUCHPAD_PRESS, +#endif + + ACTION_MENU_OK, + ACTION_MENU_CANCEL, + ACTION_MAX_MENU = ACTION_MENU_CANCEL, + + MINECRAFT_ACTION_JUMP, + MINECRAFT_ACTION_FORWARD, + MINECRAFT_ACTION_BACKWARD, + MINECRAFT_ACTION_LEFT, + MINECRAFT_ACTION_RIGHT, + MINECRAFT_ACTION_LOOK_LEFT, + MINECRAFT_ACTION_LOOK_RIGHT, + MINECRAFT_ACTION_LOOK_UP, + MINECRAFT_ACTION_LOOK_DOWN, + MINECRAFT_ACTION_USE, + MINECRAFT_ACTION_ACTION, + MINECRAFT_ACTION_LEFT_SCROLL, + MINECRAFT_ACTION_RIGHT_SCROLL, + MINECRAFT_ACTION_INVENTORY, + MINECRAFT_ACTION_PAUSEMENU, + MINECRAFT_ACTION_DROP, + MINECRAFT_ACTION_SNEAK_TOGGLE, + MINECRAFT_ACTION_CRAFTING, + MINECRAFT_ACTION_RENDER_THIRD_PERSON, + MINECRAFT_ACTION_GAME_INFO, + MINECRAFT_ACTION_DPAD_LEFT, + MINECRAFT_ACTION_DPAD_RIGHT, + MINECRAFT_ACTION_DPAD_UP, + MINECRAFT_ACTION_DPAD_DOWN, + + MINECRAFT_ACTION_MAX, + + // These 4 aren't mapped to the input manager directly but are created from the dpad controls if required in Minecraft::run_middle + // Don't use them with the input manager directly, just through LocalPlayer::ullButtonsPressed + MINECRAFT_ACTION_SPAWN_CREEPER, + MINECRAFT_ACTION_CHANGE_SKIN, + MINECRAFT_ACTION_FLY_TOGGLE, + MINECRAFT_ACTION_RENDER_DEBUG, + MINECRAFT_ACTION_SCREENSHOT +}; + +enum eMCLang +{ + eMCLang_null=0, + eMCLang_enUS, + eMCLang_enGB, + eMCLang_enIE, + eMCLang_enAU, + eMCLang_enNZ, + eMCLang_enCA, + eMCLang_jaJP, + eMCLang_deDE, + eMCLang_deAT, + eMCLang_frFR, + eMCLang_frCA, + eMCLang_esES, + eMCLang_esMX, + eMCLang_itIT, + eMCLang_koKR, + eMCLang_ptPT, + eMCLang_ptBR, + eMCLang_ruRU, + eMCLang_nlNL, + eMCLang_fiFI, + eMCLang_svSV, + eMCLang_daDA, + eMCLang_noNO, + eMCLang_plPL, + eMCLang_trTR, + eMCLang_elEL, + eMCLang_csCS, + eMCLang_zhCHT, + eMCLang_laLAS, + + eMCLang_zhSG, + eMCLang_zhCN, + eMCLang_zhHK, + eMCLang_zhTW, + eMCLang_nlBE, + eMCLang_daDK, + eMCLang_frBE, + eMCLang_frCH, + eMCLang_deCH, + eMCLang_nbNO, + eMCLang_enGR, + eMCLang_enHK, + eMCLang_enSA, + eMCLang_enHU, + eMCLang_enIN, + eMCLang_enIL, + eMCLang_enSG, + eMCLang_enSK, + eMCLang_enZA, + eMCLang_enCZ, + eMCLang_enAE, + eMCLang_esAR, + eMCLang_esCL, + eMCLang_esCO, + eMCLang_esUS, + eMCLang_svSE, + + eMCLang_csCZ, + eMCLang_elGR, + eMCLang_nnNO, + eMCLang_skSK, + + eMCLang_hans, + eMCLang_hant, +}; diff --git a/Minecraft.Client/Common/Consoles_App.cpp b/Minecraft.Client/Common/Consoles_App.cpp index 0caf3e18..69f07204 100644 --- a/Minecraft.Client/Common/Consoles_App.cpp +++ b/Minecraft.Client/Common/Consoles_App.cpp @@ -1,10701 +1,10751 @@ -#include "stdafx.h" -#include "../../Minecraft.World/net.minecraft.world.entity.item.h" -#include "../../Minecraft.World/net.minecraft.world.entity.player.h" -#include "../../Minecraft.World/net.minecraft.world.level.tile.entity.h" -#include "../../Minecraft.World/net.minecraft.world.phys.h" -#include "../../Minecraft.World/InputOutputStream.h" -#include "../../Minecraft.World/compression.h" -#include "../Options.h" -#include "../MinecraftServer.h" -#include "../MultiPlayerLevel.h" -#include "../GameRenderer.h" -#include "../ProgressRenderer.h" -#include "../LevelRenderer.h" -#include "../MobSkinMemTextureProcessor.h" -#include "../Minecraft.h" -#include "../ClientConnection.h" -#include "../MultiPlayerLocalPlayer.h" -#include "../LocalPlayer.h" -#include "../../Minecraft.World/Player.h" -#include "../../Minecraft.World/Inventory.h" -#include "../../Minecraft.World/Level.h" -#include "../../Minecraft.World/FurnaceTileEntity.h" -#include "../../Minecraft.World/Container.h" -#include "../../Minecraft.World/DispenserTileEntity.h" -#include "../../Minecraft.World/SignTileEntity.h" -#include "../StatsCounter.h" -#include "../GameMode.h" -#include "../Xbox/Social/SocialManager.h" -#include "Tutorial/TutorialMode.h" -#ifdef _WINDOWS64 -#include "../Windows64/Network/WinsockNetLayer.h" // HUCKLE - added for quit on disconnect -#endif -#if defined _XBOX || defined _WINDOWS64 -#include "../Xbox/XML/ATGXmlParser.h" -#include "../Xbox/XML/xmlFilesCallback.h" -#endif -#include "Minecraft_Macros.h" -#include "../PlayerList.h" -#include "../ServerPlayer.h" -#include "GameRules/ConsoleGameRules.h" -#include "GameRules/ConsoleSchematicFile.h" -#include "../User.h" -#include "../../Minecraft.World/LevelData.h" -#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD) -#include "../../Minecraft.Server/ServerLogManager.h" -#endif -#include "../../Minecraft.World/net.minecraft.world.entity.player.h" -#include "../EntityRenderDispatcher.h" -#include "../../Minecraft.World/compression.h" -#include "../TexturePackRepository.h" -#include "../DLCTexturePack.h" -#include "DLC/DLCPack.h" -#include "../StringTable.h" -#ifndef _XBOX -#include "../ArchiveFile.h" -#endif -#include "../Minecraft.h" -#ifdef _XBOX -#include "../Xbox/GameConfig/Minecraft.spa.h" -#include "../Xbox/Network/NetworkPlayerXbox.h" -#include "XUI/XUI_TextEntry.h" -#include "XUI/XUI_XZP_Icons.h" -#include "XUI/XUI_PauseMenu.h" -#else -#include "UI/UI.h" -#include "UI/UIScene_PauseMenu.h" -#endif -#ifdef __PS3__ -#include -#endif -#ifdef __ORBIS__ -#include -#endif - -#include "../Common/Leaderboards/LeaderboardManager.h" -#include - -//CMinecraftApp app; -unsigned int CMinecraftApp::m_uiLastSignInData = 0; - -const float CMinecraftApp::fSafeZoneX = 64.0f; // 5% of 1280 -const float CMinecraftApp::fSafeZoneY = 36.0f; // 5% of 720 - -int CMinecraftApp::s_iHTMLFontSizesA[eHTMLSize_COUNT] = -{ -#ifdef _XBOX - 14,12,14,24 -#else - //20,15,20,24 - 20,13,20,26 -#endif -}; - - -CMinecraftApp::CMinecraftApp() -{ - if(GAME_SETTINGS_PROFILE_DATA_BYTES != sizeof(GAME_SETTINGS)) - { - // 4J Stu - See comment for GAME_SETTINGS_PROFILE_DATA_BYTES in Xbox_App.h - DebugPrintf("WARNING: The size of the profile GAME_SETTINGS struct has changed, so all stat data is likely incorrect. Is: %d, Should be: %d\n",sizeof(GAME_SETTINGS),GAME_SETTINGS_PROFILE_DATA_BYTES); -#ifndef _CONTENT_PACKAGE - DEBUG_BREAK(); -#endif - } - - for(int i=0;i; - } - - LocaleAndLanguageInit(); - -#ifdef _XBOX_ONE - m_hasReachedMainMenu = false; -#endif -} - - -void CMinecraftApp::GetSkinAdjustments(_SkinAdjustments* out, - unsigned int skinId) -{ - _SkinAdjustments adj; - - EnterCriticalSection(&csAdditionalSkinBoxes); - - if (!m_SkinAdjustmentsMap.empty()) - { - auto it = m_SkinAdjustmentsMap.find(skinId); - if (it != m_SkinAdjustmentsMap.end()) - adj = it->second; - } - - LeaveCriticalSection(&csAdditionalSkinBoxes); - - *out = adj; -} - -void CMinecraftApp::SetSkinAdjustments(unsigned int skinId, - const _SkinAdjustments& adj) -{ - EnterCriticalSection(&csAdditionalSkinBoxes); - - m_SkinAdjustmentsMap[skinId] = adj; - - LeaveCriticalSection(&csAdditionalSkinBoxes); -} - -void CMinecraftApp::DebugPrintf(const char *szFormat, ...) -{ - -#ifndef _FINAL_BUILD - va_list ap; - va_start(ap, szFormat); -#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD) - // Dedicated server routes client debug spew through ServerLogger so CLI output stays prompt-safe. - if (ServerRuntime::ServerLogManager::ShouldForwardClientDebugLogs()) - { - ServerRuntime::ServerLogManager::ForwardClientAppDebugLogV(szFormat, ap); - va_end(ap); - return; - } -#endif - char buf[1024]; - vsnprintf(buf, sizeof(buf), szFormat, ap); - va_end(ap); - OutputDebugStringA(buf); -#endif - -} - -void CMinecraftApp::DebugPrintf(int user, const char *szFormat, ...) -{ -#ifndef _FINAL_BUILD - if(user == USER_NONE) - return; - va_list ap; - va_start(ap, szFormat); -#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD) - // Dedicated server routes client debug spew through ServerLogger so CLI output stays prompt-safe. - if (ServerRuntime::ServerLogManager::ShouldForwardClientDebugLogs()) - { - ServerRuntime::ServerLogManager::ForwardClientUserDebugLogV(user, szFormat, ap); - va_end(ap); - return; - } -#endif - char buf[1024]; - vsnprintf(buf, sizeof(buf), szFormat, ap); - va_end(ap); -#ifdef __PS3__ - unsigned int writelen; - sys_tty_write(SYS_TTYP_USER1 + ( user - 1 ), buf, strlen(buf), &writelen ); -#elif defined __PSVITA__ - switch(user) - { - case 0: - { - SceUID tty2 = sceIoOpen("tty2:", SCE_O_WRONLY, 0); - if(tty2>=0) - { - std::string string1(buf); - sceIoWrite(tty2, string1.c_str(), string1.length()); - sceIoClose(tty2); - } - } - break; - case 1: - { - SceUID tty3 = sceIoOpen("tty3:", SCE_O_WRONLY, 0); - if(tty3>=0) - { - std::string string1(buf); - sceIoWrite(tty3, string1.c_str(), string1.length()); - sceIoClose(tty3); - } - } - break; - default: - OutputDebugStringA(buf); - break; - } -#else - OutputDebugStringA(buf); -#endif -#ifndef _XBOX - if(user == USER_UI) - { - ui.logDebugString(buf); - } -#endif -#endif -} - -namespace -{ -const wchar_t *ResolveStringKeyFromId(int iID) -{ -#ifdef _WINDOWS64 - switch(iID) - { - #include "StringIdLookup.generated.inc" - default: - return nullptr; - } -#else - (void)iID; - return nullptr; -#endif -} -} - -LPCWSTR CMinecraftApp::GetString(int iID) -{ - if(app.m_stringTable == nullptr) - { - const wchar_t *key = ResolveStringKeyFromId(iID); - return key != nullptr ? key : L""; - } - - LPCWSTR byIndex = app.m_stringTable->getString(iID); - if(byIndex != nullptr && byIndex[0] != L'\0') - { - return byIndex; - } - - const wchar_t *key = ResolveStringKeyFromId(iID); - if(key != nullptr) - { - LPCWSTR byKey = app.m_stringTable->getString(key); - if(byKey != nullptr && byKey[0] != L'\0') - { - return byKey; - } - - // Prefer visible fallback text instead of returning an empty string. - return key; - } - - return L""; -} - -LPCWSTR CMinecraftApp::GetString(const wchar_t *id) -{ - if(id == nullptr) - { - return L""; - } - - if(app.m_stringTable == nullptr) - { - return id; - } - - LPCWSTR byKey = app.m_stringTable->getString(id); - if(byKey != nullptr && byKey[0] != L'\0') - { - return byKey; - } - - return id; -} - -void CMinecraftApp::SetAction(int iPad, eXuiAction action, LPVOID param) -{ - if( ( m_eXuiAction[iPad] == eAppAction_ReloadTexturePack ) && ( action == eAppAction_EthernetDisconnected ) ) - { - app.DebugPrintf("Invalid change of App action for pad %d from %d to %d, ignoring\n", iPad, m_eXuiAction[iPad], action); - } - else if( ( m_eXuiAction[iPad] == eAppAction_ReloadTexturePack ) && ( action == eAppAction_ExitWorld ) ) - { - app.DebugPrintf("Invalid change of App action for pad %d from %d to %d, ignoring\n", iPad, m_eXuiAction[iPad], action); - } - else if(m_eXuiAction[iPad] == eAppAction_ExitWorldCapturedThumbnail && action != eAppAction_Idle) - { - app.DebugPrintf("Invalid change of App action for pad %d from %d to %d, ignoring\n", iPad, m_eXuiAction[iPad], action); - } - else - { - app.DebugPrintf("Changing App action for pad %d from %d to %d\n", iPad, m_eXuiAction[iPad], action); - m_eXuiAction[iPad]=action; - m_eXuiActionParam[iPad] = param; - } -} - -bool CMinecraftApp::IsAppPaused() -{ -#if defined(_XBOX_ONE) || defined(__ORBIS__) || defined(_WINDOWS64) - bool paused = m_bIsAppPaused; - EnterCriticalSection(&m_saveNotificationCriticalSection); - if( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 ) - { - paused |= m_saveNotificationDepth > 0; - } - LeaveCriticalSection(&m_saveNotificationCriticalSection); - return paused; -#else - return m_bIsAppPaused; -#endif -} - -void CMinecraftApp::SetAppPaused(bool val) -{ - m_bIsAppPaused = val; -} - -void CMinecraftApp::HandleButtonPresses() -{ - for(int i=0;i<4;i++) - { - HandleButtonPresses(i); - } -} - -void CMinecraftApp::HandleButtonPresses(int iPad) -{ - - // // test an update of the profile data - // void *pData=ProfileManager.GetGameDefinedProfileData(iPad); - // - // unsigned char *pchData= (unsigned char *)pData; - // int iCount=0; - // for(int i=0;i player,bool bNavigateBack) -{ - bool success = true; - - InventoryScreenInput* initData = new InventoryScreenInput(); - initData->player = player; - initData->bNavigateBack=bNavigateBack; - initData->iPad = iPad; - - if(app.GetLocalPlayerCount()>1) - { - initData->bSplitscreen=true; - success = ui.NavigateToScene(iPad,eUIScene_InventoryMenu,initData); - } - else - { - initData->bSplitscreen=false; - success = ui.NavigateToScene(iPad,eUIScene_InventoryMenu,initData); - } - - return success; -} - -bool CMinecraftApp::LoadCreativeMenu(int iPad,shared_ptr player,bool bNavigateBack) -{ - bool success = true; - - InventoryScreenInput* initData = new InventoryScreenInput(); - initData->player = player; - initData->bNavigateBack=bNavigateBack; - initData->iPad = iPad; - - if(app.GetLocalPlayerCount()>1) - { - initData->bSplitscreen=true; - success = ui.NavigateToScene(iPad,eUIScene_CreativeMenu,initData); - } - else - { - initData->bSplitscreen=false; - success = ui.NavigateToScene(iPad,eUIScene_CreativeMenu,initData); - } - - return success; -} - -bool CMinecraftApp::LoadCrafting2x2Menu(int iPad,shared_ptr player) -{ - bool success = true; - - CraftingPanelScreenInput* initData = new CraftingPanelScreenInput(); - initData->player = player; - initData->iContainerType=RECIPE_TYPE_2x2; - initData->iPad = iPad; - initData->x = 0; - initData->y = 0; - initData->z = 0; - - if(app.GetLocalPlayerCount()>1) - { - initData->bSplitscreen=true; - success = ui.NavigateToScene(iPad,eUIScene_Crafting2x2Menu, initData); - } - else - { - initData->bSplitscreen=false; - success = ui.NavigateToScene(iPad,eUIScene_Crafting2x2Menu, initData); - } - - return success; -} - -bool CMinecraftApp::LoadCrafting3x3Menu(int iPad,shared_ptr player, int x, int y, int z) -{ - bool success = true; - - CraftingPanelScreenInput* initData = new CraftingPanelScreenInput(); - initData->player = player; - initData->iContainerType=RECIPE_TYPE_3x3; - initData->iPad = iPad; - initData->x = x; - initData->y = y; - initData->z = z; - - if (app.GetLocalPlayerCount() > 1) - initData->bSplitscreen = true; - else - initData->bSplitscreen = false; - - if (app.GetGameSettings(iPad, eGameSetting_ClassicCrafting)) - success = ui.NavigateToScene(iPad, eUIScene_ClassicCraftingMenu, initData); - else - success = ui.NavigateToScene(iPad, eUIScene_Crafting3x3Menu, initData); - - return success; -} - -bool CMinecraftApp::LoadFireworksMenu(int iPad,shared_ptr player, int x, int y, int z) -{ - bool success = true; - - FireworksScreenInput* initData = new FireworksScreenInput(); - initData->player = player; - initData->iPad = iPad; - initData->x = x; - initData->y = y; - initData->z = z; - - if(app.GetLocalPlayerCount()>1) - { - initData->bSplitscreen=true; - success = ui.NavigateToScene(iPad,eUIScene_FireworksMenu, initData); - } - else - { - initData->bSplitscreen=false; - success = ui.NavigateToScene(iPad,eUIScene_FireworksMenu, initData); - } - - return success; -} - -bool CMinecraftApp::LoadEnchantingMenu(int iPad,shared_ptr inventory, int x, int y, int z, Level *level, const wstring &name) -{ - bool success = true; - - EnchantingScreenInput* initData = new EnchantingScreenInput(); - initData->inventory = inventory; - initData->level = level; - initData->x = x; - initData->y = y; - initData->z = z; - initData->iPad = iPad; - initData->name = name; - - if(app.GetLocalPlayerCount()>1) - { - initData->bSplitscreen=true; - success = ui.NavigateToScene(iPad,eUIScene_EnchantingMenu, initData); - } - else - { - initData->bSplitscreen=false; - success = ui.NavigateToScene(iPad,eUIScene_EnchantingMenu, initData); - } - - return success; -} - -bool CMinecraftApp::LoadFurnaceMenu(int iPad,shared_ptr inventory, shared_ptr furnace) -{ - bool success = true; - - FurnaceScreenInput* initData = new FurnaceScreenInput(); - - initData->furnace = furnace; - initData->inventory = inventory; - initData->iPad = iPad; - - // Load the scene. - if(app.GetLocalPlayerCount()>1) - { - initData->bSplitscreen=true; - success = ui.NavigateToScene(iPad,eUIScene_FurnaceMenu, initData); - } - else - { - initData->bSplitscreen=false; - success = ui.NavigateToScene(iPad,eUIScene_FurnaceMenu, initData); - } - - return success; -} - -bool CMinecraftApp::LoadBrewingStandMenu(int iPad,shared_ptr inventory, shared_ptr brewingStand) -{ - bool success = true; - - BrewingScreenInput* initData = new BrewingScreenInput(); - - initData->brewingStand = brewingStand; - initData->inventory = inventory; - initData->iPad = iPad; - - // Load the scene. - if(app.GetLocalPlayerCount()>1) - { - initData->bSplitscreen=true; - success = ui.NavigateToScene(iPad,eUIScene_BrewingStandMenu, initData); - } - else - { - initData->bSplitscreen=false; - success = ui.NavigateToScene(iPad,eUIScene_BrewingStandMenu, initData); - } - - return success; -} - - -bool CMinecraftApp::LoadContainerMenu(int iPad,shared_ptr inventory, shared_ptr container) -{ - bool success = true; - - ContainerScreenInput* initData = new ContainerScreenInput(); - - initData->inventory = inventory; - initData->container = container; - initData->iPad = iPad; - - // Load the scene. - if(app.GetLocalPlayerCount()>1) - { - initData->bSplitscreen=true; - - bool bLargeChest = (initData->container->getContainerSize() > 3*9)?true:false; - if(bLargeChest) - { - success = ui.NavigateToScene(iPad,eUIScene_LargeContainerMenu,initData); - } - else - { - success = ui.NavigateToScene(iPad,eUIScene_ContainerMenu,initData); - } - } - else - { - initData->bSplitscreen=false; - success = ui.NavigateToScene(iPad,eUIScene_ContainerMenu,initData); - } - - return success; -} - -bool CMinecraftApp::LoadTrapMenu(int iPad,shared_ptr inventory, shared_ptr trap) -{ - bool success = true; - - TrapScreenInput* initData = new TrapScreenInput(); - - initData->inventory = inventory; - initData->trap = trap; - initData->iPad = iPad; - - // Load the scene. - if(app.GetLocalPlayerCount()>1) - { - initData->bSplitscreen=true; - success = ui.NavigateToScene(iPad,eUIScene_DispenserMenu, initData); - } - else - { - initData->bSplitscreen=false; - success = ui.NavigateToScene(iPad,eUIScene_DispenserMenu, initData); - } - - return success; -} - -bool CMinecraftApp::LoadSignEntryMenu(int iPad,shared_ptr sign) -{ - bool success = true; - - SignEntryScreenInput* initData = new SignEntryScreenInput(); - - initData->sign = sign; - initData->iPad = iPad; - - success = ui.NavigateToScene(iPad,eUIScene_SignEntryMenu, initData); - - delete initData; - - return success; -} - -bool CMinecraftApp::LoadRepairingMenu(int iPad,shared_ptr inventory, Level *level, int x, int y, int z) -{ - bool success = true; - - AnvilScreenInput *initData = new AnvilScreenInput(); - initData->inventory = inventory; - initData->level = level; - initData->x = x; - initData->y = y; - initData->z = z; - initData->iPad = iPad; - if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true; - else initData->bSplitscreen=false; - - success = ui.NavigateToScene(iPad,eUIScene_AnvilMenu, initData); - - return success; -} - -bool CMinecraftApp::LoadTradingMenu(int iPad, shared_ptr inventory, shared_ptr trader, Level *level, const wstring &name) -{ - bool success = true; - - TradingScreenInput *initData = new TradingScreenInput(); - initData->inventory = inventory; - initData->trader = trader; - initData->level = level; - initData->iPad = iPad; - if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true; - else initData->bSplitscreen=false; - - success = ui.NavigateToScene(iPad,eUIScene_TradingMenu, initData); - - return success; -} - -bool CMinecraftApp::LoadHopperMenu(int iPad ,shared_ptr inventory, shared_ptr hopper) -{ - bool success = true; - - HopperScreenInput *initData = new HopperScreenInput(); - initData->inventory = inventory; - initData->hopper = hopper; - initData->iPad = iPad; - if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true; - else initData->bSplitscreen=false; - - success = ui.NavigateToScene(iPad,eUIScene_HopperMenu, initData); - - return success; -} - -bool CMinecraftApp::LoadHopperMenu(int iPad ,shared_ptr inventory, shared_ptr hopper) -{ - bool success = true; - - HopperScreenInput *initData = new HopperScreenInput(); - initData->inventory = inventory; - initData->hopper = dynamic_pointer_cast(hopper); - initData->iPad = iPad; - if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true; - else initData->bSplitscreen=false; - - success = ui.NavigateToScene(iPad,eUIScene_HopperMenu, initData); - - return success; -} - - -bool CMinecraftApp::LoadHorseMenu(int iPad ,shared_ptr inventory, shared_ptr container, shared_ptr horse) -{ - bool success = true; - - HorseScreenInput *initData = new HorseScreenInput(); - initData->inventory = inventory; - initData->container = container; - initData->horse = horse; - initData->iPad = iPad; - if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true; - else initData->bSplitscreen=false; - - success = ui.NavigateToScene(iPad,eUIScene_HorseMenu, initData); - - return success; -} - -bool CMinecraftApp::LoadBeaconMenu(int iPad ,shared_ptr inventory, shared_ptr beacon) -{ - bool success = true; - - BeaconScreenInput *initData = new BeaconScreenInput(); - initData->inventory = inventory; - initData->beacon = beacon; - initData->iPad = iPad; - if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true; - else initData->bSplitscreen=false; - - success = ui.NavigateToScene(iPad,eUIScene_BeaconMenu, initData); - - return success; -} - -bool CMinecraftApp::LoadWritingBookMenu(int iPad, shared_ptr instance, shared_ptr player, bool editable) -{ - bool success = true; - - WritingBookMenuParams* initData = new WritingBookMenuParams(); - initData->itemInstance = instance; - initData->player = player; - initData->iPad = iPad; - initData->isEditable = editable; - - success = ui.NavigateToScene(iPad, eUIScene_BookMenu, initData); - - return success; -} - -////////////////////////////////////////////// -// GAME SETTINGS -////////////////////////////////////////////// - -#ifdef _WINDOWS64 -static void Win64_GetSettingsPath(char *outPath, DWORD size) -{ - GetModuleFileNameA(nullptr, outPath, size); - char *lastSlash = strrchr(outPath, '\\'); - if (lastSlash) *(lastSlash + 1) = '\0'; - strncat_s(outPath, size, "settings.dat", _TRUNCATE); -} -static void Win64_SaveSettings(GAME_SETTINGS *gs) -{ - if (!gs) return; - char filePath[MAX_PATH] = {}; - Win64_GetSettingsPath(filePath, MAX_PATH); - FILE *f = nullptr; - if (fopen_s(&f, filePath, "wb") == 0 && f) - { - fwrite(gs, sizeof(GAME_SETTINGS), 1, f); - fclose(f); - } -} -static void Win64_LoadSettings(GAME_SETTINGS *gs) -{ - if (!gs) return; - char filePath[MAX_PATH] = {}; - Win64_GetSettingsPath(filePath, MAX_PATH); - FILE *f = nullptr; - if (fopen_s(&f, filePath, "rb") == 0 && f) - { - GAME_SETTINGS temp = {}; - if (fread(&temp, sizeof(GAME_SETTINGS), 1, f) == 1) - memcpy(gs, &temp, sizeof(GAME_SETTINGS)); - fclose(f); - } -} -#endif - -void CMinecraftApp::InitGameSettings() -{ - for(int i=0;i(ProfileManager.GetGameDefinedProfileData(i)); -#endif - // clear the flag to say the settings have changed - GameSettingsA[i]->bSettingsChanged=false; - - //SetDefaultGameSettings(i); - done on a callback from the profile manager - - // 4J-PB - adding in for Windows & PS3 to set the defaults for the joypad -#if defined _WINDOWS64// || defined __PSVITA__ - C_4JProfile::PROFILESETTINGS *pProfileSettings=ProfileManager.GetDashboardProfileSettings(i); - // clear this for now - it will come from reading the system values - memset(pProfileSettings,0,sizeof(C_4JProfile::PROFILESETTINGS)); - SetDefaultOptions(pProfileSettings,i); - Win64_LoadSettings(GameSettingsA[i]); -#ifndef MINECRAFT_SERVER_BUILD - ApplyGameSettingsChanged(i); -#endif -#elif defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__ - C4JStorage::PROFILESETTINGS *pProfileSettings=StorageManager.GetDashboardProfileSettings(i); - // 4J-PB - don't cause an options write to happen here - SetDefaultOptions(pProfileSettings,i,false); - -#endif - - Minecraft* minecraft = Minecraft::GetInstance(); - if (minecraft != nullptr && minecraft->stats[i] != nullptr) - { - minecraft->stats[i]->clear(); - minecraft->stats[i]->parse(GameSettingsA[i]); - } - } -} - -#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) -int CMinecraftApp::SetDefaultOptions(C4JStorage::PROFILESETTINGS *pSettings,const int iPad,bool bWriteProfile) -#else -int CMinecraftApp::SetDefaultOptions(C_4JProfile::PROFILESETTINGS *pSettings,const int iPad) -#endif -{ - SetGameSettings(iPad,eGameSetting_MusicVolume,DEFAULT_VOLUME_LEVEL); - SetGameSettings(iPad,eGameSetting_SoundFXVolume,DEFAULT_VOLUME_LEVEL); - SetGameSettings(iPad,eGameSetting_RenderDistance,16); - SetGameSettings(iPad,eGameSetting_Gamma,50); - SetGameSettings(iPad,eGameSetting_FOV,0); - - // 4J-PB - Don't reset the difficult level if we're in-game - if(Minecraft::GetInstance()->level==nullptr) - { - app.DebugPrintf("SetDefaultOptions - Difficulty = 1\n"); - SetGameSettings(iPad,eGameSetting_Difficulty,1); - } - SetGameSettings(iPad,eGameSetting_Sensitivity_InGame,100); - SetGameSettings(iPad,eGameSetting_ViewBob,1); - SetGameSettings(iPad,eGameSetting_ControlScheme,0); - SetGameSettings(iPad,eGameSetting_ControlInvertLook,(pSettings->iYAxisInversion!=0)?1:0); - SetGameSettings(iPad,eGameSetting_ControlSouthPaw,pSettings->bSwapSticks?1:0); - SetGameSettings(iPad,eGameSetting_SplitScreenVertical,0); - SetGameSettings(iPad,eGameSetting_GamertagsVisible,1); - - // Interim TU 1.6.6 - SetGameSettings(iPad,eGameSetting_Sensitivity_InMenu,100); - SetGameSettings(iPad,eGameSetting_DisplaySplitscreenGamertags,1); - SetGameSettings(iPad,eGameSetting_Hints,1); - SetGameSettings(iPad,eGameSetting_Autosave,2); - SetGameSettings(iPad,eGameSetting_Tooltips,1); - SetGameSettings(iPad,eGameSetting_InterfaceOpacity,80); - - // TU 5 - SetGameSettings(iPad,eGameSetting_Clouds,1); - SetGameSettings(iPad,eGameSetting_Online,1); - SetGameSettings(iPad,eGameSetting_InviteOnly,0); - SetGameSettings(iPad,eGameSetting_FriendsOfFriends,1); - - // default the update changes message to zero - // 4J-PB - We'll only display the message if the profile is pre-TU5 - //SetGameSettings(iPad,eGameSetting_DisplayUpdateMessage,0); - - // TU 6 - SetGameSettings(iPad,eGameSetting_BedrockFog,0); - SetGameSettings(iPad,eGameSetting_DisplayHUD,1); - SetGameSettings(iPad,eGameSetting_DisplayHand,1); - - // TU 7 - SetGameSettings(iPad,eGameSetting_CustomSkinAnim,1); - - // TU 9 - SetGameSettings(iPad,eGameSetting_DeathMessages,1); - SetGameSettings(iPad,eGameSetting_UISize,1); - SetGameSettings(iPad,eGameSetting_UISizeSplitscreen,2); - SetGameSettings(iPad,eGameSetting_AnimatedCharacter,1); - - // TU 12 - GameSettingsA[iPad]->ucCurrentFavoriteSkinPos=0; - for(int i=0;iuiFavoriteSkinA[i]=0xFFFFFFFF; - } - - // TU 13 - GameSettingsA[iPad]->uiMashUpPackWorldsDisplay=0xFFFFFFFF; - - // 1.6.4 - app.SetGameHostOption(eGameHostOption_MobGriefing, 1); - app.SetGameHostOption(eGameHostOption_KeepInventory, 0); - app.SetGameHostOption(eGameHostOption_DoMobSpawning, 1 ); - app.SetGameHostOption(eGameHostOption_DoMobLoot, 1 ); - app.SetGameHostOption(eGameHostOption_DoTileDrops, 1 ); - app.SetGameHostOption(eGameHostOption_NaturalRegeneration, 1 ); - app.SetGameHostOption(eGameHostOption_DoDaylightCycle, 1 ); - - //TU25 - SetGameSettings(iPad, eGameSetting_ClassicCrafting, 0); - SetGameSettings(iPad, eGameSetting_CaveSounds, 1); - - //TU34 - SetGameSettings(iPad, eGameSetting_MinecartSounds, 1); - - // 4J-PB - leave these in, or remove from everywhere they are referenced! - // Although probably best to leave in unless we split the profile settings into platform specific classes - having different meaning per platform for the same bitmask could get confusing - //#ifdef __PS3__ - // PS3DEC13 - SetGameSettings(iPad,eGameSetting_PS3_EULA_Read,0); // EULA not read - - // PS3 1.05 - added Greek - - // 4J-JEV: We cannot change these in-game, as they could affect localised strings and font. - // XB1: Fix for #172947 - Content: Gameplay: While playing in language different form system default one and resetting options to their defaults in active gameplay causes in-game language to change and HUD to disappear - if (!app.GetGameStarted()) - { - GameSettingsA[iPad]->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language - GameSettingsA[iPad]->ucLocale = MINECRAFT_LANGUAGE_DEFAULT; // use the system locale - } - - //#endif - -#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) - GameSettingsA[iPad]->bSettingsChanged=bWriteProfile; -#endif - - return 0; -} - -#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) -int CMinecraftApp::DefaultOptionsCallback(LPVOID pParam,C4JStorage::PROFILESETTINGS *pSettings, const int iPad) -#else -int CMinecraftApp::DefaultOptionsCallback(LPVOID pParam,C_4JProfile::PROFILESETTINGS *pSettings, const int iPad) -#endif -{ - CMinecraftApp *pApp=static_cast(pParam); - - // flag the default options to be set - - pApp->DebugPrintf("Setting default options for player %d", iPad); - pApp->SetAction(iPad,eAppAction_SetDefaultOptions, (LPVOID)pSettings); - //pApp->SetDefaultOptions(pSettings,iPad); - - // if the profile data has been changed, then force a profile write - // It seems we're allowed to break the 5 minute rule if it's the result of a user action - //pApp->CheckGameSettingsChanged(); - - return 0; -} - -#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) - -wstring CMinecraftApp::toStringOptionsStatus(const C4JStorage::eOptionsCallback &eStatus) -{ -#ifndef _CONTENT_PACKAGE - switch(eStatus) - { - case C4JStorage::eOptions_Callback_Idle: return L"Idle"; - case C4JStorage::eOptions_Callback_Write: return L"Write"; - case C4JStorage::eOptions_Callback_Write_Fail_NoSpace: return L"Write_Fail_NoSpace"; - case C4JStorage::eOptions_Callback_Write_Fail: return L"Write_Fail"; - case C4JStorage::eOptions_Callback_Read: return L"Read"; - case C4JStorage::eOptions_Callback_Read_Fail: return L"Read_Fail"; - case C4JStorage::eOptions_Callback_Read_FileNotFound: return L"Read_FileNotFound"; - case C4JStorage::eOptions_Callback_Read_Corrupt: return L"Read_Corrupt"; - case C4JStorage::eOptions_Callback_Read_CorruptDeletePending: return L"Read_CorruptDeletePending"; - case C4JStorage::eOptions_Callback_Read_CorruptDeleted: return L"Read_CorruptDeleted"; - default: return L"[UNRECOGNISED_OPTIONS_STATUS]"; - } -#else - return L""; -#endif -} - -#ifdef __ORBIS__ -int CMinecraftApp::OptionsDataCallback(LPVOID pParam,int iPad,unsigned short usVersion,C4JStorage::eOptionsCallback eStatus,int iBlocksRequired) -{ - CMinecraftApp *pApp=(CMinecraftApp *)pParam; - pApp->m_eOptionsStatusA[iPad]=eStatus; - pApp->m_eOptionsBlocksRequiredA[iPad]=iBlocksRequired; - return 0; -} - -int CMinecraftApp::GetOptionsBlocksRequired(int iPad) -{ - return m_eOptionsBlocksRequiredA[iPad]; -} - -#else -int CMinecraftApp::OptionsDataCallback(LPVOID pParam,int iPad,unsigned short usVersion,C4JStorage::eOptionsCallback eStatus) -{ - CMinecraftApp *pApp=(CMinecraftApp *)pParam; - -#ifndef _CONTENT_PACKAGE - pApp->DebugPrintf("[OptionsDataCallback] Pad_%i: new status == %ls(%i).\n", iPad, pApp->toStringOptionsStatus(eStatus).c_str(), (int) eStatus); -#endif - - pApp->m_eOptionsStatusA[iPad] = eStatus; - - return 0; -} -#endif - -C4JStorage::eOptionsCallback CMinecraftApp::GetOptionsCallbackStatus(int iPad) -{ - return m_eOptionsStatusA[iPad]; -} - -void CMinecraftApp::SetOptionsCallbackStatus(int iPad, C4JStorage::eOptionsCallback eStatus) -{ - m_eOptionsStatusA[iPad]=eStatus; -} -#endif - -int CMinecraftApp::OldProfileVersionCallback(LPVOID pParam,unsigned char *pucData, const unsigned short usVersion, const int iPad) -{ - // check what needs to be done with this version to update to the current one - - switch(usVersion) - { -#ifdef _XBOX - case PROFILE_VERSION_1: - case PROFILE_VERSION_2: - // need to fill in values for the new profile data. No need to save the profile - that'll happen if they get changed, or if the auto save for the profile kicks in - { - GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; - pGameSettings->ucMenuSensitivity=100; //eGameSetting_Sensitivity_InMenu - pGameSettings->ucInterfaceOpacity=80; //eGameSetting_Sensitivity_InMenu - pGameSettings->usBitmaskValues|=0x0200; //eGameSetting_DisplaySplitscreenGamertags - on - pGameSettings->usBitmaskValues|=0x0400; //eGameSetting_Hints - on - pGameSettings->usBitmaskValues|=0x1000; //eGameSetting_Autosave - 2 - pGameSettings->usBitmaskValues|=0x8000; //eGameSetting_Tooltips - on - - // 4J-PB - Let's also award all the achievements they have again because of the profile bug that seemed to stop the awards of some - // Changing this to check the system achievements at sign-in and award any that the game says we have and the system says we haven't - //ProfileManager.ReAwardAchievements(iPad); - - pGameSettings->uiBitmaskValues=0L; // reset - pGameSettings->uiBitmaskValues|=GAMESETTING_CLOUDS; //eGameSetting_Clouds - on - pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on - //eGameSetting_GameSetting_Invite - off - pGameSettings->uiBitmaskValues|=GAMESETTING_FRIENDSOFFRIENDS; //eGameSetting_GameSetting_FriendsOfFriends - on - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) - // TU6 - pGameSettings->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG; //eGameSetting_BedrockFog - off - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHUD; //eGameSetting_DisplayHUD - on - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHAND; //eGameSetting_DisplayHand - on - // TU7 - pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on - // TU9 - pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on - pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2 - pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3 - pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on - // TU12 - // favorite skins added, but only set in TU12 - set to FFs - for(int i=0;iuiFavoriteSkinA[i]=0xFFFFFFFF; - } - pGameSettings->ucCurrentFavoriteSkinPos=0; - // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list - pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; - - // PS3 1.05 - added Greek - pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language - } - break; - case PROFILE_VERSION_3: - - { - GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; - pGameSettings->uiBitmaskValues=0L; // reset - pGameSettings->uiBitmaskValues|=GAMESETTING_CLOUDS; //eGameSetting_Clouds - on - pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on - //eGameSetting_GameSetting_Invite - off - pGameSettings->uiBitmaskValues|=GAMESETTING_FRIENDSOFFRIENDS; //eGameSetting_GameSetting_FriendsOfFriends - on - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) - // TU6 - pGameSettings->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG; //eGameSetting_BedrockFog - off - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHUD; //eGameSetting_DisplayHUD - on - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHAND; //eGameSetting_DisplayHand - on - // TU7 - pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on - // TU9 - pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on - pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2 - pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3 - pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on - // TU12 - // favorite skins added, but only set in TU12 - set to FFs - for(int i=0;iuiFavoriteSkinA[i]=0xFFFFFFFF; - } - pGameSettings->ucCurrentFavoriteSkinPos=0; - // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list - pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; - - // PS3 1.05 - added Greek - pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language - - } - break; - case PROFILE_VERSION_4: - { - GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; - - pGameSettings->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG; //eGameSetting_BedrockFog - off - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHUD; //eGameSetting_DisplayHUD - on - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHAND; //eGameSetting_DisplayHand - on - // TU7 - pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on - // TU9 - pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on - pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2 - pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3 - pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on - - // Set the online flag to on, so it's not saved if a game starts offline when the user didn't change it to be offline (xbox disconnected from LIVE) - pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on - // TU12 - // favorite skins added, but only set in TU12 - set to FFs - for(int i=0;iuiFavoriteSkinA[i]=0xFFFFFFFF; - } - pGameSettings->ucCurrentFavoriteSkinPos=0; - // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list - pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; - - // PS3 1.05 - added Greek - pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language - - } - - break; - case PROFILE_VERSION_5: - { - GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; - - // reset the display new message counter - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) - // TU7 - pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on - // TU9 - pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on - pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2 - pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3 - pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on - // Set the online flag to on, so it's not saved if a game starts offline when the user didn't change it to be offline (xbox disconnected from LIVE) - pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on - // TU12 - // favorite skins added, but only set in TU12 - set to FFs - for(int i=0;iuiFavoriteSkinA[i]=0xFFFFFFFF; - } - pGameSettings->ucCurrentFavoriteSkinPos=0; - // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list - pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; - - // PS3 1.05 - added Greek - pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language - - - } - - break; - case PROFILE_VERSION_6: - { - GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; - - // Added gui size for splitscreen and fullscreen - // Added death messages toggle - - // reset the display new message counter - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) - // TU9 - pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on - pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2 - pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3 - pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on - // Set the online flag to on, so it's not saved if a game starts offline when the user didn't change it to be offline (xbox disconnected from LIVE) - pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on - // TU12 - // favorite skins added, but only set in TU12 - set to FFs - for(int i=0;iuiFavoriteSkinA[i]=0xFFFFFFFF; - } - pGameSettings->ucCurrentFavoriteSkinPos=0; - // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list - pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; - - // PS3 1.05 - added Greek - pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language - - - } - - break; - - case PROFILE_VERSION_7: - { - GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; - // reset the display new message counter - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) - - // TU12 - // favorite skins added, but only set in TU12 - set to FFs - for(int i=0;iuiFavoriteSkinA[i]=0xFFFFFFFF; - } - pGameSettings->ucCurrentFavoriteSkinPos=0; - // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list - pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; - - // PS3 1.05 - added Greek - pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language - - - } - break; -#endif - case PROFILE_VERSION_8: - { - GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; - // reset the display new message counter - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) - - // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list - pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; - - // PS3DEC13 - pGameSettings->uiBitmaskValues&=~GAMESETTING_PS3EULAREAD; //eGameSetting_PS3_EULA_Read - off - - // PS3 1.05 - added Greek - pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language - - } - break; - case PROFILE_VERSION_9: - // PS3DEC13 - { - GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) - pGameSettings->uiBitmaskValues&=~GAMESETTING_PS3EULAREAD; //eGameSetting_PS3_EULA_Read - off - - // PS3 1.05 - added Greek - pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language - - } - break; - case PROFILE_VERSION_10: - { - GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) - pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language - } - break; - case PROFILE_VERSION_11: - { - GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) - } - break; - case PROFILE_VERSION_12: - { - GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) - } - break; - default: - { - // This might be from a version during testing of new profile updates - app.DebugPrintf("Don't know what to do with this profile version!\n"); - - GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; - pGameSettings->ucMenuSensitivity=100; //eGameSetting_Sensitivity_InMenu - pGameSettings->ucInterfaceOpacity=80; //eGameSetting_Sensitivity_InMenu - pGameSettings->usBitmaskValues|=0x0200; //eGameSetting_DisplaySplitscreenGamertags - on - pGameSettings->usBitmaskValues|=0x0400; //eGameSetting_Hints - on - pGameSettings->usBitmaskValues|=0x1000; //eGameSetting_Autosave - 2 - pGameSettings->usBitmaskValues|=0x8000; //eGameSetting_Tooltips - on - - pGameSettings->uiBitmaskValues=0L; // reset - pGameSettings->uiBitmaskValues|=GAMESETTING_CLOUDS; //eGameSetting_Clouds - on - pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on - //eGameSetting_GameSetting_Invite - off - pGameSettings->uiBitmaskValues|=GAMESETTING_FRIENDSOFFRIENDS; //eGameSetting_GameSetting_FriendsOfFriends - on - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) - pGameSettings->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG; //eGameSetting_BedrockFog - off - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHUD; //eGameSetting_DisplayHUD - on - pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHAND; //eGameSetting_DisplayHand - on - pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on - pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on - pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2 - pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3 - pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on - pGameSettings->uiBitmaskValues |= GAMESETTING_CLASSICCRAFTING; //eGameSetting_ClassicCrafting - off - // TU12 - // favorite skins added, but only set in TU12 - set to FFs - for(int i=0;iuiFavoriteSkinA[i]=0xFFFFFFFF; - } - pGameSettings->ucCurrentFavoriteSkinPos=0; - // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list - pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; - - // PS3DEC13 - pGameSettings->uiBitmaskValues&=~GAMESETTING_PS3EULAREAD; //eGameSetting_PS3_EULA_Read - off - - // PS3 1.05 - added Greek - pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language - - } - break; - } - - return 0; -} - -void CMinecraftApp::ApplyGameSettingsChanged(int iPad) -{ - ActionGameSettings(iPad,eGameSetting_MusicVolume ); - ActionGameSettings(iPad,eGameSetting_SoundFXVolume ); - ActionGameSettings(iPad,eGameSetting_RenderDistance ); - ActionGameSettings(iPad,eGameSetting_Gamma ); - ActionGameSettings(iPad,eGameSetting_FOV ); - ActionGameSettings(iPad,eGameSetting_Difficulty ); - ActionGameSettings(iPad,eGameSetting_Sensitivity_InGame ); - ActionGameSettings(iPad,eGameSetting_ViewBob ); - ActionGameSettings(iPad,eGameSetting_ControlScheme ); - ActionGameSettings(iPad,eGameSetting_ControlInvertLook); - ActionGameSettings(iPad,eGameSetting_ControlSouthPaw); - ActionGameSettings(iPad,eGameSetting_ControlType); - ActionGameSettings(iPad,eGameSetting_SplitScreenVertical); - ActionGameSettings(iPad,eGameSetting_GamertagsVisible); - - // Interim TU 1.6.6 - ActionGameSettings(iPad,eGameSetting_Sensitivity_InMenu ); - ActionGameSettings(iPad,eGameSetting_DisplaySplitscreenGamertags); - ActionGameSettings(iPad,eGameSetting_Hints); - ActionGameSettings(iPad,eGameSetting_InterfaceOpacity); - ActionGameSettings(iPad,eGameSetting_Tooltips); - - ActionGameSettings(iPad,eGameSetting_Clouds); - ActionGameSettings(iPad,eGameSetting_BedrockFog); - ActionGameSettings(iPad,eGameSetting_DisplayHUD); - ActionGameSettings(iPad,eGameSetting_DisplayHand); - ActionGameSettings(iPad,eGameSetting_CustomSkinAnim); - ActionGameSettings(iPad,eGameSetting_DeathMessages); - ActionGameSettings(iPad,eGameSetting_UISize); - ActionGameSettings(iPad,eGameSetting_UISizeSplitscreen); - ActionGameSettings(iPad,eGameSetting_AnimatedCharacter); - - ActionGameSettings(iPad,eGameSetting_PS3_EULA_Read); - ActionGameSettings(iPad,eGameSetting_VSync); - - //TU25 - ActionGameSettings(iPad, eGameSetting_ClassicCrafting); - ActionGameSettings(iPad, eGameSetting_CaveSounds); - ActionGameSettings(iPad, eGameSetting_MinecartSounds); - ActionGameSettings(iPad, eGameSetting_HideSaveSizeBar); -} - -void CMinecraftApp::ActionGameSettings(int iPad,eGameSetting eVal) -{ - Minecraft *pMinecraft=Minecraft::GetInstance(); - switch(eVal) - { - case eGameSetting_MusicVolume: - if(iPad==ProfileManager.GetPrimaryPad()) - { - pMinecraft->options->set(Options::Option::MUSIC,static_cast(GameSettingsA[iPad]->ucMusicVolume)/100.0f); - } - break; - case eGameSetting_SoundFXVolume: - if (iPad == ProfileManager.GetPrimaryPad()) - { - pMinecraft->options->set(Options::Option::SOUND, static_cast(GameSettingsA[iPad]->ucSoundFXVolume) / 100.0f); - } - break; - case eGameSetting_RenderDistance: - if (iPad == ProfileManager.GetPrimaryPad()) - { - int dist = (GameSettingsA[iPad]->uiBitmaskValues >> 16) & 0xFF; - - int level = UIScene_SettingsGraphicsMenu::DistanceToLevel(dist); - pMinecraft->options->set(Options::Option::RENDER_DISTANCE, 3 - level); - }; - break; - case eGameSetting_Gamma: - if(iPad==ProfileManager.GetPrimaryPad()) - { -#if defined(_WIN64) || defined(_WINDOWS64) - pMinecraft->options->set(Options::Option::GAMMA, static_cast(GameSettingsA[iPad]->ucGamma) / 100.0f); -#else - // ucGamma range is 0-100, UpdateGamma is 0 - 32768 - float fVal=((float)GameSettingsA[iPad]->ucGamma)*327.68f; - RenderManager.UpdateGamma((unsigned short)fVal); -#endif - } - - break; - case eGameSetting_FOV: - if(iPad==ProfileManager.GetPrimaryPad()) - { - float fovDeg = 70.0f + (float)GameSettingsA[iPad]->ucFov * 40.0f / 100.0f; - pMinecraft->gameRenderer->SetFovVal(fovDeg); - pMinecraft->options->set(Options::Option::FOV, (float)GameSettingsA[iPad]->ucFov / 100.0f); - } - break; - case eGameSetting_Difficulty: - if(iPad==ProfileManager.GetPrimaryPad()) - { - pMinecraft->options->toggle(Options::Option::DIFFICULTY,GameSettingsA[iPad]->usBitmaskValues&0x03); - app.DebugPrintf("Difficulty toggle to %d\n",GameSettingsA[iPad]->usBitmaskValues&0x03); - - // Update the Game Host setting - app.SetGameHostOption(eGameHostOption_Difficulty,pMinecraft->options->difficulty); - - // send this to the other players if we are in-game - bool bInGame=pMinecraft->level!=nullptr; - - // Game Host only (and for now we can't change the diff while in game, so this shouldn't happen) - if(bInGame && g_NetworkManager.IsHost() && (iPad==ProfileManager.GetPrimaryPad())) - { - app.SetXuiServerAction(iPad,eXuiServerAction_ServerSettingChanged_Difficulty); - } - } - else - { - app.DebugPrintf("NOT ACTIONING DIFFICULTY - Primary pad is %d, This pad is %d\n",ProfileManager.GetPrimaryPad(),iPad); - } - - break; - case eGameSetting_Sensitivity_InGame: - // 4J-PB - we don't use the options value - // tell the input that we've changed the sensitivity - range of the slider is 0 to 200, default is 100 - pMinecraft->options->set(Options::Option::SENSITIVITY,static_cast(GameSettingsA[iPad]->ucSensitivity)/100.0f); - //InputManager.SetJoypadSensitivity(iPad,((float)GameSettingsA[iPad]->ucSensitivity)/100.0f); - - break; - case eGameSetting_ViewBob: - // 4J-PB - not handled here any more - it's read from the gamesettings per player - //pMinecraft->options->toggle(Options::Option::VIEW_BOBBING,GameSettingsA[iPad]->usBitmaskValues&0x04); - break; - case eGameSetting_ControlScheme: - InputManager.SetJoypadMapVal(iPad,(GameSettingsA[iPad]->usBitmaskValues&0x30)>>4); - break; - - case eGameSetting_ControlInvertLook: - // Nothing specific to do for this setting. - break; - - case eGameSetting_ControlSouthPaw: - // What is the setting? - if ( GameSettingsA[iPad]->usBitmaskValues & 0x80 ) - { - // Southpaw. - InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_LX, AXIS_MAP_RX ); - InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_LY, AXIS_MAP_RY ); - InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_RX, AXIS_MAP_LX ); - InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_RY, AXIS_MAP_LY ); - InputManager.SetJoypadStickTriggerMap( iPad, TRIGGER_MAP_0, TRIGGER_MAP_1 ); - InputManager.SetJoypadStickTriggerMap( iPad, TRIGGER_MAP_1, TRIGGER_MAP_0 ); - } - else - { - // Right handed. - InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_LX, AXIS_MAP_LX ); - InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_LY, AXIS_MAP_LY ); - InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_RX, AXIS_MAP_RX ); - InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_RY, AXIS_MAP_RY ); - InputManager.SetJoypadStickTriggerMap( iPad, TRIGGER_MAP_0, TRIGGER_MAP_0 ); - InputManager.SetJoypadStickTriggerMap( iPad, TRIGGER_MAP_1, TRIGGER_MAP_1 ); - } - break; - case eGameSetting_SplitScreenVertical: - if(iPad==ProfileManager.GetPrimaryPad()) - { - pMinecraft->updatePlayerViewportAssignments(); - } - break; - case eGameSetting_GamertagsVisible: - { - bool bInGame=pMinecraft->level!=nullptr; - - // Game Host only - if(bInGame && g_NetworkManager.IsHost() && (iPad==ProfileManager.GetPrimaryPad())) - { - // Update the Game Host setting if you are the host and you are in-game - app.SetGameHostOption(eGameHostOption_Gamertags,((GameSettingsA[iPad]->usBitmaskValues&0x0008)!=0)?1:0); - app.SetXuiServerAction(iPad,eXuiServerAction_ServerSettingChanged_Gamertags); - - PlayerList *players = MinecraftServer::getInstance()->getPlayerList(); - for( auto& decorationPlayer : players->players ) - { - decorationPlayer->setShowOnMaps((app.GetGameHostOption(eGameHostOption_Gamertags)!=0)?true:false); - } - } - } - break; - // Interim TU 1.6.6 - case eGameSetting_Sensitivity_InMenu: - // 4J-PB - we don't use the options value - // tell the input that we've changed the sensitivity - range of the slider is 0 to 200, default is 100 - //pMinecraft->options->set(Options::Option::SENSITIVITY,((float)GameSettingsA[iPad]->ucSensitivity)/100.0f); - //InputManager.SetJoypadSensitivity(iPad,((float)GameSettingsA[iPad]->ucSensitivity)/100.0f); - - break; - - case eGameSetting_DisplaySplitscreenGamertags: - for( BYTE idx = 0; idx < XUSER_MAX_COUNT; ++idx) - { - if(pMinecraft->localplayers[idx] != nullptr) - { - if(pMinecraft->localplayers[idx]->m_iScreenSection==C4JRender::VIEWPORT_TYPE_FULLSCREEN) - { - ui.DisplayGamertag(idx,false); - } - else - { - ui.DisplayGamertag(idx,true); - } - } - } - - break; - case eGameSetting_InterfaceOpacity: - // update the tooltips display - ui.RefreshTooltips( iPad); - - break; - case eGameSetting_Hints: - //nothing to do here - break; - case eGameSetting_Tooltips: - if((GameSettingsA[iPad]->usBitmaskValues&0x8000)!=0) - { - ui.SetEnableTooltips(iPad,TRUE); - } - else - { - ui.SetEnableTooltips(iPad,FALSE); - } - break; - case eGameSetting_Clouds: - //nothing to do here - break; - case eGameSetting_Online: - //nothing to do here - break; - case eGameSetting_InviteOnly: - //nothing to do here - break; - case eGameSetting_FriendsOfFriends: - //nothing to do here - break; - case eGameSetting_BedrockFog: - { - bool bInGame = pMinecraft->level != nullptr; - - if (bInGame && g_NetworkManager.IsHost() && (iPad == ProfileManager.GetPrimaryPad())) - { - app.SetGameHostOption(eGameHostOption_BedrockFog, GetGameSettings(iPad, eGameSetting_BedrockFog) ? 1 : 0); - app.SetXuiServerAction(iPad, eXuiServerAction_ServerSettingChanged_BedrockFog); - } - } - break; - case eGameSetting_DisplayHUD: - //nothing to do here - break; - case eGameSetting_DisplayHand: - //nothing to do here - break; - case eGameSetting_CustomSkinAnim: - //nothing to do here - break; - case eGameSetting_DeathMessages: - //nothing to do here - break; - case eGameSetting_UISize: - //nothing to do here - break; - case eGameSetting_UISizeSplitscreen: - //nothing to do here - break; - case eGameSetting_AnimatedCharacter: - //nothing to do here - break; - case eGameSetting_PS3_EULA_Read: - //nothing to do here - break; - case eGameSetting_PSVita_NetworkModeAdhoc: - //nothing to do here - break; - case eGameSetting_VSync: -#ifdef _WINDOWS64 - { - extern bool g_bVSync; - g_bVSync = (GetGameSettings(iPad, eGameSetting_VSync) != 0); - } -#endif - break; - case eGameSetting_ExclusiveFullscreen: -#ifdef _WINDOWS64 - { - extern void SetExclusiveFullscreen(bool enabled); - SetExclusiveFullscreen(GetGameSettings(iPad, eGameSetting_ExclusiveFullscreen) != 0); - } -#endif - break; - case eGameSetting_ClassicCrafting: - //nothing to do here - break; - case eGameSetting_HideSaveSizeBar: - //nothing to do here - break; - } -} - -void CMinecraftApp::SetPlayerSkin(int iPad,const wstring &name) -{ - DWORD skinId = app.getSkinIdFromPath(name); - - SetPlayerSkin(iPad,skinId); -} - -void CMinecraftApp::SetPlayerSkin(int iPad,DWORD dwSkinId) -{ - DebugPrintf("Setting skin for %d to %08X\n", iPad, dwSkinId); - - GameSettingsA[iPad]->dwSelectedSkin = dwSkinId; - GameSettingsA[iPad]->bSettingsChanged = true; - - TelemetryManager->RecordSkinChanged(iPad, GameSettingsA[iPad]->dwSelectedSkin); - - if(Minecraft::GetInstance()->localplayers[iPad]!=nullptr) Minecraft::GetInstance()->localplayers[iPad]->setAndBroadcastCustomSkin(dwSkinId); -} - - -wstring CMinecraftApp::GetPlayerSkinName(int iPad) -{ - return app.getSkinPathFromId(GameSettingsA[iPad]->dwSelectedSkin); -} - -DWORD CMinecraftApp::GetPlayerSkinId(int iPad) -{ - // 4J-PB -check the user has rights to use this skin - they may have had at some point but the entitlement has been removed. - DLCPack *Pack=nullptr; - DLCSkinFile *skinFile=nullptr; - DWORD dwSkin=GameSettingsA[iPad]->dwSelectedSkin; - wchar_t chars[256]; - - if( GET_IS_DLC_SKIN_FROM_BITMASK(dwSkin) ) - { - // 4J Stu - DLC skins are numbered using decimal rather than hex to make it easier to number manually - swprintf(chars, 256, L"dlcskin%08d.png", GET_DLC_SKIN_ID_FROM_BITMASK(dwSkin)); - - Pack=app.m_dlcManager.getPackContainingSkin(chars); - - if(Pack) - { - skinFile = Pack->getSkinFile(chars); - - bool bSkinIsFree = skinFile->getParameterAsBool( DLCManager::e_DLCParamType_Free ); - bool bLicensed = Pack->hasPurchasedFile( DLCManager::e_DLCType_Skin, skinFile->getPath() ); - - if(bSkinIsFree || bLicensed) - { - return dwSkin; - } - else - { - return 0; - } - } - } - - - return dwSkin; -} - -DWORD CMinecraftApp::GetAdditionalModelParts(int iPad) -{ - return m_dwAdditionalModelParts[iPad]; -} - - -void CMinecraftApp::SetPlayerCape(int iPad,const wstring &name) -{ - DWORD capeId = Player::getCapeIdFromPath(name); - - SetPlayerCape(iPad,capeId); -} - -void CMinecraftApp::SetPlayerCape(int iPad,DWORD dwCapeId) -{ - DebugPrintf("Setting cape for %d to %08X\n", iPad, dwCapeId); - - GameSettingsA[iPad]->dwSelectedCape = dwCapeId; - GameSettingsA[iPad]->bSettingsChanged = true; - - //SentientManager.RecordSkinChanged(iPad, GameSettingsA[iPad]->dwSelectedSkin); - - if(Minecraft::GetInstance()->localplayers[iPad]!=nullptr) Minecraft::GetInstance()->localplayers[iPad]->setAndBroadcastCustomCape(dwCapeId); -} - -wstring CMinecraftApp::GetPlayerCapeName(int iPad) -{ - return Player::getCapePathFromId(GameSettingsA[iPad]->dwSelectedCape); -} - -DWORD CMinecraftApp::GetPlayerCapeId(int iPad) -{ - return GameSettingsA[iPad]->dwSelectedCape; -} - -void CMinecraftApp::SetPlayerFavoriteSkin(int iPad, int iIndex,unsigned int uiSkinID) -{ - DebugPrintf("Setting favorite skin for %d to %08X\n", iPad, uiSkinID); - - GameSettingsA[iPad]->uiFavoriteSkinA[iIndex] = uiSkinID; - GameSettingsA[iPad]->bSettingsChanged = true; -} - -unsigned int CMinecraftApp::GetPlayerFavoriteSkin(int iPad,int iIndex) -{ - return GameSettingsA[iPad]->uiFavoriteSkinA[iIndex]; -} - -unsigned char CMinecraftApp::GetPlayerFavoriteSkinsPos(int iPad) -{ - return GameSettingsA[iPad]->ucCurrentFavoriteSkinPos; -} - -void CMinecraftApp::SetPlayerFavoriteSkinsPos(int iPad, int iPos) -{ - GameSettingsA[iPad]->ucCurrentFavoriteSkinPos=static_cast(iPos); - GameSettingsA[iPad]->bSettingsChanged = true; -} - -unsigned int CMinecraftApp::GetPlayerFavoriteSkinsCount(int iPad) -{ - unsigned int uiCount=0; - for(int i=0;iuiFavoriteSkinA[i]!=0xFFFFFFFF) - { - uiCount++; - } - else - { - break; - } - } - return uiCount; -} - -void CMinecraftApp::ValidateFavoriteSkins(int iPad) -{ - unsigned int uiCount=GetPlayerFavoriteSkinsCount(iPad); - - // remove invalid skins - unsigned int uiValidSkin=0; - wchar_t chars[256]; - - for(unsigned int i=0;igetFile(DLCManager::e_DLCType_Skin,chars); - DLCSkinFile *pSkinFile = pDLCPack->getSkinFile(chars); - - if( pDLCPack->hasPurchasedFile(DLCManager::e_DLCType_Skin, L"") || (pSkinFile && pSkinFile->isFree())) - { - GameSettingsA[iPad]->uiFavoriteSkinA[uiValidSkin++]=GameSettingsA[iPad]->uiFavoriteSkinA[i]; - } - } - } - - for(unsigned int i=uiValidSkin;iuiFavoriteSkinA[i]=0xFFFFFFFF; - } -} - -// Mash-up pack worlds -void CMinecraftApp::HideMashupPackWorld(int iPad, unsigned int iMashupPackID) -{ - unsigned int uiPackID=iMashupPackID - 1024; // mash-up ids start at 1024 - GameSettingsA[iPad]->uiMashUpPackWorldsDisplay&=~(1<bSettingsChanged = true; -} - -void CMinecraftApp::EnableMashupPackWorlds(int iPad) -{ - GameSettingsA[iPad]->uiMashUpPackWorldsDisplay=0xFFFFFFFF; - GameSettingsA[iPad]->bSettingsChanged = true; -} - -unsigned int CMinecraftApp::GetMashupPackWorlds(int iPad) -{ - return GameSettingsA[iPad]->uiMashUpPackWorldsDisplay; -} - -void CMinecraftApp::SetMinecraftLanguage(int iPad, unsigned char ucLanguage) -{ - GameSettingsA[iPad]->ucLanguage = ucLanguage; - GameSettingsA[iPad]->bSettingsChanged = true; -} - -unsigned char CMinecraftApp::GetMinecraftLanguage(int iPad) -{ - // if there are no game settings read yet, return the default language - if(GameSettingsA[iPad]==nullptr) - { - return 0; - } - else - { - return GameSettingsA[iPad]->ucLanguage; - } -} - -void CMinecraftApp::SetMinecraftLocale(int iPad, unsigned char ucLocale) -{ - GameSettingsA[iPad]->ucLocale = ucLocale; - GameSettingsA[iPad]->bSettingsChanged = true; -} - -unsigned char CMinecraftApp::GetMinecraftLocale(int iPad) -{ - // if there are no game settings read yet, return the default language - if(GameSettingsA[iPad]==nullptr) - { - return 0; - } - else - { - return GameSettingsA[iPad]->ucLocale; - } -} - -void CMinecraftApp::SetGameSettings(int iPad,eGameSetting eVal,unsigned char ucVal) -{ - //Minecraft *pMinecraft=Minecraft::GetInstance(); - - switch(eVal) - { - case eGameSetting_MusicVolume: - if(GameSettingsA[iPad]->ucMusicVolume!=ucVal) - { - GameSettingsA[iPad]->ucMusicVolume=ucVal; - if(iPad==ProfileManager.GetPrimaryPad()) - { - ActionGameSettings(iPad,eVal); - } - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_SoundFXVolume: - if(GameSettingsA[iPad]->ucSoundFXVolume!=ucVal) - { - GameSettingsA[iPad]->ucSoundFXVolume=ucVal; - if(iPad==ProfileManager.GetPrimaryPad()) - { - ActionGameSettings(iPad,eVal); - } - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_RenderDistance: - { - unsigned int val = ucVal & 0xFF; - - GameSettingsA[iPad]->uiBitmaskValues &= ~(0xFF << 16); - GameSettingsA[iPad]->uiBitmaskValues |= val << 16; - if(iPad == ProfileManager.GetPrimaryPad()) - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_Gamma: - if(GameSettingsA[iPad]->ucGamma!=ucVal) - { - GameSettingsA[iPad]->ucGamma=ucVal; - if(iPad==ProfileManager.GetPrimaryPad()) - { - ActionGameSettings(iPad,eVal); - } - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_FOV: - if(GameSettingsA[iPad]->ucFov!=ucVal) - { - GameSettingsA[iPad]->ucFov=ucVal; - if(iPad==ProfileManager.GetPrimaryPad()) - { - ActionGameSettings(iPad,eVal); - } - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_Difficulty: - if((GameSettingsA[iPad]->usBitmaskValues&0x03)!=(ucVal&0x03)) - { - GameSettingsA[iPad]->usBitmaskValues&=~0x03; - GameSettingsA[iPad]->usBitmaskValues|=ucVal&0x03; - if(iPad==ProfileManager.GetPrimaryPad()) - { - ActionGameSettings(iPad,eVal); - } - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_Sensitivity_InGame: - if(GameSettingsA[iPad]->ucSensitivity!=ucVal) - { - GameSettingsA[iPad]->ucSensitivity=ucVal; - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_ViewBob: - if((GameSettingsA[iPad]->usBitmaskValues&0x0004)!=((ucVal&0x01)<<2)) - { - if(ucVal!=0) - { - GameSettingsA[iPad]->usBitmaskValues|=0x0004; - } - else - { - GameSettingsA[iPad]->usBitmaskValues&=~0x0004; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_ControlScheme: // bits 5 and 6 - if((GameSettingsA[iPad]->usBitmaskValues&0x30)!=((ucVal&0x03)<<4)) - { - GameSettingsA[iPad]->usBitmaskValues&=~0x0030; - if(ucVal!=0) - { - GameSettingsA[iPad]->usBitmaskValues|=(ucVal&0x03)<<4; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - - case eGameSetting_ControlInvertLook: - if((GameSettingsA[iPad]->usBitmaskValues&0x0040)!=((ucVal&0x01)<<6)) - { - if(ucVal!=0) - { - GameSettingsA[iPad]->usBitmaskValues|=0x0040; - } - else - { - GameSettingsA[iPad]->usBitmaskValues&=~0x0040; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - - case eGameSetting_ControlSouthPaw: - if((GameSettingsA[iPad]->usBitmaskValues&0x0080)!=((ucVal&0x01)<<7)) - { - if(ucVal!=0) - { - GameSettingsA[iPad]->usBitmaskValues|=0x0080; - } - else - { - GameSettingsA[iPad]->usBitmaskValues&=~0x0080; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_ControlType: - if((GameSettingsA[iPad]->uiBitmaskValues & 0x00070000) != ((ucVal & 0x07) << 16)) - { - GameSettingsA[iPad]->uiBitmaskValues &= ~0x00070000; - GameSettingsA[iPad]->uiBitmaskValues |= (ucVal & 0x07) << 16; - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_SplitScreenVertical: - if((GameSettingsA[iPad]->usBitmaskValues&0x0100)!=((ucVal&0x01)<<8)) - { - if(ucVal!=0) - { - GameSettingsA[iPad]->usBitmaskValues|=0x0100; - } - else - { - GameSettingsA[iPad]->usBitmaskValues&=~0x0100; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_GamertagsVisible: - if((GameSettingsA[iPad]->usBitmaskValues&0x0008)!=((ucVal&0x01)<<3)) - { - if(ucVal!=0) - { - GameSettingsA[iPad]->usBitmaskValues|=0x0008; - } - else - { - GameSettingsA[iPad]->usBitmaskValues&=~0x0008; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - - // 4J-PB - Added for Interim TU for 1.6.6 - case eGameSetting_Sensitivity_InMenu: - if(GameSettingsA[iPad]->ucMenuSensitivity!=ucVal) - { - GameSettingsA[iPad]->ucMenuSensitivity=ucVal; - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_DisplaySplitscreenGamertags: - if((GameSettingsA[iPad]->usBitmaskValues&0x0200)!=((ucVal&0x01)<<9)) - { - if(ucVal!=0) - { - GameSettingsA[iPad]->usBitmaskValues|=0x0200; - } - else - { - GameSettingsA[iPad]->usBitmaskValues&=~0x0200; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_Hints: - if((GameSettingsA[iPad]->usBitmaskValues&0x0400)!=((ucVal&0x01)<<10)) - { - if(ucVal!=0) - { - GameSettingsA[iPad]->usBitmaskValues|=0x0400; - } - else - { - GameSettingsA[iPad]->usBitmaskValues&=~0x0400; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_Autosave: - if((GameSettingsA[iPad]->usBitmaskValues&0x7800)!=((ucVal&0x0F)<<11)) - { - GameSettingsA[iPad]->usBitmaskValues&=~0x7800; - if(ucVal!=0) - { - GameSettingsA[iPad]->usBitmaskValues|=(ucVal&0x0F)<<11; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - - case eGameSetting_Tooltips: - if((GameSettingsA[iPad]->usBitmaskValues&0x8000)!=((ucVal&0x01)<<15)) - { - if(ucVal!=0) - { - GameSettingsA[iPad]->usBitmaskValues|=0x8000; - } - else - { - GameSettingsA[iPad]->usBitmaskValues&=~0x8000; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_InterfaceOpacity: - if(GameSettingsA[iPad]->ucInterfaceOpacity!=ucVal) - { - GameSettingsA[iPad]->ucInterfaceOpacity=ucVal; - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - - break; - case eGameSetting_Clouds: - if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_CLOUDS)!=(ucVal&0x01)) - { - if(ucVal==1) - { - GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_CLOUDS; - } - else - { - GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_CLOUDS; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - - break; - - case eGameSetting_Online: - if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_ONLINE)!=(ucVal&0x01)<<1) - { - if(ucVal==1) - { - GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_ONLINE; - } - else - { - GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_ONLINE; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - - break; - case eGameSetting_InviteOnly: - if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_INVITEONLY)!=(ucVal&0x01)<<2) - { - if(ucVal==1) - { - GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_INVITEONLY; - } - else - { - GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_INVITEONLY; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - - break; - case eGameSetting_FriendsOfFriends: - if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_FRIENDSOFFRIENDS)!=(ucVal&0x01)<<3) - { - if(ucVal==1) - { - GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_FRIENDSOFFRIENDS; - } - else - { - GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_FRIENDSOFFRIENDS; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - - break; - case eGameSetting_DisplayUpdateMessage: - if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYUPDATEMSG)!=(ucVal&0x03)<<4) - { - GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_DISPLAYUPDATEMSG; - if(ucVal>0) - { - GameSettingsA[iPad]->uiBitmaskValues|=(ucVal&0x03)<<4; - } - - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - - break; - - case eGameSetting_BedrockFog: - if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_BEDROCKFOG)!=(ucVal&0x01)<<6) - { - if(ucVal==1) - { - GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_BEDROCKFOG; - } - else - { - GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - - break; - case eGameSetting_DisplayHUD: - if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYHUD)!=(ucVal&0x01)<<7) - { - if(ucVal==1) - { - GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_DISPLAYHUD; - } - else - { - GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_DISPLAYHUD; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - - break; - case eGameSetting_DisplayHand: - if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYHAND)!=(ucVal&0x01)<<8) - { - if(ucVal==1) - { - GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_DISPLAYHAND; - } - else - { - GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_DISPLAYHAND; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - - break; - - case eGameSetting_CustomSkinAnim: - if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_CUSTOMSKINANIM)!=(ucVal&0x01)<<9) - { - if(ucVal==1) - { - GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; - } - else - { - GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_CUSTOMSKINANIM; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - - break; - // TU9 - case eGameSetting_DeathMessages: - if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DEATHMESSAGES)!=(ucVal&0x01)<<10) - { - if(ucVal==1) - { - GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; - } - else - { - GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_DEATHMESSAGES; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_UISize: - if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_UISIZE)!=((ucVal&0x03)<<11)) - { - GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_UISIZE; - if(ucVal!=0) - { - GameSettingsA[iPad]->uiBitmaskValues|=(ucVal&0x03)<<11; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_UISizeSplitscreen: - if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_UISIZE_SPLITSCREEN)!=((ucVal&0x03)<<13)) - { - GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_UISIZE_SPLITSCREEN; - if(ucVal!=0) - { - GameSettingsA[iPad]->uiBitmaskValues|=(ucVal&0x03)<<13; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_AnimatedCharacter: - if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_ANIMATEDCHARACTER)!=(ucVal&0x01)<<15) - { - if(ucVal==1) - { - GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; - } - else - { - GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_ANIMATEDCHARACTER; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_PS3_EULA_Read: - if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PS3EULAREAD)!=(ucVal&0x01)<<16) - { - if(ucVal==1) - { - GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_PS3EULAREAD; - } - else - { - GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_PS3EULAREAD; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_PSVita_NetworkModeAdhoc: - if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PSVITANETWORKMODEADHOC)!=(ucVal&0x01)<<17) - { - if(ucVal==1) - { - GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_PSVITANETWORKMODEADHOC; - } - else - { - GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_PSVITANETWORKMODEADHOC; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - - case eGameSetting_VSync: - if(((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_VSYNC)>>24)!=(ucVal&0x01)) - { - if(ucVal==1) - { - GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_VSYNC; - } - else - { - GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_VSYNC; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - - case eGameSetting_ExclusiveFullscreen: - if(((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_EXCLUSIVEFULLSCREEN)>>25)!=(ucVal&0x01)) - { - if(ucVal==1) - { - GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_EXCLUSIVEFULLSCREEN; - } - else - { - GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_EXCLUSIVEFULLSCREEN; - } - ActionGameSettings(iPad,eVal); - GameSettingsA[iPad]->bSettingsChanged=true; - } - break; - case eGameSetting_ClassicCrafting: - if ((GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_CLASSICCRAFTING) != (ucVal & 0x01) << 19) - { - if (ucVal == 1) - { - GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_CLASSICCRAFTING; - } - else - { - GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_CLASSICCRAFTING; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_CaveSounds: - if ((GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_CAVESOUNDS) != (ucVal & 0x01) << 27) - { - if (ucVal == 1) - { - GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_CAVESOUNDS; - } - else - { - GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_CAVESOUNDS; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_MinecartSounds: - if ((GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_MINECARTSOUNDS) != (ucVal & 0x01) << 28) - { - if (ucVal == 1) - { - GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_MINECARTSOUNDS; - } - else - { - GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_MINECARTSOUNDS; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_HideSaveSizeBar: - if ((GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_HIDESAVESIZEBAR) != (ucVal & 0x01) << 27) - { - if (ucVal == 1) - { - GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_HIDESAVESIZEBAR; - } - else - { - GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_HIDESAVESIZEBAR; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - } -} - -unsigned char CMinecraftApp::GetGameSettings(eGameSetting eVal) -{ - int iPad=ProfileManager.GetPrimaryPad(); - - return GetGameSettings(iPad,eVal); -} - -unsigned char CMinecraftApp::GetGameSettings(int iPad,eGameSetting eVal) -{ - if (iPad < 0 || iPad >= XUSER_MAX_COUNT || GameSettingsA[iPad] == nullptr) - { - return 0; - } - - switch(eVal) - { - case eGameSetting_MusicVolume: - return GameSettingsA[iPad]->ucMusicVolume; - break; - case eGameSetting_SoundFXVolume: - return GameSettingsA[iPad]->ucSoundFXVolume; - break; - case eGameSetting_RenderDistance: - { - int val = (GameSettingsA[iPad]->uiBitmaskValues >> 16) & 0xFF; - if(val == 0) return val = 16; //brain - return val; - break; - } - case eGameSetting_Gamma: - return GameSettingsA[iPad]->ucGamma; - break; - case eGameSetting_FOV: - return GameSettingsA[iPad]->ucFov; - break; - case eGameSetting_Difficulty: - return GameSettingsA[iPad]->usBitmaskValues&0x0003; - break; - case eGameSetting_Sensitivity_InGame: - return GameSettingsA[iPad]->ucSensitivity; - break; - case eGameSetting_ViewBob: - return ((GameSettingsA[iPad]->usBitmaskValues&0x0004)>>2); - break; - case eGameSetting_GamertagsVisible: - return ((GameSettingsA[iPad]->usBitmaskValues&0x0008)>>3); - break; - case eGameSetting_ControlScheme: - return ((GameSettingsA[iPad]->usBitmaskValues&0x0030)>>4); // 2 bits - break; - case eGameSetting_ControlInvertLook: - return ((GameSettingsA[iPad]->usBitmaskValues&0x0040)>>6); - break; - case eGameSetting_ControlSouthPaw: - return ((GameSettingsA[iPad]->usBitmaskValues&0x0080)>>7); - break; - case eGameSetting_SplitScreenVertical: - return ((GameSettingsA[iPad]->usBitmaskValues&0x0100)>>8); - break; - // 4J-PB - Added for Interim TU for 1.6.6 - case eGameSetting_Sensitivity_InMenu: - return GameSettingsA[iPad]->ucMenuSensitivity; - break; - - case eGameSetting_DisplaySplitscreenGamertags: - return ((GameSettingsA[iPad]->usBitmaskValues&0x0200)>>9); - break; - - case eGameSetting_Hints: - return ((GameSettingsA[iPad]->usBitmaskValues&0x0400)>>10); - break; - case eGameSetting_Autosave: - { - unsigned char ucVal=(GameSettingsA[iPad]->usBitmaskValues&0x7800)>>11; - return ucVal; - } - break; - case eGameSetting_Tooltips: - return ((GameSettingsA[iPad]->usBitmaskValues&0x8000)>>15); - break; - - case eGameSetting_InterfaceOpacity: - return GameSettingsA[iPad]->ucInterfaceOpacity; - break; - - case eGameSetting_Clouds: - return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_CLOUDS); - break; - case eGameSetting_Online: - return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_ONLINE)>>1; - break; - case eGameSetting_InviteOnly: - return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_INVITEONLY)>>2; - break; - case eGameSetting_FriendsOfFriends: - return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_FRIENDSOFFRIENDS)>>3; - break; - case eGameSetting_DisplayUpdateMessage: - return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYUPDATEMSG)>>4; - break; - case eGameSetting_BedrockFog: - return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_BEDROCKFOG)>>6; - break; - case eGameSetting_DisplayHUD: - return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYHUD)>>7; - break; - case eGameSetting_DisplayHand: - return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYHAND)>>8; - break; - case eGameSetting_CustomSkinAnim: - return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_CUSTOMSKINANIM)>>9; - break; - // TU9 - case eGameSetting_DeathMessages: - return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DEATHMESSAGES)>>10; - break; - case eGameSetting_UISize: - { - unsigned char ucVal=(GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_UISIZE)>>11; - return ucVal; - } - break; - case eGameSetting_UISizeSplitscreen: - { - unsigned char ucVal=(GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_UISIZE_SPLITSCREEN)>>13; - return ucVal; - } - break; - case eGameSetting_AnimatedCharacter: - return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_ANIMATEDCHARACTER)>>15; - - case eGameSetting_PS3_EULA_Read: - return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PS3EULAREAD)>>16; - - case eGameSetting_PSVita_NetworkModeAdhoc: - return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PSVITANETWORKMODEADHOC)>>17; - - case eGameSetting_ClassicCrafting: - return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_CLASSICCRAFTING) >> 26; - - case eGameSetting_CaveSounds: - return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_CAVESOUNDS) >> 27; - - case eGameSetting_MinecartSounds: - return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_MINECARTSOUNDS) >> 28; - - case eGameSetting_HideSaveSizeBar: - return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_HIDESAVESIZEBAR) >> 27; - - case eGameSetting_VSync: - return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_VSYNC)>>24; - - case eGameSetting_ExclusiveFullscreen: - return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_EXCLUSIVEFULLSCREEN)>>25; - case eGameSetting_ControlType: - return (GameSettingsA[iPad]->uiBitmaskValues & 0x00070000) >> 16; - - } - return 0; -} - -void CMinecraftApp::CheckGameSettingsChanged(bool bOverride5MinuteTimer, int iPad) -{ - // If the settings have changed, write them to the profile - - if(iPad==XUSER_INDEX_ANY) - { - for(int i=0;ibSettingsChanged) - { -#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__ ) - StorageManager.WriteToProfile(i,true, bOverride5MinuteTimer); -#else - ProfileManager.WriteToProfile(i,true, bOverride5MinuteTimer); -#ifdef _WINDOWS64 - Win64_SaveSettings(GameSettingsA[i]); -#endif -#endif - GameSettingsA[i]->bSettingsChanged=false; - } - } - } - else - { - if(GameSettingsA[iPad]->bSettingsChanged) - { -#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) - StorageManager.WriteToProfile(iPad,true, bOverride5MinuteTimer); -#else - ProfileManager.WriteToProfile(iPad,true, bOverride5MinuteTimer); -#ifdef _WINDOWS64 - Win64_SaveSettings(GameSettingsA[iPad]); -#endif -#endif - GameSettingsA[iPad]->bSettingsChanged=false; - } - } -} - -void CMinecraftApp::ClearGameSettingsChangedFlag(int iPad) -{ - GameSettingsA[iPad]->bSettingsChanged=false; -} - -/////////////////////////// -// -// Remove the debug settings in the release build -// -//////////////////////////// -#ifndef _DEBUG -unsigned int CMinecraftApp::GetGameSettingsDebugMask(int iPad,bool bOverridePlayer) //bOverridePlayer is to force the send for the server to get the read options -{ - return 0; -} - -void CMinecraftApp::SetGameSettingsDebugMask(int iPad, unsigned int uiVal) -{ -} - -void CMinecraftApp::ActionDebugMask(int iPad,bool bSetAllClear) -{ -} - -#else - -unsigned int CMinecraftApp::GetGameSettingsDebugMask(int iPad,bool bOverridePlayer) //bOverridePlayer is to force the send for the server to get the read options -{ - if(iPad==-1) - { - iPad=ProfileManager.GetPrimaryPad(); - } - if(iPad < 0) iPad = 0; - - shared_ptr player = Minecraft::GetInstance()->localplayers[iPad]; - - if(bOverridePlayer || player==nullptr) - { - return GameSettingsA[iPad]->uiDebugBitmask; - } - else - { - return player->GetDebugOptions(); - } -} - - -void CMinecraftApp::SetGameSettingsDebugMask(int iPad, unsigned int uiVal) -{ -#ifndef _CONTENT_PACKAGE - GameSettingsA[iPad]->bSettingsChanged=true; - GameSettingsA[iPad]->uiDebugBitmask=uiVal; - - // update the value so the network server can use it - shared_ptr player = Minecraft::GetInstance()->localplayers[iPad]; - - if(player) - { - Minecraft::GetInstance()->localgameModes[iPad]->handleDebugOptions(uiVal,player); - } -#endif -} - -void CMinecraftApp::ActionDebugMask(int iPad,bool bSetAllClear) -{ - unsigned int ulBitmask=app.GetGameSettingsDebugMask(iPad); - - if(bSetAllClear) ulBitmask=0L; - - - - // these settings should only be actioned for the primary player - if(ProfileManager.GetPrimaryPad()!=iPad) return; - - for(int i=0;i(param); - app.SetAction(actionInfo->iPad, actionInfo->action); -} - - -void CMinecraftApp::HandleXuiActions(void) -{ - eXuiAction eAction; - eTMSAction eTMS; - LPVOID param; - Minecraft *pMinecraft=Minecraft::GetInstance(); - shared_ptr player; - - // are there any global actions to deal with? - eAction = app.GetGlobalXuiAction(); - if(eAction!=eAppAction_Idle) - { - switch(eAction) - { - case eAppAction_DisplayLavaMessage: - // Display a warning about placing lava in the spawn area - { - UINT uiIDA[1]; - uiIDA[0]=IDS_CONFIRM_OK; - C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_CANT_PLACE_NEAR_SPAWN_TITLE, IDS_CANT_PLACE_NEAR_SPAWN_TEXT, uiIDA,1,XUSER_INDEX_ANY); - if(result != C4JStorage::EMessage_Busy) SetGlobalXuiAction(eAppAction_Idle); - - } - break; - default: - break; - } - } - - // are there any app actions to deal with? - for(int i=0;iIsTitleAllowedToPostImages() && CSocialManager::Instance()->AreAllUsersAllowedToPostImages() ) - { - // disable character name tags for the shot - //m_bwasHidingGui = pMinecraft->options->hideGui; // 4J Stu - Removed 1.8.2 bug fix (TU6) as don't need this - pMinecraft->options->hideGui = true; - - SetAction(i,eAppAction_SocialPostScreenshot); - } - else - { - SetAction(i,eAppAction_Idle); - } - } - else - { - SetAction(i,eAppAction_Idle); - } - break; - case eAppAction_SocialPostScreenshot: - { - SetAction(i,eAppAction_Idle); - bool bKeepHiding = false; - for(int j=0; j < XUSER_MAX_COUNT;++j) - { - if(app.GetXuiAction(j) == eAppAction_SocialPostScreenshot) - { - bKeepHiding = true; - break; - } - } - pMinecraft->options->hideGui=bKeepHiding; - - // Facebook Share - - if(app.GetLocalPlayerCount()>1) - { - ui.NavigateToScene(i,eUIScene_SocialPost); - } - else - { - ui.NavigateToScene(i,eUIScene_SocialPost); - } - } - break; - case eAppAction_SaveGame: - SetAction(i,eAppAction_Idle); - if(!GetChangingSessionType()) - { - // If this is the trial game, do an upsell - if(ProfileManager.IsFullVersion()) - { - - // flag the render to capture the screenshot for the save - SetAction(i,eAppAction_SaveGameCapturedThumbnail); - } - else - { - // ask the player if they would like to upgrade, or they'll lose the level - - UINT uiIDA[2]; - uiIDA[0]=IDS_CONFIRM_OK; - uiIDA[1]=IDS_CONFIRM_CANCEL; - ui.RequestErrorMessage(IDS_UNLOCK_TITLE, IDS_UNLOCK_TOSAVE_TEXT, uiIDA, 2,i,&CMinecraftApp::UnlockFullSaveReturned,this); - } - } - - break; - case eAppAction_AutosaveSaveGame: - { - // Need to run a check to see if the save exists in order to stop the dialog asking if we want to overwrite it coming up on an autosave - bool bSaveExists; - StorageManager.DoesSaveExist(&bSaveExists); - - SetAction(i,eAppAction_Idle); - if(!GetChangingSessionType()) - { - - // flag the render to capture the screenshot for the save - SetAction(i,eAppAction_AutosaveSaveGameCapturedThumbnail); - } - } - - break; - - case eAppAction_SaveGameCapturedThumbnail: - // reset the autosave timer - app.SetAutosaveTimerTime(); - SetAction(i,eAppAction_Idle); - // Check that there is a name for the save - if we're saving from the tutorial and this is the first save from the tutorial, we'll not have a name - /*if(StorageManager.GetSaveName()==nullptr) - { - app.NavigateToScene(i,eUIScene_SaveWorld); - } - else*/ - { - // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen - ui.HideAllGameUIElements(); - - // Hide the other players scenes - ui.ShowOtherPlayersBaseScene(ProfileManager.GetPrimaryPad(), false); - - //INT saveOrCheckpointId = 0; - //bool validSave = StorageManager.GetSaveUniqueNumber(&saveOrCheckpointId); - //SentientManager.RecordLevelSaveOrCheckpoint(ProfileManager.GetPrimaryPad(), saveOrCheckpointId); - - LoadingInputParams *loadingParams = new LoadingInputParams(); - loadingParams->func = &UIScene_PauseMenu::SaveWorldThreadProc; - loadingParams->lpParam = static_cast(false); - - // 4J-JEV - PS4: Fix for #5708 - [ONLINE] - If the user pulls their network cable out while saving the title will hang. - loadingParams->waitForThreadToDelete = true; - - UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); - completionData->bShowBackground=TRUE; - completionData->bShowLogo=TRUE; - completionData->type = e_ProgressCompletion_NavigateBackToScene; - completionData->iPad = ProfileManager.GetPrimaryPad(); - - if( ui.IsSceneInStack( ProfileManager.GetPrimaryPad(), eUIScene_EndPoem ) ) - { - completionData->scene = eUIScene_EndPoem; - } - else - { - completionData->scene = eUIScene_PauseMenu; - } - - loadingParams->completionData = completionData; - - // 4J Stu - Xbox only -#ifdef _XBOX - // Temporarily make this scene fullscreen - CXuiSceneBase::SetPlayerBaseScenePosition( ProfileManager.GetPrimaryPad(), CXuiSceneBase::e_BaseScene_Fullscreen ); -#endif - - ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams , eUILayer_Fullscreen, eUIGroup_Fullscreen); - - } - break; - case eAppAction_AutosaveSaveGameCapturedThumbnail: - - { - app.SetAutosaveTimerTime(); - SetAction(i,eAppAction_Idle); - -#if defined(_XBOX_ONE) || defined(__ORBIS__) - app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_AutoSaveGame); - - if(app.GetGameHostOption(eGameHostOption_DisableSaving)) StorageManager.SetSaveDisabled(true); -#else - // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen - ui.HideAllGameUIElements(); - - //app.CloseAllPlayersXuiScenes(); - // Hide the other players scenes - ui.ShowOtherPlayersBaseScene(ProfileManager.GetPrimaryPad(), false); - - // This just allows it to be shown - if(pMinecraft->localgameModes[ProfileManager.GetPrimaryPad()] != nullptr) pMinecraft->localgameModes[ProfileManager.GetPrimaryPad()]->getTutorial()->showTutorialPopup(false); - - //INT saveOrCheckpointId = 0; - //bool validSave = StorageManager.GetSaveUniqueNumber(&saveOrCheckpointId); - //SentientManager.RecordLevelSaveOrCheckpoint(ProfileManager.GetPrimaryPad(), saveOrCheckpointId); - - - LoadingInputParams *loadingParams = new LoadingInputParams(); - loadingParams->func = &UIScene_PauseMenu::SaveWorldThreadProc; - - loadingParams->lpParam = (LPVOID)(true); - - UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); - completionData->bShowBackground=TRUE; - completionData->bShowLogo=TRUE; - completionData->type = e_ProgressCompletion_AutosaveNavigateBack; - completionData->iPad = ProfileManager.GetPrimaryPad(); - //completionData->bAutosaveWasMenuDisplayed=ui.GetMenuDisplayed(ProfileManager.GetPrimaryPad()); - loadingParams->completionData = completionData; - - // 4J Stu - Xbox only -#ifdef _XBOX - // Temporarily make this scene fullscreen - CXuiSceneBase::SetPlayerBaseScenePosition( ProfileManager.GetPrimaryPad(), CXuiSceneBase::e_BaseScene_Fullscreen ); -#endif - - ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams , eUILayer_Fullscreen, eUIGroup_Fullscreen); -#endif - } - break; - case eAppAction_ExitPlayer: - // a secondary player has chosen to quit - { - int iPlayerC=g_NetworkManager.GetPlayerCount(); - - // Since the player is exiting, let's flush any profile writes for them, and hope we're not breaking TCR 136... -#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) - StorageManager.ForceQueuedProfileWrites(i); - LeaderboardManager::Instance()->OpenSession(); - for (int j = 0; j < XUSER_MAX_COUNT; j++) - { - if( ProfileManager.IsSignedIn(j) ) - { - app.DebugPrintf("Stats save for an offline game for the player at index %d\n", 0); - Minecraft::GetInstance()->forceStatsSave(j); - } - } - LeaderboardManager::Instance()->CloseSession(); -#else - ProfileManager.ForceQueuedProfileWrites(i); -#endif - - // not required - it's done within the removeLocalPlayerIdx - // if(pMinecraft->level->isClientSide) - // { - // // we need to remove the qnetplayer, or this player won't be able to get back into the game until qnet times out and removes them - // g_NetworkManager.NotifyPlayerLeaving(g_NetworkManager.GetLocalPlayerByUserIndex(i)); - // } - - // if there are any tips showing, we need to close them - - pMinecraft->gui->clearMessages(i); - - // Make sure we've not got this player selected as current - this shouldn't be the case anyway - pMinecraft->setLocalPlayerIdx(ProfileManager.GetPrimaryPad()); - pMinecraft->removeLocalPlayerIdx(i); - -#ifdef _XBOX - // tell the xui scenes a splitscreen player left - has to come after removeLocalPlayerIdx which calls updatePlayerViewportAssignments - XUIMessage xuiMsg; - CustomMessage_Splitscreenplayer_Struct myMsgData; - CustomMessage_Splitscreenplayer( &xuiMsg, &myMsgData, false); - - // send the message - for(int idx=0;idxlocalplayers[idx]!=nullptr)) - { - XuiBroadcastMessage( CXuiSceneBase::GetPlayerBaseScene(idx), &xuiMsg ); - } - } -#endif - -#ifndef _XBOX - // Wipe out the tooltips - ui.SetTooltips(i, -1); -#endif - - // Change the presence info - // Are we offline or online, and how many players are there - if(iPlayerC>2) // one player is about to leave here - they'll be set to idle in the qnet manager player leave - { - for(int iPlayer=0;iPlayerlocalplayers[iPlayer]) - { - if(g_NetworkManager.IsLocalGame()) - { - ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false); - } - else - { - ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER,false); - } - } - } - } - else - { - for(int iPlayer=0;iPlayerlocalplayers[iPlayer]) - { - if(g_NetworkManager.IsLocalGame()) - { - ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE,false); - } - else - { - ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER_1P,false); - } - } - } - } - -#ifdef _DURANGO - ProfileManager.RemoveGamepadFromGame(i); -#endif - - SetAction(i,eAppAction_Idle); - } - break; - case eAppAction_ExitPlayerPreLogin: - { - int iPlayerC=g_NetworkManager.GetPlayerCount(); - // Since the player is exiting, let's flush any profile writes for them, and hope we're not breaking TCR 136... -#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) - StorageManager.ForceQueuedProfileWrites(i); -#else - ProfileManager.ForceQueuedProfileWrites(i); -#endif - // if there are any tips showing, we need to close them - - pMinecraft->gui->clearMessages(i); - - // Make sure we've not got this player selected as current - this shouldn't be the case anyway - pMinecraft->setLocalPlayerIdx(ProfileManager.GetPrimaryPad()); - pMinecraft->removeLocalPlayerIdx(i); - -#ifdef _XBOX - // tell the xui scenes a splitscreen player left - has to come after removeLocalPlayerIdx which calls updatePlayerViewportAssignments - XUIMessage xuiMsg; - CustomMessage_Splitscreenplayer_Struct myMsgData; - CustomMessage_Splitscreenplayer( &xuiMsg, &myMsgData, false); - - // send the message - for(int idx=0;idxlocalplayers[idx]!=nullptr)) - { - XuiBroadcastMessage( CXuiSceneBase::GetPlayerBaseScene(idx), &xuiMsg ); - } - } -#endif - -#ifndef _XBOX - // Wipe out the tooltips - ui.SetTooltips(i, -1); -#endif - - // Change the presence info - // Are we offline or online, and how many players are there - if(iPlayerC>2) // one player is about to leave here - they'll be set to idle in the qnet manager player leave - { - for(int iPlayer=0;iPlayerlocalplayers[iPlayer]) - { - if(g_NetworkManager.IsLocalGame()) - { - ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false); - } - else - { - ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER,false); - } - } - } - } - else - { - for(int iPlayer=0;iPlayerlocalplayers[iPlayer]) - { - if(g_NetworkManager.IsLocalGame()) - { - ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE,false); - } - else - { - ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER_1P,false); - } - } - } - } - SetAction(i,eAppAction_Idle); - } - break; - -#ifdef __ORBIS__ - case eAppAction_OptionsSaveNoSpace: - { - SetAction(i,eAppAction_Idle); - - SceSaveDataDialogParam param; - SceSaveDataDialogSystemMessageParam sysParam; - SceSaveDataDialogItems items; - SceSaveDataDirName dirName; - - sceSaveDataDialogParamInitialize(¶m); - param.mode = SCE_SAVE_DATA_DIALOG_MODE_SYSTEM_MSG; - param.dispType = SCE_SAVE_DATA_DIALOG_TYPE_SAVE; - memset(&sysParam,0,sizeof(sysParam)); - param.sysMsgParam = &sysParam; - param.sysMsgParam->sysMsgType = SCE_SAVE_DATA_DIALOG_SYSMSG_TYPE_NOSPACE_CONTINUABLE; - param.sysMsgParam->value = app.GetOptionsBlocksRequired(i); - memset(&items, 0, sizeof(items)); - param.items = &items; - param.items->userId = ProfileManager.getUserID(i); - - int ret = sceSaveDataDialogInitialize(); - ret = sceSaveDataDialogOpen(¶m); - - app.SetOptionsSaveDataDialogRunning(true);//m_bOptionsSaveDataDialogRunning = true; - //pClass->m_eSaveIncompleteType = saveIncompleteType; - - //StorageManager.SetSaveDisabled(true); - //pClass->EnterSaveNotificationSection(); - - } - break; -#endif - - case eAppAction_ExitWorld: - - SetAction(i,eAppAction_Idle); - - // HUCKLE - added for quit game on disconnect -#ifdef _WINDOWS64 - if(g_Win64MultiplayerQuitOnDisconnect == true) - { - app.ExitGame(); - return; - } -#endif - - // If we're already leaving don't exit - if (g_NetworkManager.IsLeavingGame()) - { - break; - } - - pMinecraft->gui->clearMessages(); - - // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen - ui.HideAllGameUIElements(); - - // reset the flag stopping new dlc message being shown if you've seen the message before - DisplayNewDLCTipAgain(); - - // clear the autosave timer that might be on screen - ui.ShowAutosaveCountdownTimer(false); - - // Hide the selected item text - ui.HideAllGameUIElements(); - - // Since the player forced the exit, let's flush any profile writes, and hope we're not breaking TCR 136... -#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) - StorageManager.ForceQueuedProfileWrites(); - LeaderboardManager::Instance()->OpenSession(); - for (int j = 0; j < XUSER_MAX_COUNT; j++) - { - if( ProfileManager.IsSignedIn(j) ) - { - app.DebugPrintf("Stats save for an offline game for the player at index %d\n", 0); - Minecraft::GetInstance()->forceStatsSave(j); - } - } - LeaderboardManager::Instance()->CloseSession(); -#elif (defined _XBOX) - ProfileManager.ForceQueuedProfileWrites(); -#endif - - // 4J-PB - cancel any possible string verifications queued with LIVE - //InputManager.CancelAllVerifyInProgress(); - - if(ProfileManager.IsFullVersion()) - { - - // In a split screen, only the primary player actually quits the game, others just remove their players - if( i != ProfileManager.GetPrimaryPad() ) - { - // Make sure we've not got this player selected as current - this shouldn't be the case anyway - pMinecraft->setLocalPlayerIdx(ProfileManager.GetPrimaryPad()); - pMinecraft->removeLocalPlayerIdx(i); - -#ifdef _DURANGO - ProfileManager.RemoveGamepadFromGame(i); -#endif - SetAction(i,eAppAction_Idle); - return; - } - // flag to capture the save thumbnail - SetAction(i,eAppAction_ExitWorldCapturedThumbnail, param); - } - else - { - // ask the player if they would like to upgrade, or they'll lose the level - UINT uiIDA[2]; - uiIDA[0]=IDS_CONFIRM_OK; - uiIDA[1]=IDS_CONFIRM_CANCEL; - ui.RequestErrorMessage(IDS_UNLOCK_TITLE, IDS_UNLOCK_TOSAVE_TEXT, uiIDA, 2, i,&CMinecraftApp::UnlockFullExitReturned,this); - } - - // Change the presence info - // Are we offline or online, and how many players are there - - if(g_NetworkManager.GetPlayerCount()>1) - { - for(int j=0;jlocalplayers[j]) - { - if(g_NetworkManager.IsLocalGame()) - { - app.SetRichPresenceContext(j,CONTEXT_GAME_STATE_BLANK); - ProfileManager.SetCurrentGameActivity(j,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false); - } - else - { - app.SetRichPresenceContext(j,CONTEXT_GAME_STATE_BLANK); - ProfileManager.SetCurrentGameActivity(j,CONTEXT_PRESENCE_MULTIPLAYER,false); - } - TelemetryManager->RecordLevelExit(j, eSen_LevelExitStatus_Exited); - } - } - } - else - { - app.SetRichPresenceContext(i,CONTEXT_GAME_STATE_BLANK); - if(g_NetworkManager.IsLocalGame()) - { - ProfileManager.SetCurrentGameActivity(i,CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE,false); - } - else - { - ProfileManager.SetCurrentGameActivity(i,CONTEXT_PRESENCE_MULTIPLAYER_1P,false); - } - TelemetryManager->RecordLevelExit(i, eSen_LevelExitStatus_Exited); - } - break; - case eAppAction_ExitWorldCapturedThumbnail: - { - SetAction(i,eAppAction_Idle); - // Stop app running - SetGameStarted(false); - SetChangingSessionType(true); // Added to stop handling ethernet disconnects - - ui.CloseAllPlayersScenes(); - - // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen - ui.HideAllGameUIElements(); - - // 4J Stu - Fix for #12368 - Crash: Game crashes when saving then exiting and selecting to save - for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx) - { -#ifdef _XBOX - app.TutorialSceneNavigateBack(idx,true); -#endif - - // 4J Stu - Fix for #13257 - CRASH: Gameplay: Title crashed after exiting the tutorial - // It doesn't matter if they were in the tutorial already - pMinecraft->playerLeftTutorial( idx ); - } - - LoadingInputParams *loadingParams = new LoadingInputParams(); - loadingParams->func = &UIScene_PauseMenu::ExitWorldThreadProc; - loadingParams->lpParam = param; - - UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); - // If param is non-null then this is a forced exit by the server, so make sure the player knows why - // 4J Stu - Changed - Don't use the FullScreenProgressScreen for action, use a dialog instead - completionData->bRequiresUserAction = FALSE;//(param != nullptr) ? TRUE : FALSE; - completionData->bShowTips = (param != nullptr) ? FALSE : TRUE; - completionData->bShowBackground=TRUE; - completionData->bShowLogo=TRUE; - completionData->type = e_ProgressCompletion_NavigateToHomeMenu; - completionData->iPad = DEFAULT_XUI_MENU_USER; - loadingParams->completionData = completionData; - - ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); - } - break; - case eAppAction_ExitWorldTrial: - { - SetAction(i,eAppAction_Idle); - - pMinecraft->gui->clearMessages(); - - // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen - ui.HideAllGameUIElements(); - - // Stop app running - SetGameStarted(false); - - ui.CloseAllPlayersScenes(); - - // 4J Stu - Fix for #12368 - Crash: Game crashes when saving then exiting and selecting to save - for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx) - { -#ifdef _XBOX - app.TutorialSceneNavigateBack(idx,true); -#endif - - // 4J Stu - Fix for #13257 - CRASH: Gameplay: Title crashed after exiting the tutorial - // It doesn't matter if they were in the tutorial already - pMinecraft->playerLeftTutorial( idx ); - } - - LoadingInputParams *loadingParams = new LoadingInputParams(); - loadingParams->func = &UIScene_PauseMenu::ExitWorldThreadProc; - loadingParams->lpParam = param; - - UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); - completionData->bShowBackground=TRUE; - completionData->bShowLogo=TRUE; - completionData->type = e_ProgressCompletion_NavigateToHomeMenu; - completionData->iPad = DEFAULT_XUI_MENU_USER; - loadingParams->completionData = completionData; - - ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); - } - - break; - case eAppAction_ExitTrial: - //XLaunchNewImage(XLAUNCH_KEYWORD_DASH_ARCADE, 0); - ExitGame(); - break; - - case eAppAction_Respawn: - { - ConnectionProgressParams *param = new ConnectionProgressParams(); - param->iPad = i; - param->stringId = IDS_PROGRESS_RESPAWNING; - param->showTooltips = false; - param->setFailTimer = false; - ui.NavigateToScene(i,eUIScene_ConnectingProgress, param); - - // Need to reset this incase the player has already died and respawned - pMinecraft->localplayers[i]->SetPlayerRespawned(false); - - SetAction(i,eAppAction_WaitForRespawnComplete); - if( app.GetLocalPlayerCount()>1 ) - { - // In split screen mode, we don't want to do any async loading or flushing of the cache, just a simple respawn - pMinecraft->localplayers[i]->respawn(); - - // If the respawn requires a dimension change then the action will have changed - //if(app.GetXuiAction(i) == eAppAction_Respawn) - //{ - // SetAction(i,eAppAction_Idle); - // CloseXuiScenes(i); - //} - } - else - { - //SetAction(i,eAppAction_WaitForRespawnComplete); - - //LoadingInputParams *loadingParams = new LoadingInputParams(); - //loadingParams->func = &CScene_Death::RespawnThreadProc; - //loadingParams->lpParam = (LPVOID)i; - - // Disable game & update thread whilst we do any of this - //app.SetGameStarted(false); - pMinecraft->gameRenderer->DisableUpdateThread(); - - // 4J Stu - We don't need this on a thread in multiplayer as respawning is asynchronous. - pMinecraft->localplayers[i]->respawn(); - - //app.SetGameStarted(true); - pMinecraft->gameRenderer->EnableUpdateThread(); - - //UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); - //completionData->bShowBackground=TRUE; - //completionData->bShowLogo=TRUE; - //completionData->type = e_ProgressCompletion_CloseUIScenes; - //completionData->iPad = i; - //loadingParams->completionData = completionData; - - //app.NavigateToScene(i,eUIScene_FullscreenProgress, loadingParams, true); - } - } - break; - case eAppAction_WaitForRespawnComplete: - player = pMinecraft->localplayers[i]; - if(player != nullptr && player->GetPlayerRespawned()) - { - SetAction(i,eAppAction_Idle); - - if(ui.IsSceneInStack(i, eUIScene_EndPoem)) - { - ui.NavigateBack(i,false,eUIScene_EndPoem); - } - else - { - ui.CloseUIScenes(i); - } - - // clear the progress messages - - // pMinecraft->progressRenderer->progressStart(-1); - // pMinecraft->progressRenderer->progressStage(-1); - } - else if(!g_NetworkManager.IsInGameplay()) - { - SetAction(i,eAppAction_Idle); - } - break; - case eAppAction_WaitForDimensionChangeComplete: - player = pMinecraft->localplayers[i]; - if(player != nullptr && player->connection && player->connection->isStarted()) - { - SetAction(i,eAppAction_Idle); - ui.CloseUIScenes(i); - } - else if(!g_NetworkManager.IsInGameplay()) - { - SetAction(i,eAppAction_Idle); - } - break; - case eAppAction_PrimaryPlayerSignedOut: - { - //SetAction(i,eAppAction_Idle); - - // clear the autosavetimer that might be displayed - ui.ShowAutosaveCountdownTimer(false); - - // If the player signs out before the game started the server can be killed a bit earlier to stop - // the loading or saving of a new game continuing running while the UI/Guide is up - if(!app.GetGameStarted()) MinecraftServer::HaltServer(true); - - // inform the player they are being returned to the menus because they signed out - StorageManager.SetSaveDeviceSelected(i,false); - // need to clear the player stats - can't assume it'll be done in setlevel - we may not be in the game - StatsCounter* pStats = Minecraft::GetInstance()->stats[ i ]; - pStats->clear(); - - // 4J-PB - the libs will display the Returned to Title screen - // UINT uiIDA[1]; - // uiIDA[0]=IDS_CONFIRM_OK; - // - // ui.RequestMessageBox(IDS_RETURNEDTOMENU_TITLE, IDS_RETURNEDTOTITLESCREEN_TEXT, uiIDA, 1, i,&CMinecraftApp::PrimaryPlayerSignedOutReturned,this,app.GetStringTable()); - if( g_NetworkManager.IsInSession() ) - { - app.SetAction(i,eAppAction_PrimaryPlayerSignedOutReturned); - } - else - { - app.SetAction(i,eAppAction_PrimaryPlayerSignedOutReturned_Menus); - MinecraftServer::resetFlags(); - } - } - break; - case eAppAction_EthernetDisconnected: - { - app.DebugPrintf("Handling eAppAction_EthernetDisconnected\n"); - SetAction(i,eAppAction_Idle); - - // 4J Stu - Fix for #12530 -TCR 001 BAS Game Stability: Title will crash if the player disconnects while starting a new world and then opts to play the tutorial once they have been returned to the Main Menu. - if(!g_NetworkManager.IsLeavingGame()) - { - app.DebugPrintf("Handling eAppAction_EthernetDisconnected - Not leaving game\n"); - // 4J-PB - not the same as a signout. We should only leave the game if this machine is not the host. We shouldn't get rid of the save device either. - if( g_NetworkManager.IsHost() ) - { - app.DebugPrintf("Handling eAppAction_EthernetDisconnected - Is Host\n"); - // If it's already a local game, then an ethernet disconnect should have no effect - if( !g_NetworkManager.IsLocalGame() && g_NetworkManager.IsInGameplay() ) - { - // Change the session to an offline session - SetAction(i,eAppAction_ChangeSessionType); - } - else if(!g_NetworkManager.IsLocalGame() && !g_NetworkManager.IsInGameplay() ) - { - // There are two cases here, either: - // 1. We're early enough in the create/load game that we can do a really minimal shutdown or - // 2. We're far enough in (game has started but the actual game started flag hasn't been set) that we should just wait until we're in the game and switch to offline mode - - // If there's a non-null level then, for our purposes, the game has started - bool gameStarted = false; - for(int j = 0; j < pMinecraft->levels.length; j++) - { - if (pMinecraft->levels.data[i] != nullptr) - { - gameStarted = true; - break; - } - } - - if (!gameStarted) - { - // 1. Exit - MinecraftServer::HaltServer(); - - // Fix for #12530 - TCR 001 BAS Game Stability: Title will crash if the player disconnects while starting a new world and then opts to play the tutorial once they have been returned to the Main Menu. - // 4J Stu - Leave the session - g_NetworkManager.LeaveGame(FALSE); - - // need to clear the player stats - can't assume it'll be done in setlevel - we may not be in the game - StatsCounter* pStats = Minecraft::GetInstance()->stats[ i ]; - pStats->clear(); - UINT uiIDA[1]; - uiIDA[0]=IDS_CONFIRM_OK; - - ui.RequestErrorMessage(g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST), g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE), uiIDA, 1, i,&CMinecraftApp::EthernetDisconnectReturned,this); - } - else - { - // 2. Switch to offline - SetAction(i,eAppAction_ChangeSessionType); - } - } - } - else - { -#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ - if(UIScene_LoadOrJoinMenu::isSaveTransferRunning()) - { - // the save transfer is still in progress, delay jumping back to the main menu until we've cleaned up - SetAction(i,eAppAction_EthernetDisconnected); - } - else -#endif - { - app.DebugPrintf("Handling eAppAction_EthernetDisconnected - Not host\n"); - // need to clear the player stats - can't assume it'll be done in setlevel - we may not be in the game - StatsCounter* pStats = Minecraft::GetInstance()->stats[ i ]; - pStats->clear(); - UINT uiIDA[1]; - uiIDA[0]=IDS_CONFIRM_OK; - - ui.RequestErrorMessage(g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST), g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE), uiIDA, 1, i,&CMinecraftApp::EthernetDisconnectReturned,this); - - } - } - } - } - break; - // We currently handle both these returns the same way. - case eAppAction_EthernetDisconnectedReturned: - case eAppAction_PrimaryPlayerSignedOutReturned: - { - SetAction(i,eAppAction_Idle); - - pMinecraft->gui->clearMessages(); - - // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen - ui.HideAllGameUIElements(); - - // set the state back to pre-game - ProfileManager.ResetProfileProcessState(); - - - if( g_NetworkManager.IsLeavingGame() ) - { - // 4J Stu - If we are already leaving the game, then we just need to signal that the player signed out to stop saves - pMinecraft->progressRenderer->progressStartNoAbort( IDS_EXITING_GAME ); - pMinecraft->progressRenderer->progressStage(-1); - // This has no effect on client machines - MinecraftServer::HaltServer(true); - } - else - { - // Stop app running - SetGameStarted(false); - - // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen - ui.HideAllGameUIElements(); - - ui.CloseAllPlayersScenes(); - - // 4J Stu - Fix for #12368 - Crash: Game crashes when saving then exiting and selecting to save - for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx) - { -#ifdef _XBOX - app.TutorialSceneNavigateBack(idx,true); -#endif - - // 4J Stu - Fix for #13257 - CRASH: Gameplay: Title crashed after exiting the tutorial - // It doesn't matter if they were in the tutorial already - pMinecraft->playerLeftTutorial( idx ); - } - - LoadingInputParams *loadingParams = new LoadingInputParams(); - loadingParams->func = &CMinecraftApp::SignoutExitWorldThreadProc; - - UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); - completionData->bShowBackground=TRUE; - completionData->bShowLogo=TRUE; - completionData->iPad=DEFAULT_XUI_MENU_USER; - completionData->type = e_ProgressCompletion_NavigateToHomeMenu; - loadingParams->completionData = completionData; - - ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); - } - } - break; - case eAppAction_PrimaryPlayerSignedOutReturned_Menus: - SetAction(i,eAppAction_Idle); - // set the state back to pre-game - ProfileManager.ResetProfileProcessState(); - // clear the save device - StorageManager.SetSaveDeviceSelected(i,false); - - ui.UpdatePlayerBasePositions(); - // there are multiple layers in the help menu, so a navigate back isn't enough - ui.NavigateToHomeMenu(); - - break; - case eAppAction_EthernetDisconnectedReturned_Menus: - SetAction(i,eAppAction_Idle); - // set the state back to pre-game - ProfileManager.ResetProfileProcessState(); - - ui.UpdatePlayerBasePositions(); - - // there are multiple layers in the help menu, so a navigate back isn't enough - ui.NavigateToHomeMenu(); - - break; - - case eAppAction_TrialOver: - { - SetAction(i,eAppAction_Idle); - UINT uiIDA[2]; - uiIDA[0]=IDS_UNLOCK_TITLE; - uiIDA[1]=IDS_EXIT_GAME; - - ui.RequestErrorMessage(IDS_TRIALOVER_TITLE, IDS_TRIALOVER_TEXT, uiIDA, 2, i,&CMinecraftApp::TrialOverReturned,this); - } - break; - - // INVITES - case eAppAction_DashboardTrialJoinFromInvite: - { - TelemetryManager->RecordUpsellPresented(i, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID); - - SetAction(i,eAppAction_Idle); - UINT uiIDA[2]; - uiIDA[0]=IDS_CONFIRM_OK; - uiIDA[1]=IDS_CONFIRM_CANCEL; - - ui.RequestErrorMessage(IDS_UNLOCK_TITLE, IDS_UNLOCK_ACCEPT_INVITE, uiIDA, 2, i,&CMinecraftApp::UnlockFullInviteReturned,this); - } - break; - case eAppAction_ExitAndJoinFromInvite: - { - UINT uiIDA[3]; - - SetAction(i,eAppAction_Idle); - // Check the player really wants to do this - -#if defined(_XBOX_ONE) || defined(__ORBIS__) - // Show save option is saves ARE disabled - if(ProfileManager.IsFullVersion() && StorageManager.GetSaveDisabled() && i==ProfileManager.GetPrimaryPad() && g_NetworkManager.IsHost() && GetGameStarted() ) - { - uiIDA[0]=IDS_CONFIRM_CANCEL; - uiIDA[1]=IDS_EXIT_GAME_SAVE; - uiIDA[2]=IDS_EXIT_GAME_NO_SAVE; - - ui.RequestAlertMessage(IDS_EXIT_GAME, IDS_CONFIRM_LEAVE_VIA_INVITE, uiIDA, 3, i,&CMinecraftApp::ExitAndJoinFromInviteSaveDialogReturned,this); - } - else -#else - if(ProfileManager.IsFullVersion() && !StorageManager.GetSaveDisabled() && i==ProfileManager.GetPrimaryPad() && g_NetworkManager.IsHost() && GetGameStarted() ) - { - uiIDA[0]=IDS_CONFIRM_CANCEL; - uiIDA[1]=IDS_EXIT_GAME_SAVE; - uiIDA[2]=IDS_EXIT_GAME_NO_SAVE; - - ui.RequestAlertMessage(IDS_EXIT_GAME, IDS_CONFIRM_LEAVE_VIA_INVITE, uiIDA, 3, i,&CMinecraftApp::ExitAndJoinFromInviteSaveDialogReturned,this); - } - else -#endif - { - if(!ProfileManager.IsFullVersion()) - { - TelemetryManager->RecordUpsellPresented(i, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID); - - // upsell - uiIDA[0]=IDS_CONFIRM_OK; - uiIDA[1]=IDS_CONFIRM_CANCEL; - ui.RequestErrorMessage(IDS_UNLOCK_TITLE, IDS_UNLOCK_ACCEPT_INVITE, uiIDA, 2, i,&CMinecraftApp::UnlockFullInviteReturned,this); - } - else - { - uiIDA[0]=IDS_CONFIRM_CANCEL; - uiIDA[1]=IDS_CONFIRM_OK; - ui.RequestAlertMessage(IDS_EXIT_GAME, IDS_CONFIRM_LEAVE_VIA_INVITE, uiIDA, 2,i,&CMinecraftApp::ExitAndJoinFromInvite,this); - } - } - } - break; - case eAppAction_ExitAndJoinFromInviteConfirmed: - { - SetAction(i,eAppAction_Idle); - - pMinecraft->gui->clearMessages(); - - // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen - ui.HideAllGameUIElements(); - - // Stop app running - SetGameStarted(false); - - ui.CloseAllPlayersScenes(); - - // 4J Stu - Fix for #12368 - Crash: Game crashes when saving then exiting and selecting to save - for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx) - { -#ifdef _XBOX - app.TutorialSceneNavigateBack(idx,true); -#endif - - // 4J Stu - Fix for #13257 - CRASH: Gameplay: Title crashed after exiting the tutorial - // It doesn't matter if they were in the tutorial already - pMinecraft->playerLeftTutorial( idx ); - } - - // 4J-PB - may have been using a texture pack with audio , so clean up anything texture pack related here - - // unload any texture pack audio - // if there is audio in use, clear out the audio, and unmount the pack - TexturePack *pTexPack=Minecraft::GetInstance()->skins->getSelected(); - DLCTexturePack *pDLCTexPack=nullptr; - - if(pTexPack->hasAudio()) - { - // get the dlc texture pack, and store it - pDLCTexPack=static_cast(pTexPack); - } - - // change to the default texture pack - pMinecraft->skins->selectTexturePackById(TexturePackRepository::DEFAULT_TEXTURE_PACK_ID); - - if(pTexPack->hasAudio()) - { - // need to stop the streaming audio - by playing streaming audio from the default texture pack now - // reset the streaming sounds back to the normal ones -#ifndef _XBOX - pMinecraft->soundEngine->SetStreamingSounds(eStream_Overworld_Calm1,eStream_Overworld_piano3, - eStream_Nether1,eStream_Nether4, - eStream_end_dragon,eStream_end_end, - eStream_Overworld_Creative1,eStream_Overworld_Creative6, - eStream_Overworld_Menu1,eStream_Overworld_Menu4, - eStream_BattleMode1,eStream_BattleMode4, - eStream_CD_1); -#endif - pMinecraft->soundEngine->playStreaming(L"", 0, 0, 0, 1, 1); - -#ifdef _XBOX - if(pDLCTexPack->m_pStreamedWaveBank!=nullptr) - { - pDLCTexPack->m_pStreamedWaveBank->Destroy(); - } - if(pDLCTexPack->m_pSoundBank!=nullptr) - { - pDLCTexPack->m_pSoundBank->Destroy(); - } -#endif -#ifdef _DURANGO - DWORD result = StorageManager.UnmountInstalledDLC(L"TPACK"); -#else - DWORD result = StorageManager.UnmountInstalledDLC("TPACK"); -#endif - app.DebugPrintf("Unmount result is %d\n",result); - } - -#ifdef _XBOX_ONE - // 4J Stu - It's possible that we can sign in/remove players between the mask initially being set and this point - m_InviteData.dwLocalUsersMask = 0; - for(unsigned int index = 0; index < XUSER_MAX_COUNT; ++index) - { - if(ProfileManager.IsSignedIn(index) ) - { - if (index == i || pMinecraft->localplayers[index] != nullptr) - { - m_InviteData.dwLocalUsersMask |= g_NetworkManager.GetLocalPlayerMask(index); - } - } - } -#endif - - LoadingInputParams *loadingParams = new LoadingInputParams(); - loadingParams->func = &CGameNetworkManager::ExitAndJoinFromInviteThreadProc; - loadingParams->lpParam = static_cast(&m_InviteData); - - UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); - completionData->bShowBackground=TRUE; - completionData->bShowLogo=TRUE; - completionData->iPad=DEFAULT_XUI_MENU_USER; - completionData->type = e_ProgressCompletion_NoAction; - loadingParams->completionData = completionData; - - ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); - } - - break; - case eAppAction_JoinFromInvite: - { - SetAction(i,eAppAction_Idle); - - // 4J Stu - Move this state block from CPlatformNetworkManager::ExitAndJoinFromInviteThreadProc, as g_NetworkManager.JoinGameFromInviteInfo ultimately can call NavigateToScene, - /// and we should only be calling that from the main thread - app.SetTutorialMode( false ); - - g_NetworkManager.SetLocalGame(false); - - JoinFromInviteData *inviteData = static_cast(param); - // 4J-PB - clear any previous connection errors - Minecraft::GetInstance()->clearConnectionFailed(); - - app.DebugPrintf( "Changing Primary Pad on an invite accept - pad was %d, and is now %d\n", ProfileManager.GetPrimaryPad(), inviteData->dwUserIndex ); - ProfileManager.SetLockedProfile(inviteData->dwUserIndex); - ProfileManager.SetPrimaryPad(inviteData->dwUserIndex); - -#ifdef _XBOX_ONE - // 4J Stu - If a player is signed in (i.e. locked) but not in the mask, unlock them - for(unsigned int index = 0; index < XUSER_MAX_COUNT; ++index) - { - if( index != inviteData->dwUserIndex && ProfileManager.IsSignedIn(index) ) - { - if( (m_InviteData.dwLocalUsersMask & g_NetworkManager.GetLocalPlayerMask( index ) ) == 0 ) - { - ProfileManager.RemoveGamepadFromGame(index); - } - } - } -#endif - - // change the minecraft player name - Minecraft::GetInstance()->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); - - bool success = g_NetworkManager.JoinGameFromInviteInfo( - inviteData->dwUserIndex, // dwUserIndex - inviteData->dwLocalUsersMask, // dwUserMask - inviteData->pInviteInfo ); // pInviteInfo - - if( !success ) - { - app.DebugPrintf( "Failed joining game from invite\n" ); - //return hr; - - // 4J Stu - Copied this from XUI_FullScreenProgress to properly handle the fail case, as the thread will no longer be failing - UINT uiIDA[1]; - uiIDA[0]=IDS_CONFIRM_OK; - ui.RequestErrorMessage( IDS_CONNECTION_FAILED, IDS_CONNECTION_LOST_SERVER, uiIDA,1,ProfileManager.GetPrimaryPad()); - - ui.NavigateToHomeMenu(); - ui.UpdatePlayerBasePositions(); - } - } - break; - case eAppAction_ChangeSessionType: - { - // If we are not in gameplay yet, then wait until the server is setup before changing the session type - if( g_NetworkManager.IsInGameplay() ) - { - // This kicks off a thread that waits for the server to end, then closes the current session, starts a new one and joins the local players into it - - SetAction(i,eAppAction_Idle); - - if( !GetChangingSessionType() && !g_NetworkManager.IsLocalGame() ) - { - SetGameStarted(false); - SetChangingSessionType(true); - SetReallyChangingSessionType(true); - - // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen - ui.HideAllGameUIElements(); - - if( !ui.IsSceneInStack( ProfileManager.GetPrimaryPad(), eUIScene_EndPoem ) ) - { - ui.CloseAllPlayersScenes(); - } - ui.ShowOtherPlayersBaseScene(ProfileManager.GetPrimaryPad(), true); - - // Remove this line to fix: - // #49084 - TU5: Code: Gameplay: The title crashes every time client navigates to 'Play game' menu and loads/creates new game after a "Connection to Xbox LIVE was lost" message has appeared. - //app.NavigateToScene(0,eUIScene_Main); - - LoadingInputParams *loadingParams = new LoadingInputParams(); - loadingParams->func = &CGameNetworkManager::ChangeSessionTypeThreadProc; - loadingParams->lpParam = nullptr; - - UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); -#ifdef __PS3__ - completionData->bRequiresUserAction=FALSE; -#else - completionData->bRequiresUserAction=TRUE; -#endif - completionData->bShowBackground=TRUE; - completionData->bShowLogo=TRUE; - completionData->iPad=DEFAULT_XUI_MENU_USER; - if( ui.IsSceneInStack( ProfileManager.GetPrimaryPad(), eUIScene_EndPoem ) ) - { - completionData->type = e_ProgressCompletion_NavigateBackToScene; - completionData->scene = eUIScene_EndPoem; - } - else - { - completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes; - } - loadingParams->completionData = completionData; - - ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); - } - } - else if( g_NetworkManager.IsLeavingGame() ) - { - // If we are leaving the game, then ignore the state change - SetAction(i,eAppAction_Idle); - } -#if 0 - // 4J-HG - Took this out since ChangeSessionType is only set in two places (both in EthernetDisconnected) and this case is handled there, plus this breaks - // this if statements original purpose (to allow us to wait for IsInGameplay before actioning switching to offline - - // QNet must do this kind of thing automatically by itself, but on PS3 at least, we need the disconnection to definitely end up with us out of the game one way or another, - // and the other two cases above don't catch the case where we are just starting the game and get a disconnection during the loading/creation - else - { - if( g_NetworkManager.IsInSession() ) - { - g_NetworkManager._LeaveGame(); - } - } -#endif - } - break; - case eAppAction_SetDefaultOptions: - SetAction(i,eAppAction_Idle); -#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) - SetDefaultOptions((C4JStorage::PROFILESETTINGS *)param,i); -#else - SetDefaultOptions(static_cast(param), i); -#endif - - // if the profile data has been changed, then force a profile write - // It seems we're allowed to break the 5 minute rule if it's the result of a user action - CheckGameSettingsChanged(true,i); - - break; - - case eAppAction_RemoteServerSave: - { - // If the remote server save has already finished, don't complete the action - if (GetGameStarted()) - { - SetAction(ProfileManager.GetPrimaryPad(), eAppAction_Idle); - break; - } - - SetAction(i,eAppAction_WaitRemoteServerSaveComplete); - - for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) - { - ui.CloseUIScenes(i, true); - } - - // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen - ui.HideAllGameUIElements(); - - LoadingInputParams *loadingParams = new LoadingInputParams(); - loadingParams->func = &CMinecraftApp::RemoteSaveThreadProc; - loadingParams->lpParam = nullptr; - - UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); - completionData->bRequiresUserAction=FALSE; - completionData->bShowBackground=TRUE; - completionData->bShowLogo=TRUE; - completionData->iPad=DEFAULT_XUI_MENU_USER; - if( ui.IsSceneInStack( ProfileManager.GetPrimaryPad(), eUIScene_EndPoem ) ) - { - completionData->type = e_ProgressCompletion_NavigateBackToScene; - completionData->scene = eUIScene_EndPoem; - } - else - { - completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes; - } - loadingParams->completionData = completionData; - - loadingParams->cancelFunc = &CMinecraftApp::ExitGameFromRemoteSave; - loadingParams->cancelText = IDS_TOOLTIPS_EXIT; - - ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); - } - break; - case eAppAction_WaitRemoteServerSaveComplete: - // Do nothing - break; - case eAppAction_FailedToJoinNoPrivileges: - { - UINT uiIDA[1]; - uiIDA[0]=IDS_CONFIRM_OK; - C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad()); - if(result != C4JStorage::EMessage_Busy) SetAction(i,eAppAction_Idle); - } - break; - case eAppAction_ProfileReadError: - // Return player to the main menu - code largely copied from that for handling - // eAppAction_PrimaryPlayerSignedOut, although I don't think we should have got as - // far as needing to halt the server, or running the game, before returning to the menu - if(!app.GetGameStarted()) MinecraftServer::HaltServer(true); - - if( g_NetworkManager.IsInSession() ) - { - app.SetAction(i,eAppAction_PrimaryPlayerSignedOutReturned); - } - else - { - app.SetAction(i,eAppAction_PrimaryPlayerSignedOutReturned_Menus); - MinecraftServer::resetFlags(); - } - break; - - case eAppAction_BanLevel: - { - // It's possible that this state can get set after the game has been exited (e.g. by network disconnection) so we can't ban the level at that point - if(g_NetworkManager.IsInGameplay() && !g_NetworkManager.IsLeavingGame()) - { - TelemetryManager->RecordBanLevel(i); - -#if defined _XBOX - INetworkPlayer *pHost=g_NetworkManager.GetHostPlayer(); - // write the level to the banned level list, and exit the world - AddLevelToBannedLevelList(i,((NetworkPlayerXbox *)pHost)->GetUID(),GetUniqueMapName(),true); -#elif defined _XBOX_ONE - INetworkPlayer *pHost=g_NetworkManager.GetHostPlayer(); - AddLevelToBannedLevelList(i,pHost->GetUID(),GetUniqueMapName(),true); -#endif - // primary player would exit the world, secondary would exit the player - if(ProfileManager.GetPrimaryPad()==i) - { - SetAction(i,eAppAction_ExitWorld); - } - else - { - SetAction(i,eAppAction_ExitPlayer); - } - } - } - break; - case eAppAction_LevelInBanLevelList: - { - UINT uiIDA[2]; - uiIDA[0]=IDS_BUTTON_REMOVE_FROM_BAN_LIST; - uiIDA[1]=IDS_EXIT_GAME; - - // pass in the gamertag format string - WCHAR wchFormat[40]; - INetworkPlayer *player = g_NetworkManager.GetLocalPlayerByUserIndex(i); - - // If not the primary player, but the primary player has banned this level and decided not to unban - // then we may have left the game by now - if(player) - { - swprintf(wchFormat, 40, L"%ls\n\n%%ls",player->GetOnlineName()); - - C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_BANNED_LEVEL_TITLE, IDS_PLAYER_BANNED_LEVEL, uiIDA,2,i,&CMinecraftApp::BannedLevelDialogReturned,this, wchFormat); - if(result != C4JStorage::EMessage_Busy) SetAction(i,eAppAction_Idle); - } - else - { - SetAction(i,eAppAction_Idle); - } - } - break; - case eAppAction_DebugText: - // launch the xui for text entry - { -#ifdef _XBOX - CScene_TextEntry::XuiTextInputParams *pDebugTextParams= new CScene_TextEntry::XuiTextInputParams; - pDebugTextParams->iPad=i; - pDebugTextParams->wch=(WCHAR)param; - - app.NavigateToScene(i,eUIScene_TextEntry,pDebugTextParams); -#endif - SetAction(i,eAppAction_Idle); - } - break; - - case eAppAction_ReloadTexturePack: - { - SetAction(i,eAppAction_Idle); - Minecraft *pMinecraft = Minecraft::GetInstance(); - pMinecraft->textures->reloadAll(); - pMinecraft->skins->updateUI(); - - if(!pMinecraft->skins->isUsingDefaultSkin()) - { - TexturePack *pTexturePack = pMinecraft->skins->getSelected(); - - DLCPack *pDLCPack=pTexturePack->getDLCPack(); - - bool purchased = false; - // do we have a license? - if(pDLCPack && pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" )) - { - purchased = true; - } -#ifdef _XBOX - TelemetryManager->RecordTexturePackLoaded(i, pTexturePack->getId(), purchased?1:0); -#endif - } - - // 4J-PB - If the texture pack has audio, we need to switch to this - if(pMinecraft->skins->getSelected()->hasAudio()) - { - Minecraft::GetInstance()->soundEngine->playStreaming(L"", 0, 0, 0, 1, 1); - } - } - break; - - case eAppAction_ReloadFont: - { -#ifndef _XBOX - app.DebugPrintf( - "[Consoles_App] eAppAction_ReloadFont, ingame='%s'.\n", - app.GetGameStarted() ? "Yes" : "No" ); - - SetAction(i,eAppAction_Idle); - - ui.SetTooltips(i, -1); - - ui.ReloadSkin(); - ui.StartReloadSkinThread(); - - ui.setCleanupOnReload(); -#endif - } - break; - - case eAppAction_TexturePackRequired: - { -#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ - UINT uiIDA[2]; - uiIDA[0]=IDS_TEXTUREPACK_FULLVERSION; - uiIDA[1]=IDS_CONFIRM_CANCEL; // let them continue without the texture pack here (as this is only really for r - // Give the player a warning about the texture pack missing - ui.RequestErrorMessage(IDS_DLC_TEXTUREPACK_NOT_PRESENT_TITLE, IDS_DLC_TEXTUREPACK_NOT_PRESENT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::TexturePackDialogReturned,this); - SetAction(i,eAppAction_Idle); -#else -#ifdef _XBOX - ULONGLONG ullOfferID_Full; - app.GetDLCFullOfferIDForPackID(app.GetRequiredTexturePackID(),&ullOfferID_Full); - - TelemetryManager->RecordUpsellPresented(ProfileManager.GetPrimaryPad(), eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF); -#endif - UINT uiIDA[2]; - - uiIDA[0]=IDS_TEXTUREPACK_FULLVERSION; - uiIDA[1]=IDS_TEXTURE_PACK_TRIALVERSION; - - // Give the player a warning about the texture pack missing - ui.RequestErrorMessage(IDS_DLC_TEXTUREPACK_NOT_PRESENT_TITLE, IDS_DLC_TEXTUREPACK_NOT_PRESENT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::TexturePackDialogReturned,this); - SetAction(i,eAppAction_Idle); -#endif - } - - break; - } - } - - // Any TMS actions? - - eTMS = app.GetTMSAction(i); - - if(eTMS!=eTMSAction_Idle) - { - switch(eTMS) - { - // TMS++ actions - case eTMSAction_TMSPP_RetrieveFiles_CreateLoad_SignInReturned: - case eTMSAction_TMSPP_RetrieveFiles_RunPlayGame: -#ifdef _XBOX - app.TMSPP_SetTitleGroupID(GROUP_ID); - SetTMSAction(i,eTMSAction_TMSPP_GlobalFileList); -#elif defined _XBOX_ONE - SetTMSAction(i,eTMSAction_TMSPP_GlobalFileList_Waiting); - app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_Title,eTMSAction_TMSPP_UserFileList); -#else - SetTMSAction(i,eTMSAction_TMSPP_UserFileList); -#endif - break; - -#ifdef _XBOX - case eTMSAction_TMSPP_GlobalFileList: - SetTMSAction(i,eTMSAction_TMSPP_GlobalFileList_Waiting); - app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_Title,"\\",eTMSAction_TMSPP_UserFileList); - break; -#endif - case eTMSAction_TMSPP_UserFileList: - // retrieve the file list first -#if defined _XBOX - SetTMSAction(i,eTMSAction_TMSPP_UserFileList_Waiting); - app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_TitleUser,"\\",eTMSAction_TMSPP_XUIDSFile); -#elif defined _XBOX_ONE - SetTMSAction(i,eTMSAction_TMSPP_UserFileList_Waiting); - app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_TitleUser,eTMSAction_TMSPP_DLCFile); -#else - SetTMSAction(i,eTMSAction_TMSPP_XUIDSFile); -#endif - break; - case eTMSAction_TMSPP_XUIDSFile: -#ifdef _XBOX - SetTMSAction(i,eTMSAction_TMSPP_XUIDSFile_Waiting); - // pass in the next app action on the call or callback completing - app.TMSPP_ReadXuidsFile(i,eTMSAction_TMSPP_DLCFile); -#else - SetTMSAction(i,eTMSAction_TMSPP_DLCFile); -#endif - - break; - case eTMSAction_TMSPP_DLCFile: -#if defined _XBOX || defined _XBOX_ONE - SetTMSAction(i,eTMSAction_TMSPP_DLCFile_Waiting); - // pass in the next app action on the call or callback completing - app.TMSPP_ReadDLCFile(i,eTMSAction_TMSPP_BannedListFile); -#else - SetTMSAction(i,eTMSAction_TMSPP_BannedListFile); -#endif - break; - case eTMSAction_TMSPP_BannedListFile: - // If we have one in TMSPP, then we can assume we can ignore TMS -#if defined _XBOX - SetTMSAction(i,eTMSAction_TMSPP_BannedListFile_Waiting); - // pass in the next app action on the call or callback completing - if(app.TMSPP_ReadBannedList(i,eTMSAction_TMS_RetrieveFiles_Complete)==false) - { - // we don't have a banned list in TMSPP, so we should check TMS - app.ReadBannedList(i, eTMSAction_TMS_RetrieveFiles_Complete,true); - } -#elif defined _XBOX_ONE - SetTMSAction(i,eTMSAction_TMSPP_BannedListFile_Waiting); - // pass in the next app action on the call or callback completing - app.TMSPP_ReadBannedList(i,eTMSAction_TMS_RetrieveFiles_Complete); - -#else - SetTMSAction(i,eTMSAction_TMS_RetrieveFiles_Complete); -#endif - break; - - // SPECIAL CASE - where the user goes directly in to Help & Options from the main menu - case eTMSAction_TMSPP_RetrieveFiles_HelpAndOptions: - case eTMSAction_TMSPP_RetrieveFiles_DLCMain: - // retrieve the file list first -#if defined _XBOX - // pass in the next app action on the call or callback completing - SetTMSAction(i,eTMSAction_TMSPP_XUIDSFile_Waiting); - app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_Title,"\\",eTMSAction_TMSPP_DLCFileOnly); -#elif defined _XBOX_ONE - SetTMSAction(i,eTMSAction_TMSPP_GlobalFileList_Waiting); - app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_Title,eTMSAction_TMSPP_RetrieveUserFilelist_DLCFileOnly); -#else - SetTMSAction(i,eTMSAction_TMSPP_DLCFileOnly); -#endif - break; - case eTMSAction_TMSPP_RetrieveUserFilelist_DLCFileOnly: -#if defined _XBOX - SetTMSAction(i,eTMSAction_TMSPP_UserFileList_Waiting); - app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_TitleUser,"\\",eTMSAction_TMSPP_XUIDSFile); -#elif defined _XBOX_ONE - //StorageManager.TMSPP_DeleteFile(i,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,L"TP06.png",nullptr,nullptr, 0); - SetTMSAction(i,eTMSAction_TMSPP_UserFileList_Waiting); - app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_TitleUser,eTMSAction_TMSPP_DLCFileOnly); -#else - SetTMSAction(i,eTMSAction_TMSPP_DLCFileOnly); -#endif - - break; - - case eTMSAction_TMSPP_DLCFileOnly: -#if defined _XBOX || defined _XBOX_ONE - SetTMSAction(i,eTMSAction_TMSPP_DLCFile_Waiting); - // pass in the next app action on the call or callback completing - app.TMSPP_ReadDLCFile(i,eTMSAction_TMSPP_RetrieveFiles_Complete); -#else - SetTMSAction(i,eTMSAction_TMSPP_RetrieveFiles_Complete); -#endif - break; - - - case eTMSAction_TMSPP_RetrieveFiles_Complete: - SetTMSAction(i,eTMSAction_Idle); - break; - - - // TMS files - /* case eTMSAction_TMS_RetrieveFiles_CreateLoad_SignInReturned: - case eTMSAction_TMS_RetrieveFiles_RunPlayGame: - #ifdef _XBOX - SetTMSAction(i,eTMSAction_TMS_XUIDSFile_Waiting); - // pass in the next app action on the call or callback completing - app.ReadXuidsFileFromTMS(i,eTMSAction_TMS_DLCFile,true); - #else - SetTMSAction(i,eTMSAction_TMS_DLCFile); - #endif - break; - - case eTMSAction_TMS_DLCFile: - #ifdef _XBOX - SetTMSAction(i,eTMSAction_TMS_DLCFile_Waiting); - // pass in the next app action on the call or callback completing - app.ReadDLCFileFromTMS(i,eTMSAction_TMS_BannedListFile,true); - #else - SetTMSAction(i,eTMSAction_TMS_BannedListFile); - #endif - - break; - - case eTMSAction_TMS_RetrieveFiles_HelpAndOptions: - case eTMSAction_TMS_RetrieveFiles_DLCMain: - #ifdef _XBOX - SetTMSAction(i,eTMSAction_TMS_DLCFile_Waiting); - // pass in the next app action on the call or callback completing - app.ReadDLCFileFromTMS(i,eTMSAction_Idle,true); - #else - SetTMSAction(i,eTMSAction_Idle); - #endif - - break; - case eTMSAction_TMS_BannedListFile: - #ifdef _XBOX - SetTMSAction(i,eTMSAction_TMS_BannedListFile_Waiting); - // pass in the next app action on the call or callback completing - app.ReadBannedList(i, eTMSAction_TMS_RetrieveFiles_Complete,true); - #else - SetTMSAction(i,eTMSAction_TMS_RetrieveFiles_Complete); - #endif - - break; - - */ - case eTMSAction_TMS_RetrieveFiles_Complete: - SetTMSAction(i,eTMSAction_Idle); - // if(StorageManager.SetSaveDevice(&CScene_Main::DeviceSelectReturned,pClass)) - // { - // // save device already selected - // // ensure we've applied this player's settings - // app.ApplyGameSettingsChanged(ProfileManager.GetPrimaryPad()); - // app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_MultiGameJoinLoad); - // } - break; - } - } - - } -} - -int CMinecraftApp::BannedLevelDialogReturned(void *pParam,int iPad,const C4JStorage::EMessageResult result) -{ - CMinecraftApp* pApp = static_cast(pParam); - //Minecraft *pMinecraft=Minecraft::GetInstance(); - - if(result==C4JStorage::EMessage_ResultAccept) - { -#if defined _XBOX || defined _XBOX_ONE - INetworkPlayer *pHost = g_NetworkManager.GetHostPlayer(); - // unban the level - if (pHost != nullptr) - { -#if defined _XBOX - pApp->RemoveLevelFromBannedLevelList(iPad,((NetworkPlayerXbox *)pHost)->GetUID(),pApp->GetUniqueMapName()); -#else - pApp->RemoveLevelFromBannedLevelList(iPad,pHost->GetUID(),pApp->GetUniqueMapName()); -#endif - } -#endif - } - else - { - if( iPad == ProfileManager.GetPrimaryPad() ) - { - pApp->SetAction(iPad,eAppAction_ExitWorld); - } - else - { - pApp->SetAction(iPad,eAppAction_ExitPlayer); - } - } - - return 0; -} - -void CMinecraftApp::loadMediaArchive() -{ - wstring mediapath = L""; - -#ifdef __PS3__ - mediapath = L"Common\\Media\\MediaPS3"; -#elif _WINDOWS64 - mediapath = L"Common\\Media\\MediaWindows64"; -#elif __ORBIS__ - mediapath = L"Common\\Media\\MediaOrbis"; -#elif _DURANGO - mediapath = L"Common\\Media\\MediaDurango"; -#elif __PSVITA__ - mediapath = L"Common\\Media\\MediaPSVita"; -#endif - - if (!mediapath.empty()) - { - m_mediaArchive = new FolderFile(mediapath); - } -#if 0 - string path = "Common\\media.arc"; - HANDLE hFile = CreateFile( path.c_str(), - GENERIC_READ, - FILE_SHARE_READ, - nullptr, - OPEN_EXISTING, - FILE_FLAG_SEQUENTIAL_SCAN, - nullptr ); - - if( hFile != INVALID_HANDLE_VALUE ) - { - File fileHelper(convStringToWstring(path)); - DWORD dwFileSize = fileHelper.length(); - - // Initialize memory. - PBYTE m_fBody = new BYTE[ dwFileSize ]; - ZeroMemory(m_fBody, dwFileSize); - - DWORD m_fSize = 0; - BOOL hr = ReadFile( hFile, - m_fBody, - dwFileSize, - &m_fSize, - nullptr ); - - assert( m_fSize == dwFileSize ); - - CloseHandle( hFile ); - - m_mediaArchive = new ArchiveFile(m_fBody, m_fSize); - } - else - { - assert( false ); - // AHHHHHHHHHHHH - m_mediaArchive = nullptr; - } -#endif -} - -void CMinecraftApp::loadStringTable() -{ -#ifndef _XBOX - - if(m_stringTable!=nullptr) - { - // we need to unload the current string table, this is a reload - delete m_stringTable; - } -#ifdef _WINDOWS64 - m_stringTable = nullptr; - const wstring localisationCandidates[] = - { - L"Common\\Localization", // Fireblade - check multiple directories before resulting to .loc usage - L"Windows64Media\\loc", - L"..\\Minecraft.Client\\Windows64Media\\loc" - }; - - for (const auto &localisationFolder : localisationCandidates) - { - File localisationDirectory(localisationFolder); - if (localisationDirectory.exists() && localisationDirectory.isDirectory()) - { - StringTable *candidateTable = new StringTable(localisationFolder); // Fireblade - xml before loc - - const bool hasKeyString = candidateTable->hasStringKey(L"IDS_OK"); - bool hasIndexString = false; - #ifdef IDS_OK - LPCWSTR indexedString = candidateTable->getString(IDS_OK); - hasIndexString = (indexedString != nullptr && indexedString[0] != L'\0'); - #endif - - if (hasKeyString || hasIndexString) - { - m_stringTable = candidateTable; - app.DebugPrintf("Loaded language data from '%ls'\n", localisationFolder.c_str()); - break; - } - - app.DebugPrintf("Ignoring localisation path '%ls' (missing expected IDs)\n", localisationFolder.c_str()); - delete candidateTable; - } - } - - if (m_stringTable == nullptr && m_mediaArchive != nullptr) // Fireblade - fallback to previous behavior - { - const wstring localisationFile = L"languages.loc"; - if (m_mediaArchive->hasFile(localisationFile)) - { - byteArray locFile = m_mediaArchive->getFile(localisationFile); - m_stringTable = new StringTable(locFile.data, locFile.length); - delete locFile.data; - } - } - - if (m_stringTable == nullptr) - { - app.DebugPrintf("Failed to initialize language data\n"); - assert(false); - } -#else // Fireblade - other platforms keep same logic - wstring localisationFile = L"languages.loc"; - if (m_mediaArchive->hasFile(localisationFile)) - { - byteArray locFile = m_mediaArchive->getFile(localisationFile); - m_stringTable = new StringTable(locFile.data, locFile.length); - delete locFile.data; - } - else - { - m_stringTable = nullptr; - assert(false); - // AHHHHHHHHH. - } -#endif -#endif -} - -int CMinecraftApp::PrimaryPlayerSignedOutReturned(void *pParam,int iPad,const C4JStorage::EMessageResult) -{ - //CMinecraftApp* pApp = (CMinecraftApp*)pParam; - //Minecraft *pMinecraft=Minecraft::GetInstance(); - - // if the player is null, we're in the menus - //if(Minecraft::GetInstance()->player!=nullptr) - - // We always create a session before kicking of any of the game code, so even though we may still be joining/creating a game - // at this point we want to handle it differently from just being in a menu - if( g_NetworkManager.IsInSession() ) - { - app.SetAction(iPad,eAppAction_PrimaryPlayerSignedOutReturned); - } - else - { - app.SetAction(iPad,eAppAction_PrimaryPlayerSignedOutReturned_Menus); - } - return 0; -} - -int CMinecraftApp::EthernetDisconnectReturned(void *pParam,int iPad,const C4JStorage::EMessageResult) -{ - //CMinecraftApp* pApp = (CMinecraftApp*)pParam; - Minecraft *pMinecraft=Minecraft::GetInstance(); - - // if the player is null, we're in the menus - if (Minecraft::GetInstance()->player != nullptr) - { - app.SetAction(pMinecraft->player->GetXboxPad(), eAppAction_EthernetDisconnectedReturned); - } - else - { - // 4J-PB - turn off the PSN store icon just in case this happened when we were in one of the DLC menus -#if defined __ORBIS__ || defined __PSVITA__ - app.GetCommerce()->HidePsStoreIcon(); -#endif - app.SetAction(iPad,eAppAction_EthernetDisconnectedReturned_Menus); - } - return 0; -} - -int CMinecraftApp::SignoutExitWorldThreadProc( void* lpParameter ) -{ - - // Share AABB & Vec3 pools with default (main thread) - should be ok as long as we don't tick the main thread whilst this thread is running - AABB::UseDefaultThreadStorage(); - Vec3::UseDefaultThreadStorage(); - Compression::UseDefaultThreadStorage(); - - //app.SetGameStarted(false); - - Minecraft *pMinecraft=Minecraft::GetInstance(); - - int exitReasonStringId = -1; - - bool saveStats = false; - if (pMinecraft->isClientSide() || g_NetworkManager.IsInSession() ) - { - if(lpParameter != nullptr ) - { - switch( app.GetDisconnectReason() ) - { - case DisconnectPacket::eDisconnect_Kicked: - exitReasonStringId = IDS_DISCONNECTED_KICKED; - break; - case DisconnectPacket::eDisconnect_NoUGC_AllLocal: - exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL; - break; - case DisconnectPacket::eDisconnect_NoUGC_Single_Local: - exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL; - break; -#ifdef _XBOX - case DisconnectPacket::eDisconnect_NoUGC_Remote: - exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_REMOTE; - break; -#endif - case DisconnectPacket::eDisconnect_NoFlying: - exitReasonStringId = IDS_DISCONNECTED_FLYING; - break; - case DisconnectPacket::eDisconnect_OutdatedServer: - exitReasonStringId = IDS_DISCONNECTED_SERVER_OLD; - break; - case DisconnectPacket::eDisconnect_OutdatedClient: - exitReasonStringId = IDS_DISCONNECTED_CLIENT_OLD; - break; - default: - exitReasonStringId = IDS_DISCONNECTED; - } - pMinecraft->progressRenderer->progressStartNoAbort( exitReasonStringId ); - // 4J - Force a disconnection, this handles the situation that the server has already disconnected - if( pMinecraft->levels[0] != nullptr ) pMinecraft->levels[0]->disconnect(false); - if( pMinecraft->levels[1] != nullptr ) pMinecraft->levels[1]->disconnect(false); - } - else - { - exitReasonStringId = IDS_EXITING_GAME; - pMinecraft->progressRenderer->progressStartNoAbort( IDS_EXITING_GAME ); - - if( pMinecraft->levels[0] != nullptr ) pMinecraft->levels[0]->disconnect(); - if( pMinecraft->levels[1] != nullptr ) pMinecraft->levels[1]->disconnect(); - } - - // 4J Stu - This only does something if we actually have a server, so don't need to do any other checks - MinecraftServer::HaltServer(true); - - // We need to call the stats & leaderboards save before we exit the session - //pMinecraft->forceStatsSave(); - saveStats = false; - - // 4J Stu - Leave the session once the disconnect packet has been sent - g_NetworkManager.LeaveGame(FALSE); - } - else - { - if(lpParameter != nullptr ) - { - switch( app.GetDisconnectReason() ) - { - case DisconnectPacket::eDisconnect_Kicked: - exitReasonStringId = IDS_DISCONNECTED_KICKED; - break; - case DisconnectPacket::eDisconnect_NoUGC_AllLocal: - exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL; - break; - case DisconnectPacket::eDisconnect_NoUGC_Single_Local: - exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL; - break; -#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) - case DisconnectPacket::eDisconnect_ContentRestricted_AllLocal: - exitReasonStringId = IDS_CONTENT_RESTRICTION_MULTIPLAYER; - break; - case DisconnectPacket::eDisconnect_ContentRestricted_Single_Local: - exitReasonStringId = IDS_CONTENT_RESTRICTION; - break; -#endif -#ifdef _XBOX - case DisconnectPacket::eDisconnect_NoUGC_Remote: - exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_REMOTE; - break; -#endif - case DisconnectPacket::eDisconnect_OutdatedServer: - exitReasonStringId = IDS_DISCONNECTED_SERVER_OLD; - break; - case DisconnectPacket::eDisconnect_OutdatedClient: - exitReasonStringId = IDS_DISCONNECTED_CLIENT_OLD; - default: - exitReasonStringId = IDS_DISCONNECTED; - } - pMinecraft->progressRenderer->progressStartNoAbort( exitReasonStringId ); - } - } - pMinecraft->setLevel(nullptr,exitReasonStringId,nullptr,saveStats,true); - - // 4J-JEV: Fix for #106402 - TCR #014 BAS Debug Output: - // TU12: Mass Effect Mash-UP: Save file "Default_DisplayName" is created on all storage devices after signing out from a re-launched pre-generated world - app.m_gameRules.unloadCurrentGameRules(); // - - MinecraftServer::resetFlags(); - - // We can't start/join a new game until the session is destroyed, so wait for it to be idle again - while( g_NetworkManager.IsInSession() ) - { - Sleep(1); - } - - return S_OK; -} - -int CMinecraftApp::UnlockFullInviteReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) -{ - //CMinecraftApp* pApp = (CMinecraftApp*)pParam; - Minecraft *pMinecraft=Minecraft::GetInstance(); - bool bNoPlayer; - - // bug 11285 - TCR 001: BAS Game Stability: CRASH - When trying to join a full version game with a trial version, the trial crashes - // 4J-PB - we may be in the main menus here, and we don't have a pMinecraft->player - - if(pMinecraft->player==nullptr) - { - bNoPlayer=true; - } - - if(result==C4JStorage::EMessage_ResultAccept) - { - if(ProfileManager.IsSignedInLive(iPad)) - { - // 4J-PB - need to check this user can access the store -#if defined(__PS3__) || defined(__PSVITA__) - bool bContentRestricted; - ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,nullptr,&bContentRestricted,nullptr); - if(bContentRestricted) - { - UINT uiIDA[1]; - uiIDA[0]=IDS_CONFIRM_OK; - ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad()); - } - else -#endif - { - ProfileManager.DisplayFullVersionPurchase(false,iPad,eSen_UpsellID_Full_Version_Of_Game); - } - } -#if defined(__PS3__) - else - { - // you're not signed in to PSN! - UINT uiIDA[2]; - uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; - uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; - ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app); - - } -#endif - } - else - { - TelemetryManager->RecordUpsellResponded(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, eSen_UpsellOutcome_Declined); - } - - return 0; -} - -int CMinecraftApp::UnlockFullSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) -{ - //CMinecraftApp* pApp = (CMinecraftApp*)pParam; - Minecraft *pMinecraft=Minecraft::GetInstance(); - - if(result==C4JStorage::EMessage_ResultAccept) - { - if(ProfileManager.IsSignedInLive(pMinecraft->player->GetXboxPad())) - { - // 4J-PB - need to check this user can access the store -#if defined(__PS3__) || defined(__PSVITA__) - bool bContentRestricted; - ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,nullptr,&bContentRestricted,nullptr); - if(bContentRestricted) - { - UINT uiIDA[1]; - uiIDA[0]=IDS_CONFIRM_OK; - ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad()); - } - else -#endif - { - ProfileManager.DisplayFullVersionPurchase(false,pMinecraft->player->GetXboxPad(),eSen_UpsellID_Full_Version_Of_Game); - } - } -#if defined(__PS3__) - else - { - // you're not signed in to PSN! - UINT uiIDA[2]; - uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; - uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; - ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app); - } -#elif defined(__ORBIS__) - else - { - // Determine why they're not "signed in live" - if (ProfileManager.isSignedInPSN(iPad)) - { - // Signed in to PSN but not connected (no internet access) - assert(!ProfileManager.isConnectedToPSN(iPad)); - - UINT uiIDA[1]; - uiIDA[0] = IDS_OK; - ui.RequestErrorMessage( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad); - } - else - { - // Not signed in to PSN - UINT uiIDA[1]; - uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; - ui.RequestAlertMessage( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, iPad, &CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app); - } - } -#endif - } - else - { - TelemetryManager->RecordUpsellResponded(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, eSen_UpsellOutcome_Declined); - } - - return 0; -} - -int CMinecraftApp::UnlockFullExitReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) -{ - CMinecraftApp* pApp = static_cast(pParam); - Minecraft *pMinecraft=Minecraft::GetInstance(); - - if(result==C4JStorage::EMessage_ResultAccept) - { - if(ProfileManager.IsSignedInLive(pMinecraft->player->GetXboxPad())) - { - // 4J-PB - need to check this user can access the store -#if defined(__PS3__) || defined(__PSVITA__) - bool bContentRestricted; - ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,nullptr,&bContentRestricted,nullptr); - if(bContentRestricted) - { - UINT uiIDA[1]; - uiIDA[0]=IDS_CONFIRM_OK; - ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad()); - } - else -#endif - { - ProfileManager.DisplayFullVersionPurchase(false,pMinecraft->player->GetXboxPad(),eSen_UpsellID_Full_Version_Of_Game); -#if defined __ORBIS__ || defined __PS3__ || defined __PSVITA__ - // still need to exit the trial or we'll be in the Pause menu with input ignored - pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial); -#endif - } - } -#if defined(__PS3__) || defined __PSVITA__ - else - { - // you're not signed in to PSN! - UINT uiIDA[2]; - uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; - uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; - ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturnedExitTrial,&app); - } -#elif defined(__ORBIS__) - else - { - // Determine why they're not "signed in live" - if (ProfileManager.isSignedInPSN(iPad)) - { - // Signed in to PSN but not connected (no internet access) - assert(!ProfileManager.isConnectedToPSN(iPad)); - - UINT uiIDA[1]; - uiIDA[0] = IDS_OK; - ui.RequestErrorMessage( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad); - // still need to exit the trial or we'll be in the Pause menu with input ignored - pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial); - } - else - { - // Not signed in to PSN - UINT uiIDA[1]; - uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; - ui.RequestAlertMessage( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, iPad, &CMinecraftApp::MustSignInFullVersionPurchaseReturnedExitTrial,&app); - } - } -#endif - } - else - { - TelemetryManager->RecordUpsellResponded(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, eSen_UpsellOutcome_Declined); - pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial); - } - - return 0; -} - -int CMinecraftApp::TrialOverReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) -{ - CMinecraftApp* pApp = static_cast(pParam); - Minecraft *pMinecraft=Minecraft::GetInstance(); - - if(result==C4JStorage::EMessage_ResultAccept) - { - // we need a signed in user for the unlock - if(ProfileManager.IsSignedInLive(pMinecraft->player->GetXboxPad())) - { - // 4J-PB - need to check this user can access the store -#if defined(__PS3__) || defined(__PSVITA__) - bool bContentRestricted; - ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,nullptr,&bContentRestricted,nullptr); - if(bContentRestricted) - { - UINT uiIDA[1]; - uiIDA[0]=IDS_CONFIRM_OK; - ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad()); - } - else -#endif - { - ProfileManager.DisplayFullVersionPurchase(false,pMinecraft->player->GetXboxPad(),eSen_UpsellID_Full_Version_Of_Game); - } - } - else - { -#if defined(__PS3__) - - // you're not signed in to PSN! - UINT uiIDA[2]; - uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; - uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; - ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app); - - // 4J Stu - We can't actually exit the game, so just exit back to the main menu - //pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial); -#else - pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitTrial); -#endif - } - } - else - { - TelemetryManager->RecordUpsellResponded(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, eSen_UpsellOutcome_Declined); - -#if defined(__PS3__) || defined(__ORBIS__) - // 4J Stu - We can't actually exit the game, so just exit back to the main menu - pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial); -#else - pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitTrial); -#endif - } - - return 0; -} - -void CMinecraftApp::ProfileReadErrorCallback(void *pParam) -{ - CMinecraftApp *pApp=static_cast(pParam); - int iPrimaryPlayer=ProfileManager.GetPrimaryPad(); - pApp->SetAction(iPrimaryPlayer, eAppAction_ProfileReadError); -} - -void CMinecraftApp::ClearSignInChangeUsersMask() -{ - // 4J-PB - When in the main menu, the user is on pad 0, and any change they make to their profile will be to pad 0 data - // If they then go in as a secondary player to a splitscreen game, their profile will not be read again on pad 1 if they were previously in a splitscreen game - // This is because m_uiLastSignInData remembers they were in previously, and doesn't read the profile data for them again - // Fix this by resetting the m_uiLastSignInData on pressing play game for secondary users. The Primary user does a read profile on play game anyway - int iPrimaryPlayer=ProfileManager.GetPrimaryPad(); - - if(m_uiLastSignInData!=0) - { - if(iPrimaryPlayer>=0) - { - m_uiLastSignInData=1<user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); -#endif - - CMinecraftApp *pApp=static_cast(pParam); - // check if the primary player signed out - int iPrimaryPlayer=ProfileManager.GetPrimaryPad(); - - if((ProfileManager.GetLockedProfile()!=-1) && iPrimaryPlayer!=-1) - { - if ( ((uiSignInData & (1<SetAction(iPrimaryPlayer,eAppAction_PrimaryPlayerSignedOut); - - // 4J-PB - invalidate their banned level list - pApp->InvalidateBannedList(iPrimaryPlayer); - - // need to ditch any DLCOffers info - StorageManager.ClearDLCOffers(); - pApp->ClearAndResetDLCDownloadQueue(); - pApp->ClearDLCInstalled(); - } - else - { - unsigned int uiChangedPlayers = uiSignInData ^ m_uiLastSignInData; - - if( g_NetworkManager.IsInSession() ) - { - bool hasGuestIdChanged = false; - for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) - { - DWORD guestNumber = 0; - if(ProfileManager.IsSignedIn(i)) - { - XUSER_SIGNIN_INFO info; - XUserGetSigninInfo(i,XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY ,&info); - pApp->DebugPrintf("Player at index %d has guest number %d\n", i,info.dwGuestNumber ); - guestNumber = info.dwGuestNumber; - } - if( pApp->m_currentSigninInfo[i].dwGuestNumber != 0 && guestNumber != 0 && pApp->m_currentSigninInfo[i].dwGuestNumber != guestNumber ) - { - hasGuestIdChanged = true; - } - } - - if( hasGuestIdChanged ) - { - UINT uiIDA[1]; - uiIDA[0]=IDS_CONFIRM_OK; - ui.RequestErrorMessage(IDS_GUEST_ORDER_CHANGED_TITLE, IDS_GUEST_ORDER_CHANGED_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad()); - } - - // 4J Stu - On PS4 we can also cause to exit players if they are signed out here, but we shouldn't do that if - // we are going to switch to an offline game as it will likely crash due to incompatible parallel processes - bool switchToOffline = false; - // If it's an online game, and the primary profile is no longer signed into LIVE then we act as if disconnected - if( !ProfileManager.IsSignedInLive( ProfileManager.GetLockedProfile() ) && !g_NetworkManager.IsLocalGame() ) - { - switchToOffline = true; - } - - //printf("Old: %x, New: %x, Changed: %x\n", m_ulLastSignInData, ulSignInData, changedPlayers); - for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) - { - // Primary player shouldn't be subjected to these checks, and shouldn't call ExitPlayer - if(i == iPrimaryPlayer) continue; - - // A guest a signed in or out, out of order which invalidates all the guest players we have in the game - if(hasGuestIdChanged && pApp->m_currentSigninInfo[i].dwGuestNumber != 0 && g_NetworkManager.GetLocalPlayerByUserIndex(i)!=nullptr) - { - pApp->DebugPrintf("Recommending removal of player at index %d because their guest id changed\n",i); - pApp->SetAction(i, eAppAction_ExitPlayer); - } - else - { - XUSER_SIGNIN_INFO info; - XUserGetSigninInfo(i,XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY ,&info); - // 4J Stu - Also need to detect the case where the sign in mask is the same, but the player has swapped users (eg still signed in but xuid different) - // Fix for #48451 - TU5: Code: UI: Splitscreen: Title crashes when switching to a profile previously signed out via splitscreen profile selection - - // 4J-PB - compiler complained about if below ('&&' within '||') - making it easier to read - bool bPlayerChanged=(uiChangedPlayers&(1<m_currentSigninInfo[i].xuid, info.xuid) ) )) - { - // 4J-PB - invalidate their banned level list - pApp->DebugPrintf("Player at index %d Left - invalidating their banned list\n",i); - pApp->InvalidateBannedList(i); - - // 4J-HG: If either the player is in the network manager or in the game, need to exit player - // TODO: Do we need to check the network manager? - if (g_NetworkManager.GetLocalPlayerByUserIndex(i) != nullptr || Minecraft::GetInstance()->localplayers[i] != nullptr) - { - pApp->DebugPrintf("Player %d signed out\n", i); - pApp->SetAction(i, eAppAction_ExitPlayer); - } - } - } -#ifdef __ORBIS__ - // check if any of the addition players have signed out of PSN (primary player is handled below) - if(!switchToOffline && i != ProfileManager.GetLockedProfile() && !g_NetworkManager.IsLocalGame()) - { - if(g_NetworkManager.GetLocalPlayerByUserIndex(i)!=nullptr) - { - if(ProfileManager.IsSignedInLive(i) == false) - { - pApp->DebugPrintf("Recommending removal of player at index %d because they're no longer signed into PSNd\n",i); - pApp->SetAction(i,eAppAction_ExitPlayer); - } - } - } -#endif - } - - // If it's an online game, and the primary profile is no longer signed into LIVE then we act as if disconnected - if( switchToOffline ) - { - pApp->SetAction(iPrimaryPlayer,eAppAction_EthernetDisconnected); - } - - - g_NetworkManager.HandleSignInChange(); - } - // Some menus require the player to be signed in to live, so if this callback happens and the primary player is - // no longer signed in then nav back - else if ( pApp->GetLiveLinkRequired() && !ProfileManager.IsSignedInLive( ProfileManager.GetLockedProfile() ) ) - { -#ifdef __PSVITA__ - if(!CGameNetworkManager::usingAdhocMode()) // if we're in adhoc mode, we can ignore this -#endif - { - pApp->SetAction(iPrimaryPlayer,eAppAction_EthernetDisconnected); - } - } - -#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__ ) - // 4J-JEV: Need to kick of loading of profile data for sub-sign in players. - for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) - { - if( i != iPrimaryPlayer - && ( uiChangedPlayers & (1<InvalidateBannedList(iPrimaryPlayer); - - // need to ditch any DLCOffers info - StorageManager.ClearDLCOffers(); - pApp->ClearAndResetDLCDownloadQueue(); - pApp->ClearDLCInstalled(); - - } - - // Update the guest numbers to the current state - for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) - { - if(FAILED(XUserGetSigninInfo(i,XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY,&pApp->m_currentSigninInfo[i]))) - { - pApp->m_currentSigninInfo[i].xuid = INVALID_XUID; - pApp->m_currentSigninInfo[i].dwGuestNumber = 0; - } - app.DebugPrintf("Player at index %d has guest number %d\n", i,pApp->m_currentSigninInfo[i].dwGuestNumber ); - } -} - -void CMinecraftApp::NotificationsCallback(LPVOID pParam,DWORD dwNotification, unsigned int uiParam) -{ - CMinecraftApp* pClass = static_cast(pParam); - - // push these on to the notifications to be handled in qnet's dowork - - PNOTIFICATION pNotification = new NOTIFICATION; - - pNotification->dwNotification=dwNotification; - pNotification->uiParam=uiParam; - - switch( dwNotification ) - { - case XN_SYS_SIGNINCHANGED: - { - pClass->DebugPrintf("Signing changed - %d\n", uiParam ); - } - break; - case XN_SYS_INPUTDEVICESCHANGED: - if(app.GetGameStarted() && g_NetworkManager.IsInSession()) - { - for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) - { - if(!InputManager.IsPadConnected(i) && - Minecraft::GetInstance()->localplayers[i] != nullptr && - !ui.IsPauseMenuDisplayed(i) && !ui.IsSceneInStack(i, eUIScene_EndPoem) ) - { - ui.CloseUIScenes(i); - ui.NavigateToScene(i,eUIScene_PauseMenu); - } - } - } - break; - case XN_LIVE_CONTENT_INSTALLED: - // Need to inform xuis that we've possibly had DLC installed - { - //app.m_dlcManager.SetNeedsUpdated(true); - // Clear the DLC installed flag to cause a GetDLC to run if it's called - app.ClearDLCInstalled(); - - ui.HandleDLCInstalled(ProfileManager.GetPrimaryPad()); - } - break; - case XN_SYS_STORAGEDEVICESCHANGED: - { -#ifdef _XBOX - // If the devices have changed, and we've got a dlc pack with audio selected, and that pack's content device is no longer valid... then pull the plug on - // audio streaming, as if we leave this until later xact gets locked up attempting to destroy the streamed wave bank. - TexturePack *pTexPack=Minecraft::GetInstance()->skins->getSelected(); - if(pTexPack->hasAudio()) - { - DLCTexturePack *pDLCTexPack=(DLCTexturePack *)pTexPack; - XCONTENTDEVICEID deviceID = pDLCTexPack->GetDLCDeviceID(); - if( XContentGetDeviceState( deviceID, nullptr ) != ERROR_SUCCESS ) - { - // Set texture pack flag so that it is now considered as not having audio - this is critical so that the next playStreaming does what it is meant to do, - // and also so that we don't try and unmount this again, or play any sounds from it in the future - pTexPack->setHasAudio(false); - // need to stop the streaming audio - by playing streaming audio from the default texture pack now - Minecraft::GetInstance()->soundEngine->playStreaming(L"", 0, 0, 0, 0, 0); - - if(pDLCTexPack->m_pStreamedWaveBank!=nullptr) - { - pDLCTexPack->m_pStreamedWaveBank->Destroy(); - } - if(pDLCTexPack->m_pSoundBank!=nullptr) - { - pDLCTexPack->m_pSoundBank->Destroy(); - } - DWORD result = StorageManager.UnmountInstalledDLC("TPACK"); - app.DebugPrintf("Unmount result is %d\n",result); - } - } -#endif - } - break; - } - - pClass->m_vNotifications.push_back(pNotification); -} - -#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__ -int CMinecraftApp::MustSignInFullVersionPurchaseReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) -{ - if(result==C4JStorage::EMessage_ResultAccept) - { -#ifdef __PS3__ - SQRNetworkManager_PS3::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true); -#elif defined __PSVITA__ - SQRNetworkManager_Vita::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true); -#else // __PS4__ - SQRNetworkManager_Orbis::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true); -#endif - } - - return 0; -} - -#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__ -int CMinecraftApp::MustSignInFullVersionPurchaseReturnedExitTrial(void *pParam,int iPad,C4JStorage::EMessageResult result) -{ - if(result==C4JStorage::EMessage_ResultAccept) - { -#ifdef __PS3__ - SQRNetworkManager_PS3::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true); -#elif defined __PSVITA__ - SQRNetworkManager_Vita::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true); -#else // __PS4__ - SQRNetworkManager_Orbis::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true); -#endif - } - - //4J-PB - we need to exit the trial, or we'll be in the pause menu with ignore input true - app.SetAction(iPad,eAppAction_ExitWorldTrial); - - return 0; -} -#endif - -int CMinecraftApp::NowDisplayFullVersionPurchase(void *pParam, bool bContinue, int iPad) -{ - app.m_bDisplayFullVersionPurchase=true; - return 0; -} -#endif -void CMinecraftApp::UpsellReturnedCallback(LPVOID pParam, eUpsellType type, eUpsellResponse result, int iUserData) -{ - ESen_UpsellID senType; - ESen_UpsellOutcome senResponse; -#ifdef __PS3__ - UINT uiIDA[2]; -#endif - - // Map the eUpsellResponse to the enum we use for sentient - switch(result) - { - case eUpsellResponse_Accepted_NoPurchase: - senResponse = eSen_UpsellOutcome_Went_To_Guide; - break; - case eUpsellResponse_Accepted_Purchase: - senResponse = eSen_UpsellOutcome_Accepted; - break; -#ifdef __PS3__ - // special case for people who are not signed in to the PSN while playing the trial game - case eUpsellResponse_UserNotSignedInPSN: - - uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; - uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; - ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app); - - return; - - case eUpsellResponse_NotAllowedOnline: // On earning a trophy in the trial version, where the user is underage and can't go online to buy the game, but they selected to buy the game on the trophy upsell - uiIDA[0]=IDS_CONFIRM_OK; - ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad()); - break; -#endif - case eUpsellResponse_Declined: - default: - senResponse = eSen_UpsellOutcome_Declined; - break; - }; - - // Map the eUpsellType to the enum we use for sentient - switch(type) - { - case eUpsellType_Custom: - senType = eSen_UpsellID_Full_Version_Of_Game; - break; - default: - senType = eSen_UpsellID_Undefined; - break; - }; - - // Always the primary pad that gets an upsell - TelemetryManager->RecordUpsellResponded(ProfileManager.GetPrimaryPad(), eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, senResponse); -} - -#ifdef _DEBUG_MENUS_ENABLED -bool CMinecraftApp::DebugArtToolsOn() -{ - return DebugSettingsOn() && (GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<(pParam); - //printf("sequence matched\n"); - pClass->m_bDebugOptions=!pClass->m_bDebugOptions; - - for(int i=0;ilocalplayers[i] != nullptr) - { - iPlayerC++; - } - } - - return iPlayerC; -} - -int CMinecraftApp::MarketplaceCountsCallback(LPVOID pParam,C4JStorage::DLC_TMS_DETAILS *pTMSDetails, int iPad) -{ - app.DebugPrintf("Marketplace Counts= New - %d Total - %d\n",pTMSDetails->dwNewOffers,pTMSDetails->dwTotalOffers); - - if(pTMSDetails->dwNewOffers>0) - { - app.m_bNewDLCAvailable=true; - app.m_bSeenNewDLCTip=false; - } - else - { - app.m_bNewDLCAvailable=false; - app.m_bSeenNewDLCTip=true; - } - - return 0; -} - -bool CMinecraftApp::StartInstallDLCProcess(int iPad) -{ - app.DebugPrintf("--- CMinecraftApp::StartInstallDLCProcess: pad=%i.\n", iPad); - - // If there is already a call to this in progress, then do nothing - // If the app says dlc is installed, then there has been no new system message to tell us there's new DLC since the last call to StartInstallDLCProcess - if((app.DLCInstallProcessCompleted()==false) && (m_bDLCInstallPending==false)) - { - app.m_dlcManager.resetUnnamedCorruptCount(); - m_bDLCInstallPending = true; - m_iTotalDLC = 0; - m_iTotalDLCInstalled = 0; - app.DebugPrintf("--- CMinecraftApp::StartInstallDLCProcess - StorageManager.GetInstalledDLC\n"); - - StorageManager.GetInstalledDLC(iPad,&CMinecraftApp::DLCInstalledCallback,this); - return true; - } - else - { - app.DebugPrintf("--- CMinecraftApp::StartInstallDLCProcess - nothing to do\n"); - - return false; - } - -} - -// Installed DLC callback -int CMinecraftApp::DLCInstalledCallback(LPVOID pParam,int iInstalledC,int iPad) -{ - app.DebugPrintf("--- CMinecraftApp::DLCInstalledCallback: totalDLC=%i, pad=%i.\n", iInstalledC, iPad); - app.m_iTotalDLC = iInstalledC; - app.MountNextDLC(iPad); - return 0; -} - -void CMinecraftApp::MountNextDLC(int iPad) -{ - app.DebugPrintf("--- CMinecraftApp::MountNextDLC: pad=%i.\n", iPad); - if(m_iTotalDLCInstalled < m_iTotalDLC) - { - // Mount it - // We also need to match the ones the user wants to mount with the installed DLC - // We're supposed to use a generic save game as a cache of these to do this, with XUSER_ANY - - if(StorageManager.MountInstalledDLC(iPad,m_iTotalDLCInstalled,&CMinecraftApp::DLCMountedCallback,this)!=ERROR_IO_PENDING ) - { - // corrupt DLC - app.DebugPrintf("Failed to mount DLC %d for pad %d\n",m_iTotalDLCInstalled,iPad); - ++m_iTotalDLCInstalled; - app.MountNextDLC(iPad); - } - else - { - app.DebugPrintf("StorageManager.MountInstalledDLC ok\n"); - } - } - else - { - /* Removed - now loading these on demand instead of as each pack is mounted - if(m_iTotalDLCInstalled > 0) - { - Minecraft *pMinecraft=Minecraft::GetInstance(); - pMinecraft->levelRenderer->AddDLCSkinsToMemTextures(); - } - */ - - m_bDLCInstallPending = false; - m_bDLCInstallProcessCompleted=true; - - ui.HandleDLCMountingComplete(); - -#if defined(_XBOX_ONE) || defined(__ORBIS__) - // Check if the current texture pack is now installed - if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) - { - TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); - DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; - - DLCPack *pParentPack=pDLCTexPack->getDLCInfoParentPack();//tPack->getDLCPack(); - - if(pParentPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" )) - { - StorageManager.SetSaveDisabled(false); - } - } -#endif -#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ - { - TexturePack* currentTPack = Minecraft::GetInstance()->skins->getSelected(); - TexturePack* requiredTPack = Minecraft::GetInstance()->skins->getTexturePackById(app.GetRequiredTexturePackID()); - if(currentTPack != requiredTPack) - { - Minecraft::GetInstance()->skins->selectTexturePackById(app.GetRequiredTexturePackID()); - } - } -#endif - } -} - -// 4J-JEV: For the sake of clarity in DLCMountedCallback. -#if defined(_XBOX) || defined(__PS3__) || defined(_WINDOWS64) -#define CONTENT_DATA_DISPLAY_NAME(a) (a.szDisplayName) -#else -#define CONTENT_DATA_DISPLAY_NAME(a) (a.wszDisplayName) -#endif - -int CMinecraftApp::DLCMountedCallback(LPVOID pParam,int iPad,DWORD dwErr,DWORD dwLicenceMask) -{ -#if defined(_XBOX) || defined(_DURANGO) || defined(__PS3__) || defined(__ORBIS__) || defined(_WINDOWS64) || defined (__PSVITA__) //Chris TODO - app.DebugPrintf("--- CMinecraftApp::DLCMountedCallback\n"); - - if(dwErr!=ERROR_SUCCESS) - { - // corrupt DLC - app.DebugPrintf("Failed to mount DLC for pad %d: %d\n",iPad,dwErr); - app.m_dlcManager.incrementUnnamedCorruptCount(); - } - else - { - XCONTENT_DATA ContentData = StorageManager.GetDLC(app.m_iTotalDLCInstalled); - - DLCPack *pack = app.m_dlcManager.getPack( CONTENT_DATA_DISPLAY_NAME(ContentData) ); - - if( pack != nullptr && pack->IsCorrupt() ) - { - app.DebugPrintf("Pack '%ls' is corrupt, removing it from the DLC Manager.\n", CONTENT_DATA_DISPLAY_NAME(ContentData)); - - app.m_dlcManager.removePack(pack); - pack = nullptr; - } - - if(pack == nullptr) - { - app.DebugPrintf("Pack \"%ls\" is not installed, so adding it\n", CONTENT_DATA_DISPLAY_NAME(ContentData)); - -#if defined(_XBOX) || defined(__PS3__) || defined(_WINDOWS64) - pack = new DLCPack(ContentData.szDisplayName,dwLicenceMask); -#elif defined _XBOX_ONE - pack = new DLCPack(ContentData.wszDisplayName,ContentData.wszProductID,dwLicenceMask); -#else - pack = new DLCPack(ContentData.wszDisplayName,dwLicenceMask); -#endif - pack->SetDLCMountIndex(app.m_iTotalDLCInstalled); - pack->SetDLCDeviceID(ContentData.DeviceID); - app.m_dlcManager.addPack(pack); - - app.HandleDLC(pack); - - if(pack->getDLCItemsCount(DLCManager::e_DLCType_Texture) > 0) - { - Minecraft::GetInstance()->skins->addTexturePackFromDLC(pack, pack->GetPackId() ); - } - } - else - { - app.DebugPrintf("Pack \"%ls\" is already installed. Updating license to %d\n", CONTENT_DATA_DISPLAY_NAME(ContentData), dwLicenceMask); - - pack->SetDLCMountIndex(app.m_iTotalDLCInstalled); - pack->SetDLCDeviceID(ContentData.DeviceID); - pack->updateLicenseMask(dwLicenceMask); - } - - StorageManager.UnmountInstalledDLC(); - } - ++app.m_iTotalDLCInstalled; - app.MountNextDLC(iPad); - -#endif // __PSVITA__ - return 0; -} -#undef CONTENT_DATA_DISPLAY_NAME - -// void CMinecraftApp::InstallDefaultCape() -// { -// if(!m_bDefaultCapeInstallAttempted) -// { -// // we only attempt to install the cape once per launch of the game -// m_bDefaultCapeInstallAttempted=true; -// -// wstring wTemp=L"Default_Cape.png"; -// bool bRes=app.IsFileInMemoryTextures(wTemp); -// // if the file is not already in the memory textures, then read it from TMS -// if(!bRes) -// { -// BYTE* pBuffer = nullptr; -// DWORD dwSize=0; -// // 4J-PB - out for now for DaveK so he doesn't get the birthday cape -// #ifdef _CONTENT_PACKAGE -// C4JStorage::ETMSStatus eTMSStatus; -// eTMSStatus=StorageManager.ReadTMSFile(ProfileManager.GetPrimaryPad(),C4JStorage::eGlobalStorage_Title,C4JStorage::eTMS_FileType_Graphic, L"Default_Cape.png",&pBuffer, &dwSize); -// if(eTMSStatus==C4JStorage::ETMSStatus_Idle) -// { -// app.AddMemoryTextureFile(wTemp,pBuffer,dwSize); -// } -// #endif -// } -// } -// } - -void CMinecraftApp::HandleDLC(DLCPack *pack) -{ - DWORD dwFilesProcessed = 0; -#ifndef _XBOX -#if defined(__PS3__) || defined(__ORBIS__) || defined(_WINDOWS64) || defined (__PSVITA__) - std::vector dlcFilenames; -#elif defined _DURANGO - std::vector dlcFilenames; -#endif - StorageManager.GetMountedDLCFileList("DLCDrive", dlcFilenames); -#ifdef __ORBIS__ - // 4J Stu - I don't know why we handle more than one file here any more, however this doesn't seem to work with the PS4 patches - if(dlcFilenames.size() > 0) m_dlcManager.readDLCDataFile(dwFilesProcessed, dlcFilenames[0], pack); -#else - for(size_t i=0; i(qwTicksPerSec.QuadPart); - - // Save the start time - QueryPerformanceCounter( &m_Time.qwTime ); - - // Zero out the elapsed and total time - m_Time.qwAppTime.QuadPart = 0; - m_Time.fAppTime = 0.0f; - m_Time.fElapsedTime = 0.0f; -} - -//------------------------------------------------------------------------------------- -// Name: UpdateTime() -// Desc: Updates the elapsed time since our last frame. -//------------------------------------------------------------------------------------- -void CMinecraftApp::UpdateTime() -{ - LARGE_INTEGER qwNewTime; - LARGE_INTEGER qwDeltaTime; - - QueryPerformanceCounter( &qwNewTime ); - qwDeltaTime.QuadPart = qwNewTime.QuadPart - m_Time.qwTime.QuadPart; - - m_Time.qwAppTime.QuadPart += qwDeltaTime.QuadPart; - m_Time.qwTime.QuadPart = qwNewTime.QuadPart; - - m_Time.fElapsedTime = m_Time.fSecsPerTick * static_cast(qwDeltaTime.QuadPart); - m_Time.fAppTime = m_Time.fSecsPerTick * static_cast(m_Time.qwAppTime.QuadPart); -} - -bool CMinecraftApp::isXuidNotch(PlayerUID xuid) -{ - if(m_xuidNotch != INVALID_XUID && xuid != INVALID_XUID) - { - return ProfileManager.AreXUIDSEqual(xuid, m_xuidNotch) == TRUE; - } - return false; -} - -bool CMinecraftApp::isXuidDeadmau5(PlayerUID xuid) -{ - auto it = MojangData.find(xuid); // 4J Stu - The .at and [] accessors insert elements if they don't exist - if (it != MojangData.end() ) - { - MOJANG_DATA *pMojangData=MojangData[xuid]; - if(pMojangData && pMojangData->eXuid==eXUID_Deadmau5) - { - return true; - } - } - - return false; -} - -void CMinecraftApp::AddMemoryTextureFile(const wstring &wName,PBYTE pbData,DWORD dwBytes) -{ - EnterCriticalSection(&csMemFilesLock); - // check it's not already in - PMEMDATA pData=nullptr; - auto it = m_MEM_Files.find(wName); - if(it != m_MEM_Files.end()) - { -#ifndef _CONTENT_PACKAGE - wprintf(L"Incrementing the memory texture file count for %ls\n", wName.c_str()); -#endif - pData = (*it).second; - - if(pData->dwBytes == 0 && dwBytes != 0) - { - // This should never be nullptr if dwBytes is 0 - if(pData->pbData!=nullptr) delete [] pData->pbData; - - pData->pbData=pbData; - pData->dwBytes=dwBytes; - } - - ++pData->ucRefCount; - LeaveCriticalSection(&csMemFilesLock); - return; - } - -#ifndef _CONTENT_PACKAGE - //wprintf(L"Adding the memory texture file data for %ls\n", wName.c_str()); -#endif - // this is a texture (png) file - - // add this texture to the list of memory texture files - it will then be picked up by the level renderer's AddEntity - - pData = (PMEMDATA)new BYTE[sizeof(MEMDATA)]; - ZeroMemory( pData, sizeof(MEMDATA) ); - pData->pbData=pbData; - pData->dwBytes=dwBytes; - pData->ucRefCount = 1; - - // use the xuid to access the skin data - m_MEM_Files[wName]=pData; - - LeaveCriticalSection(&csMemFilesLock); -} - -void CMinecraftApp::RemoveMemoryTextureFile(const wstring &wName) -{ - EnterCriticalSection(&csMemFilesLock); - - auto it = m_MEM_Files.find(wName); - if(it != m_MEM_Files.end()) - { -#ifndef _CONTENT_PACKAGE - wprintf(L"Decrementing the memory texture file count for %ls\n", wName.c_str()); -#endif - PMEMDATA pData = (*it).second; - --pData->ucRefCount; - if(pData->ucRefCount <= 0) - { -#ifndef _CONTENT_PACKAGE - wprintf(L"Erasing the memory texture file data for %ls\n", wName.c_str()); -#endif - delete [] pData; - m_MEM_Files.erase(wName); - } - } - LeaveCriticalSection(&csMemFilesLock); -} - -bool CMinecraftApp::DefaultCapeExists() -{ - wstring wTex=L"Special_Cape.png"; - bool val = false; - - EnterCriticalSection(&csMemFilesLock); - auto it = m_MEM_Files.find(wTex); - if(it != m_MEM_Files.end()) val = true; - LeaveCriticalSection(&csMemFilesLock); - - return val; -} - -bool CMinecraftApp::IsFileInMemoryTextures(const wstring &wName) -{ - bool val = false; - - EnterCriticalSection(&csMemFilesLock); - auto it = m_MEM_Files.find(wName); - if(it != m_MEM_Files.end()) val = true; - LeaveCriticalSection(&csMemFilesLock); - - return val; -} - -void CMinecraftApp::GetMemFileDetails(const wstring &wName,PBYTE *ppbData,DWORD *pdwBytes) -{ - EnterCriticalSection(&csMemFilesLock); - auto it = m_MEM_Files.find(wName); - if(it != m_MEM_Files.end()) - { - PMEMDATA pData = (*it).second; - *ppbData=pData->pbData; - *pdwBytes=pData->dwBytes; - } - LeaveCriticalSection(&csMemFilesLock); -} - -void CMinecraftApp::AddMemoryTPDFile(int iConfig,PBYTE pbData,DWORD dwBytes) -{ - EnterCriticalSection(&csMemTPDLock); - // check it's not already in - PMEMDATA pData=nullptr; - auto it = m_MEM_TPD.find(iConfig); - if(it == m_MEM_TPD.end()) - { - pData = (PMEMDATA)new BYTE[sizeof(MEMDATA)]; - ZeroMemory( pData, sizeof(MEMDATA) ); - pData->pbData=pbData; - pData->dwBytes=dwBytes; - pData->ucRefCount = 1; - - m_MEM_TPD[iConfig]=pData; - } - - LeaveCriticalSection(&csMemTPDLock); -} - -void CMinecraftApp::RemoveMemoryTPDFile(int iConfig) -{ - EnterCriticalSection(&csMemTPDLock); - // check it's not already in - PMEMDATA pData=nullptr; - auto it = m_MEM_TPD.find(iConfig); - if(it != m_MEM_TPD.end()) - { - pData=m_MEM_TPD[iConfig]; - delete [] pData; - m_MEM_TPD.erase(iConfig); - } - - LeaveCriticalSection(&csMemTPDLock); -} - -#ifdef _XBOX -int CMinecraftApp::GetTPConfigVal(WCHAR *pwchDataFile) -{ - DLC_INFO *pDLCInfo=nullptr; - // run through the DLC info to find the right texture pack/mash-up pack - for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i) - { - ULONGLONG ull=app.GetDLCInfoTexturesFullOffer(i); - pDLCInfo=app.GetDLCInfoForFullOfferID(ull); - - if(wcscmp(pwchDataFile,pDLCInfo->wchDataFile)==0) - { - return pDLCInfo->iConfig; - } - } - - return -1; -} -#elif defined _XBOX_ONE -int CMinecraftApp::GetTPConfigVal(WCHAR *pwchDataFile) -{ - DLC_INFO *pDLCInfo=nullptr; - // run through the DLC info to find the right texture pack/mash-up pack - for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i) - { - pDLCInfo=app.GetDLCInfoForFullOfferID((WCHAR *)app.GetDLCInfoTexturesFullOffer(i).c_str()); - - if(wcscmp(pwchDataFile,pDLCInfo->wchDataFile)==0) - { - return pDLCInfo->iConfig; - } - } - - return -1; -} -#elif defined _WINDOWS64 -int CMinecraftApp::GetTPConfigVal(WCHAR *pwchDataFile) -{ - return -1; -} -#endif -bool CMinecraftApp::IsFileInTPD(int iConfig) -{ - bool val = false; - - EnterCriticalSection(&csMemTPDLock); - auto it = m_MEM_TPD.find(iConfig); - if(it != m_MEM_TPD.end()) val = true; - LeaveCriticalSection(&csMemTPDLock); - - return val; -} - -void CMinecraftApp::GetTPD(int iConfig,PBYTE *ppbData,DWORD *pdwBytes) -{ - EnterCriticalSection(&csMemTPDLock); - auto it = m_MEM_TPD.find(iConfig); - if(it != m_MEM_TPD.end()) - { - PMEMDATA pData = (*it).second; - *ppbData=pData->pbData; - *pdwBytes=pData->dwBytes; - } - LeaveCriticalSection(&csMemTPDLock); -} - - -// bool CMinecraftApp::UploadFileToGlobalStorage(int iQuadrant, C4JStorage::eGlobalStorage eStorageFacility, wstring *wsFile ) -// { -// bool bRes=false; -// #ifndef _CONTENT_PACKAGE -// // read the local file -// File gtsFile( wsFile->c_str() ); -// -// int64_t fileSize = gtsFile.length(); -// -// if(fileSize!=0) -// { -// FileInputStream fis(gtsFile); -// byteArray ba((int)fileSize); -// fis.read(ba); -// fis.close(); -// -// bRes=StorageManager.WriteTMSFile(iQuadrant,eStorageFacility,(WCHAR *)wsFile->c_str(),ba.data, ba.length); -// -// } -// #endif -// return bRes; -// } - - - - - - -void CMinecraftApp::StoreLaunchData() -{ - -} - -void CMinecraftApp::ExitGame() -{ -} - -// Invites - -void CMinecraftApp::ProcessInvite(DWORD dwUserIndex, DWORD dwLocalUsersMask, const INVITE_INFO * pInviteInfo) -{ - m_InviteData.dwUserIndex=dwUserIndex; - m_InviteData.dwLocalUsersMask=dwLocalUsersMask; - m_InviteData.pInviteInfo=pInviteInfo; - //memcpy(&m_InviteData,pJoinData,sizeof(JoinFromInviteData)); - SetAction(dwUserIndex,eAppAction_ExitAndJoinFromInvite); -} - -int CMinecraftApp::ExitAndJoinFromInvite(void *pParam,int iPad,C4JStorage::EMessageResult result) -{ - CMinecraftApp* pApp = static_cast(pParam); - //Minecraft *pMinecraft=Minecraft::GetInstance(); - - // buttons are swapped on this menu - if(result==C4JStorage::EMessage_ResultDecline) - { - pApp->SetAction(iPad,eAppAction_ExitAndJoinFromInviteConfirmed); - } - - return 0; -} - -int CMinecraftApp::ExitAndJoinFromInviteSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) -{ - CMinecraftApp *pClass = static_cast(pParam); - // Exit with or without saving - // Decline means save in this dialog - if(result==C4JStorage::EMessage_ResultDecline || result==C4JStorage::EMessage_ResultThirdOption) - { - if( result==C4JStorage::EMessage_ResultDecline ) // Save - { - // Check they have the full texture pack if they are using one - // 4J-PB - Is the player trying to save but they are using a trial texturepack ? - if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) - { - TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); - - DLCPack * pDLCPack=tPack->getDLCPack(); - if(!pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" )) - { - // upsell - // get the dlc texture pack - -#ifdef _XBOX - DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; - ULONGLONG ullOfferID_Full; - app.GetDLCFullOfferIDForPackID(pDLCTexPack->getDLCParentPackId(),&ullOfferID_Full); - - // tell sentient about the upsell of the full version of the skin pack - TelemetryManager->RecordUpsellPresented(iPad, eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF); -#endif - - UINT uiIDA[2]; - uiIDA[0]=IDS_CONFIRM_OK; - uiIDA[1]=IDS_CONFIRM_CANCEL; - - // Give the player a warning about the trial version of the texture pack - ui.RequestErrorMessage(IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, IDS_WARNING_DLC_TRIALTEXTUREPACK_TEXT, uiIDA, 2, iPad,&CMinecraftApp::WarningTrialTexturePackReturned,pClass); - - return S_OK; - } - } -#ifndef _XBOX_ONE - // does the save exist? - bool bSaveExists; - StorageManager.DoesSaveExist(&bSaveExists); - // 4J-PB - we check if the save exists inside the libs - // we need to ask if they are sure they want to overwrite the existing game - if(bSaveExists) - { - UINT uiIDA[2]; - uiIDA[0]=IDS_CONFIRM_CANCEL; - uiIDA[1]=IDS_CONFIRM_OK; - ui.RequestErrorMessage(IDS_TITLE_SAVE_GAME, IDS_CONFIRM_SAVE_GAME, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::ExitAndJoinFromInviteAndSaveReturned,pClass); - return 0; - } - else -#endif - { -#if defined(_XBOX_ONE) || defined(__ORBIS__) - StorageManager.SetSaveDisabled(false); -#endif - MinecraftServer::getInstance()->setSaveOnExit( true ); - } - } - else - { - // been a few requests for a confirm on exit without saving - UINT uiIDA[2]; - uiIDA[0]=IDS_CONFIRM_CANCEL; - uiIDA[1]=IDS_CONFIRM_OK; - ui.RequestErrorMessage(IDS_TITLE_DECLINE_SAVE_GAME, IDS_CONFIRM_DECLINE_SAVE_GAME, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::ExitAndJoinFromInviteDeclineSaveReturned,pClass); - return 0; - } - - app.SetAction(ProfileManager.GetPrimaryPad(),eAppAction_ExitAndJoinFromInviteConfirmed); - } - return 0; -} - -int CMinecraftApp::WarningTrialTexturePackReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) -{ - // 4J Stu - I added this in when fixing an X1 bug. We should probably add this as well but I don't have time to test all platforms atm -#if 0 //defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) - if(result==C4JStorage::EMessage_ResultAccept) - { - if(!ProfileManager.IsSignedInLive(iPad)) - { - // you're not signed in to PSN! - - } - else - { - // 4J-PB - need to check this user can access the store - bool bContentRestricted; - ProfileManager.GetChatAndContentRestrictions(iPad,true,nullptr,&bContentRestricted,nullptr); - if(bContentRestricted) - { - UINT uiIDA[1]; - uiIDA[0]=IDS_CONFIRM_OK; - ui.RequestAlertMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPad); - } - else - { - // need to get info on the pack to see if the user has already downloaded it - TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); - DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; - - // retrieve the store name for the skin pack - DLCPack *pDLCPack=pDLCTexPack->getDLCInfoParentPack();//tPack->getDLCPack(); - const char *pchPackName=wstringtofilename(pDLCPack->getName()); - app.DebugPrintf("Texture Pack - %s\n",pchPackName); - SONYDLC *pSONYDLCInfo=app.GetSONYDLCInfo((char *)pchPackName); - - if(pSONYDLCInfo!=nullptr) - { - char chName[42]; - char chSkuID[SCE_NP_COMMERCE2_SKU_ID_LEN]; - - memset(chSkuID,0,SCE_NP_COMMERCE2_SKU_ID_LEN); - // find the info on the skin pack - // we have to retrieve the skuid from the store info, it can't be hardcoded since Sony may change it. - // So we assume the first sku for the product is the one we want -#ifdef __ORBIS__ - sprintf(chName,"%s",pSONYDLCInfo->chDLCKeyname); -#else - sprintf(chName,"%s-%s",app.GetCommerceCategory(),pSONYDLCInfo->chDLCKeyname); -#endif - app.GetDLCSkuIDFromProductList(chName,chSkuID); - // 4J-PB - need to check for an empty store -#if defined __ORBIS__ || defined __PSVITA__ || defined __PS3__ - if(app.CheckForEmptyStore(iPad)==false) -#endif - { - if(app.DLCAlreadyPurchased(chSkuID)) - { - app.DownloadAlreadyPurchased(chSkuID); - } - else - { - app.Checkout(chSkuID); - } - } - } - } - } - } -#endif // - -#ifdef _XBOX_ONE - if(result==C4JStorage::EMessage_ResultAccept) - { - if(ProfileManager.IsSignedIn(iPad)) - { - if (ProfileManager.IsSignedInLive(iPad)) - { - TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); - // get the dlc texture pack - DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; - - DLCPack *pDLCPack=pDLCTexPack->getDLCInfoParentPack(); - - DLC_INFO *pDLCInfo=app.GetDLCInfoForProductName((WCHAR *)pDLCPack->getName().c_str()); - - StorageManager.InstallOffer(1,(WCHAR *)pDLCInfo->wsProductId.c_str(),nullptr,nullptr); - - // the license change coming in when the offer has been installed will cause this scene to refresh - } - else - { - // 4J-JEV: Fix for XB1: #165863 - XR-074: Compliance: With no active network connection user is unable to convert from Trial to Full texture pack and is not messaged why. - UINT uiIDA[1] = { IDS_CONFIRM_OK }; - ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1, iPad); - } - } - } - -#endif -#ifdef _XBOX - - CMinecraftApp* pClass = (CMinecraftApp*)pParam; - - TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); - // get the dlc texture pack - DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; - ULONGLONG ullIndexA[1]; - - // Need to get the parent packs id, since this may be one of many child packs with their own ids - app.GetDLCFullOfferIDForPackID(pDLCTexPack->getDLCParentPackId(),&ullIndexA[0]); - - if(result==C4JStorage::EMessage_ResultAccept) - { - if(ProfileManager.IsSignedIn(iPad)) - { - // need to allow downloads here, or the player would need to quit the game to let the download of a texture pack happen. This might affect the network traffic, since the download could take all the bandwidth... - XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW); - - StorageManager.InstallOffer(1,ullIndexA,nullptr,nullptr); - } - } - else - { - TelemetryManager->RecordUpsellResponded(iPad, eSet_UpsellID_Texture_DLC, ( ullIndexA[0] & 0xFFFFFFFF ), eSen_UpsellOutcome_Declined); - } -#endif - return 0; -} - -int CMinecraftApp::ExitAndJoinFromInviteAndSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) -{ - //CMinecraftApp* pClass = (CMinecraftApp*)pParam; - - // results switched for this dialog - if(result==C4JStorage::EMessage_ResultDecline) - { - INT saveOrCheckpointId = 0; - - // Check they have the full texture pack if they are using one - // 4J-PB - Is the player trying to save but they are using a trial texturepack ? - if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) - { - TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); - - DLCPack * pDLCPack=tPack->getDLCPack(); - if(!pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" )) - { - // upsell - // get the dlc texture pack - -#ifdef _XBOX - DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; - ULONGLONG ullOfferID_Full; - app.GetDLCFullOfferIDForPackID(pDLCTexPack->getDLCParentPackId(),&ullOfferID_Full); - - // tell sentient about the upsell of the full version of the skin pack - TelemetryManager->RecordUpsellPresented(iPad, eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF); -#endif - - UINT uiIDA[2]; - uiIDA[0]=IDS_CONFIRM_OK; - uiIDA[1]=IDS_CONFIRM_CANCEL; - - // Give the player a warning about the trial version of the texture pack - ui.RequestErrorMessage(IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, IDS_WARNING_DLC_TRIALTEXTUREPACK_TEXT, uiIDA, 2, iPad,&CMinecraftApp::WarningTrialTexturePackReturned,nullptr); - - return S_OK; - } - } - //bool validSave = StorageManager.GetSaveUniqueNumber(&saveOrCheckpointId); - //SentientManager.RecordLevelSaveOrCheckpoint(ProfileManager.GetPrimaryPad(), saveOrCheckpointId); - MinecraftServer::getInstance()->setSaveOnExit( true ); - // flag a app action of exit and join game from invite - app.SetAction(iPad,eAppAction_ExitAndJoinFromInviteConfirmed); - } - return 0; -} - -int CMinecraftApp::ExitAndJoinFromInviteDeclineSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) -{ - // results switched for this dialog - if(result==C4JStorage::EMessage_ResultDecline) - { -#if defined(_XBOX_ONE) || defined(__ORBIS__) - StorageManager.SetSaveDisabled(false); -#endif - MinecraftServer::getInstance()->setSaveOnExit( false ); - // flag a app action of exit and join game from invite - app.SetAction(iPad,eAppAction_ExitAndJoinFromInviteConfirmed); - } - return 0; -} - -////////////////////////////////////////////////////////////////////////// -// -// FatalLoadError -// -// This is called when we can't load one of the required files at startup -// It tends to mean the files have been corrupted. -// We have to assume that we've not been able to load the text for the game. -// -////////////////////////////////////////////////////////////////////////// -void CMinecraftApp::FatalLoadError() -{ - -} - -TIPSTRUCT CMinecraftApp::m_GameTipA[MAX_TIPS_GAMETIP]= -{ - { 0, IDS_TIPS_GAMETIP_1}, - { 0, IDS_TIPS_GAMETIP_2}, - { 0, IDS_TIPS_GAMETIP_3}, - { 0, IDS_TIPS_GAMETIP_4}, - { 0, IDS_TIPS_GAMETIP_5}, - { 0, IDS_TIPS_GAMETIP_6}, - { 0, IDS_TIPS_GAMETIP_7}, - { 0, IDS_TIPS_GAMETIP_8}, - { 0, IDS_TIPS_GAMETIP_9}, - { 0, IDS_TIPS_GAMETIP_10}, - { 0, IDS_TIPS_GAMETIP_11}, - { 0, IDS_TIPS_GAMETIP_12}, - { 0, IDS_TIPS_GAMETIP_13}, - { 0, IDS_TIPS_GAMETIP_14}, - { 0, IDS_TIPS_GAMETIP_15}, - { 0, IDS_TIPS_GAMETIP_16}, - { 0, IDS_TIPS_GAMETIP_17}, - { 0, IDS_TIPS_GAMETIP_18}, - { 0, IDS_TIPS_GAMETIP_19}, - { 0, IDS_TIPS_GAMETIP_20}, - { 0, IDS_TIPS_GAMETIP_21}, - { 0, IDS_TIPS_GAMETIP_22}, - { 0, IDS_TIPS_GAMETIP_23}, - { 0, IDS_TIPS_GAMETIP_24}, - { 0, IDS_TIPS_GAMETIP_25}, - { 0, IDS_TIPS_GAMETIP_26}, - { 0, IDS_TIPS_GAMETIP_27}, - { 0, IDS_TIPS_GAMETIP_28}, - { 0, IDS_TIPS_GAMETIP_29}, - { 0, IDS_TIPS_GAMETIP_30}, - { 0, IDS_TIPS_GAMETIP_31}, - { 0, IDS_TIPS_GAMETIP_32}, - { 0, IDS_TIPS_GAMETIP_33}, - { 0, IDS_TIPS_GAMETIP_34}, - { 0, IDS_TIPS_GAMETIP_35}, - { 0, IDS_TIPS_GAMETIP_36}, - { 0, IDS_TIPS_GAMETIP_37}, - { 0, IDS_TIPS_GAMETIP_38}, - { 0, IDS_TIPS_GAMETIP_39}, - { 0, IDS_TIPS_GAMETIP_40}, - { 0, IDS_TIPS_GAMETIP_41}, - { 0, IDS_TIPS_GAMETIP_42}, - { 0, IDS_TIPS_GAMETIP_43}, - { 0, IDS_TIPS_GAMETIP_44}, - { 0, IDS_TIPS_GAMETIP_45}, - { 0, IDS_TIPS_GAMETIP_46}, - { 0, IDS_TIPS_GAMETIP_47}, - { 0, IDS_TIPS_GAMETIP_48}, - { 0, IDS_TIPS_GAMETIP_49}, - { 0, IDS_TIPS_GAMETIP_50}, -}; - -TIPSTRUCT CMinecraftApp::m_TriviaTipA[MAX_TIPS_TRIVIATIP]= -{ - { 0, IDS_TIPS_TRIVIA_1}, - { 0, IDS_TIPS_TRIVIA_2}, - { 0, IDS_TIPS_TRIVIA_3}, - { 0, IDS_TIPS_TRIVIA_4}, - { 0, IDS_TIPS_TRIVIA_5}, - { 0, IDS_TIPS_TRIVIA_6}, - { 0, IDS_TIPS_TRIVIA_7}, - { 0, IDS_TIPS_TRIVIA_8}, - { 0, IDS_TIPS_TRIVIA_9}, - { 0, IDS_TIPS_TRIVIA_10}, - { 0, IDS_TIPS_TRIVIA_11}, - { 0, IDS_TIPS_TRIVIA_12}, - { 0, IDS_TIPS_TRIVIA_13}, - { 0, IDS_TIPS_TRIVIA_14}, - { 0, IDS_TIPS_TRIVIA_15}, - { 0, IDS_TIPS_TRIVIA_16}, - { 0, IDS_TIPS_TRIVIA_17}, - { 0, IDS_TIPS_TRIVIA_18}, - { 0, IDS_TIPS_TRIVIA_19}, - { 0, IDS_TIPS_TRIVIA_20}, -}; - -Random *CMinecraftApp::TipRandom = new Random(); - -int CMinecraftApp::TipsSortFunction(const void* a, const void* b) -{ - return ((TIPSTRUCT*)a)->iSortValue - ((TIPSTRUCT*)b)->iSortValue; -} - -void CMinecraftApp::InitialiseTips() -{ - // We'll randomise the tips at start up based on their priority - - ZeroMemory(m_TipIDA,sizeof(UINT)*MAX_TIPS_GAMETIP+MAX_TIPS_TRIVIATIP); - - // Make the first tip tell you that you can play splitscreen in HD modes if you are in SD - if(!RenderManager.IsHiDef()) - { - m_GameTipA[0].uiStringID=IDS_TIPS_GAMETIP_0; - } - // randomise then quicksort - // going to leave the multiplayer tip so it is always first - - // Only randomise the content package build -#ifdef _CONTENT_PACKAGE - - for(int i=1;inextInt(); - } - qsort( &m_GameTipA[1], MAX_TIPS_GAMETIP-1, sizeof(TIPSTRUCT), TipsSortFunction ); -#endif - - for(int i=0;inextInt(); - } - qsort( m_TriviaTipA, MAX_TIPS_TRIVIATIP, sizeof(TIPSTRUCT), TipsSortFunction ); - - - int iCurrentGameTip=0; - int iCurrentTriviaTip=0; - - for(int i=0;iskins->getSelected()->getColourTable()->getColour(colour); -} - -int CMinecraftApp::GetHTMLFontSize(EHTMLFontSize size) -{ - return s_iHTMLFontSizesA[size]; -} - -wstring CMinecraftApp::FormatHTMLString(int iPad, const wstring &desc, int shadowColour /*= 0xFFFFFFFF*/, bool override) -{ - wstring text(desc); - - wchar_t replacements[64]; - // We will also insert line breaks here as couldn't figure out how to get them to come through from strings.resx ! - text = replaceAll(text, L"{*B*}", L"
" ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_T1)); - text = replaceAll(text, L"{*T1*}", replacements ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_T2)); - text = replaceAll(text, L"{*T2*}", replacements ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_T3)); - text = replaceAll(text, L"{*T3*}", replacements ); // for How To Play - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_Black)); - text = replaceAll(text, L"{*ETB*}", replacements ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_White)); - text = replaceAll(text, L"{*ETW*}", replacements ); - text = replaceAll(text, L"{*EF*}", L"" ); - - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_0), shadowColour); - text = replaceAll(text, L"{*C0*}", replacements ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_1), shadowColour); - text = replaceAll(text, L"{*C1*}", replacements ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_2), shadowColour); - text = replaceAll(text, L"{*C2*}", replacements ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_3), shadowColour); - text = replaceAll(text, L"{*C3*}", replacements ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_4), shadowColour); - text = replaceAll(text, L"{*C4*}", replacements ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_5), shadowColour); - text = replaceAll(text, L"{*C5*}", replacements ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_6), shadowColour); - text = replaceAll(text, L"{*C6*}", replacements ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_7), shadowColour); - text = replaceAll(text, L"{*C7*}", replacements ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_8), shadowColour); - text = replaceAll(text, L"{*C8*}", replacements ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_9), shadowColour); - text = replaceAll(text, L"{*C9*}", replacements ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_a), shadowColour); - text = replaceAll(text, L"{*CA*}", replacements ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_b), shadowColour); - text = replaceAll(text, L"{*CB*}", replacements ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_c), shadowColour); - text = replaceAll(text, L"{*CC*}", replacements ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_d), shadowColour); - text = replaceAll(text, L"{*CD*}", replacements ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_e), shadowColour); - text = replaceAll(text, L"{*CE*}", replacements ); - swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_f), shadowColour); - text = replaceAll(text, L"{*CF*}", replacements ); - - // Swap for southpaw. - if ( app.GetGameSettings(iPad,eGameSetting_ControlSouthPaw) ) - { - text = replaceAll(text, L"{*CONTROLLER_ACTION_MOVE*}", GetActionReplacement(iPad,MINECRAFT_ACTION_LOOK_RIGHT ) ); - text = replaceAll(text, L"{*CONTROLLER_ACTION_LOOK*}", GetActionReplacement(iPad,MINECRAFT_ACTION_RIGHT ) ); - - text = replaceAll(text, L"{*CONTROLLER_MENU_NAVIGATE*}", GetVKReplacement(VK_PAD_RTHUMB_LEFT) ); - } - else // Normal right handed. - { - text = replaceAll(text, L"{*CONTROLLER_ACTION_MOVE*}", GetActionReplacement(iPad,MINECRAFT_ACTION_RIGHT ) ); - text = replaceAll(text, L"{*CONTROLLER_ACTION_LOOK*}", GetActionReplacement(iPad,MINECRAFT_ACTION_LOOK_RIGHT ) ); - - text = replaceAll(text, L"{*CONTROLLER_MENU_NAVIGATE*}", GetVKReplacement(VK_PAD_LTHUMB_LEFT) ); - } - - text = replaceAll(text, L"{*CONTROLLER_ACTION_JUMP*}", GetActionReplacement(iPad,MINECRAFT_ACTION_JUMP ) ); - text = replaceAll(text, L"{*CONTROLLER_ACTION_SNEAK*}", GetActionReplacement(iPad,MINECRAFT_ACTION_SNEAK_TOGGLE ) ); - text = replaceAll(text, L"{*CONTROLLER_ACTION_USE*}", GetActionReplacement(iPad,MINECRAFT_ACTION_USE ) ); - text = replaceAll(text, L"{*CONTROLLER_ACTION_ACTION*}", GetActionReplacement(iPad,MINECRAFT_ACTION_ACTION ) ); - text = replaceAll(text, L"{*CONTROLLER_ACTION_LEFT_SCROLL*}", GetActionReplacement(iPad,MINECRAFT_ACTION_LEFT_SCROLL ) ); - text = replaceAll(text, L"{*CONTROLLER_ACTION_RIGHT_SCROLL*}", GetActionReplacement(iPad,MINECRAFT_ACTION_RIGHT_SCROLL ) ); - text = replaceAll(text, L"{*CONTROLLER_ACTION_INVENTORY*}", GetActionReplacement(iPad,MINECRAFT_ACTION_INVENTORY ) ); - text = replaceAll(text, L"{*CONTROLLER_ACTION_CRAFTING*}", GetActionReplacement(iPad,MINECRAFT_ACTION_CRAFTING ) ); - text = replaceAll(text, L"{*CONTROLLER_ACTION_DROP*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DROP ) ); - text = replaceAll(text, L"{*CONTROLLER_ACTION_CAMERA*}", GetActionReplacement(iPad,MINECRAFT_ACTION_RENDER_THIRD_PERSON ) ); - text = replaceAll(text, L"{*CONTROLLER_ACTION_MENU_PAGEDOWN*}", GetActionReplacement(iPad,ACTION_MENU_PAGEDOWN ) ); - text = replaceAll(text, L"{*CONTROLLER_ACTION_DISMOUNT*}", GetActionReplacement(iPad,MINECRAFT_ACTION_SNEAK_TOGGLE ) ); - text = replaceAll(text, L"{*CONTROLLER_VK_A*}", GetVKReplacement(VK_PAD_A) ); - text = replaceAll(text, L"{*CONTROLLER_VK_B*}", GetVKReplacement(VK_PAD_B) ); - text = replaceAll(text, L"{*CONTROLLER_VK_X*}", GetVKReplacement(VK_PAD_X) ); - text = replaceAll(text, L"{*CONTROLLER_VK_Y*}", GetVKReplacement(VK_PAD_Y, override) ); - text = replaceAll(text, L"{*CONTROLLER_VK_LB*}", GetVKReplacement(VK_PAD_LSHOULDER) ); - text = replaceAll(text, L"{*CONTROLLER_VK_RB*}", GetVKReplacement(VK_PAD_RSHOULDER) ); - text = replaceAll(text, L"{*CONTROLLER_VK_LS*}", GetVKReplacement(VK_PAD_LTHUMB_UP) ); - text = replaceAll(text, L"{*CONTROLLER_VK_RS*}", GetVKReplacement(VK_PAD_RTHUMB_UP) ); - text = replaceAll(text, L"{*CONTROLLER_VK_LT*}", GetVKReplacement(VK_PAD_LTRIGGER) ); - text = replaceAll(text, L"{*CONTROLLER_VK_RT*}", GetVKReplacement(VK_PAD_RTRIGGER) ); - text = replaceAll(text, L"{*ICON_SHANK_01*}", GetIconReplacement(XZP_ICON_SHANK_01) ); - text = replaceAll(text, L"{*ICON_SHANK_03*}", GetIconReplacement(XZP_ICON_SHANK_03) ); - text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_UP*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DPAD_UP ) ); - text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_DOWN*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DPAD_DOWN ) ); - text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_RIGHT*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DPAD_RIGHT ) ); - text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_LEFT*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DPAD_LEFT ) ); -#if defined _XBOX_ONE || defined __PSVITA__ - text = replaceAll(text, L"{*CONTROLLER_VK_START*}", GetVKReplacement(VK_PAD_START ) ); - text = replaceAll(text, L"{*CONTROLLER_VK_BACK*}", GetVKReplacement(VK_PAD_BACK ) ); -#endif - -#ifdef _XBOX - wstring imageRoot = L""; - - Minecraft *pMinecraft = Minecraft::GetInstance(); - imageRoot = pMinecraft->skins->getSelected()->getXuiRootPath(); - - text = replaceAll(text, L"{*IMAGEROOT*}", imageRoot); -#endif // _XBOX - - // Fix for #8903 - UI: Localization: KOR/JPN/CHT: Button Icons are rendered with padding space, which looks no good - DWORD dwLanguage = XGetLanguage( ); - switch(dwLanguage) - { - case XC_LANGUAGE_KOREAN: - case XC_LANGUAGE_JAPANESE: - case XC_LANGUAGE_TCHINESE: - text = replaceAll(text, L" ", L"" ); - break; - } - - return text; -} - -//found list of html escapes at https://stackoverflow.com/questions/7381974/which-characters-need-to-be-escaped-in-html -wstring CMinecraftApp::EscapeHTMLString(const wstring& desc) -{ - static std::unordered_map replacementMap = { - {L'&', L"&"}, - {L'<', L"<"}, - {L'>', L">"}, - {L'\'', L"\u2019"}, - }; - - wstring finalString = L""; - for (int i = 0; i < desc.size(); i++) { - wchar_t _char = desc[i]; - auto it = replacementMap.find(_char); - - if (it != replacementMap.end()) finalString += it->second; - else finalString += _char; - } - - return finalString; -} - -wstring CMinecraftApp::FormatChatMessage(const wstring& desc, bool applyStyling) -{ - static std::wregex IDS_Pattern(LR"(\{\*IDS_(\d+)\*\})"); //maybe theres a better way to do translateable IDS - static std::wstring_view colorFormatString = L""; - - wstring results = desc; - wchar_t replacements[64]; - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_0), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A70", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_1), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A71", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_2), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A72", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_3), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A73", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_4), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A74", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_5), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A75", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_6), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A76", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_7), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A77", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_8), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A78", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_9), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A79", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_a), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A7a", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_b), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A7b", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_c), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A7c", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_d), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A7d", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_e), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A7e", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_f), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A7f", replacements); - results = replaceAll(results, L"\u00A7r", replacements); //we only support color so reset is the same as white color - - if (applyStyling) { - std::wsmatch match; - while (std::regex_search(results, match, IDS_Pattern)) { - results = replaceAll(results, match[0], app.GetString(std::stoi(match[1].str()))); - } - } - - - return results; -} - -wstring CMinecraftApp::GetActionReplacement(int iPad, unsigned char ucAction) -{ - unsigned int input = InputManager.GetGameJoypadMaps(InputManager.GetJoypadMapVal(iPad) ,ucAction); - -#ifdef _XBOX - switch(input) - { - case _360_JOY_BUTTON_A: - return app.GetString( IDS_CONTROLLER_A ); - case _360_JOY_BUTTON_B: - return app.GetString( IDS_CONTROLLER_B ); - case _360_JOY_BUTTON_X: - return app.GetString( IDS_CONTROLLER_X ); - case _360_JOY_BUTTON_Y: - return app.GetString( IDS_CONTROLLER_Y ); - case _360_JOY_BUTTON_LSTICK_UP: - case _360_JOY_BUTTON_LSTICK_DOWN: - case _360_JOY_BUTTON_LSTICK_LEFT: - case _360_JOY_BUTTON_LSTICK_RIGHT: - return app.GetString( IDS_CONTROLLER_LEFT_STICK ); - case _360_JOY_BUTTON_RSTICK_LEFT: - case _360_JOY_BUTTON_RSTICK_RIGHT: - case _360_JOY_BUTTON_RSTICK_UP: - case _360_JOY_BUTTON_RSTICK_DOWN: - return app.GetString( IDS_CONTROLLER_RIGHT_STICK ); - case _360_JOY_BUTTON_LT: - return app.GetString( IDS_CONTROLLER_LEFT_TRIGGER ); - case _360_JOY_BUTTON_RT: - return app.GetString( IDS_CONTROLLER_RIGHT_TRIGGER ); - case _360_JOY_BUTTON_RB: - return app.GetString( IDS_CONTROLLER_RIGHT_BUMPER ); - case _360_JOY_BUTTON_LB: - return app.GetString( IDS_CONTROLLER_LEFT_BUMPER ); - case _360_JOY_BUTTON_BACK: - return app.GetString( IDS_CONTROLLER_BACK ); - case _360_JOY_BUTTON_START: - return app.GetString( IDS_CONTROLLER_START ); - case _360_JOY_BUTTON_RTHUMB: - return app.GetString( IDS_CONTROLLER_RIGHT_THUMBSTICK ); - case _360_JOY_BUTTON_LTHUMB: - return app.GetString( IDS_CONTROLLER_LEFT_THUMBSTICK ); - case _360_JOY_BUTTON_DPAD_LEFT: - return app.GetString( IDS_CONTROLLER_DPAD_L ); - case _360_JOY_BUTTON_DPAD_RIGHT: - return app.GetString( IDS_CONTROLLER_DPAD_R ); - case _360_JOY_BUTTON_DPAD_UP: - return app.GetString( IDS_CONTROLLER_DPAD_U ); - case _360_JOY_BUTTON_DPAD_DOWN: - return app.GetString( IDS_CONTROLLER_DPAD_D ); - }; - return L""; -#else - wstring replacement = L""; - - // 4J Stu - Some of our actions can be mapped to multiple physical buttons, so replaces the switch that was here - if (input & _360_JOY_BUTTON_A) replacement = L"ButtonA"; - else if(input &_360_JOY_BUTTON_B) replacement = L"ButtonB"; - else if(input &_360_JOY_BUTTON_X) replacement = L"ButtonX"; - else if(input &_360_JOY_BUTTON_Y) replacement = L"ButtonY"; - else if( - (input &_360_JOY_BUTTON_LSTICK_UP) || - (input &_360_JOY_BUTTON_LSTICK_DOWN) || - (input &_360_JOY_BUTTON_LSTICK_LEFT) || - (input &_360_JOY_BUTTON_LSTICK_RIGHT) - ) - { - replacement = L"ButtonLeftStick"; - } - else if( - (input &_360_JOY_BUTTON_RSTICK_LEFT) || - (input &_360_JOY_BUTTON_RSTICK_RIGHT) || - (input &_360_JOY_BUTTON_RSTICK_UP) || - (input &_360_JOY_BUTTON_RSTICK_DOWN) - ) - { - replacement = L"ButtonRightStick"; - } - else if(input &_360_JOY_BUTTON_DPAD_LEFT) replacement = L"ButtonDpadL"; - else if(input &_360_JOY_BUTTON_DPAD_RIGHT) replacement = L"ButtonDpadR"; - else if(input &_360_JOY_BUTTON_DPAD_UP) replacement = L"ButtonDpadU"; - else if(input &_360_JOY_BUTTON_DPAD_DOWN) replacement = L"ButtonDpadD"; - else if(input &_360_JOY_BUTTON_LT) replacement = L"ButtonLeftTrigger"; - else if(input &_360_JOY_BUTTON_RT) replacement = L"ButtonRightTrigger"; - else if(input &_360_JOY_BUTTON_RB) replacement = L"ButtonRightBumper"; - else if(input &_360_JOY_BUTTON_LB) replacement = L"ButtonLeftBumper"; - else if(input &_360_JOY_BUTTON_BACK) replacement = L"ButtonBack"; - else if(input &_360_JOY_BUTTON_START) replacement = L"ButtonStart"; - else if(input &_360_JOY_BUTTON_RTHUMB) replacement = L"ButtonRS"; - else if(input &_360_JOY_BUTTON_LTHUMB) replacement = L"ButtonLS"; - - wchar_t string[128]; - -#ifdef __PS3__ - int size = 30; -#elif defined _WIN64 - int size = 45; - if(ui.getScreenHeight() < 1080) size = 30; -#else - int size = 45; -#endif - - swprintf(string,128,L"", replacement.c_str(), size, size); - - return string; -#endif -} - -wstring CMinecraftApp::GetVKReplacement(unsigned int uiVKey, bool override) -{ -#ifdef _XBOX - switch(uiVKey) - { - case VK_PAD_A: - return app.GetString( IDS_CONTROLLER_A ); - case VK_PAD_B: - return app.GetString( IDS_CONTROLLER_B ); - case VK_PAD_X: - return app.GetString( IDS_CONTROLLER_X ); - case VK_PAD_Y: - return app.GetString( IDS_CONTROLLER_Y ); - case VK_PAD_LSHOULDER: - return app.GetString( IDS_CONTROLLER_LEFT_BUMPER ); - case VK_PAD_RSHOULDER: - return app.GetString( IDS_CONTROLLER_RIGHT_BUMPER ); - case VK_PAD_LTRIGGER: - return app.GetString( IDS_CONTROLLER_LEFT_TRIGGER ); - case VK_PAD_RTRIGGER: - return app.GetString( IDS_CONTROLLER_RIGHT_TRIGGER ); - case VK_PAD_LTHUMB_UP : - case VK_PAD_LTHUMB_DOWN : - case VK_PAD_LTHUMB_RIGHT : - case VK_PAD_LTHUMB_LEFT : - case VK_PAD_LTHUMB_UPLEFT : - case VK_PAD_LTHUMB_UPRIGHT : - case VK_PAD_LTHUMB_DOWNRIGHT: - case VK_PAD_LTHUMB_DOWNLEFT : - return app.GetString( IDS_CONTROLLER_LEFT_STICK ); - case VK_PAD_RTHUMB_UP : - case VK_PAD_RTHUMB_DOWN : - case VK_PAD_RTHUMB_RIGHT : - case VK_PAD_RTHUMB_LEFT : - case VK_PAD_RTHUMB_UPLEFT : - case VK_PAD_RTHUMB_UPRIGHT : - case VK_PAD_RTHUMB_DOWNRIGHT: - case VK_PAD_RTHUMB_DOWNLEFT : - return app.GetString( IDS_CONTROLLER_RIGHT_STICK ); - default: - break; - } - return nullptr; -#else - wstring replacement = L""; - switch(uiVKey) - { - case VK_PAD_A: -#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) - if( InputManager.IsCircleCrossSwapped() ) replacement = L"ButtonB"; - else replacement = L"ButtonA"; -#else - replacement = L"ButtonA"; -#endif - break; - case VK_PAD_B: -#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) - if( InputManager.IsCircleCrossSwapped() ) replacement = L"ButtonA"; - else replacement = L"ButtonB"; -#else - replacement = L"ButtonB"; -#endif - break; - case VK_PAD_X: - replacement = L"ButtonX"; - break; - case VK_PAD_Y: - replacement = L"ButtonY"; - break; - case VK_PAD_LSHOULDER: - replacement = L"ButtonLeftBumper"; - break; - case VK_PAD_RSHOULDER: - replacement = L"ButtonRightBumper"; - break; - case VK_PAD_LTRIGGER: - replacement = L"ButtonLeftTrigger"; - break; - case VK_PAD_RTRIGGER: - replacement = L"ButtonRightTrigger"; - break; - case VK_PAD_LTHUMB_UP : - case VK_PAD_LTHUMB_DOWN : - case VK_PAD_LTHUMB_RIGHT : - case VK_PAD_LTHUMB_LEFT : - case VK_PAD_LTHUMB_UPLEFT : - case VK_PAD_LTHUMB_UPRIGHT : - case VK_PAD_LTHUMB_DOWNRIGHT: - case VK_PAD_LTHUMB_DOWNLEFT : - replacement = L"ButtonLeftStick"; - break; - case VK_PAD_RTHUMB_UP : - case VK_PAD_RTHUMB_DOWN : - case VK_PAD_RTHUMB_RIGHT : - case VK_PAD_RTHUMB_LEFT : - case VK_PAD_RTHUMB_UPLEFT : - case VK_PAD_RTHUMB_UPRIGHT : - case VK_PAD_RTHUMB_DOWNRIGHT: - case VK_PAD_RTHUMB_DOWNLEFT : - replacement = L"ButtonRightStick"; - break; -#if defined _XBOX_ONE || defined __PSVITA__ - case VK_PAD_START: - replacement = L"ButtonStart"; - break; - case VK_PAD_BACK: - replacement = L"ButtonBack"; - break; -#endif - default: - break; - } - wchar_t string[128]; - -#ifdef __PS3__ - int size = 30; -#elif defined _WIN64 - int size = 45; - if(ui.getScreenHeight() < 1080 || override == true) size = 30; -#else - int size = 45; -#endif - - swprintf(string,128,L"", replacement.c_str(), size, size); - - return string; -#endif -} - -wstring CMinecraftApp::GetIconReplacement(unsigned int uiIcon) -{ -#ifdef _XBOX - switch(uiIcon) - { - case XZP_ICON_SHANK_01: - return app.GetString( IDS_ICON_SHANK_01 ); - case XZP_ICON_SHANK_03: - return app.GetString( IDS_ICON_SHANK_03 ); - default: - break; - } - return nullptr; -#else - wchar_t string[128]; - -#ifdef __PS3__ - int size = 22; -#elif defined _WIN64 - int size = 33; - if(ui.getScreenHeight() < 1080) size = 22; -#else - int size = 33; -#endif - - swprintf(string,128,L"", size, size); - wstring result = L""; - switch(uiIcon) - { - case XZP_ICON_SHANK_01: - result = string; - break; - case XZP_ICON_SHANK_03: - result.append(string).append(string).append(string); - break; - default: - break; - } - return result; -#endif -} - -#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) -unordered_map CMinecraftApp::MojangData; -unordered_map CMinecraftApp::DLCTextures_PackID; -unordered_map CMinecraftApp::DLCInfo; -unordered_map CMinecraftApp::DLCInfo_SkinName; -#elif defined(_DURANGO) -unordered_map CMinecraftApp::MojangData; -unordered_map CMinecraftApp::DLCTextures_PackID; // for mash-up packs & texture packs -//unordered_map CMinecraftApp::DLCInfo_Trial; // full offerid, dlc_info -unordered_map CMinecraftApp::DLCInfo_Full; // full offerid, dlc_info -unordered_map CMinecraftApp::DLCInfo_SkinName; // skin name, full offer id -#else -unordered_map CMinecraftApp::MojangData; -unordered_map CMinecraftApp::DLCTextures_PackID; -unordered_map CMinecraftApp::DLCInfo_Trial; -unordered_map CMinecraftApp::DLCInfo_Full; -unordered_map CMinecraftApp::DLCInfo_SkinName; -#endif - - - -HRESULT CMinecraftApp::RegisterMojangData(WCHAR *pXuidName, PlayerUID xuid, WCHAR *pSkin, WCHAR *pCape) -{ - HRESULT hr=S_OK; - eXUID eTempXuid=eXUID_Undefined; - MOJANG_DATA *pMojangData=nullptr; - - // ignore the names if we don't recognize them - if (pXuidName != nullptr) - { - if( wcscmp( pXuidName, L"XUID_NOTCH" ) == 0 ) - { - eTempXuid = eXUID_Notch; // might be needed for the apple at some point - } - else if( wcscmp( pXuidName, L"XUID_DEADMAU5" ) == 0 ) - { - eTempXuid = eXUID_Deadmau5; // Needed for the deadmau5 ears - } - else - { - eTempXuid=eXUID_NoName; - } - } - - if(eTempXuid!=eXUID_Undefined) - { - pMojangData = new MOJANG_DATA; - ZeroMemory(pMojangData,sizeof(MOJANG_DATA)); - pMojangData->eXuid=eTempXuid; - - wcsncpy( pMojangData->wchSkin, pSkin, MAX_CAPENAME_SIZE); - wcsncpy( pMojangData->wchCape, pCape, MAX_CAPENAME_SIZE); - MojangData[xuid]=pMojangData; - } - - return hr; -} - -MOJANG_DATA *CMinecraftApp::GetMojangDataForXuid(PlayerUID xuid) -{ - return MojangData[xuid]; -} - -HRESULT CMinecraftApp::RegisterConfigValues(WCHAR *pType, int iValue) -{ - HRESULT hr=S_OK; - - // #ifdef _XBOX - // if(pType!=nullptr) - // { - // if(wcscmp(pType,L"XboxOneTransfer")==0) - // { - // if(iValue>0) - // { - // app.m_bTransferSavesToXboxOne=true; - // } - // else - // { - // app.m_bTransferSavesToXboxOne=false; - // } - // } - // else if(wcscmp(pType,L"TransferSlotCount")==0) - // { - // app.m_uiTransferSlotC=iValue; - // } - // - // } - // #endif - - - return hr; -} - -#if (defined _XBOX || defined _WINDOWS64) -HRESULT CMinecraftApp::RegisterDLCData(WCHAR *pType, WCHAR *pBannerName, int iGender, uint64_t ullOfferID_Full, uint64_t ullOfferID_Trial, WCHAR *pFirstSkin, unsigned int uiSortIndex, int iConfig, WCHAR *pDataFile) -{ - HRESULT hr=S_OK; - DLC_INFO *pDLCData=new DLC_INFO; - ZeroMemory(pDLCData,sizeof(DLC_INFO)); - pDLCData->ullOfferID_Full=ullOfferID_Full; - pDLCData->ullOfferID_Trial=ullOfferID_Trial; - pDLCData->eDLCType=e_DLC_NotDefined; - pDLCData->iGender=iGender; - pDLCData->uiSortIndex=uiSortIndex; - pDLCData->iConfig=iConfig; - -#ifndef __ORBIS__ - // ignore the names if we don't recognize them - if(pBannerName!=L"") - { - wcsncpy_s( pDLCData->wchBanner, pBannerName, MAX_BANNERNAME_SIZE); - } - - if(pDataFile[0]!=0) - { - wcsncpy_s( pDLCData->wchDataFile, pDataFile, MAX_BANNERNAME_SIZE); - } -#endif - - if(pType!=nullptr) - { - if(wcscmp(pType,L"Skin")==0) - { - pDLCData->eDLCType=e_DLC_SkinPack; - } - else if(wcscmp(pType,L"Gamerpic")==0) - { - pDLCData->eDLCType=e_DLC_Gamerpics; - } - else if(wcscmp(pType,L"Theme")==0) - { - pDLCData->eDLCType=e_DLC_Themes; - } - else if(wcscmp(pType,L"Avatar")==0) - { - pDLCData->eDLCType=e_DLC_AvatarItems; - } - else if(wcscmp(pType,L"MashUpPack")==0) - { - pDLCData->eDLCType=e_DLC_MashupPacks; - DLCTextures_PackID[pDLCData->iConfig]=ullOfferID_Full; - } - else if(wcscmp(pType,L"TexturePack")==0) - { - pDLCData->eDLCType=e_DLC_TexturePacks; - DLCTextures_PackID[pDLCData->iConfig]=ullOfferID_Full; - } - - - } - - if(ullOfferID_Trial!=0ll) DLCInfo_Trial[ullOfferID_Trial]=pDLCData; - if(ullOfferID_Full!=0ll) DLCInfo_Full[ullOfferID_Full]=pDLCData; - if(pFirstSkin[0]!=0) DLCInfo_SkinName[pFirstSkin]=ullOfferID_Full; - - return hr; -} -#elif defined _XBOX_ONE - -unordered_map *CMinecraftApp::GetDLCInfo() -{ - return &DLCInfo_Full; -} - -HRESULT CMinecraftApp::RegisterDLCData(eDLCContentType eType, WCHAR *pwchBannerName,WCHAR *pwchProductId, WCHAR *pwchProductName, WCHAR *pwchFirstSkin, int iConfig, unsigned int uiSortIndex) -{ - HRESULT hr=S_OK; - // 4J-PB - need to convert the product id to uppercase because the catalog calls come back with upper case - WCHAR wchUppercaseProductID[64]; - if(pwchProductId[0]!=0) - { - for(int i=0;i<64;i++) - { - wchUppercaseProductID[i]=towupper((wchar_t)pwchProductId[i]); - } - } - - // check if we already have this info from the local DLC file - wstring wsTemp=wchUppercaseProductID; - - auto it = DLCInfo_Full.find(wsTemp); - if( it == DLCInfo_Full.end() ) - { - // Not found - - DLC_INFO *pDLCData=new DLC_INFO; - ZeroMemory(pDLCData,sizeof(DLC_INFO)); - - pDLCData->eDLCType=e_DLC_NotDefined; - pDLCData->uiSortIndex=uiSortIndex; - pDLCData->iConfig=iConfig; - - if(pwchProductId[0]!=0) - { - pDLCData->wsProductId=wchUppercaseProductID; - } - - // ignore the names if we don't recognize them - if(pwchBannerName!=L"") - { - wcsncpy_s( pDLCData->wchBanner, pwchBannerName, MAX_BANNERNAME_SIZE); - } - - if(pwchProductName[0]!=0) - { - pDLCData->wsDisplayName=pwchProductName; - } - - pDLCData->eDLCType=eType; - - switch(eType) - { - case e_DLC_MashupPacks: - case e_DLC_TexturePacks: - DLCTextures_PackID[iConfig]=pDLCData->wsProductId; - break; - } - - if(pwchFirstSkin[0]!=0) DLCInfo_SkinName[pwchFirstSkin]=pDLCData->wsProductId; - -#ifdef _XBOX_ONE - // ignore the names, and use the product id instead - DLCInfo_Full[pDLCData->wsProductId]=pDLCData; -#else - DLCInfo_Full[pDLCData->wsDisplayName]=pDLCData; -#endif - } - app.DebugPrintf("DLCInfo - type - %d, productID - %ls, name - %ls , banner - %ls, iconfig - %d, sort index - %d\n",eType,pwchProductId, pwchProductName,pwchBannerName, iConfig, uiSortIndex); - return hr; -} -#else - -HRESULT CMinecraftApp::RegisterDLCData(char *pchDLCName, unsigned int uiSortIndex,char *pchImageURL) -{ - // on PS3 we get all the required info from the name - char chDLCType[3]; - HRESULT hr=S_OK; - DLC_INFO *pDLCData=new DLC_INFO; - ZeroMemory(pDLCData,sizeof(DLC_INFO)); - - chDLCType[0]=pchDLCName[0]; - chDLCType[1]=pchDLCName[1]; - chDLCType[2]=0; - - pDLCData->iConfig = app.GetiConfigFromName(pchDLCName); - pDLCData->uiSortIndex=uiSortIndex; - pDLCData->eDLCType = app.GetDLCTypeFromName(pchDLCName); - strcpy(pDLCData->chImageURL,pchImageURL); - //bool bIsTrialDLC = app.GetTrialFromName(pchDLCName); - - switch(pDLCData->eDLCType) - { - case e_DLC_TexturePacks: - { - char *pchName=(char *)malloc(strlen(pchDLCName)+1); - strcpy(pchName,pchDLCName); - DLCTextures_PackID[pDLCData->iConfig]=pchName; - } - break; - case e_DLC_MashupPacks: - { - char *pchName=(char *)malloc(strlen(pchDLCName)+1); - strcpy(pchName,pchDLCName); - DLCTextures_PackID[pDLCData->iConfig]=pchName; - } - break; - default: - break; - } - - app.DebugPrintf(5,"Adding DLC - %s\n",pchDLCName); - DLCInfo[pchDLCName]=pDLCData; - - // if(ullOfferID_Trial!=0ll) DLCInfo_Trial[ullOfferID_Trial]=pDLCData; - // if(ullOfferID_Full!=0ll) DLCInfo_Full[ullOfferID_Full]=pDLCData; - // if(pFirstSkin[0]!=0) DLCInfo_SkinName[pFirstSkin]=ullOfferID_Full; - - // DLCInfo[ullOfferID_Trial]=pDLCData; - - return hr; -} -#endif - - - -#if defined( __PS3__) || defined(__ORBIS__) || defined(__PSVITA__) -bool CMinecraftApp::GetDLCFullOfferIDForSkinID(const wstring &FirstSkin,ULONGLONG *pullVal) -{ - auto it = DLCInfo_SkinName.find(FirstSkin); - if( it == DLCInfo_SkinName.end() ) - { - return false; - } - else - { - *pullVal=(ULONGLONG)it->second; - return true; - } -} -bool CMinecraftApp::GetDLCNameForPackID(const int iPackID,char **ppchKeyID) -{ - auto it = DLCTextures_PackID.find(iPackID); - if( it == DLCTextures_PackID.end() ) - { - *ppchKeyID=nullptr; - return false; - } - else - { - *ppchKeyID=(char *)it->second; - return true; - } -} -DLC_INFO *CMinecraftApp::GetDLCInfo(char *pchDLCName) -{ - string tempString=pchDLCName; - - if(DLCInfo.size()>0) - { - auto it = DLCInfo.find(tempString); - - if( it == DLCInfo.end() ) - { - // nothing for this - return nullptr; - } - else - { - return it->second; - } - } - else return nullptr; -} - -DLC_INFO *CMinecraftApp::GetDLCInfoFromTPackID(int iTPID) -{ - unordered_map::iterator it= DLCInfo.begin(); - - for(size_t i=0;isecond)->iConfig==iTPID) - { - return it->second; - } - ++it; - } - return nullptr; -} - -DLC_INFO *CMinecraftApp::GetDLCInfo(int iIndex) -{ - unordered_map::iterator it= DLCInfo.begin(); - - for(int i=0;isecond; -} - -char *CMinecraftApp::GetDLCInfoTextures(int iIndex) -{ - unordered_map::iterator it= DLCTextures_PackID.begin(); - - for(int i=0;isecond; -} - -#elif defined _XBOX_ONE -bool CMinecraftApp::GetDLCFullOfferIDForSkinID(const wstring &FirstSkin,wstring &ProductId) -{ - auto it = DLCInfo_SkinName.find(FirstSkin); - if( it == DLCInfo_SkinName.end() ) - { - return false; - } - else - { - ProductId=it->second; - return true; - } -} -bool CMinecraftApp::GetDLCFullOfferIDForPackID(const int iPackID,wstring &ProductId) -{ - auto it = DLCTextures_PackID.find(iPackID); - if( it == DLCTextures_PackID.end() ) - { - return false; - } - else - { - ProductId=it->second; - return true; - } -} -// DLC_INFO *CMinecraftApp::GetDLCInfoForTrialOfferID(wstring &ProductId) -// { -// return nullptr; -// } - -DLC_INFO *CMinecraftApp::GetDLCInfoTrialOffer(int iIndex) -{ - return nullptr; -} -DLC_INFO *CMinecraftApp::GetDLCInfoFullOffer(int iIndex) -{ - unordered_map::iterator it= DLCInfo_Full.begin(); - - for(int i=0;isecond; -} -wstring CMinecraftApp::GetDLCInfoTexturesFullOffer(int iIndex) -{ - unordered_map::iterator it= DLCTextures_PackID.begin(); - - for(int i=0;isecond; -} -#else -bool CMinecraftApp::GetDLCFullOfferIDForSkinID(const wstring &FirstSkin,ULONGLONG *pullVal) -{ - auto it = DLCInfo_SkinName.find(FirstSkin); - if( it == DLCInfo_SkinName.end() ) - { - return false; - } - else - { - *pullVal=(ULONGLONG)it->second; - return true; - } -} -bool CMinecraftApp::GetDLCFullOfferIDForPackID(const int iPackID,ULONGLONG *pullVal) -{ - auto it = DLCTextures_PackID.find(iPackID); - if( it == DLCTextures_PackID.end() ) - { - *pullVal=0ULL; - return false; - } - else - { - *pullVal=it->second; - return true; - } -} -DLC_INFO *CMinecraftApp::GetDLCInfoForTrialOfferID(ULONGLONG ullOfferID_Trial) -{ - //DLC_INFO *pDLCInfo=nullptr; - if(DLCInfo_Trial.size()>0) - { - auto it = DLCInfo_Trial.find(ullOfferID_Trial); - - if( it == DLCInfo_Trial.end() ) - { - // nothing for this - return nullptr; - } - else - { - return it->second; - } - } - else return nullptr; -} - -DLC_INFO *CMinecraftApp::GetDLCInfoTrialOffer(int iIndex) -{ - unordered_map::iterator it= DLCInfo_Trial.begin(); - - for(int i=0;isecond; -} -DLC_INFO *CMinecraftApp::GetDLCInfoFullOffer(int iIndex) -{ - unordered_map::iterator it= DLCInfo_Full.begin(); - - for(int i=0;isecond; -} -ULONGLONG CMinecraftApp::GetDLCInfoTexturesFullOffer(int iIndex) -{ - unordered_map::iterator it= DLCTextures_PackID.begin(); - - for(int i=0;isecond; -} -#endif - -#ifdef _XBOX_ONE - -DLC_INFO *CMinecraftApp::GetDLCInfoForFullOfferID(WCHAR *pwchProductID) -{ - wstring wsTemp = pwchProductID; - if(DLCInfo_Full.size()>0) - { - auto it = DLCInfo_Full.find(wsTemp); - - if( it == DLCInfo_Full.end() ) - { - // nothing for this - return nullptr; - } - else - { - return it->second; - } - } - else return nullptr; -} -DLC_INFO *CMinecraftApp::GetDLCInfoForProductName(WCHAR *pwchProductName) -{ - unordered_map::iterator it= DLCInfo_Full.begin(); - wstring wsProductName=pwchProductName; - - for(size_t i=0;isecond; - if(wsProductName==pDLCInfo->wsDisplayName) - { - return pDLCInfo; - } - ++it; - } - - return nullptr; -} - -#elif defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) -#else - -DLC_INFO *CMinecraftApp::GetDLCInfoForFullOfferID(ULONGLONG ullOfferID_Full) -{ - - if(DLCInfo_Full.size()>0) - { - auto it = DLCInfo_Full.find(ullOfferID_Full); - - if( it == DLCInfo_Full.end() ) - { - // nothing for this - return nullptr; - } - else - { - return it->second; - } - } - else return nullptr; -} -#endif - -void CMinecraftApp::EnterSaveNotificationSection() -{ - EnterCriticalSection(&m_saveNotificationCriticalSection); - if( m_saveNotificationDepth++ == 0 ) - { - if(g_NetworkManager.IsInSession()) // this can be triggered from the front end if we're downloading a save - { - MinecraftServer::getInstance()->broadcastStartSavingPacket(); - - if( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 ) - { - app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_PauseServer,(void *)TRUE); - } - } - } - LeaveCriticalSection(&m_saveNotificationCriticalSection); -} - -void CMinecraftApp::LeaveSaveNotificationSection() -{ - EnterCriticalSection(&m_saveNotificationCriticalSection); - if( --m_saveNotificationDepth == 0 ) - { - if(g_NetworkManager.IsInSession()) // this can be triggered from the front end if we're downloading a save - { - MinecraftServer::getInstance()->broadcastStopSavingPacket(); - - if( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 ) - { - app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_PauseServer,(void *)FALSE); - } - } - } - LeaveCriticalSection(&m_saveNotificationCriticalSection); -} - - -int CMinecraftApp::RemoteSaveThreadProc( void* lpParameter ) -{ - // The game should be stopped while we are doing this, but the connections ticks may try to create some AABB's or Vec3's - AABB::UseDefaultThreadStorage(); - Vec3::UseDefaultThreadStorage(); - Compression::UseDefaultThreadStorage(); - - // 4J-PB - Xbox 360 - 163153 - [CRASH] TU17: Code: Multiplayer: During the Autosave in an online Multiplayer session, the game occasionally crashes for one or more Clients - // callstack - > if(tls->tileId != this->id) updateDefaultShape(); - // callstack - > default.exe!WaterlilyTile::getAABB(Level * level, int x, int y, int z) line 38 + 8 bytes C++ - // ... - // default.exe!CMinecraftApp::RemoteSaveThreadProc(void * lpParameter) line 6694 C++ - // host autosave, and the clients can crash on receiving handleMoveEntity when it's a tile within this thread, so need to do the tls for tiles - Tile::CreateNewThreadStorage(); - - Minecraft *pMinecraft = Minecraft::GetInstance(); - - pMinecraft->progressRenderer->progressStartNoAbort( IDS_PROGRESS_HOST_SAVING ); - pMinecraft->progressRenderer->progressStage( -1 ); - pMinecraft->progressRenderer->progressStagePercentage(0); - - while( !app.GetGameStarted() && app.GetXuiAction( ProfileManager.GetPrimaryPad() ) == eAppAction_WaitRemoteServerSaveComplete ) - { - // Tick all the games connections - pMinecraft->tickAllConnections(); - Sleep( 100 ); - } - - if( app.GetXuiAction( ProfileManager.GetPrimaryPad() ) != eAppAction_WaitRemoteServerSaveComplete ) - { - // Something cancelled us? - return ERROR_CANCELLED; - } - app.SetAction(ProfileManager.GetPrimaryPad(),eAppAction_Idle); - - ui.UpdatePlayerBasePositions(); - - Tile::ReleaseThreadStorage(); - - return S_OK; -} - -void CMinecraftApp::ExitGameFromRemoteSave( LPVOID lpParameter ) -{ - int primaryPad = ProfileManager.GetPrimaryPad(); - - UINT uiIDA[3]; - uiIDA[0]=IDS_CONFIRM_CANCEL; - uiIDA[1]=IDS_CONFIRM_OK; - - ui.RequestAlertMessage(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 2, primaryPad,&CMinecraftApp::ExitGameFromRemoteSaveDialogReturned,nullptr); -} - -int CMinecraftApp::ExitGameFromRemoteSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) -{ - //CScene_Pause* pClass = (CScene_Pause*)pParam; - - // results switched for this dialog - if(result==C4JStorage::EMessage_ResultDecline) - { - app.SetAction(iPad,eAppAction_ExitWorld); - } - else - { -#ifndef _XBOX - // Inform fullscreen progress scene that it's not being cancelled after all - UIScene_FullscreenProgress *pScene = static_cast(ui.FindScene(eUIScene_FullscreenProgress)); -#ifdef __PS3__ - if(pScene!=nullptr) -#else - if (pScene != nullptr) -#endif - { - pScene->SetWasCancelled(false); - } -#else - // Don't have to worry about this on Xbox -#endif - } - return 0; -} - -void CMinecraftApp::SetSpecialTutorialCompletionFlag(int iPad, int index) -{ - if(index >= 0 && index < 32 && GameSettingsA[iPad] != nullptr) - { - GameSettingsA[iPad]->uiSpecialTutorialBitmask |= (1<clear(); - - if(BannedListA[iPad].pBannedList) - { - delete [] BannedListA[iPad].pBannedList; - BannedListA[iPad].pBannedList=nullptr; - } - } -} - -#ifdef _XBOX_ONE -void CMinecraftApp::AddLevelToBannedLevelList(int iPad, PBANNEDLISTDATA pBannedListData, bool bWriteToTMS) -{ - PlayerUID xuid= pBannedListData->wchPlayerUID; - - AddLevelToBannedLevelList(iPad,xuid,pBannedListData->pszLevelName,bWriteToTMS); -} -#endif - -void CMinecraftApp::AddLevelToBannedLevelList(int iPad, PlayerUID xuid, char *pszLevelName, bool bWriteToTMS) -{ - // we will have retrieved the banned level list from TMS, so add this one to it and write it back to TMS - - BANNEDLISTDATA *pBannedListData = new BANNEDLISTDATA; - memset(pBannedListData,0,sizeof(BANNEDLISTDATA)); - -#ifdef _DURANGO - memcpy(&pBannedListData->wchPlayerUID, xuid.toString().c_str(), sizeof(WCHAR)*64); -#else - memcpy(&pBannedListData->xuid, &xuid, sizeof(PlayerUID)); -#endif - strcpy(pBannedListData->pszLevelName,pszLevelName); - m_vBannedListA[iPad]->push_back(pBannedListData); - - if (bWriteToTMS) - { - DWORD dwDataBytes = static_cast(sizeof(BANNEDLISTDATA)* m_vBannedListA[iPad]->size()); - PBANNEDLISTDATA pBannedList = reinterpret_cast(new CHAR [dwDataBytes]); - int iCount=0; - for (PBANNEDLISTDATA pData : *m_vBannedListA[iPad] ) - { - memcpy(&pBannedList[iCount++],pData,sizeof(BANNEDLISTDATA)); - } - - // 4J-PB - write to TMS++ now - - //bool bRes=StorageManager.WriteTMSFile(iPad,C4JStorage::eGlobalStorage_TitleUser,L"BannedList",(PBYTE)pBannedList, dwDataBytes); -#ifdef _XBOX - StorageManager.TMSPP_WriteFile(iPad,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,C4JStorage::TMS_UGCTYPE_NONE,"BannedList",(PCHAR) pBannedList, dwDataBytes,nullptr,nullptr, 0); -#elif defined _XBOX_ONE - StorageManager.TMSPP_WriteFile(iPad,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,L"BannedList",(PBYTE) pBannedList, dwDataBytes,nullptr,nullptr, 0); -#endif - } - // update telemetry too -} - -bool CMinecraftApp::IsInBannedLevelList(int iPad, PlayerUID xuid, char *pszLevelName) -{ - for( PBANNEDLISTDATA pData : *m_vBannedListA[iPad] ) - { -#ifdef _XBOX_ONE - PlayerUID bannedPlayerUID = pData->wchPlayerUID; - if(IsEqualXUID (bannedPlayerUID,xuid) && (strcmp(pData->pszLevelName,pszLevelName)==0)) -#else - if(IsEqualXUID (pData->xuid,xuid) && (strcmp(pData->pszLevelName,pszLevelName)==0)) -#endif - { - return true; - } - } - - return false; -} - -void CMinecraftApp::RemoveLevelFromBannedLevelList(int iPad, PlayerUID xuid, char *pszLevelName) -{ - //bool bFound=false; - //bool bRes; - - // we will have retrieved the banned level list from TMS, so remove this one from it and write it back to TMS - for (auto it = m_vBannedListA[iPad]->begin(); it != m_vBannedListA[iPad]->end(); ) - { - PBANNEDLISTDATA pBannedListData = *it; - - if(pBannedListData!=nullptr) - { -#ifdef _XBOX_ONE - PlayerUID bannedPlayerUID = pBannedListData->wchPlayerUID; - if(IsEqualXUID (bannedPlayerUID,xuid) && (strcmp(pBannedListData->pszLevelName,pszLevelName)==0)) -#else - if(IsEqualXUID (pBannedListData->xuid,xuid) && (strcmp(pBannedListData->pszLevelName,pszLevelName)==0)) -#endif - { - TelemetryManager->RecordUnBanLevel(iPad); - - // match found, so remove this entry - it = m_vBannedListA[iPad]->erase(it); - } - else - { - ++it; - } - } - else - { - ++it; - } - } - - DWORD dwDataBytes=static_cast(sizeof(BANNEDLISTDATA) * m_vBannedListA[iPad]->size()); - if(dwDataBytes==0) - { - // wipe the file -#ifdef _XBOX - StorageManager.DeleteTMSFile(iPad,C4JStorage::eGlobalStorage_TitleUser,L"BannedList"); -#elif defined _XBOX_ONE - StorageManager.TMSPP_DeleteFile(iPad,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,L"BannedList",nullptr,nullptr, 0); -#endif - } - else - { - PBANNEDLISTDATA pBannedList = (BANNEDLISTDATA *)(new BYTE [dwDataBytes]); - - size_t iSize=m_vBannedListA[iPad]->size(); - for(size_t i=0;iat(i); - - memcpy(&pBannedList[i],pBannedListData,sizeof(BANNEDLISTDATA)); - } -#ifdef _XBOX - StorageManager.WriteTMSFile(iPad,C4JStorage::eGlobalStorage_TitleUser,L"BannedList",(PBYTE)pBannedList, dwDataBytes); -#elif defined _XBOX_ONE - StorageManager.TMSPP_WriteFile(iPad,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,L"BannedList",(PBYTE) pBannedList, dwDataBytes,nullptr,nullptr, 0); -#endif - delete [] pBannedList; - } - - // update telemetry too -} - -// function to add credits for the DLC packs -void CMinecraftApp::AddCreditText(LPCWSTR lpStr) -{ - DebugPrintf("ADDING CREDIT - %ls\n",lpStr); - // add a string from the DLC to a credits vector - SCreditTextItemDef *pCreditStruct = new SCreditTextItemDef; - pCreditStruct->m_eType=eSmallText; - pCreditStruct->m_iStringID[0]=NO_TRANSLATED_STRING; - pCreditStruct->m_iStringID[1]=NO_TRANSLATED_STRING; - pCreditStruct->m_Text=new WCHAR [wcslen(lpStr)+1]; - wcscpy((WCHAR *)pCreditStruct->m_Text,lpStr); - - vDLCCredits.push_back(pCreditStruct); -} - -bool CMinecraftApp::AlreadySeenCreditText(const wstring &wstemp) -{ - - for(unsigned int i=0;i(vDLCCredits.size()); -} - -SCreditTextItemDef * CMinecraftApp::GetDLCCredits(int iIndex) -{ - return vDLCCredits.at(iIndex); -} - -// Game Host options - -void CMinecraftApp::SetGameHostOption(eGameHostOption eVal,unsigned int uiVal) -{ - SetGameHostOption(m_uiGameHostSettings,eVal,uiVal); -} - - -void CMinecraftApp::SetGameHostOption(unsigned int &uiHostSettings, eGameHostOption eVal, unsigned int uiVal) -{ - switch(eVal) - { - case eGameHostOption_FriendsOfFriends: - if(uiVal!=0) - { - uiHostSettings|=GAME_HOST_OPTION_BITMASK_FRIENDSOFFRIENDS; - } - else - { - // off - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_FRIENDSOFFRIENDS; - } - break; - case eGameHostOption_Difficulty: - // clear the difficulty first - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_DIFFICULTY; - uiHostSettings|=(GAME_HOST_OPTION_BITMASK_DIFFICULTY&uiVal); - break; - case eGameHostOption_Gamertags: - if(uiVal!=0) - { - uiHostSettings|=GAME_HOST_OPTION_BITMASK_GAMERTAGS; - } - else - { - // off - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_GAMERTAGS; - } - - break; - case eGameHostOption_GameType: - // clear the game type first - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_GAMETYPE; - uiHostSettings|=(GAME_HOST_OPTION_BITMASK_GAMETYPE&(uiVal<<4)); - break; - case eGameHostOption_LevelType: - if(uiVal!=0) - { - uiHostSettings|=GAME_HOST_OPTION_BITMASK_LEVELTYPE; - } - else - { - // off - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_LEVELTYPE; - } - - break; - case eGameHostOption_Structures: - if(uiVal!=0) - { - uiHostSettings|=GAME_HOST_OPTION_BITMASK_STRUCTURES; - } - else - { - // off - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_STRUCTURES; - } - - break; - case eGameHostOption_BonusChest: - if(uiVal!=0) - { - uiHostSettings|=GAME_HOST_OPTION_BITMASK_BONUSCHEST; - } - else - { - // off - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_BONUSCHEST; - } - - break; - case eGameHostOption_HasBeenInCreative: - if(uiVal!=0) - { - uiHostSettings|=GAME_HOST_OPTION_BITMASK_BEENINCREATIVE; - } - else - { - // off - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_BEENINCREATIVE; - } - - break; - case eGameHostOption_PvP: - if(uiVal!=0) - { - uiHostSettings|=GAME_HOST_OPTION_BITMASK_PVP; - } - else - { - // off - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_PVP; - } - - break; - case eGameHostOption_TrustPlayers: - if(uiVal!=0) - { - uiHostSettings|=GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS; - } - else - { - // off - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS; - } - - break; - case eGameHostOption_TNT: - if(uiVal!=0) - { - uiHostSettings|=GAME_HOST_OPTION_BITMASK_TNT; - } - else - { - // off - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_TNT; - } - - break; - case eGameHostOption_FireSpreads: - if(uiVal!=0) - { - uiHostSettings|=GAME_HOST_OPTION_BITMASK_FIRESPREADS; - } - else - { - // off - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_FIRESPREADS; - } - break; - case eGameHostOption_CheatsEnabled: - if(uiVal!=0) - { - uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTFLY; - uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTHUNGER; - uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE; - } - else - { - // off - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTFLY; - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTHUNGER; - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE; - } - break; - case eGameHostOption_HostCanFly: - if(uiVal!=0) - { - uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTFLY; - } - else - { - // off - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTFLY; - } - break; - case eGameHostOption_HostCanChangeHunger: - if(uiVal!=0) - { - uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTHUNGER; - } - else - { - // off - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTHUNGER; - } - break; - case eGameHostOption_HostCanBeInvisible: - if(uiVal!=0) - { - uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE; - } - else - { - // off - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE; - } - break; - - case eGameHostOption_BedrockFog: - if(uiVal!=0) - { - uiHostSettings|=GAME_HOST_OPTION_BITMASK_BEDROCKFOG; - } - else - { - // off - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_BEDROCKFOG; - } - break; - case eGameHostOption_DisableSaving: - if(uiVal!=0) - { - uiHostSettings|=GAME_HOST_OPTION_BITMASK_DISABLESAVE; - } - else - { - // off - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_DISABLESAVE; - } - break; - case eGameHostOption_WasntSaveOwner: - if(uiVal!=0) - { - uiHostSettings|=GAME_HOST_OPTION_BITMASK_NOTOWNER; - } - else - { - // off - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_NOTOWNER; - } - break; - case eGameHostOption_MobGriefing: - if(uiVal!=1) - { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_MOBGRIEFING; - } - else - { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_MOBGRIEFING; - } - break; - case eGameHostOption_KeepInventory: - if(uiVal!=0) - { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_KEEPINVENTORY; - } - else - { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_KEEPINVENTORY; - } - break; - case eGameHostOption_DoMobSpawning: - if(uiVal!=1) - { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_DOMOBSPAWNING; - } - else - { - // off - uiHostSettings &=~ GAME_HOST_OPTION_BITMASK_DOMOBSPAWNING; - } - break; - case eGameHostOption_DoMobLoot: - if(uiVal!=1) - { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_DOMOBLOOT; - } - else - { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DOMOBLOOT; - } - break; - case eGameHostOption_DoTileDrops: - if(uiVal!=1) - { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_DOTILEDROPS; - } - else - { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DOTILEDROPS; - } - break; - case eGameHostOption_NaturalRegeneration: - if(uiVal!=1) - { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_NATURALREGEN; - } - else - { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_NATURALREGEN; - } - break; - case eGameHostOption_DoDaylightCycle: - if(uiVal!=1) - { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE; - } - else - { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE; - } - break; - case eGameHostOption_WorldSize: - // clear the difficulty first - uiHostSettings&=~GAME_HOST_OPTION_BITMASK_WORLDSIZE; - uiHostSettings|=(GAME_HOST_OPTION_BITMASK_WORLDSIZE & (uiVal<>4; - break; - case eGameHostOption_All: - return (uiHostSettings&GAME_HOST_OPTION_BITMASK_ALL); - break; - case eGameHostOption_Tutorial: - // special case - tutorial is offline, but we want the gamertag option, and set Easy mode, structures on, fire on, tnt on, pvp on, trust players on - return ((uiHostSettings&GAME_HOST_OPTION_BITMASK_GAMERTAGS)| - GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS| - GAME_HOST_OPTION_BITMASK_FIRESPREADS| - GAME_HOST_OPTION_BITMASK_TNT| - GAME_HOST_OPTION_BITMASK_PVP| - GAME_HOST_OPTION_BITMASK_STRUCTURES|1); - break; - case eGameHostOption_LevelType: - return (uiHostSettings&GAME_HOST_OPTION_BITMASK_LEVELTYPE); - break; - case eGameHostOption_Structures: - return (uiHostSettings&GAME_HOST_OPTION_BITMASK_STRUCTURES); - break; - case eGameHostOption_BonusChest: - return (uiHostSettings&GAME_HOST_OPTION_BITMASK_BONUSCHEST); - break; - case eGameHostOption_HasBeenInCreative: - return (uiHostSettings&GAME_HOST_OPTION_BITMASK_BEENINCREATIVE); - break; - case eGameHostOption_PvP: - return (uiHostSettings&GAME_HOST_OPTION_BITMASK_PVP); - break; - case eGameHostOption_TrustPlayers: - return (uiHostSettings&GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS); - break; - case eGameHostOption_TNT: - return (uiHostSettings&GAME_HOST_OPTION_BITMASK_TNT); - break; - case eGameHostOption_FireSpreads: - return (uiHostSettings&GAME_HOST_OPTION_BITMASK_FIRESPREADS); - break; - case eGameHostOption_CheatsEnabled: - return (uiHostSettings&(GAME_HOST_OPTION_BITMASK_HOSTFLY|GAME_HOST_OPTION_BITMASK_HOSTHUNGER|GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE)); - break; - case eGameHostOption_HostCanFly: - return (uiHostSettings&GAME_HOST_OPTION_BITMASK_HOSTFLY); - break; - case eGameHostOption_HostCanChangeHunger: - return (uiHostSettings&GAME_HOST_OPTION_BITMASK_HOSTHUNGER); - break; - case eGameHostOption_HostCanBeInvisible: - return (uiHostSettings&GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE); - break; - case eGameHostOption_BedrockFog: - return (uiHostSettings&GAME_HOST_OPTION_BITMASK_BEDROCKFOG); - break; - case eGameHostOption_DisableSaving: - return (uiHostSettings&GAME_HOST_OPTION_BITMASK_DISABLESAVE); - break; - case eGameHostOption_WasntSaveOwner: - return (uiHostSettings&GAME_HOST_OPTION_BITMASK_NOTOWNER); - case eGameHostOption_WorldSize: - return (uiHostSettings&GAME_HOST_OPTION_BITMASK_WORLDSIZE) >> GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT; - case eGameHostOption_MobGriefing: - return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_MOBGRIEFING); - case eGameHostOption_KeepInventory: - return (uiHostSettings&GAME_HOST_OPTION_BITMASK_KEEPINVENTORY); - case eGameHostOption_DoMobSpawning: - return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DOMOBSPAWNING); - case eGameHostOption_DoMobLoot: - return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DOMOBLOOT); - case eGameHostOption_DoTileDrops: - return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DOTILEDROPS); - case eGameHostOption_NaturalRegeneration: - return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_NATURALREGEN); - case eGameHostOption_DoDaylightCycle: - return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE); - break; - case eGameHostOption_Hardcore: // 4J Added - for hardcore mode - return (uiHostSettings&GAME_HOST_OPTION_BITMASK_HARDCORE) ? 1 : 0; - break; - } - - return false; -} - -bool CMinecraftApp::CanRecordStatsAndAchievements() -{ - bool isTutorial = Minecraft::GetInstance() != nullptr && Minecraft::GetInstance()->isTutorial(); - // 4J Stu - All of these options give the host player some advantage, so should not allow achievements - return !(app.GetGameHostOption(eGameHostOption_HasBeenInCreative) || - app.GetGameHostOption(eGameHostOption_HostCanBeInvisible) || - app.GetGameHostOption(eGameHostOption_HostCanChangeHunger) || - app.GetGameHostOption(eGameHostOption_HostCanFly) || - app.GetGameHostOption(eGameHostOption_WasntSaveOwner) || - !app.GetGameHostOption(eGameHostOption_MobGriefing) || - app.GetGameHostOption(eGameHostOption_KeepInventory) || - !app.GetGameHostOption(eGameHostOption_DoMobSpawning) || - (!app.GetGameHostOption(eGameHostOption_DoDaylightCycle) && !isTutorial ) - ); -} - -void CMinecraftApp::processSchematics(LevelChunk *levelChunk) -{ - m_gameRules.processSchematics(levelChunk); -} - -void CMinecraftApp::processSchematicsLighting(LevelChunk *levelChunk) -{ - m_gameRules.processSchematicsLighting(levelChunk); -} - -void CMinecraftApp::loadDefaultGameRules() -{ - m_gameRules.loadDefaultGameRules(); -} - -void CMinecraftApp::setLevelGenerationOptions(LevelGenerationOptions *levelGen) -{ - m_gameRules.setLevelGenerationOptions(levelGen); -} - -LPCWSTR CMinecraftApp::GetGameRulesString(const wstring &key) -{ - return m_gameRules.GetGameRulesString(key); -} - -unsigned char CMinecraftApp::m_szPNG[8]= -{ - 137,80,78,71,13,10,26,10 -}; - -#define PNG_TAG_tEXt 0x74455874 - -unsigned int CMinecraftApp::FromBigEndian(unsigned int uiValue) -{ -#if defined(__PS3__) || defined(_XBOX) - // Keep it in big endian - return uiValue; -#else - unsigned int uiReturn = ( ( uiValue >> 24 ) & 0x000000ff ) | - ( ( uiValue >> 8 ) & 0x0000ff00 ) | - ( ( uiValue << 8 ) & 0x00ff0000 ) | - ( ( uiValue << 24 ) & 0xff000000 ); - return uiReturn; -#endif -} - -void CMinecraftApp::GetImageTextData(PBYTE pbImageData, DWORD dwImageBytes,unsigned char *pszSeed,unsigned int &uiHostOptions,bool &bHostOptionsRead,DWORD &uiTexturePack) -{ - unsigned char *ucPtr=pbImageData; - unsigned int uiCount=0; - unsigned int uiChunkLen; - unsigned int uiChunkType; - unsigned int uiCRC; - char szKeyword[80]; - - // check it's a png - for(int i=0;i<8;i++) - { - if(m_szPNG[i]!=ucPtr[i]) return; - } - - uiCount+=8; - - while(uiCount> std::hex >> uiHostOptions; - } - else if(strcmp(szKeyword,"4J_TEXTUREPACK")==0) - { - // read the texture pack value - unsigned int uiValueC=0; - unsigned char pszTexturePack[9]; // Hex representation of unsigned int - ZeroMemory(&pszTexturePack,9); - while(*pszKeyword!=0 && (pszKeyword < ucPtr + uiCount + uiChunkLen) && uiValueC < 8) - { - pszTexturePack[uiValueC++]=*pszKeyword; - pszKeyword++; - } - - std::stringstream ss; - ss << pszTexturePack; - ss >> std::hex >> uiTexturePack; - } - } - } - uiCount+=uiChunkLen; - uiCRC=*(unsigned int*)&ucPtr[uiCount]; - uiCRC=FromBigEndian(uiCRC); - uiCount+=sizeof(int); - } - - return; -} - -unsigned int CMinecraftApp::CreateImageTextData(PBYTE bTextMetadata, int64_t seed, bool hasSeed, unsigned int uiHostOptions, unsigned int uiTexturePackId) -{ - int iTextMetadataBytes = 0; - if(hasSeed) - { - strcpy((char *)bTextMetadata,"4J_SEED"); - _i64toa_s(seed,(char *)&bTextMetadata[8],42,10); - - // get the length - iTextMetadataBytes+=8; - while(bTextMetadata[iTextMetadataBytes]!=0) iTextMetadataBytes++; - ++iTextMetadataBytes; // Add a null terminator at the end of the seed value - } - - // Save the host options that this world was last played with - strcpy((char *)&bTextMetadata[iTextMetadataBytes],"4J_HOSTOPTIONS"); - _itoa_s(uiHostOptions,(char *)&bTextMetadata[iTextMetadataBytes+15],9,16); - - iTextMetadataBytes += 15; - while(bTextMetadata[iTextMetadataBytes]!=0) iTextMetadataBytes++; - ++iTextMetadataBytes; // Add a null terminator at the end of the host options value - - // Save the texture pack id - strcpy((char *)&bTextMetadata[iTextMetadataBytes],"4J_TEXTUREPACK"); - _itoa_s(uiTexturePackId,(char *)&bTextMetadata[iTextMetadataBytes+15],9,16); - - iTextMetadataBytes += 15; - while(bTextMetadata[iTextMetadataBytes]!=0) iTextMetadataBytes++; - - return iTextMetadataBytes; -} - -void CMinecraftApp::AddTerrainFeaturePosition(_eTerrainFeatureType eFeatureType,int x,int z) -{ - // check we don't already have this in - for( FEATURE_DATA *pFeatureData : m_vTerrainFeatures ) - { - if((pFeatureData->eTerrainFeature==eFeatureType) &&(pFeatureData->x==x) && (pFeatureData->z==z)) return; - } - - FEATURE_DATA *pFeatureData= new FEATURE_DATA; - pFeatureData->eTerrainFeature=eFeatureType; - pFeatureData->x=x; - pFeatureData->z=z; - - m_vTerrainFeatures.push_back(pFeatureData); -} - -_eTerrainFeatureType CMinecraftApp::IsTerrainFeature(int x,int z) -{ - for(FEATURE_DATA *pFeatureData : m_vTerrainFeatures ) - { - if((pFeatureData->x==x) && (pFeatureData->z==z)) return pFeatureData->eTerrainFeature; - } - - return eTerrainFeature_None; -} - -bool CMinecraftApp::GetTerrainFeaturePosition(_eTerrainFeatureType eType,int *pX, int *pZ) -{ - for ( const FEATURE_DATA *pFeatureData : m_vTerrainFeatures ) - { - if(pFeatureData->eTerrainFeature==eType) - { - *pX=pFeatureData->x; - *pZ=pFeatureData->z; - return true; - } - } - - return false; -} - -void CMinecraftApp::ClearTerrainFeaturePosition() -{ - FEATURE_DATA *pFeatureData; - while(m_vTerrainFeatures.size()>0) - { - pFeatureData = m_vTerrainFeatures.back(); - m_vTerrainFeatures.pop_back(); - delete pFeatureData; - } -} - -void CMinecraftApp::UpdatePlayerInfo(BYTE networkSmallId, SHORT playerColourIndex, unsigned int playerGamePrivileges) -{ - for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) - { - if(m_playerColours[i]==networkSmallId) - { - m_playerColours[i] = 0; - m_playerGamePrivileges[i] = 0; - } - } - if(playerColourIndex >=0 && playerColourIndex < MINECRAFT_NET_MAX_PLAYERS) - { - m_playerColours[playerColourIndex] = networkSmallId; - m_playerGamePrivileges[playerColourIndex] = playerGamePrivileges; - } -} - -short CMinecraftApp::GetPlayerColour(BYTE networkSmallId) -{ - short index = -1; - for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) - { - if(m_playerColours[i]==networkSmallId) - { - index = i; - break; - } - } - return index; -} - -void CMinecraftApp::SetPlayerMapIcon(const wchar_t* name, char icon) -{ - if (name == nullptr) return; - // Update existing entry or use first empty slot - int emptySlot = -1; - for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) - { - if (m_playerMapIcons[i].name[0] != 0 && _wcsicmp(m_playerMapIcons[i].name, name) == 0) - { - m_playerMapIcons[i].icon = icon; - return; - } - if (emptySlot < 0 && m_playerMapIcons[i].name[0] == 0) - emptySlot = i; - } - if (emptySlot >= 0) - { - wcsncpy_s(m_playerMapIcons[emptySlot].name, 32, name, _TRUNCATE); - m_playerMapIcons[emptySlot].icon = icon; - } -} - -char CMinecraftApp::GetPlayerMapIconByName(const wchar_t* name) -{ - if (name == nullptr) return 0; - for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) - { - if (m_playerMapIcons[i].name[0] != 0 && _wcsicmp(m_playerMapIcons[i].name, name) == 0) - return m_playerMapIcons[i].icon; - } - return 0; -} - - -unsigned int CMinecraftApp::GetPlayerPrivileges(BYTE networkSmallId) -{ - unsigned int privileges = 0; - for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) - { - if(m_playerColours[i]==networkSmallId) - { - privileges = m_playerGamePrivileges[i]; - break; - } - } - return privileges; -} - -wstring CMinecraftApp::getEntityName(eINSTANCEOF type) -{ - switch(type) - { - case eTYPE_WOLF: - return app.GetString(IDS_WOLF); - case eTYPE_CREEPER: - return app.GetString(IDS_CREEPER); - case eTYPE_SKELETON: - return app.GetString(IDS_SKELETON); - case eTYPE_SPIDER: - return app.GetString(IDS_SPIDER); - case eTYPE_ZOMBIE: - return app.GetString(IDS_ZOMBIE); - case eTYPE_PIGZOMBIE: - return app.GetString(IDS_PIGZOMBIE); - case eTYPE_ENDERMAN: - return app.GetString(IDS_ENDERMAN); - case eTYPE_SILVERFISH: - return app.GetString(IDS_SILVERFISH); - case eTYPE_CAVESPIDER: - return app.GetString(IDS_CAVE_SPIDER); - case eTYPE_GHAST: - return app.GetString(IDS_GHAST); - case eTYPE_SLIME: - return app.GetString(IDS_SLIME); - case eTYPE_ARROW: - return app.GetString(IDS_ITEM_ARROW); - case eTYPE_ENDERDRAGON: - return app.GetString(IDS_ENDERDRAGON); - case eTYPE_BLAZE: - return app.GetString(IDS_BLAZE); - case eTYPE_LAVASLIME: - return app.GetString(IDS_LAVA_SLIME); - // 4J-PB - fix for #107167 - Customer Encountered: TU12: Content: UI: There is no information what killed Player after being slain by Iron Golem. - case eTYPE_VILLAGERGOLEM: - return app.GetString(IDS_IRONGOLEM); - case eTYPE_HORSE: - return app.GetString(IDS_HORSE); - case eTYPE_WITCH: - return app.GetString(IDS_WITCH); - case eTYPE_WITHERBOSS: - return app.GetString(IDS_WITHER); - case eTYPE_BAT: - return app.GetString(IDS_BAT); - case eTYPE_RABBIT: - return app.GetString(IDS_RABBIT); - - }; - - return L""; -} - -DWORD CMinecraftApp::m_dwContentTypeA[e_Marketplace_MAX]= -{ - XMARKETPLACE_OFFERING_TYPE_CONTENT, // e_DLC_SkinPack, e_DLC_TexturePacks, e_DLC_MashupPacks -#ifndef _XBOX_ONE - XMARKETPLACE_OFFERING_TYPE_THEME, // e_DLC_Themes - XMARKETPLACE_OFFERING_TYPE_AVATARITEM, // e_DLC_AvatarItems - XMARKETPLACE_OFFERING_TYPE_TILE, // e_DLC_Gamerpics -#endif -}; - -unsigned int CMinecraftApp::AddDLCRequest(eDLCMarketplaceType eType, bool bPromote) -{ - // lock access - EnterCriticalSection(&csDLCDownloadQueue); - - // If it's already in there, promote it to the top of the list - int iPosition=0; - for( DLCRequest *pCurrent : m_DLCDownloadQueue ) - { - if(pCurrent->dwType==m_dwContentTypeA[eType]) - { - // already got this in the list - if(pCurrent->eState == e_DLC_ContentState_Retrieving || pCurrent->eState == e_DLC_ContentState_Retrieved) - { - // already retrieved this - LeaveCriticalSection(&csDLCDownloadQueue); - return 0; - } - else - { - // promote - if(bPromote) - { - m_DLCDownloadQueue.erase(m_DLCDownloadQueue.begin()+iPosition); - m_DLCDownloadQueue.insert(m_DLCDownloadQueue.begin(),pCurrent); - } - LeaveCriticalSection(&csDLCDownloadQueue); - return 0; - } - } - iPosition++; - } - - DLCRequest *pDLCreq = new DLCRequest; - pDLCreq->dwType=m_dwContentTypeA[eType]; - pDLCreq->eState=e_DLC_ContentState_Idle; - - m_DLCDownloadQueue.push_back(pDLCreq); - - m_bAllDLCContentRetrieved=false; - LeaveCriticalSection(&csDLCDownloadQueue); - - app.DebugPrintf("[Consoles_App] Added DLC request.\n"); - return 1; -} - -unsigned int CMinecraftApp::AddTMSPPFileTypeRequest(eDLCContentType eType, bool bPromote) -{ -#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) - // lock access - EnterCriticalSection(&csTMSPPDownloadQueue); - - // If it's already in there, promote it to the top of the list - int iPosition=0; - //ignore promoting for now - /* - bool bPromoted=false; - - - for ( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue ) - { - TMSPPRequest *pCurrent = *it; - - if(pCurrent->eType==eType) - { - if(!(pCurrent->eState == e_TMS_ContentState_Retrieving || pCurrent->eState == e_TMS_ContentState_Retrieved)) - { - // promote - if(bPromote) - { - m_TMSPPDownloadQueue.erase(m_TMSPPDownloadQueue.begin()+iPosition); - m_TMSPPDownloadQueue.insert(m_TMSPPDownloadQueue.begin(),pCurrent); - bPromoted=true; - } - } - } - iPosition++; - } - - if(bPromoted) - { - // re-ordered the list, so leave now - LeaveCriticalSection(&csTMSPPDownloadQueue); - return 0; - } - */ - - // special case for data files (not image files) - if(eType==e_DLC_TexturePackData) - { - - - int iCount=GetDLCInfoFullOffersCount(); - - for(int i=0;ieDLCType==e_DLC_TexturePacks) || (pDLC->eDLCType==e_DLC_MashupPacks)) - { - // first check if the image is already in the memory textures, since we might be loading some from the Title Update partition - if(pDLC->wchDataFile[0]!=0) - { - //WCHAR *cString = pDLC->wchDataFile; - // 4J-PB - shouldn't check this here - let the TMS files override it, so if they are on TMS, we'll take them first - //int iIndex = app.GetLocalTMSFileIndex(pDLC->wchDataFile,true); - - //if(iIndex!=-1) - { - bool bPresent = app.IsFileInTPD(pDLC->iConfig); - - if(!bPresent) - { - // this may already be present in the vector because of a previous trial/full offer - - bool bAlreadyInQueue=false; - for( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue ) - { - if(wcscmp(pDLC->wchDataFile,pCurrent->wchFilename)==0) - { - bAlreadyInQueue=true; - break; - } - } - - if(!bAlreadyInQueue) - { - TMSPPRequest *pTMSPPreq = new TMSPPRequest; - - pTMSPPreq->CallbackFunc=&CMinecraftApp::TMSPPFileReturned; - pTMSPPreq->lpCallbackParam=this; - pTMSPPreq->eStorageFacility=C4JStorage::eGlobalStorage_Title; - pTMSPPreq->eFileTypeVal=C4JStorage::TMS_FILETYPE_BINARY; - memcpy(pTMSPPreq->wchFilename,pDLC->wchDataFile,sizeof(WCHAR)*MAX_BANNERNAME_SIZE); - pTMSPPreq->eType=e_DLC_TexturePackData; - pTMSPPreq->eState=e_TMS_ContentState_Queued; - m_bAllTMSContentRetrieved=false; - m_TMSPPDownloadQueue.push_back(pTMSPPreq); - } - } - else - { - app.DebugPrintf("Texture data already present in the TPD\n"); - } - } - } - } - } - } - else - { // for all the files of type eType, add them to the download list - - // run through the trial offers first, then the full offers. Any duplicates won't be added to the download queue - int iCount; -#ifdef _XBOX // Only trial offers on Xbox 360 - iCount=GetDLCInfoTrialOffersCount(); - for(int i=0;ieDLCType==eType) - { - - WCHAR *cString = pDLC->wchBanner; - - // 4J-PB - shouldn't check this here - let the TMS files override it, so if they are on TMS, we'll take them first - // is the file in the TMS XZP? - //int iIndex = app.GetLocalTMSFileIndex(cString,true); - - //if(iIndex!=-1) - { - bool bPresent = app.IsFileInMemoryTextures(cString); - - if(!bPresent) // retrieve it from TMSPP - { - bool bAlreadyInQueue=false; - for( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue ) - { - if(wcscmp(pDLC->wchBanner,pCurrent->wchFilename)==0) - { - bAlreadyInQueue=true; - break; - } - } - - if(!bAlreadyInQueue) - { - TMSPPRequest *pTMSPPreq = new TMSPPRequest; - - pTMSPPreq->CallbackFunc=&CMinecraftApp::TMSPPFileReturned; - pTMSPPreq->lpCallbackParam=this; - pTMSPPreq->eStorageFacility=C4JStorage::eGlobalStorage_Title; - pTMSPPreq->eFileTypeVal=C4JStorage::TMS_FILETYPE_BINARY; - //wcstombs(pTMSPPreq->szFilename,pDLC->wchBanner,MAX_TMSFILENAME_SIZE); - memcpy(pTMSPPreq->wchFilename,pDLC->wchBanner,sizeof(WCHAR)*MAX_BANNERNAME_SIZE); - pTMSPPreq->eType=eType; - pTMSPPreq->eState=e_TMS_ContentState_Queued; - - m_bAllTMSContentRetrieved=false; - m_TMSPPDownloadQueue.push_back(pTMSPPreq); - app.DebugPrintf("===m_TMSPPDownloadQueue Adding %ls, q size is %d\n",pTMSPPreq->wchFilename,m_TMSPPDownloadQueue.size()); - } - } - } - } - } -#endif - // and the full offers - - iCount=GetDLCInfoFullOffersCount(); - for(int i=0;iwchType,wchDLCTypeNames[eType])==0) - if(pDLC->eDLCType==eType) - { - // first check if the image is already in the memory textures, since we might be loading some from the Title Update partition - - WCHAR *cString = pDLC->wchBanner; - // 4J-PB - shouldn't check this here - let the TMS files override it, so if they are on TMS, we'll take them first - //int iIndex = app.GetLocalTMSFileIndex(cString,true); - - //if(iIndex!=-1) - { - bool bPresent = app.IsFileInMemoryTextures(cString); - - if(!bPresent) - { - // this may already be present in the vector because of a previous trial/full offer - - bool bAlreadyInQueue=false; - for( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue ) - { - if(wcscmp(pDLC->wchBanner,pCurrent->wchFilename)==0) - { - bAlreadyInQueue=true; - break; - } - } - - if(!bAlreadyInQueue) - { - //app.DebugPrintf("Adding a request to the TMSPP download queue - %ls\n",pDLC->wchBanner); - TMSPPRequest *pTMSPPreq = new TMSPPRequest; - ZeroMemory(pTMSPPreq,sizeof(TMSPPRequest)); - - pTMSPPreq->CallbackFunc=&CMinecraftApp::TMSPPFileReturned; - pTMSPPreq->lpCallbackParam=this; - // 4J-PB - testing for now - //pTMSPPreq->eStorageFacility=C4JStorage::eGlobalStorage_TitleUser; - pTMSPPreq->eStorageFacility=C4JStorage::eGlobalStorage_Title; - pTMSPPreq->eFileTypeVal=C4JStorage::TMS_FILETYPE_BINARY; - //wcstombs(pTMSPPreq->szFilename,pDLC->wchBanner,MAX_TMSFILENAME_SIZE); - - memcpy(pTMSPPreq->wchFilename,pDLC->wchBanner,sizeof(WCHAR)*MAX_BANNERNAME_SIZE); - pTMSPPreq->eType=eType; - pTMSPPreq->eState=e_TMS_ContentState_Queued; - m_bAllTMSContentRetrieved=false; - m_TMSPPDownloadQueue.push_back(pTMSPPreq); - app.DebugPrintf("===m_TMSPPDownloadQueue Adding %ls, q size is %d\n",pTMSPPreq->wchFilename,m_TMSPPDownloadQueue.size()); - } - } - } - } - } - } - - LeaveCriticalSection(&csTMSPPDownloadQueue); -#endif - return 1; -} - -bool CMinecraftApp::CheckTMSDLCCanStop() -{ - EnterCriticalSection(&csTMSPPDownloadQueue); - for( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue ) - { - if(pCurrent->eState==e_TMS_ContentState_Retrieving) - { - LeaveCriticalSection(&csTMSPPDownloadQueue); - return false; - } - } - LeaveCriticalSection(&csTMSPPDownloadQueue); - - return true; -} - - -bool CMinecraftApp::RetrieveNextDLCContent() -{ - // If there's already a retrieve in progress, quit - // we may have re-ordered the list, so need to check every item - - // is there a primary player and a network connection? - int primPad = ProfileManager.GetPrimaryPad(); - if ( primPad == -1 || !ProfileManager.IsSignedInLive(primPad) ) - { - return true; // 4J-JEV: We need to wait until the primary player is online. - } - - EnterCriticalSection(&csDLCDownloadQueue); - for( const DLCRequest* pCurrent : m_DLCDownloadQueue ) - { - if(pCurrent->eState==e_DLC_ContentState_Retrieving) - { - LeaveCriticalSection(&csDLCDownloadQueue); - return true; - } - } - - // Now look for the next retrieval - for( DLCRequest *pCurrent : m_DLCDownloadQueue ) - { - if(pCurrent->eState==e_DLC_ContentState_Idle) - { -#ifdef _DEBUG - app.DebugPrintf("RetrieveNextDLCContent - type = %d\n",pCurrent->dwType); -#endif - - C4JStorage::EDLCStatus status = StorageManager.GetDLCOffers(ProfileManager.GetPrimaryPad(), &CMinecraftApp::DLCOffersReturned, this, pCurrent->dwType); - if(status==C4JStorage::EDLC_Pending) - { - pCurrent->eState=e_DLC_ContentState_Retrieving; - } - else - { - // no content of this type, or some other problem - app.DebugPrintf("RetrieveNextDLCContent - PROBLEM\n"); - pCurrent->eState=e_DLC_ContentState_Retrieved; - } - LeaveCriticalSection(&csDLCDownloadQueue); - return true; - } - } - LeaveCriticalSection(&csDLCDownloadQueue); - - app.DebugPrintf("[Consoles_App] Finished downloading dlc content.\n"); - return false; -} - -#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) -#ifdef _XBOX_ONE -int CMinecraftApp::TMSPPFileReturned(LPVOID pParam,int iPad,int iUserData,LPVOID lpvData, WCHAR* wchFilename) -{ - C4JStorage::PTMSPP_FILEDATA pFileData=(C4JStorage::PTMSPP_FILEDATA)lpvData; -#else -int CMinecraftApp::TMSPPFileReturned(LPVOID pParam,int iPad,int iUserData,C4JStorage::PTMSPP_FILEDATA pFileData, LPCSTR szFilename) -{ -#endif - - CMinecraftApp* pClass = static_cast(pParam); - - // find the right one in the vector - EnterCriticalSection(&pClass->csTMSPPDownloadQueue); - for( TMSPPRequest *pCurrent : pClass->m_TMSPPDownloadQueue ) - { -#if defined(_XBOX) || defined(_WINDOWS64) - char szFile[MAX_TMSFILENAME_SIZE]; - wcstombs(szFile,pCurrent->wchFilename,MAX_TMSFILENAME_SIZE); - - - if(strcmp(szFilename,szFile)==0) -#elif _XBOX_ONE - if(wcscmp(wchFilename,pCurrent->wchFilename)==0) -#endif - { - // set this to retrieved whether it found it or not - pCurrent->eState=e_TMS_ContentState_Retrieved; - - if(pFileData!=nullptr) - { -#ifdef _XBOX_ONE - - - switch(pCurrent->eType) - { - case e_DLC_TexturePackData: - { - // 4J-PB - we need to allocate memory for the file data and copy into it, since the current data is a reference into the blob download memory - PBYTE pbData = new BYTE [pFileData->dwSize]; - memcpy(pbData,pFileData->pbData,pFileData->dwSize); - - pClass->m_vTMSPPData.push_back(pbData); - app.DebugPrintf("Got texturepack data\n"); - // get the config value for the texture pack - int iConfig=app.GetTPConfigVal(pCurrent->wchFilename); - app.AddMemoryTPDFile(iConfig, pbData, pFileData->dwSize); - } - break; - default: - // 4J-PB - check the data is an image - if(pFileData->pbData[0]==0x89) - { - // 4J-PB - we need to allocate memory for the file data and copy into it, since the current data is a reference into the blob download memory - PBYTE pbData = new BYTE [pFileData->dwSize]; - memcpy(pbData,pFileData->pbData,pFileData->dwSize); - - pClass->m_vTMSPPData.push_back(pbData); - app.DebugPrintf("Got image data - %ls\n",pCurrent->wchFilename); - app.AddMemoryTextureFile(pCurrent->wchFilename, pbData, pFileData->dwSize); - } - else - { - app.DebugPrintf("Got image data, but it's not a png - %ls\n",pCurrent->wchFilename); - } - break; - } - -#else - switch(pCurrent->eType) - { - case e_DLC_TexturePackData: - { - app.DebugPrintf("--- Got texturepack data %ls\n",pCurrent->wchFilename); - // get the config value for the texture pack - int iConfig=app.GetTPConfigVal(pCurrent->wchFilename); - app.AddMemoryTPDFile(iConfig, pFileData->pbData, pFileData->dwSize); - } - break; - default: - app.DebugPrintf("--- Got image data - %ls\n",pCurrent->wchFilename); - app.AddMemoryTextureFile(pCurrent->wchFilename, pFileData->pbData, pFileData->dwSize); - break; - } -#endif - } - else - { -#ifdef _XBOX_ONE - app.DebugPrintf("TMSImageReturned failed (%ls)...\n",wchFilename); -#else - app.DebugPrintf("TMSImageReturned failed (%s)...\n",szFilename); -#endif - } - break; - } - - } - LeaveCriticalSection(&pClass->csTMSPPDownloadQueue); - - return 0; -} -#endif - -bool CMinecraftApp::RetrieveNextTMSPPContent() -{ -#if defined _XBOX || defined _XBOX_ONE - // If there's already a retrieve in progress, quit - // we may have re-ordered the list, so need to check every item - - // is there a primary player and a network connection? - if(ProfileManager.GetPrimaryPad()==-1) return false; - - if(ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad())==false) return false; - - for( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue ) - { - TMSPPRequest *pCurrent = *it; - - if(pCurrent->eState==e_TMS_ContentState_Retrieving) - { - app.DebugPrintf("."); - LeaveCriticalSection(&csTMSPPDownloadQueue); - return true; - } - } - - // Now look for the next retrieval - for( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue ) - { - TMSPPRequest *pCurrent = *it; - - if(pCurrent->eState==e_TMS_ContentState_Queued) - { - // 4J-PB - the file may be in the local TMS files, but try to retrieve it from the remote TMS in case it's been changed. If it's not in the list of TMS files, this will - // return right away with a ETMSStatus_Fail_ReadDetailsNotRetrieved -#ifdef _XBOX - char szFilename[MAX_TMSFILENAME_SIZE]; - wcstombs(szFilename,pCurrent->wchFilename,MAX_TMSFILENAME_SIZE); - - app.DebugPrintf("\nRetrieveNextTMSPPContent - type = %d, %s\n",pCurrent->eType,szFilename); - - C4JStorage::ETMSStatus status=StorageManager.TMSPP_ReadFile(ProfileManager.GetPrimaryPad(),pCurrent->eStorageFacility,pCurrent->eFileTypeVal,szFilename,pCurrent->CallbackFunc,this); - switch(status) - { - case C4JStorage::ETMSStatus_Pending: - pCurrent->eState=e_TMS_ContentState_Retrieving; - break; - case C4JStorage::ETMSStatus_Idle: - pCurrent->eState=e_TMS_ContentState_Retrieved; - break; - case C4JStorage::ETMSStatus_Fail_ReadInProgress: - case C4JStorage::ETMSStatus_ReadInProgress: - pCurrent->eState=e_TMS_ContentState_Retrieving; - if(pCurrent->eState==C4JStorage::ETMSStatus_Fail_ReadInProgress) - { - app.DebugPrintf("TMSPP_ReadFile failed - read in progress\n"); - Sleep(50); - LeaveCriticalSection(&csTMSPPDownloadQueue); - return false; - } - break; - default: - pCurrent->eState=e_TMS_ContentState_Retrieved; - break; - } -#else - eTitleStorageState status; - app.DebugPrintf("RetrieveNextTMSPPContent - type = %d, %ls\n",pCurrent->eType,pCurrent->wchFilename); - //eTitleStorageState status=StorageManager.TMSPP_ReadFile(ProfileManager.GetPrimaryPad(),pCurrent->eStorageFacility,pCurrent->eFileTypeVal,pCurrent->wchFilename,pCurrent->CallbackFunc,this,0); - if(0)//wcscmp(pCurrent->wchFilename,L"TP01.png")==0) - { - // TP01 fails because the blob size returned is bigger than the global metadata says it should be - status=eTitleStorage_readerror; - } - else - { - status=StorageManager.TMSPP_ReadFile(ProfileManager.GetPrimaryPad(),pCurrent->eStorageFacility,pCurrent->eFileTypeVal,pCurrent->wchFilename,pCurrent->CallbackFunc,this,0); - } - switch(status) - { - case eTitleStorage_pending: - pCurrent->eState=e_TMS_ContentState_Retrieving; - break; - case eTitleStorage_idle: - pCurrent->eState=e_TMS_ContentState_Retrieved; - break; - case eTitleStorage_busy: - // try again next time - { - app.DebugPrintf("@@@@@@@@@@@@@@@@@ TMSPP_ReadFile failed - busy (probably reading already)\n"); - Sleep(50); - LeaveCriticalSection(&csTMSPPDownloadQueue); - return false; - } - break; - default: - pCurrent->eState=e_TMS_ContentState_Retrieved; - break; - } -#endif - - - - LeaveCriticalSection(&csTMSPPDownloadQueue); - return true; - } - } - - LeaveCriticalSection(&csTMSPPDownloadQueue); - -#endif - return false; -} - -void CMinecraftApp::TickDLCOffersRetrieved() -{ - if(!m_bAllDLCContentRetrieved) - { - if (!app.RetrieveNextDLCContent()) - { - app.DebugPrintf("[Consoles_App] All content retrieved.\n"); - m_bAllDLCContentRetrieved=true; - } - } -} -void CMinecraftApp::ClearAndResetDLCDownloadQueue() -{ - app.DebugPrintf("[Consoles_App] Clear and reset download queue.\n"); - - int iPosition=0; - EnterCriticalSection(&csTMSPPDownloadQueue); - for( DLCRequest *pCurrent : m_DLCDownloadQueue ) - { - if ( pCurrent ) - delete pCurrent; - iPosition++; - } - m_DLCDownloadQueue.clear(); - m_bAllDLCContentRetrieved=true; - LeaveCriticalSection(&csTMSPPDownloadQueue); -} - -void CMinecraftApp::TickTMSPPFilesRetrieved() -{ - if(m_bTickTMSDLCFiles && !m_bAllTMSContentRetrieved) - { - if(app.RetrieveNextTMSPPContent()==false) - { - m_bAllTMSContentRetrieved=true; - } - } -} -void CMinecraftApp::ClearTMSPPFilesRetrieved() -{ - int iPosition=0; - EnterCriticalSection(&csTMSPPDownloadQueue); - for ( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue ) - { - if ( pCurrent ) - delete pCurrent; - iPosition++; - } - m_TMSPPDownloadQueue.clear(); - m_bAllTMSContentRetrieved=true; - LeaveCriticalSection(&csTMSPPDownloadQueue); -} - -int CMinecraftApp::DLCOffersReturned(void *pParam, int iOfferC, DWORD dwType, int iPad) -{ - CMinecraftApp* pClass = static_cast(pParam); - - // find the right one in the vector - EnterCriticalSection(&pClass->csTMSPPDownloadQueue); - for( DLCRequest *pCurrent : pClass->m_DLCDownloadQueue ) - { - // avatar items are coming back as type Content, so we can't trust the type setting - if(pCurrent->dwType==dwType) - { - pClass->m_iDLCOfferC = iOfferC; - app.DebugPrintf("DLCOffersReturned - type %d, count %d - setting to retrieved\n",dwType,iOfferC); - pCurrent->eState=e_DLC_ContentState_Retrieved; - break; - } - } - LeaveCriticalSection(&pClass->csTMSPPDownloadQueue); - return 0; -} - -eDLCContentType CMinecraftApp::Find_eDLCContentType(DWORD dwType) -{ - for(int i=0;i(i); - } - } - return static_cast(0); -} -bool CMinecraftApp::DLCContentRetrieved(eDLCMarketplaceType eType) -{ - // If there's already a retrieve in progress, quit - // we may have re-ordered the list, so need to check every item - EnterCriticalSection(&csDLCDownloadQueue); - for( DLCRequest *pCurrent : m_DLCDownloadQueue ) - { - if((pCurrent->dwType==m_dwContentTypeA[eType]) && (pCurrent->eState==e_DLC_ContentState_Retrieved)) - { - LeaveCriticalSection(&csDLCDownloadQueue); - return true; - } - } - LeaveCriticalSection(&csDLCDownloadQueue); - return false; -} - -void CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, SKIN_BOX *SkinBoxA, DWORD dwSkinBoxC) -{ - EntityRenderDispatcher *dispatcher = EntityRenderDispatcher::instance; - EntityRenderer *renderer = dispatcher ? dispatcher->getRenderer(eTYPE_PLAYER) : nullptr; - Model *pModel = renderer ? renderer->getModel() : nullptr; - vector *pvModelPart = new vector; - vector *pvSkinBoxes = new vector; - - EnterCriticalSection( &csAdditionalModelParts ); - EnterCriticalSection( &csAdditionalSkinBoxes ); - - app.DebugPrintf("*** SetAdditionalSkinBoxes - Inserting model parts for skin %d from array of Skin Boxes\n",dwSkinID&0x0FFFFFFF); - - // convert the skin boxes into model parts, and add to the humanoid model - for(unsigned int i=0;iAddOrRetrievePart(&SkinBoxA[i]); - pvModelPart->push_back(pModelPart); - pvSkinBoxes->push_back(&SkinBoxA[i]); - } - } - - - m_AdditionalModelParts.insert( std::pair *>(dwSkinID, pvModelPart) ); - m_AdditionalSkinBoxes.insert( std::pair *>(dwSkinID, pvSkinBoxes) ); - - LeaveCriticalSection( &csAdditionalSkinBoxes ); - LeaveCriticalSection( &csAdditionalModelParts ); - -} - -vector * CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, vector *pvSkinBoxA) -{ - EntityRenderDispatcher *dispatcher = EntityRenderDispatcher::instance; - EntityRenderer *renderer = dispatcher ? dispatcher->getRenderer(eTYPE_PLAYER) : nullptr; - Model *pModel = renderer ? renderer->getModel() : nullptr; - vector *pvModelPart = new vector; - - EnterCriticalSection( &csAdditionalModelParts ); - EnterCriticalSection( &csAdditionalSkinBoxes ); - app.DebugPrintf("*** SetAdditionalSkinBoxes - Inserting model parts for skin %d from array of Skin Boxes\n",dwSkinID&0x0FFFFFFF); - - // convert the skin boxes into model parts, and add to the humanoid model - for( auto& it : *pvSkinBoxA ) - { - if(pModel) - { - ModelPart *pModelPart=pModel->AddOrRetrievePart(it); - pvModelPart->push_back(pModelPart); - } - } - - m_AdditionalModelParts.emplace(dwSkinID, pvModelPart); - m_AdditionalSkinBoxes.emplace(dwSkinID, pvSkinBoxA); - - LeaveCriticalSection( &csAdditionalSkinBoxes ); - LeaveCriticalSection( &csAdditionalModelParts ); - return pvModelPart; -} - - -vector *CMinecraftApp::GetAdditionalModelParts(DWORD dwSkinID) -{ - EnterCriticalSection( &csAdditionalModelParts ); - vector *pvModelParts=nullptr; - if(m_AdditionalModelParts.size()>0) - { - auto it = m_AdditionalModelParts.find(dwSkinID); - if(it!=m_AdditionalModelParts.end()) - { - pvModelParts = (*it).second; - } - } - - LeaveCriticalSection( &csAdditionalModelParts ); - return pvModelParts; -} - -vector *CMinecraftApp::GetAdditionalSkinBoxes(DWORD dwSkinID) -{ - EnterCriticalSection( &csAdditionalSkinBoxes ); - vector *pvSkinBoxes=nullptr; - if(m_AdditionalSkinBoxes.size()>0) - { - auto it = m_AdditionalSkinBoxes.find(dwSkinID); - if(it!=m_AdditionalSkinBoxes.end()) - { - pvSkinBoxes = (*it).second; - } - } - - LeaveCriticalSection( &csAdditionalSkinBoxes ); - return pvSkinBoxes; -} - -unsigned int CMinecraftApp::GetAnimOverrideBitmask(DWORD dwSkinID) -{ - EnterCriticalSection( &csAnimOverrideBitmask ); - unsigned int uiAnimOverrideBitmask=0L; - - if(m_AnimOverrides.size()>0) - { - auto it = m_AnimOverrides.find(dwSkinID); - if(it!=m_AnimOverrides.end()) - { - uiAnimOverrideBitmask = (*it).second; - } - } - - LeaveCriticalSection( &csAnimOverrideBitmask ); - return uiAnimOverrideBitmask; -} - -void CMinecraftApp::SetAnimOverrideBitmask(DWORD dwSkinID,unsigned int uiAnimOverrideBitmask) -{ - // Make thread safe - EnterCriticalSection( &csAnimOverrideBitmask ); - - if(m_AnimOverrides.size()>0) - { - auto it = m_AnimOverrides.find(dwSkinID); - if(it!=m_AnimOverrides.end()) - { - LeaveCriticalSection( &csAnimOverrideBitmask ); - return; // already in here - } - } - m_AnimOverrides.insert( std::pair(dwSkinID, uiAnimOverrideBitmask) ); - LeaveCriticalSection( &csAnimOverrideBitmask ); -} - -DWORD CMinecraftApp::getSkinIdFromPath(const wstring &skin) -{ - bool dlcSkin = false; - unsigned int skinId = 0; - - if(skin.size() >= 14) - { - dlcSkin = skin.substr(0,3).compare(L"dlc") == 0; - - wstring skinValue = skin.substr(7,skin.size()); - skinValue = skinValue.substr(0,skinValue.find_first_of(L'.')); - - std::wstringstream ss; - // 4J Stu - dlc skins are numbered using decimal to make it easier for artists/people to number manually - // Everything else is numbered using hex - if(dlcSkin) - ss << std::dec << skinValue.c_str(); - else - ss << std::hex << skinValue.c_str(); - ss >> skinId; - - skinId = MAKE_SKIN_BITMASK(dlcSkin, skinId); - } - return skinId; -} - -wstring CMinecraftApp::getSkinPathFromId(DWORD skinId) -{ - // 4J Stu - This function maps the encoded DWORD we store in the player profile - // to a filename that is stored as a memory texture and shared between systems in game - wchar_t chars[256]; - if( GET_IS_DLC_SKIN_FROM_BITMASK(skinId) ) - { - // 4J Stu - DLC skins are numbered using decimal rather than hex to make it easier to number manually - swprintf(chars, 256, L"dlcskin%08d.png", GET_DLC_SKIN_ID_FROM_BITMASK(skinId)); - - } - else - { - DWORD ugcSkinIndex = GET_UGC_SKIN_ID_FROM_BITMASK(skinId); - DWORD defaultSkinIndex = GET_DEFAULT_SKIN_ID_FROM_BITMASK(skinId); - if( ugcSkinIndex == 0 ) - { - swprintf(chars, 256, L"defskin%08X.png",defaultSkinIndex); - } - else - { - swprintf(chars, 256, L"ugcskin%08X.png",ugcSkinIndex); - } - } - return chars; -} - - -int CMinecraftApp::TexturePackDialogReturned(void* pParam, int iPad, C4JStorage::EMessageResult result) -{ - -#if defined __PSVITA__ || defined __PS3__ || defined __ORBIS__ - if (result == C4JStorage::EMessage_ResultAccept) - { - Minecraft* pMinecraft = Minecraft::GetInstance(); - if (pMinecraft->skins->selectTexturePackById(app.GetRequiredTexturePackID())) - { - // it's been installed already - } - else - { - // we need to enable background downloading for the DLC - XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW); - - SONYDLC* pSONYDLCInfo = app.GetSONYDLCInfo(app.GetRequiredTexturePackID()); - if (pSONYDLCInfo != nullptr) - { - char chName[42]; - char chKeyName[20]; - char chSkuID[SCE_NP_COMMERCE2_SKU_ID_LEN]; - - memset(chSkuID, 0, SCE_NP_COMMERCE2_SKU_ID_LEN); - - memset(chKeyName, 0, sizeof(chKeyName)); - strncpy(chKeyName, pSONYDLCInfo->chDLCKeyname, 16); - - #ifdef __ORBIS__ - strcpy(chName, chKeyName); - #else - sprintf(chName, "%s-%s", app.GetCommerceCategory(), chKeyName); - #endif - - app.GetDLCSkuIDFromProductList(chName, chSkuID); - - if (app.CheckForEmptyStore(iPad) == false) - { - if (app.DLCAlreadyPurchased(chSkuID)) - { - app.DownloadAlreadyPurchased(chSkuID); - } - else - { - app.Checkout(chSkuID); - } - } - } - } - } - else - { - app.DebugPrintf("Continuing without installing texture pack\n"); - } -#endif - -#ifdef _XBOX - if (result != C4JStorage::EMessage_Cancelled) - { - if (app.GetRequiredTexturePackID() != 0) - { - XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW); - - ULONGLONG ullOfferID_Full; - ULONGLONG ullIndexA[1]; - app.GetDLCFullOfferIDForPackID(app.GetRequiredTexturePackID(), &ullOfferID_Full); - - if (result == C4JStorage::EMessage_ResultAccept) - { - ullIndexA[0] = ullOfferID_Full; - StorageManager.InstallOffer(1, ullIndexA, nullptr, nullptr); - } - else - { - DLC_INFO* pDLCInfo = app.GetDLCInfoForFullOfferID(ullOfferID_Full); - ullIndexA[0] = pDLCInfo->ullOfferID_Trial; - StorageManager.InstallOffer(1, ullIndexA, nullptr, nullptr); - } - } - } -#endif - return 0; -} -int CMinecraftApp::getArchiveFileSize(const wstring &filename) -{ - TexturePack *tPack = nullptr; - Minecraft *pMinecraft = Minecraft::GetInstance(); - if(pMinecraft && pMinecraft->skins) tPack = pMinecraft->skins->getSelected(); - if(tPack && tPack->hasData() && tPack->getArchiveFile() && tPack->getArchiveFile()->hasFile(filename)) - { - return tPack->getArchiveFile()->getFileSize(filename); - } - else return m_mediaArchive->getFileSize(filename); -} - -bool CMinecraftApp::hasArchiveFile(const wstring &filename) -{ - TexturePack *tPack = nullptr; - Minecraft *pMinecraft = Minecraft::GetInstance(); - if(pMinecraft && pMinecraft->skins) tPack = pMinecraft->skins->getSelected(); - if(tPack && tPack->hasData() && tPack->getArchiveFile() && tPack->getArchiveFile()->hasFile(filename)) return true; - else return m_mediaArchive->hasFile(filename); -} - -byteArray CMinecraftApp::getArchiveFile(const wstring &filename) -{ - TexturePack *tPack = nullptr; - Minecraft *pMinecraft = Minecraft::GetInstance(); - if(pMinecraft && pMinecraft->skins) tPack = pMinecraft->skins->getSelected(); - if(tPack && tPack->hasData() && tPack->getArchiveFile() && tPack->getArchiveFile()->hasFile(filename)) - { - return tPack->getArchiveFile()->getFile(filename); - } - else return m_mediaArchive->getFile(filename); -} - -// DLC - -#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) -int CMinecraftApp::GetDLCInfoCount() -{ - return (int)DLCInfo.size(); -} -#elif defined _XBOX_ONE -int CMinecraftApp::GetDLCInfoTrialOffersCount() -{ - return 0; -} - -int CMinecraftApp::GetDLCInfoFullOffersCount() -{ - return (int)DLCInfo_Full.size(); -} -#else -int CMinecraftApp::GetDLCInfoTrialOffersCount() -{ - return static_cast(DLCInfo_Trial.size()); -} - -int CMinecraftApp::GetDLCInfoFullOffersCount() -{ - return static_cast(DLCInfo_Full.size()); -} -#endif - -int CMinecraftApp::GetDLCInfoTexturesOffersCount() -{ - return static_cast(DLCTextures_PackID.size()); -} - -// AUTOSAVE -void CMinecraftApp::SetAutosaveTimerTime(void) -{ -#if defined(_XBOX_ONE) || defined(__ORBIS__) - m_uiAutosaveTimer= GetTickCount()+1000*60; -#else - m_uiAutosaveTimer= GetTickCount()+GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_Autosave)*1000*60*15; -#endif -}// value x 15 to get mins, x60 for secs - -bool CMinecraftApp::AutosaveDue(void) -{ - return (GetTickCount()>m_uiAutosaveTimer); -} - -unsigned int CMinecraftApp::SecondsToAutosave() -{ - return (m_uiAutosaveTimer - GetTickCount() ) / 1000; -} - -void CMinecraftApp::SetTrialTimerStart(void) -{ - m_fTrialTimerStart=m_Time.fAppTime; mfTrialPausedTime=0.0f; -} - -float CMinecraftApp::getTrialTimer(void) -{ - return m_Time.fAppTime-m_fTrialTimerStart-mfTrialPausedTime; -} - -bool CMinecraftApp::IsLocalMultiplayerAvailable() -{ - DWORD connectedControllers = 0; - for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) - { - if( InputManager.IsPadConnected(i) || ProfileManager.IsSignedIn(i) ) ++connectedControllers; - } - -#ifdef _WINDOWS64 - bool available = connectedControllers > 1; -#else - bool available = RenderManager.IsHiDef() && connectedControllers > 1; -#endif - -#ifdef __ORBIS__ - // Check for remote play - available = available && InputManager.IsLocalMultiplayerAvailable(); -#endif - - return available; - - // Found this in GameNetworkManager? - //#ifdef _DURANGO - // iOtherConnectedControllers = InputManager.GetConnectedGamepadCount(); - // if((InputManager.IsPadConnected(userIndex) || ProfileManager.IsSignedIn(userIndex))) - // { - // --iOtherConnectedControllers; - // } - //#else - // for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) - // { - // if( (i!=userIndex) && (InputManager.IsPadConnected(i) || ProfileManager.IsSignedIn(i)) ) - // { - // iOtherConnectedControllers++; - // } - // } - //#endif -} - - -// 4J-PB - language and locale function - -void CMinecraftApp::getLocale(vector &vecWstrLocales) -{ - vector locales; - - DWORD dwSystemLanguage = XGetLanguage( ); - - // 4J-PB - restrict the 360 language until we're ready to have them in - -#ifdef _XBOX - switch(dwSystemLanguage) - { - case XC_LANGUAGE_FRENCH : - locales.push_back(eMCLang_frFR); - break; - case XC_LANGUAGE_ITALIAN : - locales.push_back(eMCLang_itIT); - break; - case XC_LANGUAGE_GERMAN : - locales.push_back(eMCLang_deDE); - break; - case XC_LANGUAGE_SPANISH : - locales.push_back(eMCLang_esES); - break; - case XC_LANGUAGE_PORTUGUESE : - if(XGetLocale()==XC_LOCALE_BRAZIL) - { - locales.push_back(eMCLang_ptBR); - } - locales.push_back(eMCLang_ptPT); - break; - case XC_LANGUAGE_JAPANESE : - locales.push_back(eMCLang_jaJP); - break; - case XC_LANGUAGE_KOREAN : - locales.push_back(eMCLang_koKR); - break; - case XC_LANGUAGE_TCHINESE : - locales.push_back(eMCLang_zhCHT); - break; - } -#else - switch(dwSystemLanguage) - { - - case XC_LANGUAGE_ENGLISH: - switch(XGetLocale()) - { - case XC_LOCALE_AUSTRALIA: - case XC_LOCALE_CANADA: - case XC_LOCALE_CZECH_REPUBLIC: - case XC_LOCALE_GREECE: - case XC_LOCALE_HONG_KONG: - case XC_LOCALE_HUNGARY: - case XC_LOCALE_INDIA: - case XC_LOCALE_IRELAND: - case XC_LOCALE_ISRAEL: - case XC_LOCALE_NEW_ZEALAND: - case XC_LOCALE_SAUDI_ARABIA: - case XC_LOCALE_SINGAPORE: - case XC_LOCALE_SLOVAK_REPUBLIC: - case XC_LOCALE_SOUTH_AFRICA: - case XC_LOCALE_UNITED_ARAB_EMIRATES: - case XC_LOCALE_GREAT_BRITAIN: - locales.push_back(eMCLang_enGB); - break; - default: //XC_LOCALE_UNITED_STATES - break; - } - break; - case XC_LANGUAGE_JAPANESE : - locales.push_back(eMCLang_jaJP); - break; - case XC_LANGUAGE_GERMAN : - switch(XGetLocale()) - { - case XC_LOCALE_AUSTRIA: - locales.push_back(eMCLang_deAT); - break; - case XC_LOCALE_SWITZERLAND: - locales.push_back(eMCLang_deCH); - break; - default:// XC_LOCALE_GERMANY: - break; - } - locales.push_back(eMCLang_deDE); - break; - case XC_LANGUAGE_FRENCH : - switch(XGetLocale()) - { - case XC_LOCALE_BELGIUM: - locales.push_back(eMCLang_frBE); - break; - case XC_LOCALE_CANADA: - locales.push_back(eMCLang_frCA); - break; - case XC_LOCALE_SWITZERLAND: - locales.push_back(eMCLang_frCH); - break; - default:// XC_LOCALE_FRANCE: - break; - } - locales.push_back(eMCLang_frFR); - break; - case XC_LANGUAGE_SPANISH : - switch(XGetLocale()) - { - case XC_LOCALE_MEXICO: - case XC_LOCALE_ARGENTINA: - case XC_LOCALE_CHILE: - case XC_LOCALE_COLOMBIA: - case XC_LOCALE_UNITED_STATES: - case XC_LOCALE_LATIN_AMERICA: - locales.push_back(eMCLang_laLAS); - locales.push_back(eMCLang_esMX); - break; - default://XC_LOCALE_SPAIN - break; - } - locales.push_back(eMCLang_esES); - break; - case XC_LANGUAGE_ITALIAN : - locales.push_back(eMCLang_itIT); - break; - case XC_LANGUAGE_KOREAN : - locales.push_back(eMCLang_koKR); - break; - case XC_LANGUAGE_TCHINESE : - switch(XGetLocale()) - { - case XC_LOCALE_HONG_KONG: - locales.push_back(eMCLang_zhHK); - locales.push_back(eMCLang_zhTW); - break; - case XC_LOCALE_TAIWAN: - locales.push_back(eMCLang_zhTW); - locales.push_back(eMCLang_zhHK); - default: - break; - } - locales.push_back(eMCLang_hant); - locales.push_back(eMCLang_zhCHT); - break; - case XC_LANGUAGE_PORTUGUESE : - if(XGetLocale()==XC_LOCALE_BRAZIL) - { - locales.push_back(eMCLang_ptBR); - } - locales.push_back(eMCLang_ptPT); - break; - case XC_LANGUAGE_POLISH : - locales.push_back(eMCLang_plPL); - break; - case XC_LANGUAGE_RUSSIAN : - locales.push_back(eMCLang_ruRU); - break; - case XC_LANGUAGE_SWEDISH : - locales.push_back(eMCLang_svSV); - locales.push_back(eMCLang_svSE); - break; - case XC_LANGUAGE_TURKISH : - locales.push_back(eMCLang_trTR); - break; - case XC_LANGUAGE_BNORWEGIAN : - locales.push_back(eMCLang_nbNO); - locales.push_back(eMCLang_noNO); - locales.push_back(eMCLang_nnNO); - break; - case XC_LANGUAGE_DUTCH : - switch(XGetLocale()) - { - case XC_LOCALE_BELGIUM: - locales.push_back(eMCLang_nlBE); - break; - default: - break; - } - locales.push_back(eMCLang_nlNL); - break; - case XC_LANGUAGE_SCHINESE : - switch(XGetLocale()) - { - case XC_LOCALE_SINGAPORE: - locales.push_back(eMCLang_zhSG); - break; - default: - break; - } - locales.push_back(eMCLang_hans); - locales.push_back(eMCLang_csCS); - locales.push_back(eMCLang_zhCN); - break; - -#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ || defined _DURANGO - case XC_LANGUAGE_DANISH: - locales.push_back(eMCLang_daDA); - locales.push_back(eMCLang_daDK); - break; - - case XC_LANGUAGE_FINISH : - locales.push_back(eMCLang_fiFI); - break; - - case XC_LANGUAGE_CZECH : - locales.push_back(eMCLang_csCZ); - locales.push_back(eMCLang_enCZ); - break; - - case XC_LANGUAGE_SLOVAK : - locales.push_back(eMCLang_skSK); - locales.push_back(eMCLang_enSK); - break; - - case XC_LANGUAGE_GREEK : - locales.push_back(eMCLang_elEL); - locales.push_back(eMCLang_elGR); - locales.push_back(eMCLang_enGR); - locales.push_back(eMCLang_enGB); - break; -#endif - } -#endif - - locales.push_back(eMCLang_enUS); - locales.push_back(eMCLang_null); - - for (size_t i=0; i +#endif +#ifdef __ORBIS__ +#include +#endif + +#include "../Common/Leaderboards/LeaderboardManager.h" +#include + +//CMinecraftApp app; +unsigned int CMinecraftApp::m_uiLastSignInData = 0; + +const float CMinecraftApp::fSafeZoneX = 64.0f; // 5% of 1280 +const float CMinecraftApp::fSafeZoneY = 36.0f; // 5% of 720 + +int CMinecraftApp::s_iHTMLFontSizesA[eHTMLSize_COUNT] = +{ +#ifdef _XBOX + 14,12,14,24 +#else + //20,15,20,24 + 20,13,20,26 +#endif +}; + + +CMinecraftApp::CMinecraftApp() +{ + if(GAME_SETTINGS_PROFILE_DATA_BYTES != sizeof(GAME_SETTINGS)) + { + // 4J Stu - See comment for GAME_SETTINGS_PROFILE_DATA_BYTES in Xbox_App.h + DebugPrintf("WARNING: The size of the profile GAME_SETTINGS struct has changed, so all stat data is likely incorrect. Is: %d, Should be: %d\n",sizeof(GAME_SETTINGS),GAME_SETTINGS_PROFILE_DATA_BYTES); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + } + + for(int i=0;i; + } + + LocaleAndLanguageInit(); + +#ifdef _XBOX_ONE + m_hasReachedMainMenu = false; +#endif +} + + +void CMinecraftApp::GetSkinAdjustments(_SkinAdjustments* out, + unsigned int skinId) +{ + _SkinAdjustments adj; + + EnterCriticalSection(&csAdditionalSkinBoxes); + + if (!m_SkinAdjustmentsMap.empty()) + { + auto it = m_SkinAdjustmentsMap.find(skinId); + if (it != m_SkinAdjustmentsMap.end()) + adj = it->second; + } + + LeaveCriticalSection(&csAdditionalSkinBoxes); + + *out = adj; +} + +void CMinecraftApp::SetSkinAdjustments(unsigned int skinId, + const _SkinAdjustments& adj) +{ + EnterCriticalSection(&csAdditionalSkinBoxes); + + m_SkinAdjustmentsMap[skinId] = adj; + + LeaveCriticalSection(&csAdditionalSkinBoxes); +} + +void CMinecraftApp::DebugPrintf(const char *szFormat, ...) +{ + +#ifndef _FINAL_BUILD + va_list ap; + va_start(ap, szFormat); +#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD) + // Dedicated server routes client debug spew through ServerLogger so CLI output stays prompt-safe. + if (ServerRuntime::ServerLogManager::ShouldForwardClientDebugLogs()) + { + ServerRuntime::ServerLogManager::ForwardClientAppDebugLogV(szFormat, ap); + va_end(ap); + return; + } +#endif + char buf[1024]; + vsnprintf(buf, sizeof(buf), szFormat, ap); + va_end(ap); + OutputDebugStringA(buf); +#endif + +} + +void CMinecraftApp::DebugPrintf(int user, const char *szFormat, ...) +{ +#ifndef _FINAL_BUILD + if(user == USER_NONE) + return; + va_list ap; + va_start(ap, szFormat); +#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD) + // Dedicated server routes client debug spew through ServerLogger so CLI output stays prompt-safe. + if (ServerRuntime::ServerLogManager::ShouldForwardClientDebugLogs()) + { + ServerRuntime::ServerLogManager::ForwardClientUserDebugLogV(user, szFormat, ap); + va_end(ap); + return; + } +#endif + char buf[1024]; + vsnprintf(buf, sizeof(buf), szFormat, ap); + va_end(ap); +#ifdef __PS3__ + unsigned int writelen; + sys_tty_write(SYS_TTYP_USER1 + ( user - 1 ), buf, strlen(buf), &writelen ); +#elif defined __PSVITA__ + switch(user) + { + case 0: + { + SceUID tty2 = sceIoOpen("tty2:", SCE_O_WRONLY, 0); + if(tty2>=0) + { + std::string string1(buf); + sceIoWrite(tty2, string1.c_str(), string1.length()); + sceIoClose(tty2); + } + } + break; + case 1: + { + SceUID tty3 = sceIoOpen("tty3:", SCE_O_WRONLY, 0); + if(tty3>=0) + { + std::string string1(buf); + sceIoWrite(tty3, string1.c_str(), string1.length()); + sceIoClose(tty3); + } + } + break; + default: + OutputDebugStringA(buf); + break; + } +#else + OutputDebugStringA(buf); +#endif +#ifndef _XBOX + if(user == USER_UI) + { + ui.logDebugString(buf); + } +#endif +#endif +} + +namespace +{ +const wchar_t *ResolveStringKeyFromId(int iID) +{ +#ifdef _WINDOWS64 + switch(iID) + { + #include "StringIdLookup.generated.inc" + default: + return nullptr; + } +#else + (void)iID; + return nullptr; +#endif +} +} + +LPCWSTR CMinecraftApp::GetString(int iID) +{ + if(app.m_stringTable == nullptr) + { + const wchar_t *key = ResolveStringKeyFromId(iID); + return key != nullptr ? key : L""; + } + + LPCWSTR byIndex = app.m_stringTable->getString(iID); + if(byIndex != nullptr && byIndex[0] != L'\0') + { + return byIndex; + } + + const wchar_t *key = ResolveStringKeyFromId(iID); + if(key != nullptr) + { + LPCWSTR byKey = app.m_stringTable->getString(key); + if(byKey != nullptr && byKey[0] != L'\0') + { + return byKey; + } + + // Prefer visible fallback text instead of returning an empty string. + return key; + } + + return L""; +} + +LPCWSTR CMinecraftApp::GetString(const wchar_t *id) +{ + if(id == nullptr) + { + return L""; + } + + if(app.m_stringTable == nullptr) + { + return id; + } + + LPCWSTR byKey = app.m_stringTable->getString(id); + if(byKey != nullptr && byKey[0] != L'\0') + { + return byKey; + } + + return id; +} + +void CMinecraftApp::SetAction(int iPad, eXuiAction action, LPVOID param) +{ + if( ( m_eXuiAction[iPad] == eAppAction_ReloadTexturePack ) && ( action == eAppAction_EthernetDisconnected ) ) + { + app.DebugPrintf("Invalid change of App action for pad %d from %d to %d, ignoring\n", iPad, m_eXuiAction[iPad], action); + } + else if( ( m_eXuiAction[iPad] == eAppAction_ReloadTexturePack ) && ( action == eAppAction_ExitWorld ) ) + { + app.DebugPrintf("Invalid change of App action for pad %d from %d to %d, ignoring\n", iPad, m_eXuiAction[iPad], action); + } + else if(m_eXuiAction[iPad] == eAppAction_ExitWorldCapturedThumbnail && action != eAppAction_Idle) + { + app.DebugPrintf("Invalid change of App action for pad %d from %d to %d, ignoring\n", iPad, m_eXuiAction[iPad], action); + } + else + { + app.DebugPrintf("Changing App action for pad %d from %d to %d\n", iPad, m_eXuiAction[iPad], action); + m_eXuiAction[iPad]=action; + m_eXuiActionParam[iPad] = param; + } +} + +bool CMinecraftApp::IsAppPaused() +{ +#if defined(_XBOX_ONE) || defined(__ORBIS__) || defined(_WINDOWS64) + bool paused = m_bIsAppPaused; + EnterCriticalSection(&m_saveNotificationCriticalSection); + if( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 ) + { + paused |= m_saveNotificationDepth > 0; + } + LeaveCriticalSection(&m_saveNotificationCriticalSection); + return paused; +#else + return m_bIsAppPaused; +#endif +} + +void CMinecraftApp::SetAppPaused(bool val) +{ + m_bIsAppPaused = val; +} + +void CMinecraftApp::HandleButtonPresses() +{ + for(int i=0;i<4;i++) + { + HandleButtonPresses(i); + } +} + +void CMinecraftApp::HandleButtonPresses(int iPad) +{ + + // // test an update of the profile data + // void *pData=ProfileManager.GetGameDefinedProfileData(iPad); + // + // unsigned char *pchData= (unsigned char *)pData; + // int iCount=0; + // for(int i=0;i player,bool bNavigateBack) +{ + bool success = true; + + InventoryScreenInput* initData = new InventoryScreenInput(); + initData->player = player; + initData->bNavigateBack=bNavigateBack; + initData->iPad = iPad; + + if(app.GetLocalPlayerCount()>1) + { + initData->bSplitscreen=true; + success = ui.NavigateToScene(iPad,eUIScene_InventoryMenu,initData); + } + else + { + initData->bSplitscreen=false; + success = ui.NavigateToScene(iPad,eUIScene_InventoryMenu,initData); + } + + return success; +} + +bool CMinecraftApp::LoadCreativeMenu(int iPad,shared_ptr player,bool bNavigateBack) +{ + bool success = true; + + InventoryScreenInput* initData = new InventoryScreenInput(); + initData->player = player; + initData->bNavigateBack=bNavigateBack; + initData->iPad = iPad; + + if(app.GetLocalPlayerCount()>1) + { + initData->bSplitscreen=true; + success = ui.NavigateToScene(iPad,eUIScene_CreativeMenu,initData); + } + else + { + initData->bSplitscreen=false; + success = ui.NavigateToScene(iPad,eUIScene_CreativeMenu,initData); + } + + return success; +} + +bool CMinecraftApp::LoadCrafting2x2Menu(int iPad,shared_ptr player) +{ + bool success = true; + + CraftingPanelScreenInput* initData = new CraftingPanelScreenInput(); + initData->player = player; + initData->iContainerType=RECIPE_TYPE_2x2; + initData->iPad = iPad; + initData->x = 0; + initData->y = 0; + initData->z = 0; + + if(app.GetLocalPlayerCount()>1) + { + initData->bSplitscreen=true; + success = ui.NavigateToScene(iPad,eUIScene_Crafting2x2Menu, initData); + } + else + { + initData->bSplitscreen=false; + success = ui.NavigateToScene(iPad,eUIScene_Crafting2x2Menu, initData); + } + + return success; +} + +bool CMinecraftApp::LoadCrafting3x3Menu(int iPad,shared_ptr player, int x, int y, int z) +{ + bool success = true; + + CraftingPanelScreenInput* initData = new CraftingPanelScreenInput(); + initData->player = player; + initData->iContainerType=RECIPE_TYPE_3x3; + initData->iPad = iPad; + initData->x = x; + initData->y = y; + initData->z = z; + + if (app.GetLocalPlayerCount() > 1) + initData->bSplitscreen = true; + else + initData->bSplitscreen = false; + + if (app.GetGameSettings(iPad, eGameSetting_ClassicCrafting)) + success = ui.NavigateToScene(iPad, eUIScene_ClassicCraftingMenu, initData); + else + success = ui.NavigateToScene(iPad, eUIScene_Crafting3x3Menu, initData); + + return success; +} + +bool CMinecraftApp::LoadFireworksMenu(int iPad,shared_ptr player, int x, int y, int z) +{ + bool success = true; + + FireworksScreenInput* initData = new FireworksScreenInput(); + initData->player = player; + initData->iPad = iPad; + initData->x = x; + initData->y = y; + initData->z = z; + + if(app.GetLocalPlayerCount()>1) + { + initData->bSplitscreen=true; + success = ui.NavigateToScene(iPad,eUIScene_FireworksMenu, initData); + } + else + { + initData->bSplitscreen=false; + success = ui.NavigateToScene(iPad,eUIScene_FireworksMenu, initData); + } + + return success; +} + +bool CMinecraftApp::LoadEnchantingMenu(int iPad,shared_ptr inventory, int x, int y, int z, Level *level, const wstring &name) +{ + bool success = true; + + EnchantingScreenInput* initData = new EnchantingScreenInput(); + initData->inventory = inventory; + initData->level = level; + initData->x = x; + initData->y = y; + initData->z = z; + initData->iPad = iPad; + initData->name = name; + + if(app.GetLocalPlayerCount()>1) + { + initData->bSplitscreen=true; + success = ui.NavigateToScene(iPad,eUIScene_EnchantingMenu, initData); + } + else + { + initData->bSplitscreen=false; + success = ui.NavigateToScene(iPad,eUIScene_EnchantingMenu, initData); + } + + return success; +} + +bool CMinecraftApp::LoadFurnaceMenu(int iPad,shared_ptr inventory, shared_ptr furnace) +{ + bool success = true; + + FurnaceScreenInput* initData = new FurnaceScreenInput(); + + initData->furnace = furnace; + initData->inventory = inventory; + initData->iPad = iPad; + + // Load the scene. + if(app.GetLocalPlayerCount()>1) + { + initData->bSplitscreen=true; + success = ui.NavigateToScene(iPad,eUIScene_FurnaceMenu, initData); + } + else + { + initData->bSplitscreen=false; + success = ui.NavigateToScene(iPad,eUIScene_FurnaceMenu, initData); + } + + return success; +} + +bool CMinecraftApp::LoadBrewingStandMenu(int iPad,shared_ptr inventory, shared_ptr brewingStand) +{ + bool success = true; + + BrewingScreenInput* initData = new BrewingScreenInput(); + + initData->brewingStand = brewingStand; + initData->inventory = inventory; + initData->iPad = iPad; + + // Load the scene. + if(app.GetLocalPlayerCount()>1) + { + initData->bSplitscreen=true; + success = ui.NavigateToScene(iPad,eUIScene_BrewingStandMenu, initData); + } + else + { + initData->bSplitscreen=false; + success = ui.NavigateToScene(iPad,eUIScene_BrewingStandMenu, initData); + } + + return success; +} + + +bool CMinecraftApp::LoadContainerMenu(int iPad,shared_ptr inventory, shared_ptr container) +{ + bool success = true; + + ContainerScreenInput* initData = new ContainerScreenInput(); + + initData->inventory = inventory; + initData->container = container; + initData->iPad = iPad; + + // Load the scene. + if(app.GetLocalPlayerCount()>1) + { + initData->bSplitscreen=true; + + bool bLargeChest = (initData->container->getContainerSize() > 3*9)?true:false; + if(bLargeChest) + { + success = ui.NavigateToScene(iPad,eUIScene_LargeContainerMenu,initData); + } + else + { + success = ui.NavigateToScene(iPad,eUIScene_ContainerMenu,initData); + } + } + else + { + initData->bSplitscreen=false; + success = ui.NavigateToScene(iPad,eUIScene_ContainerMenu,initData); + } + + return success; +} + +bool CMinecraftApp::LoadTrapMenu(int iPad,shared_ptr inventory, shared_ptr trap) +{ + bool success = true; + + TrapScreenInput* initData = new TrapScreenInput(); + + initData->inventory = inventory; + initData->trap = trap; + initData->iPad = iPad; + + // Load the scene. + if(app.GetLocalPlayerCount()>1) + { + initData->bSplitscreen=true; + success = ui.NavigateToScene(iPad,eUIScene_DispenserMenu, initData); + } + else + { + initData->bSplitscreen=false; + success = ui.NavigateToScene(iPad,eUIScene_DispenserMenu, initData); + } + + return success; +} + +bool CMinecraftApp::LoadSignEntryMenu(int iPad,shared_ptr sign) +{ + bool success = true; + + SignEntryScreenInput* initData = new SignEntryScreenInput(); + + initData->sign = sign; + initData->iPad = iPad; + + success = ui.NavigateToScene(iPad,eUIScene_SignEntryMenu, initData); + + delete initData; + + return success; +} + +bool CMinecraftApp::LoadRepairingMenu(int iPad,shared_ptr inventory, Level *level, int x, int y, int z) +{ + bool success = true; + + AnvilScreenInput *initData = new AnvilScreenInput(); + initData->inventory = inventory; + initData->level = level; + initData->x = x; + initData->y = y; + initData->z = z; + initData->iPad = iPad; + if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true; + else initData->bSplitscreen=false; + + success = ui.NavigateToScene(iPad,eUIScene_AnvilMenu, initData); + + return success; +} + +bool CMinecraftApp::LoadTradingMenu(int iPad, shared_ptr inventory, shared_ptr trader, Level *level, const wstring &name) +{ + bool success = true; + + TradingScreenInput *initData = new TradingScreenInput(); + initData->inventory = inventory; + initData->trader = trader; + initData->level = level; + initData->iPad = iPad; + if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true; + else initData->bSplitscreen=false; + + success = ui.NavigateToScene(iPad,eUIScene_TradingMenu, initData); + + return success; +} + +bool CMinecraftApp::LoadHopperMenu(int iPad ,shared_ptr inventory, shared_ptr hopper) +{ + bool success = true; + + HopperScreenInput *initData = new HopperScreenInput(); + initData->inventory = inventory; + initData->hopper = hopper; + initData->iPad = iPad; + if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true; + else initData->bSplitscreen=false; + + success = ui.NavigateToScene(iPad,eUIScene_HopperMenu, initData); + + return success; +} + +bool CMinecraftApp::LoadHopperMenu(int iPad ,shared_ptr inventory, shared_ptr hopper) +{ + bool success = true; + + HopperScreenInput *initData = new HopperScreenInput(); + initData->inventory = inventory; + initData->hopper = dynamic_pointer_cast(hopper); + initData->iPad = iPad; + if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true; + else initData->bSplitscreen=false; + + success = ui.NavigateToScene(iPad,eUIScene_HopperMenu, initData); + + return success; +} + + +bool CMinecraftApp::LoadHorseMenu(int iPad ,shared_ptr inventory, shared_ptr container, shared_ptr horse) +{ + bool success = true; + + HorseScreenInput *initData = new HorseScreenInput(); + initData->inventory = inventory; + initData->container = container; + initData->horse = horse; + initData->iPad = iPad; + if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true; + else initData->bSplitscreen=false; + + success = ui.NavigateToScene(iPad,eUIScene_HorseMenu, initData); + + return success; +} + +bool CMinecraftApp::LoadBeaconMenu(int iPad ,shared_ptr inventory, shared_ptr beacon) +{ + bool success = true; + + BeaconScreenInput *initData = new BeaconScreenInput(); + initData->inventory = inventory; + initData->beacon = beacon; + initData->iPad = iPad; + if(app.GetLocalPlayerCount()>1) initData->bSplitscreen=true; + else initData->bSplitscreen=false; + + success = ui.NavigateToScene(iPad,eUIScene_BeaconMenu, initData); + + return success; +} + +bool CMinecraftApp::LoadWritingBookMenu(int iPad, shared_ptr instance, shared_ptr player, bool editable) +{ + bool success = true; + + WritingBookMenuParams* initData = new WritingBookMenuParams(); + initData->itemInstance = instance; + initData->player = player; + initData->iPad = iPad; + initData->isEditable = editable; + + success = ui.NavigateToScene(iPad, eUIScene_BookMenu, initData); + + return success; +} + +////////////////////////////////////////////// +// GAME SETTINGS +////////////////////////////////////////////// + +#ifdef _WINDOWS64 +static void Win64_GetSettingsPath(char *outPath, DWORD size) +{ + GetModuleFileNameA(nullptr, outPath, size); + char *lastSlash = strrchr(outPath, '\\'); + if (lastSlash) *(lastSlash + 1) = '\0'; + strncat_s(outPath, size, "settings.dat", _TRUNCATE); +} +static void Win64_SaveSettings(GAME_SETTINGS *gs) +{ + if (!gs) return; + char filePath[MAX_PATH] = {}; + Win64_GetSettingsPath(filePath, MAX_PATH); + FILE *f = nullptr; + if (fopen_s(&f, filePath, "wb") == 0 && f) + { + fwrite(gs, sizeof(GAME_SETTINGS), 1, f); + fclose(f); + } +} +static void Win64_LoadSettings(GAME_SETTINGS *gs) +{ + if (!gs) return; + char filePath[MAX_PATH] = {}; + Win64_GetSettingsPath(filePath, MAX_PATH); + FILE *f = nullptr; + if (fopen_s(&f, filePath, "rb") == 0 && f) + { + GAME_SETTINGS temp = {}; + if (fread(&temp, sizeof(GAME_SETTINGS), 1, f) == 1) + memcpy(gs, &temp, sizeof(GAME_SETTINGS)); + fclose(f); + } +} +#endif + +void CMinecraftApp::InitGameSettings() +{ + for(int i=0;i(ProfileManager.GetGameDefinedProfileData(i)); +#endif + // clear the flag to say the settings have changed + GameSettingsA[i]->bSettingsChanged=false; + + //SetDefaultGameSettings(i); - done on a callback from the profile manager + + // 4J-PB - adding in for Windows & PS3 to set the defaults for the joypad +#if defined _WINDOWS64// || defined __PSVITA__ + C_4JProfile::PROFILESETTINGS *pProfileSettings=ProfileManager.GetDashboardProfileSettings(i); + // clear this for now - it will come from reading the system values + memset(pProfileSettings,0,sizeof(C_4JProfile::PROFILESETTINGS)); + SetDefaultOptions(pProfileSettings,i); + Win64_LoadSettings(GameSettingsA[i]); +#ifndef MINECRAFT_SERVER_BUILD + ApplyGameSettingsChanged(i); +#endif +#elif defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__ + C4JStorage::PROFILESETTINGS *pProfileSettings=StorageManager.GetDashboardProfileSettings(i); + // 4J-PB - don't cause an options write to happen here + SetDefaultOptions(pProfileSettings,i,false); + +#endif + + Minecraft* minecraft = Minecraft::GetInstance(); + if (minecraft != nullptr && minecraft->stats[i] != nullptr) + { + minecraft->stats[i]->clear(); + minecraft->stats[i]->parse(GameSettingsA[i]); + } + } +} + +#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) +int CMinecraftApp::SetDefaultOptions(C4JStorage::PROFILESETTINGS *pSettings,const int iPad,bool bWriteProfile) +#else +int CMinecraftApp::SetDefaultOptions(C_4JProfile::PROFILESETTINGS *pSettings,const int iPad) +#endif +{ + SetGameSettings(iPad,eGameSetting_MusicVolume,DEFAULT_VOLUME_LEVEL); + SetGameSettings(iPad,eGameSetting_SoundFXVolume,DEFAULT_VOLUME_LEVEL); + SetGameSettings(iPad,eGameSetting_RenderDistance,16); + SetGameSettings(iPad,eGameSetting_Gamma,50); + SetGameSettings(iPad,eGameSetting_FOV,0); + + // 4J-PB - Don't reset the difficult level if we're in-game + if(Minecraft::GetInstance()->level==nullptr) + { + app.DebugPrintf("SetDefaultOptions - Difficulty = 1\n"); + SetGameSettings(iPad,eGameSetting_Difficulty,1); + } + SetGameSettings(iPad,eGameSetting_Sensitivity_InGame,100); + SetGameSettings(iPad,eGameSetting_ViewBob,1); + SetGameSettings(iPad,eGameSetting_ControlScheme,0); + SetGameSettings(iPad,eGameSetting_ControlInvertLook,(pSettings->iYAxisInversion!=0)?1:0); + SetGameSettings(iPad,eGameSetting_ControlSouthPaw,pSettings->bSwapSticks?1:0); + SetGameSettings(iPad,eGameSetting_SplitScreenVertical,0); + SetGameSettings(iPad,eGameSetting_GamertagsVisible,1); + + // Interim TU 1.6.6 + SetGameSettings(iPad,eGameSetting_Sensitivity_InMenu,100); + SetGameSettings(iPad,eGameSetting_DisplaySplitscreenGamertags,1); + SetGameSettings(iPad,eGameSetting_Hints,1); + SetGameSettings(iPad,eGameSetting_Autosave,2); + SetGameSettings(iPad,eGameSetting_Tooltips,1); + SetGameSettings(iPad,eGameSetting_InterfaceOpacity,80); + + // TU 5 + SetGameSettings(iPad,eGameSetting_Clouds,1); + SetGameSettings(iPad,eGameSetting_Online,1); + SetGameSettings(iPad,eGameSetting_InviteOnly,0); + SetGameSettings(iPad,eGameSetting_FriendsOfFriends,1); + + // default the update changes message to zero + // 4J-PB - We'll only display the message if the profile is pre-TU5 + //SetGameSettings(iPad,eGameSetting_DisplayUpdateMessage,0); + + // TU 6 + SetGameSettings(iPad,eGameSetting_BedrockFog,0); + SetGameSettings(iPad,eGameSetting_DisplayHUD,1); + SetGameSettings(iPad,eGameSetting_DisplayHand,1); + + // TU 7 + SetGameSettings(iPad,eGameSetting_CustomSkinAnim,1); + + // TU 9 + SetGameSettings(iPad,eGameSetting_DeathMessages,1); + SetGameSettings(iPad,eGameSetting_UISize,1); + SetGameSettings(iPad,eGameSetting_UISizeSplitscreen,2); + SetGameSettings(iPad,eGameSetting_AnimatedCharacter,1); + + // TU 12 + GameSettingsA[iPad]->ucCurrentFavoriteSkinPos=0; + for(int i=0;iuiFavoriteSkinA[i]=0xFFFFFFFF; + } + + // TU 13 + GameSettingsA[iPad]->uiMashUpPackWorldsDisplay=0xFFFFFFFF; + + // 1.6.4 + app.SetGameHostOption(eGameHostOption_MobGriefing, 1); + app.SetGameHostOption(eGameHostOption_KeepInventory, 0); + app.SetGameHostOption(eGameHostOption_DoMobSpawning, 1 ); + app.SetGameHostOption(eGameHostOption_DoMobLoot, 1 ); + app.SetGameHostOption(eGameHostOption_DoTileDrops, 1 ); + app.SetGameHostOption(eGameHostOption_NaturalRegeneration, 1 ); + app.SetGameHostOption(eGameHostOption_DoDaylightCycle, 1 ); + + //TU25 + SetGameSettings(iPad, eGameSetting_ClassicCrafting, 0); + SetGameSettings(iPad, eGameSetting_CaveSounds, 1); + + //TU34 + SetGameSettings(iPad, eGameSetting_MinecartSounds, 1); + + // 4J-PB - leave these in, or remove from everywhere they are referenced! + // Although probably best to leave in unless we split the profile settings into platform specific classes - having different meaning per platform for the same bitmask could get confusing + //#ifdef __PS3__ + // PS3DEC13 + SetGameSettings(iPad,eGameSetting_PS3_EULA_Read,0); // EULA not read + + // PS3 1.05 - added Greek + + // 4J-JEV: We cannot change these in-game, as they could affect localised strings and font. + // XB1: Fix for #172947 - Content: Gameplay: While playing in language different form system default one and resetting options to their defaults in active gameplay causes in-game language to change and HUD to disappear + if (!app.GetGameStarted()) + { + GameSettingsA[iPad]->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language + GameSettingsA[iPad]->ucLocale = MINECRAFT_LANGUAGE_DEFAULT; // use the system locale + } + + //#endif + +#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) + GameSettingsA[iPad]->bSettingsChanged=bWriteProfile; +#endif + + return 0; +} + +#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) +int CMinecraftApp::DefaultOptionsCallback(LPVOID pParam,C4JStorage::PROFILESETTINGS *pSettings, const int iPad) +#else +int CMinecraftApp::DefaultOptionsCallback(LPVOID pParam,C_4JProfile::PROFILESETTINGS *pSettings, const int iPad) +#endif +{ + CMinecraftApp *pApp=static_cast(pParam); + + // flag the default options to be set + + pApp->DebugPrintf("Setting default options for player %d", iPad); + pApp->SetAction(iPad,eAppAction_SetDefaultOptions, (LPVOID)pSettings); + //pApp->SetDefaultOptions(pSettings,iPad); + + // if the profile data has been changed, then force a profile write + // It seems we're allowed to break the 5 minute rule if it's the result of a user action + //pApp->CheckGameSettingsChanged(); + + return 0; +} + +#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) + +wstring CMinecraftApp::toStringOptionsStatus(const C4JStorage::eOptionsCallback &eStatus) +{ +#ifndef _CONTENT_PACKAGE + switch(eStatus) + { + case C4JStorage::eOptions_Callback_Idle: return L"Idle"; + case C4JStorage::eOptions_Callback_Write: return L"Write"; + case C4JStorage::eOptions_Callback_Write_Fail_NoSpace: return L"Write_Fail_NoSpace"; + case C4JStorage::eOptions_Callback_Write_Fail: return L"Write_Fail"; + case C4JStorage::eOptions_Callback_Read: return L"Read"; + case C4JStorage::eOptions_Callback_Read_Fail: return L"Read_Fail"; + case C4JStorage::eOptions_Callback_Read_FileNotFound: return L"Read_FileNotFound"; + case C4JStorage::eOptions_Callback_Read_Corrupt: return L"Read_Corrupt"; + case C4JStorage::eOptions_Callback_Read_CorruptDeletePending: return L"Read_CorruptDeletePending"; + case C4JStorage::eOptions_Callback_Read_CorruptDeleted: return L"Read_CorruptDeleted"; + default: return L"[UNRECOGNISED_OPTIONS_STATUS]"; + } +#else + return L""; +#endif +} + +#ifdef __ORBIS__ +int CMinecraftApp::OptionsDataCallback(LPVOID pParam,int iPad,unsigned short usVersion,C4JStorage::eOptionsCallback eStatus,int iBlocksRequired) +{ + CMinecraftApp *pApp=(CMinecraftApp *)pParam; + pApp->m_eOptionsStatusA[iPad]=eStatus; + pApp->m_eOptionsBlocksRequiredA[iPad]=iBlocksRequired; + return 0; +} + +int CMinecraftApp::GetOptionsBlocksRequired(int iPad) +{ + return m_eOptionsBlocksRequiredA[iPad]; +} + +#else +int CMinecraftApp::OptionsDataCallback(LPVOID pParam,int iPad,unsigned short usVersion,C4JStorage::eOptionsCallback eStatus) +{ + CMinecraftApp *pApp=(CMinecraftApp *)pParam; + +#ifndef _CONTENT_PACKAGE + pApp->DebugPrintf("[OptionsDataCallback] Pad_%i: new status == %ls(%i).\n", iPad, pApp->toStringOptionsStatus(eStatus).c_str(), (int) eStatus); +#endif + + pApp->m_eOptionsStatusA[iPad] = eStatus; + + return 0; +} +#endif + +C4JStorage::eOptionsCallback CMinecraftApp::GetOptionsCallbackStatus(int iPad) +{ + return m_eOptionsStatusA[iPad]; +} + +void CMinecraftApp::SetOptionsCallbackStatus(int iPad, C4JStorage::eOptionsCallback eStatus) +{ + m_eOptionsStatusA[iPad]=eStatus; +} +#endif + +int CMinecraftApp::OldProfileVersionCallback(LPVOID pParam,unsigned char *pucData, const unsigned short usVersion, const int iPad) +{ + // check what needs to be done with this version to update to the current one + + switch(usVersion) + { +#ifdef _XBOX + case PROFILE_VERSION_1: + case PROFILE_VERSION_2: + // need to fill in values for the new profile data. No need to save the profile - that'll happen if they get changed, or if the auto save for the profile kicks in + { + GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; + pGameSettings->ucMenuSensitivity=100; //eGameSetting_Sensitivity_InMenu + pGameSettings->ucInterfaceOpacity=80; //eGameSetting_Sensitivity_InMenu + pGameSettings->usBitmaskValues|=0x0200; //eGameSetting_DisplaySplitscreenGamertags - on + pGameSettings->usBitmaskValues|=0x0400; //eGameSetting_Hints - on + pGameSettings->usBitmaskValues|=0x1000; //eGameSetting_Autosave - 2 + pGameSettings->usBitmaskValues|=0x8000; //eGameSetting_Tooltips - on + + // 4J-PB - Let's also award all the achievements they have again because of the profile bug that seemed to stop the awards of some + // Changing this to check the system achievements at sign-in and award any that the game says we have and the system says we haven't + //ProfileManager.ReAwardAchievements(iPad); + + pGameSettings->uiBitmaskValues=0L; // reset + pGameSettings->uiBitmaskValues|=GAMESETTING_CLOUDS; //eGameSetting_Clouds - on + pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on + //eGameSetting_GameSetting_Invite - off + pGameSettings->uiBitmaskValues|=GAMESETTING_FRIENDSOFFRIENDS; //eGameSetting_GameSetting_FriendsOfFriends - on + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) + // TU6 + pGameSettings->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG; //eGameSetting_BedrockFog - off + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHUD; //eGameSetting_DisplayHUD - on + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHAND; //eGameSetting_DisplayHand - on + // TU7 + pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on + // TU9 + pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on + pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2 + pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3 + pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on + // TU12 + // favorite skins added, but only set in TU12 - set to FFs + for(int i=0;iuiFavoriteSkinA[i]=0xFFFFFFFF; + } + pGameSettings->ucCurrentFavoriteSkinPos=0; + // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list + pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; + + // PS3 1.05 - added Greek + pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language + } + break; + case PROFILE_VERSION_3: + + { + GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; + pGameSettings->uiBitmaskValues=0L; // reset + pGameSettings->uiBitmaskValues|=GAMESETTING_CLOUDS; //eGameSetting_Clouds - on + pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on + //eGameSetting_GameSetting_Invite - off + pGameSettings->uiBitmaskValues|=GAMESETTING_FRIENDSOFFRIENDS; //eGameSetting_GameSetting_FriendsOfFriends - on + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) + // TU6 + pGameSettings->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG; //eGameSetting_BedrockFog - off + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHUD; //eGameSetting_DisplayHUD - on + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHAND; //eGameSetting_DisplayHand - on + // TU7 + pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on + // TU9 + pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on + pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2 + pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3 + pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on + // TU12 + // favorite skins added, but only set in TU12 - set to FFs + for(int i=0;iuiFavoriteSkinA[i]=0xFFFFFFFF; + } + pGameSettings->ucCurrentFavoriteSkinPos=0; + // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list + pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; + + // PS3 1.05 - added Greek + pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language + + } + break; + case PROFILE_VERSION_4: + { + GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; + + pGameSettings->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG; //eGameSetting_BedrockFog - off + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHUD; //eGameSetting_DisplayHUD - on + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHAND; //eGameSetting_DisplayHand - on + // TU7 + pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on + // TU9 + pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on + pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2 + pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3 + pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on + + // Set the online flag to on, so it's not saved if a game starts offline when the user didn't change it to be offline (xbox disconnected from LIVE) + pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on + // TU12 + // favorite skins added, but only set in TU12 - set to FFs + for(int i=0;iuiFavoriteSkinA[i]=0xFFFFFFFF; + } + pGameSettings->ucCurrentFavoriteSkinPos=0; + // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list + pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; + + // PS3 1.05 - added Greek + pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language + + } + + break; + case PROFILE_VERSION_5: + { + GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; + + // reset the display new message counter + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) + // TU7 + pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on + // TU9 + pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on + pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2 + pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3 + pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on + // Set the online flag to on, so it's not saved if a game starts offline when the user didn't change it to be offline (xbox disconnected from LIVE) + pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on + // TU12 + // favorite skins added, but only set in TU12 - set to FFs + for(int i=0;iuiFavoriteSkinA[i]=0xFFFFFFFF; + } + pGameSettings->ucCurrentFavoriteSkinPos=0; + // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list + pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; + + // PS3 1.05 - added Greek + pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language + + + } + + break; + case PROFILE_VERSION_6: + { + GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; + + // Added gui size for splitscreen and fullscreen + // Added death messages toggle + + // reset the display new message counter + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) + // TU9 + pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on + pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2 + pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3 + pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on + // Set the online flag to on, so it's not saved if a game starts offline when the user didn't change it to be offline (xbox disconnected from LIVE) + pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on + // TU12 + // favorite skins added, but only set in TU12 - set to FFs + for(int i=0;iuiFavoriteSkinA[i]=0xFFFFFFFF; + } + pGameSettings->ucCurrentFavoriteSkinPos=0; + // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list + pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; + + // PS3 1.05 - added Greek + pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language + + + } + + break; + + case PROFILE_VERSION_7: + { + GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; + // reset the display new message counter + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) + + // TU12 + // favorite skins added, but only set in TU12 - set to FFs + for(int i=0;iuiFavoriteSkinA[i]=0xFFFFFFFF; + } + pGameSettings->ucCurrentFavoriteSkinPos=0; + // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list + pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; + + // PS3 1.05 - added Greek + pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language + + + } + break; +#endif + case PROFILE_VERSION_8: + { + GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; + // reset the display new message counter + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) + + // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list + pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; + + // PS3DEC13 + pGameSettings->uiBitmaskValues&=~GAMESETTING_PS3EULAREAD; //eGameSetting_PS3_EULA_Read - off + + // PS3 1.05 - added Greek + pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language + + } + break; + case PROFILE_VERSION_9: + // PS3DEC13 + { + GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) + pGameSettings->uiBitmaskValues&=~GAMESETTING_PS3EULAREAD; //eGameSetting_PS3_EULA_Read - off + + // PS3 1.05 - added Greek + pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language + + } + break; + case PROFILE_VERSION_10: + { + GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) + pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language + } + break; + case PROFILE_VERSION_11: + { + GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) + } + break; + case PROFILE_VERSION_12: + { + GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) + } + break; + default: + { + // This might be from a version during testing of new profile updates + app.DebugPrintf("Don't know what to do with this profile version!\n"); + + GAME_SETTINGS *pGameSettings=(GAME_SETTINGS *)pucData; + pGameSettings->ucMenuSensitivity=100; //eGameSetting_Sensitivity_InMenu + pGameSettings->ucInterfaceOpacity=80; //eGameSetting_Sensitivity_InMenu + pGameSettings->usBitmaskValues|=0x0200; //eGameSetting_DisplaySplitscreenGamertags - on + pGameSettings->usBitmaskValues|=0x0400; //eGameSetting_Hints - on + pGameSettings->usBitmaskValues|=0x1000; //eGameSetting_Autosave - 2 + pGameSettings->usBitmaskValues|=0x8000; //eGameSetting_Tooltips - on + + pGameSettings->uiBitmaskValues=0L; // reset + pGameSettings->uiBitmaskValues|=GAMESETTING_CLOUDS; //eGameSetting_Clouds - on + pGameSettings->uiBitmaskValues|=GAMESETTING_ONLINE; //eGameSetting_GameSetting_Online - on + //eGameSetting_GameSetting_Invite - off + pGameSettings->uiBitmaskValues|=GAMESETTING_FRIENDSOFFRIENDS; //eGameSetting_GameSetting_FriendsOfFriends - on + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYUPDATEMSG; //eGameSetting_DisplayUpdateMessage (counter) + pGameSettings->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG; //eGameSetting_BedrockFog - off + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHUD; //eGameSetting_DisplayHUD - on + pGameSettings->uiBitmaskValues|=GAMESETTING_DISPLAYHAND; //eGameSetting_DisplayHand - on + pGameSettings->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; //eGameSetting_CustomSkinAnim - on + pGameSettings->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; //eGameSetting_DeathMessages - on + pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE&0x00000800); // uisize 2 + pGameSettings->uiBitmaskValues|=(GAMESETTING_UISIZE_SPLITSCREEN&0x00004000); // splitscreen ui size 3 + pGameSettings->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; //eGameSetting_AnimatedCharacter - on + pGameSettings->uiBitmaskValues |= GAMESETTING_CLASSICCRAFTING; //eGameSetting_ClassicCrafting - off + // TU12 + // favorite skins added, but only set in TU12 - set to FFs + for(int i=0;iuiFavoriteSkinA[i]=0xFFFFFFFF; + } + pGameSettings->ucCurrentFavoriteSkinPos=0; + // Added a bitmask in TU13 to enable/disable display of the Mash-up pack worlds in the saves list + pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; + + // PS3DEC13 + pGameSettings->uiBitmaskValues&=~GAMESETTING_PS3EULAREAD; //eGameSetting_PS3_EULA_Read - off + + // PS3 1.05 - added Greek + pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language + + } + break; + } + + return 0; +} + +void CMinecraftApp::ApplyGameSettingsChanged(int iPad) +{ + ActionGameSettings(iPad,eGameSetting_MusicVolume ); + ActionGameSettings(iPad,eGameSetting_SoundFXVolume ); + ActionGameSettings(iPad,eGameSetting_RenderDistance ); + ActionGameSettings(iPad,eGameSetting_Gamma ); + ActionGameSettings(iPad,eGameSetting_FOV ); + ActionGameSettings(iPad,eGameSetting_Difficulty ); + ActionGameSettings(iPad,eGameSetting_Sensitivity_InGame ); + ActionGameSettings(iPad,eGameSetting_ViewBob ); + ActionGameSettings(iPad,eGameSetting_ControlScheme ); + ActionGameSettings(iPad,eGameSetting_ControlInvertLook); + ActionGameSettings(iPad,eGameSetting_ControlSouthPaw); + ActionGameSettings(iPad,eGameSetting_ControlType); + ActionGameSettings(iPad,eGameSetting_SplitScreenVertical); + ActionGameSettings(iPad,eGameSetting_GamertagsVisible); + + // Interim TU 1.6.6 + ActionGameSettings(iPad,eGameSetting_Sensitivity_InMenu ); + ActionGameSettings(iPad,eGameSetting_DisplaySplitscreenGamertags); + ActionGameSettings(iPad,eGameSetting_Hints); + ActionGameSettings(iPad,eGameSetting_InterfaceOpacity); + ActionGameSettings(iPad,eGameSetting_Tooltips); + + ActionGameSettings(iPad,eGameSetting_Clouds); + ActionGameSettings(iPad,eGameSetting_BedrockFog); + ActionGameSettings(iPad,eGameSetting_DisplayHUD); + ActionGameSettings(iPad,eGameSetting_DisplayHand); + ActionGameSettings(iPad,eGameSetting_CustomSkinAnim); + ActionGameSettings(iPad,eGameSetting_DeathMessages); + ActionGameSettings(iPad,eGameSetting_UISize); + ActionGameSettings(iPad,eGameSetting_UISizeSplitscreen); + ActionGameSettings(iPad,eGameSetting_AnimatedCharacter); + + ActionGameSettings(iPad,eGameSetting_PS3_EULA_Read); + ActionGameSettings(iPad,eGameSetting_VSync); + + //TU25 + ActionGameSettings(iPad, eGameSetting_ClassicCrafting); + ActionGameSettings(iPad, eGameSetting_CaveSounds); + ActionGameSettings(iPad, eGameSetting_MinecartSounds); + ActionGameSettings(iPad, eGameSetting_HideSaveSizeBar); + ActionGameSettings(iPad, eGameSetting_SafeCam); + ActionGameSettings(iPad, eGameSetting_Swap); +} + +void CMinecraftApp::ActionGameSettings(int iPad,eGameSetting eVal) +{ + Minecraft *pMinecraft=Minecraft::GetInstance(); + switch(eVal) + { + case eGameSetting_MusicVolume: + if(iPad==ProfileManager.GetPrimaryPad()) + { + pMinecraft->options->set(Options::Option::MUSIC,static_cast(GameSettingsA[iPad]->ucMusicVolume)/100.0f); + } + break; + case eGameSetting_SoundFXVolume: + if (iPad == ProfileManager.GetPrimaryPad()) + { + pMinecraft->options->set(Options::Option::SOUND, static_cast(GameSettingsA[iPad]->ucSoundFXVolume) / 100.0f); + } + break; + case eGameSetting_RenderDistance: + if (iPad == ProfileManager.GetPrimaryPad()) + { + int dist = (GameSettingsA[iPad]->uiBitmaskValues >> 16) & 0xFF; + + int level = UIScene_SettingsGraphicsMenu::DistanceToLevel(dist); + pMinecraft->options->set(Options::Option::RENDER_DISTANCE, 3 - level); + }; + break; + case eGameSetting_Gamma: + if(iPad==ProfileManager.GetPrimaryPad()) + { +#if defined(_WIN64) || defined(_WINDOWS64) + pMinecraft->options->set(Options::Option::GAMMA, static_cast(GameSettingsA[iPad]->ucGamma) / 100.0f); +#else + // ucGamma range is 0-100, UpdateGamma is 0 - 32768 + float fVal=((float)GameSettingsA[iPad]->ucGamma)*327.68f; + RenderManager.UpdateGamma((unsigned short)fVal); +#endif + } + + break; + case eGameSetting_FOV: + if(iPad==ProfileManager.GetPrimaryPad()) + { + float fovDeg = 70.0f + (float)GameSettingsA[iPad]->ucFov * 40.0f / 100.0f; + pMinecraft->gameRenderer->SetFovVal(fovDeg); + pMinecraft->options->set(Options::Option::FOV, (float)GameSettingsA[iPad]->ucFov / 100.0f); + } + break; + case eGameSetting_Difficulty: + if(iPad==ProfileManager.GetPrimaryPad()) + { + pMinecraft->options->toggle(Options::Option::DIFFICULTY,GameSettingsA[iPad]->usBitmaskValues&0x03); + app.DebugPrintf("Difficulty toggle to %d\n",GameSettingsA[iPad]->usBitmaskValues&0x03); + + // Update the Game Host setting + app.SetGameHostOption(eGameHostOption_Difficulty,pMinecraft->options->difficulty); + + // send this to the other players if we are in-game + bool bInGame=pMinecraft->level!=nullptr; + + // Game Host only (and for now we can't change the diff while in game, so this shouldn't happen) + if(bInGame && g_NetworkManager.IsHost() && (iPad==ProfileManager.GetPrimaryPad())) + { + app.SetXuiServerAction(iPad,eXuiServerAction_ServerSettingChanged_Difficulty); + } + } + else + { + app.DebugPrintf("NOT ACTIONING DIFFICULTY - Primary pad is %d, This pad is %d\n",ProfileManager.GetPrimaryPad(),iPad); + } + + break; + case eGameSetting_Sensitivity_InGame: + // 4J-PB - we don't use the options value + // tell the input that we've changed the sensitivity - range of the slider is 0 to 200, default is 100 + pMinecraft->options->set(Options::Option::SENSITIVITY,static_cast(GameSettingsA[iPad]->ucSensitivity)/100.0f); + //InputManager.SetJoypadSensitivity(iPad,((float)GameSettingsA[iPad]->ucSensitivity)/100.0f); + + break; + case eGameSetting_ViewBob: + // 4J-PB - not handled here any more - it's read from the gamesettings per player + //pMinecraft->options->toggle(Options::Option::VIEW_BOBBING,GameSettingsA[iPad]->usBitmaskValues&0x04); + break; + case eGameSetting_ControlScheme: + InputManager.SetJoypadMapVal(iPad,(GameSettingsA[iPad]->usBitmaskValues&0x30)>>4); + break; + + case eGameSetting_ControlInvertLook: + // Nothing specific to do for this setting. + break; + + case eGameSetting_ControlSouthPaw: + // What is the setting? + if ( GameSettingsA[iPad]->usBitmaskValues & 0x80 ) + { + // Southpaw. + InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_LX, AXIS_MAP_RX ); + InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_LY, AXIS_MAP_RY ); + InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_RX, AXIS_MAP_LX ); + InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_RY, AXIS_MAP_LY ); + InputManager.SetJoypadStickTriggerMap( iPad, TRIGGER_MAP_0, TRIGGER_MAP_1 ); + InputManager.SetJoypadStickTriggerMap( iPad, TRIGGER_MAP_1, TRIGGER_MAP_0 ); + } + else + { + // Right handed. + InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_LX, AXIS_MAP_LX ); + InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_LY, AXIS_MAP_LY ); + InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_RX, AXIS_MAP_RX ); + InputManager.SetJoypadStickAxisMap( iPad, AXIS_MAP_RY, AXIS_MAP_RY ); + InputManager.SetJoypadStickTriggerMap( iPad, TRIGGER_MAP_0, TRIGGER_MAP_0 ); + InputManager.SetJoypadStickTriggerMap( iPad, TRIGGER_MAP_1, TRIGGER_MAP_1 ); + } + break; + case eGameSetting_SplitScreenVertical: + if(iPad==ProfileManager.GetPrimaryPad()) + { + pMinecraft->updatePlayerViewportAssignments(); + } + break; + case eGameSetting_GamertagsVisible: + { + bool bInGame=pMinecraft->level!=nullptr; + + // Game Host only + if(bInGame && g_NetworkManager.IsHost() && (iPad==ProfileManager.GetPrimaryPad())) + { + // Update the Game Host setting if you are the host and you are in-game + app.SetGameHostOption(eGameHostOption_Gamertags,((GameSettingsA[iPad]->usBitmaskValues&0x0008)!=0)?1:0); + app.SetXuiServerAction(iPad,eXuiServerAction_ServerSettingChanged_Gamertags); + + PlayerList *players = MinecraftServer::getInstance()->getPlayerList(); + for( auto& decorationPlayer : players->players ) + { + decorationPlayer->setShowOnMaps((app.GetGameHostOption(eGameHostOption_Gamertags)!=0)?true:false); + } + } + } + break; + // Interim TU 1.6.6 + case eGameSetting_Sensitivity_InMenu: + // 4J-PB - we don't use the options value + // tell the input that we've changed the sensitivity - range of the slider is 0 to 200, default is 100 + //pMinecraft->options->set(Options::Option::SENSITIVITY,((float)GameSettingsA[iPad]->ucSensitivity)/100.0f); + //InputManager.SetJoypadSensitivity(iPad,((float)GameSettingsA[iPad]->ucSensitivity)/100.0f); + + break; + + case eGameSetting_DisplaySplitscreenGamertags: + for( BYTE idx = 0; idx < XUSER_MAX_COUNT; ++idx) + { + if(pMinecraft->localplayers[idx] != nullptr) + { + if(pMinecraft->localplayers[idx]->m_iScreenSection==C4JRender::VIEWPORT_TYPE_FULLSCREEN) + { + ui.DisplayGamertag(idx,false); + } + else + { + ui.DisplayGamertag(idx,true); + } + } + } + + break; + case eGameSetting_InterfaceOpacity: + // update the tooltips display + ui.RefreshTooltips( iPad); + + break; + case eGameSetting_Hints: + //nothing to do here + break; + case eGameSetting_Tooltips: + if((GameSettingsA[iPad]->usBitmaskValues&0x8000)!=0) + { + ui.SetEnableTooltips(iPad,TRUE); + } + else + { + ui.SetEnableTooltips(iPad,FALSE); + } + break; + case eGameSetting_Clouds: + //nothing to do here + break; + case eGameSetting_Online: + //nothing to do here + break; + case eGameSetting_InviteOnly: + //nothing to do here + break; + case eGameSetting_FriendsOfFriends: + //nothing to do here + break; + case eGameSetting_BedrockFog: + { + bool bInGame = pMinecraft->level != nullptr; + + if (bInGame && g_NetworkManager.IsHost() && (iPad == ProfileManager.GetPrimaryPad())) + { + app.SetGameHostOption(eGameHostOption_BedrockFog, GetGameSettings(iPad, eGameSetting_BedrockFog) ? 1 : 0); + app.SetXuiServerAction(iPad, eXuiServerAction_ServerSettingChanged_BedrockFog); + } + } + break; + case eGameSetting_DisplayHUD: + //nothing to do here + break; + case eGameSetting_DisplayHand: + //nothing to do here + break; + case eGameSetting_CustomSkinAnim: + //nothing to do here + break; + case eGameSetting_DeathMessages: + //nothing to do here + break; + case eGameSetting_UISize: + //nothing to do here + break; + case eGameSetting_UISizeSplitscreen: + //nothing to do here + break; + case eGameSetting_AnimatedCharacter: + //nothing to do here + break; + case eGameSetting_PS3_EULA_Read: + //nothing to do here + break; + case eGameSetting_PSVita_NetworkModeAdhoc: + //nothing to do here + break; + case eGameSetting_VSync: +#ifdef _WINDOWS64 + { + extern bool g_bVSync; + g_bVSync = (GetGameSettings(iPad, eGameSetting_VSync) != 0); + } +#endif + break; + case eGameSetting_ExclusiveFullscreen: +#ifdef _WINDOWS64 + { + extern void SetExclusiveFullscreen(bool enabled); + SetExclusiveFullscreen(GetGameSettings(iPad, eGameSetting_ExclusiveFullscreen) != 0); + } +#endif + break; + case eGameSetting_ClassicCrafting: + //nothing to do here + break; + case eGameSetting_HideSaveSizeBar: + //nothing to do here + break; + case eGameSetting_SafeCam: + { + int iVal = GetGameSettings(iPad, eGameSetting_SafeCam); + InputManager.SetButtonSwapEnabled(iPad, 0, iVal != 0); + } + break; + case eGameSetting_Swap: + { + int iVal = GetGameSettings(iPad, eGameSetting_Swap); + InputManager.SetButtonSwapEnabled(iPad, 1, iVal != 0); + } + break; + } +} + +void CMinecraftApp::SetPlayerSkin(int iPad,const wstring &name) +{ + DWORD skinId = app.getSkinIdFromPath(name); + + SetPlayerSkin(iPad,skinId); +} + +void CMinecraftApp::SetPlayerSkin(int iPad,DWORD dwSkinId) +{ + DebugPrintf("Setting skin for %d to %08X\n", iPad, dwSkinId); + + GameSettingsA[iPad]->dwSelectedSkin = dwSkinId; + GameSettingsA[iPad]->bSettingsChanged = true; + + TelemetryManager->RecordSkinChanged(iPad, GameSettingsA[iPad]->dwSelectedSkin); + + if(Minecraft::GetInstance()->localplayers[iPad]!=nullptr) Minecraft::GetInstance()->localplayers[iPad]->setAndBroadcastCustomSkin(dwSkinId); +} + + +wstring CMinecraftApp::GetPlayerSkinName(int iPad) +{ + return app.getSkinPathFromId(GameSettingsA[iPad]->dwSelectedSkin); +} + +DWORD CMinecraftApp::GetPlayerSkinId(int iPad) +{ + // 4J-PB -check the user has rights to use this skin - they may have had at some point but the entitlement has been removed. + DLCPack *Pack=nullptr; + DLCSkinFile *skinFile=nullptr; + DWORD dwSkin=GameSettingsA[iPad]->dwSelectedSkin; + wchar_t chars[256]; + + if( GET_IS_DLC_SKIN_FROM_BITMASK(dwSkin) ) + { + // 4J Stu - DLC skins are numbered using decimal rather than hex to make it easier to number manually + swprintf(chars, 256, L"dlcskin%08d.png", GET_DLC_SKIN_ID_FROM_BITMASK(dwSkin)); + + Pack=app.m_dlcManager.getPackContainingSkin(chars); + + if(Pack) + { + skinFile = Pack->getSkinFile(chars); + + bool bSkinIsFree = skinFile->getParameterAsBool( DLCManager::e_DLCParamType_Free ); + bool bLicensed = Pack->hasPurchasedFile( DLCManager::e_DLCType_Skin, skinFile->getPath() ); + + if(bSkinIsFree || bLicensed) + { + return dwSkin; + } + else + { + return 0; + } + } + } + + + return dwSkin; +} + +DWORD CMinecraftApp::GetAdditionalModelParts(int iPad) +{ + return m_dwAdditionalModelParts[iPad]; +} + + +void CMinecraftApp::SetPlayerCape(int iPad,const wstring &name) +{ + DWORD capeId = Player::getCapeIdFromPath(name); + + SetPlayerCape(iPad,capeId); +} + +void CMinecraftApp::SetPlayerCape(int iPad,DWORD dwCapeId) +{ + DebugPrintf("Setting cape for %d to %08X\n", iPad, dwCapeId); + + GameSettingsA[iPad]->dwSelectedCape = dwCapeId; + GameSettingsA[iPad]->bSettingsChanged = true; + + //SentientManager.RecordSkinChanged(iPad, GameSettingsA[iPad]->dwSelectedSkin); + + if(Minecraft::GetInstance()->localplayers[iPad]!=nullptr) Minecraft::GetInstance()->localplayers[iPad]->setAndBroadcastCustomCape(dwCapeId); +} + +wstring CMinecraftApp::GetPlayerCapeName(int iPad) +{ + return Player::getCapePathFromId(GameSettingsA[iPad]->dwSelectedCape); +} + +DWORD CMinecraftApp::GetPlayerCapeId(int iPad) +{ + return GameSettingsA[iPad]->dwSelectedCape; +} + +void CMinecraftApp::SetPlayerFavoriteSkin(int iPad, int iIndex,unsigned int uiSkinID) +{ + DebugPrintf("Setting favorite skin for %d to %08X\n", iPad, uiSkinID); + + GameSettingsA[iPad]->uiFavoriteSkinA[iIndex] = uiSkinID; + GameSettingsA[iPad]->bSettingsChanged = true; +} + +unsigned int CMinecraftApp::GetPlayerFavoriteSkin(int iPad,int iIndex) +{ + return GameSettingsA[iPad]->uiFavoriteSkinA[iIndex]; +} + +unsigned char CMinecraftApp::GetPlayerFavoriteSkinsPos(int iPad) +{ + return GameSettingsA[iPad]->ucCurrentFavoriteSkinPos; +} + +void CMinecraftApp::SetPlayerFavoriteSkinsPos(int iPad, int iPos) +{ + GameSettingsA[iPad]->ucCurrentFavoriteSkinPos=static_cast(iPos); + GameSettingsA[iPad]->bSettingsChanged = true; +} + +unsigned int CMinecraftApp::GetPlayerFavoriteSkinsCount(int iPad) +{ + unsigned int uiCount=0; + for(int i=0;iuiFavoriteSkinA[i]!=0xFFFFFFFF) + { + uiCount++; + } + else + { + break; + } + } + return uiCount; +} + +void CMinecraftApp::ValidateFavoriteSkins(int iPad) +{ + unsigned int uiCount=GetPlayerFavoriteSkinsCount(iPad); + + // remove invalid skins + unsigned int uiValidSkin=0; + wchar_t chars[256]; + + for(unsigned int i=0;igetFile(DLCManager::e_DLCType_Skin,chars); + DLCSkinFile *pSkinFile = pDLCPack->getSkinFile(chars); + + if( pDLCPack->hasPurchasedFile(DLCManager::e_DLCType_Skin, L"") || (pSkinFile && pSkinFile->isFree())) + { + GameSettingsA[iPad]->uiFavoriteSkinA[uiValidSkin++]=GameSettingsA[iPad]->uiFavoriteSkinA[i]; + } + } + } + + for(unsigned int i=uiValidSkin;iuiFavoriteSkinA[i]=0xFFFFFFFF; + } +} + +// Mash-up pack worlds +void CMinecraftApp::HideMashupPackWorld(int iPad, unsigned int iMashupPackID) +{ + unsigned int uiPackID=iMashupPackID - 1024; // mash-up ids start at 1024 + GameSettingsA[iPad]->uiMashUpPackWorldsDisplay&=~(1<bSettingsChanged = true; +} + +void CMinecraftApp::EnableMashupPackWorlds(int iPad) +{ + GameSettingsA[iPad]->uiMashUpPackWorldsDisplay=0xFFFFFFFF; + GameSettingsA[iPad]->bSettingsChanged = true; +} + +unsigned int CMinecraftApp::GetMashupPackWorlds(int iPad) +{ + return GameSettingsA[iPad]->uiMashUpPackWorldsDisplay; +} + +void CMinecraftApp::SetMinecraftLanguage(int iPad, unsigned char ucLanguage) +{ + GameSettingsA[iPad]->ucLanguage = ucLanguage; + GameSettingsA[iPad]->bSettingsChanged = true; +} + +unsigned char CMinecraftApp::GetMinecraftLanguage(int iPad) +{ + // if there are no game settings read yet, return the default language + if(GameSettingsA[iPad]==nullptr) + { + return 0; + } + else + { + return GameSettingsA[iPad]->ucLanguage; + } +} + +void CMinecraftApp::SetMinecraftLocale(int iPad, unsigned char ucLocale) +{ + GameSettingsA[iPad]->ucLocale = ucLocale; + GameSettingsA[iPad]->bSettingsChanged = true; +} + +unsigned char CMinecraftApp::GetMinecraftLocale(int iPad) +{ + // if there are no game settings read yet, return the default language + if(GameSettingsA[iPad]==nullptr) + { + return 0; + } + else + { + return GameSettingsA[iPad]->ucLocale; + } +} + +void CMinecraftApp::SetGameSettings(int iPad,eGameSetting eVal,unsigned char ucVal) +{ + //Minecraft *pMinecraft=Minecraft::GetInstance(); + + switch(eVal) + { + case eGameSetting_MusicVolume: + if(GameSettingsA[iPad]->ucMusicVolume!=ucVal) + { + GameSettingsA[iPad]->ucMusicVolume=ucVal; + if(iPad==ProfileManager.GetPrimaryPad()) + { + ActionGameSettings(iPad,eVal); + } + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_SoundFXVolume: + if(GameSettingsA[iPad]->ucSoundFXVolume!=ucVal) + { + GameSettingsA[iPad]->ucSoundFXVolume=ucVal; + if(iPad==ProfileManager.GetPrimaryPad()) + { + ActionGameSettings(iPad,eVal); + } + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_RenderDistance: + { + unsigned int val = ucVal & 0xFF; + + GameSettingsA[iPad]->uiBitmaskValues &= ~(0xFF << 16); + GameSettingsA[iPad]->uiBitmaskValues |= val << 16; + if(iPad == ProfileManager.GetPrimaryPad()) + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_Gamma: + if(GameSettingsA[iPad]->ucGamma!=ucVal) + { + GameSettingsA[iPad]->ucGamma=ucVal; + if(iPad==ProfileManager.GetPrimaryPad()) + { + ActionGameSettings(iPad,eVal); + } + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_FOV: + if(GameSettingsA[iPad]->ucFov!=ucVal) + { + GameSettingsA[iPad]->ucFov=ucVal; + if(iPad==ProfileManager.GetPrimaryPad()) + { + ActionGameSettings(iPad,eVal); + } + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_Difficulty: + if((GameSettingsA[iPad]->usBitmaskValues&0x03)!=(ucVal&0x03)) + { + GameSettingsA[iPad]->usBitmaskValues&=~0x03; + GameSettingsA[iPad]->usBitmaskValues|=ucVal&0x03; + if(iPad==ProfileManager.GetPrimaryPad()) + { + ActionGameSettings(iPad,eVal); + } + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_Sensitivity_InGame: + if(GameSettingsA[iPad]->ucSensitivity!=ucVal) + { + GameSettingsA[iPad]->ucSensitivity=ucVal; + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_ViewBob: + if((GameSettingsA[iPad]->usBitmaskValues&0x0004)!=((ucVal&0x01)<<2)) + { + if(ucVal!=0) + { + GameSettingsA[iPad]->usBitmaskValues|=0x0004; + } + else + { + GameSettingsA[iPad]->usBitmaskValues&=~0x0004; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_ControlScheme: // bits 5 and 6 + if((GameSettingsA[iPad]->usBitmaskValues&0x30)!=((ucVal&0x03)<<4)) + { + GameSettingsA[iPad]->usBitmaskValues&=~0x0030; + if(ucVal!=0) + { + GameSettingsA[iPad]->usBitmaskValues|=(ucVal&0x03)<<4; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + + case eGameSetting_ControlInvertLook: + if((GameSettingsA[iPad]->usBitmaskValues&0x0040)!=((ucVal&0x01)<<6)) + { + if(ucVal!=0) + { + GameSettingsA[iPad]->usBitmaskValues|=0x0040; + } + else + { + GameSettingsA[iPad]->usBitmaskValues&=~0x0040; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + + case eGameSetting_ControlSouthPaw: + if((GameSettingsA[iPad]->usBitmaskValues&0x0080)!=((ucVal&0x01)<<7)) + { + if(ucVal!=0) + { + GameSettingsA[iPad]->usBitmaskValues|=0x0080; + } + else + { + GameSettingsA[iPad]->usBitmaskValues&=~0x0080; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_ControlType: + if((GameSettingsA[iPad]->uiBitmaskValues & 0x00070000) != ((ucVal & 0x07) << 16)) + { + GameSettingsA[iPad]->uiBitmaskValues &= ~0x00070000; + GameSettingsA[iPad]->uiBitmaskValues |= (ucVal & 0x07) << 16; + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_SplitScreenVertical: + if((GameSettingsA[iPad]->usBitmaskValues&0x0100)!=((ucVal&0x01)<<8)) + { + if(ucVal!=0) + { + GameSettingsA[iPad]->usBitmaskValues|=0x0100; + } + else + { + GameSettingsA[iPad]->usBitmaskValues&=~0x0100; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_GamertagsVisible: + if((GameSettingsA[iPad]->usBitmaskValues&0x0008)!=((ucVal&0x01)<<3)) + { + if(ucVal!=0) + { + GameSettingsA[iPad]->usBitmaskValues|=0x0008; + } + else + { + GameSettingsA[iPad]->usBitmaskValues&=~0x0008; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + + // 4J-PB - Added for Interim TU for 1.6.6 + case eGameSetting_Sensitivity_InMenu: + if(GameSettingsA[iPad]->ucMenuSensitivity!=ucVal) + { + GameSettingsA[iPad]->ucMenuSensitivity=ucVal; + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_DisplaySplitscreenGamertags: + if((GameSettingsA[iPad]->usBitmaskValues&0x0200)!=((ucVal&0x01)<<9)) + { + if(ucVal!=0) + { + GameSettingsA[iPad]->usBitmaskValues|=0x0200; + } + else + { + GameSettingsA[iPad]->usBitmaskValues&=~0x0200; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_Hints: + if((GameSettingsA[iPad]->usBitmaskValues&0x0400)!=((ucVal&0x01)<<10)) + { + if(ucVal!=0) + { + GameSettingsA[iPad]->usBitmaskValues|=0x0400; + } + else + { + GameSettingsA[iPad]->usBitmaskValues&=~0x0400; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_Autosave: + if((GameSettingsA[iPad]->usBitmaskValues&0x7800)!=((ucVal&0x0F)<<11)) + { + GameSettingsA[iPad]->usBitmaskValues&=~0x7800; + if(ucVal!=0) + { + GameSettingsA[iPad]->usBitmaskValues|=(ucVal&0x0F)<<11; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + + case eGameSetting_Tooltips: + if((GameSettingsA[iPad]->usBitmaskValues&0x8000)!=((ucVal&0x01)<<15)) + { + if(ucVal!=0) + { + GameSettingsA[iPad]->usBitmaskValues|=0x8000; + } + else + { + GameSettingsA[iPad]->usBitmaskValues&=~0x8000; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_InterfaceOpacity: + if(GameSettingsA[iPad]->ucInterfaceOpacity!=ucVal) + { + GameSettingsA[iPad]->ucInterfaceOpacity=ucVal; + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + + break; + case eGameSetting_Clouds: + if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_CLOUDS)!=(ucVal&0x01)) + { + if(ucVal==1) + { + GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_CLOUDS; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_CLOUDS; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + + break; + + case eGameSetting_Online: + if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_ONLINE)!=(ucVal&0x01)<<1) + { + if(ucVal==1) + { + GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_ONLINE; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_ONLINE; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + + break; + case eGameSetting_InviteOnly: + if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_INVITEONLY)!=(ucVal&0x01)<<2) + { + if(ucVal==1) + { + GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_INVITEONLY; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_INVITEONLY; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + + break; + case eGameSetting_FriendsOfFriends: + if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_FRIENDSOFFRIENDS)!=(ucVal&0x01)<<3) + { + if(ucVal==1) + { + GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_FRIENDSOFFRIENDS; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_FRIENDSOFFRIENDS; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + + break; + case eGameSetting_DisplayUpdateMessage: + if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYUPDATEMSG)!=(ucVal&0x03)<<4) + { + GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_DISPLAYUPDATEMSG; + if(ucVal>0) + { + GameSettingsA[iPad]->uiBitmaskValues|=(ucVal&0x03)<<4; + } + + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + + break; + + case eGameSetting_BedrockFog: + if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_BEDROCKFOG)!=(ucVal&0x01)<<6) + { + if(ucVal==1) + { + GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_BEDROCKFOG; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_BEDROCKFOG; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + + break; + case eGameSetting_DisplayHUD: + if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYHUD)!=(ucVal&0x01)<<7) + { + if(ucVal==1) + { + GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_DISPLAYHUD; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_DISPLAYHUD; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + + break; + case eGameSetting_DisplayHand: + if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYHAND)!=(ucVal&0x01)<<8) + { + if(ucVal==1) + { + GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_DISPLAYHAND; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_DISPLAYHAND; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + + break; + + case eGameSetting_CustomSkinAnim: + if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_CUSTOMSKINANIM)!=(ucVal&0x01)<<9) + { + if(ucVal==1) + { + GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_CUSTOMSKINANIM; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_CUSTOMSKINANIM; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + + break; + // TU9 + case eGameSetting_DeathMessages: + if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DEATHMESSAGES)!=(ucVal&0x01)<<10) + { + if(ucVal==1) + { + GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_DEATHMESSAGES; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_DEATHMESSAGES; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_UISize: + if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_UISIZE)!=((ucVal&0x03)<<11)) + { + GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_UISIZE; + if(ucVal!=0) + { + GameSettingsA[iPad]->uiBitmaskValues|=(ucVal&0x03)<<11; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_UISizeSplitscreen: + if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_UISIZE_SPLITSCREEN)!=((ucVal&0x03)<<13)) + { + GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_UISIZE_SPLITSCREEN; + if(ucVal!=0) + { + GameSettingsA[iPad]->uiBitmaskValues|=(ucVal&0x03)<<13; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_AnimatedCharacter: + if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_ANIMATEDCHARACTER)!=(ucVal&0x01)<<15) + { + if(ucVal==1) + { + GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_ANIMATEDCHARACTER; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_ANIMATEDCHARACTER; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_PS3_EULA_Read: + if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PS3EULAREAD)!=(ucVal&0x01)<<16) + { + if(ucVal==1) + { + GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_PS3EULAREAD; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_PS3EULAREAD; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_PSVita_NetworkModeAdhoc: + if((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PSVITANETWORKMODEADHOC)!=(ucVal&0x01)<<17) + { + if(ucVal==1) + { + GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_PSVITANETWORKMODEADHOC; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_PSVITANETWORKMODEADHOC; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + + case eGameSetting_VSync: + if(((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_VSYNC)>>24)!=(ucVal&0x01)) + { + if(ucVal==1) + { + GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_VSYNC; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_VSYNC; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + + case eGameSetting_ExclusiveFullscreen: + if(((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_EXCLUSIVEFULLSCREEN)>>25)!=(ucVal&0x01)) + { + if(ucVal==1) + { + GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_EXCLUSIVEFULLSCREEN; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_EXCLUSIVEFULLSCREEN; + } + ActionGameSettings(iPad,eVal); + GameSettingsA[iPad]->bSettingsChanged=true; + } + break; + case eGameSetting_ClassicCrafting: + if ((GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_CLASSICCRAFTING) != (ucVal & 0x01) << 19) + { + if (ucVal == 1) + { + GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_CLASSICCRAFTING; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_CLASSICCRAFTING; + } + ActionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_CaveSounds: + if ((GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_CAVESOUNDS) != (ucVal & 0x01) << 27) + { + if (ucVal == 1) + { + GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_CAVESOUNDS; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_CAVESOUNDS; + } + ActionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_MinecartSounds: + if ((GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_MINECARTSOUNDS) != (ucVal & 0x01) << 28) + { + if (ucVal == 1) + { + GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_MINECARTSOUNDS; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_MINECARTSOUNDS; + } + ActionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_HideSaveSizeBar: + if ((GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_HIDESAVESIZEBAR) != (ucVal & 0x01) << 27) + { + if (ucVal == 1) + { + GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_HIDESAVESIZEBAR; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_HIDESAVESIZEBAR; + } + ActionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_SafeCam: + if ((GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_SAFECAM) != ((unsigned int)(ucVal & 0x01) << 30)) + { + if (ucVal == 1) + { + GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_SAFECAM; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_SAFECAM; + } + ActionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_Swap: + if ((GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_SWAP) != ((unsigned int)(ucVal & 0x01) << 31)) + { + if (ucVal == 1) + { + GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_SWAP; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_SWAP; + } + ActionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + } +} + +unsigned char CMinecraftApp::GetGameSettings(eGameSetting eVal) +{ + int iPad=ProfileManager.GetPrimaryPad(); + + return GetGameSettings(iPad,eVal); +} + +unsigned char CMinecraftApp::GetGameSettings(int iPad,eGameSetting eVal) +{ + if (iPad < 0 || iPad >= XUSER_MAX_COUNT || GameSettingsA[iPad] == nullptr) + { + return 0; + } + + switch(eVal) + { + case eGameSetting_MusicVolume: + return GameSettingsA[iPad]->ucMusicVolume; + break; + case eGameSetting_SoundFXVolume: + return GameSettingsA[iPad]->ucSoundFXVolume; + break; + case eGameSetting_RenderDistance: + { + int val = (GameSettingsA[iPad]->uiBitmaskValues >> 16) & 0xFF; + if(val == 0) return val = 16; //brain + return val; + break; + } + case eGameSetting_Gamma: + return GameSettingsA[iPad]->ucGamma; + break; + case eGameSetting_FOV: + return GameSettingsA[iPad]->ucFov; + break; + case eGameSetting_Difficulty: + return GameSettingsA[iPad]->usBitmaskValues&0x0003; + break; + case eGameSetting_Sensitivity_InGame: + return GameSettingsA[iPad]->ucSensitivity; + break; + case eGameSetting_ViewBob: + return ((GameSettingsA[iPad]->usBitmaskValues&0x0004)>>2); + break; + case eGameSetting_GamertagsVisible: + return ((GameSettingsA[iPad]->usBitmaskValues&0x0008)>>3); + break; + case eGameSetting_ControlScheme: + return ((GameSettingsA[iPad]->usBitmaskValues&0x0030)>>4); // 2 bits + break; + case eGameSetting_ControlInvertLook: + return ((GameSettingsA[iPad]->usBitmaskValues&0x0040)>>6); + break; + case eGameSetting_ControlSouthPaw: + return ((GameSettingsA[iPad]->usBitmaskValues&0x0080)>>7); + break; + case eGameSetting_SplitScreenVertical: + return ((GameSettingsA[iPad]->usBitmaskValues&0x0100)>>8); + break; + // 4J-PB - Added for Interim TU for 1.6.6 + case eGameSetting_Sensitivity_InMenu: + return GameSettingsA[iPad]->ucMenuSensitivity; + break; + + case eGameSetting_DisplaySplitscreenGamertags: + return ((GameSettingsA[iPad]->usBitmaskValues&0x0200)>>9); + break; + + case eGameSetting_Hints: + return ((GameSettingsA[iPad]->usBitmaskValues&0x0400)>>10); + break; + case eGameSetting_Autosave: + { + unsigned char ucVal=(GameSettingsA[iPad]->usBitmaskValues&0x7800)>>11; + return ucVal; + } + break; + case eGameSetting_Tooltips: + return ((GameSettingsA[iPad]->usBitmaskValues&0x8000)>>15); + break; + + case eGameSetting_InterfaceOpacity: + return GameSettingsA[iPad]->ucInterfaceOpacity; + break; + + case eGameSetting_Clouds: + return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_CLOUDS); + break; + case eGameSetting_Online: + return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_ONLINE)>>1; + break; + case eGameSetting_InviteOnly: + return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_INVITEONLY)>>2; + break; + case eGameSetting_FriendsOfFriends: + return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_FRIENDSOFFRIENDS)>>3; + break; + case eGameSetting_DisplayUpdateMessage: + return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYUPDATEMSG)>>4; + break; + case eGameSetting_BedrockFog: + return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_BEDROCKFOG)>>6; + break; + case eGameSetting_DisplayHUD: + return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYHUD)>>7; + break; + case eGameSetting_DisplayHand: + return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DISPLAYHAND)>>8; + break; + case eGameSetting_CustomSkinAnim: + return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_CUSTOMSKINANIM)>>9; + break; + // TU9 + case eGameSetting_DeathMessages: + return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_DEATHMESSAGES)>>10; + break; + case eGameSetting_UISize: + { + unsigned char ucVal=(GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_UISIZE)>>11; + return ucVal; + } + break; + case eGameSetting_UISizeSplitscreen: + { + unsigned char ucVal=(GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_UISIZE_SPLITSCREEN)>>13; + return ucVal; + } + break; + case eGameSetting_AnimatedCharacter: + return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_ANIMATEDCHARACTER)>>15; + + case eGameSetting_PS3_EULA_Read: + return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PS3EULAREAD)>>16; + + case eGameSetting_PSVita_NetworkModeAdhoc: + return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PSVITANETWORKMODEADHOC)>>17; + + case eGameSetting_ClassicCrafting: + return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_CLASSICCRAFTING) >> 26; + + case eGameSetting_CaveSounds: + return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_CAVESOUNDS) >> 27; + + case eGameSetting_MinecartSounds: + return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_MINECARTSOUNDS) >> 28; + + case eGameSetting_HideSaveSizeBar: + return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_HIDESAVESIZEBAR) >> 27; + + case eGameSetting_VSync: + return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_VSYNC)>>24; + + case eGameSetting_ExclusiveFullscreen: + return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_EXCLUSIVEFULLSCREEN)>>25; + case eGameSetting_ControlType: + return (GameSettingsA[iPad]->uiBitmaskValues & 0x00070000) >> 16; + + case eGameSetting_SafeCam: + return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_SAFECAM) >> 30; + + case eGameSetting_Swap: + return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_SWAP) >> 31; + + } + return 0; +} + +void CMinecraftApp::CheckGameSettingsChanged(bool bOverride5MinuteTimer, int iPad) +{ + // If the settings have changed, write them to the profile + + if(iPad==XUSER_INDEX_ANY) + { + for(int i=0;ibSettingsChanged) + { +#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__ ) + StorageManager.WriteToProfile(i,true, bOverride5MinuteTimer); +#else + ProfileManager.WriteToProfile(i,true, bOverride5MinuteTimer); +#ifdef _WINDOWS64 + Win64_SaveSettings(GameSettingsA[i]); +#endif +#endif + GameSettingsA[i]->bSettingsChanged=false; + } + } + } + else + { + if(GameSettingsA[iPad]->bSettingsChanged) + { +#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) + StorageManager.WriteToProfile(iPad,true, bOverride5MinuteTimer); +#else + ProfileManager.WriteToProfile(iPad,true, bOverride5MinuteTimer); +#ifdef _WINDOWS64 + Win64_SaveSettings(GameSettingsA[iPad]); +#endif +#endif + GameSettingsA[iPad]->bSettingsChanged=false; + } + } +} + +void CMinecraftApp::ClearGameSettingsChangedFlag(int iPad) +{ + GameSettingsA[iPad]->bSettingsChanged=false; +} + +/////////////////////////// +// +// Remove the debug settings in the release build +// +//////////////////////////// +#ifndef _DEBUG +unsigned int CMinecraftApp::GetGameSettingsDebugMask(int iPad,bool bOverridePlayer) //bOverridePlayer is to force the send for the server to get the read options +{ + return 0; +} + +void CMinecraftApp::SetGameSettingsDebugMask(int iPad, unsigned int uiVal) +{ +} + +void CMinecraftApp::ActionDebugMask(int iPad,bool bSetAllClear) +{ +} + +#else + +unsigned int CMinecraftApp::GetGameSettingsDebugMask(int iPad,bool bOverridePlayer) //bOverridePlayer is to force the send for the server to get the read options +{ + if(iPad==-1) + { + iPad=ProfileManager.GetPrimaryPad(); + } + if(iPad < 0) iPad = 0; + + shared_ptr player = Minecraft::GetInstance()->localplayers[iPad]; + + if(bOverridePlayer || player==nullptr) + { + return GameSettingsA[iPad]->uiDebugBitmask; + } + else + { + return player->GetDebugOptions(); + } +} + + +void CMinecraftApp::SetGameSettingsDebugMask(int iPad, unsigned int uiVal) +{ +#ifndef _CONTENT_PACKAGE + GameSettingsA[iPad]->bSettingsChanged=true; + GameSettingsA[iPad]->uiDebugBitmask=uiVal; + + // update the value so the network server can use it + shared_ptr player = Minecraft::GetInstance()->localplayers[iPad]; + + if(player) + { + Minecraft::GetInstance()->localgameModes[iPad]->handleDebugOptions(uiVal,player); + } +#endif +} + +void CMinecraftApp::ActionDebugMask(int iPad,bool bSetAllClear) +{ + unsigned int ulBitmask=app.GetGameSettingsDebugMask(iPad); + + if(bSetAllClear) ulBitmask=0L; + + + + // these settings should only be actioned for the primary player + if(ProfileManager.GetPrimaryPad()!=iPad) return; + + for(int i=0;i(param); + app.SetAction(actionInfo->iPad, actionInfo->action); +} + + +void CMinecraftApp::HandleXuiActions(void) +{ + eXuiAction eAction; + eTMSAction eTMS; + LPVOID param; + Minecraft *pMinecraft=Minecraft::GetInstance(); + shared_ptr player; + + // are there any global actions to deal with? + eAction = app.GetGlobalXuiAction(); + if(eAction!=eAppAction_Idle) + { + switch(eAction) + { + case eAppAction_DisplayLavaMessage: + // Display a warning about placing lava in the spawn area + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_CANT_PLACE_NEAR_SPAWN_TITLE, IDS_CANT_PLACE_NEAR_SPAWN_TEXT, uiIDA,1,XUSER_INDEX_ANY); + if(result != C4JStorage::EMessage_Busy) SetGlobalXuiAction(eAppAction_Idle); + + } + break; + default: + break; + } + } + + // are there any app actions to deal with? + for(int i=0;iIsTitleAllowedToPostImages() && CSocialManager::Instance()->AreAllUsersAllowedToPostImages() ) + { + // disable character name tags for the shot + //m_bwasHidingGui = pMinecraft->options->hideGui; // 4J Stu - Removed 1.8.2 bug fix (TU6) as don't need this + pMinecraft->options->hideGui = true; + + SetAction(i,eAppAction_SocialPostScreenshot); + } + else + { + SetAction(i,eAppAction_Idle); + } + } + else + { + SetAction(i,eAppAction_Idle); + } + break; + case eAppAction_SocialPostScreenshot: + { + SetAction(i,eAppAction_Idle); + bool bKeepHiding = false; + for(int j=0; j < XUSER_MAX_COUNT;++j) + { + if(app.GetXuiAction(j) == eAppAction_SocialPostScreenshot) + { + bKeepHiding = true; + break; + } + } + pMinecraft->options->hideGui=bKeepHiding; + + // Facebook Share + + if(app.GetLocalPlayerCount()>1) + { + ui.NavigateToScene(i,eUIScene_SocialPost); + } + else + { + ui.NavigateToScene(i,eUIScene_SocialPost); + } + } + break; + case eAppAction_SaveGame: + SetAction(i,eAppAction_Idle); + if(!GetChangingSessionType()) + { + // If this is the trial game, do an upsell + if(ProfileManager.IsFullVersion()) + { + + // flag the render to capture the screenshot for the save + SetAction(i,eAppAction_SaveGameCapturedThumbnail); + } + else + { + // ask the player if they would like to upgrade, or they'll lose the level + + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + ui.RequestErrorMessage(IDS_UNLOCK_TITLE, IDS_UNLOCK_TOSAVE_TEXT, uiIDA, 2,i,&CMinecraftApp::UnlockFullSaveReturned,this); + } + } + + break; + case eAppAction_AutosaveSaveGame: + { + // Need to run a check to see if the save exists in order to stop the dialog asking if we want to overwrite it coming up on an autosave + bool bSaveExists; + StorageManager.DoesSaveExist(&bSaveExists); + + SetAction(i,eAppAction_Idle); + if(!GetChangingSessionType()) + { + + // flag the render to capture the screenshot for the save + SetAction(i,eAppAction_AutosaveSaveGameCapturedThumbnail); + } + } + + break; + + case eAppAction_SaveGameCapturedThumbnail: + // reset the autosave timer + app.SetAutosaveTimerTime(); + SetAction(i,eAppAction_Idle); + // Check that there is a name for the save - if we're saving from the tutorial and this is the first save from the tutorial, we'll not have a name + /*if(StorageManager.GetSaveName()==nullptr) + { + app.NavigateToScene(i,eUIScene_SaveWorld); + } + else*/ + { + // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen + ui.HideAllGameUIElements(); + + // Hide the other players scenes + ui.ShowOtherPlayersBaseScene(ProfileManager.GetPrimaryPad(), false); + + //INT saveOrCheckpointId = 0; + //bool validSave = StorageManager.GetSaveUniqueNumber(&saveOrCheckpointId); + //SentientManager.RecordLevelSaveOrCheckpoint(ProfileManager.GetPrimaryPad(), saveOrCheckpointId); + + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &UIScene_PauseMenu::SaveWorldThreadProc; + loadingParams->lpParam = static_cast(false); + + // 4J-JEV - PS4: Fix for #5708 - [ONLINE] - If the user pulls their network cable out while saving the title will hang. + loadingParams->waitForThreadToDelete = true; + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->type = e_ProgressCompletion_NavigateBackToScene; + completionData->iPad = ProfileManager.GetPrimaryPad(); + + if( ui.IsSceneInStack( ProfileManager.GetPrimaryPad(), eUIScene_EndPoem ) ) + { + completionData->scene = eUIScene_EndPoem; + } + else + { + completionData->scene = eUIScene_PauseMenu; + } + + loadingParams->completionData = completionData; + + // 4J Stu - Xbox only +#ifdef _XBOX + // Temporarily make this scene fullscreen + CXuiSceneBase::SetPlayerBaseScenePosition( ProfileManager.GetPrimaryPad(), CXuiSceneBase::e_BaseScene_Fullscreen ); +#endif + + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams , eUILayer_Fullscreen, eUIGroup_Fullscreen); + + } + break; + case eAppAction_AutosaveSaveGameCapturedThumbnail: + + { + app.SetAutosaveTimerTime(); + SetAction(i,eAppAction_Idle); + +#if defined(_XBOX_ONE) || defined(__ORBIS__) + app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_AutoSaveGame); + + if(app.GetGameHostOption(eGameHostOption_DisableSaving)) StorageManager.SetSaveDisabled(true); +#else + // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen + ui.HideAllGameUIElements(); + + //app.CloseAllPlayersXuiScenes(); + // Hide the other players scenes + ui.ShowOtherPlayersBaseScene(ProfileManager.GetPrimaryPad(), false); + + // This just allows it to be shown + if(pMinecraft->localgameModes[ProfileManager.GetPrimaryPad()] != nullptr) pMinecraft->localgameModes[ProfileManager.GetPrimaryPad()]->getTutorial()->showTutorialPopup(false); + + //INT saveOrCheckpointId = 0; + //bool validSave = StorageManager.GetSaveUniqueNumber(&saveOrCheckpointId); + //SentientManager.RecordLevelSaveOrCheckpoint(ProfileManager.GetPrimaryPad(), saveOrCheckpointId); + + + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &UIScene_PauseMenu::SaveWorldThreadProc; + + loadingParams->lpParam = (LPVOID)(true); + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->type = e_ProgressCompletion_AutosaveNavigateBack; + completionData->iPad = ProfileManager.GetPrimaryPad(); + //completionData->bAutosaveWasMenuDisplayed=ui.GetMenuDisplayed(ProfileManager.GetPrimaryPad()); + loadingParams->completionData = completionData; + + // 4J Stu - Xbox only +#ifdef _XBOX + // Temporarily make this scene fullscreen + CXuiSceneBase::SetPlayerBaseScenePosition( ProfileManager.GetPrimaryPad(), CXuiSceneBase::e_BaseScene_Fullscreen ); +#endif + + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams , eUILayer_Fullscreen, eUIGroup_Fullscreen); +#endif + } + break; + case eAppAction_ExitPlayer: + // a secondary player has chosen to quit + { + int iPlayerC=g_NetworkManager.GetPlayerCount(); + + // Since the player is exiting, let's flush any profile writes for them, and hope we're not breaking TCR 136... +#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) + StorageManager.ForceQueuedProfileWrites(i); + LeaderboardManager::Instance()->OpenSession(); + for (int j = 0; j < XUSER_MAX_COUNT; j++) + { + if( ProfileManager.IsSignedIn(j) ) + { + app.DebugPrintf("Stats save for an offline game for the player at index %d\n", 0); + Minecraft::GetInstance()->forceStatsSave(j); + } + } + LeaderboardManager::Instance()->CloseSession(); +#else + ProfileManager.ForceQueuedProfileWrites(i); +#endif + + // not required - it's done within the removeLocalPlayerIdx + // if(pMinecraft->level->isClientSide) + // { + // // we need to remove the qnetplayer, or this player won't be able to get back into the game until qnet times out and removes them + // g_NetworkManager.NotifyPlayerLeaving(g_NetworkManager.GetLocalPlayerByUserIndex(i)); + // } + + // if there are any tips showing, we need to close them + + pMinecraft->gui->clearMessages(i); + + // Make sure we've not got this player selected as current - this shouldn't be the case anyway + pMinecraft->setLocalPlayerIdx(ProfileManager.GetPrimaryPad()); + pMinecraft->removeLocalPlayerIdx(i); + +#ifdef _XBOX + // tell the xui scenes a splitscreen player left - has to come after removeLocalPlayerIdx which calls updatePlayerViewportAssignments + XUIMessage xuiMsg; + CustomMessage_Splitscreenplayer_Struct myMsgData; + CustomMessage_Splitscreenplayer( &xuiMsg, &myMsgData, false); + + // send the message + for(int idx=0;idxlocalplayers[idx]!=nullptr)) + { + XuiBroadcastMessage( CXuiSceneBase::GetPlayerBaseScene(idx), &xuiMsg ); + } + } +#endif + +#ifndef _XBOX + // Wipe out the tooltips + ui.SetTooltips(i, -1); +#endif + + // Change the presence info + // Are we offline or online, and how many players are there + if(iPlayerC>2) // one player is about to leave here - they'll be set to idle in the qnet manager player leave + { + for(int iPlayer=0;iPlayerlocalplayers[iPlayer]) + { + if(g_NetworkManager.IsLocalGame()) + { + ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false); + } + else + { + ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER,false); + } + } + } + } + else + { + for(int iPlayer=0;iPlayerlocalplayers[iPlayer]) + { + if(g_NetworkManager.IsLocalGame()) + { + ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE,false); + } + else + { + ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER_1P,false); + } + } + } + } + +#ifdef _DURANGO + ProfileManager.RemoveGamepadFromGame(i); +#endif + + SetAction(i,eAppAction_Idle); + } + break; + case eAppAction_ExitPlayerPreLogin: + { + int iPlayerC=g_NetworkManager.GetPlayerCount(); + // Since the player is exiting, let's flush any profile writes for them, and hope we're not breaking TCR 136... +#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) + StorageManager.ForceQueuedProfileWrites(i); +#else + ProfileManager.ForceQueuedProfileWrites(i); +#endif + // if there are any tips showing, we need to close them + + pMinecraft->gui->clearMessages(i); + + // Make sure we've not got this player selected as current - this shouldn't be the case anyway + pMinecraft->setLocalPlayerIdx(ProfileManager.GetPrimaryPad()); + pMinecraft->removeLocalPlayerIdx(i); + +#ifdef _XBOX + // tell the xui scenes a splitscreen player left - has to come after removeLocalPlayerIdx which calls updatePlayerViewportAssignments + XUIMessage xuiMsg; + CustomMessage_Splitscreenplayer_Struct myMsgData; + CustomMessage_Splitscreenplayer( &xuiMsg, &myMsgData, false); + + // send the message + for(int idx=0;idxlocalplayers[idx]!=nullptr)) + { + XuiBroadcastMessage( CXuiSceneBase::GetPlayerBaseScene(idx), &xuiMsg ); + } + } +#endif + +#ifndef _XBOX + // Wipe out the tooltips + ui.SetTooltips(i, -1); +#endif + + // Change the presence info + // Are we offline or online, and how many players are there + if(iPlayerC>2) // one player is about to leave here - they'll be set to idle in the qnet manager player leave + { + for(int iPlayer=0;iPlayerlocalplayers[iPlayer]) + { + if(g_NetworkManager.IsLocalGame()) + { + ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false); + } + else + { + ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER,false); + } + } + } + } + else + { + for(int iPlayer=0;iPlayerlocalplayers[iPlayer]) + { + if(g_NetworkManager.IsLocalGame()) + { + ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE,false); + } + else + { + ProfileManager.SetCurrentGameActivity(iPlayer,CONTEXT_PRESENCE_MULTIPLAYER_1P,false); + } + } + } + } + SetAction(i,eAppAction_Idle); + } + break; + +#ifdef __ORBIS__ + case eAppAction_OptionsSaveNoSpace: + { + SetAction(i,eAppAction_Idle); + + SceSaveDataDialogParam param; + SceSaveDataDialogSystemMessageParam sysParam; + SceSaveDataDialogItems items; + SceSaveDataDirName dirName; + + sceSaveDataDialogParamInitialize(¶m); + param.mode = SCE_SAVE_DATA_DIALOG_MODE_SYSTEM_MSG; + param.dispType = SCE_SAVE_DATA_DIALOG_TYPE_SAVE; + memset(&sysParam,0,sizeof(sysParam)); + param.sysMsgParam = &sysParam; + param.sysMsgParam->sysMsgType = SCE_SAVE_DATA_DIALOG_SYSMSG_TYPE_NOSPACE_CONTINUABLE; + param.sysMsgParam->value = app.GetOptionsBlocksRequired(i); + memset(&items, 0, sizeof(items)); + param.items = &items; + param.items->userId = ProfileManager.getUserID(i); + + int ret = sceSaveDataDialogInitialize(); + ret = sceSaveDataDialogOpen(¶m); + + app.SetOptionsSaveDataDialogRunning(true);//m_bOptionsSaveDataDialogRunning = true; + //pClass->m_eSaveIncompleteType = saveIncompleteType; + + //StorageManager.SetSaveDisabled(true); + //pClass->EnterSaveNotificationSection(); + + } + break; +#endif + + case eAppAction_ExitWorld: + + SetAction(i,eAppAction_Idle); + + // HUCKLE - added for quit game on disconnect +#ifdef _WINDOWS64 + if(g_Win64MultiplayerQuitOnDisconnect == true) + { + app.ExitGame(); + return; + } +#endif + + // If we're already leaving don't exit + if (g_NetworkManager.IsLeavingGame()) + { + break; + } + + pMinecraft->gui->clearMessages(); + + // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen + ui.HideAllGameUIElements(); + + // reset the flag stopping new dlc message being shown if you've seen the message before + DisplayNewDLCTipAgain(); + + // clear the autosave timer that might be on screen + ui.ShowAutosaveCountdownTimer(false); + + // Hide the selected item text + ui.HideAllGameUIElements(); + + // Since the player forced the exit, let's flush any profile writes, and hope we're not breaking TCR 136... +#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) + StorageManager.ForceQueuedProfileWrites(); + LeaderboardManager::Instance()->OpenSession(); + for (int j = 0; j < XUSER_MAX_COUNT; j++) + { + if( ProfileManager.IsSignedIn(j) ) + { + app.DebugPrintf("Stats save for an offline game for the player at index %d\n", 0); + Minecraft::GetInstance()->forceStatsSave(j); + } + } + LeaderboardManager::Instance()->CloseSession(); +#elif (defined _XBOX) + ProfileManager.ForceQueuedProfileWrites(); +#endif + + // 4J-PB - cancel any possible string verifications queued with LIVE + //InputManager.CancelAllVerifyInProgress(); + + if(ProfileManager.IsFullVersion()) + { + + // In a split screen, only the primary player actually quits the game, others just remove their players + if( i != ProfileManager.GetPrimaryPad() ) + { + // Make sure we've not got this player selected as current - this shouldn't be the case anyway + pMinecraft->setLocalPlayerIdx(ProfileManager.GetPrimaryPad()); + pMinecraft->removeLocalPlayerIdx(i); + +#ifdef _DURANGO + ProfileManager.RemoveGamepadFromGame(i); +#endif + SetAction(i,eAppAction_Idle); + return; + } + // flag to capture the save thumbnail + SetAction(i,eAppAction_ExitWorldCapturedThumbnail, param); + } + else + { + // ask the player if they would like to upgrade, or they'll lose the level + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + ui.RequestErrorMessage(IDS_UNLOCK_TITLE, IDS_UNLOCK_TOSAVE_TEXT, uiIDA, 2, i,&CMinecraftApp::UnlockFullExitReturned,this); + } + + // Change the presence info + // Are we offline or online, and how many players are there + + if(g_NetworkManager.GetPlayerCount()>1) + { + for(int j=0;jlocalplayers[j]) + { + if(g_NetworkManager.IsLocalGame()) + { + app.SetRichPresenceContext(j,CONTEXT_GAME_STATE_BLANK); + ProfileManager.SetCurrentGameActivity(j,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false); + } + else + { + app.SetRichPresenceContext(j,CONTEXT_GAME_STATE_BLANK); + ProfileManager.SetCurrentGameActivity(j,CONTEXT_PRESENCE_MULTIPLAYER,false); + } + TelemetryManager->RecordLevelExit(j, eSen_LevelExitStatus_Exited); + } + } + } + else + { + app.SetRichPresenceContext(i,CONTEXT_GAME_STATE_BLANK); + if(g_NetworkManager.IsLocalGame()) + { + ProfileManager.SetCurrentGameActivity(i,CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE,false); + } + else + { + ProfileManager.SetCurrentGameActivity(i,CONTEXT_PRESENCE_MULTIPLAYER_1P,false); + } + TelemetryManager->RecordLevelExit(i, eSen_LevelExitStatus_Exited); + } + break; + case eAppAction_ExitWorldCapturedThumbnail: + { + SetAction(i,eAppAction_Idle); + // Stop app running + SetGameStarted(false); + SetChangingSessionType(true); // Added to stop handling ethernet disconnects + + ui.CloseAllPlayersScenes(); + + // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen + ui.HideAllGameUIElements(); + + // 4J Stu - Fix for #12368 - Crash: Game crashes when saving then exiting and selecting to save + for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx) + { +#ifdef _XBOX + app.TutorialSceneNavigateBack(idx,true); +#endif + + // 4J Stu - Fix for #13257 - CRASH: Gameplay: Title crashed after exiting the tutorial + // It doesn't matter if they were in the tutorial already + pMinecraft->playerLeftTutorial( idx ); + } + + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &UIScene_PauseMenu::ExitWorldThreadProc; + loadingParams->lpParam = param; + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + // If param is non-null then this is a forced exit by the server, so make sure the player knows why + // 4J Stu - Changed - Don't use the FullScreenProgressScreen for action, use a dialog instead + completionData->bRequiresUserAction = FALSE;//(param != nullptr) ? TRUE : FALSE; + completionData->bShowTips = (param != nullptr) ? FALSE : TRUE; + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->type = e_ProgressCompletion_NavigateToHomeMenu; + completionData->iPad = DEFAULT_XUI_MENU_USER; + loadingParams->completionData = completionData; + + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); + } + break; + case eAppAction_ExitWorldTrial: + { + SetAction(i,eAppAction_Idle); + + pMinecraft->gui->clearMessages(); + + // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen + ui.HideAllGameUIElements(); + + // Stop app running + SetGameStarted(false); + + ui.CloseAllPlayersScenes(); + + // 4J Stu - Fix for #12368 - Crash: Game crashes when saving then exiting and selecting to save + for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx) + { +#ifdef _XBOX + app.TutorialSceneNavigateBack(idx,true); +#endif + + // 4J Stu - Fix for #13257 - CRASH: Gameplay: Title crashed after exiting the tutorial + // It doesn't matter if they were in the tutorial already + pMinecraft->playerLeftTutorial( idx ); + } + + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &UIScene_PauseMenu::ExitWorldThreadProc; + loadingParams->lpParam = param; + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->type = e_ProgressCompletion_NavigateToHomeMenu; + completionData->iPad = DEFAULT_XUI_MENU_USER; + loadingParams->completionData = completionData; + + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); + } + + break; + case eAppAction_ExitTrial: + //XLaunchNewImage(XLAUNCH_KEYWORD_DASH_ARCADE, 0); + ExitGame(); + break; + + case eAppAction_Respawn: + { + ConnectionProgressParams *param = new ConnectionProgressParams(); + param->iPad = i; + param->stringId = IDS_PROGRESS_RESPAWNING; + param->showTooltips = false; + param->setFailTimer = false; + ui.NavigateToScene(i,eUIScene_ConnectingProgress, param); + + // Need to reset this incase the player has already died and respawned + pMinecraft->localplayers[i]->SetPlayerRespawned(false); + + SetAction(i,eAppAction_WaitForRespawnComplete); + if( app.GetLocalPlayerCount()>1 ) + { + // In split screen mode, we don't want to do any async loading or flushing of the cache, just a simple respawn + pMinecraft->localplayers[i]->respawn(); + + // If the respawn requires a dimension change then the action will have changed + //if(app.GetXuiAction(i) == eAppAction_Respawn) + //{ + // SetAction(i,eAppAction_Idle); + // CloseXuiScenes(i); + //} + } + else + { + //SetAction(i,eAppAction_WaitForRespawnComplete); + + //LoadingInputParams *loadingParams = new LoadingInputParams(); + //loadingParams->func = &CScene_Death::RespawnThreadProc; + //loadingParams->lpParam = (LPVOID)i; + + // Disable game & update thread whilst we do any of this + //app.SetGameStarted(false); + pMinecraft->gameRenderer->DisableUpdateThread(); + + // 4J Stu - We don't need this on a thread in multiplayer as respawning is asynchronous. + pMinecraft->localplayers[i]->respawn(); + + //app.SetGameStarted(true); + pMinecraft->gameRenderer->EnableUpdateThread(); + + //UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + //completionData->bShowBackground=TRUE; + //completionData->bShowLogo=TRUE; + //completionData->type = e_ProgressCompletion_CloseUIScenes; + //completionData->iPad = i; + //loadingParams->completionData = completionData; + + //app.NavigateToScene(i,eUIScene_FullscreenProgress, loadingParams, true); + } + } + break; + case eAppAction_WaitForRespawnComplete: + player = pMinecraft->localplayers[i]; + if(player != nullptr && player->GetPlayerRespawned()) + { + SetAction(i,eAppAction_Idle); + + if(ui.IsSceneInStack(i, eUIScene_EndPoem)) + { + ui.NavigateBack(i,false,eUIScene_EndPoem); + } + else + { + ui.CloseUIScenes(i); + } + + // clear the progress messages + + // pMinecraft->progressRenderer->progressStart(-1); + // pMinecraft->progressRenderer->progressStage(-1); + } + else if(!g_NetworkManager.IsInGameplay()) + { + SetAction(i,eAppAction_Idle); + } + break; + case eAppAction_WaitForDimensionChangeComplete: + player = pMinecraft->localplayers[i]; + if(player != nullptr && player->connection && player->connection->isStarted()) + { + SetAction(i,eAppAction_Idle); + ui.CloseUIScenes(i); + } + else if(!g_NetworkManager.IsInGameplay()) + { + SetAction(i,eAppAction_Idle); + } + break; + case eAppAction_PrimaryPlayerSignedOut: + { + //SetAction(i,eAppAction_Idle); + + // clear the autosavetimer that might be displayed + ui.ShowAutosaveCountdownTimer(false); + + // If the player signs out before the game started the server can be killed a bit earlier to stop + // the loading or saving of a new game continuing running while the UI/Guide is up + if(!app.GetGameStarted()) MinecraftServer::HaltServer(true); + + // inform the player they are being returned to the menus because they signed out + StorageManager.SetSaveDeviceSelected(i,false); + // need to clear the player stats - can't assume it'll be done in setlevel - we may not be in the game + StatsCounter* pStats = Minecraft::GetInstance()->stats[ i ]; + pStats->clear(); + + // 4J-PB - the libs will display the Returned to Title screen + // UINT uiIDA[1]; + // uiIDA[0]=IDS_CONFIRM_OK; + // + // ui.RequestMessageBox(IDS_RETURNEDTOMENU_TITLE, IDS_RETURNEDTOTITLESCREEN_TEXT, uiIDA, 1, i,&CMinecraftApp::PrimaryPlayerSignedOutReturned,this,app.GetStringTable()); + if( g_NetworkManager.IsInSession() ) + { + app.SetAction(i,eAppAction_PrimaryPlayerSignedOutReturned); + } + else + { + app.SetAction(i,eAppAction_PrimaryPlayerSignedOutReturned_Menus); + MinecraftServer::resetFlags(); + } + } + break; + case eAppAction_EthernetDisconnected: + { + app.DebugPrintf("Handling eAppAction_EthernetDisconnected\n"); + SetAction(i,eAppAction_Idle); + + // 4J Stu - Fix for #12530 -TCR 001 BAS Game Stability: Title will crash if the player disconnects while starting a new world and then opts to play the tutorial once they have been returned to the Main Menu. + if(!g_NetworkManager.IsLeavingGame()) + { + app.DebugPrintf("Handling eAppAction_EthernetDisconnected - Not leaving game\n"); + // 4J-PB - not the same as a signout. We should only leave the game if this machine is not the host. We shouldn't get rid of the save device either. + if( g_NetworkManager.IsHost() ) + { + app.DebugPrintf("Handling eAppAction_EthernetDisconnected - Is Host\n"); + // If it's already a local game, then an ethernet disconnect should have no effect + if( !g_NetworkManager.IsLocalGame() && g_NetworkManager.IsInGameplay() ) + { + // Change the session to an offline session + SetAction(i,eAppAction_ChangeSessionType); + } + else if(!g_NetworkManager.IsLocalGame() && !g_NetworkManager.IsInGameplay() ) + { + // There are two cases here, either: + // 1. We're early enough in the create/load game that we can do a really minimal shutdown or + // 2. We're far enough in (game has started but the actual game started flag hasn't been set) that we should just wait until we're in the game and switch to offline mode + + // If there's a non-null level then, for our purposes, the game has started + bool gameStarted = false; + for(int j = 0; j < pMinecraft->levels.length; j++) + { + if (pMinecraft->levels.data[i] != nullptr) + { + gameStarted = true; + break; + } + } + + if (!gameStarted) + { + // 1. Exit + MinecraftServer::HaltServer(); + + // Fix for #12530 - TCR 001 BAS Game Stability: Title will crash if the player disconnects while starting a new world and then opts to play the tutorial once they have been returned to the Main Menu. + // 4J Stu - Leave the session + g_NetworkManager.LeaveGame(FALSE); + + // need to clear the player stats - can't assume it'll be done in setlevel - we may not be in the game + StatsCounter* pStats = Minecraft::GetInstance()->stats[ i ]; + pStats->clear(); + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + + ui.RequestErrorMessage(g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST), g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE), uiIDA, 1, i,&CMinecraftApp::EthernetDisconnectReturned,this); + } + else + { + // 2. Switch to offline + SetAction(i,eAppAction_ChangeSessionType); + } + } + } + else + { +#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ + if(UIScene_LoadOrJoinMenu::isSaveTransferRunning()) + { + // the save transfer is still in progress, delay jumping back to the main menu until we've cleaned up + SetAction(i,eAppAction_EthernetDisconnected); + } + else +#endif + { + app.DebugPrintf("Handling eAppAction_EthernetDisconnected - Not host\n"); + // need to clear the player stats - can't assume it'll be done in setlevel - we may not be in the game + StatsCounter* pStats = Minecraft::GetInstance()->stats[ i ]; + pStats->clear(); + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + + ui.RequestErrorMessage(g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST), g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE), uiIDA, 1, i,&CMinecraftApp::EthernetDisconnectReturned,this); + + } + } + } + } + break; + // We currently handle both these returns the same way. + case eAppAction_EthernetDisconnectedReturned: + case eAppAction_PrimaryPlayerSignedOutReturned: + { + SetAction(i,eAppAction_Idle); + + pMinecraft->gui->clearMessages(); + + // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen + ui.HideAllGameUIElements(); + + // set the state back to pre-game + ProfileManager.ResetProfileProcessState(); + + + if( g_NetworkManager.IsLeavingGame() ) + { + // 4J Stu - If we are already leaving the game, then we just need to signal that the player signed out to stop saves + pMinecraft->progressRenderer->progressStartNoAbort( IDS_EXITING_GAME ); + pMinecraft->progressRenderer->progressStage(-1); + // This has no effect on client machines + MinecraftServer::HaltServer(true); + } + else + { + // Stop app running + SetGameStarted(false); + + // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen + ui.HideAllGameUIElements(); + + ui.CloseAllPlayersScenes(); + + // 4J Stu - Fix for #12368 - Crash: Game crashes when saving then exiting and selecting to save + for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx) + { +#ifdef _XBOX + app.TutorialSceneNavigateBack(idx,true); +#endif + + // 4J Stu - Fix for #13257 - CRASH: Gameplay: Title crashed after exiting the tutorial + // It doesn't matter if they were in the tutorial already + pMinecraft->playerLeftTutorial( idx ); + } + + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &CMinecraftApp::SignoutExitWorldThreadProc; + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->iPad=DEFAULT_XUI_MENU_USER; + completionData->type = e_ProgressCompletion_NavigateToHomeMenu; + loadingParams->completionData = completionData; + + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); + } + } + break; + case eAppAction_PrimaryPlayerSignedOutReturned_Menus: + SetAction(i,eAppAction_Idle); + // set the state back to pre-game + ProfileManager.ResetProfileProcessState(); + // clear the save device + StorageManager.SetSaveDeviceSelected(i,false); + + ui.UpdatePlayerBasePositions(); + // there are multiple layers in the help menu, so a navigate back isn't enough + ui.NavigateToHomeMenu(); + + break; + case eAppAction_EthernetDisconnectedReturned_Menus: + SetAction(i,eAppAction_Idle); + // set the state back to pre-game + ProfileManager.ResetProfileProcessState(); + + ui.UpdatePlayerBasePositions(); + + // there are multiple layers in the help menu, so a navigate back isn't enough + ui.NavigateToHomeMenu(); + + break; + + case eAppAction_TrialOver: + { + SetAction(i,eAppAction_Idle); + UINT uiIDA[2]; + uiIDA[0]=IDS_UNLOCK_TITLE; + uiIDA[1]=IDS_EXIT_GAME; + + ui.RequestErrorMessage(IDS_TRIALOVER_TITLE, IDS_TRIALOVER_TEXT, uiIDA, 2, i,&CMinecraftApp::TrialOverReturned,this); + } + break; + + // INVITES + case eAppAction_DashboardTrialJoinFromInvite: + { + TelemetryManager->RecordUpsellPresented(i, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID); + + SetAction(i,eAppAction_Idle); + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + + ui.RequestErrorMessage(IDS_UNLOCK_TITLE, IDS_UNLOCK_ACCEPT_INVITE, uiIDA, 2, i,&CMinecraftApp::UnlockFullInviteReturned,this); + } + break; + case eAppAction_ExitAndJoinFromInvite: + { + UINT uiIDA[3]; + + SetAction(i,eAppAction_Idle); + // Check the player really wants to do this + +#if defined(_XBOX_ONE) || defined(__ORBIS__) + // Show save option is saves ARE disabled + if(ProfileManager.IsFullVersion() && StorageManager.GetSaveDisabled() && i==ProfileManager.GetPrimaryPad() && g_NetworkManager.IsHost() && GetGameStarted() ) + { + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_EXIT_GAME_SAVE; + uiIDA[2]=IDS_EXIT_GAME_NO_SAVE; + + ui.RequestAlertMessage(IDS_EXIT_GAME, IDS_CONFIRM_LEAVE_VIA_INVITE, uiIDA, 3, i,&CMinecraftApp::ExitAndJoinFromInviteSaveDialogReturned,this); + } + else +#else + if(ProfileManager.IsFullVersion() && !StorageManager.GetSaveDisabled() && i==ProfileManager.GetPrimaryPad() && g_NetworkManager.IsHost() && GetGameStarted() ) + { + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_EXIT_GAME_SAVE; + uiIDA[2]=IDS_EXIT_GAME_NO_SAVE; + + ui.RequestAlertMessage(IDS_EXIT_GAME, IDS_CONFIRM_LEAVE_VIA_INVITE, uiIDA, 3, i,&CMinecraftApp::ExitAndJoinFromInviteSaveDialogReturned,this); + } + else +#endif + { + if(!ProfileManager.IsFullVersion()) + { + TelemetryManager->RecordUpsellPresented(i, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID); + + // upsell + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + ui.RequestErrorMessage(IDS_UNLOCK_TITLE, IDS_UNLOCK_ACCEPT_INVITE, uiIDA, 2, i,&CMinecraftApp::UnlockFullInviteReturned,this); + } + else + { + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestAlertMessage(IDS_EXIT_GAME, IDS_CONFIRM_LEAVE_VIA_INVITE, uiIDA, 2,i,&CMinecraftApp::ExitAndJoinFromInvite,this); + } + } + } + break; + case eAppAction_ExitAndJoinFromInviteConfirmed: + { + SetAction(i,eAppAction_Idle); + + pMinecraft->gui->clearMessages(); + + // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen + ui.HideAllGameUIElements(); + + // Stop app running + SetGameStarted(false); + + ui.CloseAllPlayersScenes(); + + // 4J Stu - Fix for #12368 - Crash: Game crashes when saving then exiting and selecting to save + for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx) + { +#ifdef _XBOX + app.TutorialSceneNavigateBack(idx,true); +#endif + + // 4J Stu - Fix for #13257 - CRASH: Gameplay: Title crashed after exiting the tutorial + // It doesn't matter if they were in the tutorial already + pMinecraft->playerLeftTutorial( idx ); + } + + // 4J-PB - may have been using a texture pack with audio , so clean up anything texture pack related here + + // unload any texture pack audio + // if there is audio in use, clear out the audio, and unmount the pack + TexturePack *pTexPack=Minecraft::GetInstance()->skins->getSelected(); + DLCTexturePack *pDLCTexPack=nullptr; + + if(pTexPack->hasAudio()) + { + // get the dlc texture pack, and store it + pDLCTexPack=static_cast(pTexPack); + } + + // change to the default texture pack + pMinecraft->skins->selectTexturePackById(TexturePackRepository::DEFAULT_TEXTURE_PACK_ID); + + if(pTexPack->hasAudio()) + { + // need to stop the streaming audio - by playing streaming audio from the default texture pack now + // reset the streaming sounds back to the normal ones +#ifndef _XBOX + pMinecraft->soundEngine->SetStreamingSounds(eStream_Overworld_Calm1,eStream_Overworld_piano3, + eStream_Nether1,eStream_Nether4, + eStream_end_dragon,eStream_end_end, + eStream_Overworld_Creative1,eStream_Overworld_Creative6, + eStream_Overworld_Menu1,eStream_Overworld_Menu4, + eStream_BattleMode1,eStream_BattleMode4, + eStream_CD_1); +#endif + pMinecraft->soundEngine->playStreaming(L"", 0, 0, 0, 1, 1); + +#ifdef _XBOX + if(pDLCTexPack->m_pStreamedWaveBank!=nullptr) + { + pDLCTexPack->m_pStreamedWaveBank->Destroy(); + } + if(pDLCTexPack->m_pSoundBank!=nullptr) + { + pDLCTexPack->m_pSoundBank->Destroy(); + } +#endif +#ifdef _DURANGO + DWORD result = StorageManager.UnmountInstalledDLC(L"TPACK"); +#else + DWORD result = StorageManager.UnmountInstalledDLC("TPACK"); +#endif + app.DebugPrintf("Unmount result is %d\n",result); + } + +#ifdef _XBOX_ONE + // 4J Stu - It's possible that we can sign in/remove players between the mask initially being set and this point + m_InviteData.dwLocalUsersMask = 0; + for(unsigned int index = 0; index < XUSER_MAX_COUNT; ++index) + { + if(ProfileManager.IsSignedIn(index) ) + { + if (index == i || pMinecraft->localplayers[index] != nullptr) + { + m_InviteData.dwLocalUsersMask |= g_NetworkManager.GetLocalPlayerMask(index); + } + } + } +#endif + + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &CGameNetworkManager::ExitAndJoinFromInviteThreadProc; + loadingParams->lpParam = static_cast(&m_InviteData); + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->iPad=DEFAULT_XUI_MENU_USER; + completionData->type = e_ProgressCompletion_NoAction; + loadingParams->completionData = completionData; + + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); + } + + break; + case eAppAction_JoinFromInvite: + { + SetAction(i,eAppAction_Idle); + + // 4J Stu - Move this state block from CPlatformNetworkManager::ExitAndJoinFromInviteThreadProc, as g_NetworkManager.JoinGameFromInviteInfo ultimately can call NavigateToScene, + /// and we should only be calling that from the main thread + app.SetTutorialMode( false ); + + g_NetworkManager.SetLocalGame(false); + + JoinFromInviteData *inviteData = static_cast(param); + // 4J-PB - clear any previous connection errors + Minecraft::GetInstance()->clearConnectionFailed(); + + app.DebugPrintf( "Changing Primary Pad on an invite accept - pad was %d, and is now %d\n", ProfileManager.GetPrimaryPad(), inviteData->dwUserIndex ); + ProfileManager.SetLockedProfile(inviteData->dwUserIndex); + ProfileManager.SetPrimaryPad(inviteData->dwUserIndex); + +#ifdef _XBOX_ONE + // 4J Stu - If a player is signed in (i.e. locked) but not in the mask, unlock them + for(unsigned int index = 0; index < XUSER_MAX_COUNT; ++index) + { + if( index != inviteData->dwUserIndex && ProfileManager.IsSignedIn(index) ) + { + if( (m_InviteData.dwLocalUsersMask & g_NetworkManager.GetLocalPlayerMask( index ) ) == 0 ) + { + ProfileManager.RemoveGamepadFromGame(index); + } + } + } +#endif + + // change the minecraft player name + Minecraft::GetInstance()->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); + + bool success = g_NetworkManager.JoinGameFromInviteInfo( + inviteData->dwUserIndex, // dwUserIndex + inviteData->dwLocalUsersMask, // dwUserMask + inviteData->pInviteInfo ); // pInviteInfo + + if( !success ) + { + app.DebugPrintf( "Failed joining game from invite\n" ); + //return hr; + + // 4J Stu - Copied this from XUI_FullScreenProgress to properly handle the fail case, as the thread will no longer be failing + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestErrorMessage( IDS_CONNECTION_FAILED, IDS_CONNECTION_LOST_SERVER, uiIDA,1,ProfileManager.GetPrimaryPad()); + + ui.NavigateToHomeMenu(); + ui.UpdatePlayerBasePositions(); + } + } + break; + case eAppAction_ChangeSessionType: + { + // If we are not in gameplay yet, then wait until the server is setup before changing the session type + if( g_NetworkManager.IsInGameplay() ) + { + // This kicks off a thread that waits for the server to end, then closes the current session, starts a new one and joins the local players into it + + SetAction(i,eAppAction_Idle); + + if( !GetChangingSessionType() && !g_NetworkManager.IsLocalGame() ) + { + SetGameStarted(false); + SetChangingSessionType(true); + SetReallyChangingSessionType(true); + + // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen + ui.HideAllGameUIElements(); + + if( !ui.IsSceneInStack( ProfileManager.GetPrimaryPad(), eUIScene_EndPoem ) ) + { + ui.CloseAllPlayersScenes(); + } + ui.ShowOtherPlayersBaseScene(ProfileManager.GetPrimaryPad(), true); + + // Remove this line to fix: + // #49084 - TU5: Code: Gameplay: The title crashes every time client navigates to 'Play game' menu and loads/creates new game after a "Connection to Xbox LIVE was lost" message has appeared. + //app.NavigateToScene(0,eUIScene_Main); + + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &CGameNetworkManager::ChangeSessionTypeThreadProc; + loadingParams->lpParam = nullptr; + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); +#ifdef __PS3__ + completionData->bRequiresUserAction=FALSE; +#else + completionData->bRequiresUserAction=TRUE; +#endif + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->iPad=DEFAULT_XUI_MENU_USER; + if( ui.IsSceneInStack( ProfileManager.GetPrimaryPad(), eUIScene_EndPoem ) ) + { + completionData->type = e_ProgressCompletion_NavigateBackToScene; + completionData->scene = eUIScene_EndPoem; + } + else + { + completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes; + } + loadingParams->completionData = completionData; + + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); + } + } + else if( g_NetworkManager.IsLeavingGame() ) + { + // If we are leaving the game, then ignore the state change + SetAction(i,eAppAction_Idle); + } +#if 0 + // 4J-HG - Took this out since ChangeSessionType is only set in two places (both in EthernetDisconnected) and this case is handled there, plus this breaks + // this if statements original purpose (to allow us to wait for IsInGameplay before actioning switching to offline + + // QNet must do this kind of thing automatically by itself, but on PS3 at least, we need the disconnection to definitely end up with us out of the game one way or another, + // and the other two cases above don't catch the case where we are just starting the game and get a disconnection during the loading/creation + else + { + if( g_NetworkManager.IsInSession() ) + { + g_NetworkManager._LeaveGame(); + } + } +#endif + } + break; + case eAppAction_SetDefaultOptions: + SetAction(i,eAppAction_Idle); +#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__) + SetDefaultOptions((C4JStorage::PROFILESETTINGS *)param,i); +#else + SetDefaultOptions(static_cast(param), i); +#endif + + // if the profile data has been changed, then force a profile write + // It seems we're allowed to break the 5 minute rule if it's the result of a user action + CheckGameSettingsChanged(true,i); + + break; + + case eAppAction_RemoteServerSave: + { + // If the remote server save has already finished, don't complete the action + if (GetGameStarted()) + { + SetAction(ProfileManager.GetPrimaryPad(), eAppAction_Idle); + break; + } + + SetAction(i,eAppAction_WaitRemoteServerSaveComplete); + + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + ui.CloseUIScenes(i, true); + } + + // turn off the gamertags in splitscreen for the primary player, since they are about to be made fullscreen + ui.HideAllGameUIElements(); + + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &CMinecraftApp::RemoteSaveThreadProc; + loadingParams->lpParam = nullptr; + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + completionData->bRequiresUserAction=FALSE; + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->iPad=DEFAULT_XUI_MENU_USER; + if( ui.IsSceneInStack( ProfileManager.GetPrimaryPad(), eUIScene_EndPoem ) ) + { + completionData->type = e_ProgressCompletion_NavigateBackToScene; + completionData->scene = eUIScene_EndPoem; + } + else + { + completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes; + } + loadingParams->completionData = completionData; + + loadingParams->cancelFunc = &CMinecraftApp::ExitGameFromRemoteSave; + loadingParams->cancelText = IDS_TOOLTIPS_EXIT; + + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); + } + break; + case eAppAction_WaitRemoteServerSaveComplete: + // Do nothing + break; + case eAppAction_FailedToJoinNoPrivileges: + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad()); + if(result != C4JStorage::EMessage_Busy) SetAction(i,eAppAction_Idle); + } + break; + case eAppAction_ProfileReadError: + // Return player to the main menu - code largely copied from that for handling + // eAppAction_PrimaryPlayerSignedOut, although I don't think we should have got as + // far as needing to halt the server, or running the game, before returning to the menu + if(!app.GetGameStarted()) MinecraftServer::HaltServer(true); + + if( g_NetworkManager.IsInSession() ) + { + app.SetAction(i,eAppAction_PrimaryPlayerSignedOutReturned); + } + else + { + app.SetAction(i,eAppAction_PrimaryPlayerSignedOutReturned_Menus); + MinecraftServer::resetFlags(); + } + break; + + case eAppAction_BanLevel: + { + // It's possible that this state can get set after the game has been exited (e.g. by network disconnection) so we can't ban the level at that point + if(g_NetworkManager.IsInGameplay() && !g_NetworkManager.IsLeavingGame()) + { + TelemetryManager->RecordBanLevel(i); + +#if defined _XBOX + INetworkPlayer *pHost=g_NetworkManager.GetHostPlayer(); + // write the level to the banned level list, and exit the world + AddLevelToBannedLevelList(i,((NetworkPlayerXbox *)pHost)->GetUID(),GetUniqueMapName(),true); +#elif defined _XBOX_ONE + INetworkPlayer *pHost=g_NetworkManager.GetHostPlayer(); + AddLevelToBannedLevelList(i,pHost->GetUID(),GetUniqueMapName(),true); +#endif + // primary player would exit the world, secondary would exit the player + if(ProfileManager.GetPrimaryPad()==i) + { + SetAction(i,eAppAction_ExitWorld); + } + else + { + SetAction(i,eAppAction_ExitPlayer); + } + } + } + break; + case eAppAction_LevelInBanLevelList: + { + UINT uiIDA[2]; + uiIDA[0]=IDS_BUTTON_REMOVE_FROM_BAN_LIST; + uiIDA[1]=IDS_EXIT_GAME; + + // pass in the gamertag format string + WCHAR wchFormat[40]; + INetworkPlayer *player = g_NetworkManager.GetLocalPlayerByUserIndex(i); + + // If not the primary player, but the primary player has banned this level and decided not to unban + // then we may have left the game by now + if(player) + { + swprintf(wchFormat, 40, L"%ls\n\n%%ls",player->GetOnlineName()); + + C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_BANNED_LEVEL_TITLE, IDS_PLAYER_BANNED_LEVEL, uiIDA,2,i,&CMinecraftApp::BannedLevelDialogReturned,this, wchFormat); + if(result != C4JStorage::EMessage_Busy) SetAction(i,eAppAction_Idle); + } + else + { + SetAction(i,eAppAction_Idle); + } + } + break; + case eAppAction_DebugText: + // launch the xui for text entry + { +#ifdef _XBOX + CScene_TextEntry::XuiTextInputParams *pDebugTextParams= new CScene_TextEntry::XuiTextInputParams; + pDebugTextParams->iPad=i; + pDebugTextParams->wch=(WCHAR)param; + + app.NavigateToScene(i,eUIScene_TextEntry,pDebugTextParams); +#endif + SetAction(i,eAppAction_Idle); + } + break; + + case eAppAction_ReloadTexturePack: + { + SetAction(i,eAppAction_Idle); + Minecraft *pMinecraft = Minecraft::GetInstance(); + pMinecraft->textures->reloadAll(); + pMinecraft->skins->updateUI(); + + if(!pMinecraft->skins->isUsingDefaultSkin()) + { + TexturePack *pTexturePack = pMinecraft->skins->getSelected(); + + DLCPack *pDLCPack=pTexturePack->getDLCPack(); + + bool purchased = false; + // do we have a license? + if(pDLCPack && pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" )) + { + purchased = true; + } +#ifdef _XBOX + TelemetryManager->RecordTexturePackLoaded(i, pTexturePack->getId(), purchased?1:0); +#endif + } + + // 4J-PB - If the texture pack has audio, we need to switch to this + if(pMinecraft->skins->getSelected()->hasAudio()) + { + Minecraft::GetInstance()->soundEngine->playStreaming(L"", 0, 0, 0, 1, 1); + } + } + break; + + case eAppAction_ReloadFont: + { +#ifndef _XBOX + app.DebugPrintf( + "[Consoles_App] eAppAction_ReloadFont, ingame='%s'.\n", + app.GetGameStarted() ? "Yes" : "No" ); + + SetAction(i,eAppAction_Idle); + + ui.SetTooltips(i, -1); + + ui.ReloadSkin(); + ui.StartReloadSkinThread(); + + ui.setCleanupOnReload(); +#endif + } + break; + + case eAppAction_TexturePackRequired: + { +#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ + UINT uiIDA[2]; + uiIDA[0]=IDS_TEXTUREPACK_FULLVERSION; + uiIDA[1]=IDS_CONFIRM_CANCEL; // let them continue without the texture pack here (as this is only really for r + // Give the player a warning about the texture pack missing + ui.RequestErrorMessage(IDS_DLC_TEXTUREPACK_NOT_PRESENT_TITLE, IDS_DLC_TEXTUREPACK_NOT_PRESENT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::TexturePackDialogReturned,this); + SetAction(i,eAppAction_Idle); +#else +#ifdef _XBOX + ULONGLONG ullOfferID_Full; + app.GetDLCFullOfferIDForPackID(app.GetRequiredTexturePackID(),&ullOfferID_Full); + + TelemetryManager->RecordUpsellPresented(ProfileManager.GetPrimaryPad(), eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF); +#endif + UINT uiIDA[2]; + + uiIDA[0]=IDS_TEXTUREPACK_FULLVERSION; + uiIDA[1]=IDS_TEXTURE_PACK_TRIALVERSION; + + // Give the player a warning about the texture pack missing + ui.RequestErrorMessage(IDS_DLC_TEXTUREPACK_NOT_PRESENT_TITLE, IDS_DLC_TEXTUREPACK_NOT_PRESENT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::TexturePackDialogReturned,this); + SetAction(i,eAppAction_Idle); +#endif + } + + break; + } + } + + // Any TMS actions? + + eTMS = app.GetTMSAction(i); + + if(eTMS!=eTMSAction_Idle) + { + switch(eTMS) + { + // TMS++ actions + case eTMSAction_TMSPP_RetrieveFiles_CreateLoad_SignInReturned: + case eTMSAction_TMSPP_RetrieveFiles_RunPlayGame: +#ifdef _XBOX + app.TMSPP_SetTitleGroupID(GROUP_ID); + SetTMSAction(i,eTMSAction_TMSPP_GlobalFileList); +#elif defined _XBOX_ONE + SetTMSAction(i,eTMSAction_TMSPP_GlobalFileList_Waiting); + app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_Title,eTMSAction_TMSPP_UserFileList); +#else + SetTMSAction(i,eTMSAction_TMSPP_UserFileList); +#endif + break; + +#ifdef _XBOX + case eTMSAction_TMSPP_GlobalFileList: + SetTMSAction(i,eTMSAction_TMSPP_GlobalFileList_Waiting); + app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_Title,"\\",eTMSAction_TMSPP_UserFileList); + break; +#endif + case eTMSAction_TMSPP_UserFileList: + // retrieve the file list first +#if defined _XBOX + SetTMSAction(i,eTMSAction_TMSPP_UserFileList_Waiting); + app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_TitleUser,"\\",eTMSAction_TMSPP_XUIDSFile); +#elif defined _XBOX_ONE + SetTMSAction(i,eTMSAction_TMSPP_UserFileList_Waiting); + app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_TitleUser,eTMSAction_TMSPP_DLCFile); +#else + SetTMSAction(i,eTMSAction_TMSPP_XUIDSFile); +#endif + break; + case eTMSAction_TMSPP_XUIDSFile: +#ifdef _XBOX + SetTMSAction(i,eTMSAction_TMSPP_XUIDSFile_Waiting); + // pass in the next app action on the call or callback completing + app.TMSPP_ReadXuidsFile(i,eTMSAction_TMSPP_DLCFile); +#else + SetTMSAction(i,eTMSAction_TMSPP_DLCFile); +#endif + + break; + case eTMSAction_TMSPP_DLCFile: +#if defined _XBOX || defined _XBOX_ONE + SetTMSAction(i,eTMSAction_TMSPP_DLCFile_Waiting); + // pass in the next app action on the call or callback completing + app.TMSPP_ReadDLCFile(i,eTMSAction_TMSPP_BannedListFile); +#else + SetTMSAction(i,eTMSAction_TMSPP_BannedListFile); +#endif + break; + case eTMSAction_TMSPP_BannedListFile: + // If we have one in TMSPP, then we can assume we can ignore TMS +#if defined _XBOX + SetTMSAction(i,eTMSAction_TMSPP_BannedListFile_Waiting); + // pass in the next app action on the call or callback completing + if(app.TMSPP_ReadBannedList(i,eTMSAction_TMS_RetrieveFiles_Complete)==false) + { + // we don't have a banned list in TMSPP, so we should check TMS + app.ReadBannedList(i, eTMSAction_TMS_RetrieveFiles_Complete,true); + } +#elif defined _XBOX_ONE + SetTMSAction(i,eTMSAction_TMSPP_BannedListFile_Waiting); + // pass in the next app action on the call or callback completing + app.TMSPP_ReadBannedList(i,eTMSAction_TMS_RetrieveFiles_Complete); + +#else + SetTMSAction(i,eTMSAction_TMS_RetrieveFiles_Complete); +#endif + break; + + // SPECIAL CASE - where the user goes directly in to Help & Options from the main menu + case eTMSAction_TMSPP_RetrieveFiles_HelpAndOptions: + case eTMSAction_TMSPP_RetrieveFiles_DLCMain: + // retrieve the file list first +#if defined _XBOX + // pass in the next app action on the call or callback completing + SetTMSAction(i,eTMSAction_TMSPP_XUIDSFile_Waiting); + app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_Title,"\\",eTMSAction_TMSPP_DLCFileOnly); +#elif defined _XBOX_ONE + SetTMSAction(i,eTMSAction_TMSPP_GlobalFileList_Waiting); + app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_Title,eTMSAction_TMSPP_RetrieveUserFilelist_DLCFileOnly); +#else + SetTMSAction(i,eTMSAction_TMSPP_DLCFileOnly); +#endif + break; + case eTMSAction_TMSPP_RetrieveUserFilelist_DLCFileOnly: +#if defined _XBOX + SetTMSAction(i,eTMSAction_TMSPP_UserFileList_Waiting); + app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_TitleUser,"\\",eTMSAction_TMSPP_XUIDSFile); +#elif defined _XBOX_ONE + //StorageManager.TMSPP_DeleteFile(i,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,L"TP06.png",nullptr,nullptr, 0); + SetTMSAction(i,eTMSAction_TMSPP_UserFileList_Waiting); + app.TMSPP_RetrieveFileList(i,C4JStorage::eGlobalStorage_TitleUser,eTMSAction_TMSPP_DLCFileOnly); +#else + SetTMSAction(i,eTMSAction_TMSPP_DLCFileOnly); +#endif + + break; + + case eTMSAction_TMSPP_DLCFileOnly: +#if defined _XBOX || defined _XBOX_ONE + SetTMSAction(i,eTMSAction_TMSPP_DLCFile_Waiting); + // pass in the next app action on the call or callback completing + app.TMSPP_ReadDLCFile(i,eTMSAction_TMSPP_RetrieveFiles_Complete); +#else + SetTMSAction(i,eTMSAction_TMSPP_RetrieveFiles_Complete); +#endif + break; + + + case eTMSAction_TMSPP_RetrieveFiles_Complete: + SetTMSAction(i,eTMSAction_Idle); + break; + + + // TMS files + /* case eTMSAction_TMS_RetrieveFiles_CreateLoad_SignInReturned: + case eTMSAction_TMS_RetrieveFiles_RunPlayGame: + #ifdef _XBOX + SetTMSAction(i,eTMSAction_TMS_XUIDSFile_Waiting); + // pass in the next app action on the call or callback completing + app.ReadXuidsFileFromTMS(i,eTMSAction_TMS_DLCFile,true); + #else + SetTMSAction(i,eTMSAction_TMS_DLCFile); + #endif + break; + + case eTMSAction_TMS_DLCFile: + #ifdef _XBOX + SetTMSAction(i,eTMSAction_TMS_DLCFile_Waiting); + // pass in the next app action on the call or callback completing + app.ReadDLCFileFromTMS(i,eTMSAction_TMS_BannedListFile,true); + #else + SetTMSAction(i,eTMSAction_TMS_BannedListFile); + #endif + + break; + + case eTMSAction_TMS_RetrieveFiles_HelpAndOptions: + case eTMSAction_TMS_RetrieveFiles_DLCMain: + #ifdef _XBOX + SetTMSAction(i,eTMSAction_TMS_DLCFile_Waiting); + // pass in the next app action on the call or callback completing + app.ReadDLCFileFromTMS(i,eTMSAction_Idle,true); + #else + SetTMSAction(i,eTMSAction_Idle); + #endif + + break; + case eTMSAction_TMS_BannedListFile: + #ifdef _XBOX + SetTMSAction(i,eTMSAction_TMS_BannedListFile_Waiting); + // pass in the next app action on the call or callback completing + app.ReadBannedList(i, eTMSAction_TMS_RetrieveFiles_Complete,true); + #else + SetTMSAction(i,eTMSAction_TMS_RetrieveFiles_Complete); + #endif + + break; + + */ + case eTMSAction_TMS_RetrieveFiles_Complete: + SetTMSAction(i,eTMSAction_Idle); + // if(StorageManager.SetSaveDevice(&CScene_Main::DeviceSelectReturned,pClass)) + // { + // // save device already selected + // // ensure we've applied this player's settings + // app.ApplyGameSettingsChanged(ProfileManager.GetPrimaryPad()); + // app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_MultiGameJoinLoad); + // } + break; + } + } + + } +} + +int CMinecraftApp::BannedLevelDialogReturned(void *pParam,int iPad,const C4JStorage::EMessageResult result) +{ + CMinecraftApp* pApp = static_cast(pParam); + //Minecraft *pMinecraft=Minecraft::GetInstance(); + + if(result==C4JStorage::EMessage_ResultAccept) + { +#if defined _XBOX || defined _XBOX_ONE + INetworkPlayer *pHost = g_NetworkManager.GetHostPlayer(); + // unban the level + if (pHost != nullptr) + { +#if defined _XBOX + pApp->RemoveLevelFromBannedLevelList(iPad,((NetworkPlayerXbox *)pHost)->GetUID(),pApp->GetUniqueMapName()); +#else + pApp->RemoveLevelFromBannedLevelList(iPad,pHost->GetUID(),pApp->GetUniqueMapName()); +#endif + } +#endif + } + else + { + if( iPad == ProfileManager.GetPrimaryPad() ) + { + pApp->SetAction(iPad,eAppAction_ExitWorld); + } + else + { + pApp->SetAction(iPad,eAppAction_ExitPlayer); + } + } + + return 0; +} + +void CMinecraftApp::loadMediaArchive() +{ + wstring mediapath = L""; + +#ifdef __PS3__ + mediapath = L"Common\\Media\\MediaPS3"; +#elif _WINDOWS64 + mediapath = L"Common\\Media\\MediaWindows64"; +#elif __ORBIS__ + mediapath = L"Common\\Media\\MediaOrbis"; +#elif _DURANGO + mediapath = L"Common\\Media\\MediaDurango"; +#elif __PSVITA__ + mediapath = L"Common\\Media\\MediaPSVita"; +#endif + + if (!mediapath.empty()) + { + m_mediaArchive = new FolderFile(mediapath); + } +#if 0 + string path = "Common\\media.arc"; + HANDLE hFile = CreateFile( path.c_str(), + GENERIC_READ, + FILE_SHARE_READ, + nullptr, + OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, + nullptr ); + + if( hFile != INVALID_HANDLE_VALUE ) + { + File fileHelper(convStringToWstring(path)); + DWORD dwFileSize = fileHelper.length(); + + // Initialize memory. + PBYTE m_fBody = new BYTE[ dwFileSize ]; + ZeroMemory(m_fBody, dwFileSize); + + DWORD m_fSize = 0; + BOOL hr = ReadFile( hFile, + m_fBody, + dwFileSize, + &m_fSize, + nullptr ); + + assert( m_fSize == dwFileSize ); + + CloseHandle( hFile ); + + m_mediaArchive = new ArchiveFile(m_fBody, m_fSize); + } + else + { + assert( false ); + // AHHHHHHHHHHHH + m_mediaArchive = nullptr; + } +#endif +} + +void CMinecraftApp::loadStringTable() +{ +#ifndef _XBOX + + if(m_stringTable!=nullptr) + { + // we need to unload the current string table, this is a reload + delete m_stringTable; + } +#ifdef _WINDOWS64 + m_stringTable = nullptr; + const wstring localisationCandidates[] = + { + L"Common\\Localization", // Fireblade - check multiple directories before resulting to .loc usage + L"Windows64Media\\loc", + L"..\\Minecraft.Client\\Windows64Media\\loc" + }; + + for (const auto &localisationFolder : localisationCandidates) + { + File localisationDirectory(localisationFolder); + if (localisationDirectory.exists() && localisationDirectory.isDirectory()) + { + StringTable *candidateTable = new StringTable(localisationFolder); // Fireblade - xml before loc + + const bool hasKeyString = candidateTable->hasStringKey(L"IDS_OK"); + bool hasIndexString = false; + #ifdef IDS_OK + LPCWSTR indexedString = candidateTable->getString(IDS_OK); + hasIndexString = (indexedString != nullptr && indexedString[0] != L'\0'); + #endif + + if (hasKeyString || hasIndexString) + { + m_stringTable = candidateTable; + app.DebugPrintf("Loaded language data from '%ls'\n", localisationFolder.c_str()); + break; + } + + app.DebugPrintf("Ignoring localisation path '%ls' (missing expected IDs)\n", localisationFolder.c_str()); + delete candidateTable; + } + } + + if (m_stringTable == nullptr && m_mediaArchive != nullptr) // Fireblade - fallback to previous behavior + { + const wstring localisationFile = L"languages.loc"; + if (m_mediaArchive->hasFile(localisationFile)) + { + byteArray locFile = m_mediaArchive->getFile(localisationFile); + m_stringTable = new StringTable(locFile.data, locFile.length); + delete locFile.data; + } + } + + if (m_stringTable == nullptr) + { + app.DebugPrintf("Failed to initialize language data\n"); + assert(false); + } +#else // Fireblade - other platforms keep same logic + wstring localisationFile = L"languages.loc"; + if (m_mediaArchive->hasFile(localisationFile)) + { + byteArray locFile = m_mediaArchive->getFile(localisationFile); + m_stringTable = new StringTable(locFile.data, locFile.length); + delete locFile.data; + } + else + { + m_stringTable = nullptr; + assert(false); + // AHHHHHHHHH. + } +#endif +#endif +} + +int CMinecraftApp::PrimaryPlayerSignedOutReturned(void *pParam,int iPad,const C4JStorage::EMessageResult) +{ + //CMinecraftApp* pApp = (CMinecraftApp*)pParam; + //Minecraft *pMinecraft=Minecraft::GetInstance(); + + // if the player is null, we're in the menus + //if(Minecraft::GetInstance()->player!=nullptr) + + // We always create a session before kicking of any of the game code, so even though we may still be joining/creating a game + // at this point we want to handle it differently from just being in a menu + if( g_NetworkManager.IsInSession() ) + { + app.SetAction(iPad,eAppAction_PrimaryPlayerSignedOutReturned); + } + else + { + app.SetAction(iPad,eAppAction_PrimaryPlayerSignedOutReturned_Menus); + } + return 0; +} + +int CMinecraftApp::EthernetDisconnectReturned(void *pParam,int iPad,const C4JStorage::EMessageResult) +{ + //CMinecraftApp* pApp = (CMinecraftApp*)pParam; + Minecraft *pMinecraft=Minecraft::GetInstance(); + + // if the player is null, we're in the menus + if (Minecraft::GetInstance()->player != nullptr) + { + app.SetAction(pMinecraft->player->GetXboxPad(), eAppAction_EthernetDisconnectedReturned); + } + else + { + // 4J-PB - turn off the PSN store icon just in case this happened when we were in one of the DLC menus +#if defined __ORBIS__ || defined __PSVITA__ + app.GetCommerce()->HidePsStoreIcon(); +#endif + app.SetAction(iPad,eAppAction_EthernetDisconnectedReturned_Menus); + } + return 0; +} + +int CMinecraftApp::SignoutExitWorldThreadProc( void* lpParameter ) +{ + + // Share AABB & Vec3 pools with default (main thread) - should be ok as long as we don't tick the main thread whilst this thread is running + AABB::UseDefaultThreadStorage(); + Vec3::UseDefaultThreadStorage(); + Compression::UseDefaultThreadStorage(); + + //app.SetGameStarted(false); + + Minecraft *pMinecraft=Minecraft::GetInstance(); + + int exitReasonStringId = -1; + + bool saveStats = false; + if (pMinecraft->isClientSide() || g_NetworkManager.IsInSession() ) + { + if(lpParameter != nullptr ) + { + switch( app.GetDisconnectReason() ) + { + case DisconnectPacket::eDisconnect_Kicked: + exitReasonStringId = IDS_DISCONNECTED_KICKED; + break; + case DisconnectPacket::eDisconnect_NoUGC_AllLocal: + exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL; + break; + case DisconnectPacket::eDisconnect_NoUGC_Single_Local: + exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL; + break; +#ifdef _XBOX + case DisconnectPacket::eDisconnect_NoUGC_Remote: + exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_REMOTE; + break; +#endif + case DisconnectPacket::eDisconnect_NoFlying: + exitReasonStringId = IDS_DISCONNECTED_FLYING; + break; + case DisconnectPacket::eDisconnect_OutdatedServer: + exitReasonStringId = IDS_DISCONNECTED_SERVER_OLD; + break; + case DisconnectPacket::eDisconnect_OutdatedClient: + exitReasonStringId = IDS_DISCONNECTED_CLIENT_OLD; + break; + default: + exitReasonStringId = IDS_DISCONNECTED; + } + pMinecraft->progressRenderer->progressStartNoAbort( exitReasonStringId ); + // 4J - Force a disconnection, this handles the situation that the server has already disconnected + if( pMinecraft->levels[0] != nullptr ) pMinecraft->levels[0]->disconnect(false); + if( pMinecraft->levels[1] != nullptr ) pMinecraft->levels[1]->disconnect(false); + } + else + { + exitReasonStringId = IDS_EXITING_GAME; + pMinecraft->progressRenderer->progressStartNoAbort( IDS_EXITING_GAME ); + + if( pMinecraft->levels[0] != nullptr ) pMinecraft->levels[0]->disconnect(); + if( pMinecraft->levels[1] != nullptr ) pMinecraft->levels[1]->disconnect(); + } + + // 4J Stu - This only does something if we actually have a server, so don't need to do any other checks + MinecraftServer::HaltServer(true); + + // We need to call the stats & leaderboards save before we exit the session + //pMinecraft->forceStatsSave(); + saveStats = false; + + // 4J Stu - Leave the session once the disconnect packet has been sent + g_NetworkManager.LeaveGame(FALSE); + } + else + { + if(lpParameter != nullptr ) + { + switch( app.GetDisconnectReason() ) + { + case DisconnectPacket::eDisconnect_Kicked: + exitReasonStringId = IDS_DISCONNECTED_KICKED; + break; + case DisconnectPacket::eDisconnect_NoUGC_AllLocal: + exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL; + break; + case DisconnectPacket::eDisconnect_NoUGC_Single_Local: + exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL; + break; +#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) + case DisconnectPacket::eDisconnect_ContentRestricted_AllLocal: + exitReasonStringId = IDS_CONTENT_RESTRICTION_MULTIPLAYER; + break; + case DisconnectPacket::eDisconnect_ContentRestricted_Single_Local: + exitReasonStringId = IDS_CONTENT_RESTRICTION; + break; +#endif +#ifdef _XBOX + case DisconnectPacket::eDisconnect_NoUGC_Remote: + exitReasonStringId = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_REMOTE; + break; +#endif + case DisconnectPacket::eDisconnect_OutdatedServer: + exitReasonStringId = IDS_DISCONNECTED_SERVER_OLD; + break; + case DisconnectPacket::eDisconnect_OutdatedClient: + exitReasonStringId = IDS_DISCONNECTED_CLIENT_OLD; + default: + exitReasonStringId = IDS_DISCONNECTED; + } + pMinecraft->progressRenderer->progressStartNoAbort( exitReasonStringId ); + } + } + pMinecraft->setLevel(nullptr,exitReasonStringId,nullptr,saveStats,true); + + // 4J-JEV: Fix for #106402 - TCR #014 BAS Debug Output: + // TU12: Mass Effect Mash-UP: Save file "Default_DisplayName" is created on all storage devices after signing out from a re-launched pre-generated world + app.m_gameRules.unloadCurrentGameRules(); // + + MinecraftServer::resetFlags(); + + // We can't start/join a new game until the session is destroyed, so wait for it to be idle again + while( g_NetworkManager.IsInSession() ) + { + Sleep(1); + } + + return S_OK; +} + +int CMinecraftApp::UnlockFullInviteReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + //CMinecraftApp* pApp = (CMinecraftApp*)pParam; + Minecraft *pMinecraft=Minecraft::GetInstance(); + bool bNoPlayer; + + // bug 11285 - TCR 001: BAS Game Stability: CRASH - When trying to join a full version game with a trial version, the trial crashes + // 4J-PB - we may be in the main menus here, and we don't have a pMinecraft->player + + if(pMinecraft->player==nullptr) + { + bNoPlayer=true; + } + + if(result==C4JStorage::EMessage_ResultAccept) + { + if(ProfileManager.IsSignedInLive(iPad)) + { + // 4J-PB - need to check this user can access the store +#if defined(__PS3__) || defined(__PSVITA__) + bool bContentRestricted; + ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,nullptr,&bContentRestricted,nullptr); + if(bContentRestricted) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad()); + } + else +#endif + { + ProfileManager.DisplayFullVersionPurchase(false,iPad,eSen_UpsellID_Full_Version_Of_Game); + } + } +#if defined(__PS3__) + else + { + // you're not signed in to PSN! + UINT uiIDA[2]; + uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; + uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; + ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app); + + } +#endif + } + else + { + TelemetryManager->RecordUpsellResponded(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, eSen_UpsellOutcome_Declined); + } + + return 0; +} + +int CMinecraftApp::UnlockFullSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + //CMinecraftApp* pApp = (CMinecraftApp*)pParam; + Minecraft *pMinecraft=Minecraft::GetInstance(); + + if(result==C4JStorage::EMessage_ResultAccept) + { + if(ProfileManager.IsSignedInLive(pMinecraft->player->GetXboxPad())) + { + // 4J-PB - need to check this user can access the store +#if defined(__PS3__) || defined(__PSVITA__) + bool bContentRestricted; + ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,nullptr,&bContentRestricted,nullptr); + if(bContentRestricted) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad()); + } + else +#endif + { + ProfileManager.DisplayFullVersionPurchase(false,pMinecraft->player->GetXboxPad(),eSen_UpsellID_Full_Version_Of_Game); + } + } +#if defined(__PS3__) + else + { + // you're not signed in to PSN! + UINT uiIDA[2]; + uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; + uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; + ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app); + } +#elif defined(__ORBIS__) + else + { + // Determine why they're not "signed in live" + if (ProfileManager.isSignedInPSN(iPad)) + { + // Signed in to PSN but not connected (no internet access) + assert(!ProfileManager.isConnectedToPSN(iPad)); + + UINT uiIDA[1]; + uiIDA[0] = IDS_OK; + ui.RequestErrorMessage( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad); + } + else + { + // Not signed in to PSN + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestAlertMessage( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, iPad, &CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app); + } + } +#endif + } + else + { + TelemetryManager->RecordUpsellResponded(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, eSen_UpsellOutcome_Declined); + } + + return 0; +} + +int CMinecraftApp::UnlockFullExitReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + CMinecraftApp* pApp = static_cast(pParam); + Minecraft *pMinecraft=Minecraft::GetInstance(); + + if(result==C4JStorage::EMessage_ResultAccept) + { + if(ProfileManager.IsSignedInLive(pMinecraft->player->GetXboxPad())) + { + // 4J-PB - need to check this user can access the store +#if defined(__PS3__) || defined(__PSVITA__) + bool bContentRestricted; + ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,nullptr,&bContentRestricted,nullptr); + if(bContentRestricted) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad()); + } + else +#endif + { + ProfileManager.DisplayFullVersionPurchase(false,pMinecraft->player->GetXboxPad(),eSen_UpsellID_Full_Version_Of_Game); +#if defined __ORBIS__ || defined __PS3__ || defined __PSVITA__ + // still need to exit the trial or we'll be in the Pause menu with input ignored + pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial); +#endif + } + } +#if defined(__PS3__) || defined __PSVITA__ + else + { + // you're not signed in to PSN! + UINT uiIDA[2]; + uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; + uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; + ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturnedExitTrial,&app); + } +#elif defined(__ORBIS__) + else + { + // Determine why they're not "signed in live" + if (ProfileManager.isSignedInPSN(iPad)) + { + // Signed in to PSN but not connected (no internet access) + assert(!ProfileManager.isConnectedToPSN(iPad)); + + UINT uiIDA[1]; + uiIDA[0] = IDS_OK; + ui.RequestErrorMessage( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad); + // still need to exit the trial or we'll be in the Pause menu with input ignored + pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial); + } + else + { + // Not signed in to PSN + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestAlertMessage( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, iPad, &CMinecraftApp::MustSignInFullVersionPurchaseReturnedExitTrial,&app); + } + } +#endif + } + else + { + TelemetryManager->RecordUpsellResponded(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, eSen_UpsellOutcome_Declined); + pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial); + } + + return 0; +} + +int CMinecraftApp::TrialOverReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + CMinecraftApp* pApp = static_cast(pParam); + Minecraft *pMinecraft=Minecraft::GetInstance(); + + if(result==C4JStorage::EMessage_ResultAccept) + { + // we need a signed in user for the unlock + if(ProfileManager.IsSignedInLive(pMinecraft->player->GetXboxPad())) + { + // 4J-PB - need to check this user can access the store +#if defined(__PS3__) || defined(__PSVITA__) + bool bContentRestricted; + ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,nullptr,&bContentRestricted,nullptr); + if(bContentRestricted) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad()); + } + else +#endif + { + ProfileManager.DisplayFullVersionPurchase(false,pMinecraft->player->GetXboxPad(),eSen_UpsellID_Full_Version_Of_Game); + } + } + else + { +#if defined(__PS3__) + + // you're not signed in to PSN! + UINT uiIDA[2]; + uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; + uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; + ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app); + + // 4J Stu - We can't actually exit the game, so just exit back to the main menu + //pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial); +#else + pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitTrial); +#endif + } + } + else + { + TelemetryManager->RecordUpsellResponded(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, eSen_UpsellOutcome_Declined); + +#if defined(__PS3__) || defined(__ORBIS__) + // 4J Stu - We can't actually exit the game, so just exit back to the main menu + pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitWorldTrial); +#else + pApp->SetAction(pMinecraft->player->GetXboxPad(),eAppAction_ExitTrial); +#endif + } + + return 0; +} + +void CMinecraftApp::ProfileReadErrorCallback(void *pParam) +{ + CMinecraftApp *pApp=static_cast(pParam); + int iPrimaryPlayer=ProfileManager.GetPrimaryPad(); + pApp->SetAction(iPrimaryPlayer, eAppAction_ProfileReadError); +} + +void CMinecraftApp::ClearSignInChangeUsersMask() +{ + // 4J-PB - When in the main menu, the user is on pad 0, and any change they make to their profile will be to pad 0 data + // If they then go in as a secondary player to a splitscreen game, their profile will not be read again on pad 1 if they were previously in a splitscreen game + // This is because m_uiLastSignInData remembers they were in previously, and doesn't read the profile data for them again + // Fix this by resetting the m_uiLastSignInData on pressing play game for secondary users. The Primary user does a read profile on play game anyway + int iPrimaryPlayer=ProfileManager.GetPrimaryPad(); + + if(m_uiLastSignInData!=0) + { + if(iPrimaryPlayer>=0) + { + m_uiLastSignInData=1<user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); +#endif + + CMinecraftApp *pApp=static_cast(pParam); + // check if the primary player signed out + int iPrimaryPlayer=ProfileManager.GetPrimaryPad(); + + if((ProfileManager.GetLockedProfile()!=-1) && iPrimaryPlayer!=-1) + { + if ( ((uiSignInData & (1<SetAction(iPrimaryPlayer,eAppAction_PrimaryPlayerSignedOut); + + // 4J-PB - invalidate their banned level list + pApp->InvalidateBannedList(iPrimaryPlayer); + + // need to ditch any DLCOffers info + StorageManager.ClearDLCOffers(); + pApp->ClearAndResetDLCDownloadQueue(); + pApp->ClearDLCInstalled(); + } + else + { + unsigned int uiChangedPlayers = uiSignInData ^ m_uiLastSignInData; + + if( g_NetworkManager.IsInSession() ) + { + bool hasGuestIdChanged = false; + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + DWORD guestNumber = 0; + if(ProfileManager.IsSignedIn(i)) + { + XUSER_SIGNIN_INFO info; + XUserGetSigninInfo(i,XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY ,&info); + pApp->DebugPrintf("Player at index %d has guest number %d\n", i,info.dwGuestNumber ); + guestNumber = info.dwGuestNumber; + } + if( pApp->m_currentSigninInfo[i].dwGuestNumber != 0 && guestNumber != 0 && pApp->m_currentSigninInfo[i].dwGuestNumber != guestNumber ) + { + hasGuestIdChanged = true; + } + } + + if( hasGuestIdChanged ) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestErrorMessage(IDS_GUEST_ORDER_CHANGED_TITLE, IDS_GUEST_ORDER_CHANGED_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad()); + } + + // 4J Stu - On PS4 we can also cause to exit players if they are signed out here, but we shouldn't do that if + // we are going to switch to an offline game as it will likely crash due to incompatible parallel processes + bool switchToOffline = false; + // If it's an online game, and the primary profile is no longer signed into LIVE then we act as if disconnected + if( !ProfileManager.IsSignedInLive( ProfileManager.GetLockedProfile() ) && !g_NetworkManager.IsLocalGame() ) + { + switchToOffline = true; + } + + //printf("Old: %x, New: %x, Changed: %x\n", m_ulLastSignInData, ulSignInData, changedPlayers); + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + // Primary player shouldn't be subjected to these checks, and shouldn't call ExitPlayer + if(i == iPrimaryPlayer) continue; + + // A guest a signed in or out, out of order which invalidates all the guest players we have in the game + if(hasGuestIdChanged && pApp->m_currentSigninInfo[i].dwGuestNumber != 0 && g_NetworkManager.GetLocalPlayerByUserIndex(i)!=nullptr) + { + pApp->DebugPrintf("Recommending removal of player at index %d because their guest id changed\n",i); + pApp->SetAction(i, eAppAction_ExitPlayer); + } + else + { + XUSER_SIGNIN_INFO info; + XUserGetSigninInfo(i,XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY ,&info); + // 4J Stu - Also need to detect the case where the sign in mask is the same, but the player has swapped users (eg still signed in but xuid different) + // Fix for #48451 - TU5: Code: UI: Splitscreen: Title crashes when switching to a profile previously signed out via splitscreen profile selection + + // 4J-PB - compiler complained about if below ('&&' within '||') - making it easier to read + bool bPlayerChanged=(uiChangedPlayers&(1<m_currentSigninInfo[i].xuid, info.xuid) ) )) + { + // 4J-PB - invalidate their banned level list + pApp->DebugPrintf("Player at index %d Left - invalidating their banned list\n",i); + pApp->InvalidateBannedList(i); + + // 4J-HG: If either the player is in the network manager or in the game, need to exit player + // TODO: Do we need to check the network manager? + if (g_NetworkManager.GetLocalPlayerByUserIndex(i) != nullptr || Minecraft::GetInstance()->localplayers[i] != nullptr) + { + pApp->DebugPrintf("Player %d signed out\n", i); + pApp->SetAction(i, eAppAction_ExitPlayer); + } + } + } +#ifdef __ORBIS__ + // check if any of the addition players have signed out of PSN (primary player is handled below) + if(!switchToOffline && i != ProfileManager.GetLockedProfile() && !g_NetworkManager.IsLocalGame()) + { + if(g_NetworkManager.GetLocalPlayerByUserIndex(i)!=nullptr) + { + if(ProfileManager.IsSignedInLive(i) == false) + { + pApp->DebugPrintf("Recommending removal of player at index %d because they're no longer signed into PSNd\n",i); + pApp->SetAction(i,eAppAction_ExitPlayer); + } + } + } +#endif + } + + // If it's an online game, and the primary profile is no longer signed into LIVE then we act as if disconnected + if( switchToOffline ) + { + pApp->SetAction(iPrimaryPlayer,eAppAction_EthernetDisconnected); + } + + + g_NetworkManager.HandleSignInChange(); + } + // Some menus require the player to be signed in to live, so if this callback happens and the primary player is + // no longer signed in then nav back + else if ( pApp->GetLiveLinkRequired() && !ProfileManager.IsSignedInLive( ProfileManager.GetLockedProfile() ) ) + { +#ifdef __PSVITA__ + if(!CGameNetworkManager::usingAdhocMode()) // if we're in adhoc mode, we can ignore this +#endif + { + pApp->SetAction(iPrimaryPlayer,eAppAction_EthernetDisconnected); + } + } + +#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__ ) + // 4J-JEV: Need to kick of loading of profile data for sub-sign in players. + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + if( i != iPrimaryPlayer + && ( uiChangedPlayers & (1<InvalidateBannedList(iPrimaryPlayer); + + // need to ditch any DLCOffers info + StorageManager.ClearDLCOffers(); + pApp->ClearAndResetDLCDownloadQueue(); + pApp->ClearDLCInstalled(); + + } + + // Update the guest numbers to the current state + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + if(FAILED(XUserGetSigninInfo(i,XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY,&pApp->m_currentSigninInfo[i]))) + { + pApp->m_currentSigninInfo[i].xuid = INVALID_XUID; + pApp->m_currentSigninInfo[i].dwGuestNumber = 0; + } + app.DebugPrintf("Player at index %d has guest number %d\n", i,pApp->m_currentSigninInfo[i].dwGuestNumber ); + } +} + +void CMinecraftApp::NotificationsCallback(LPVOID pParam,DWORD dwNotification, unsigned int uiParam) +{ + CMinecraftApp* pClass = static_cast(pParam); + + // push these on to the notifications to be handled in qnet's dowork + + PNOTIFICATION pNotification = new NOTIFICATION; + + pNotification->dwNotification=dwNotification; + pNotification->uiParam=uiParam; + + switch( dwNotification ) + { + case XN_SYS_SIGNINCHANGED: + { + pClass->DebugPrintf("Signing changed - %d\n", uiParam ); + } + break; + case XN_SYS_INPUTDEVICESCHANGED: + if(app.GetGameStarted() && g_NetworkManager.IsInSession()) + { + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + if(!InputManager.IsPadConnected(i) && + Minecraft::GetInstance()->localplayers[i] != nullptr && + !ui.IsPauseMenuDisplayed(i) && !ui.IsSceneInStack(i, eUIScene_EndPoem) ) + { + ui.CloseUIScenes(i); + ui.NavigateToScene(i,eUIScene_PauseMenu); + } + } + } + break; + case XN_LIVE_CONTENT_INSTALLED: + // Need to inform xuis that we've possibly had DLC installed + { + //app.m_dlcManager.SetNeedsUpdated(true); + // Clear the DLC installed flag to cause a GetDLC to run if it's called + app.ClearDLCInstalled(); + + ui.HandleDLCInstalled(ProfileManager.GetPrimaryPad()); + } + break; + case XN_SYS_STORAGEDEVICESCHANGED: + { +#ifdef _XBOX + // If the devices have changed, and we've got a dlc pack with audio selected, and that pack's content device is no longer valid... then pull the plug on + // audio streaming, as if we leave this until later xact gets locked up attempting to destroy the streamed wave bank. + TexturePack *pTexPack=Minecraft::GetInstance()->skins->getSelected(); + if(pTexPack->hasAudio()) + { + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)pTexPack; + XCONTENTDEVICEID deviceID = pDLCTexPack->GetDLCDeviceID(); + if( XContentGetDeviceState( deviceID, nullptr ) != ERROR_SUCCESS ) + { + // Set texture pack flag so that it is now considered as not having audio - this is critical so that the next playStreaming does what it is meant to do, + // and also so that we don't try and unmount this again, or play any sounds from it in the future + pTexPack->setHasAudio(false); + // need to stop the streaming audio - by playing streaming audio from the default texture pack now + Minecraft::GetInstance()->soundEngine->playStreaming(L"", 0, 0, 0, 0, 0); + + if(pDLCTexPack->m_pStreamedWaveBank!=nullptr) + { + pDLCTexPack->m_pStreamedWaveBank->Destroy(); + } + if(pDLCTexPack->m_pSoundBank!=nullptr) + { + pDLCTexPack->m_pSoundBank->Destroy(); + } + DWORD result = StorageManager.UnmountInstalledDLC("TPACK"); + app.DebugPrintf("Unmount result is %d\n",result); + } + } +#endif + } + break; + } + + pClass->m_vNotifications.push_back(pNotification); +} + +#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__ +int CMinecraftApp::MustSignInFullVersionPurchaseReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + if(result==C4JStorage::EMessage_ResultAccept) + { +#ifdef __PS3__ + SQRNetworkManager_PS3::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true); +#elif defined __PSVITA__ + SQRNetworkManager_Vita::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true); +#else // __PS4__ + SQRNetworkManager_Orbis::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true); +#endif + } + + return 0; +} + +#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__ +int CMinecraftApp::MustSignInFullVersionPurchaseReturnedExitTrial(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + if(result==C4JStorage::EMessage_ResultAccept) + { +#ifdef __PS3__ + SQRNetworkManager_PS3::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true); +#elif defined __PSVITA__ + SQRNetworkManager_Vita::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true); +#else // __PS4__ + SQRNetworkManager_Orbis::AttemptPSNSignIn(&CMinecraftApp::NowDisplayFullVersionPurchase, &app,true); +#endif + } + + //4J-PB - we need to exit the trial, or we'll be in the pause menu with ignore input true + app.SetAction(iPad,eAppAction_ExitWorldTrial); + + return 0; +} +#endif + +int CMinecraftApp::NowDisplayFullVersionPurchase(void *pParam, bool bContinue, int iPad) +{ + app.m_bDisplayFullVersionPurchase=true; + return 0; +} +#endif +void CMinecraftApp::UpsellReturnedCallback(LPVOID pParam, eUpsellType type, eUpsellResponse result, int iUserData) +{ + ESen_UpsellID senType; + ESen_UpsellOutcome senResponse; +#ifdef __PS3__ + UINT uiIDA[2]; +#endif + + // Map the eUpsellResponse to the enum we use for sentient + switch(result) + { + case eUpsellResponse_Accepted_NoPurchase: + senResponse = eSen_UpsellOutcome_Went_To_Guide; + break; + case eUpsellResponse_Accepted_Purchase: + senResponse = eSen_UpsellOutcome_Accepted; + break; +#ifdef __PS3__ + // special case for people who are not signed in to the PSN while playing the trial game + case eUpsellResponse_UserNotSignedInPSN: + + uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; + uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; + ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::MustSignInFullVersionPurchaseReturned,&app); + + return; + + case eUpsellResponse_NotAllowedOnline: // On earning a trophy in the trial version, where the user is underage and can't go online to buy the game, but they selected to buy the game on the trophy upsell + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad()); + break; +#endif + case eUpsellResponse_Declined: + default: + senResponse = eSen_UpsellOutcome_Declined; + break; + }; + + // Map the eUpsellType to the enum we use for sentient + switch(type) + { + case eUpsellType_Custom: + senType = eSen_UpsellID_Full_Version_Of_Game; + break; + default: + senType = eSen_UpsellID_Undefined; + break; + }; + + // Always the primary pad that gets an upsell + TelemetryManager->RecordUpsellResponded(ProfileManager.GetPrimaryPad(), eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID, senResponse); +} + +#ifdef _DEBUG_MENUS_ENABLED +bool CMinecraftApp::DebugArtToolsOn() +{ + return DebugSettingsOn() && (GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<(pParam); + //printf("sequence matched\n"); + pClass->m_bDebugOptions=!pClass->m_bDebugOptions; + + for(int i=0;ilocalplayers[i] != nullptr) + { + iPlayerC++; + } + } + + return iPlayerC; +} + +int CMinecraftApp::MarketplaceCountsCallback(LPVOID pParam,C4JStorage::DLC_TMS_DETAILS *pTMSDetails, int iPad) +{ + app.DebugPrintf("Marketplace Counts= New - %d Total - %d\n",pTMSDetails->dwNewOffers,pTMSDetails->dwTotalOffers); + + if(pTMSDetails->dwNewOffers>0) + { + app.m_bNewDLCAvailable=true; + app.m_bSeenNewDLCTip=false; + } + else + { + app.m_bNewDLCAvailable=false; + app.m_bSeenNewDLCTip=true; + } + + return 0; +} + +bool CMinecraftApp::StartInstallDLCProcess(int iPad) +{ + app.DebugPrintf("--- CMinecraftApp::StartInstallDLCProcess: pad=%i.\n", iPad); + + // If there is already a call to this in progress, then do nothing + // If the app says dlc is installed, then there has been no new system message to tell us there's new DLC since the last call to StartInstallDLCProcess + if((app.DLCInstallProcessCompleted()==false) && (m_bDLCInstallPending==false)) + { + app.m_dlcManager.resetUnnamedCorruptCount(); + m_bDLCInstallPending = true; + m_iTotalDLC = 0; + m_iTotalDLCInstalled = 0; + app.DebugPrintf("--- CMinecraftApp::StartInstallDLCProcess - StorageManager.GetInstalledDLC\n"); + + StorageManager.GetInstalledDLC(iPad,&CMinecraftApp::DLCInstalledCallback,this); + return true; + } + else + { + app.DebugPrintf("--- CMinecraftApp::StartInstallDLCProcess - nothing to do\n"); + + return false; + } + +} + +// Installed DLC callback +int CMinecraftApp::DLCInstalledCallback(LPVOID pParam,int iInstalledC,int iPad) +{ + app.DebugPrintf("--- CMinecraftApp::DLCInstalledCallback: totalDLC=%i, pad=%i.\n", iInstalledC, iPad); + app.m_iTotalDLC = iInstalledC; + app.MountNextDLC(iPad); + return 0; +} + +void CMinecraftApp::MountNextDLC(int iPad) +{ + app.DebugPrintf("--- CMinecraftApp::MountNextDLC: pad=%i.\n", iPad); + if(m_iTotalDLCInstalled < m_iTotalDLC) + { + // Mount it + // We also need to match the ones the user wants to mount with the installed DLC + // We're supposed to use a generic save game as a cache of these to do this, with XUSER_ANY + + if(StorageManager.MountInstalledDLC(iPad,m_iTotalDLCInstalled,&CMinecraftApp::DLCMountedCallback,this)!=ERROR_IO_PENDING ) + { + // corrupt DLC + app.DebugPrintf("Failed to mount DLC %d for pad %d\n",m_iTotalDLCInstalled,iPad); + ++m_iTotalDLCInstalled; + app.MountNextDLC(iPad); + } + else + { + app.DebugPrintf("StorageManager.MountInstalledDLC ok\n"); + } + } + else + { + /* Removed - now loading these on demand instead of as each pack is mounted + if(m_iTotalDLCInstalled > 0) + { + Minecraft *pMinecraft=Minecraft::GetInstance(); + pMinecraft->levelRenderer->AddDLCSkinsToMemTextures(); + } + */ + + m_bDLCInstallPending = false; + m_bDLCInstallProcessCompleted=true; + + ui.HandleDLCMountingComplete(); + +#if defined(_XBOX_ONE) || defined(__ORBIS__) + // Check if the current texture pack is now installed + if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) + { + TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; + + DLCPack *pParentPack=pDLCTexPack->getDLCInfoParentPack();//tPack->getDLCPack(); + + if(pParentPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" )) + { + StorageManager.SetSaveDisabled(false); + } + } +#endif +#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ + { + TexturePack* currentTPack = Minecraft::GetInstance()->skins->getSelected(); + TexturePack* requiredTPack = Minecraft::GetInstance()->skins->getTexturePackById(app.GetRequiredTexturePackID()); + if(currentTPack != requiredTPack) + { + Minecraft::GetInstance()->skins->selectTexturePackById(app.GetRequiredTexturePackID()); + } + } +#endif + } +} + +// 4J-JEV: For the sake of clarity in DLCMountedCallback. +#if defined(_XBOX) || defined(__PS3__) || defined(_WINDOWS64) +#define CONTENT_DATA_DISPLAY_NAME(a) (a.szDisplayName) +#else +#define CONTENT_DATA_DISPLAY_NAME(a) (a.wszDisplayName) +#endif + +int CMinecraftApp::DLCMountedCallback(LPVOID pParam,int iPad,DWORD dwErr,DWORD dwLicenceMask) +{ +#if defined(_XBOX) || defined(_DURANGO) || defined(__PS3__) || defined(__ORBIS__) || defined(_WINDOWS64) || defined (__PSVITA__) //Chris TODO + app.DebugPrintf("--- CMinecraftApp::DLCMountedCallback\n"); + + if(dwErr!=ERROR_SUCCESS) + { + // corrupt DLC + app.DebugPrintf("Failed to mount DLC for pad %d: %d\n",iPad,dwErr); + app.m_dlcManager.incrementUnnamedCorruptCount(); + } + else + { + XCONTENT_DATA ContentData = StorageManager.GetDLC(app.m_iTotalDLCInstalled); + + DLCPack *pack = app.m_dlcManager.getPack( CONTENT_DATA_DISPLAY_NAME(ContentData) ); + + if( pack != nullptr && pack->IsCorrupt() ) + { + app.DebugPrintf("Pack '%ls' is corrupt, removing it from the DLC Manager.\n", CONTENT_DATA_DISPLAY_NAME(ContentData)); + + app.m_dlcManager.removePack(pack); + pack = nullptr; + } + + if(pack == nullptr) + { + app.DebugPrintf("Pack \"%ls\" is not installed, so adding it\n", CONTENT_DATA_DISPLAY_NAME(ContentData)); + +#if defined(_XBOX) || defined(__PS3__) || defined(_WINDOWS64) + pack = new DLCPack(ContentData.szDisplayName,dwLicenceMask); +#elif defined _XBOX_ONE + pack = new DLCPack(ContentData.wszDisplayName,ContentData.wszProductID,dwLicenceMask); +#else + pack = new DLCPack(ContentData.wszDisplayName,dwLicenceMask); +#endif + pack->SetDLCMountIndex(app.m_iTotalDLCInstalled); + pack->SetDLCDeviceID(ContentData.DeviceID); + app.m_dlcManager.addPack(pack); + + app.HandleDLC(pack); + + if(pack->getDLCItemsCount(DLCManager::e_DLCType_Texture) > 0) + { + Minecraft::GetInstance()->skins->addTexturePackFromDLC(pack, pack->GetPackId() ); + } + } + else + { + app.DebugPrintf("Pack \"%ls\" is already installed. Updating license to %d\n", CONTENT_DATA_DISPLAY_NAME(ContentData), dwLicenceMask); + + pack->SetDLCMountIndex(app.m_iTotalDLCInstalled); + pack->SetDLCDeviceID(ContentData.DeviceID); + pack->updateLicenseMask(dwLicenceMask); + } + + StorageManager.UnmountInstalledDLC(); + } + ++app.m_iTotalDLCInstalled; + app.MountNextDLC(iPad); + +#endif // __PSVITA__ + return 0; +} +#undef CONTENT_DATA_DISPLAY_NAME + +// void CMinecraftApp::InstallDefaultCape() +// { +// if(!m_bDefaultCapeInstallAttempted) +// { +// // we only attempt to install the cape once per launch of the game +// m_bDefaultCapeInstallAttempted=true; +// +// wstring wTemp=L"Default_Cape.png"; +// bool bRes=app.IsFileInMemoryTextures(wTemp); +// // if the file is not already in the memory textures, then read it from TMS +// if(!bRes) +// { +// BYTE* pBuffer = nullptr; +// DWORD dwSize=0; +// // 4J-PB - out for now for DaveK so he doesn't get the birthday cape +// #ifdef _CONTENT_PACKAGE +// C4JStorage::ETMSStatus eTMSStatus; +// eTMSStatus=StorageManager.ReadTMSFile(ProfileManager.GetPrimaryPad(),C4JStorage::eGlobalStorage_Title,C4JStorage::eTMS_FileType_Graphic, L"Default_Cape.png",&pBuffer, &dwSize); +// if(eTMSStatus==C4JStorage::ETMSStatus_Idle) +// { +// app.AddMemoryTextureFile(wTemp,pBuffer,dwSize); +// } +// #endif +// } +// } +// } + +void CMinecraftApp::HandleDLC(DLCPack *pack) +{ + DWORD dwFilesProcessed = 0; +#ifndef _XBOX +#if defined(__PS3__) || defined(__ORBIS__) || defined(_WINDOWS64) || defined (__PSVITA__) + std::vector dlcFilenames; +#elif defined _DURANGO + std::vector dlcFilenames; +#endif + StorageManager.GetMountedDLCFileList("DLCDrive", dlcFilenames); +#ifdef __ORBIS__ + // 4J Stu - I don't know why we handle more than one file here any more, however this doesn't seem to work with the PS4 patches + if(dlcFilenames.size() > 0) m_dlcManager.readDLCDataFile(dwFilesProcessed, dlcFilenames[0], pack); +#else + for(size_t i=0; i(qwTicksPerSec.QuadPart); + + // Save the start time + QueryPerformanceCounter( &m_Time.qwTime ); + + // Zero out the elapsed and total time + m_Time.qwAppTime.QuadPart = 0; + m_Time.fAppTime = 0.0f; + m_Time.fElapsedTime = 0.0f; +} + +//------------------------------------------------------------------------------------- +// Name: UpdateTime() +// Desc: Updates the elapsed time since our last frame. +//------------------------------------------------------------------------------------- +void CMinecraftApp::UpdateTime() +{ + LARGE_INTEGER qwNewTime; + LARGE_INTEGER qwDeltaTime; + + QueryPerformanceCounter( &qwNewTime ); + qwDeltaTime.QuadPart = qwNewTime.QuadPart - m_Time.qwTime.QuadPart; + + m_Time.qwAppTime.QuadPart += qwDeltaTime.QuadPart; + m_Time.qwTime.QuadPart = qwNewTime.QuadPart; + + m_Time.fElapsedTime = m_Time.fSecsPerTick * static_cast(qwDeltaTime.QuadPart); + m_Time.fAppTime = m_Time.fSecsPerTick * static_cast(m_Time.qwAppTime.QuadPart); +} + +bool CMinecraftApp::isXuidNotch(PlayerUID xuid) +{ + if(m_xuidNotch != INVALID_XUID && xuid != INVALID_XUID) + { + return ProfileManager.AreXUIDSEqual(xuid, m_xuidNotch) == TRUE; + } + return false; +} + +bool CMinecraftApp::isXuidDeadmau5(PlayerUID xuid) +{ + auto it = MojangData.find(xuid); // 4J Stu - The .at and [] accessors insert elements if they don't exist + if (it != MojangData.end() ) + { + MOJANG_DATA *pMojangData=MojangData[xuid]; + if(pMojangData && pMojangData->eXuid==eXUID_Deadmau5) + { + return true; + } + } + + return false; +} + +void CMinecraftApp::AddMemoryTextureFile(const wstring &wName,PBYTE pbData,DWORD dwBytes) +{ + EnterCriticalSection(&csMemFilesLock); + // check it's not already in + PMEMDATA pData=nullptr; + auto it = m_MEM_Files.find(wName); + if(it != m_MEM_Files.end()) + { +#ifndef _CONTENT_PACKAGE + wprintf(L"Incrementing the memory texture file count for %ls\n", wName.c_str()); +#endif + pData = (*it).second; + + if(pData->dwBytes == 0 && dwBytes != 0) + { + // This should never be nullptr if dwBytes is 0 + if(pData->pbData!=nullptr) delete [] pData->pbData; + + pData->pbData=pbData; + pData->dwBytes=dwBytes; + } + + ++pData->ucRefCount; + LeaveCriticalSection(&csMemFilesLock); + return; + } + +#ifndef _CONTENT_PACKAGE + //wprintf(L"Adding the memory texture file data for %ls\n", wName.c_str()); +#endif + // this is a texture (png) file + + // add this texture to the list of memory texture files - it will then be picked up by the level renderer's AddEntity + + pData = (PMEMDATA)new BYTE[sizeof(MEMDATA)]; + ZeroMemory( pData, sizeof(MEMDATA) ); + pData->pbData=pbData; + pData->dwBytes=dwBytes; + pData->ucRefCount = 1; + + // use the xuid to access the skin data + m_MEM_Files[wName]=pData; + + LeaveCriticalSection(&csMemFilesLock); +} + +void CMinecraftApp::RemoveMemoryTextureFile(const wstring &wName) +{ + EnterCriticalSection(&csMemFilesLock); + + auto it = m_MEM_Files.find(wName); + if(it != m_MEM_Files.end()) + { +#ifndef _CONTENT_PACKAGE + wprintf(L"Decrementing the memory texture file count for %ls\n", wName.c_str()); +#endif + PMEMDATA pData = (*it).second; + --pData->ucRefCount; + if(pData->ucRefCount <= 0) + { +#ifndef _CONTENT_PACKAGE + wprintf(L"Erasing the memory texture file data for %ls\n", wName.c_str()); +#endif + delete [] pData; + m_MEM_Files.erase(wName); + } + } + LeaveCriticalSection(&csMemFilesLock); +} + +bool CMinecraftApp::DefaultCapeExists() +{ + wstring wTex=L"Special_Cape.png"; + bool val = false; + + EnterCriticalSection(&csMemFilesLock); + auto it = m_MEM_Files.find(wTex); + if(it != m_MEM_Files.end()) val = true; + LeaveCriticalSection(&csMemFilesLock); + + return val; +} + +bool CMinecraftApp::IsFileInMemoryTextures(const wstring &wName) +{ + bool val = false; + + EnterCriticalSection(&csMemFilesLock); + auto it = m_MEM_Files.find(wName); + if(it != m_MEM_Files.end()) val = true; + LeaveCriticalSection(&csMemFilesLock); + + return val; +} + +void CMinecraftApp::GetMemFileDetails(const wstring &wName,PBYTE *ppbData,DWORD *pdwBytes) +{ + EnterCriticalSection(&csMemFilesLock); + auto it = m_MEM_Files.find(wName); + if(it != m_MEM_Files.end()) + { + PMEMDATA pData = (*it).second; + *ppbData=pData->pbData; + *pdwBytes=pData->dwBytes; + } + LeaveCriticalSection(&csMemFilesLock); +} + +void CMinecraftApp::AddMemoryTPDFile(int iConfig,PBYTE pbData,DWORD dwBytes) +{ + EnterCriticalSection(&csMemTPDLock); + // check it's not already in + PMEMDATA pData=nullptr; + auto it = m_MEM_TPD.find(iConfig); + if(it == m_MEM_TPD.end()) + { + pData = (PMEMDATA)new BYTE[sizeof(MEMDATA)]; + ZeroMemory( pData, sizeof(MEMDATA) ); + pData->pbData=pbData; + pData->dwBytes=dwBytes; + pData->ucRefCount = 1; + + m_MEM_TPD[iConfig]=pData; + } + + LeaveCriticalSection(&csMemTPDLock); +} + +void CMinecraftApp::RemoveMemoryTPDFile(int iConfig) +{ + EnterCriticalSection(&csMemTPDLock); + // check it's not already in + PMEMDATA pData=nullptr; + auto it = m_MEM_TPD.find(iConfig); + if(it != m_MEM_TPD.end()) + { + pData=m_MEM_TPD[iConfig]; + delete [] pData; + m_MEM_TPD.erase(iConfig); + } + + LeaveCriticalSection(&csMemTPDLock); +} + +#ifdef _XBOX +int CMinecraftApp::GetTPConfigVal(WCHAR *pwchDataFile) +{ + DLC_INFO *pDLCInfo=nullptr; + // run through the DLC info to find the right texture pack/mash-up pack + for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i) + { + ULONGLONG ull=app.GetDLCInfoTexturesFullOffer(i); + pDLCInfo=app.GetDLCInfoForFullOfferID(ull); + + if(wcscmp(pwchDataFile,pDLCInfo->wchDataFile)==0) + { + return pDLCInfo->iConfig; + } + } + + return -1; +} +#elif defined _XBOX_ONE +int CMinecraftApp::GetTPConfigVal(WCHAR *pwchDataFile) +{ + DLC_INFO *pDLCInfo=nullptr; + // run through the DLC info to find the right texture pack/mash-up pack + for(unsigned int i = 0; i < app.GetDLCInfoTexturesOffersCount(); ++i) + { + pDLCInfo=app.GetDLCInfoForFullOfferID((WCHAR *)app.GetDLCInfoTexturesFullOffer(i).c_str()); + + if(wcscmp(pwchDataFile,pDLCInfo->wchDataFile)==0) + { + return pDLCInfo->iConfig; + } + } + + return -1; +} +#elif defined _WINDOWS64 +int CMinecraftApp::GetTPConfigVal(WCHAR *pwchDataFile) +{ + return -1; +} +#endif +bool CMinecraftApp::IsFileInTPD(int iConfig) +{ + bool val = false; + + EnterCriticalSection(&csMemTPDLock); + auto it = m_MEM_TPD.find(iConfig); + if(it != m_MEM_TPD.end()) val = true; + LeaveCriticalSection(&csMemTPDLock); + + return val; +} + +void CMinecraftApp::GetTPD(int iConfig,PBYTE *ppbData,DWORD *pdwBytes) +{ + EnterCriticalSection(&csMemTPDLock); + auto it = m_MEM_TPD.find(iConfig); + if(it != m_MEM_TPD.end()) + { + PMEMDATA pData = (*it).second; + *ppbData=pData->pbData; + *pdwBytes=pData->dwBytes; + } + LeaveCriticalSection(&csMemTPDLock); +} + + +// bool CMinecraftApp::UploadFileToGlobalStorage(int iQuadrant, C4JStorage::eGlobalStorage eStorageFacility, wstring *wsFile ) +// { +// bool bRes=false; +// #ifndef _CONTENT_PACKAGE +// // read the local file +// File gtsFile( wsFile->c_str() ); +// +// int64_t fileSize = gtsFile.length(); +// +// if(fileSize!=0) +// { +// FileInputStream fis(gtsFile); +// byteArray ba((int)fileSize); +// fis.read(ba); +// fis.close(); +// +// bRes=StorageManager.WriteTMSFile(iQuadrant,eStorageFacility,(WCHAR *)wsFile->c_str(),ba.data, ba.length); +// +// } +// #endif +// return bRes; +// } + + + + + + +void CMinecraftApp::StoreLaunchData() +{ + +} + +void CMinecraftApp::ExitGame() +{ +} + +// Invites + +void CMinecraftApp::ProcessInvite(DWORD dwUserIndex, DWORD dwLocalUsersMask, const INVITE_INFO * pInviteInfo) +{ + m_InviteData.dwUserIndex=dwUserIndex; + m_InviteData.dwLocalUsersMask=dwLocalUsersMask; + m_InviteData.pInviteInfo=pInviteInfo; + //memcpy(&m_InviteData,pJoinData,sizeof(JoinFromInviteData)); + SetAction(dwUserIndex,eAppAction_ExitAndJoinFromInvite); +} + +int CMinecraftApp::ExitAndJoinFromInvite(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + CMinecraftApp* pApp = static_cast(pParam); + //Minecraft *pMinecraft=Minecraft::GetInstance(); + + // buttons are swapped on this menu + if(result==C4JStorage::EMessage_ResultDecline) + { + pApp->SetAction(iPad,eAppAction_ExitAndJoinFromInviteConfirmed); + } + + return 0; +} + +int CMinecraftApp::ExitAndJoinFromInviteSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + CMinecraftApp *pClass = static_cast(pParam); + // Exit with or without saving + // Decline means save in this dialog + if(result==C4JStorage::EMessage_ResultDecline || result==C4JStorage::EMessage_ResultThirdOption) + { + if( result==C4JStorage::EMessage_ResultDecline ) // Save + { + // Check they have the full texture pack if they are using one + // 4J-PB - Is the player trying to save but they are using a trial texturepack ? + if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) + { + TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); + + DLCPack * pDLCPack=tPack->getDLCPack(); + if(!pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" )) + { + // upsell + // get the dlc texture pack + +#ifdef _XBOX + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; + ULONGLONG ullOfferID_Full; + app.GetDLCFullOfferIDForPackID(pDLCTexPack->getDLCParentPackId(),&ullOfferID_Full); + + // tell sentient about the upsell of the full version of the skin pack + TelemetryManager->RecordUpsellPresented(iPad, eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF); +#endif + + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + + // Give the player a warning about the trial version of the texture pack + ui.RequestErrorMessage(IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, IDS_WARNING_DLC_TRIALTEXTUREPACK_TEXT, uiIDA, 2, iPad,&CMinecraftApp::WarningTrialTexturePackReturned,pClass); + + return S_OK; + } + } +#ifndef _XBOX_ONE + // does the save exist? + bool bSaveExists; + StorageManager.DoesSaveExist(&bSaveExists); + // 4J-PB - we check if the save exists inside the libs + // we need to ask if they are sure they want to overwrite the existing game + if(bSaveExists) + { + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestErrorMessage(IDS_TITLE_SAVE_GAME, IDS_CONFIRM_SAVE_GAME, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::ExitAndJoinFromInviteAndSaveReturned,pClass); + return 0; + } + else +#endif + { +#if defined(_XBOX_ONE) || defined(__ORBIS__) + StorageManager.SetSaveDisabled(false); +#endif + MinecraftServer::getInstance()->setSaveOnExit( true ); + } + } + else + { + // been a few requests for a confirm on exit without saving + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + ui.RequestErrorMessage(IDS_TITLE_DECLINE_SAVE_GAME, IDS_CONFIRM_DECLINE_SAVE_GAME, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CMinecraftApp::ExitAndJoinFromInviteDeclineSaveReturned,pClass); + return 0; + } + + app.SetAction(ProfileManager.GetPrimaryPad(),eAppAction_ExitAndJoinFromInviteConfirmed); + } + return 0; +} + +int CMinecraftApp::WarningTrialTexturePackReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + // 4J Stu - I added this in when fixing an X1 bug. We should probably add this as well but I don't have time to test all platforms atm +#if 0 //defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + if(result==C4JStorage::EMessage_ResultAccept) + { + if(!ProfileManager.IsSignedInLive(iPad)) + { + // you're not signed in to PSN! + + } + else + { + // 4J-PB - need to check this user can access the store + bool bContentRestricted; + ProfileManager.GetChatAndContentRestrictions(iPad,true,nullptr,&bContentRestricted,nullptr); + if(bContentRestricted) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestAlertMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPad); + } + else + { + // need to get info on the pack to see if the user has already downloaded it + TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; + + // retrieve the store name for the skin pack + DLCPack *pDLCPack=pDLCTexPack->getDLCInfoParentPack();//tPack->getDLCPack(); + const char *pchPackName=wstringtofilename(pDLCPack->getName()); + app.DebugPrintf("Texture Pack - %s\n",pchPackName); + SONYDLC *pSONYDLCInfo=app.GetSONYDLCInfo((char *)pchPackName); + + if(pSONYDLCInfo!=nullptr) + { + char chName[42]; + char chSkuID[SCE_NP_COMMERCE2_SKU_ID_LEN]; + + memset(chSkuID,0,SCE_NP_COMMERCE2_SKU_ID_LEN); + // find the info on the skin pack + // we have to retrieve the skuid from the store info, it can't be hardcoded since Sony may change it. + // So we assume the first sku for the product is the one we want +#ifdef __ORBIS__ + sprintf(chName,"%s",pSONYDLCInfo->chDLCKeyname); +#else + sprintf(chName,"%s-%s",app.GetCommerceCategory(),pSONYDLCInfo->chDLCKeyname); +#endif + app.GetDLCSkuIDFromProductList(chName,chSkuID); + // 4J-PB - need to check for an empty store +#if defined __ORBIS__ || defined __PSVITA__ || defined __PS3__ + if(app.CheckForEmptyStore(iPad)==false) +#endif + { + if(app.DLCAlreadyPurchased(chSkuID)) + { + app.DownloadAlreadyPurchased(chSkuID); + } + else + { + app.Checkout(chSkuID); + } + } + } + } + } + } +#endif // + +#ifdef _XBOX_ONE + if(result==C4JStorage::EMessage_ResultAccept) + { + if(ProfileManager.IsSignedIn(iPad)) + { + if (ProfileManager.IsSignedInLive(iPad)) + { + TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); + // get the dlc texture pack + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; + + DLCPack *pDLCPack=pDLCTexPack->getDLCInfoParentPack(); + + DLC_INFO *pDLCInfo=app.GetDLCInfoForProductName((WCHAR *)pDLCPack->getName().c_str()); + + StorageManager.InstallOffer(1,(WCHAR *)pDLCInfo->wsProductId.c_str(),nullptr,nullptr); + + // the license change coming in when the offer has been installed will cause this scene to refresh + } + else + { + // 4J-JEV: Fix for XB1: #165863 - XR-074: Compliance: With no active network connection user is unable to convert from Trial to Full texture pack and is not messaged why. + UINT uiIDA[1] = { IDS_CONFIRM_OK }; + ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1, iPad); + } + } + } + +#endif +#ifdef _XBOX + + CMinecraftApp* pClass = (CMinecraftApp*)pParam; + + TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); + // get the dlc texture pack + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; + ULONGLONG ullIndexA[1]; + + // Need to get the parent packs id, since this may be one of many child packs with their own ids + app.GetDLCFullOfferIDForPackID(pDLCTexPack->getDLCParentPackId(),&ullIndexA[0]); + + if(result==C4JStorage::EMessage_ResultAccept) + { + if(ProfileManager.IsSignedIn(iPad)) + { + // need to allow downloads here, or the player would need to quit the game to let the download of a texture pack happen. This might affect the network traffic, since the download could take all the bandwidth... + XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW); + + StorageManager.InstallOffer(1,ullIndexA,nullptr,nullptr); + } + } + else + { + TelemetryManager->RecordUpsellResponded(iPad, eSet_UpsellID_Texture_DLC, ( ullIndexA[0] & 0xFFFFFFFF ), eSen_UpsellOutcome_Declined); + } +#endif + return 0; +} + +int CMinecraftApp::ExitAndJoinFromInviteAndSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + //CMinecraftApp* pClass = (CMinecraftApp*)pParam; + + // results switched for this dialog + if(result==C4JStorage::EMessage_ResultDecline) + { + INT saveOrCheckpointId = 0; + + // Check they have the full texture pack if they are using one + // 4J-PB - Is the player trying to save but they are using a trial texturepack ? + if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) + { + TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); + + DLCPack * pDLCPack=tPack->getDLCPack(); + if(!pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" )) + { + // upsell + // get the dlc texture pack + +#ifdef _XBOX + DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; + ULONGLONG ullOfferID_Full; + app.GetDLCFullOfferIDForPackID(pDLCTexPack->getDLCParentPackId(),&ullOfferID_Full); + + // tell sentient about the upsell of the full version of the skin pack + TelemetryManager->RecordUpsellPresented(iPad, eSet_UpsellID_Texture_DLC, ullOfferID_Full & 0xFFFFFFFF); +#endif + + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + + // Give the player a warning about the trial version of the texture pack + ui.RequestErrorMessage(IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, IDS_WARNING_DLC_TRIALTEXTUREPACK_TEXT, uiIDA, 2, iPad,&CMinecraftApp::WarningTrialTexturePackReturned,nullptr); + + return S_OK; + } + } + //bool validSave = StorageManager.GetSaveUniqueNumber(&saveOrCheckpointId); + //SentientManager.RecordLevelSaveOrCheckpoint(ProfileManager.GetPrimaryPad(), saveOrCheckpointId); + MinecraftServer::getInstance()->setSaveOnExit( true ); + // flag a app action of exit and join game from invite + app.SetAction(iPad,eAppAction_ExitAndJoinFromInviteConfirmed); + } + return 0; +} + +int CMinecraftApp::ExitAndJoinFromInviteDeclineSaveReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + // results switched for this dialog + if(result==C4JStorage::EMessage_ResultDecline) + { +#if defined(_XBOX_ONE) || defined(__ORBIS__) + StorageManager.SetSaveDisabled(false); +#endif + MinecraftServer::getInstance()->setSaveOnExit( false ); + // flag a app action of exit and join game from invite + app.SetAction(iPad,eAppAction_ExitAndJoinFromInviteConfirmed); + } + return 0; +} + +////////////////////////////////////////////////////////////////////////// +// +// FatalLoadError +// +// This is called when we can't load one of the required files at startup +// It tends to mean the files have been corrupted. +// We have to assume that we've not been able to load the text for the game. +// +////////////////////////////////////////////////////////////////////////// +void CMinecraftApp::FatalLoadError() +{ + +} + +TIPSTRUCT CMinecraftApp::m_GameTipA[MAX_TIPS_GAMETIP]= +{ + { 0, IDS_TIPS_GAMETIP_1}, + { 0, IDS_TIPS_GAMETIP_2}, + { 0, IDS_TIPS_GAMETIP_3}, + { 0, IDS_TIPS_GAMETIP_4}, + { 0, IDS_TIPS_GAMETIP_5}, + { 0, IDS_TIPS_GAMETIP_6}, + { 0, IDS_TIPS_GAMETIP_7}, + { 0, IDS_TIPS_GAMETIP_8}, + { 0, IDS_TIPS_GAMETIP_9}, + { 0, IDS_TIPS_GAMETIP_10}, + { 0, IDS_TIPS_GAMETIP_11}, + { 0, IDS_TIPS_GAMETIP_12}, + { 0, IDS_TIPS_GAMETIP_13}, + { 0, IDS_TIPS_GAMETIP_14}, + { 0, IDS_TIPS_GAMETIP_15}, + { 0, IDS_TIPS_GAMETIP_16}, + { 0, IDS_TIPS_GAMETIP_17}, + { 0, IDS_TIPS_GAMETIP_18}, + { 0, IDS_TIPS_GAMETIP_19}, + { 0, IDS_TIPS_GAMETIP_20}, + { 0, IDS_TIPS_GAMETIP_21}, + { 0, IDS_TIPS_GAMETIP_22}, + { 0, IDS_TIPS_GAMETIP_23}, + { 0, IDS_TIPS_GAMETIP_24}, + { 0, IDS_TIPS_GAMETIP_25}, + { 0, IDS_TIPS_GAMETIP_26}, + { 0, IDS_TIPS_GAMETIP_27}, + { 0, IDS_TIPS_GAMETIP_28}, + { 0, IDS_TIPS_GAMETIP_29}, + { 0, IDS_TIPS_GAMETIP_30}, + { 0, IDS_TIPS_GAMETIP_31}, + { 0, IDS_TIPS_GAMETIP_32}, + { 0, IDS_TIPS_GAMETIP_33}, + { 0, IDS_TIPS_GAMETIP_34}, + { 0, IDS_TIPS_GAMETIP_35}, + { 0, IDS_TIPS_GAMETIP_36}, + { 0, IDS_TIPS_GAMETIP_37}, + { 0, IDS_TIPS_GAMETIP_38}, + { 0, IDS_TIPS_GAMETIP_39}, + { 0, IDS_TIPS_GAMETIP_40}, + { 0, IDS_TIPS_GAMETIP_41}, + { 0, IDS_TIPS_GAMETIP_42}, + { 0, IDS_TIPS_GAMETIP_43}, + { 0, IDS_TIPS_GAMETIP_44}, + { 0, IDS_TIPS_GAMETIP_45}, + { 0, IDS_TIPS_GAMETIP_46}, + { 0, IDS_TIPS_GAMETIP_47}, + { 0, IDS_TIPS_GAMETIP_48}, + { 0, IDS_TIPS_GAMETIP_49}, + { 0, IDS_TIPS_GAMETIP_50}, +}; + +TIPSTRUCT CMinecraftApp::m_TriviaTipA[MAX_TIPS_TRIVIATIP]= +{ + { 0, IDS_TIPS_TRIVIA_1}, + { 0, IDS_TIPS_TRIVIA_2}, + { 0, IDS_TIPS_TRIVIA_3}, + { 0, IDS_TIPS_TRIVIA_4}, + { 0, IDS_TIPS_TRIVIA_5}, + { 0, IDS_TIPS_TRIVIA_6}, + { 0, IDS_TIPS_TRIVIA_7}, + { 0, IDS_TIPS_TRIVIA_8}, + { 0, IDS_TIPS_TRIVIA_9}, + { 0, IDS_TIPS_TRIVIA_10}, + { 0, IDS_TIPS_TRIVIA_11}, + { 0, IDS_TIPS_TRIVIA_12}, + { 0, IDS_TIPS_TRIVIA_13}, + { 0, IDS_TIPS_TRIVIA_14}, + { 0, IDS_TIPS_TRIVIA_15}, + { 0, IDS_TIPS_TRIVIA_16}, + { 0, IDS_TIPS_TRIVIA_17}, + { 0, IDS_TIPS_TRIVIA_18}, + { 0, IDS_TIPS_TRIVIA_19}, + { 0, IDS_TIPS_TRIVIA_20}, +}; + +Random *CMinecraftApp::TipRandom = new Random(); + +int CMinecraftApp::TipsSortFunction(const void* a, const void* b) +{ + return ((TIPSTRUCT*)a)->iSortValue - ((TIPSTRUCT*)b)->iSortValue; +} + +void CMinecraftApp::InitialiseTips() +{ + // We'll randomise the tips at start up based on their priority + + ZeroMemory(m_TipIDA,sizeof(UINT)*MAX_TIPS_GAMETIP+MAX_TIPS_TRIVIATIP); + + // Make the first tip tell you that you can play splitscreen in HD modes if you are in SD + if(!RenderManager.IsHiDef()) + { + m_GameTipA[0].uiStringID=IDS_TIPS_GAMETIP_0; + } + // randomise then quicksort + // going to leave the multiplayer tip so it is always first + + // Only randomise the content package build +#ifdef _CONTENT_PACKAGE + + for(int i=1;inextInt(); + } + qsort( &m_GameTipA[1], MAX_TIPS_GAMETIP-1, sizeof(TIPSTRUCT), TipsSortFunction ); +#endif + + for(int i=0;inextInt(); + } + qsort( m_TriviaTipA, MAX_TIPS_TRIVIATIP, sizeof(TIPSTRUCT), TipsSortFunction ); + + + int iCurrentGameTip=0; + int iCurrentTriviaTip=0; + + for(int i=0;iskins->getSelected()->getColourTable()->getColour(colour); +} + +int CMinecraftApp::GetHTMLFontSize(EHTMLFontSize size) +{ + return s_iHTMLFontSizesA[size]; +} + +wstring CMinecraftApp::FormatHTMLString(int iPad, const wstring &desc, int shadowColour /*= 0xFFFFFFFF*/, bool override) +{ + wstring text(desc); + + wchar_t replacements[64]; + // We will also insert line breaks here as couldn't figure out how to get them to come through from strings.resx ! + text = replaceAll(text, L"{*B*}", L"
" ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_T1)); + text = replaceAll(text, L"{*T1*}", replacements ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_T2)); + text = replaceAll(text, L"{*T2*}", replacements ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_T3)); + text = replaceAll(text, L"{*T3*}", replacements ); // for How To Play + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_Black)); + text = replaceAll(text, L"{*ETB*}", replacements ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_White)); + text = replaceAll(text, L"{*ETW*}", replacements ); + text = replaceAll(text, L"{*EF*}", L"" ); + + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_0), shadowColour); + text = replaceAll(text, L"{*C0*}", replacements ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_1), shadowColour); + text = replaceAll(text, L"{*C1*}", replacements ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_2), shadowColour); + text = replaceAll(text, L"{*C2*}", replacements ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_3), shadowColour); + text = replaceAll(text, L"{*C3*}", replacements ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_4), shadowColour); + text = replaceAll(text, L"{*C4*}", replacements ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_5), shadowColour); + text = replaceAll(text, L"{*C5*}", replacements ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_6), shadowColour); + text = replaceAll(text, L"{*C6*}", replacements ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_7), shadowColour); + text = replaceAll(text, L"{*C7*}", replacements ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_8), shadowColour); + text = replaceAll(text, L"{*C8*}", replacements ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_9), shadowColour); + text = replaceAll(text, L"{*C9*}", replacements ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_a), shadowColour); + text = replaceAll(text, L"{*CA*}", replacements ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_b), shadowColour); + text = replaceAll(text, L"{*CB*}", replacements ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_c), shadowColour); + text = replaceAll(text, L"{*CC*}", replacements ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_d), shadowColour); + text = replaceAll(text, L"{*CD*}", replacements ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_e), shadowColour); + text = replaceAll(text, L"{*CE*}", replacements ); + swprintf(replacements,64,L"", GetHTMLColour(eHTMLColor_f), shadowColour); + text = replaceAll(text, L"{*CF*}", replacements ); + + // Swap for southpaw. + if ( app.GetGameSettings(iPad,eGameSetting_ControlSouthPaw) ) + { + text = replaceAll(text, L"{*CONTROLLER_ACTION_MOVE*}", GetActionReplacement(iPad,MINECRAFT_ACTION_LOOK_RIGHT ) ); + text = replaceAll(text, L"{*CONTROLLER_ACTION_LOOK*}", GetActionReplacement(iPad,MINECRAFT_ACTION_RIGHT ) ); + + text = replaceAll(text, L"{*CONTROLLER_MENU_NAVIGATE*}", GetVKReplacement(VK_PAD_RTHUMB_LEFT) ); + } + else // Normal right handed. + { + text = replaceAll(text, L"{*CONTROLLER_ACTION_MOVE*}", GetActionReplacement(iPad,MINECRAFT_ACTION_RIGHT ) ); + text = replaceAll(text, L"{*CONTROLLER_ACTION_LOOK*}", GetActionReplacement(iPad,MINECRAFT_ACTION_LOOK_RIGHT ) ); + + text = replaceAll(text, L"{*CONTROLLER_MENU_NAVIGATE*}", GetVKReplacement(VK_PAD_LTHUMB_LEFT) ); + } + + text = replaceAll(text, L"{*CONTROLLER_ACTION_JUMP*}", GetActionReplacement(iPad,MINECRAFT_ACTION_JUMP ) ); + text = replaceAll(text, L"{*CONTROLLER_ACTION_SNEAK*}", GetActionReplacement(iPad,MINECRAFT_ACTION_SNEAK_TOGGLE ) ); + text = replaceAll(text, L"{*CONTROLLER_ACTION_USE*}", GetActionReplacement(iPad,MINECRAFT_ACTION_USE ) ); + text = replaceAll(text, L"{*CONTROLLER_ACTION_ACTION*}", GetActionReplacement(iPad,MINECRAFT_ACTION_ACTION ) ); + text = replaceAll(text, L"{*CONTROLLER_ACTION_LEFT_SCROLL*}", GetActionReplacement(iPad,MINECRAFT_ACTION_LEFT_SCROLL ) ); + text = replaceAll(text, L"{*CONTROLLER_ACTION_RIGHT_SCROLL*}", GetActionReplacement(iPad,MINECRAFT_ACTION_RIGHT_SCROLL ) ); + text = replaceAll(text, L"{*CONTROLLER_ACTION_INVENTORY*}", GetActionReplacement(iPad,MINECRAFT_ACTION_INVENTORY ) ); + text = replaceAll(text, L"{*CONTROLLER_ACTION_CRAFTING*}", GetActionReplacement(iPad,MINECRAFT_ACTION_CRAFTING ) ); + text = replaceAll(text, L"{*CONTROLLER_ACTION_DROP*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DROP ) ); + text = replaceAll(text, L"{*CONTROLLER_ACTION_CAMERA*}", GetActionReplacement(iPad,MINECRAFT_ACTION_RENDER_THIRD_PERSON ) ); + text = replaceAll(text, L"{*CONTROLLER_ACTION_MENU_PAGEDOWN*}", GetActionReplacement(iPad,ACTION_MENU_PAGEDOWN ) ); + text = replaceAll(text, L"{*CONTROLLER_ACTION_DISMOUNT*}", GetActionReplacement(iPad,MINECRAFT_ACTION_SNEAK_TOGGLE ) ); + text = replaceAll(text, L"{*CONTROLLER_VK_A*}", GetVKReplacement(VK_PAD_A) ); + text = replaceAll(text, L"{*CONTROLLER_VK_B*}", GetVKReplacement(VK_PAD_B) ); + text = replaceAll(text, L"{*CONTROLLER_VK_X*}", GetVKReplacement(VK_PAD_X) ); + text = replaceAll(text, L"{*CONTROLLER_VK_Y*}", GetVKReplacement(VK_PAD_Y, override) ); + text = replaceAll(text, L"{*CONTROLLER_VK_LB*}", GetVKReplacement(VK_PAD_LSHOULDER) ); + text = replaceAll(text, L"{*CONTROLLER_VK_RB*}", GetVKReplacement(VK_PAD_RSHOULDER) ); + text = replaceAll(text, L"{*CONTROLLER_VK_LS*}", GetVKReplacement(VK_PAD_LTHUMB_UP) ); + text = replaceAll(text, L"{*CONTROLLER_VK_RS*}", GetVKReplacement(VK_PAD_RTHUMB_UP) ); + text = replaceAll(text, L"{*CONTROLLER_VK_LT*}", GetVKReplacement(VK_PAD_LTRIGGER) ); + text = replaceAll(text, L"{*CONTROLLER_VK_RT*}", GetVKReplacement(VK_PAD_RTRIGGER) ); + text = replaceAll(text, L"{*ICON_SHANK_01*}", GetIconReplacement(XZP_ICON_SHANK_01) ); + text = replaceAll(text, L"{*ICON_SHANK_03*}", GetIconReplacement(XZP_ICON_SHANK_03) ); + text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_UP*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DPAD_UP ) ); + text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_DOWN*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DPAD_DOWN ) ); + text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_RIGHT*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DPAD_RIGHT ) ); + text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_LEFT*}", GetActionReplacement(iPad,MINECRAFT_ACTION_DPAD_LEFT ) ); +#if defined _XBOX_ONE || defined __PSVITA__ + text = replaceAll(text, L"{*CONTROLLER_VK_START*}", GetVKReplacement(VK_PAD_START ) ); + text = replaceAll(text, L"{*CONTROLLER_VK_BACK*}", GetVKReplacement(VK_PAD_BACK ) ); +#endif + +#ifdef _XBOX + wstring imageRoot = L""; + + Minecraft *pMinecraft = Minecraft::GetInstance(); + imageRoot = pMinecraft->skins->getSelected()->getXuiRootPath(); + + text = replaceAll(text, L"{*IMAGEROOT*}", imageRoot); +#endif // _XBOX + + // Fix for #8903 - UI: Localization: KOR/JPN/CHT: Button Icons are rendered with padding space, which looks no good + DWORD dwLanguage = XGetLanguage( ); + switch(dwLanguage) + { + case XC_LANGUAGE_KOREAN: + case XC_LANGUAGE_JAPANESE: + case XC_LANGUAGE_TCHINESE: + text = replaceAll(text, L" ", L"" ); + break; + } + + return text; +} + +//found list of html escapes at https://stackoverflow.com/questions/7381974/which-characters-need-to-be-escaped-in-html +wstring CMinecraftApp::EscapeHTMLString(const wstring& desc) +{ + static std::unordered_map replacementMap = { + {L'&', L"&"}, + {L'<', L"<"}, + {L'>', L">"}, + {L'\'', L"\u2019"}, + }; + + wstring finalString = L""; + for (int i = 0; i < desc.size(); i++) { + wchar_t _char = desc[i]; + auto it = replacementMap.find(_char); + + if (it != replacementMap.end()) finalString += it->second; + else finalString += _char; + } + + return finalString; +} + +wstring CMinecraftApp::FormatChatMessage(const wstring& desc, bool applyStyling) +{ + static std::wregex IDS_Pattern(LR"(\{\*IDS_(\d+)\*\})"); //maybe theres a better way to do translateable IDS + static std::wstring_view colorFormatString = L""; + + wstring results = desc; + wchar_t replacements[64]; + + swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_0), 0xFFFFFFFF); + results = replaceAll(results, L"\u00A70", replacements); + + swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_1), 0xFFFFFFFF); + results = replaceAll(results, L"\u00A71", replacements); + + swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_2), 0xFFFFFFFF); + results = replaceAll(results, L"\u00A72", replacements); + + swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_3), 0xFFFFFFFF); + results = replaceAll(results, L"\u00A73", replacements); + + swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_4), 0xFFFFFFFF); + results = replaceAll(results, L"\u00A74", replacements); + + swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_5), 0xFFFFFFFF); + results = replaceAll(results, L"\u00A75", replacements); + + swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_6), 0xFFFFFFFF); + results = replaceAll(results, L"\u00A76", replacements); + + swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_7), 0xFFFFFFFF); + results = replaceAll(results, L"\u00A77", replacements); + + swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_8), 0xFFFFFFFF); + results = replaceAll(results, L"\u00A78", replacements); + + swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_9), 0xFFFFFFFF); + results = replaceAll(results, L"\u00A79", replacements); + + swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_a), 0xFFFFFFFF); + results = replaceAll(results, L"\u00A7a", replacements); + + swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_b), 0xFFFFFFFF); + results = replaceAll(results, L"\u00A7b", replacements); + + swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_c), 0xFFFFFFFF); + results = replaceAll(results, L"\u00A7c", replacements); + + swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_d), 0xFFFFFFFF); + results = replaceAll(results, L"\u00A7d", replacements); + + swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_e), 0xFFFFFFFF); + results = replaceAll(results, L"\u00A7e", replacements); + + swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_f), 0xFFFFFFFF); + results = replaceAll(results, L"\u00A7f", replacements); + results = replaceAll(results, L"\u00A7r", replacements); //we only support color so reset is the same as white color + + if (applyStyling) { + std::wsmatch match; + while (std::regex_search(results, match, IDS_Pattern)) { + results = replaceAll(results, match[0], app.GetString(std::stoi(match[1].str()))); + } + } + + + return results; +} + +wstring CMinecraftApp::GetActionReplacement(int iPad, unsigned char ucAction) +{ + unsigned int input = InputManager.GetGameJoypadMaps(InputManager.GetJoypadMapVal(iPad) ,ucAction); + +#ifdef _XBOX + switch(input) + { + case _360_JOY_BUTTON_A: + return app.GetString( IDS_CONTROLLER_A ); + case _360_JOY_BUTTON_B: + return app.GetString( IDS_CONTROLLER_B ); + case _360_JOY_BUTTON_X: + return app.GetString( IDS_CONTROLLER_X ); + case _360_JOY_BUTTON_Y: + return app.GetString( IDS_CONTROLLER_Y ); + case _360_JOY_BUTTON_LSTICK_UP: + case _360_JOY_BUTTON_LSTICK_DOWN: + case _360_JOY_BUTTON_LSTICK_LEFT: + case _360_JOY_BUTTON_LSTICK_RIGHT: + return app.GetString( IDS_CONTROLLER_LEFT_STICK ); + case _360_JOY_BUTTON_RSTICK_LEFT: + case _360_JOY_BUTTON_RSTICK_RIGHT: + case _360_JOY_BUTTON_RSTICK_UP: + case _360_JOY_BUTTON_RSTICK_DOWN: + return app.GetString( IDS_CONTROLLER_RIGHT_STICK ); + case _360_JOY_BUTTON_LT: + return app.GetString( IDS_CONTROLLER_LEFT_TRIGGER ); + case _360_JOY_BUTTON_RT: + return app.GetString( IDS_CONTROLLER_RIGHT_TRIGGER ); + case _360_JOY_BUTTON_RB: + return app.GetString( IDS_CONTROLLER_RIGHT_BUMPER ); + case _360_JOY_BUTTON_LB: + return app.GetString( IDS_CONTROLLER_LEFT_BUMPER ); + case _360_JOY_BUTTON_BACK: + return app.GetString( IDS_CONTROLLER_BACK ); + case _360_JOY_BUTTON_START: + return app.GetString( IDS_CONTROLLER_START ); + case _360_JOY_BUTTON_RTHUMB: + return app.GetString( IDS_CONTROLLER_RIGHT_THUMBSTICK ); + case _360_JOY_BUTTON_LTHUMB: + return app.GetString( IDS_CONTROLLER_LEFT_THUMBSTICK ); + case _360_JOY_BUTTON_DPAD_LEFT: + return app.GetString( IDS_CONTROLLER_DPAD_L ); + case _360_JOY_BUTTON_DPAD_RIGHT: + return app.GetString( IDS_CONTROLLER_DPAD_R ); + case _360_JOY_BUTTON_DPAD_UP: + return app.GetString( IDS_CONTROLLER_DPAD_U ); + case _360_JOY_BUTTON_DPAD_DOWN: + return app.GetString( IDS_CONTROLLER_DPAD_D ); + }; + return L""; +#else + wstring replacement = L""; + + // 4J Stu - Some of our actions can be mapped to multiple physical buttons, so replaces the switch that was here + if (input & _360_JOY_BUTTON_A) replacement = L"ButtonA"; + else if(input &_360_JOY_BUTTON_B) replacement = L"ButtonB"; + else if(input &_360_JOY_BUTTON_X) replacement = L"ButtonX"; + else if(input &_360_JOY_BUTTON_Y) replacement = L"ButtonY"; + else if( + (input &_360_JOY_BUTTON_LSTICK_UP) || + (input &_360_JOY_BUTTON_LSTICK_DOWN) || + (input &_360_JOY_BUTTON_LSTICK_LEFT) || + (input &_360_JOY_BUTTON_LSTICK_RIGHT) + ) + { + replacement = L"ButtonLeftStick"; + } + else if( + (input &_360_JOY_BUTTON_RSTICK_LEFT) || + (input &_360_JOY_BUTTON_RSTICK_RIGHT) || + (input &_360_JOY_BUTTON_RSTICK_UP) || + (input &_360_JOY_BUTTON_RSTICK_DOWN) + ) + { + replacement = L"ButtonRightStick"; + } + else if(input &_360_JOY_BUTTON_DPAD_LEFT) replacement = L"ButtonDpadL"; + else if(input &_360_JOY_BUTTON_DPAD_RIGHT) replacement = L"ButtonDpadR"; + else if(input &_360_JOY_BUTTON_DPAD_UP) replacement = L"ButtonDpadU"; + else if(input &_360_JOY_BUTTON_DPAD_DOWN) replacement = L"ButtonDpadD"; + else if(input &_360_JOY_BUTTON_LT) replacement = L"ButtonLeftTrigger"; + else if(input &_360_JOY_BUTTON_RT) replacement = L"ButtonRightTrigger"; + else if(input &_360_JOY_BUTTON_RB) replacement = L"ButtonRightBumper"; + else if(input &_360_JOY_BUTTON_LB) replacement = L"ButtonLeftBumper"; + else if(input &_360_JOY_BUTTON_BACK) replacement = L"ButtonBack"; + else if(input &_360_JOY_BUTTON_START) replacement = L"ButtonStart"; + else if(input &_360_JOY_BUTTON_RTHUMB) replacement = L"ButtonRS"; + else if(input &_360_JOY_BUTTON_LTHUMB) replacement = L"ButtonLS"; + + wchar_t string[128]; + +#ifdef __PS3__ + int size = 30; +#elif defined _WIN64 + int size = 45; + if(ui.getScreenHeight() < 1080) size = 30; +#else + int size = 45; +#endif + + swprintf(string,128,L"", replacement.c_str(), size, size); + + return string; +#endif +} + +wstring CMinecraftApp::GetVKReplacement(unsigned int uiVKey, bool override) +{ +#ifdef _XBOX + switch(uiVKey) + { + case VK_PAD_A: + return app.GetString( IDS_CONTROLLER_A ); + case VK_PAD_B: + return app.GetString( IDS_CONTROLLER_B ); + case VK_PAD_X: + return app.GetString( IDS_CONTROLLER_X ); + case VK_PAD_Y: + return app.GetString( IDS_CONTROLLER_Y ); + case VK_PAD_LSHOULDER: + return app.GetString( IDS_CONTROLLER_LEFT_BUMPER ); + case VK_PAD_RSHOULDER: + return app.GetString( IDS_CONTROLLER_RIGHT_BUMPER ); + case VK_PAD_LTRIGGER: + return app.GetString( IDS_CONTROLLER_LEFT_TRIGGER ); + case VK_PAD_RTRIGGER: + return app.GetString( IDS_CONTROLLER_RIGHT_TRIGGER ); + case VK_PAD_LTHUMB_UP : + case VK_PAD_LTHUMB_DOWN : + case VK_PAD_LTHUMB_RIGHT : + case VK_PAD_LTHUMB_LEFT : + case VK_PAD_LTHUMB_UPLEFT : + case VK_PAD_LTHUMB_UPRIGHT : + case VK_PAD_LTHUMB_DOWNRIGHT: + case VK_PAD_LTHUMB_DOWNLEFT : + return app.GetString( IDS_CONTROLLER_LEFT_STICK ); + case VK_PAD_RTHUMB_UP : + case VK_PAD_RTHUMB_DOWN : + case VK_PAD_RTHUMB_RIGHT : + case VK_PAD_RTHUMB_LEFT : + case VK_PAD_RTHUMB_UPLEFT : + case VK_PAD_RTHUMB_UPRIGHT : + case VK_PAD_RTHUMB_DOWNRIGHT: + case VK_PAD_RTHUMB_DOWNLEFT : + return app.GetString( IDS_CONTROLLER_RIGHT_STICK ); + default: + break; + } + return nullptr; +#else + wstring replacement = L""; + switch(uiVKey) + { + case VK_PAD_A: +#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) + if( InputManager.IsCircleCrossSwapped() ) replacement = L"ButtonB"; + else replacement = L"ButtonA"; +#else + replacement = L"ButtonA"; +#endif + break; + case VK_PAD_B: +#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) + if( InputManager.IsCircleCrossSwapped() ) replacement = L"ButtonA"; + else replacement = L"ButtonB"; +#else + replacement = L"ButtonB"; +#endif + break; + case VK_PAD_X: + replacement = L"ButtonX"; + break; + case VK_PAD_Y: + replacement = L"ButtonY"; + break; + case VK_PAD_LSHOULDER: + replacement = L"ButtonLeftBumper"; + break; + case VK_PAD_RSHOULDER: + replacement = L"ButtonRightBumper"; + break; + case VK_PAD_LTRIGGER: + replacement = L"ButtonLeftTrigger"; + break; + case VK_PAD_RTRIGGER: + replacement = L"ButtonRightTrigger"; + break; + case VK_PAD_LTHUMB_UP : + case VK_PAD_LTHUMB_DOWN : + case VK_PAD_LTHUMB_RIGHT : + case VK_PAD_LTHUMB_LEFT : + case VK_PAD_LTHUMB_UPLEFT : + case VK_PAD_LTHUMB_UPRIGHT : + case VK_PAD_LTHUMB_DOWNRIGHT: + case VK_PAD_LTHUMB_DOWNLEFT : + replacement = L"ButtonLeftStick"; + break; + case VK_PAD_RTHUMB_UP : + case VK_PAD_RTHUMB_DOWN : + case VK_PAD_RTHUMB_RIGHT : + case VK_PAD_RTHUMB_LEFT : + case VK_PAD_RTHUMB_UPLEFT : + case VK_PAD_RTHUMB_UPRIGHT : + case VK_PAD_RTHUMB_DOWNRIGHT: + case VK_PAD_RTHUMB_DOWNLEFT : + replacement = L"ButtonRightStick"; + break; +#if defined _XBOX_ONE || defined __PSVITA__ + case VK_PAD_START: + replacement = L"ButtonStart"; + break; + case VK_PAD_BACK: + replacement = L"ButtonBack"; + break; +#endif + default: + break; + } + wchar_t string[128]; + +#ifdef __PS3__ + int size = 30; +#elif defined _WIN64 + int size = 45; + if(ui.getScreenHeight() < 1080 || override == true) size = 30; +#else + int size = 45; +#endif + + swprintf(string,128,L"", replacement.c_str(), size, size); + + return string; +#endif +} + +wstring CMinecraftApp::GetIconReplacement(unsigned int uiIcon) +{ +#ifdef _XBOX + switch(uiIcon) + { + case XZP_ICON_SHANK_01: + return app.GetString( IDS_ICON_SHANK_01 ); + case XZP_ICON_SHANK_03: + return app.GetString( IDS_ICON_SHANK_03 ); + default: + break; + } + return nullptr; +#else + wchar_t string[128]; + +#ifdef __PS3__ + int size = 22; +#elif defined _WIN64 + int size = 33; + if(ui.getScreenHeight() < 1080) size = 22; +#else + int size = 33; +#endif + + swprintf(string,128,L"", size, size); + wstring result = L""; + switch(uiIcon) + { + case XZP_ICON_SHANK_01: + result = string; + break; + case XZP_ICON_SHANK_03: + result.append(string).append(string).append(string); + break; + default: + break; + } + return result; +#endif +} + +#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) +unordered_map CMinecraftApp::MojangData; +unordered_map CMinecraftApp::DLCTextures_PackID; +unordered_map CMinecraftApp::DLCInfo; +unordered_map CMinecraftApp::DLCInfo_SkinName; +#elif defined(_DURANGO) +unordered_map CMinecraftApp::MojangData; +unordered_map CMinecraftApp::DLCTextures_PackID; // for mash-up packs & texture packs +//unordered_map CMinecraftApp::DLCInfo_Trial; // full offerid, dlc_info +unordered_map CMinecraftApp::DLCInfo_Full; // full offerid, dlc_info +unordered_map CMinecraftApp::DLCInfo_SkinName; // skin name, full offer id +#else +unordered_map CMinecraftApp::MojangData; +unordered_map CMinecraftApp::DLCTextures_PackID; +unordered_map CMinecraftApp::DLCInfo_Trial; +unordered_map CMinecraftApp::DLCInfo_Full; +unordered_map CMinecraftApp::DLCInfo_SkinName; +#endif + + + +HRESULT CMinecraftApp::RegisterMojangData(WCHAR *pXuidName, PlayerUID xuid, WCHAR *pSkin, WCHAR *pCape) +{ + HRESULT hr=S_OK; + eXUID eTempXuid=eXUID_Undefined; + MOJANG_DATA *pMojangData=nullptr; + + // ignore the names if we don't recognize them + if (pXuidName != nullptr) + { + if( wcscmp( pXuidName, L"XUID_NOTCH" ) == 0 ) + { + eTempXuid = eXUID_Notch; // might be needed for the apple at some point + } + else if( wcscmp( pXuidName, L"XUID_DEADMAU5" ) == 0 ) + { + eTempXuid = eXUID_Deadmau5; // Needed for the deadmau5 ears + } + else + { + eTempXuid=eXUID_NoName; + } + } + + if(eTempXuid!=eXUID_Undefined) + { + pMojangData = new MOJANG_DATA; + ZeroMemory(pMojangData,sizeof(MOJANG_DATA)); + pMojangData->eXuid=eTempXuid; + + wcsncpy( pMojangData->wchSkin, pSkin, MAX_CAPENAME_SIZE); + wcsncpy( pMojangData->wchCape, pCape, MAX_CAPENAME_SIZE); + MojangData[xuid]=pMojangData; + } + + return hr; +} + +MOJANG_DATA *CMinecraftApp::GetMojangDataForXuid(PlayerUID xuid) +{ + return MojangData[xuid]; +} + +HRESULT CMinecraftApp::RegisterConfigValues(WCHAR *pType, int iValue) +{ + HRESULT hr=S_OK; + + // #ifdef _XBOX + // if(pType!=nullptr) + // { + // if(wcscmp(pType,L"XboxOneTransfer")==0) + // { + // if(iValue>0) + // { + // app.m_bTransferSavesToXboxOne=true; + // } + // else + // { + // app.m_bTransferSavesToXboxOne=false; + // } + // } + // else if(wcscmp(pType,L"TransferSlotCount")==0) + // { + // app.m_uiTransferSlotC=iValue; + // } + // + // } + // #endif + + + return hr; +} + +#if (defined _XBOX || defined _WINDOWS64) +HRESULT CMinecraftApp::RegisterDLCData(WCHAR *pType, WCHAR *pBannerName, int iGender, uint64_t ullOfferID_Full, uint64_t ullOfferID_Trial, WCHAR *pFirstSkin, unsigned int uiSortIndex, int iConfig, WCHAR *pDataFile) +{ + HRESULT hr=S_OK; + DLC_INFO *pDLCData=new DLC_INFO; + ZeroMemory(pDLCData,sizeof(DLC_INFO)); + pDLCData->ullOfferID_Full=ullOfferID_Full; + pDLCData->ullOfferID_Trial=ullOfferID_Trial; + pDLCData->eDLCType=e_DLC_NotDefined; + pDLCData->iGender=iGender; + pDLCData->uiSortIndex=uiSortIndex; + pDLCData->iConfig=iConfig; + +#ifndef __ORBIS__ + // ignore the names if we don't recognize them + if(pBannerName!=L"") + { + wcsncpy_s( pDLCData->wchBanner, pBannerName, MAX_BANNERNAME_SIZE); + } + + if(pDataFile[0]!=0) + { + wcsncpy_s( pDLCData->wchDataFile, pDataFile, MAX_BANNERNAME_SIZE); + } +#endif + + if(pType!=nullptr) + { + if(wcscmp(pType,L"Skin")==0) + { + pDLCData->eDLCType=e_DLC_SkinPack; + } + else if(wcscmp(pType,L"Gamerpic")==0) + { + pDLCData->eDLCType=e_DLC_Gamerpics; + } + else if(wcscmp(pType,L"Theme")==0) + { + pDLCData->eDLCType=e_DLC_Themes; + } + else if(wcscmp(pType,L"Avatar")==0) + { + pDLCData->eDLCType=e_DLC_AvatarItems; + } + else if(wcscmp(pType,L"MashUpPack")==0) + { + pDLCData->eDLCType=e_DLC_MashupPacks; + DLCTextures_PackID[pDLCData->iConfig]=ullOfferID_Full; + } + else if(wcscmp(pType,L"TexturePack")==0) + { + pDLCData->eDLCType=e_DLC_TexturePacks; + DLCTextures_PackID[pDLCData->iConfig]=ullOfferID_Full; + } + + + } + + if(ullOfferID_Trial!=0ll) DLCInfo_Trial[ullOfferID_Trial]=pDLCData; + if(ullOfferID_Full!=0ll) DLCInfo_Full[ullOfferID_Full]=pDLCData; + if(pFirstSkin[0]!=0) DLCInfo_SkinName[pFirstSkin]=ullOfferID_Full; + + return hr; +} +#elif defined _XBOX_ONE + +unordered_map *CMinecraftApp::GetDLCInfo() +{ + return &DLCInfo_Full; +} + +HRESULT CMinecraftApp::RegisterDLCData(eDLCContentType eType, WCHAR *pwchBannerName,WCHAR *pwchProductId, WCHAR *pwchProductName, WCHAR *pwchFirstSkin, int iConfig, unsigned int uiSortIndex) +{ + HRESULT hr=S_OK; + // 4J-PB - need to convert the product id to uppercase because the catalog calls come back with upper case + WCHAR wchUppercaseProductID[64]; + if(pwchProductId[0]!=0) + { + for(int i=0;i<64;i++) + { + wchUppercaseProductID[i]=towupper((wchar_t)pwchProductId[i]); + } + } + + // check if we already have this info from the local DLC file + wstring wsTemp=wchUppercaseProductID; + + auto it = DLCInfo_Full.find(wsTemp); + if( it == DLCInfo_Full.end() ) + { + // Not found + + DLC_INFO *pDLCData=new DLC_INFO; + ZeroMemory(pDLCData,sizeof(DLC_INFO)); + + pDLCData->eDLCType=e_DLC_NotDefined; + pDLCData->uiSortIndex=uiSortIndex; + pDLCData->iConfig=iConfig; + + if(pwchProductId[0]!=0) + { + pDLCData->wsProductId=wchUppercaseProductID; + } + + // ignore the names if we don't recognize them + if(pwchBannerName!=L"") + { + wcsncpy_s( pDLCData->wchBanner, pwchBannerName, MAX_BANNERNAME_SIZE); + } + + if(pwchProductName[0]!=0) + { + pDLCData->wsDisplayName=pwchProductName; + } + + pDLCData->eDLCType=eType; + + switch(eType) + { + case e_DLC_MashupPacks: + case e_DLC_TexturePacks: + DLCTextures_PackID[iConfig]=pDLCData->wsProductId; + break; + } + + if(pwchFirstSkin[0]!=0) DLCInfo_SkinName[pwchFirstSkin]=pDLCData->wsProductId; + +#ifdef _XBOX_ONE + // ignore the names, and use the product id instead + DLCInfo_Full[pDLCData->wsProductId]=pDLCData; +#else + DLCInfo_Full[pDLCData->wsDisplayName]=pDLCData; +#endif + } + app.DebugPrintf("DLCInfo - type - %d, productID - %ls, name - %ls , banner - %ls, iconfig - %d, sort index - %d\n",eType,pwchProductId, pwchProductName,pwchBannerName, iConfig, uiSortIndex); + return hr; +} +#else + +HRESULT CMinecraftApp::RegisterDLCData(char *pchDLCName, unsigned int uiSortIndex,char *pchImageURL) +{ + // on PS3 we get all the required info from the name + char chDLCType[3]; + HRESULT hr=S_OK; + DLC_INFO *pDLCData=new DLC_INFO; + ZeroMemory(pDLCData,sizeof(DLC_INFO)); + + chDLCType[0]=pchDLCName[0]; + chDLCType[1]=pchDLCName[1]; + chDLCType[2]=0; + + pDLCData->iConfig = app.GetiConfigFromName(pchDLCName); + pDLCData->uiSortIndex=uiSortIndex; + pDLCData->eDLCType = app.GetDLCTypeFromName(pchDLCName); + strcpy(pDLCData->chImageURL,pchImageURL); + //bool bIsTrialDLC = app.GetTrialFromName(pchDLCName); + + switch(pDLCData->eDLCType) + { + case e_DLC_TexturePacks: + { + char *pchName=(char *)malloc(strlen(pchDLCName)+1); + strcpy(pchName,pchDLCName); + DLCTextures_PackID[pDLCData->iConfig]=pchName; + } + break; + case e_DLC_MashupPacks: + { + char *pchName=(char *)malloc(strlen(pchDLCName)+1); + strcpy(pchName,pchDLCName); + DLCTextures_PackID[pDLCData->iConfig]=pchName; + } + break; + default: + break; + } + + app.DebugPrintf(5,"Adding DLC - %s\n",pchDLCName); + DLCInfo[pchDLCName]=pDLCData; + + // if(ullOfferID_Trial!=0ll) DLCInfo_Trial[ullOfferID_Trial]=pDLCData; + // if(ullOfferID_Full!=0ll) DLCInfo_Full[ullOfferID_Full]=pDLCData; + // if(pFirstSkin[0]!=0) DLCInfo_SkinName[pFirstSkin]=ullOfferID_Full; + + // DLCInfo[ullOfferID_Trial]=pDLCData; + + return hr; +} +#endif + + + +#if defined( __PS3__) || defined(__ORBIS__) || defined(__PSVITA__) +bool CMinecraftApp::GetDLCFullOfferIDForSkinID(const wstring &FirstSkin,ULONGLONG *pullVal) +{ + auto it = DLCInfo_SkinName.find(FirstSkin); + if( it == DLCInfo_SkinName.end() ) + { + return false; + } + else + { + *pullVal=(ULONGLONG)it->second; + return true; + } +} +bool CMinecraftApp::GetDLCNameForPackID(const int iPackID,char **ppchKeyID) +{ + auto it = DLCTextures_PackID.find(iPackID); + if( it == DLCTextures_PackID.end() ) + { + *ppchKeyID=nullptr; + return false; + } + else + { + *ppchKeyID=(char *)it->second; + return true; + } +} +DLC_INFO *CMinecraftApp::GetDLCInfo(char *pchDLCName) +{ + string tempString=pchDLCName; + + if(DLCInfo.size()>0) + { + auto it = DLCInfo.find(tempString); + + if( it == DLCInfo.end() ) + { + // nothing for this + return nullptr; + } + else + { + return it->second; + } + } + else return nullptr; +} + +DLC_INFO *CMinecraftApp::GetDLCInfoFromTPackID(int iTPID) +{ + unordered_map::iterator it= DLCInfo.begin(); + + for(size_t i=0;isecond)->iConfig==iTPID) + { + return it->second; + } + ++it; + } + return nullptr; +} + +DLC_INFO *CMinecraftApp::GetDLCInfo(int iIndex) +{ + unordered_map::iterator it= DLCInfo.begin(); + + for(int i=0;isecond; +} + +char *CMinecraftApp::GetDLCInfoTextures(int iIndex) +{ + unordered_map::iterator it= DLCTextures_PackID.begin(); + + for(int i=0;isecond; +} + +#elif defined _XBOX_ONE +bool CMinecraftApp::GetDLCFullOfferIDForSkinID(const wstring &FirstSkin,wstring &ProductId) +{ + auto it = DLCInfo_SkinName.find(FirstSkin); + if( it == DLCInfo_SkinName.end() ) + { + return false; + } + else + { + ProductId=it->second; + return true; + } +} +bool CMinecraftApp::GetDLCFullOfferIDForPackID(const int iPackID,wstring &ProductId) +{ + auto it = DLCTextures_PackID.find(iPackID); + if( it == DLCTextures_PackID.end() ) + { + return false; + } + else + { + ProductId=it->second; + return true; + } +} +// DLC_INFO *CMinecraftApp::GetDLCInfoForTrialOfferID(wstring &ProductId) +// { +// return nullptr; +// } + +DLC_INFO *CMinecraftApp::GetDLCInfoTrialOffer(int iIndex) +{ + return nullptr; +} +DLC_INFO *CMinecraftApp::GetDLCInfoFullOffer(int iIndex) +{ + unordered_map::iterator it= DLCInfo_Full.begin(); + + for(int i=0;isecond; +} +wstring CMinecraftApp::GetDLCInfoTexturesFullOffer(int iIndex) +{ + unordered_map::iterator it= DLCTextures_PackID.begin(); + + for(int i=0;isecond; +} +#else +bool CMinecraftApp::GetDLCFullOfferIDForSkinID(const wstring &FirstSkin,ULONGLONG *pullVal) +{ + auto it = DLCInfo_SkinName.find(FirstSkin); + if( it == DLCInfo_SkinName.end() ) + { + return false; + } + else + { + *pullVal=(ULONGLONG)it->second; + return true; + } +} +bool CMinecraftApp::GetDLCFullOfferIDForPackID(const int iPackID,ULONGLONG *pullVal) +{ + auto it = DLCTextures_PackID.find(iPackID); + if( it == DLCTextures_PackID.end() ) + { + *pullVal=0ULL; + return false; + } + else + { + *pullVal=it->second; + return true; + } +} +DLC_INFO *CMinecraftApp::GetDLCInfoForTrialOfferID(ULONGLONG ullOfferID_Trial) +{ + //DLC_INFO *pDLCInfo=nullptr; + if(DLCInfo_Trial.size()>0) + { + auto it = DLCInfo_Trial.find(ullOfferID_Trial); + + if( it == DLCInfo_Trial.end() ) + { + // nothing for this + return nullptr; + } + else + { + return it->second; + } + } + else return nullptr; +} + +DLC_INFO *CMinecraftApp::GetDLCInfoTrialOffer(int iIndex) +{ + unordered_map::iterator it= DLCInfo_Trial.begin(); + + for(int i=0;isecond; +} +DLC_INFO *CMinecraftApp::GetDLCInfoFullOffer(int iIndex) +{ + unordered_map::iterator it= DLCInfo_Full.begin(); + + for(int i=0;isecond; +} +ULONGLONG CMinecraftApp::GetDLCInfoTexturesFullOffer(int iIndex) +{ + unordered_map::iterator it= DLCTextures_PackID.begin(); + + for(int i=0;isecond; +} +#endif + +#ifdef _XBOX_ONE + +DLC_INFO *CMinecraftApp::GetDLCInfoForFullOfferID(WCHAR *pwchProductID) +{ + wstring wsTemp = pwchProductID; + if(DLCInfo_Full.size()>0) + { + auto it = DLCInfo_Full.find(wsTemp); + + if( it == DLCInfo_Full.end() ) + { + // nothing for this + return nullptr; + } + else + { + return it->second; + } + } + else return nullptr; +} +DLC_INFO *CMinecraftApp::GetDLCInfoForProductName(WCHAR *pwchProductName) +{ + unordered_map::iterator it= DLCInfo_Full.begin(); + wstring wsProductName=pwchProductName; + + for(size_t i=0;isecond; + if(wsProductName==pDLCInfo->wsDisplayName) + { + return pDLCInfo; + } + ++it; + } + + return nullptr; +} + +#elif defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) +#else + +DLC_INFO *CMinecraftApp::GetDLCInfoForFullOfferID(ULONGLONG ullOfferID_Full) +{ + + if(DLCInfo_Full.size()>0) + { + auto it = DLCInfo_Full.find(ullOfferID_Full); + + if( it == DLCInfo_Full.end() ) + { + // nothing for this + return nullptr; + } + else + { + return it->second; + } + } + else return nullptr; +} +#endif + +void CMinecraftApp::EnterSaveNotificationSection() +{ + EnterCriticalSection(&m_saveNotificationCriticalSection); + if( m_saveNotificationDepth++ == 0 ) + { + if(g_NetworkManager.IsInSession()) // this can be triggered from the front end if we're downloading a save + { + MinecraftServer::getInstance()->broadcastStartSavingPacket(); + + if( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 ) + { + app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_PauseServer,(void *)TRUE); + } + } + } + LeaveCriticalSection(&m_saveNotificationCriticalSection); +} + +void CMinecraftApp::LeaveSaveNotificationSection() +{ + EnterCriticalSection(&m_saveNotificationCriticalSection); + if( --m_saveNotificationDepth == 0 ) + { + if(g_NetworkManager.IsInSession()) // this can be triggered from the front end if we're downloading a save + { + MinecraftServer::getInstance()->broadcastStopSavingPacket(); + + if( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 ) + { + app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),eXuiServerAction_PauseServer,(void *)FALSE); + } + } + } + LeaveCriticalSection(&m_saveNotificationCriticalSection); +} + + +int CMinecraftApp::RemoteSaveThreadProc( void* lpParameter ) +{ + // The game should be stopped while we are doing this, but the connections ticks may try to create some AABB's or Vec3's + AABB::UseDefaultThreadStorage(); + Vec3::UseDefaultThreadStorage(); + Compression::UseDefaultThreadStorage(); + + // 4J-PB - Xbox 360 - 163153 - [CRASH] TU17: Code: Multiplayer: During the Autosave in an online Multiplayer session, the game occasionally crashes for one or more Clients + // callstack - > if(tls->tileId != this->id) updateDefaultShape(); + // callstack - > default.exe!WaterlilyTile::getAABB(Level * level, int x, int y, int z) line 38 + 8 bytes C++ + // ... + // default.exe!CMinecraftApp::RemoteSaveThreadProc(void * lpParameter) line 6694 C++ + // host autosave, and the clients can crash on receiving handleMoveEntity when it's a tile within this thread, so need to do the tls for tiles + Tile::CreateNewThreadStorage(); + + Minecraft *pMinecraft = Minecraft::GetInstance(); + + pMinecraft->progressRenderer->progressStartNoAbort( IDS_PROGRESS_HOST_SAVING ); + pMinecraft->progressRenderer->progressStage( -1 ); + pMinecraft->progressRenderer->progressStagePercentage(0); + + while( !app.GetGameStarted() && app.GetXuiAction( ProfileManager.GetPrimaryPad() ) == eAppAction_WaitRemoteServerSaveComplete ) + { + // Tick all the games connections + pMinecraft->tickAllConnections(); + Sleep( 100 ); + } + + if( app.GetXuiAction( ProfileManager.GetPrimaryPad() ) != eAppAction_WaitRemoteServerSaveComplete ) + { + // Something cancelled us? + return ERROR_CANCELLED; + } + app.SetAction(ProfileManager.GetPrimaryPad(),eAppAction_Idle); + + ui.UpdatePlayerBasePositions(); + + Tile::ReleaseThreadStorage(); + + return S_OK; +} + +void CMinecraftApp::ExitGameFromRemoteSave( LPVOID lpParameter ) +{ + int primaryPad = ProfileManager.GetPrimaryPad(); + + UINT uiIDA[3]; + uiIDA[0]=IDS_CONFIRM_CANCEL; + uiIDA[1]=IDS_CONFIRM_OK; + + ui.RequestAlertMessage(IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 2, primaryPad,&CMinecraftApp::ExitGameFromRemoteSaveDialogReturned,nullptr); +} + +int CMinecraftApp::ExitGameFromRemoteSaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + //CScene_Pause* pClass = (CScene_Pause*)pParam; + + // results switched for this dialog + if(result==C4JStorage::EMessage_ResultDecline) + { + app.SetAction(iPad,eAppAction_ExitWorld); + } + else + { +#ifndef _XBOX + // Inform fullscreen progress scene that it's not being cancelled after all + UIScene_FullscreenProgress *pScene = static_cast(ui.FindScene(eUIScene_FullscreenProgress)); +#ifdef __PS3__ + if(pScene!=nullptr) +#else + if (pScene != nullptr) +#endif + { + pScene->SetWasCancelled(false); + } +#else + // Don't have to worry about this on Xbox +#endif + } + return 0; +} + +void CMinecraftApp::SetSpecialTutorialCompletionFlag(int iPad, int index) +{ + if(index >= 0 && index < 32 && GameSettingsA[iPad] != nullptr) + { + GameSettingsA[iPad]->uiSpecialTutorialBitmask |= (1<clear(); + + if(BannedListA[iPad].pBannedList) + { + delete [] BannedListA[iPad].pBannedList; + BannedListA[iPad].pBannedList=nullptr; + } + } +} + +#ifdef _XBOX_ONE +void CMinecraftApp::AddLevelToBannedLevelList(int iPad, PBANNEDLISTDATA pBannedListData, bool bWriteToTMS) +{ + PlayerUID xuid= pBannedListData->wchPlayerUID; + + AddLevelToBannedLevelList(iPad,xuid,pBannedListData->pszLevelName,bWriteToTMS); +} +#endif + +void CMinecraftApp::AddLevelToBannedLevelList(int iPad, PlayerUID xuid, char *pszLevelName, bool bWriteToTMS) +{ + // we will have retrieved the banned level list from TMS, so add this one to it and write it back to TMS + + BANNEDLISTDATA *pBannedListData = new BANNEDLISTDATA; + memset(pBannedListData,0,sizeof(BANNEDLISTDATA)); + +#ifdef _DURANGO + memcpy(&pBannedListData->wchPlayerUID, xuid.toString().c_str(), sizeof(WCHAR)*64); +#else + memcpy(&pBannedListData->xuid, &xuid, sizeof(PlayerUID)); +#endif + strcpy(pBannedListData->pszLevelName,pszLevelName); + m_vBannedListA[iPad]->push_back(pBannedListData); + + if (bWriteToTMS) + { + DWORD dwDataBytes = static_cast(sizeof(BANNEDLISTDATA)* m_vBannedListA[iPad]->size()); + PBANNEDLISTDATA pBannedList = reinterpret_cast(new CHAR [dwDataBytes]); + int iCount=0; + for (PBANNEDLISTDATA pData : *m_vBannedListA[iPad] ) + { + memcpy(&pBannedList[iCount++],pData,sizeof(BANNEDLISTDATA)); + } + + // 4J-PB - write to TMS++ now + + //bool bRes=StorageManager.WriteTMSFile(iPad,C4JStorage::eGlobalStorage_TitleUser,L"BannedList",(PBYTE)pBannedList, dwDataBytes); +#ifdef _XBOX + StorageManager.TMSPP_WriteFile(iPad,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,C4JStorage::TMS_UGCTYPE_NONE,"BannedList",(PCHAR) pBannedList, dwDataBytes,nullptr,nullptr, 0); +#elif defined _XBOX_ONE + StorageManager.TMSPP_WriteFile(iPad,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,L"BannedList",(PBYTE) pBannedList, dwDataBytes,nullptr,nullptr, 0); +#endif + } + // update telemetry too +} + +bool CMinecraftApp::IsInBannedLevelList(int iPad, PlayerUID xuid, char *pszLevelName) +{ + for( PBANNEDLISTDATA pData : *m_vBannedListA[iPad] ) + { +#ifdef _XBOX_ONE + PlayerUID bannedPlayerUID = pData->wchPlayerUID; + if(IsEqualXUID (bannedPlayerUID,xuid) && (strcmp(pData->pszLevelName,pszLevelName)==0)) +#else + if(IsEqualXUID (pData->xuid,xuid) && (strcmp(pData->pszLevelName,pszLevelName)==0)) +#endif + { + return true; + } + } + + return false; +} + +void CMinecraftApp::RemoveLevelFromBannedLevelList(int iPad, PlayerUID xuid, char *pszLevelName) +{ + //bool bFound=false; + //bool bRes; + + // we will have retrieved the banned level list from TMS, so remove this one from it and write it back to TMS + for (auto it = m_vBannedListA[iPad]->begin(); it != m_vBannedListA[iPad]->end(); ) + { + PBANNEDLISTDATA pBannedListData = *it; + + if(pBannedListData!=nullptr) + { +#ifdef _XBOX_ONE + PlayerUID bannedPlayerUID = pBannedListData->wchPlayerUID; + if(IsEqualXUID (bannedPlayerUID,xuid) && (strcmp(pBannedListData->pszLevelName,pszLevelName)==0)) +#else + if(IsEqualXUID (pBannedListData->xuid,xuid) && (strcmp(pBannedListData->pszLevelName,pszLevelName)==0)) +#endif + { + TelemetryManager->RecordUnBanLevel(iPad); + + // match found, so remove this entry + it = m_vBannedListA[iPad]->erase(it); + } + else + { + ++it; + } + } + else + { + ++it; + } + } + + DWORD dwDataBytes=static_cast(sizeof(BANNEDLISTDATA) * m_vBannedListA[iPad]->size()); + if(dwDataBytes==0) + { + // wipe the file +#ifdef _XBOX + StorageManager.DeleteTMSFile(iPad,C4JStorage::eGlobalStorage_TitleUser,L"BannedList"); +#elif defined _XBOX_ONE + StorageManager.TMSPP_DeleteFile(iPad,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,L"BannedList",nullptr,nullptr, 0); +#endif + } + else + { + PBANNEDLISTDATA pBannedList = (BANNEDLISTDATA *)(new BYTE [dwDataBytes]); + + size_t iSize=m_vBannedListA[iPad]->size(); + for(size_t i=0;iat(i); + + memcpy(&pBannedList[i],pBannedListData,sizeof(BANNEDLISTDATA)); + } +#ifdef _XBOX + StorageManager.WriteTMSFile(iPad,C4JStorage::eGlobalStorage_TitleUser,L"BannedList",(PBYTE)pBannedList, dwDataBytes); +#elif defined _XBOX_ONE + StorageManager.TMSPP_WriteFile(iPad,C4JStorage::eGlobalStorage_TitleUser,C4JStorage::TMS_FILETYPE_BINARY,L"BannedList",(PBYTE) pBannedList, dwDataBytes,nullptr,nullptr, 0); +#endif + delete [] pBannedList; + } + + // update telemetry too +} + +// function to add credits for the DLC packs +void CMinecraftApp::AddCreditText(LPCWSTR lpStr) +{ + DebugPrintf("ADDING CREDIT - %ls\n",lpStr); + // add a string from the DLC to a credits vector + SCreditTextItemDef *pCreditStruct = new SCreditTextItemDef; + pCreditStruct->m_eType=eSmallText; + pCreditStruct->m_iStringID[0]=NO_TRANSLATED_STRING; + pCreditStruct->m_iStringID[1]=NO_TRANSLATED_STRING; + pCreditStruct->m_Text=new WCHAR [wcslen(lpStr)+1]; + wcscpy((WCHAR *)pCreditStruct->m_Text,lpStr); + + vDLCCredits.push_back(pCreditStruct); +} + +bool CMinecraftApp::AlreadySeenCreditText(const wstring &wstemp) +{ + + for(unsigned int i=0;i(vDLCCredits.size()); +} + +SCreditTextItemDef * CMinecraftApp::GetDLCCredits(int iIndex) +{ + return vDLCCredits.at(iIndex); +} + +// Game Host options + +void CMinecraftApp::SetGameHostOption(eGameHostOption eVal,unsigned int uiVal) +{ + SetGameHostOption(m_uiGameHostSettings,eVal,uiVal); +} + + +void CMinecraftApp::SetGameHostOption(unsigned int &uiHostSettings, eGameHostOption eVal, unsigned int uiVal) +{ + switch(eVal) + { + case eGameHostOption_FriendsOfFriends: + if(uiVal!=0) + { + uiHostSettings|=GAME_HOST_OPTION_BITMASK_FRIENDSOFFRIENDS; + } + else + { + // off + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_FRIENDSOFFRIENDS; + } + break; + case eGameHostOption_Difficulty: + // clear the difficulty first + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_DIFFICULTY; + uiHostSettings|=(GAME_HOST_OPTION_BITMASK_DIFFICULTY&uiVal); + break; + case eGameHostOption_Gamertags: + if(uiVal!=0) + { + uiHostSettings|=GAME_HOST_OPTION_BITMASK_GAMERTAGS; + } + else + { + // off + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_GAMERTAGS; + } + + break; + case eGameHostOption_GameType: + // clear the game type first + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_GAMETYPE; + uiHostSettings|=(GAME_HOST_OPTION_BITMASK_GAMETYPE&(uiVal<<4)); + break; + case eGameHostOption_LevelType: + if(uiVal!=0) + { + uiHostSettings|=GAME_HOST_OPTION_BITMASK_LEVELTYPE; + } + else + { + // off + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_LEVELTYPE; + } + + break; + case eGameHostOption_Structures: + if(uiVal!=0) + { + uiHostSettings|=GAME_HOST_OPTION_BITMASK_STRUCTURES; + } + else + { + // off + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_STRUCTURES; + } + + break; + case eGameHostOption_BonusChest: + if(uiVal!=0) + { + uiHostSettings|=GAME_HOST_OPTION_BITMASK_BONUSCHEST; + } + else + { + // off + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_BONUSCHEST; + } + + break; + case eGameHostOption_HasBeenInCreative: + if(uiVal!=0) + { + uiHostSettings|=GAME_HOST_OPTION_BITMASK_BEENINCREATIVE; + } + else + { + // off + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_BEENINCREATIVE; + } + + break; + case eGameHostOption_PvP: + if(uiVal!=0) + { + uiHostSettings|=GAME_HOST_OPTION_BITMASK_PVP; + } + else + { + // off + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_PVP; + } + + break; + case eGameHostOption_TrustPlayers: + if(uiVal!=0) + { + uiHostSettings|=GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS; + } + else + { + // off + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS; + } + + break; + case eGameHostOption_TNT: + if(uiVal!=0) + { + uiHostSettings|=GAME_HOST_OPTION_BITMASK_TNT; + } + else + { + // off + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_TNT; + } + + break; + case eGameHostOption_FireSpreads: + if(uiVal!=0) + { + uiHostSettings|=GAME_HOST_OPTION_BITMASK_FIRESPREADS; + } + else + { + // off + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_FIRESPREADS; + } + break; + case eGameHostOption_CheatsEnabled: + if(uiVal!=0) + { + uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTFLY; + uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTHUNGER; + uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE; + } + else + { + // off + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTFLY; + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTHUNGER; + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE; + } + break; + case eGameHostOption_HostCanFly: + if(uiVal!=0) + { + uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTFLY; + } + else + { + // off + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTFLY; + } + break; + case eGameHostOption_HostCanChangeHunger: + if(uiVal!=0) + { + uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTHUNGER; + } + else + { + // off + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTHUNGER; + } + break; + case eGameHostOption_HostCanBeInvisible: + if(uiVal!=0) + { + uiHostSettings|=GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE; + } + else + { + // off + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE; + } + break; + + case eGameHostOption_BedrockFog: + if(uiVal!=0) + { + uiHostSettings|=GAME_HOST_OPTION_BITMASK_BEDROCKFOG; + } + else + { + // off + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_BEDROCKFOG; + } + break; + case eGameHostOption_DisableSaving: + if(uiVal!=0) + { + uiHostSettings|=GAME_HOST_OPTION_BITMASK_DISABLESAVE; + } + else + { + // off + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_DISABLESAVE; + } + break; + case eGameHostOption_WasntSaveOwner: + if(uiVal!=0) + { + uiHostSettings|=GAME_HOST_OPTION_BITMASK_NOTOWNER; + } + else + { + // off + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_NOTOWNER; + } + break; + case eGameHostOption_MobGriefing: + if(uiVal!=1) + { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_MOBGRIEFING; + } + else + { + // off + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_MOBGRIEFING; + } + break; + case eGameHostOption_KeepInventory: + if(uiVal!=0) + { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_KEEPINVENTORY; + } + else + { + // off + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_KEEPINVENTORY; + } + break; + case eGameHostOption_DoMobSpawning: + if(uiVal!=1) + { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_DOMOBSPAWNING; + } + else + { + // off + uiHostSettings &=~ GAME_HOST_OPTION_BITMASK_DOMOBSPAWNING; + } + break; + case eGameHostOption_DoMobLoot: + if(uiVal!=1) + { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_DOMOBLOOT; + } + else + { + // off + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DOMOBLOOT; + } + break; + case eGameHostOption_DoTileDrops: + if(uiVal!=1) + { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_DOTILEDROPS; + } + else + { + // off + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DOTILEDROPS; + } + break; + case eGameHostOption_NaturalRegeneration: + if(uiVal!=1) + { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_NATURALREGEN; + } + else + { + // off + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_NATURALREGEN; + } + break; + case eGameHostOption_DoDaylightCycle: + if(uiVal!=1) + { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE; + } + else + { + // off + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE; + } + break; + case eGameHostOption_WorldSize: + // clear the difficulty first + uiHostSettings&=~GAME_HOST_OPTION_BITMASK_WORLDSIZE; + uiHostSettings|=(GAME_HOST_OPTION_BITMASK_WORLDSIZE & (uiVal<>4; + break; + case eGameHostOption_All: + return (uiHostSettings&GAME_HOST_OPTION_BITMASK_ALL); + break; + case eGameHostOption_Tutorial: + // special case - tutorial is offline, but we want the gamertag option, and set Easy mode, structures on, fire on, tnt on, pvp on, trust players on + return ((uiHostSettings&GAME_HOST_OPTION_BITMASK_GAMERTAGS)| + GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS| + GAME_HOST_OPTION_BITMASK_FIRESPREADS| + GAME_HOST_OPTION_BITMASK_TNT| + GAME_HOST_OPTION_BITMASK_PVP| + GAME_HOST_OPTION_BITMASK_STRUCTURES|1); + break; + case eGameHostOption_LevelType: + return (uiHostSettings&GAME_HOST_OPTION_BITMASK_LEVELTYPE); + break; + case eGameHostOption_Structures: + return (uiHostSettings&GAME_HOST_OPTION_BITMASK_STRUCTURES); + break; + case eGameHostOption_BonusChest: + return (uiHostSettings&GAME_HOST_OPTION_BITMASK_BONUSCHEST); + break; + case eGameHostOption_HasBeenInCreative: + return (uiHostSettings&GAME_HOST_OPTION_BITMASK_BEENINCREATIVE); + break; + case eGameHostOption_PvP: + return (uiHostSettings&GAME_HOST_OPTION_BITMASK_PVP); + break; + case eGameHostOption_TrustPlayers: + return (uiHostSettings&GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS); + break; + case eGameHostOption_TNT: + return (uiHostSettings&GAME_HOST_OPTION_BITMASK_TNT); + break; + case eGameHostOption_FireSpreads: + return (uiHostSettings&GAME_HOST_OPTION_BITMASK_FIRESPREADS); + break; + case eGameHostOption_CheatsEnabled: + return (uiHostSettings&(GAME_HOST_OPTION_BITMASK_HOSTFLY|GAME_HOST_OPTION_BITMASK_HOSTHUNGER|GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE)); + break; + case eGameHostOption_HostCanFly: + return (uiHostSettings&GAME_HOST_OPTION_BITMASK_HOSTFLY); + break; + case eGameHostOption_HostCanChangeHunger: + return (uiHostSettings&GAME_HOST_OPTION_BITMASK_HOSTHUNGER); + break; + case eGameHostOption_HostCanBeInvisible: + return (uiHostSettings&GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE); + break; + case eGameHostOption_BedrockFog: + return (uiHostSettings&GAME_HOST_OPTION_BITMASK_BEDROCKFOG); + break; + case eGameHostOption_DisableSaving: + return (uiHostSettings&GAME_HOST_OPTION_BITMASK_DISABLESAVE); + break; + case eGameHostOption_WasntSaveOwner: + return (uiHostSettings&GAME_HOST_OPTION_BITMASK_NOTOWNER); + case eGameHostOption_WorldSize: + return (uiHostSettings&GAME_HOST_OPTION_BITMASK_WORLDSIZE) >> GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT; + case eGameHostOption_MobGriefing: + return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_MOBGRIEFING); + case eGameHostOption_KeepInventory: + return (uiHostSettings&GAME_HOST_OPTION_BITMASK_KEEPINVENTORY); + case eGameHostOption_DoMobSpawning: + return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DOMOBSPAWNING); + case eGameHostOption_DoMobLoot: + return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DOMOBLOOT); + case eGameHostOption_DoTileDrops: + return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DOTILEDROPS); + case eGameHostOption_NaturalRegeneration: + return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_NATURALREGEN); + case eGameHostOption_DoDaylightCycle: + return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE); + break; + case eGameHostOption_Hardcore: // 4J Added - for hardcore mode + return (uiHostSettings&GAME_HOST_OPTION_BITMASK_HARDCORE) ? 1 : 0; + break; + } + + return false; +} + +bool CMinecraftApp::CanRecordStatsAndAchievements() +{ + bool isTutorial = Minecraft::GetInstance() != nullptr && Minecraft::GetInstance()->isTutorial(); + // 4J Stu - All of these options give the host player some advantage, so should not allow achievements + return !(app.GetGameHostOption(eGameHostOption_HasBeenInCreative) || + app.GetGameHostOption(eGameHostOption_HostCanBeInvisible) || + app.GetGameHostOption(eGameHostOption_HostCanChangeHunger) || + app.GetGameHostOption(eGameHostOption_HostCanFly) || + app.GetGameHostOption(eGameHostOption_WasntSaveOwner) || + !app.GetGameHostOption(eGameHostOption_MobGriefing) || + app.GetGameHostOption(eGameHostOption_KeepInventory) || + !app.GetGameHostOption(eGameHostOption_DoMobSpawning) || + (!app.GetGameHostOption(eGameHostOption_DoDaylightCycle) && !isTutorial ) + ); +} + +void CMinecraftApp::processSchematics(LevelChunk *levelChunk) +{ + m_gameRules.processSchematics(levelChunk); +} + +void CMinecraftApp::processSchematicsLighting(LevelChunk *levelChunk) +{ + m_gameRules.processSchematicsLighting(levelChunk); +} + +void CMinecraftApp::loadDefaultGameRules() +{ + m_gameRules.loadDefaultGameRules(); +} + +void CMinecraftApp::setLevelGenerationOptions(LevelGenerationOptions *levelGen) +{ + m_gameRules.setLevelGenerationOptions(levelGen); +} + +LPCWSTR CMinecraftApp::GetGameRulesString(const wstring &key) +{ + return m_gameRules.GetGameRulesString(key); +} + +unsigned char CMinecraftApp::m_szPNG[8]= +{ + 137,80,78,71,13,10,26,10 +}; + +#define PNG_TAG_tEXt 0x74455874 + +unsigned int CMinecraftApp::FromBigEndian(unsigned int uiValue) +{ +#if defined(__PS3__) || defined(_XBOX) + // Keep it in big endian + return uiValue; +#else + unsigned int uiReturn = ( ( uiValue >> 24 ) & 0x000000ff ) | + ( ( uiValue >> 8 ) & 0x0000ff00 ) | + ( ( uiValue << 8 ) & 0x00ff0000 ) | + ( ( uiValue << 24 ) & 0xff000000 ); + return uiReturn; +#endif +} + +void CMinecraftApp::GetImageTextData(PBYTE pbImageData, DWORD dwImageBytes,unsigned char *pszSeed,unsigned int &uiHostOptions,bool &bHostOptionsRead,DWORD &uiTexturePack) +{ + unsigned char *ucPtr=pbImageData; + unsigned int uiCount=0; + unsigned int uiChunkLen; + unsigned int uiChunkType; + unsigned int uiCRC; + char szKeyword[80]; + + // check it's a png + for(int i=0;i<8;i++) + { + if(m_szPNG[i]!=ucPtr[i]) return; + } + + uiCount+=8; + + while(uiCount> std::hex >> uiHostOptions; + } + else if(strcmp(szKeyword,"4J_TEXTUREPACK")==0) + { + // read the texture pack value + unsigned int uiValueC=0; + unsigned char pszTexturePack[9]; // Hex representation of unsigned int + ZeroMemory(&pszTexturePack,9); + while(*pszKeyword!=0 && (pszKeyword < ucPtr + uiCount + uiChunkLen) && uiValueC < 8) + { + pszTexturePack[uiValueC++]=*pszKeyword; + pszKeyword++; + } + + std::stringstream ss; + ss << pszTexturePack; + ss >> std::hex >> uiTexturePack; + } + } + } + uiCount+=uiChunkLen; + uiCRC=*(unsigned int*)&ucPtr[uiCount]; + uiCRC=FromBigEndian(uiCRC); + uiCount+=sizeof(int); + } + + return; +} + +unsigned int CMinecraftApp::CreateImageTextData(PBYTE bTextMetadata, int64_t seed, bool hasSeed, unsigned int uiHostOptions, unsigned int uiTexturePackId) +{ + int iTextMetadataBytes = 0; + if(hasSeed) + { + strcpy((char *)bTextMetadata,"4J_SEED"); + _i64toa_s(seed,(char *)&bTextMetadata[8],42,10); + + // get the length + iTextMetadataBytes+=8; + while(bTextMetadata[iTextMetadataBytes]!=0) iTextMetadataBytes++; + ++iTextMetadataBytes; // Add a null terminator at the end of the seed value + } + + // Save the host options that this world was last played with + strcpy((char *)&bTextMetadata[iTextMetadataBytes],"4J_HOSTOPTIONS"); + _itoa_s(uiHostOptions,(char *)&bTextMetadata[iTextMetadataBytes+15],9,16); + + iTextMetadataBytes += 15; + while(bTextMetadata[iTextMetadataBytes]!=0) iTextMetadataBytes++; + ++iTextMetadataBytes; // Add a null terminator at the end of the host options value + + // Save the texture pack id + strcpy((char *)&bTextMetadata[iTextMetadataBytes],"4J_TEXTUREPACK"); + _itoa_s(uiTexturePackId,(char *)&bTextMetadata[iTextMetadataBytes+15],9,16); + + iTextMetadataBytes += 15; + while(bTextMetadata[iTextMetadataBytes]!=0) iTextMetadataBytes++; + + return iTextMetadataBytes; +} + +void CMinecraftApp::AddTerrainFeaturePosition(_eTerrainFeatureType eFeatureType,int x,int z) +{ + // check we don't already have this in + for( FEATURE_DATA *pFeatureData : m_vTerrainFeatures ) + { + if((pFeatureData->eTerrainFeature==eFeatureType) &&(pFeatureData->x==x) && (pFeatureData->z==z)) return; + } + + FEATURE_DATA *pFeatureData= new FEATURE_DATA; + pFeatureData->eTerrainFeature=eFeatureType; + pFeatureData->x=x; + pFeatureData->z=z; + + m_vTerrainFeatures.push_back(pFeatureData); +} + +_eTerrainFeatureType CMinecraftApp::IsTerrainFeature(int x,int z) +{ + for(FEATURE_DATA *pFeatureData : m_vTerrainFeatures ) + { + if((pFeatureData->x==x) && (pFeatureData->z==z)) return pFeatureData->eTerrainFeature; + } + + return eTerrainFeature_None; +} + +bool CMinecraftApp::GetTerrainFeaturePosition(_eTerrainFeatureType eType,int *pX, int *pZ) +{ + for ( const FEATURE_DATA *pFeatureData : m_vTerrainFeatures ) + { + if(pFeatureData->eTerrainFeature==eType) + { + *pX=pFeatureData->x; + *pZ=pFeatureData->z; + return true; + } + } + + return false; +} + +void CMinecraftApp::ClearTerrainFeaturePosition() +{ + FEATURE_DATA *pFeatureData; + while(m_vTerrainFeatures.size()>0) + { + pFeatureData = m_vTerrainFeatures.back(); + m_vTerrainFeatures.pop_back(); + delete pFeatureData; + } +} + +void CMinecraftApp::UpdatePlayerInfo(BYTE networkSmallId, SHORT playerColourIndex, unsigned int playerGamePrivileges) +{ + for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) + { + if(m_playerColours[i]==networkSmallId) + { + m_playerColours[i] = 0; + m_playerGamePrivileges[i] = 0; + } + } + if(playerColourIndex >=0 && playerColourIndex < MINECRAFT_NET_MAX_PLAYERS) + { + m_playerColours[playerColourIndex] = networkSmallId; + m_playerGamePrivileges[playerColourIndex] = playerGamePrivileges; + } +} + +short CMinecraftApp::GetPlayerColour(BYTE networkSmallId) +{ + short index = -1; + for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) + { + if(m_playerColours[i]==networkSmallId) + { + index = i; + break; + } + } + return index; +} + +void CMinecraftApp::SetPlayerMapIcon(const wchar_t* name, char icon) +{ + if (name == nullptr) return; + // Update existing entry or use first empty slot + int emptySlot = -1; + for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) + { + if (m_playerMapIcons[i].name[0] != 0 && _wcsicmp(m_playerMapIcons[i].name, name) == 0) + { + m_playerMapIcons[i].icon = icon; + return; + } + if (emptySlot < 0 && m_playerMapIcons[i].name[0] == 0) + emptySlot = i; + } + if (emptySlot >= 0) + { + wcsncpy_s(m_playerMapIcons[emptySlot].name, 32, name, _TRUNCATE); + m_playerMapIcons[emptySlot].icon = icon; + } +} + +char CMinecraftApp::GetPlayerMapIconByName(const wchar_t* name) +{ + if (name == nullptr) return 0; + for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) + { + if (m_playerMapIcons[i].name[0] != 0 && _wcsicmp(m_playerMapIcons[i].name, name) == 0) + return m_playerMapIcons[i].icon; + } + return 0; +} + + +unsigned int CMinecraftApp::GetPlayerPrivileges(BYTE networkSmallId) +{ + unsigned int privileges = 0; + for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) + { + if(m_playerColours[i]==networkSmallId) + { + privileges = m_playerGamePrivileges[i]; + break; + } + } + return privileges; +} + +wstring CMinecraftApp::getEntityName(eINSTANCEOF type) +{ + switch(type) + { + case eTYPE_WOLF: + return app.GetString(IDS_WOLF); + case eTYPE_CREEPER: + return app.GetString(IDS_CREEPER); + case eTYPE_SKELETON: + return app.GetString(IDS_SKELETON); + case eTYPE_SPIDER: + return app.GetString(IDS_SPIDER); + case eTYPE_ZOMBIE: + return app.GetString(IDS_ZOMBIE); + case eTYPE_PIGZOMBIE: + return app.GetString(IDS_PIGZOMBIE); + case eTYPE_ENDERMAN: + return app.GetString(IDS_ENDERMAN); + case eTYPE_SILVERFISH: + return app.GetString(IDS_SILVERFISH); + case eTYPE_CAVESPIDER: + return app.GetString(IDS_CAVE_SPIDER); + case eTYPE_GHAST: + return app.GetString(IDS_GHAST); + case eTYPE_SLIME: + return app.GetString(IDS_SLIME); + case eTYPE_ARROW: + return app.GetString(IDS_ITEM_ARROW); + case eTYPE_ENDERDRAGON: + return app.GetString(IDS_ENDERDRAGON); + case eTYPE_BLAZE: + return app.GetString(IDS_BLAZE); + case eTYPE_LAVASLIME: + return app.GetString(IDS_LAVA_SLIME); + // 4J-PB - fix for #107167 - Customer Encountered: TU12: Content: UI: There is no information what killed Player after being slain by Iron Golem. + case eTYPE_VILLAGERGOLEM: + return app.GetString(IDS_IRONGOLEM); + case eTYPE_HORSE: + return app.GetString(IDS_HORSE); + case eTYPE_WITCH: + return app.GetString(IDS_WITCH); + case eTYPE_WITHERBOSS: + return app.GetString(IDS_WITHER); + case eTYPE_BAT: + return app.GetString(IDS_BAT); + case eTYPE_RABBIT: + return app.GetString(IDS_RABBIT); + + }; + + return L""; +} + +DWORD CMinecraftApp::m_dwContentTypeA[e_Marketplace_MAX]= +{ + XMARKETPLACE_OFFERING_TYPE_CONTENT, // e_DLC_SkinPack, e_DLC_TexturePacks, e_DLC_MashupPacks +#ifndef _XBOX_ONE + XMARKETPLACE_OFFERING_TYPE_THEME, // e_DLC_Themes + XMARKETPLACE_OFFERING_TYPE_AVATARITEM, // e_DLC_AvatarItems + XMARKETPLACE_OFFERING_TYPE_TILE, // e_DLC_Gamerpics +#endif +}; + +unsigned int CMinecraftApp::AddDLCRequest(eDLCMarketplaceType eType, bool bPromote) +{ + // lock access + EnterCriticalSection(&csDLCDownloadQueue); + + // If it's already in there, promote it to the top of the list + int iPosition=0; + for( DLCRequest *pCurrent : m_DLCDownloadQueue ) + { + if(pCurrent->dwType==m_dwContentTypeA[eType]) + { + // already got this in the list + if(pCurrent->eState == e_DLC_ContentState_Retrieving || pCurrent->eState == e_DLC_ContentState_Retrieved) + { + // already retrieved this + LeaveCriticalSection(&csDLCDownloadQueue); + return 0; + } + else + { + // promote + if(bPromote) + { + m_DLCDownloadQueue.erase(m_DLCDownloadQueue.begin()+iPosition); + m_DLCDownloadQueue.insert(m_DLCDownloadQueue.begin(),pCurrent); + } + LeaveCriticalSection(&csDLCDownloadQueue); + return 0; + } + } + iPosition++; + } + + DLCRequest *pDLCreq = new DLCRequest; + pDLCreq->dwType=m_dwContentTypeA[eType]; + pDLCreq->eState=e_DLC_ContentState_Idle; + + m_DLCDownloadQueue.push_back(pDLCreq); + + m_bAllDLCContentRetrieved=false; + LeaveCriticalSection(&csDLCDownloadQueue); + + app.DebugPrintf("[Consoles_App] Added DLC request.\n"); + return 1; +} + +unsigned int CMinecraftApp::AddTMSPPFileTypeRequest(eDLCContentType eType, bool bPromote) +{ +#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) + // lock access + EnterCriticalSection(&csTMSPPDownloadQueue); + + // If it's already in there, promote it to the top of the list + int iPosition=0; + //ignore promoting for now + /* + bool bPromoted=false; + + + for ( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue ) + { + TMSPPRequest *pCurrent = *it; + + if(pCurrent->eType==eType) + { + if(!(pCurrent->eState == e_TMS_ContentState_Retrieving || pCurrent->eState == e_TMS_ContentState_Retrieved)) + { + // promote + if(bPromote) + { + m_TMSPPDownloadQueue.erase(m_TMSPPDownloadQueue.begin()+iPosition); + m_TMSPPDownloadQueue.insert(m_TMSPPDownloadQueue.begin(),pCurrent); + bPromoted=true; + } + } + } + iPosition++; + } + + if(bPromoted) + { + // re-ordered the list, so leave now + LeaveCriticalSection(&csTMSPPDownloadQueue); + return 0; + } + */ + + // special case for data files (not image files) + if(eType==e_DLC_TexturePackData) + { + + + int iCount=GetDLCInfoFullOffersCount(); + + for(int i=0;ieDLCType==e_DLC_TexturePacks) || (pDLC->eDLCType==e_DLC_MashupPacks)) + { + // first check if the image is already in the memory textures, since we might be loading some from the Title Update partition + if(pDLC->wchDataFile[0]!=0) + { + //WCHAR *cString = pDLC->wchDataFile; + // 4J-PB - shouldn't check this here - let the TMS files override it, so if they are on TMS, we'll take them first + //int iIndex = app.GetLocalTMSFileIndex(pDLC->wchDataFile,true); + + //if(iIndex!=-1) + { + bool bPresent = app.IsFileInTPD(pDLC->iConfig); + + if(!bPresent) + { + // this may already be present in the vector because of a previous trial/full offer + + bool bAlreadyInQueue=false; + for( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue ) + { + if(wcscmp(pDLC->wchDataFile,pCurrent->wchFilename)==0) + { + bAlreadyInQueue=true; + break; + } + } + + if(!bAlreadyInQueue) + { + TMSPPRequest *pTMSPPreq = new TMSPPRequest; + + pTMSPPreq->CallbackFunc=&CMinecraftApp::TMSPPFileReturned; + pTMSPPreq->lpCallbackParam=this; + pTMSPPreq->eStorageFacility=C4JStorage::eGlobalStorage_Title; + pTMSPPreq->eFileTypeVal=C4JStorage::TMS_FILETYPE_BINARY; + memcpy(pTMSPPreq->wchFilename,pDLC->wchDataFile,sizeof(WCHAR)*MAX_BANNERNAME_SIZE); + pTMSPPreq->eType=e_DLC_TexturePackData; + pTMSPPreq->eState=e_TMS_ContentState_Queued; + m_bAllTMSContentRetrieved=false; + m_TMSPPDownloadQueue.push_back(pTMSPPreq); + } + } + else + { + app.DebugPrintf("Texture data already present in the TPD\n"); + } + } + } + } + } + } + else + { // for all the files of type eType, add them to the download list + + // run through the trial offers first, then the full offers. Any duplicates won't be added to the download queue + int iCount; +#ifdef _XBOX // Only trial offers on Xbox 360 + iCount=GetDLCInfoTrialOffersCount(); + for(int i=0;ieDLCType==eType) + { + + WCHAR *cString = pDLC->wchBanner; + + // 4J-PB - shouldn't check this here - let the TMS files override it, so if they are on TMS, we'll take them first + // is the file in the TMS XZP? + //int iIndex = app.GetLocalTMSFileIndex(cString,true); + + //if(iIndex!=-1) + { + bool bPresent = app.IsFileInMemoryTextures(cString); + + if(!bPresent) // retrieve it from TMSPP + { + bool bAlreadyInQueue=false; + for( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue ) + { + if(wcscmp(pDLC->wchBanner,pCurrent->wchFilename)==0) + { + bAlreadyInQueue=true; + break; + } + } + + if(!bAlreadyInQueue) + { + TMSPPRequest *pTMSPPreq = new TMSPPRequest; + + pTMSPPreq->CallbackFunc=&CMinecraftApp::TMSPPFileReturned; + pTMSPPreq->lpCallbackParam=this; + pTMSPPreq->eStorageFacility=C4JStorage::eGlobalStorage_Title; + pTMSPPreq->eFileTypeVal=C4JStorage::TMS_FILETYPE_BINARY; + //wcstombs(pTMSPPreq->szFilename,pDLC->wchBanner,MAX_TMSFILENAME_SIZE); + memcpy(pTMSPPreq->wchFilename,pDLC->wchBanner,sizeof(WCHAR)*MAX_BANNERNAME_SIZE); + pTMSPPreq->eType=eType; + pTMSPPreq->eState=e_TMS_ContentState_Queued; + + m_bAllTMSContentRetrieved=false; + m_TMSPPDownloadQueue.push_back(pTMSPPreq); + app.DebugPrintf("===m_TMSPPDownloadQueue Adding %ls, q size is %d\n",pTMSPPreq->wchFilename,m_TMSPPDownloadQueue.size()); + } + } + } + } + } +#endif + // and the full offers + + iCount=GetDLCInfoFullOffersCount(); + for(int i=0;iwchType,wchDLCTypeNames[eType])==0) + if(pDLC->eDLCType==eType) + { + // first check if the image is already in the memory textures, since we might be loading some from the Title Update partition + + WCHAR *cString = pDLC->wchBanner; + // 4J-PB - shouldn't check this here - let the TMS files override it, so if they are on TMS, we'll take them first + //int iIndex = app.GetLocalTMSFileIndex(cString,true); + + //if(iIndex!=-1) + { + bool bPresent = app.IsFileInMemoryTextures(cString); + + if(!bPresent) + { + // this may already be present in the vector because of a previous trial/full offer + + bool bAlreadyInQueue=false; + for( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue ) + { + if(wcscmp(pDLC->wchBanner,pCurrent->wchFilename)==0) + { + bAlreadyInQueue=true; + break; + } + } + + if(!bAlreadyInQueue) + { + //app.DebugPrintf("Adding a request to the TMSPP download queue - %ls\n",pDLC->wchBanner); + TMSPPRequest *pTMSPPreq = new TMSPPRequest; + ZeroMemory(pTMSPPreq,sizeof(TMSPPRequest)); + + pTMSPPreq->CallbackFunc=&CMinecraftApp::TMSPPFileReturned; + pTMSPPreq->lpCallbackParam=this; + // 4J-PB - testing for now + //pTMSPPreq->eStorageFacility=C4JStorage::eGlobalStorage_TitleUser; + pTMSPPreq->eStorageFacility=C4JStorage::eGlobalStorage_Title; + pTMSPPreq->eFileTypeVal=C4JStorage::TMS_FILETYPE_BINARY; + //wcstombs(pTMSPPreq->szFilename,pDLC->wchBanner,MAX_TMSFILENAME_SIZE); + + memcpy(pTMSPPreq->wchFilename,pDLC->wchBanner,sizeof(WCHAR)*MAX_BANNERNAME_SIZE); + pTMSPPreq->eType=eType; + pTMSPPreq->eState=e_TMS_ContentState_Queued; + m_bAllTMSContentRetrieved=false; + m_TMSPPDownloadQueue.push_back(pTMSPPreq); + app.DebugPrintf("===m_TMSPPDownloadQueue Adding %ls, q size is %d\n",pTMSPPreq->wchFilename,m_TMSPPDownloadQueue.size()); + } + } + } + } + } + } + + LeaveCriticalSection(&csTMSPPDownloadQueue); +#endif + return 1; +} + +bool CMinecraftApp::CheckTMSDLCCanStop() +{ + EnterCriticalSection(&csTMSPPDownloadQueue); + for( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue ) + { + if(pCurrent->eState==e_TMS_ContentState_Retrieving) + { + LeaveCriticalSection(&csTMSPPDownloadQueue); + return false; + } + } + LeaveCriticalSection(&csTMSPPDownloadQueue); + + return true; +} + + +bool CMinecraftApp::RetrieveNextDLCContent() +{ + // If there's already a retrieve in progress, quit + // we may have re-ordered the list, so need to check every item + + // is there a primary player and a network connection? + int primPad = ProfileManager.GetPrimaryPad(); + if ( primPad == -1 || !ProfileManager.IsSignedInLive(primPad) ) + { + return true; // 4J-JEV: We need to wait until the primary player is online. + } + + EnterCriticalSection(&csDLCDownloadQueue); + for( const DLCRequest* pCurrent : m_DLCDownloadQueue ) + { + if(pCurrent->eState==e_DLC_ContentState_Retrieving) + { + LeaveCriticalSection(&csDLCDownloadQueue); + return true; + } + } + + // Now look for the next retrieval + for( DLCRequest *pCurrent : m_DLCDownloadQueue ) + { + if(pCurrent->eState==e_DLC_ContentState_Idle) + { +#ifdef _DEBUG + app.DebugPrintf("RetrieveNextDLCContent - type = %d\n",pCurrent->dwType); +#endif + + C4JStorage::EDLCStatus status = StorageManager.GetDLCOffers(ProfileManager.GetPrimaryPad(), &CMinecraftApp::DLCOffersReturned, this, pCurrent->dwType); + if(status==C4JStorage::EDLC_Pending) + { + pCurrent->eState=e_DLC_ContentState_Retrieving; + } + else + { + // no content of this type, or some other problem + app.DebugPrintf("RetrieveNextDLCContent - PROBLEM\n"); + pCurrent->eState=e_DLC_ContentState_Retrieved; + } + LeaveCriticalSection(&csDLCDownloadQueue); + return true; + } + } + LeaveCriticalSection(&csDLCDownloadQueue); + + app.DebugPrintf("[Consoles_App] Finished downloading dlc content.\n"); + return false; +} + +#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) +#ifdef _XBOX_ONE +int CMinecraftApp::TMSPPFileReturned(LPVOID pParam,int iPad,int iUserData,LPVOID lpvData, WCHAR* wchFilename) +{ + C4JStorage::PTMSPP_FILEDATA pFileData=(C4JStorage::PTMSPP_FILEDATA)lpvData; +#else +int CMinecraftApp::TMSPPFileReturned(LPVOID pParam,int iPad,int iUserData,C4JStorage::PTMSPP_FILEDATA pFileData, LPCSTR szFilename) +{ +#endif + + CMinecraftApp* pClass = static_cast(pParam); + + // find the right one in the vector + EnterCriticalSection(&pClass->csTMSPPDownloadQueue); + for( TMSPPRequest *pCurrent : pClass->m_TMSPPDownloadQueue ) + { +#if defined(_XBOX) || defined(_WINDOWS64) + char szFile[MAX_TMSFILENAME_SIZE]; + wcstombs(szFile,pCurrent->wchFilename,MAX_TMSFILENAME_SIZE); + + + if(strcmp(szFilename,szFile)==0) +#elif _XBOX_ONE + if(wcscmp(wchFilename,pCurrent->wchFilename)==0) +#endif + { + // set this to retrieved whether it found it or not + pCurrent->eState=e_TMS_ContentState_Retrieved; + + if(pFileData!=nullptr) + { +#ifdef _XBOX_ONE + + + switch(pCurrent->eType) + { + case e_DLC_TexturePackData: + { + // 4J-PB - we need to allocate memory for the file data and copy into it, since the current data is a reference into the blob download memory + PBYTE pbData = new BYTE [pFileData->dwSize]; + memcpy(pbData,pFileData->pbData,pFileData->dwSize); + + pClass->m_vTMSPPData.push_back(pbData); + app.DebugPrintf("Got texturepack data\n"); + // get the config value for the texture pack + int iConfig=app.GetTPConfigVal(pCurrent->wchFilename); + app.AddMemoryTPDFile(iConfig, pbData, pFileData->dwSize); + } + break; + default: + // 4J-PB - check the data is an image + if(pFileData->pbData[0]==0x89) + { + // 4J-PB - we need to allocate memory for the file data and copy into it, since the current data is a reference into the blob download memory + PBYTE pbData = new BYTE [pFileData->dwSize]; + memcpy(pbData,pFileData->pbData,pFileData->dwSize); + + pClass->m_vTMSPPData.push_back(pbData); + app.DebugPrintf("Got image data - %ls\n",pCurrent->wchFilename); + app.AddMemoryTextureFile(pCurrent->wchFilename, pbData, pFileData->dwSize); + } + else + { + app.DebugPrintf("Got image data, but it's not a png - %ls\n",pCurrent->wchFilename); + } + break; + } + +#else + switch(pCurrent->eType) + { + case e_DLC_TexturePackData: + { + app.DebugPrintf("--- Got texturepack data %ls\n",pCurrent->wchFilename); + // get the config value for the texture pack + int iConfig=app.GetTPConfigVal(pCurrent->wchFilename); + app.AddMemoryTPDFile(iConfig, pFileData->pbData, pFileData->dwSize); + } + break; + default: + app.DebugPrintf("--- Got image data - %ls\n",pCurrent->wchFilename); + app.AddMemoryTextureFile(pCurrent->wchFilename, pFileData->pbData, pFileData->dwSize); + break; + } +#endif + } + else + { +#ifdef _XBOX_ONE + app.DebugPrintf("TMSImageReturned failed (%ls)...\n",wchFilename); +#else + app.DebugPrintf("TMSImageReturned failed (%s)...\n",szFilename); +#endif + } + break; + } + + } + LeaveCriticalSection(&pClass->csTMSPPDownloadQueue); + + return 0; +} +#endif + +bool CMinecraftApp::RetrieveNextTMSPPContent() +{ +#if defined _XBOX || defined _XBOX_ONE + // If there's already a retrieve in progress, quit + // we may have re-ordered the list, so need to check every item + + // is there a primary player and a network connection? + if(ProfileManager.GetPrimaryPad()==-1) return false; + + if(ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad())==false) return false; + + for( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue ) + { + TMSPPRequest *pCurrent = *it; + + if(pCurrent->eState==e_TMS_ContentState_Retrieving) + { + app.DebugPrintf("."); + LeaveCriticalSection(&csTMSPPDownloadQueue); + return true; + } + } + + // Now look for the next retrieval + for( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue ) + { + TMSPPRequest *pCurrent = *it; + + if(pCurrent->eState==e_TMS_ContentState_Queued) + { + // 4J-PB - the file may be in the local TMS files, but try to retrieve it from the remote TMS in case it's been changed. If it's not in the list of TMS files, this will + // return right away with a ETMSStatus_Fail_ReadDetailsNotRetrieved +#ifdef _XBOX + char szFilename[MAX_TMSFILENAME_SIZE]; + wcstombs(szFilename,pCurrent->wchFilename,MAX_TMSFILENAME_SIZE); + + app.DebugPrintf("\nRetrieveNextTMSPPContent - type = %d, %s\n",pCurrent->eType,szFilename); + + C4JStorage::ETMSStatus status=StorageManager.TMSPP_ReadFile(ProfileManager.GetPrimaryPad(),pCurrent->eStorageFacility,pCurrent->eFileTypeVal,szFilename,pCurrent->CallbackFunc,this); + switch(status) + { + case C4JStorage::ETMSStatus_Pending: + pCurrent->eState=e_TMS_ContentState_Retrieving; + break; + case C4JStorage::ETMSStatus_Idle: + pCurrent->eState=e_TMS_ContentState_Retrieved; + break; + case C4JStorage::ETMSStatus_Fail_ReadInProgress: + case C4JStorage::ETMSStatus_ReadInProgress: + pCurrent->eState=e_TMS_ContentState_Retrieving; + if(pCurrent->eState==C4JStorage::ETMSStatus_Fail_ReadInProgress) + { + app.DebugPrintf("TMSPP_ReadFile failed - read in progress\n"); + Sleep(50); + LeaveCriticalSection(&csTMSPPDownloadQueue); + return false; + } + break; + default: + pCurrent->eState=e_TMS_ContentState_Retrieved; + break; + } +#else + eTitleStorageState status; + app.DebugPrintf("RetrieveNextTMSPPContent - type = %d, %ls\n",pCurrent->eType,pCurrent->wchFilename); + //eTitleStorageState status=StorageManager.TMSPP_ReadFile(ProfileManager.GetPrimaryPad(),pCurrent->eStorageFacility,pCurrent->eFileTypeVal,pCurrent->wchFilename,pCurrent->CallbackFunc,this,0); + if(0)//wcscmp(pCurrent->wchFilename,L"TP01.png")==0) + { + // TP01 fails because the blob size returned is bigger than the global metadata says it should be + status=eTitleStorage_readerror; + } + else + { + status=StorageManager.TMSPP_ReadFile(ProfileManager.GetPrimaryPad(),pCurrent->eStorageFacility,pCurrent->eFileTypeVal,pCurrent->wchFilename,pCurrent->CallbackFunc,this,0); + } + switch(status) + { + case eTitleStorage_pending: + pCurrent->eState=e_TMS_ContentState_Retrieving; + break; + case eTitleStorage_idle: + pCurrent->eState=e_TMS_ContentState_Retrieved; + break; + case eTitleStorage_busy: + // try again next time + { + app.DebugPrintf("@@@@@@@@@@@@@@@@@ TMSPP_ReadFile failed - busy (probably reading already)\n"); + Sleep(50); + LeaveCriticalSection(&csTMSPPDownloadQueue); + return false; + } + break; + default: + pCurrent->eState=e_TMS_ContentState_Retrieved; + break; + } +#endif + + + + LeaveCriticalSection(&csTMSPPDownloadQueue); + return true; + } + } + + LeaveCriticalSection(&csTMSPPDownloadQueue); + +#endif + return false; +} + +void CMinecraftApp::TickDLCOffersRetrieved() +{ + if(!m_bAllDLCContentRetrieved) + { + if (!app.RetrieveNextDLCContent()) + { + app.DebugPrintf("[Consoles_App] All content retrieved.\n"); + m_bAllDLCContentRetrieved=true; + } + } +} +void CMinecraftApp::ClearAndResetDLCDownloadQueue() +{ + app.DebugPrintf("[Consoles_App] Clear and reset download queue.\n"); + + int iPosition=0; + EnterCriticalSection(&csTMSPPDownloadQueue); + for( DLCRequest *pCurrent : m_DLCDownloadQueue ) + { + if ( pCurrent ) + delete pCurrent; + iPosition++; + } + m_DLCDownloadQueue.clear(); + m_bAllDLCContentRetrieved=true; + LeaveCriticalSection(&csTMSPPDownloadQueue); +} + +void CMinecraftApp::TickTMSPPFilesRetrieved() +{ + if(m_bTickTMSDLCFiles && !m_bAllTMSContentRetrieved) + { + if(app.RetrieveNextTMSPPContent()==false) + { + m_bAllTMSContentRetrieved=true; + } + } +} +void CMinecraftApp::ClearTMSPPFilesRetrieved() +{ + int iPosition=0; + EnterCriticalSection(&csTMSPPDownloadQueue); + for ( TMSPPRequest *pCurrent : m_TMSPPDownloadQueue ) + { + if ( pCurrent ) + delete pCurrent; + iPosition++; + } + m_TMSPPDownloadQueue.clear(); + m_bAllTMSContentRetrieved=true; + LeaveCriticalSection(&csTMSPPDownloadQueue); +} + +int CMinecraftApp::DLCOffersReturned(void *pParam, int iOfferC, DWORD dwType, int iPad) +{ + CMinecraftApp* pClass = static_cast(pParam); + + // find the right one in the vector + EnterCriticalSection(&pClass->csTMSPPDownloadQueue); + for( DLCRequest *pCurrent : pClass->m_DLCDownloadQueue ) + { + // avatar items are coming back as type Content, so we can't trust the type setting + if(pCurrent->dwType==dwType) + { + pClass->m_iDLCOfferC = iOfferC; + app.DebugPrintf("DLCOffersReturned - type %d, count %d - setting to retrieved\n",dwType,iOfferC); + pCurrent->eState=e_DLC_ContentState_Retrieved; + break; + } + } + LeaveCriticalSection(&pClass->csTMSPPDownloadQueue); + return 0; +} + +eDLCContentType CMinecraftApp::Find_eDLCContentType(DWORD dwType) +{ + for(int i=0;i(i); + } + } + return static_cast(0); +} +bool CMinecraftApp::DLCContentRetrieved(eDLCMarketplaceType eType) +{ + // If there's already a retrieve in progress, quit + // we may have re-ordered the list, so need to check every item + EnterCriticalSection(&csDLCDownloadQueue); + for( DLCRequest *pCurrent : m_DLCDownloadQueue ) + { + if((pCurrent->dwType==m_dwContentTypeA[eType]) && (pCurrent->eState==e_DLC_ContentState_Retrieved)) + { + LeaveCriticalSection(&csDLCDownloadQueue); + return true; + } + } + LeaveCriticalSection(&csDLCDownloadQueue); + return false; +} + +void CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, SKIN_BOX *SkinBoxA, DWORD dwSkinBoxC) +{ + EntityRenderDispatcher *dispatcher = EntityRenderDispatcher::instance; + EntityRenderer *renderer = dispatcher ? dispatcher->getRenderer(eTYPE_PLAYER) : nullptr; + Model *pModel = renderer ? renderer->getModel() : nullptr; + vector *pvModelPart = new vector; + vector *pvSkinBoxes = new vector; + + EnterCriticalSection( &csAdditionalModelParts ); + EnterCriticalSection( &csAdditionalSkinBoxes ); + + app.DebugPrintf("*** SetAdditionalSkinBoxes - Inserting model parts for skin %d from array of Skin Boxes\n",dwSkinID&0x0FFFFFFF); + + // convert the skin boxes into model parts, and add to the humanoid model + for(unsigned int i=0;iAddOrRetrievePart(&SkinBoxA[i]); + pvModelPart->push_back(pModelPart); + pvSkinBoxes->push_back(&SkinBoxA[i]); + } + } + + + m_AdditionalModelParts.insert( std::pair *>(dwSkinID, pvModelPart) ); + m_AdditionalSkinBoxes.insert( std::pair *>(dwSkinID, pvSkinBoxes) ); + + LeaveCriticalSection( &csAdditionalSkinBoxes ); + LeaveCriticalSection( &csAdditionalModelParts ); + +} + +vector * CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, vector *pvSkinBoxA) +{ + EntityRenderDispatcher *dispatcher = EntityRenderDispatcher::instance; + EntityRenderer *renderer = dispatcher ? dispatcher->getRenderer(eTYPE_PLAYER) : nullptr; + Model *pModel = renderer ? renderer->getModel() : nullptr; + vector *pvModelPart = new vector; + + EnterCriticalSection( &csAdditionalModelParts ); + EnterCriticalSection( &csAdditionalSkinBoxes ); + app.DebugPrintf("*** SetAdditionalSkinBoxes - Inserting model parts for skin %d from array of Skin Boxes\n",dwSkinID&0x0FFFFFFF); + + // convert the skin boxes into model parts, and add to the humanoid model + for( auto& it : *pvSkinBoxA ) + { + if(pModel) + { + ModelPart *pModelPart=pModel->AddOrRetrievePart(it); + pvModelPart->push_back(pModelPart); + } + } + + m_AdditionalModelParts.emplace(dwSkinID, pvModelPart); + m_AdditionalSkinBoxes.emplace(dwSkinID, pvSkinBoxA); + + LeaveCriticalSection( &csAdditionalSkinBoxes ); + LeaveCriticalSection( &csAdditionalModelParts ); + return pvModelPart; +} + + +vector *CMinecraftApp::GetAdditionalModelParts(DWORD dwSkinID) +{ + EnterCriticalSection( &csAdditionalModelParts ); + vector *pvModelParts=nullptr; + if(m_AdditionalModelParts.size()>0) + { + auto it = m_AdditionalModelParts.find(dwSkinID); + if(it!=m_AdditionalModelParts.end()) + { + pvModelParts = (*it).second; + } + } + + LeaveCriticalSection( &csAdditionalModelParts ); + return pvModelParts; +} + +vector *CMinecraftApp::GetAdditionalSkinBoxes(DWORD dwSkinID) +{ + EnterCriticalSection( &csAdditionalSkinBoxes ); + vector *pvSkinBoxes=nullptr; + if(m_AdditionalSkinBoxes.size()>0) + { + auto it = m_AdditionalSkinBoxes.find(dwSkinID); + if(it!=m_AdditionalSkinBoxes.end()) + { + pvSkinBoxes = (*it).second; + } + } + + LeaveCriticalSection( &csAdditionalSkinBoxes ); + return pvSkinBoxes; +} + +unsigned int CMinecraftApp::GetAnimOverrideBitmask(DWORD dwSkinID) +{ + EnterCriticalSection( &csAnimOverrideBitmask ); + unsigned int uiAnimOverrideBitmask=0L; + + if(m_AnimOverrides.size()>0) + { + auto it = m_AnimOverrides.find(dwSkinID); + if(it!=m_AnimOverrides.end()) + { + uiAnimOverrideBitmask = (*it).second; + } + } + + LeaveCriticalSection( &csAnimOverrideBitmask ); + return uiAnimOverrideBitmask; +} + +void CMinecraftApp::SetAnimOverrideBitmask(DWORD dwSkinID,unsigned int uiAnimOverrideBitmask) +{ + // Make thread safe + EnterCriticalSection( &csAnimOverrideBitmask ); + + if(m_AnimOverrides.size()>0) + { + auto it = m_AnimOverrides.find(dwSkinID); + if(it!=m_AnimOverrides.end()) + { + LeaveCriticalSection( &csAnimOverrideBitmask ); + return; // already in here + } + } + m_AnimOverrides.insert( std::pair(dwSkinID, uiAnimOverrideBitmask) ); + LeaveCriticalSection( &csAnimOverrideBitmask ); +} + +DWORD CMinecraftApp::getSkinIdFromPath(const wstring &skin) +{ + bool dlcSkin = false; + unsigned int skinId = 0; + + if(skin.size() >= 14) + { + dlcSkin = skin.substr(0,3).compare(L"dlc") == 0; + + wstring skinValue = skin.substr(7,skin.size()); + skinValue = skinValue.substr(0,skinValue.find_first_of(L'.')); + + std::wstringstream ss; + // 4J Stu - dlc skins are numbered using decimal to make it easier for artists/people to number manually + // Everything else is numbered using hex + if(dlcSkin) + ss << std::dec << skinValue.c_str(); + else + ss << std::hex << skinValue.c_str(); + ss >> skinId; + + skinId = MAKE_SKIN_BITMASK(dlcSkin, skinId); + } + return skinId; +} + +wstring CMinecraftApp::getSkinPathFromId(DWORD skinId) +{ + // 4J Stu - This function maps the encoded DWORD we store in the player profile + // to a filename that is stored as a memory texture and shared between systems in game + wchar_t chars[256]; + if( GET_IS_DLC_SKIN_FROM_BITMASK(skinId) ) + { + // 4J Stu - DLC skins are numbered using decimal rather than hex to make it easier to number manually + swprintf(chars, 256, L"dlcskin%08d.png", GET_DLC_SKIN_ID_FROM_BITMASK(skinId)); + + } + else + { + DWORD ugcSkinIndex = GET_UGC_SKIN_ID_FROM_BITMASK(skinId); + DWORD defaultSkinIndex = GET_DEFAULT_SKIN_ID_FROM_BITMASK(skinId); + if( ugcSkinIndex == 0 ) + { + swprintf(chars, 256, L"defskin%08X.png",defaultSkinIndex); + } + else + { + swprintf(chars, 256, L"ugcskin%08X.png",ugcSkinIndex); + } + } + return chars; +} + + +int CMinecraftApp::TexturePackDialogReturned(void* pParam, int iPad, C4JStorage::EMessageResult result) +{ + +#if defined __PSVITA__ || defined __PS3__ || defined __ORBIS__ + if (result == C4JStorage::EMessage_ResultAccept) + { + Minecraft* pMinecraft = Minecraft::GetInstance(); + if (pMinecraft->skins->selectTexturePackById(app.GetRequiredTexturePackID())) + { + // it's been installed already + } + else + { + // we need to enable background downloading for the DLC + XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW); + + SONYDLC* pSONYDLCInfo = app.GetSONYDLCInfo(app.GetRequiredTexturePackID()); + if (pSONYDLCInfo != nullptr) + { + char chName[42]; + char chKeyName[20]; + char chSkuID[SCE_NP_COMMERCE2_SKU_ID_LEN]; + + memset(chSkuID, 0, SCE_NP_COMMERCE2_SKU_ID_LEN); + + memset(chKeyName, 0, sizeof(chKeyName)); + strncpy(chKeyName, pSONYDLCInfo->chDLCKeyname, 16); + + #ifdef __ORBIS__ + strcpy(chName, chKeyName); + #else + sprintf(chName, "%s-%s", app.GetCommerceCategory(), chKeyName); + #endif + + app.GetDLCSkuIDFromProductList(chName, chSkuID); + + if (app.CheckForEmptyStore(iPad) == false) + { + if (app.DLCAlreadyPurchased(chSkuID)) + { + app.DownloadAlreadyPurchased(chSkuID); + } + else + { + app.Checkout(chSkuID); + } + } + } + } + } + else + { + app.DebugPrintf("Continuing without installing texture pack\n"); + } +#endif + +#ifdef _XBOX + if (result != C4JStorage::EMessage_Cancelled) + { + if (app.GetRequiredTexturePackID() != 0) + { + XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW); + + ULONGLONG ullOfferID_Full; + ULONGLONG ullIndexA[1]; + app.GetDLCFullOfferIDForPackID(app.GetRequiredTexturePackID(), &ullOfferID_Full); + + if (result == C4JStorage::EMessage_ResultAccept) + { + ullIndexA[0] = ullOfferID_Full; + StorageManager.InstallOffer(1, ullIndexA, nullptr, nullptr); + } + else + { + DLC_INFO* pDLCInfo = app.GetDLCInfoForFullOfferID(ullOfferID_Full); + ullIndexA[0] = pDLCInfo->ullOfferID_Trial; + StorageManager.InstallOffer(1, ullIndexA, nullptr, nullptr); + } + } + } +#endif + return 0; +} +int CMinecraftApp::getArchiveFileSize(const wstring &filename) +{ + TexturePack *tPack = nullptr; + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(pMinecraft && pMinecraft->skins) tPack = pMinecraft->skins->getSelected(); + if(tPack && tPack->hasData() && tPack->getArchiveFile() && tPack->getArchiveFile()->hasFile(filename)) + { + return tPack->getArchiveFile()->getFileSize(filename); + } + else return m_mediaArchive->getFileSize(filename); +} + +bool CMinecraftApp::hasArchiveFile(const wstring &filename) +{ + TexturePack *tPack = nullptr; + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(pMinecraft && pMinecraft->skins) tPack = pMinecraft->skins->getSelected(); + if(tPack && tPack->hasData() && tPack->getArchiveFile() && tPack->getArchiveFile()->hasFile(filename)) return true; + else return m_mediaArchive->hasFile(filename); +} + +byteArray CMinecraftApp::getArchiveFile(const wstring &filename) +{ + TexturePack *tPack = nullptr; + Minecraft *pMinecraft = Minecraft::GetInstance(); + if(pMinecraft && pMinecraft->skins) tPack = pMinecraft->skins->getSelected(); + if(tPack && tPack->hasData() && tPack->getArchiveFile() && tPack->getArchiveFile()->hasFile(filename)) + { + return tPack->getArchiveFile()->getFile(filename); + } + else return m_mediaArchive->getFile(filename); +} + +// DLC + +#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) +int CMinecraftApp::GetDLCInfoCount() +{ + return (int)DLCInfo.size(); +} +#elif defined _XBOX_ONE +int CMinecraftApp::GetDLCInfoTrialOffersCount() +{ + return 0; +} + +int CMinecraftApp::GetDLCInfoFullOffersCount() +{ + return (int)DLCInfo_Full.size(); +} +#else +int CMinecraftApp::GetDLCInfoTrialOffersCount() +{ + return static_cast(DLCInfo_Trial.size()); +} + +int CMinecraftApp::GetDLCInfoFullOffersCount() +{ + return static_cast(DLCInfo_Full.size()); +} +#endif + +int CMinecraftApp::GetDLCInfoTexturesOffersCount() +{ + return static_cast(DLCTextures_PackID.size()); +} + +// AUTOSAVE +void CMinecraftApp::SetAutosaveTimerTime(void) +{ +#if defined(_XBOX_ONE) || defined(__ORBIS__) + m_uiAutosaveTimer= GetTickCount()+1000*60; +#else + m_uiAutosaveTimer= GetTickCount()+GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_Autosave)*1000*60*15; +#endif +}// value x 15 to get mins, x60 for secs + +bool CMinecraftApp::AutosaveDue(void) +{ + return (GetTickCount()>m_uiAutosaveTimer); +} + +unsigned int CMinecraftApp::SecondsToAutosave() +{ + return (m_uiAutosaveTimer - GetTickCount() ) / 1000; +} + +void CMinecraftApp::SetTrialTimerStart(void) +{ + m_fTrialTimerStart=m_Time.fAppTime; mfTrialPausedTime=0.0f; +} + +float CMinecraftApp::getTrialTimer(void) +{ + return m_Time.fAppTime-m_fTrialTimerStart-mfTrialPausedTime; +} + +bool CMinecraftApp::IsLocalMultiplayerAvailable() +{ + DWORD connectedControllers = 0; + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + { + if( InputManager.IsPadConnected(i) || ProfileManager.IsSignedIn(i) ) ++connectedControllers; + } + +#ifdef _WINDOWS64 + bool available = connectedControllers > 1; +#else + bool available = RenderManager.IsHiDef() && connectedControllers > 1; +#endif + +#ifdef __ORBIS__ + // Check for remote play + available = available && InputManager.IsLocalMultiplayerAvailable(); +#endif + + return available; + + // Found this in GameNetworkManager? + //#ifdef _DURANGO + // iOtherConnectedControllers = InputManager.GetConnectedGamepadCount(); + // if((InputManager.IsPadConnected(userIndex) || ProfileManager.IsSignedIn(userIndex))) + // { + // --iOtherConnectedControllers; + // } + //#else + // for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + // { + // if( (i!=userIndex) && (InputManager.IsPadConnected(i) || ProfileManager.IsSignedIn(i)) ) + // { + // iOtherConnectedControllers++; + // } + // } + //#endif +} + + +// 4J-PB - language and locale function + +void CMinecraftApp::getLocale(vector &vecWstrLocales) +{ + vector locales; + + DWORD dwSystemLanguage = XGetLanguage( ); + + // 4J-PB - restrict the 360 language until we're ready to have them in + +#ifdef _XBOX + switch(dwSystemLanguage) + { + case XC_LANGUAGE_FRENCH : + locales.push_back(eMCLang_frFR); + break; + case XC_LANGUAGE_ITALIAN : + locales.push_back(eMCLang_itIT); + break; + case XC_LANGUAGE_GERMAN : + locales.push_back(eMCLang_deDE); + break; + case XC_LANGUAGE_SPANISH : + locales.push_back(eMCLang_esES); + break; + case XC_LANGUAGE_PORTUGUESE : + if(XGetLocale()==XC_LOCALE_BRAZIL) + { + locales.push_back(eMCLang_ptBR); + } + locales.push_back(eMCLang_ptPT); + break; + case XC_LANGUAGE_JAPANESE : + locales.push_back(eMCLang_jaJP); + break; + case XC_LANGUAGE_KOREAN : + locales.push_back(eMCLang_koKR); + break; + case XC_LANGUAGE_TCHINESE : + locales.push_back(eMCLang_zhCHT); + break; + } +#else + switch(dwSystemLanguage) + { + + case XC_LANGUAGE_ENGLISH: + switch(XGetLocale()) + { + case XC_LOCALE_AUSTRALIA: + case XC_LOCALE_CANADA: + case XC_LOCALE_CZECH_REPUBLIC: + case XC_LOCALE_GREECE: + case XC_LOCALE_HONG_KONG: + case XC_LOCALE_HUNGARY: + case XC_LOCALE_INDIA: + case XC_LOCALE_IRELAND: + case XC_LOCALE_ISRAEL: + case XC_LOCALE_NEW_ZEALAND: + case XC_LOCALE_SAUDI_ARABIA: + case XC_LOCALE_SINGAPORE: + case XC_LOCALE_SLOVAK_REPUBLIC: + case XC_LOCALE_SOUTH_AFRICA: + case XC_LOCALE_UNITED_ARAB_EMIRATES: + case XC_LOCALE_GREAT_BRITAIN: + locales.push_back(eMCLang_enGB); + break; + default: //XC_LOCALE_UNITED_STATES + break; + } + break; + case XC_LANGUAGE_JAPANESE : + locales.push_back(eMCLang_jaJP); + break; + case XC_LANGUAGE_GERMAN : + switch(XGetLocale()) + { + case XC_LOCALE_AUSTRIA: + locales.push_back(eMCLang_deAT); + break; + case XC_LOCALE_SWITZERLAND: + locales.push_back(eMCLang_deCH); + break; + default:// XC_LOCALE_GERMANY: + break; + } + locales.push_back(eMCLang_deDE); + break; + case XC_LANGUAGE_FRENCH : + switch(XGetLocale()) + { + case XC_LOCALE_BELGIUM: + locales.push_back(eMCLang_frBE); + break; + case XC_LOCALE_CANADA: + locales.push_back(eMCLang_frCA); + break; + case XC_LOCALE_SWITZERLAND: + locales.push_back(eMCLang_frCH); + break; + default:// XC_LOCALE_FRANCE: + break; + } + locales.push_back(eMCLang_frFR); + break; + case XC_LANGUAGE_SPANISH : + switch(XGetLocale()) + { + case XC_LOCALE_MEXICO: + case XC_LOCALE_ARGENTINA: + case XC_LOCALE_CHILE: + case XC_LOCALE_COLOMBIA: + case XC_LOCALE_UNITED_STATES: + case XC_LOCALE_LATIN_AMERICA: + locales.push_back(eMCLang_laLAS); + locales.push_back(eMCLang_esMX); + break; + default://XC_LOCALE_SPAIN + break; + } + locales.push_back(eMCLang_esES); + break; + case XC_LANGUAGE_ITALIAN : + locales.push_back(eMCLang_itIT); + break; + case XC_LANGUAGE_KOREAN : + locales.push_back(eMCLang_koKR); + break; + case XC_LANGUAGE_TCHINESE : + switch(XGetLocale()) + { + case XC_LOCALE_HONG_KONG: + locales.push_back(eMCLang_zhHK); + locales.push_back(eMCLang_zhTW); + break; + case XC_LOCALE_TAIWAN: + locales.push_back(eMCLang_zhTW); + locales.push_back(eMCLang_zhHK); + default: + break; + } + locales.push_back(eMCLang_hant); + locales.push_back(eMCLang_zhCHT); + break; + case XC_LANGUAGE_PORTUGUESE : + if(XGetLocale()==XC_LOCALE_BRAZIL) + { + locales.push_back(eMCLang_ptBR); + } + locales.push_back(eMCLang_ptPT); + break; + case XC_LANGUAGE_POLISH : + locales.push_back(eMCLang_plPL); + break; + case XC_LANGUAGE_RUSSIAN : + locales.push_back(eMCLang_ruRU); + break; + case XC_LANGUAGE_SWEDISH : + locales.push_back(eMCLang_svSV); + locales.push_back(eMCLang_svSE); + break; + case XC_LANGUAGE_TURKISH : + locales.push_back(eMCLang_trTR); + break; + case XC_LANGUAGE_BNORWEGIAN : + locales.push_back(eMCLang_nbNO); + locales.push_back(eMCLang_noNO); + locales.push_back(eMCLang_nnNO); + break; + case XC_LANGUAGE_DUTCH : + switch(XGetLocale()) + { + case XC_LOCALE_BELGIUM: + locales.push_back(eMCLang_nlBE); + break; + default: + break; + } + locales.push_back(eMCLang_nlNL); + break; + case XC_LANGUAGE_SCHINESE : + switch(XGetLocale()) + { + case XC_LOCALE_SINGAPORE: + locales.push_back(eMCLang_zhSG); + break; + default: + break; + } + locales.push_back(eMCLang_hans); + locales.push_back(eMCLang_csCS); + locales.push_back(eMCLang_zhCN); + break; + +#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ || defined _DURANGO + case XC_LANGUAGE_DANISH: + locales.push_back(eMCLang_daDA); + locales.push_back(eMCLang_daDK); + break; + + case XC_LANGUAGE_FINISH : + locales.push_back(eMCLang_fiFI); + break; + + case XC_LANGUAGE_CZECH : + locales.push_back(eMCLang_csCZ); + locales.push_back(eMCLang_enCZ); + break; + + case XC_LANGUAGE_SLOVAK : + locales.push_back(eMCLang_skSK); + locales.push_back(eMCLang_enSK); + break; + + case XC_LANGUAGE_GREEK : + locales.push_back(eMCLang_elEL); + locales.push_back(eMCLang_elGR); + locales.push_back(eMCLang_enGR); + locales.push_back(eMCLang_enGB); + break; +#endif + } +#endif + + locales.push_back(eMCLang_enUS); + locales.push_back(eMCLang_null); + + for (size_t i=0; igetMovie(), + &result, + getIggyValuePath(), + m_initFunc, + 1, + value); +} + +// the internal element array +// Items are stored in insertion order so +// we walk m_itemIds to find the 0-based position of the given id +int UIControl_MultiList::getListIndex(int id) const +{ + for (size_t i = 0; i < m_itemIds.size(); ++i) + { + if (m_itemIds[i] == id) + return (int)i; + } + return -1; +} + +// returns the item id stored at the given position in m_itemIds or -1 if out of range +int UIControl_MultiList::getIdFromIndex(int index) const +{ + if (index >= 0 && index < (int)m_itemIds.size()) + return m_itemIds[index]; + return -1; +} + +void UIControl_MultiList::AddNewLabel(const wstring &label) +{ + IggyDataValue result; + IggyDataValue value[1]; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + + IggyPlayerCallMethodRS(m_parentScene->getMovie(), &result, + getIggyValuePath(), m_funcAddNewItem_Label, 1, value); + + m_itemIds.push_back(-1); + ++m_itemCount; +} + +void UIControl_MultiList::AddNewButton(const wstring &label, int id) +{ + IggyDataValue result; + IggyDataValue value[2]; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = (double)id; + + IggyPlayerCallMethodRS(m_parentScene->getMovie(), &result, + getIggyValuePath(), m_funcAddNewItem_Button, 2, value); + + m_itemIds.push_back(id); + ++m_itemCount; +} + +void UIControl_MultiList::AddNewMenuButton(const wstring &label, int id) +{ + AddNewButton(label, id); +} + +void UIControl_MultiList::AddNewCheckbox(const wstring &label, int id, bool checked) +{ + IggyDataValue result; + IggyDataValue value[3]; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = (double)id; + + value[2].type = IGGY_DATATYPE_boolean; + value[2].boolval = checked ? 1 : 0; + + IggyPlayerCallMethodRS(m_parentScene->getMovie(), &result, + getIggyValuePath(), m_funcAddNewItem_CheckBox, 3, value); + + m_itemIds.push_back(id); + ++m_itemCount; +} + +void UIControl_MultiList::AddNewSlider(const wstring &label, int id, int minVal, int maxVal, int step, int initialVal) +{ + app.DebugPrintf("[MULTILIST] AddNewSlider: label=%ls id=%d min=%d max=%d step=%d init=%d\n", + label.c_str(), id, minVal, maxVal, step, initialVal); + IggyDataValue result; + IggyDataValue value[5]; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = (double)id; + + value[2].type = IGGY_DATATYPE_number; + value[2].number = (double)minVal; + + value[3].type = IGGY_DATATYPE_number; + value[3].number = (double)maxVal; + + value[4].type = IGGY_DATATYPE_number; + value[4].number = (double)initialVal; + + IggyPlayerCallMethodRS(m_parentScene->getMovie(), &result, + getIggyValuePath(), m_funcAddNewItem_Slider, 5, value); + + m_itemIds.push_back(id); + ++m_itemCount; +} + +void UIControl_MultiList::AddNewTextInput(const wstring &label, int id) +{ + IggyDataValue result; + IggyDataValue value[2]; + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].type = IGGY_DATATYPE_string_UTF16; + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = (double)id; + + IggyPlayerCallMethodRS(m_parentScene->getMovie(), &result, + getIggyValuePath(), m_funcAddNewItem_TextInput, 2, value); + + m_itemIds.push_back(id); + ++m_itemCount; +} + +bool UIControl_MultiList::GetCheckboxValue(int id) +{ + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = (double)getListIndex(id); + + IggyPlayerCallMethodRS(m_parentScene->getMovie(), &result, + getIggyValuePath(), m_funcGetCheckBox, 1, value); + + if (result.type == IGGY_DATATYPE_boolean) + return result.boolval != 0; + if (result.type == IGGY_DATATYPE_number) + return (int)result.number == 1; + return false; +} + +void UIControl_MultiList::SetCheckboxValue(int id, bool checked, bool bImmediate) +{ + + IggyDataValue result; + IggyDataValue value[2]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = (double)getListIndex(id); + + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = checked ? 1 : 0; + + IggyPlayerCallMethodRS(m_parentScene->getMovie(), &result, + getIggyValuePath(), m_funcSetCheckBox, 2, value); +} + +int UIControl_MultiList::GetSliderValue(int id) +{ + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = (double)getListIndex(id); + + IggyPlayerCallMethodRS(m_parentScene->getMovie(), &result, + getIggyValuePath(), m_funcGetSliderValue, 1, value); + + if (result.type == IGGY_DATATYPE_number) + return (int)result.number; + return 0; +} + + +void UIControl_MultiList::SetSliderValue(int id, int value, bool bImmediate) +{ + IggyDataValue result; + IggyDataValue args[2]; + + args[0].type = IGGY_DATATYPE_number; + args[0].number = (double)getListIndex(id); + + args[1].type = IGGY_DATATYPE_number; + args[1].number = (double)value; + + IggyPlayerCallMethodRS(m_parentScene->getMovie(), &result, + getIggyValuePath(), m_funcSetSliderValue, 2, args); +} + +void UIControl_MultiList::SetSliderLabel(int id, const wstring &label, bool bImmediate) +{ + IggyDataValue result; + IggyDataValue args[2]; + + args[0].type = IGGY_DATATYPE_number; + args[0].number = (double)getListIndex(id); + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + args[1].type = IGGY_DATATYPE_string_UTF16; + args[1].string16 = stringVal; + + IggyPlayerCallMethodRS(m_parentScene->getMovie(), &result, + getIggyValuePath(), m_funcSetItemLabel, 2, args); +} + +void UIControl_MultiList::HighlightItem(int id, bool animate) +{ + IggyDataValue result; + IggyDataValue value[2]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = (double)getListIndex(id); + + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = animate ? 1 : 0; + + IggyPlayerCallMethodRS(m_parentScene->getMovie(), &result, + getIggyValuePath(), m_funcHighlightItem, 2, value); + + m_iCurrentSelection = id; +} + +void UIControl_MultiList::EnableItem(int id, bool bEnable, bool bImmediate) +{ + if (!bImmediate) + return; // deferred mode not implemented + + int listIndex = getListIndex(id); + if (listIndex < 0) + return; + + IggyDataValue result; + IggyDataValue value[2]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = (double)listIndex; + + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = bEnable ? 1 : 0; + + IggyPlayerCallMethodRS(m_parentScene->getMovie(), &result, + getIggyValuePath(), m_funcEnableItem, 2, value); +} + +bool UIControl_MultiList::CheckElementExists(int id) +{ + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = (double)id; + + IggyPlayerCallMethodRS(m_parentScene->getMovie(), &result, + getIggyValuePath(), m_funcCheckElementExists, 1, value); + + if (result.type == IGGY_DATATYPE_boolean) + return result.boolval != 0; + if (result.type == IGGY_DATATYPE_number) + return (int)result.number != 0; + return false; +} + +void UIControl_MultiList::SetTouchFocus(S32 iX, S32 iY, bool bRepeat) +{ + IggyDataValue result; + IggyDataValue value[3]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = iX; + value[1].type = IGGY_DATATYPE_number; + value[1].number = iY; + value[2].type = IGGY_DATATYPE_boolean; + value[2].boolval = bRepeat; + + IggyPlayerCallMethodRS(m_parentScene->getMovie(), &result, + getIggyValuePath(), m_funcSetTouchFocus, 3, value); +} diff --git a/Minecraft.Client/Common/UI/UIScene.cpp b/Minecraft.Client/Common/UI/UIScene.cpp index 49cf9c19..0d92176a 100644 --- a/Minecraft.Client/Common/UI/UIScene.cpp +++ b/Minecraft.Client/Common/UI/UIScene.cpp @@ -1,1509 +1,1532 @@ -#include "stdafx.h" -#include "UI.h" -#include "UIScene.h" -#include "UISplitScreenHelpers.h" - -#include "../../Lighting.h" -#include "../../LocalPlayer.h" -#include "../../ItemRenderer.h" -#include "../../../Minecraft.World/net.minecraft.world.item.h" -#include "UIScene_BookAndQuillMenu.h" - -UIScene::UIScene(int iPad, UILayer *parentLayer) -{ - m_parentLayer = parentLayer; - m_iPad = iPad; - swf = nullptr; - m_pItemRenderer = nullptr; - - bHasFocus = false; - m_hasTickedOnce = false; - m_bFocussedOnce = false; - m_bPanoramaUsesDefaultPlatformSkin = false; - m_bVisible = true; - m_bCanHandleInput = false; - m_bIsReloading = false; - - m_iFocusControl = -1; - m_iFocusChild = 0; - m_lastOpacity = 1.0f; - m_bUpdateOpacity = false; - - m_backScene = nullptr; - - m_cacheSlotRenders = false; - m_needsCacheRendered = true; - m_expectedCachedSlotCount = 0; - m_callbackUniqueId = 0; -} - -UIScene::~UIScene() -{ - if(m_bPanoramaUsesDefaultPlatformSkin) - { - ui.PopDefaultPlatformSkinForPanorama(); - m_bPanoramaUsesDefaultPlatformSkin = false; - } - - /* Destroy the Iggy player. */ - IggyPlayerDestroy( swf ); - - for(auto & it : m_registeredTextures) - { - ui.unregisterSubstitutionTexture( it.first, it.second ); - } - - if(m_callbackUniqueId != 0) - { - ui.UnregisterCallbackId(m_callbackUniqueId); - } - - if(m_pItemRenderer != nullptr) delete m_pItemRenderer; -} - -void UIScene::destroyMovie() -{ - if(m_bPanoramaUsesDefaultPlatformSkin) - { - ui.PopDefaultPlatformSkinForPanorama(); - m_bPanoramaUsesDefaultPlatformSkin = false; - } - - /* Destroy the Iggy player. */ - IggyPlayerDestroy( swf ); - swf = nullptr; - - // Clear out the controls collection (doesn't delete the controls, and they get re-setup later) - m_controls.clear(); - - // Clear out all the fast names for the current movie - m_fastNames.clear(); -} - -void UIScene::reloadMovie(bool force) -{ - if(!force && (stealsFocus() && (getSceneType() != eUIScene_FullscreenProgress && !bHasFocus))) return; - - m_bIsReloading = true; - if(swf) - { - if(m_bPanoramaUsesDefaultPlatformSkin) - { - ui.PopDefaultPlatformSkinForPanorama(); - m_bPanoramaUsesDefaultPlatformSkin = false; - } - - /* Destroy the Iggy player. */ - IggyPlayerDestroy( swf ); - - // Clear out the controls collection (doesn't delete the controls, and they get re-setup later) - m_controls.clear(); - - // Clear out all the fast names for the current movie - m_fastNames.clear(); - } - - // Reload everything - initialiseMovie(); - - handlePreReload(); - - // Reload controls - for(auto & it : m_controls) - { - it->ReInit(); - } - - updateComponents(); - handleReload(); - - IggyDataValue result; - IggyDataValue value[1]; - - value[0].type = IGGY_DATATYPE_number; - value[0].number = m_iFocusControl; - - IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetFocus , 1 , value ); - - m_needsCacheRendered = true; - m_bIsReloading = false; -} - -bool UIScene::needsReloaded() -{ - return !swf && (!stealsFocus() || bHasFocus); -} - -bool UIScene::hasMovie() -{ - return swf != nullptr; -} - -F64 UIScene::getSafeZoneHalfHeight() -{ - float height = ui.getScreenHeight(); - - float safeHeight = 0.0f; - -#ifndef __PSVITA__ - if( !RenderManager.IsHiDef() && RenderManager.IsWidescreen() ) - { - // 90% safezone - safeHeight = height * (0.15f / 2); - } - else - { - // 90% safezone - safeHeight = height * (0.1f / 2); - } -#endif - return safeHeight; -} - -F64 UIScene::getSafeZoneHalfWidth() -{ - float width = ui.getScreenWidth(); - - float safeWidth = 0.0f; -#ifndef __PSVITA__ - if( !RenderManager.IsHiDef() && RenderManager.IsWidescreen() ) - { - // 85% safezone - safeWidth = width * (0.15f / 2); - } - else - { - // 90% safezone - safeWidth = width * (0.1f / 2); - } -#endif - return safeWidth; -} - -void UIScene::updateSafeZone() -{ - // Distance from edge - F64 safeTop = 0.0; - F64 safeBottom = 0.0; - F64 safeLeft = 0.0; - F64 safeRight = 0.0; - - switch( m_parentLayer->getViewport() ) - { - case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: - safeTop = getSafeZoneHalfHeight(); - safeLeft = getSafeZoneHalfWidth(); - - break; - case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: - // safeTop mirrors SPLIT_TOP for visual symmetry. safeBottom omitted. - safeTop = getSafeZoneHalfHeight(); - safeLeft = getSafeZoneHalfWidth(); - - break; - case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: - safeTop = getSafeZoneHalfHeight(); - safeLeft = getSafeZoneHalfWidth(); - break; - case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: - safeTop = getSafeZoneHalfHeight(); - - break; - case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: - safeTop = getSafeZoneHalfHeight(); - safeLeft = getSafeZoneHalfWidth(); - break; - case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: - safeTop = getSafeZoneHalfHeight(); - - break; - case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: - safeTop = getSafeZoneHalfHeight(); - safeLeft = getSafeZoneHalfWidth(); - break; - case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: - safeTop = getSafeZoneHalfHeight(); - - break; - case C4JRender::VIEWPORT_TYPE_FULLSCREEN: - default: - safeTop = getSafeZoneHalfHeight(); - safeBottom = getSafeZoneHalfHeight(); - safeLeft = getSafeZoneHalfWidth(); - - break; - } - setSafeZone(safeTop, safeBottom, safeLeft, safeRight); -} - -void UIScene::setSafeZone(S32 safeTop, S32 safeBottom, S32 safeLeft, S32 safeRight) -{ - IggyDataValue result; - IggyDataValue value[4]; - - value[0].type = IGGY_DATATYPE_number; - value[0].number = safeTop; - value[1].type = IGGY_DATATYPE_number; - value[1].number = safeBottom; - value[2].type = IGGY_DATATYPE_number; - value[2].number = safeLeft; - value[3].type = IGGY_DATATYPE_number; - value[3].number = safeRight; - IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetSafeZone , 4 , value ); -} - -void UIScene::initialiseMovie() -{ - loadMovie(); - mapElementsAndNames(); - - updateSafeZone(); - - m_bUpdateOpacity = true; -} - -#if defined(__PSVITA__) || defined(_WINDOWS64) -void UIScene::SetFocusToElement(int iID) -{ - IggyDataValue result; - IggyDataValue value[1]; - - value[0].type = IGGY_DATATYPE_number; - value[0].number = iID; - - IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetFocus , 1 , value ); - - // also trigger handle focus change (just in case if anything else in relation needs updating!) - _handleFocusChange(iID, 0); -} -#endif - -bool UIScene::mapElementsAndNames() -{ - m_rootPath = IggyPlayerRootPath( swf ); - - m_funcRemoveObject = registerFastName( L"RemoveObject" ); - m_funcSlideLeft = registerFastName( L"SlideLeft" ); - m_funcSlideRight = registerFastName( L"SlideRight" ); - m_funcSetSafeZone = registerFastName( L"SetSafeZone" ); - m_funcSetAlpha = registerFastName( L"SetAlpha" ); - m_funcSetFocus = registerFastName( L"SetFocus" ); - m_funcHorizontalResizeCheck = registerFastName( L"DoHorizontalResizeCheck"); - return true; -} - -extern CRITICAL_SECTION s_loadSkinCS; -void UIScene::loadMovie() -{ - EnterCriticalSection(&UIController::ms_reloadSkinCS); // MGH - added to prevent crash loading Iggy movies while the skins were being reloaded - wstring moviePath = getMoviePath(); - -#ifdef _WINDOWS64 - const bool isPanoramaMovie = (moviePath == L"Panorama" || moviePath == L"PanoramaSplit"); - if(isPanoramaMovie) - { - ui.PushDefaultPlatformSkinForPanorama(); - m_bPanoramaUsesDefaultPlatformSkin = true; - } -#endif - -#ifdef __PS3__ - if(RenderManager.IsWidescreen()) - { - moviePath.append(L"720.swf"); - m_loadedResolution = eSceneResolution_720; - } - else - { - moviePath.append(L"480.swf"); - m_loadedResolution = eSceneResolution_480; - } -#elif defined __PSVITA__ - moviePath.append(L"Vita.swf"); - m_loadedResolution = eSceneResolution_Vita; -#elif defined _WINDOWS64 - int primaryPad = ProfileManager.GetPrimaryPad(); - if(primaryPad < 0 || primaryPad >= XUSER_MAX_COUNT) - primaryPad = 0; - const int controlType = app.GetGameSettings(primaryPad, eGameSetting_ControlType); - const bool force720ForControlType = (controlType == 3 || controlType == 5); - // tutorial popups + HUD elements have inaccuracies + crashes that we need to fix here - const bool isTutorialPopupMovie = (moviePath.find(L"TutorialPopup") == 0); - const bool isHUDMovie = (moviePath.find(L"HUD") == 0); - const bool use1080 = (ui.getScreenHeight() > 720.0f) && (!force720ForControlType || isTutorialPopupMovie); - if(use1080) - { - moviePath.append(L"1080.swf"); - m_loadedResolution = eSceneResolution_1080; - } - else - { - moviePath.append(L"720.swf"); - m_loadedResolution = eSceneResolution_720; - } -#else - moviePath.append(L"1080.swf"); - m_loadedResolution = eSceneResolution_1080; -#endif - - if(!app.hasArchiveFile(moviePath)) - { - app.DebugPrintf("WARNING: Could not find iggy movie %ls, trying other resolutions\n", moviePath.c_str()); - - // Try 720 first, then 1080 as final fallback - moviePath = getMoviePath(); - moviePath.append(L"720.swf"); - m_loadedResolution = eSceneResolution_720; - - if(!app.hasArchiveFile(moviePath)) - { - moviePath = getMoviePath(); - moviePath.append(L"1080.swf"); - m_loadedResolution = eSceneResolution_1080; - - if(!app.hasArchiveFile(moviePath)) - { - app.DebugPrintf("ERROR: Could not find any iggy movie for %ls!\n", moviePath.c_str()); -#ifndef _CONTENT_PACKAGE - DEBUG_BREAK(); -#endif - app.FatalLoadError(); - } - } - } - - byteArray baFile = ui.getMovieData(moviePath.c_str()); - int64_t beforeLoad = ui.iggyAllocCount; - swf = IggyPlayerCreateFromMemory ( baFile.data , baFile.length, nullptr); - int64_t afterLoad = ui.iggyAllocCount; - - if(!swf) - { - app.DebugPrintf("ERROR: Failed to load iggy scene!\n"); -#ifndef _CONTENT_PACKAGE - DEBUG_BREAK(); -#endif - app.FatalLoadError(); - } - - // Read movie dimensions from the SWF header (available immediately after - // CreateFromMemory, no init tick needed). - IggyProperties *properties = IggyPlayerProperties ( swf ); - if(!properties) - { - app.DebugPrintf("ERROR: IggyPlayerProperties returned null for scene '%ls'\n", moviePath.c_str()); -#ifndef _CONTENT_PACKAGE - __debugbreak(); -#endif - app.FatalLoadError(); - } - m_movieHeight = properties->movie_height_in_pixels; - m_movieWidth = properties->movie_width_in_pixels; - m_renderWidth = m_movieWidth; - m_renderHeight = m_movieHeight; - - // Set display size BEFORE the init tick to match what render() will use. - // InitializeAndTickRS runs ActionScript that creates text fields. If the - // display size here differs from what render() passes to SetDisplaySize, - // Iggy can cache glyph rasterizations at one scale during init and then - // reuse them at a different scale during draw, producing mixed glyph sizes. -#ifdef _WINDOWS64 - { - S32 fitW, fitH, fitOffX, fitOffY; - Fit16x9(ui.getScreenWidth(), ui.getScreenHeight(), fitW, fitH, fitOffX, fitOffY); - IggyPlayerSetDisplaySize( swf, fitW, fitH ); - } -#else - IggyPlayerSetDisplaySize( swf, m_movieWidth, m_movieHeight ); -#endif - - IggyPlayerInitializeAndTickRS ( swf ); - int64_t afterTick = ui.iggyAllocCount; - -#ifdef _WINDOWS64 - // Flush Iggy's internal font caches so all glyphs get rasterized fresh - // at the current display scale on the first Draw. Without this, stale - // cache entries from a previous scene (loaded at a different display size) - // cause mixed glyph sizes. ResizeD3D already calls this, which is why - // fonts look correct after a resize but break when a scene reloads - // without one. - IggyFlushInstalledFonts(); -#endif - - app.DebugPrintf( app.USER_SR, "Loaded iggy movie %ls\n", moviePath.c_str() ); - - IggyPlayerSetUserdata(swf,this); - -//#ifdef _DEBUG -#if 0 - IggyMemoryUseInfo memoryInfo; - rrbool res; - int iteration = 0; - int64_t totalStatic = 0; - int64_t totalDynamic = 0; - while(res = IggyDebugGetMemoryUseInfo ( swf , - nullptr , - 0 , - 0 , - iteration , - &memoryInfo )) - { - totalStatic += memoryInfo.static_allocation_bytes; - totalDynamic += memoryInfo.dynamic_allocation_bytes; - app.DebugPrintf(app.USER_SR, "%ls - %.*s static: %d ( %d ) dynamic: %d ( %d )\n", moviePath.c_str(), memoryInfo.subcategory_stringlen, memoryInfo.subcategory, - memoryInfo.static_allocation_bytes, memoryInfo.static_allocation_count, memoryInfo.dynamic_allocation_bytes, memoryInfo.dynamic_allocation_count); - ++iteration; - //if(memoryInfo.static_allocation_bytes > 0) getDebugMemoryUseRecursive(moviePath, memoryInfo); - - } - - app.DebugPrintf(app.USER_SR, "%ls - Total: %d, Expected: %d, Diff: %d\n", moviePath.c_str(), totalStatic + totalDynamic, afterTick - beforeLoad, (afterTick - beforeLoad) - (totalStatic + totalDynamic)); - -#endif - LeaveCriticalSection(&UIController::ms_reloadSkinCS); - -} - -void UIScene::getDebugMemoryUseRecursive(const wstring &moviePath, IggyMemoryUseInfo &memoryInfo) -{ - rrbool res; - IggyMemoryUseInfo internalMemoryInfo; - int internalIteration = 0; - while (res = IggyDebugGetMemoryUseInfo(swf, - 0, - memoryInfo.subcategory, - memoryInfo.subcategory_stringlen, - internalIteration, - &internalMemoryInfo)) - { - app.DebugPrintf(app.USER_SR, "%ls - %.*s static: %d ( %d ) dynamic: %d ( %d )\n", moviePath.c_str(), internalMemoryInfo.subcategory_stringlen, internalMemoryInfo.subcategory, - internalMemoryInfo.static_allocation_bytes, internalMemoryInfo.static_allocation_count, internalMemoryInfo.dynamic_allocation_bytes, internalMemoryInfo.dynamic_allocation_count); - ++internalIteration; - if (internalMemoryInfo.subcategory_stringlen > memoryInfo.subcategory_stringlen) - getDebugMemoryUseRecursive(moviePath, internalMemoryInfo); - } -} - -void UIScene::PrintTotalMemoryUsage(int64_t &totalStatic, int64_t &totalDynamic) -{ - if(!swf) return; - - IggyMemoryUseInfo memoryInfo; - rrbool res; - int iteration = 0; - int64_t sceneStatic = 0; - int64_t sceneDynamic = 0; - while(res = IggyDebugGetMemoryUseInfo ( swf , - 0 , - "" , - 0 , - iteration , - &memoryInfo )) - { - sceneStatic += memoryInfo.static_allocation_bytes; - sceneDynamic += memoryInfo.dynamic_allocation_bytes; - totalStatic += memoryInfo.static_allocation_bytes; - totalDynamic += memoryInfo.dynamic_allocation_bytes; - ++iteration; - - } - - app.DebugPrintf(app.USER_SR, " \\- Scene static: %d , Scene dynamic: %d , Total: %d - %ls\n", sceneStatic, sceneDynamic, sceneStatic + sceneDynamic, getMoviePath().c_str()); -} - -void UIScene::tick() -{ - if(m_bIsReloading) return; - if(m_hasTickedOnce) m_bCanHandleInput = true; - while(IggyPlayerReadyToTick( swf )) - { - tickTimers(); - for(auto & it : m_controls) - { - it->tick(); - } - IggyPlayerTickRS( swf ); - m_hasTickedOnce = true; - } - -#ifdef _WINDOWS64 - { - vector inputs; - getDirectEditInputs(inputs); - for (size_t i = 0; i < inputs.size(); i++) - { - UIControl_TextInput::EDirectEditResult result = inputs[i]->tickDirectEdit(); - if (result != UIControl_TextInput::eDirectEdit_Continue) - onDirectEditFinished(inputs[i], result); - } - //Attempt at matching input code for textinputs for labels - vector labels; - getDirectEditLabels(labels); - for (size_t i = 0; i < labels.size(); i++) - { - //app.DebugPrintf(("label; " + std::to_string(i) + "\n").c_str()); - UIControl_Label::EDirectEditResult result1 = labels[i]->tickDirectEdit(); - //app.DebugPrintf(("result; " + std::to_string(result1) + "\n").c_str()); - if (result1 != UIControl_Label::eDirectEdit_Continue) - onDirectEditLabelFinished(labels[i], result1); - } - } -#endif -} - -UIControl* UIScene::GetMainPanel() -{ - return nullptr; -} - -#ifdef _WINDOWS64 -bool UIScene::isDirectEditBlocking() -{ - vector inputs; - getDirectEditInputs(inputs); - for (size_t i = 0; i < inputs.size(); i++) - { - if (inputs[i]->isDirectEditing() || inputs[i]->getDirectEditCooldown() > 0) - return true; - } - return false; -} - -bool UIScene::handleMouseClick(F32 x, F32 y) -{ - S32 panelOffsetX = 0, panelOffsetY = 0; - UIControl *pMainPanel = GetMainPanel(); - if (pMainPanel) - { - pMainPanel->UpdateControl(); - panelOffsetX = pMainPanel->getXPos(); - panelOffsetY = pMainPanel->getYPos(); - } - - // Click-outside-to-deselect: confirm any active direct edit if - // the click landed outside the editing text input. - { - vector deInputs; - getDirectEditInputs(deInputs); - for (size_t i = 0; i < deInputs.size(); i++) - { - if (!deInputs[i]->isDirectEditing()) - continue; - deInputs[i]->UpdateControl(); - S32 cx = deInputs[i]->getXPos() + panelOffsetX; - S32 cy = deInputs[i]->getYPos() + panelOffsetY; - S32 cw = deInputs[i]->getWidth(); - S32 ch = deInputs[i]->getHeight(); - if (!(cw > 0 && ch > 0 && x >= cx && x <= cx + cw && y >= cy && y <= cy + ch)) - { - deInputs[i]->confirmDirectEdit(); - onDirectEditFinished(deInputs[i], UIControl_TextInput::eDirectEdit_Confirmed); - } - } - } - - vector *controls = GetControls(); - if (!controls) return false; - - // Hit-test controls and pick the smallest-area match to handle - // overlapping Flash bounds correctly without sacrificing precision. - int bestId = -1; - S32 bestArea = INT_MAX; - UIControl *bestCtrl = NULL; - - for (size_t i = 0; i < controls->size(); ++i) - { - UIControl *ctrl = (*controls)[i]; - if (!ctrl || ctrl->getHidden() || !ctrl->getVisible() || ctrl->getId() < 0) - continue; - - UIControl::eUIControlType type = ctrl->getControlType(); - if (type != UIControl::eButton && type != UIControl::eTextInput && - type != UIControl::eCheckBox && type != UIControl::eBook && type != UIControl::ePageFlip) - continue; - - if (pMainPanel && ctrl->getParentPanel() != pMainPanel) - continue; - - ctrl->UpdateControl(); - S32 cx = ctrl->getXPos() + panelOffsetX; - S32 cy = ctrl->getYPos() + panelOffsetY; - S32 cw = ctrl->getWidth(); - S32 ch = ctrl->getHeight(); - if (cw <= 0 || ch <= 0) - continue; - - if (x >= cx && x <= cx + cw && y >= cy && y <= cy + ch) - { - S32 area = cw * ch; - if (area < bestArea) - { - bestArea = area; - bestId = ctrl->getId(); - bestCtrl = ctrl; - } - } - } - - if (bestId >= 0 && bestCtrl) - { - if (bestCtrl->getControlType() == UIControl::eCheckBox) - { - UIControl_CheckBox *cb = static_cast(bestCtrl); - if (cb->IsEnabled()) - { - bool newState = !cb->IsChecked(); - cb->setChecked(newState); - handleCheckboxToggled((F64)bestId, newState); - } - } - else - { - handlePress((F64)bestId, 0); - } - return true; - } - return false; -} -#endif - -void UIScene::addTimer(int id, int ms) -{ - int currentTime = System::currentTimeMillis(); - - TimerInfo info; - info.running = true; - info.duration = ms; - info.targetTime = currentTime + ms; - m_timers[id] = info; -} - -void UIScene::killTimer(int id) -{ - auto it = m_timers.find(id); - if(it != m_timers.end()) - { - it->second.running = false; - } -} - -void UIScene::tickTimers() -{ - int currentTime = System::currentTimeMillis(); - for (auto it = m_timers.begin(); it != m_timers.end();) - { - if(!it->second.running) - { - it = m_timers.erase(it); - } - else - { - if(currentTime > it->second.targetTime) - { - handleTimerComplete(it->first); - - // Auto-restart - it->second.targetTime = it->second.duration + currentTime; - } - ++it; - } - } -} - -IggyName UIScene::registerFastName(const wstring &name) -{ - IggyName var; - auto it = m_fastNames.find(name); - if(it != m_fastNames.end()) - { - var = it->second; - } - else - { - var = IggyPlayerCreateFastName ( getMovie() , (IggyUTF16 *)name.c_str() , -1 ); - m_fastNames[name] = var; - } - return var; -} - -void UIScene::removeControl( UIControl_Base *control, bool centreScene) -{ - IggyDataValue result; - IggyDataValue value[2]; - - string name = control->getControlName(); - IggyStringUTF8 stringVal; - stringVal.string = (char*)name.c_str(); - stringVal.length = name.length(); - value[0].type = IGGY_DATATYPE_string_UTF8; - value[0].string8 = stringVal; - - value[1].type = IGGY_DATATYPE_boolean; - value[1].boolval = centreScene; - IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcRemoveObject , 2 , value ); - -#ifdef __PSVITA__ - // update the button positions since they may have changed - UpdateSceneControls(); - - // remove it from the touchboxes - ui.TouchBoxRebuild(control->getParentScene()); -#endif - - // mark the button as removed so hover/touch hit-tests skip it - control->setHidden(true); - -} - -void UIScene::slideLeft() -{ - IggyDataValue result; - IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSlideLeft , 0 , nullptr ); -} - -void UIScene::slideRight() -{ - IggyDataValue result; - IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSlideRight , 0 , nullptr ); -} - -void UIScene::doHorizontalResizeCheck() -{ - IggyDataValue result; - IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcHorizontalResizeCheck , 0 , nullptr ); -} - -void UIScene::render(S32 width, S32 height, C4JRender::eViewportType viewport) -{ - if(m_bIsReloading) return; - if(!m_hasTickedOnce || !swf) return; - - if(viewport != C4JRender::VIEWPORT_TYPE_FULLSCREEN) - { - F32 originX, originY, viewW, viewH; - GetViewportRect(ui.getScreenWidth(), ui.getScreenHeight(), viewport, originX, originY, viewW, viewH); - S32 fitW, fitH, offsetX, offsetY; - Fit16x9(viewW, viewH, fitW, fitH, offsetX, offsetY); - ui.setupRenderPosition(static_cast(originX) + offsetX, static_cast(originY) + offsetY); - IggyPlayerSetDisplaySize( swf, fitW, fitH ); - IggyPlayerDraw( swf ); - } - else - { - ui.setupRenderPosition(viewport); - IggyPlayerSetDisplaySize( swf, width, height ); - IggyPlayerDraw( swf ); - } -} - -void UIScene::setOpacity(float percent) -{ - if(percent != m_lastOpacity || (m_bUpdateOpacity && getMovie())) - { - m_lastOpacity = percent; - - // 4J-TomK once a scene has been freshly loaded or re-loaded we force update opacity via initialiseMovie - if(m_bUpdateOpacity) - m_bUpdateOpacity = false; - - IggyDataValue result; - IggyDataValue value[1]; - value[0].type = IGGY_DATATYPE_number; - value[0].number = percent; - - IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetAlpha , 1 , value ); - } -} - -void UIScene::setVisible(bool visible) -{ - m_bVisible = visible; -} - -void UIScene::customDraw(IggyCustomDrawCallbackRegion *region) -{ - //app.DebugPrintf("Handling custom draw for scene with no override!\n"); -} - -void UIScene::customDrawSlotControl(IggyCustomDrawCallbackRegion *region, int iPad, shared_ptr item, float fAlpha, bool isFoil, bool bDecorations) -{ - if (item!= nullptr) - { - if(m_cacheSlotRenders) - { - if( (m_cachedSlotDraw.size() + 1) == m_expectedCachedSlotCount) - { - //Make sure that pMinecraft->player is the correct player so that player specific rendering - // eg clock and compass, are rendered correctly - Minecraft *pMinecraft=Minecraft::GetInstance(); - shared_ptr oldPlayer = pMinecraft->player; - if( iPad >= 0 && iPad < XUSER_MAX_COUNT ) pMinecraft->player = pMinecraft->localplayers[iPad]; - - // Setup GDraw, normal game render states and matrices - //CustomDrawData *customDrawRegion = ui.setupCustomDraw(this,region); - PIXBeginNamedEvent(0,"Starting Iggy custom draw\n"); - CustomDrawData *customDrawRegion = ui.calculateCustomDraw(region); - ui.beginIggyCustomDraw4J(region, customDrawRegion); - ui.setupCustomDrawGameState(); - - int list = m_parentLayer->m_parentGroup->getCommandBufferList(); - - bool useCommandBuffers = false; -#ifdef _XBOX_ONE - useCommandBuffers = true; - - // 4J Stu - Temporary until we fix the glint animation which needs updated if we are just replaying a command buffer - m_needsCacheRendered = true; -#endif - - if(!useCommandBuffers || m_needsCacheRendered) - { -#if (!defined __PS3__) && (!defined __PSVITA__) - if(useCommandBuffers) RenderManager.CBuffStart(list, true); -#endif - PIXBeginNamedEvent(0,"Draw uncached"); - ui.setupCustomDrawMatrices(this, customDrawRegion); - _customDrawSlotControl(customDrawRegion, iPad, item, fAlpha, isFoil, bDecorations, useCommandBuffers); - delete customDrawRegion; - PIXEndNamedEvent(); - - PIXBeginNamedEvent(0,"Draw all cache"); - // Draw all the cached slots - for(auto& drawData : m_cachedSlotDraw) - { - ui.setupCustomDrawMatrices(this, drawData->customDrawRegion); - _customDrawSlotControl(drawData->customDrawRegion, iPad, drawData->item, drawData->fAlpha, drawData->isFoil, drawData->bDecorations, useCommandBuffers); - delete drawData->customDrawRegion; - delete drawData; - } - PIXEndNamedEvent(); -#ifndef __PS3__ - if(useCommandBuffers) RenderManager.CBuffEnd(); -#endif - } - m_cachedSlotDraw.clear(); - -#ifndef __PS3__ - if(useCommandBuffers) RenderManager.CBuffCall(list); -#endif - - // Finish GDraw and anything else that needs to be finalised - ui.endCustomDraw(region); - - pMinecraft->player = oldPlayer; - } - else - { - PIXBeginNamedEvent(0,"Caching region"); - CachedSlotDrawData *drawData = new CachedSlotDrawData(); - drawData->item = item; - drawData->fAlpha = fAlpha; - drawData->isFoil = isFoil; - drawData->bDecorations = bDecorations; - drawData->customDrawRegion = ui.calculateCustomDraw(region); - - m_cachedSlotDraw.push_back(drawData); - PIXEndNamedEvent(); - } - } - else - { - // Setup GDraw, normal game render states and matrices - CustomDrawData *customDrawRegion = ui.setupCustomDraw(this,region); - - Minecraft *pMinecraft=Minecraft::GetInstance(); - - //Make sure that pMinecraft->player is the correct player so that player specific rendering - // eg clock and compass, are rendered correctly - shared_ptr oldPlayer = pMinecraft->player; - if( iPad >= 0 && iPad < XUSER_MAX_COUNT ) pMinecraft->player = pMinecraft->localplayers[iPad]; - - _customDrawSlotControl(customDrawRegion, iPad, item, fAlpha, isFoil, bDecorations, false); - delete customDrawRegion; - pMinecraft->player = oldPlayer; - - // Finish GDraw and anything else that needs to be finalised - ui.endCustomDraw(region); - } - } -} - -void UIScene::_customDrawSlotControl(CustomDrawData *region, int iPad, shared_ptr item, float fAlpha, bool isFoil, bool bDecorations, bool usingCommandBuffer) -{ - Minecraft *pMinecraft=Minecraft::GetInstance(); - - float bwidth,bheight; - bwidth = region->x1 - region->x0; - bheight = region->y1 - region->y0; - - float x = region->x0; - float y = region->y0; - - // Base scale on height of this control, compared to height of what the item renderer normally renders (16 pixels high). Potentially - // we might want separate x & y scales here - - float scaleX = bwidth / 16.0f; - float scaleY = bheight / 16.0f; - - glEnable(GL_RESCALE_NORMAL); - glPushMatrix(); - glRotatef(120, 1, 0, 0); - Lighting::turnOn(); - glPopMatrix(); - - float pop = item->popTime; - if (pop > 0) - { - glPushMatrix(); - float squeeze = 1 + pop / static_cast(Inventory::POP_TIME_DURATION); - float sx = x; - float sy = y; - float sxoffs = 8 * scaleX; - float syoffs = 12 * scaleY; - glTranslatef((float)(sx + sxoffs), (float)(sy + syoffs), 0); - glScalef(1 / squeeze, (squeeze + 1) / 2, 1); - glTranslatef((float)-(sx + sxoffs), (float)-(sy + syoffs), 0); - } - - PIXBeginNamedEvent(0,"Render and decorate"); - if(m_pItemRenderer == nullptr) m_pItemRenderer = new ItemRenderer(); - RenderManager.StateSetBlendEnable(true); - RenderManager.StateSetBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - RenderManager.StateSetBlendFactor(0xffffffff); - m_pItemRenderer->renderAndDecorateItem(pMinecraft->font, pMinecraft->textures, item, x, y,scaleX,scaleY,fAlpha,isFoil,false, !usingCommandBuffer); - PIXEndNamedEvent(); - - if (pop > 0) - { - glPopMatrix(); - } - - if(bDecorations) - { - if((scaleX!=1.0f) ||(scaleY!=1.0f)) - { - glPushMatrix(); - glScalef(scaleX, scaleY, 1.0f); - int iX= static_cast(0.5f + ((float)x) / scaleX); - int iY= static_cast(0.5f + ((float)y) / scaleY); - - m_pItemRenderer->renderGuiItemDecorations(pMinecraft->font, pMinecraft->textures, item, iX, iY, fAlpha); - glPopMatrix(); - } - else - { - m_pItemRenderer->renderGuiItemDecorations(pMinecraft->font, pMinecraft->textures, item, static_cast(x), static_cast(y), fAlpha); - } - } - - Lighting::turnOff(); - glDisable(GL_RESCALE_NORMAL); -} - -// 4J Stu - Not threadsafe -//void UIScene::navigateForward(int iPad, EUIScene scene, void *initData) -//{ -// if(m_parentLayer == nullptr) -// { -// app.DebugPrintf("A scene is trying to navigate forwards, but it's parent layer is nullptr!\n"); -// } -// else -// { -// m_parentLayer->NavigateToScene(iPad,scene,initData); -// } -//} - -void UIScene::navigateBack() -{ - //CD - Added for audio - ui.PlayUISFX(eSFX_Back); - - ui.NavigateBack(m_iPad); - - if(m_parentLayer == nullptr) - { - } - else - { -// m_parentLayer->removeScene(this); - -#ifdef _DURANGO - if (ui.GetTopScene(0)) - InputManager.SetEnabledGtcButtons( ui.GetTopScene(0)->getDefaultGtcButtons() ); -#endif - } - -} - -void UIScene::gainFocus() -{ - if( !bHasFocus && stealsFocus() ) - { - // 4J Stu - Don't do this - /* - IggyEvent event; - IggyMakeEventFocusGained( &event , 0); - - IggyEventResult result; - IggyPlayerDispatchEventRS( getMovie() , &event , &result ); - - app.DebugPrintf("Sent gain focus event to scene\n"); - */ - bHasFocus = true; - if(needsReloaded()) - { - reloadMovie(); - } - - updateTooltips(); - updateComponents(); - - if(!m_bFocussedOnce) - { - IggyDataValue result; - IggyDataValue value[1]; - - value[0].type = IGGY_DATATYPE_number; - value[0].number = -1; - - IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetFocus , 1 , value ); - } - - handleGainFocus(m_bFocussedOnce); - if(bHasFocus) m_bFocussedOnce = true; - } - else if(bHasFocus && stealsFocus()) - { - updateTooltips(); - } -} - -void UIScene::loseFocus() -{ - if(bHasFocus) - { - // 4J Stu - Don't do this - /* - IggyEvent event; - IggyMakeEventFocusLost( &event ); - IggyEventResult result; - IggyPlayerDispatchEventRS ( getMovie() , &event , &result ); - */ - - app.DebugPrintf("Sent lose focus event to scene\n"); - bHasFocus = false; - handleLoseFocus(); - } -} - -void UIScene::handleGainFocus(bool navBack) -{ -#ifdef _DURANGO - InputManager.SetEnabledGtcButtons( this->getDefaultGtcButtons() ); -#endif -} - -void UIScene::updateTooltips() -{ - if(!ui.IsReloadingSkin()) - ui.SetTooltips(m_iPad, -1); -} - -void UIScene::sendInputToMovie(int key, bool repeat, bool pressed, bool released) -{ - if(!swf) return; - - int iggyKeyCode = convertGameActionToIggyKeycode(key); - - if(iggyKeyCode < 0) - { - app.DebugPrintf("UI WARNING: Ignoring input as game action does not translate to an Iggy keycode\n"); - return; - } - -#ifdef _WINDOWS64 - // If a navigation key is pressed with no focused element, focus the first - // available one so arrow keys work even when the mouse is over empty space. - if(pressed && (iggyKeyCode == IGGY_KEYCODE_UP || iggyKeyCode == IGGY_KEYCODE_DOWN || - iggyKeyCode == IGGY_KEYCODE_LEFT || iggyKeyCode == IGGY_KEYCODE_RIGHT)) - { - IggyFocusHandle currentFocus = IGGY_FOCUS_NULL; - IggyFocusableObject focusables[64]; - S32 numFocusables = 0; - IggyPlayerGetFocusableObjects(swf, ¤tFocus, focusables, 64, &numFocusables); - if(currentFocus == IGGY_FOCUS_NULL && numFocusables > 0) - { - IggyPlayerSetFocusRS(swf, focusables[0].object, 0); - return; - } - } -#endif - - IggyEvent keyEvent; - // 4J Stu - Keyloc is always standard as we don't care about shift/alt - IggyMakeEventKey( &keyEvent, pressed?IGGY_KEYEVENT_Down:IGGY_KEYEVENT_Up, static_cast(iggyKeyCode), IGGY_KEYLOC_Standard ); - - IggyEventResult result; - IggyPlayerDispatchEventRS ( swf , &keyEvent , &result ); -} - -int UIScene::convertGameActionToIggyKeycode(int action) -{ - // TODO: This action to key mapping should probably use the control mapping - int keycode = -1; - switch(action) - { -#ifdef __ORBIS__ - case ACTION_MENU_TOUCHPAD_PRESS: -#endif - case ACTION_MENU_A: - keycode = IGGY_KEYCODE_ENTER; - break; - case ACTION_MENU_B: - keycode = IGGY_KEYCODE_ESCAPE; - break; - case ACTION_MENU_X: - keycode = IGGY_KEYCODE_F1; - break; - case ACTION_MENU_Y: - keycode = IGGY_KEYCODE_F2; - break; - case ACTION_MENU_OK: - keycode = IGGY_KEYCODE_ENTER; - break; - case ACTION_MENU_CANCEL: - keycode = IGGY_KEYCODE_ESCAPE; - break; - case ACTION_MENU_UP: - keycode = IGGY_KEYCODE_UP; - break; - case ACTION_MENU_DOWN: - keycode = IGGY_KEYCODE_DOWN; - break; - case ACTION_MENU_RIGHT: - keycode = IGGY_KEYCODE_RIGHT; - break; - case ACTION_MENU_LEFT: - keycode = IGGY_KEYCODE_LEFT; - break; - case ACTION_MENU_PAGEUP: - keycode = IGGY_KEYCODE_PAGE_UP; - break; - case ACTION_MENU_PAGEDOWN: -#ifdef __PSVITA__ - if (!InputManager.IsVitaTV()) - { - keycode = IGGY_KEYCODE_F6; - } - else -#endif - { - keycode = IGGY_KEYCODE_PAGE_DOWN; - } - break; - case ACTION_MENU_RIGHT_SCROLL: - keycode = IGGY_KEYCODE_F3; - break; - case ACTION_MENU_LEFT_SCROLL: - keycode = IGGY_KEYCODE_F4; - break; - case ACTION_MENU_STICK_PRESS: - break; - case ACTION_MENU_OTHER_STICK_PRESS: - keycode = IGGY_KEYCODE_F5; - break; - case ACTION_MENU_OTHER_STICK_UP: - keycode = IGGY_KEYCODE_F11; - break; - case ACTION_MENU_OTHER_STICK_DOWN: - keycode = IGGY_KEYCODE_F12; - break; - case ACTION_MENU_OTHER_STICK_LEFT: - break; - case ACTION_MENU_OTHER_STICK_RIGHT: - break; - }; - - return keycode; -} - -bool UIScene::allowRepeat(int key) -{ - // 4J-PB - ignore repeats of action ABXY buttons - // fix for PS3 213 - [MAIN MENU] Holding down buttons will continue to activate every prompt. - switch(key) - { - case ACTION_MENU_OK: - case ACTION_MENU_CANCEL: - case ACTION_MENU_A: - case ACTION_MENU_B: - case ACTION_MENU_X: - case ACTION_MENU_Y: - return false; - } - return true; -} - -void UIScene::externalCallback(IggyExternalFunctionCallUTF16 * call) -{ - if(wcscmp((wchar_t *)call->function_name.string,L"handlePress")==0) - { - if(call->num_arguments != 2) - { - app.DebugPrintf("Callback for handlePress did not have the correct number of arguments\n"); -#ifndef _CONTENT_PACKAGE - DEBUG_BREAK(); -#endif - return; - } - if(call->arguments[0].type != IGGY_DATATYPE_number || call->arguments[1].type != IGGY_DATATYPE_number) - { - app.DebugPrintf("Arguments for handlePress were not of the correct type\n"); -#ifndef _CONTENT_PACKAGE - DEBUG_BREAK(); -#endif - return; - } - handlePress(call->arguments[0].number, call->arguments[1].number); - } - else if(wcscmp((wchar_t *)call->function_name.string,L"handleFocusChange")==0) - { - if(call->num_arguments != 2) - { - app.DebugPrintf("Callback for handleFocusChange did not have the correct number of arguments\n"); -#ifndef _CONTENT_PACKAGE - DEBUG_BREAK(); -#endif - return; - } - if(call->arguments[0].type != IGGY_DATATYPE_number || call->arguments[1].type != IGGY_DATATYPE_number) - { - app.DebugPrintf("Arguments for handleFocusChange were not of the correct type\n"); -#ifndef _CONTENT_PACKAGE - DEBUG_BREAK(); -#endif - return; - } - _handleFocusChange(call->arguments[0].number, call->arguments[1].number); - } - else if(wcscmp((wchar_t *)call->function_name.string,L"handleInitFocus")==0) - { - if(call->num_arguments != 2) - { - app.DebugPrintf("Callback for handleInitFocus did not have the correct number of arguments\n"); -#ifndef _CONTENT_PACKAGE - DEBUG_BREAK(); -#endif - return; - } - if(call->arguments[0].type != IGGY_DATATYPE_number || call->arguments[1].type != IGGY_DATATYPE_number) - { - app.DebugPrintf("Arguments for handleInitFocus were not of the correct type\n"); -#ifndef _CONTENT_PACKAGE - DEBUG_BREAK(); -#endif - return; - } - _handleInitFocus(call->arguments[0].number, call->arguments[1].number); - } - else if(wcscmp((wchar_t *)call->function_name.string,L"handleCheckboxToggled")==0) - { - if(call->num_arguments != 2) - { - app.DebugPrintf("Callback for handleCheckboxToggled did not have the correct number of arguments\n"); -#ifndef _CONTENT_PACKAGE - DEBUG_BREAK(); -#endif - return; - } - if(call->arguments[0].type != IGGY_DATATYPE_number || call->arguments[1].type != IGGY_DATATYPE_boolean) - { - app.DebugPrintf("Arguments for handleCheckboxToggled were not of the correct type\n"); -#ifndef _CONTENT_PACKAGE - DEBUG_BREAK(); -#endif - return; - } - handleCheckboxToggled(call->arguments[0].number, call->arguments[1].boolval); - } - else if(wcscmp((wchar_t *)call->function_name.string,L"handleSliderMove")==0) - { - if(call->num_arguments != 2) - { - app.DebugPrintf("Callback for handleSliderMove did not have the correct number of arguments\n"); -#ifndef _CONTENT_PACKAGE - DEBUG_BREAK(); -#endif - return; - } - if(call->arguments[0].type != IGGY_DATATYPE_number || call->arguments[1].type != IGGY_DATATYPE_number) - { - app.DebugPrintf("Arguments for handleSliderMove were not of the correct type\n"); -#ifndef _CONTENT_PACKAGE - DEBUG_BREAK(); -#endif - return; - } - handleSliderMove(call->arguments[0].number, call->arguments[1].number); - } - else if(wcscmp((wchar_t *)call->function_name.string,L"handleAnimationEnd")==0) - { - if(call->num_arguments != 0) - { - app.DebugPrintf("Callback for handleAnimationEnd did not have the correct number of arguments\n"); -#ifndef _CONTENT_PACKAGE - DEBUG_BREAK(); -#endif - return; - } - handleAnimationEnd(); - } - else if(wcscmp((wchar_t *)call->function_name.string,L"handleSelectionChanged")==0) - { - if(call->num_arguments != 1) - { - app.DebugPrintf("Callback for handleSelectionChanged did not have the correct number of arguments\n"); -#ifndef _CONTENT_PACKAGE - DEBUG_BREAK(); -#endif - return; - } - if(call->arguments[0].type != IGGY_DATATYPE_number) - { - app.DebugPrintf("Arguments for handleSelectionChanged were not of the correct type\n"); -#ifndef _CONTENT_PACKAGE - DEBUG_BREAK(); -#endif - return; - } - handleSelectionChanged(call->arguments[0].number); - } - else if(wcscmp((wchar_t *)call->function_name.string,L"handleRequestMoreData")==0) - { - if(call->num_arguments == 0) - { - handleRequestMoreData(0,false); - } - else - { - if(call->num_arguments != 2) - { - app.DebugPrintf("Callback for handleRequestMoreData did not have the correct number of arguments\n"); -#ifndef _CONTENT_PACKAGE - DEBUG_BREAK(); -#endif - return; - } - if(call->arguments[0].type != IGGY_DATATYPE_number || call->arguments[1].type != IGGY_DATATYPE_boolean) - { - app.DebugPrintf("Arguments for handleRequestMoreData were not of the correct type\n"); -#ifndef _CONTENT_PACKAGE - DEBUG_BREAK(); -#endif - return; - } - handleRequestMoreData(call->arguments[0].number, call->arguments[1].boolval); - } - } - else if(wcscmp((wchar_t *)call->function_name.string,L"handleTouchBoxRebuild")==0) - { - handleTouchBoxRebuild(); - } - else - { - app.DebugPrintf("Unhandled callback: %s\n", call->function_name.string); - } -} - -void UIScene::registerSubstitutionTexture(const wstring &textureName, PBYTE pbData, DWORD dwLength, bool deleteData) -{ - m_registeredTextures[textureName] = deleteData;; - ui.registerSubstitutionTexture(textureName, pbData, dwLength); -} - -bool UIScene::hasRegisteredSubstitutionTexture(const wstring &textureName) -{ - auto it = m_registeredTextures.find(textureName); - - return it != m_registeredTextures.end(); -} - -void UIScene::_handleFocusChange(F64 controlId, F64 childId) -{ - int newControl = static_cast(controlId); - int newChild = static_cast(childId); - if (newControl != m_iFocusControl || newChild != m_iFocusChild) - { - m_iFocusControl = newControl; - m_iFocusChild = newChild; - - handleFocusChange(controlId, childId); - ui.PlayUISFX(eSFX_Focus); - } -} - -void UIScene::_handleInitFocus(F64 controlId, F64 childId) -{ - m_iFocusControl = static_cast(controlId); - m_iFocusChild = static_cast(childId); - - //handleInitFocus(controlId, childId); - handleFocusChange(controlId, childId); -} - -bool UIScene::controlHasFocus(int iControlId) -{ - return m_iFocusControl == iControlId; -} - -bool UIScene::controlHasFocus(UIControl_Base *control) -{ - return controlHasFocus( control->getId() ); -} - -int UIScene::getControlChildFocus() -{ - return m_iFocusChild; -} - -int UIScene::getControlFocus() -{ - return m_iFocusControl; -} - -void UIScene::setBackScene(UIScene *scene) -{ - m_backScene = scene; -} - -UIScene *UIScene::getBackScene() -{ - return m_backScene; -} -#ifdef __PSVITA__ -void UIScene::UpdateSceneControls() -{ - for ( UIControl *control : *GetControls() ) - { - control->UpdateControl(); - } -} -#endif - -void UIScene::HandleMessage(EUIMessage message, void *data) -{ -} - -size_t UIScene::GetCallbackUniqueId() -{ - if( m_callbackUniqueId == 0) - { - m_callbackUniqueId = ui.RegisterForCallbackId(this); - } - return m_callbackUniqueId; -} - -bool UIScene::isReadyToDelete() -{ - return true; -} +#include "stdafx.h" +#include "UI.h" +#include "UIScene.h" +#include "UISplitScreenHelpers.h" + +#include "../../Lighting.h" +#include "../../LocalPlayer.h" +#include "../../ItemRenderer.h" +#include "../../../Minecraft.World/net.minecraft.world.item.h" +#include "UIScene_BookAndQuillMenu.h" + +UIScene::UIScene(int iPad, UILayer *parentLayer) +{ + m_parentLayer = parentLayer; + m_iPad = iPad; + swf = nullptr; + m_pItemRenderer = nullptr; + + bHasFocus = false; + m_hasTickedOnce = false; + m_bFocussedOnce = false; + m_bPanoramaUsesDefaultPlatformSkin = false; + m_bVisible = true; + m_bCanHandleInput = false; + m_bIsReloading = false; + + m_iFocusControl = -1; + m_iFocusChild = 0; + m_lastOpacity = 1.0f; + m_bUpdateOpacity = false; + + m_backScene = nullptr; + + m_cacheSlotRenders = false; + m_needsCacheRendered = true; + m_expectedCachedSlotCount = 0; + m_callbackUniqueId = 0; +} + +UIScene::~UIScene() +{ + if(m_bPanoramaUsesDefaultPlatformSkin) + { + ui.PopDefaultPlatformSkinForPanorama(); + m_bPanoramaUsesDefaultPlatformSkin = false; + } + + /* Destroy the Iggy player. */ + IggyPlayerDestroy( swf ); + + for(auto & it : m_registeredTextures) + { + ui.unregisterSubstitutionTexture( it.first, it.second ); + } + + if(m_callbackUniqueId != 0) + { + ui.UnregisterCallbackId(m_callbackUniqueId); + } + + if(m_pItemRenderer != nullptr) delete m_pItemRenderer; +} + +void UIScene::destroyMovie() +{ + if(m_bPanoramaUsesDefaultPlatformSkin) + { + ui.PopDefaultPlatformSkinForPanorama(); + m_bPanoramaUsesDefaultPlatformSkin = false; + } + + /* Destroy the Iggy player. */ + IggyPlayerDestroy( swf ); + swf = nullptr; + + // Clear out the controls collection (doesn't delete the controls, and they get re-setup later) + m_controls.clear(); + + // Clear out all the fast names for the current movie + m_fastNames.clear(); +} + +void UIScene::reloadMovie(bool force) +{ + if(!force && (stealsFocus() && (getSceneType() != eUIScene_FullscreenProgress && !bHasFocus))) return; + + m_bIsReloading = true; + if(swf) + { + if(m_bPanoramaUsesDefaultPlatformSkin) + { + ui.PopDefaultPlatformSkinForPanorama(); + m_bPanoramaUsesDefaultPlatformSkin = false; + } + + /* Destroy the Iggy player. */ + IggyPlayerDestroy( swf ); + + // Clear out the controls collection (doesn't delete the controls, and they get re-setup later) + m_controls.clear(); + + // Clear out all the fast names for the current movie + m_fastNames.clear(); + } + + // Reload everything + initialiseMovie(); + + handlePreReload(); + + // Reload controls + for(auto & it : m_controls) + { + it->ReInit(); + } + + updateComponents(); + handleReload(); + + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = m_iFocusControl; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetFocus , 1 , value ); + + m_needsCacheRendered = true; + m_bIsReloading = false; +} + +bool UIScene::needsReloaded() +{ + return !swf && (!stealsFocus() || bHasFocus); +} + +bool UIScene::hasMovie() +{ + return swf != nullptr; +} + +F64 UIScene::getSafeZoneHalfHeight() +{ + float height = ui.getScreenHeight(); + + float safeHeight = 0.0f; + +#ifndef __PSVITA__ + if( !RenderManager.IsHiDef() && RenderManager.IsWidescreen() ) + { + // 90% safezone + safeHeight = height * (0.15f / 2); + } + else + { + // 90% safezone + safeHeight = height * (0.1f / 2); + } +#endif + return safeHeight; +} + +F64 UIScene::getSafeZoneHalfWidth() +{ + float width = ui.getScreenWidth(); + + float safeWidth = 0.0f; +#ifndef __PSVITA__ + if( !RenderManager.IsHiDef() && RenderManager.IsWidescreen() ) + { + // 85% safezone + safeWidth = width * (0.15f / 2); + } + else + { + // 90% safezone + safeWidth = width * (0.1f / 2); + } +#endif + return safeWidth; +} + +void UIScene::updateSafeZone() +{ + // Distance from edge + F64 safeTop = 0.0; + F64 safeBottom = 0.0; + F64 safeLeft = 0.0; + F64 safeRight = 0.0; + + switch( m_parentLayer->getViewport() ) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + safeTop = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + // safeTop mirrors SPLIT_TOP for visual symmetry. safeBottom omitted. + safeTop = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + safeTop = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + safeTop = getSafeZoneHalfHeight(); + + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: + safeTop = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: + safeTop = getSafeZoneHalfHeight(); + + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: + safeTop = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + break; + case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: + safeTop = getSafeZoneHalfHeight(); + + break; + case C4JRender::VIEWPORT_TYPE_FULLSCREEN: + default: + safeTop = getSafeZoneHalfHeight(); + safeBottom = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + + break; + } + setSafeZone(safeTop, safeBottom, safeLeft, safeRight); +} + +void UIScene::setSafeZone(S32 safeTop, S32 safeBottom, S32 safeLeft, S32 safeRight) +{ + IggyDataValue result; + IggyDataValue value[4]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = safeTop; + value[1].type = IGGY_DATATYPE_number; + value[1].number = safeBottom; + value[2].type = IGGY_DATATYPE_number; + value[2].number = safeLeft; + value[3].type = IGGY_DATATYPE_number; + value[3].number = safeRight; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetSafeZone , 4 , value ); +} + +void UIScene::initialiseMovie() +{ + loadMovie(); + mapElementsAndNames(); + + updateSafeZone(); + + m_bUpdateOpacity = true; +} + +#if defined(__PSVITA__) || defined(_WINDOWS64) +void UIScene::SetFocusToElement(int iID) +{ + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = iID; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetFocus , 1 , value ); + + // also trigger handle focus change (just in case if anything else in relation needs updating!) + _handleFocusChange(iID, 0); +} +#endif + +bool UIScene::mapElementsAndNames() +{ + m_rootPath = IggyPlayerRootPath( swf ); + + m_funcRemoveObject = registerFastName( L"RemoveObject" ); + m_funcSlideLeft = registerFastName( L"SlideLeft" ); + m_funcSlideRight = registerFastName( L"SlideRight" ); + m_funcSetSafeZone = registerFastName( L"SetSafeZone" ); + m_funcSetAlpha = registerFastName( L"SetAlpha" ); + m_funcSetFocus = registerFastName( L"SetFocus" ); + m_funcHorizontalResizeCheck = registerFastName( L"DoHorizontalResizeCheck"); + return true; +} + +extern CRITICAL_SECTION s_loadSkinCS; +void UIScene::loadMovie() +{ + EnterCriticalSection(&UIController::ms_reloadSkinCS); // MGH - added to prevent crash loading Iggy movies while the skins were being reloaded + wstring moviePath = getMoviePath(); + +#ifdef _WINDOWS64 + const bool isPanoramaMovie = (moviePath == L"Panorama" || moviePath == L"PanoramaSplit"); + if(isPanoramaMovie) + { + ui.PushDefaultPlatformSkinForPanorama(); + m_bPanoramaUsesDefaultPlatformSkin = true; + } +#endif + +#ifdef __PS3__ + if(RenderManager.IsWidescreen()) + { + moviePath.append(L"720.swf"); + m_loadedResolution = eSceneResolution_720; + } + else + { + moviePath.append(L"480.swf"); + m_loadedResolution = eSceneResolution_480; + } +#elif defined __PSVITA__ + moviePath.append(L"Vita.swf"); + m_loadedResolution = eSceneResolution_Vita; +#elif defined _WINDOWS64 + int primaryPad = ProfileManager.GetPrimaryPad(); + if(primaryPad < 0 || primaryPad >= XUSER_MAX_COUNT) + primaryPad = 0; + const int controlType = app.GetGameSettings(primaryPad, eGameSetting_ControlType); + const bool force720ForControlType = (controlType == 3 || controlType == 5); + // tutorial popups + HUD elements have inaccuracies + crashes that we need to fix here + const bool isTutorialPopupMovie = (moviePath.find(L"TutorialPopup") == 0); + const bool isHUDMovie = (moviePath.find(L"HUD") == 0); + const bool use1080 = (ui.getScreenHeight() > 720.0f) && (!force720ForControlType || isTutorialPopupMovie); + if(use1080) + { + moviePath.append(L"1080.swf"); + m_loadedResolution = eSceneResolution_1080; + } + else + { + moviePath.append(L"720.swf"); + m_loadedResolution = eSceneResolution_720; + } +#else + moviePath.append(L"1080.swf"); + m_loadedResolution = eSceneResolution_1080; +#endif + + if(!app.hasArchiveFile(moviePath)) + { + app.DebugPrintf("WARNING: Could not find iggy movie %ls, trying other resolutions\n", moviePath.c_str()); + + // Try 720 first, then 1080 as final fallback + moviePath = getMoviePath(); + moviePath.append(L"720.swf"); + m_loadedResolution = eSceneResolution_720; + + if(!app.hasArchiveFile(moviePath)) + { + moviePath = getMoviePath(); + moviePath.append(L"1080.swf"); + m_loadedResolution = eSceneResolution_1080; + + if(!app.hasArchiveFile(moviePath)) + { + app.DebugPrintf("ERROR: Could not find any iggy movie for %ls!\n", moviePath.c_str()); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + app.FatalLoadError(); + } + } + } + + byteArray baFile = ui.getMovieData(moviePath.c_str()); + int64_t beforeLoad = ui.iggyAllocCount; + swf = IggyPlayerCreateFromMemory ( baFile.data , baFile.length, nullptr); + int64_t afterLoad = ui.iggyAllocCount; + + if(!swf) + { + app.DebugPrintf("ERROR: Failed to load iggy scene!\n"); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + app.FatalLoadError(); + } + + // Read movie dimensions from the SWF header (available immediately after + // CreateFromMemory, no init tick needed). + IggyProperties *properties = IggyPlayerProperties ( swf ); + if(!properties) + { + app.DebugPrintf("ERROR: IggyPlayerProperties returned null for scene '%ls'\n", moviePath.c_str()); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + app.FatalLoadError(); + } + m_movieHeight = properties->movie_height_in_pixels; + m_movieWidth = properties->movie_width_in_pixels; + m_renderWidth = m_movieWidth; + m_renderHeight = m_movieHeight; + + // Set display size BEFORE the init tick to match what render() will use. + // InitializeAndTickRS runs ActionScript that creates text fields. If the + // display size here differs from what render() passes to SetDisplaySize, + // Iggy can cache glyph rasterizations at one scale during init and then + // reuse them at a different scale during draw, producing mixed glyph sizes. +#ifdef _WINDOWS64 + { + S32 fitW, fitH, fitOffX, fitOffY; + Fit16x9(ui.getScreenWidth(), ui.getScreenHeight(), fitW, fitH, fitOffX, fitOffY); + IggyPlayerSetDisplaySize( swf, fitW, fitH ); + } +#else + IggyPlayerSetDisplaySize( swf, m_movieWidth, m_movieHeight ); +#endif + + IggyPlayerInitializeAndTickRS ( swf ); + int64_t afterTick = ui.iggyAllocCount; + +#ifdef _WINDOWS64 + // Flush Iggy's internal font caches so all glyphs get rasterized fresh + // at the current display scale on the first Draw. Without this, stale + // cache entries from a previous scene (loaded at a different display size) + // cause mixed glyph sizes. ResizeD3D already calls this, which is why + // fonts look correct after a resize but break when a scene reloads + // without one. + IggyFlushInstalledFonts(); +#endif + + app.DebugPrintf( app.USER_SR, "Loaded iggy movie %ls\n", moviePath.c_str() ); + + IggyPlayerSetUserdata(swf,this); + +//#ifdef _DEBUG +#if 0 + IggyMemoryUseInfo memoryInfo; + rrbool res; + int iteration = 0; + int64_t totalStatic = 0; + int64_t totalDynamic = 0; + while(res = IggyDebugGetMemoryUseInfo ( swf , + nullptr , + 0 , + 0 , + iteration , + &memoryInfo )) + { + totalStatic += memoryInfo.static_allocation_bytes; + totalDynamic += memoryInfo.dynamic_allocation_bytes; + app.DebugPrintf(app.USER_SR, "%ls - %.*s static: %d ( %d ) dynamic: %d ( %d )\n", moviePath.c_str(), memoryInfo.subcategory_stringlen, memoryInfo.subcategory, + memoryInfo.static_allocation_bytes, memoryInfo.static_allocation_count, memoryInfo.dynamic_allocation_bytes, memoryInfo.dynamic_allocation_count); + ++iteration; + //if(memoryInfo.static_allocation_bytes > 0) getDebugMemoryUseRecursive(moviePath, memoryInfo); + + } + + app.DebugPrintf(app.USER_SR, "%ls - Total: %d, Expected: %d, Diff: %d\n", moviePath.c_str(), totalStatic + totalDynamic, afterTick - beforeLoad, (afterTick - beforeLoad) - (totalStatic + totalDynamic)); + +#endif + LeaveCriticalSection(&UIController::ms_reloadSkinCS); + +} + +void UIScene::getDebugMemoryUseRecursive(const wstring &moviePath, IggyMemoryUseInfo &memoryInfo) +{ + rrbool res; + IggyMemoryUseInfo internalMemoryInfo; + int internalIteration = 0; + while (res = IggyDebugGetMemoryUseInfo(swf, + 0, + memoryInfo.subcategory, + memoryInfo.subcategory_stringlen, + internalIteration, + &internalMemoryInfo)) + { + app.DebugPrintf(app.USER_SR, "%ls - %.*s static: %d ( %d ) dynamic: %d ( %d )\n", moviePath.c_str(), internalMemoryInfo.subcategory_stringlen, internalMemoryInfo.subcategory, + internalMemoryInfo.static_allocation_bytes, internalMemoryInfo.static_allocation_count, internalMemoryInfo.dynamic_allocation_bytes, internalMemoryInfo.dynamic_allocation_count); + ++internalIteration; + if (internalMemoryInfo.subcategory_stringlen > memoryInfo.subcategory_stringlen) + getDebugMemoryUseRecursive(moviePath, internalMemoryInfo); + } +} + +void UIScene::PrintTotalMemoryUsage(int64_t &totalStatic, int64_t &totalDynamic) +{ + if(!swf) return; + + IggyMemoryUseInfo memoryInfo; + rrbool res; + int iteration = 0; + int64_t sceneStatic = 0; + int64_t sceneDynamic = 0; + while(res = IggyDebugGetMemoryUseInfo ( swf , + 0 , + "" , + 0 , + iteration , + &memoryInfo )) + { + sceneStatic += memoryInfo.static_allocation_bytes; + sceneDynamic += memoryInfo.dynamic_allocation_bytes; + totalStatic += memoryInfo.static_allocation_bytes; + totalDynamic += memoryInfo.dynamic_allocation_bytes; + ++iteration; + + } + + app.DebugPrintf(app.USER_SR, " \\- Scene static: %d , Scene dynamic: %d , Total: %d - %ls\n", sceneStatic, sceneDynamic, sceneStatic + sceneDynamic, getMoviePath().c_str()); +} + +void UIScene::tick() +{ + if(m_bIsReloading) return; + if(m_hasTickedOnce) m_bCanHandleInput = true; + while(IggyPlayerReadyToTick( swf )) + { + tickTimers(); + for(auto & it : m_controls) + { + it->tick(); + } + IggyPlayerTickRS( swf ); + m_hasTickedOnce = true; + } + +#ifdef _WINDOWS64 + { + vector inputs; + getDirectEditInputs(inputs); + for (size_t i = 0; i < inputs.size(); i++) + { + UIControl_TextInput::EDirectEditResult result = inputs[i]->tickDirectEdit(); + if (result != UIControl_TextInput::eDirectEdit_Continue) + onDirectEditFinished(inputs[i], result); + } + //Attempt at matching input code for textinputs for labels + vector labels; + getDirectEditLabels(labels); + for (size_t i = 0; i < labels.size(); i++) + { + //app.DebugPrintf(("label; " + std::to_string(i) + "\n").c_str()); + UIControl_Label::EDirectEditResult result1 = labels[i]->tickDirectEdit(); + //app.DebugPrintf(("result; " + std::to_string(result1) + "\n").c_str()); + if (result1 != UIControl_Label::eDirectEdit_Continue) + onDirectEditLabelFinished(labels[i], result1); + } + } +#endif +} + +UIControl* UIScene::GetMainPanel() +{ + return nullptr; +} + +#ifdef _WINDOWS64 +bool UIScene::isDirectEditBlocking() +{ + vector inputs; + getDirectEditInputs(inputs); + for (size_t i = 0; i < inputs.size(); i++) + { + if (inputs[i]->isDirectEditing() || inputs[i]->getDirectEditCooldown() > 0) + return true; + } + return false; +} + +bool UIScene::handleMouseClick(F32 x, F32 y) +{ + S32 panelOffsetX = 0, panelOffsetY = 0; + UIControl *pMainPanel = GetMainPanel(); + if (pMainPanel) + { + pMainPanel->UpdateControl(); + panelOffsetX = pMainPanel->getXPos(); + panelOffsetY = pMainPanel->getYPos(); + } + + // Click-outside-to-deselect: confirm any active direct edit if + // the click landed outside the editing text input. + { + vector deInputs; + getDirectEditInputs(deInputs); + for (size_t i = 0; i < deInputs.size(); i++) + { + if (!deInputs[i]->isDirectEditing()) + continue; + deInputs[i]->UpdateControl(); + S32 cx = deInputs[i]->getXPos() + panelOffsetX; + S32 cy = deInputs[i]->getYPos() + panelOffsetY; + S32 cw = deInputs[i]->getWidth(); + S32 ch = deInputs[i]->getHeight(); + if (!(cw > 0 && ch > 0 && x >= cx && x <= cx + cw && y >= cy && y <= cy + ch)) + { + deInputs[i]->confirmDirectEdit(); + onDirectEditFinished(deInputs[i], UIControl_TextInput::eDirectEdit_Confirmed); + } + } + } + + vector *controls = GetControls(); + if (!controls) return false; + + // Hit-test controls and pick the smallest-area match to handle + // overlapping Flash bounds correctly without sacrificing precision. + int bestId = -1; + S32 bestArea = INT_MAX; + UIControl *bestCtrl = NULL; + + for (size_t i = 0; i < controls->size(); ++i) + { + UIControl *ctrl = (*controls)[i]; + if (!ctrl || ctrl->getHidden() || !ctrl->getVisible() || ctrl->getId() < 0) + continue; + + UIControl::eUIControlType type = ctrl->getControlType(); + if (type != UIControl::eButton && type != UIControl::eTextInput && + type != UIControl::eCheckBox && type != UIControl::eBook && type != UIControl::ePageFlip) + continue; + + if (pMainPanel && ctrl->getParentPanel() != pMainPanel) + continue; + + ctrl->UpdateControl(); + S32 cx = ctrl->getXPos() + panelOffsetX; + S32 cy = ctrl->getYPos() + panelOffsetY; + S32 cw = ctrl->getWidth(); + S32 ch = ctrl->getHeight(); + if (cw <= 0 || ch <= 0) + continue; + + if (x >= cx && x <= cx + cw && y >= cy && y <= cy + ch) + { + S32 area = cw * ch; + if (area < bestArea) + { + bestArea = area; + bestId = ctrl->getId(); + bestCtrl = ctrl; + } + } + } + + if (bestId >= 0 && bestCtrl) + { + if (bestCtrl->getControlType() == UIControl::eCheckBox) + { + UIControl_CheckBox *cb = static_cast(bestCtrl); + if (cb->IsEnabled()) + { + bool newState = !cb->IsChecked(); + cb->setChecked(newState); + handleCheckboxToggled((F64)bestId, newState); + } + } + else + { + handlePress((F64)bestId, 0); + } + return true; + } + return false; +} +#endif + +void UIScene::addTimer(int id, int ms) +{ + int currentTime = System::currentTimeMillis(); + + TimerInfo info; + info.running = true; + info.duration = ms; + info.targetTime = currentTime + ms; + m_timers[id] = info; +} + +void UIScene::killTimer(int id) +{ + auto it = m_timers.find(id); + if(it != m_timers.end()) + { + it->second.running = false; + } +} + +void UIScene::tickTimers() +{ + int currentTime = System::currentTimeMillis(); + for (auto it = m_timers.begin(); it != m_timers.end();) + { + if(!it->second.running) + { + it = m_timers.erase(it); + } + else + { + if(currentTime > it->second.targetTime) + { + handleTimerComplete(it->first); + + // Auto-restart + it->second.targetTime = it->second.duration + currentTime; + } + ++it; + } + } +} + +IggyName UIScene::registerFastName(const wstring &name) +{ + IggyName var; + auto it = m_fastNames.find(name); + if(it != m_fastNames.end()) + { + var = it->second; + } + else + { + var = IggyPlayerCreateFastName ( getMovie() , (IggyUTF16 *)name.c_str() , -1 ); + m_fastNames[name] = var; + } + return var; +} + +void UIScene::removeControl( UIControl_Base *control, bool centreScene) +{ + IggyDataValue result; + IggyDataValue value[2]; + + string name = control->getControlName(); + IggyStringUTF8 stringVal; + stringVal.string = (char*)name.c_str(); + stringVal.length = name.length(); + value[0].type = IGGY_DATATYPE_string_UTF8; + value[0].string8 = stringVal; + + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = centreScene; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcRemoveObject , 2 , value ); + +#ifdef __PSVITA__ + // update the button positions since they may have changed + UpdateSceneControls(); + + // remove it from the touchboxes + ui.TouchBoxRebuild(control->getParentScene()); +#endif + + // mark the button as removed so hover/touch hit-tests skip it + control->setHidden(true); + +} + +void UIScene::slideLeft() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSlideLeft , 0 , nullptr ); +} + +void UIScene::slideRight() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSlideRight , 0 , nullptr ); +} + +void UIScene::doHorizontalResizeCheck() +{ + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcHorizontalResizeCheck , 0 , nullptr ); +} + +void UIScene::render(S32 width, S32 height, C4JRender::eViewportType viewport) +{ + if(m_bIsReloading) return; + if(!m_hasTickedOnce || !swf) return; + + if(viewport != C4JRender::VIEWPORT_TYPE_FULLSCREEN) + { + F32 originX, originY, viewW, viewH; + GetViewportRect(ui.getScreenWidth(), ui.getScreenHeight(), viewport, originX, originY, viewW, viewH); + S32 fitW, fitH, offsetX, offsetY; + Fit16x9(viewW, viewH, fitW, fitH, offsetX, offsetY); + ui.setupRenderPosition(static_cast(originX) + offsetX, static_cast(originY) + offsetY); + IggyPlayerSetDisplaySize( swf, fitW, fitH ); + IggyPlayerDraw( swf ); + } + else + { + ui.setupRenderPosition(viewport); + IggyPlayerSetDisplaySize( swf, width, height ); + IggyPlayerDraw( swf ); + } +} + +void UIScene::setOpacity(float percent) +{ + if(percent != m_lastOpacity || (m_bUpdateOpacity && getMovie())) + { + m_lastOpacity = percent; + + // 4J-TomK once a scene has been freshly loaded or re-loaded we force update opacity via initialiseMovie + if(m_bUpdateOpacity) + m_bUpdateOpacity = false; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = percent; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetAlpha , 1 , value ); + } +} + +void UIScene::setVisible(bool visible) +{ + m_bVisible = visible; +} + +void UIScene::customDraw(IggyCustomDrawCallbackRegion *region) +{ + //app.DebugPrintf("Handling custom draw for scene with no override!\n"); +} + +void UIScene::customDrawSlotControl(IggyCustomDrawCallbackRegion *region, int iPad, shared_ptr item, float fAlpha, bool isFoil, bool bDecorations) +{ + if (item!= nullptr) + { + bool useCommandBuffers = false; +#ifdef _XBOX_ONE + useCommandBuffers = true; + + m_needsCacheRendered = true; +#endif + + bool shouldCacheSlotRender = m_cacheSlotRenders && (m_needsCacheRendered || useCommandBuffers); + if(shouldCacheSlotRender) + { + if( (m_cachedSlotDraw.size() + 1) == m_expectedCachedSlotCount) + { + //Make sure that pMinecraft->player is the correct player so that player specific rendering + // eg clock and compass, are rendered correctly + Minecraft *pMinecraft=Minecraft::GetInstance(); + shared_ptr oldPlayer = pMinecraft->player; + if( iPad >= 0 && iPad < XUSER_MAX_COUNT ) pMinecraft->player = pMinecraft->localplayers[iPad]; + + // Setup GDraw, normal game render states and matrices + //CustomDrawData *customDrawRegion = ui.setupCustomDraw(this,region); + PIXBeginNamedEvent(0,"Starting Iggy custom draw\n"); + CustomDrawData *customDrawRegion = ui.calculateCustomDraw(region); + ui.beginIggyCustomDraw4J(region, customDrawRegion); + ui.setupCustomDrawGameState(); + + int list = m_parentLayer->m_parentGroup->getCommandBufferList(); + + if(!useCommandBuffers || m_needsCacheRendered) + { +#if (!defined __PS3__) && (!defined __PSVITA__) + if(useCommandBuffers) RenderManager.CBuffStart(list, true); +#endif + PIXBeginNamedEvent(0,"Draw uncached"); + ui.setupCustomDrawMatrices(this, customDrawRegion); + _customDrawSlotControl(customDrawRegion, iPad, item, fAlpha, isFoil, bDecorations, useCommandBuffers); + delete customDrawRegion; + PIXEndNamedEvent(); + + PIXBeginNamedEvent(0,"Draw all cache"); + // Draw all the cached slots + for(auto& drawData : m_cachedSlotDraw) + { + ui.setupCustomDrawMatrices(this, drawData->customDrawRegion); + _customDrawSlotControl(drawData->customDrawRegion, iPad, drawData->item, drawData->fAlpha, drawData->isFoil, drawData->bDecorations, useCommandBuffers); + delete drawData->customDrawRegion; + delete drawData; + } + PIXEndNamedEvent(); +#ifndef __PS3__ + if(useCommandBuffers) RenderManager.CBuffEnd(); +#endif + } + m_cachedSlotDraw.clear(); + +#ifndef __PS3__ + if(useCommandBuffers) RenderManager.CBuffCall(list); +#endif + + // Finish GDraw and anything else that needs to be finalised + ui.endCustomDraw(region); + + pMinecraft->player = oldPlayer; + } + else + { + PIXBeginNamedEvent(0,"Caching region"); + CachedSlotDrawData *drawData = new CachedSlotDrawData(); + drawData->item = item; + drawData->fAlpha = fAlpha; + drawData->isFoil = isFoil; + drawData->bDecorations = bDecorations; + drawData->customDrawRegion = ui.calculateCustomDraw(region); + + m_cachedSlotDraw.push_back(drawData); + PIXEndNamedEvent(); + } + } + else + { + // Setup GDraw, normal game render states and matrices + CustomDrawData *customDrawRegion = ui.setupCustomDraw(this,region); + + Minecraft *pMinecraft=Minecraft::GetInstance(); + + //Make sure that pMinecraft->player is the correct player so that player specific rendering + // eg clock and compass, are rendered correctly + shared_ptr oldPlayer = pMinecraft->player; + if( iPad >= 0 && iPad < XUSER_MAX_COUNT ) pMinecraft->player = pMinecraft->localplayers[iPad]; + + _customDrawSlotControl(customDrawRegion, iPad, item, fAlpha, isFoil, bDecorations, false); + delete customDrawRegion; + pMinecraft->player = oldPlayer; + + // Finish GDraw and anything else that needs to be finalised + ui.endCustomDraw(region); + } + } +} + +void UIScene::_customDrawSlotControl(CustomDrawData *region, int iPad, shared_ptr item, float fAlpha, bool isFoil, bool bDecorations, bool usingCommandBuffer) +{ + Minecraft *pMinecraft=Minecraft::GetInstance(); + + float bwidth,bheight; + bwidth = region->x1 - region->x0; + bheight = region->y1 - region->y0; + + float x = region->x0; + float y = region->y0; + + // Base scale on height of this control, compared to height of what the item renderer normally renders (16 pixels high). Potentially + // we might want separate x & y scales here + + float scaleX = bwidth / 16.0f; + float scaleY = bheight / 16.0f; + + glEnable(GL_RESCALE_NORMAL); + glPushMatrix(); + glRotatef(120, 1, 0, 0); + Lighting::turnOn(); + glPopMatrix(); + + float pop = item->popTime; + if (pop > 0) + { + glPushMatrix(); + float squeeze = 1 + pop / static_cast(Inventory::POP_TIME_DURATION); + float sx = x; + float sy = y; + float sxoffs = 8 * scaleX; + float syoffs = 12 * scaleY; + glTranslatef((float)(sx + sxoffs), (float)(sy + syoffs), 0); + glScalef(1 / squeeze, (squeeze + 1) / 2, 1); + glTranslatef((float)-(sx + sxoffs), (float)-(sy + syoffs), 0); + } + + PIXBeginNamedEvent(0,"Render and decorate"); + if(m_pItemRenderer == nullptr) m_pItemRenderer = new ItemRenderer(); + RenderManager.StateSetBlendEnable(true); + RenderManager.StateSetBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + RenderManager.StateSetBlendFactor(0xffffffff); + m_pItemRenderer->renderAndDecorateItem(pMinecraft->font, pMinecraft->textures, item, x, y,scaleX,scaleY,fAlpha,isFoil,false, !usingCommandBuffer); + PIXEndNamedEvent(); + + if (pop > 0) + { + glPopMatrix(); + } + + if(bDecorations) + { + if((scaleX!=1.0f) ||(scaleY!=1.0f)) + { + glPushMatrix(); + glScalef(scaleX, scaleY, 1.0f); + int iX= static_cast(0.5f + ((float)x) / scaleX); + int iY= static_cast(0.5f + ((float)y) / scaleY); + + m_pItemRenderer->renderGuiItemDecorations(pMinecraft->font, pMinecraft->textures, item, iX, iY, fAlpha); + glPopMatrix(); + } + else + { + m_pItemRenderer->renderGuiItemDecorations(pMinecraft->font, pMinecraft->textures, item, static_cast(x), static_cast(y), fAlpha); + } + } + + Lighting::turnOff(); + glDisable(GL_RESCALE_NORMAL); +} + +// 4J Stu - Not threadsafe +//void UIScene::navigateForward(int iPad, EUIScene scene, void *initData) +//{ +// if(m_parentLayer == nullptr) +// { +// app.DebugPrintf("A scene is trying to navigate forwards, but it's parent layer is nullptr!\n"); +// } +// else +// { +// m_parentLayer->NavigateToScene(iPad,scene,initData); +// } +//} + +void UIScene::navigateBack() +{ + //CD - Added for audio + ui.PlayUISFX(eSFX_Back); + + ui.NavigateBack(m_iPad); + + if(m_parentLayer == nullptr) + { + } + else + { +// m_parentLayer->removeScene(this); + +#ifdef _DURANGO + if (ui.GetTopScene(0)) + InputManager.SetEnabledGtcButtons( ui.GetTopScene(0)->getDefaultGtcButtons() ); +#endif + } + +} + +void UIScene::gainFocus() +{ + if( !bHasFocus && stealsFocus() ) + { + // 4J Stu - Don't do this + /* + IggyEvent event; + IggyMakeEventFocusGained( &event , 0); + + IggyEventResult result; + IggyPlayerDispatchEventRS( getMovie() , &event , &result ); + + app.DebugPrintf("Sent gain focus event to scene\n"); + */ + bHasFocus = true; + if(needsReloaded()) + { + reloadMovie(); + } + + updateTooltips(); + updateComponents(); + + if(!m_bFocussedOnce) + { + IggyDataValue result; + IggyDataValue value[1]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = -1; + + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetFocus , 1 , value ); + } + + handleGainFocus(m_bFocussedOnce); + if(bHasFocus) m_bFocussedOnce = true; + } + else if(bHasFocus && stealsFocus()) + { + updateTooltips(); + } +} + +void UIScene::loseFocus() +{ + if(bHasFocus) + { + // 4J Stu - Don't do this + /* + IggyEvent event; + IggyMakeEventFocusLost( &event ); + IggyEventResult result; + IggyPlayerDispatchEventRS ( getMovie() , &event , &result ); + */ + + app.DebugPrintf("Sent lose focus event to scene\n"); + bHasFocus = false; + handleLoseFocus(); + } +} + +void UIScene::handleGainFocus(bool navBack) +{ +#ifdef _DURANGO + InputManager.SetEnabledGtcButtons( this->getDefaultGtcButtons() ); +#endif +} + +void UIScene::updateTooltips() +{ + if(!ui.IsReloadingSkin()) + ui.SetTooltips(m_iPad, -1); +} + +void UIScene::sendInputToMovie(int key, bool repeat, bool pressed, bool released) +{ + if(!swf) return; + + int iggyKeyCode = convertGameActionToIggyKeycode(key); + + if(iggyKeyCode < 0) + { + app.DebugPrintf("UI WARNING: Ignoring input as game action does not translate to an Iggy keycode\n"); + return; + } + +#ifdef _WINDOWS64 + // If a navigation key is pressed with no focused element, focus the first + // available one so arrow keys work even when the mouse is over empty space. + if(pressed && (iggyKeyCode == IGGY_KEYCODE_UP || iggyKeyCode == IGGY_KEYCODE_DOWN || + iggyKeyCode == IGGY_KEYCODE_LEFT || iggyKeyCode == IGGY_KEYCODE_RIGHT)) + { + IggyFocusHandle currentFocus = IGGY_FOCUS_NULL; + IggyFocusableObject focusables[64]; + S32 numFocusables = 0; + IggyPlayerGetFocusableObjects(swf, ¤tFocus, focusables, 64, &numFocusables); + if(currentFocus == IGGY_FOCUS_NULL && numFocusables > 0) + { + IggyPlayerSetFocusRS(swf, focusables[0].object, 0); + return; + } + } +#endif + + IggyEvent keyEvent; + // 4J Stu - Keyloc is always standard as we don't care about shift/alt + IggyMakeEventKey( &keyEvent, pressed?IGGY_KEYEVENT_Down:IGGY_KEYEVENT_Up, static_cast(iggyKeyCode), IGGY_KEYLOC_Standard ); + + IggyEventResult result; + IggyPlayerDispatchEventRS ( swf , &keyEvent , &result ); +} + +int UIScene::convertGameActionToIggyKeycode(int action) +{ + // TODO: This action to key mapping should probably use the control mapping + int keycode = -1; + switch(action) + { +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + case ACTION_MENU_A: + keycode = IGGY_KEYCODE_ENTER; + break; + case ACTION_MENU_B: + keycode = IGGY_KEYCODE_ESCAPE; + break; + case ACTION_MENU_X: + keycode = IGGY_KEYCODE_F1; + break; + case ACTION_MENU_Y: + keycode = IGGY_KEYCODE_F2; + break; + case ACTION_MENU_OK: + keycode = IGGY_KEYCODE_ENTER; + break; + case ACTION_MENU_CANCEL: + keycode = IGGY_KEYCODE_ESCAPE; + break; + case ACTION_MENU_UP: + keycode = IGGY_KEYCODE_UP; + break; + case ACTION_MENU_DOWN: + keycode = IGGY_KEYCODE_DOWN; + break; + case ACTION_MENU_RIGHT: + keycode = IGGY_KEYCODE_RIGHT; + break; + case ACTION_MENU_LEFT: + keycode = IGGY_KEYCODE_LEFT; + break; + case ACTION_MENU_PAGEUP: + keycode = IGGY_KEYCODE_PAGE_UP; + break; + case ACTION_MENU_PAGEDOWN: +#ifdef __PSVITA__ + if (!InputManager.IsVitaTV()) + { + keycode = IGGY_KEYCODE_F6; + } + else +#endif + { + keycode = IGGY_KEYCODE_PAGE_DOWN; + } + break; + case ACTION_MENU_RIGHT_SCROLL: + keycode = IGGY_KEYCODE_F3; + break; + case ACTION_MENU_LEFT_SCROLL: + keycode = IGGY_KEYCODE_F4; + break; + case ACTION_MENU_STICK_PRESS: + break; + case ACTION_MENU_OTHER_STICK_PRESS: + keycode = IGGY_KEYCODE_F5; + break; + case ACTION_MENU_OTHER_STICK_UP: + keycode = IGGY_KEYCODE_F11; + break; + case ACTION_MENU_OTHER_STICK_DOWN: + keycode = IGGY_KEYCODE_F12; + break; + case ACTION_MENU_OTHER_STICK_LEFT: + break; + case ACTION_MENU_OTHER_STICK_RIGHT: + break; + }; + + return keycode; +} + +bool UIScene::allowRepeat(int key) +{ + // 4J-PB - ignore repeats of action ABXY buttons + // fix for PS3 213 - [MAIN MENU] Holding down buttons will continue to activate every prompt. + switch(key) + { + case ACTION_MENU_OK: + case ACTION_MENU_CANCEL: + case ACTION_MENU_A: + case ACTION_MENU_B: + case ACTION_MENU_X: + case ACTION_MENU_Y: + return false; + } + return true; +} + +void UIScene::externalCallback(IggyExternalFunctionCallUTF16 * call) +{ + if(wcscmp((wchar_t *)call->function_name.string,L"handlePress")==0) + { + if(call->num_arguments != 2) + { + app.DebugPrintf("Callback for handlePress did not have the correct number of arguments\n"); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + return; + } + if(call->arguments[0].type != IGGY_DATATYPE_number || call->arguments[1].type != IGGY_DATATYPE_number) + { + app.DebugPrintf("Arguments for handlePress were not of the correct type\n"); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + return; + } + handlePress(call->arguments[0].number, call->arguments[1].number); + } + else if(wcscmp((wchar_t *)call->function_name.string,L"handleFocusChange")==0) + { + if(call->num_arguments != 2) + { + app.DebugPrintf("Callback for handleFocusChange did not have the correct number of arguments\n"); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + return; + } + if(call->arguments[0].type != IGGY_DATATYPE_number || call->arguments[1].type != IGGY_DATATYPE_number) + { + app.DebugPrintf("Arguments for handleFocusChange were not of the correct type\n"); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + return; + } + _handleFocusChange(call->arguments[0].number, call->arguments[1].number); + } + else if(wcscmp((wchar_t *)call->function_name.string,L"handleInitFocus")==0) + { + if(call->num_arguments != 2) + { + app.DebugPrintf("Callback for handleInitFocus did not have the correct number of arguments\n"); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + return; + } + if(call->arguments[0].type != IGGY_DATATYPE_number || call->arguments[1].type != IGGY_DATATYPE_number) + { + app.DebugPrintf("Arguments for handleInitFocus were not of the correct type\n"); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + return; + } + _handleInitFocus(call->arguments[0].number, call->arguments[1].number); + } + else if(wcscmp((wchar_t *)call->function_name.string,L"handleCheckboxToggled")==0) + { + if(call->num_arguments < 2 || call->num_arguments > 3) + { + app.DebugPrintf("Callback for handleCheckboxToggled did not have the correct number of arguments (%d)\n", call->num_arguments); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + return; + } + if(call->arguments[0].type != IGGY_DATATYPE_number) + { + app.DebugPrintf("Arguments for handleCheckboxToggled were not of the correct type\n"); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + return; + } + int selArg = (call->num_arguments == 3) ? 2 : 1; + if(call->arguments[selArg].type != IGGY_DATATYPE_boolean && call->arguments[selArg].type != IGGY_DATATYPE_number) + { + app.DebugPrintf("Arguments for handleCheckboxToggled were not of the correct type\n"); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + return; + } + bool selected = (call->arguments[selArg].type == IGGY_DATATYPE_boolean) + ? call->arguments[selArg].boolval + : (call->arguments[selArg].number != 0); + handleCheckboxToggled(call->arguments[0].number, selected); + } + else if(wcscmp((wchar_t *)call->function_name.string,L"handleSliderMove")==0) + { + if(call->num_arguments < 2 || call->num_arguments > 3) + { + app.DebugPrintf("Callback for handleSliderMove did not have the correct number of arguments (%d)\n", call->num_arguments); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + return; + } + if(call->arguments[0].type != IGGY_DATATYPE_number) + { + app.DebugPrintf("Arguments for handleSliderMove were not of the correct type\n"); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + return; + } + int idArg = 0; + int valArg = (call->num_arguments == 3) ? 2 : 1; + if(call->num_arguments == 3) idArg = 1; + if(call->arguments[valArg].type != IGGY_DATATYPE_number) + { + app.DebugPrintf("Arguments for handleSliderMove were not of the correct type\n"); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + return; + } + handleSliderMove(call->arguments[idArg].number, call->arguments[valArg].number); + } + else if(wcscmp((wchar_t *)call->function_name.string,L"handleAnimationEnd")==0) + { + if(call->num_arguments != 0) + { + app.DebugPrintf("Callback for handleAnimationEnd did not have the correct number of arguments\n"); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + return; + } + handleAnimationEnd(); + } + else if(wcscmp((wchar_t *)call->function_name.string,L"handleSelectionChanged")==0) + { + if(call->num_arguments != 1) + { + app.DebugPrintf("Callback for handleSelectionChanged did not have the correct number of arguments\n"); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + return; + } + if(call->arguments[0].type != IGGY_DATATYPE_number) + { + app.DebugPrintf("Arguments for handleSelectionChanged were not of the correct type\n"); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + return; + } + handleSelectionChanged(call->arguments[0].number); + } + else if(wcscmp((wchar_t *)call->function_name.string,L"handleRequestMoreData")==0) + { + if(call->num_arguments == 0) + { + handleRequestMoreData(0,false); + } + else + { + if(call->num_arguments != 2) + { + app.DebugPrintf("Callback for handleRequestMoreData did not have the correct number of arguments\n"); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + return; + } + if(call->arguments[0].type != IGGY_DATATYPE_number || call->arguments[1].type != IGGY_DATATYPE_boolean) + { + app.DebugPrintf("Arguments for handleRequestMoreData were not of the correct type\n"); +#ifndef _CONTENT_PACKAGE + DEBUG_BREAK(); +#endif + return; + } + handleRequestMoreData(call->arguments[0].number, call->arguments[1].boolval); + } + } + else if(wcscmp((wchar_t *)call->function_name.string,L"handleTouchBoxRebuild")==0) + { + handleTouchBoxRebuild(); + } + else + { + app.DebugPrintf("Unhandled callback: %s\n", call->function_name.string); + } +} + +void UIScene::registerSubstitutionTexture(const wstring &textureName, PBYTE pbData, DWORD dwLength, bool deleteData) +{ + m_registeredTextures[textureName] = deleteData;; + ui.registerSubstitutionTexture(textureName, pbData, dwLength); +} + +bool UIScene::hasRegisteredSubstitutionTexture(const wstring &textureName) +{ + auto it = m_registeredTextures.find(textureName); + + return it != m_registeredTextures.end(); +} + +void UIScene::_handleFocusChange(F64 controlId, F64 childId) +{ + int newControl = static_cast(controlId); + int newChild = static_cast(childId); + if (newControl != m_iFocusControl || newChild != m_iFocusChild) + { + m_iFocusControl = newControl; + m_iFocusChild = newChild; + + handleFocusChange(controlId, childId); + ui.PlayUISFX(eSFX_Focus); + } +} + +void UIScene::_handleInitFocus(F64 controlId, F64 childId) +{ + m_iFocusControl = static_cast(controlId); + m_iFocusChild = static_cast(childId); + + //handleInitFocus(controlId, childId); + handleFocusChange(controlId, childId); +} + +bool UIScene::controlHasFocus(int iControlId) +{ + return m_iFocusControl == iControlId; +} + +bool UIScene::controlHasFocus(UIControl_Base *control) +{ + return controlHasFocus( control->getId() ); +} + +int UIScene::getControlChildFocus() +{ + return m_iFocusChild; +} + +int UIScene::getControlFocus() +{ + return m_iFocusControl; +} + +void UIScene::setBackScene(UIScene *scene) +{ + m_backScene = scene; +} + +UIScene *UIScene::getBackScene() +{ + return m_backScene; +} +#ifdef __PSVITA__ +void UIScene::UpdateSceneControls() +{ + for ( UIControl *control : *GetControls() ) + { + control->UpdateControl(); + } +} +#endif + +void UIScene::HandleMessage(EUIMessage message, void *data) +{ +} + +size_t UIScene::GetCallbackUniqueId() +{ + if( m_callbackUniqueId == 0) + { + m_callbackUniqueId = ui.RegisterForCallbackId(this); + } + return m_callbackUniqueId; +} + +bool UIScene::isReadyToDelete() +{ + return true; +} diff --git a/Minecraft.Client/Common/UI/UIScene_ControlsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_ControlsMenu.cpp index dc747a63..0beff3d2 100644 --- a/Minecraft.Client/Common/UI/UIScene_ControlsMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_ControlsMenu.cpp @@ -13,7 +13,9 @@ UIScene_ControlsMenu::UIScene_ControlsMenu(int iPad, void *initData, UILayer *pa IggyDataValue value[1]; value[0].type = IGGY_DATATYPE_number; #if defined(_XBOX) || defined(_WIN64) - value[0].number = static_cast(0); + int controlType = app.GetGameSettings(m_iPad, eGameSetting_ControlType); + static const int platformMap[] = {0, 1, 0, 2, 3, 5}; + value[0].number = static_cast(platformMap[controlType]); #elif defined(_DURANGO) value[0].number = (F64)1; #elif defined(__PS3__) @@ -55,6 +57,16 @@ UIScene_ControlsMenu::UIScene_ControlsMenu(int iPad, void *initData, UILayer *pa m_checkboxInvert.init(app.GetString(IDS_INVERT_LOOK), eControl_InvertLook, app.GetGameSettings(m_iPad,eGameSetting_ControlInvertLook)); m_checkboxSouthpaw.init(app.GetString(IDS_SOUTHPAW), eControl_Southpaw, app.GetGameSettings(m_iPad,eGameSetting_ControlSouthPaw)); + m_checkboxSafeCam.init(app.GetString(IDS_SAFE_SPRINT), eControl_SafeCam, app.GetGameSettings(m_iPad,eGameSetting_SafeCam)); + m_checkboxAbswap.init(app.GetString(IDS_SWAP), eControl_ABSwap, app.GetGameSettings(m_iPad,eGameSetting_Swap)); + + { + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = 0; + IggyPlayerCallMethodRS(getMovie(), &result, IggyPlayerRootPath(getMovie()), m_funcSetABSwapCheckBox, 1, value); + } m_iSchemeTextA[0]=IDS_CONTROLS_SCHEME0; m_iSchemeTextA[1]=IDS_CONTROLS_SCHEME1; @@ -96,11 +108,7 @@ UIScene_ControlsMenu::UIScene_ControlsMenu(int iPad, void *initData, UILayer *pa if (InputManager.IsVitaTV()) m_iCurrentNavigatedControlsLayout = 1; #endif - for(unsigned int i = 0; i < e_PadCOUNT; ++i) - { - m_labelsPad[i].init(L""); - m_controlLines[i].setVisible(false); - } + m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, false); m_bLayoutChanged = false; @@ -189,6 +197,14 @@ void UIScene_ControlsMenu::handleCheckboxToggled(F64 controlId, bool selected) app.SetGameSettings(m_iPad,eGameSetting_ControlSouthPaw,(unsigned char)( selected ) ); PositionAllText(m_iPad); break; + case eControl_SafeCam: + app.SetGameSettings(m_iPad,eGameSetting_SafeCam,(unsigned char)( selected ) ); + m_bLayoutChanged = true; + break; + case eControl_ABSwap: + app.SetGameSettings(m_iPad,eGameSetting_Swap,(unsigned char)( selected ) ); + m_bLayoutChanged = true; + break; }; } @@ -230,11 +246,8 @@ void UIScene_ControlsMenu::handleFocusChange(F64 controlId, F64 childId) void UIScene_ControlsMenu::PositionAllText(int iPad) { - for(unsigned int i = 0; i < e_PadCOUNT; ++i) - { - m_labelsPad[i].setLabel(L""); - m_controlLines[i].setVisible(false); - } + IggyDataValue result; + IggyPlayerCallMethodRS(getMovie(), &result, IggyPlayerRootPath(getMovie()), m_funcClearAllKeyLines, 0, 0); if(m_bCreativeMode) { @@ -331,6 +344,20 @@ void UIScene_ControlsMenu::PositionTextDirect(int iPad,int iTextID, int iControl { LPCWSTR text = app.GetString(iTextID); - m_labelsPad[iControlDetailsIndex].setLabel(text); - m_controlLines[iControlDetailsIndex].setVisible(bShow); + IggyDataValue result; + IggyDataValue value[3]; + + value[0].type = IGGY_DATATYPE_number; + value[0].number = static_cast(iControlDetailsIndex); + + IggyStringUTF16 stringVal; + stringVal.string = (IggyUTF16*)text; + stringVal.length = (int)wcslen(text); + value[1].type = IGGY_DATATYPE_string_UTF16; + value[1].string16 = stringVal; + + value[2].type = IGGY_DATATYPE_boolean; + value[2].boolval = bShow ? 1 : 0; + + IggyPlayerCallMethodRS(getMovie(), &result, IggyPlayerRootPath(getMovie()), m_funcSetLineAndText, 3, value); } \ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_ControlsMenu.h b/Minecraft.Client/Common/UI/UIScene_ControlsMenu.h index 538207fe..3f917d06 100644 --- a/Minecraft.Client/Common/UI/UIScene_ControlsMenu.h +++ b/Minecraft.Client/Common/UI/UIScene_ControlsMenu.h @@ -13,6 +13,8 @@ private: eControl_Button2, eControl_InvertLook, eControl_Southpaw, + eControl_SafeCam, + eControl_ABSwap, }; enum EPadButtons @@ -47,11 +49,11 @@ private: UIControl_Label m_labelCurrentLayout; UIControl_Label m_labelVersion; - UIControl_Label m_labelsPad[e_PadCOUNT]; - UIControl m_controlLines[e_PadCOUNT]; UIControl_Button m_buttonLayouts[3]; - UIControl_CheckBox m_checkboxInvert, m_checkboxSouthpaw; + UIControl_CheckBox m_checkboxInvert, m_checkboxSouthpaw, m_checkboxSafeCam, m_checkboxAbswap; IggyName m_funcSetPlatform, m_funcSetControllerLayout; + IggyName m_funcSetLineAndText, m_funcClearAllKeyLines; + IggyName m_funcSetABSwapCheckBox, m_funcRemoveSafeSprint; UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) #ifndef __PSVITA__ @@ -67,51 +69,17 @@ private: } #endif - UI_MAP_ELEMENT( m_labelsPad[e_PadBack], "LabelBack") - UI_MAP_ELEMENT( m_labelsPad[e_PadLT], "LabelLT") - UI_MAP_ELEMENT( m_labelsPad[e_PadLB], "LabelLB") - UI_MAP_ELEMENT( m_labelsPad[e_PadDPadLeft], "LabelDPadLeft") - UI_MAP_ELEMENT( m_labelsPad[e_PadDPadRight], "LabelDPadRight") - UI_MAP_ELEMENT( m_labelsPad[e_PadDPadUp], "LabelDPadUp") - UI_MAP_ELEMENT( m_labelsPad[e_PadDPadDown], "LabelDPadDown") - UI_MAP_ELEMENT( m_labelsPad[e_PadLS_1], "LabelLS_1") - UI_MAP_ELEMENT( m_labelsPad[e_PadLS_2], "LabelLS_2") - UI_MAP_ELEMENT( m_labelsPad[e_PadStart], "LabelStart") - UI_MAP_ELEMENT( m_labelsPad[e_PadRT], "LabelRT") - UI_MAP_ELEMENT( m_labelsPad[e_PadRB], "LabelRB") - UI_MAP_ELEMENT( m_labelsPad[e_PadY], "LabelY") - UI_MAP_ELEMENT( m_labelsPad[e_PadB], "LabelB") - UI_MAP_ELEMENT( m_labelsPad[e_PadA], "LabelA") - UI_MAP_ELEMENT( m_labelsPad[e_PadX], "LabelX") - UI_MAP_ELEMENT( m_labelsPad[e_PadRS_1], "LabelRS_1") - UI_MAP_ELEMENT( m_labelsPad[e_PadRS_2], "LabelRS_2") - UI_MAP_ELEMENT( m_labelsPad[e_PadTouch], "LabelTouch") - - UI_MAP_ELEMENT( m_controlLines[e_PadBack], "LineBack") - UI_MAP_ELEMENT( m_controlLines[e_PadLT], "LineLT") - UI_MAP_ELEMENT( m_controlLines[e_PadLB], "LineLB") - UI_MAP_ELEMENT( m_controlLines[e_PadDPadLeft], "LineDpadLeft") - UI_MAP_ELEMENT( m_controlLines[e_PadDPadRight], "LineDpadRight") - UI_MAP_ELEMENT( m_controlLines[e_PadDPadUp], "LineDpadUp") - UI_MAP_ELEMENT( m_controlLines[e_PadDPadDown], "LineDpadDown") - UI_MAP_ELEMENT( m_controlLines[e_PadLS_1], "LineL3") - UI_MAP_ELEMENT( m_controlLines[e_PadLS_2], "LineLeftStick") - UI_MAP_ELEMENT( m_controlLines[e_PadStart], "LineStart") - UI_MAP_ELEMENT( m_controlLines[e_PadRT], "LineRT") - UI_MAP_ELEMENT( m_controlLines[e_PadRB], "LineRB") - UI_MAP_ELEMENT( m_controlLines[e_PadY], "LineY") - UI_MAP_ELEMENT( m_controlLines[e_PadB], "LineB") - UI_MAP_ELEMENT( m_controlLines[e_PadA], "LineA") - UI_MAP_ELEMENT( m_controlLines[e_PadX], "LineX") - UI_MAP_ELEMENT( m_controlLines[e_PadRS_1], "LineR3") - UI_MAP_ELEMENT( m_controlLines[e_PadRS_2], "LineRightStick") - UI_MAP_ELEMENT( m_controlLines[e_PadTouch], "LineTouch") - UI_MAP_ELEMENT( m_checkboxInvert, "InvertLook") UI_MAP_ELEMENT( m_checkboxSouthpaw, "SouthPaw") + UI_MAP_ELEMENT( m_checkboxSafeCam, "SafeCam") + UI_MAP_ELEMENT( m_checkboxAbswap, "ABSwap") UI_MAP_NAME( m_funcSetPlatform, L"SetPlatform") UI_MAP_NAME( m_funcSetControllerLayout, L"SetControllerLayout") + UI_MAP_NAME( m_funcSetLineAndText, L"SetLineAndText") + UI_MAP_NAME( m_funcClearAllKeyLines, L"ClearAllKeyLines") + UI_MAP_NAME( m_funcSetABSwapCheckBox, L"SetABSwapCheckBox") + UI_MAP_NAME( m_funcRemoveSafeSprint, L"RemoveSafeSprint") UI_MAP_ELEMENT( m_labelVersion, "Version") UI_END_MAP_ELEMENTS_AND_NAMES() public: diff --git a/Minecraft.Client/Common/UI/UIScene_LanguageSelector.cpp b/Minecraft.Client/Common/UI/UIScene_LanguageSelector.cpp index c2a30d3c..c7c2816a 100644 --- a/Minecraft.Client/Common/UI/UIScene_LanguageSelector.cpp +++ b/Minecraft.Client/Common/UI/UIScene_LanguageSelector.cpp @@ -37,6 +37,7 @@ UIScene_LanguageSelector::UIScene_LanguageSelector(int iPad, void *initData, UIL // Setup all the Iggy references we need for this scene initialiseMovie(); + m_bNeedsLanguageReload = false; m_buttonListHowTo.init(eControl_Buttons); for(unsigned int i = 0; i < eLanguageSelector_MAX; ++i) @@ -51,6 +52,18 @@ wstring UIScene_LanguageSelector::getMoviePath() else return L"LanguagesMenu"; } +void UIScene_LanguageSelector::tick() +{ + UIScene::tick(); + + if(m_bNeedsLanguageReload) + { + m_bNeedsLanguageReload = false; + app.loadStringTable(); + reloadMovie(); + } +} + void UIScene_LanguageSelector::updateTooltips() { ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK); @@ -125,5 +138,6 @@ void UIScene_LanguageSelector::handlePress(F64 controlId, F64 childId) app.SetMinecraftLocale(m_iPad, newLocale); app.CheckGameSettingsChanged(true, m_iPad); + m_bNeedsLanguageReload = true; } } \ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_LanguageSelector.h b/Minecraft.Client/Common/UI/UIScene_LanguageSelector.h index b5c3d4c6..6e54206b 100644 --- a/Minecraft.Client/Common/UI/UIScene_LanguageSelector.h +++ b/Minecraft.Client/Common/UI/UIScene_LanguageSelector.h @@ -83,6 +83,7 @@ private: static const unsigned int m_uiHTPButtonNameA[eLanguageSelector_MAX]; UIControl_DynamicButtonList m_buttonListHowTo; + bool m_bNeedsLanguageReload; UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) UI_MAP_ELEMENT( m_buttonListHowTo, "HowToList") UI_END_MAP_ELEMENTS_AND_NAMES() @@ -92,6 +93,7 @@ public: virtual EUIScene getSceneType() { return eUIScene_LanguageSelector; } + virtual void tick(); virtual void updateTooltips(); virtual void updateComponents(); diff --git a/Minecraft.Client/Common/UI/UIScene_MainMenu.cpp b/Minecraft.Client/Common/UI/UIScene_MainMenu.cpp index c62dcf46..c0f8b8a1 100644 --- a/Minecraft.Client/Common/UI/UIScene_MainMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_MainMenu.cpp @@ -1,2174 +1,2200 @@ -#include "stdafx.h" -#include "../../../Minecraft.World/Mth.h" -#include "../../../Minecraft.World/StringHelpers.h" -#include "../../../Minecraft.World/Random.h" -#include "../../User.h" -#include "../../MinecraftServer.h" -#include "UI.h" -#include "UIScene_MainMenu.h" -#ifdef __ORBIS__ -#include -#endif - -Random *UIScene_MainMenu::random = new Random(); - -EUIScene UIScene_MainMenu::eNavigateWhenReady = static_cast(-1); - -UIScene_MainMenu::UIScene_MainMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) -{ -#ifdef __ORBIS - //m_ePatchCheckState=ePatchCheck_Idle; - m_bRunGameChosen=false; - m_bErrorDialogRunning=false; -#endif - - - // Setup all the Iggy references we need for this scene - initialiseMovie(); - - parentLayer->addComponent(iPad,eUIComponent_Panorama); - parentLayer->addComponent(iPad,eUIComponent_Logo); - - m_eAction=eAction_None; - m_bIgnorePress=false; - - - m_buttons[static_cast(eControl_PlayGame)].init(IDS_PLAY_GAME,eControl_PlayGame); - m_buttons[(int)eControl_MiniGames].init(L"Mini Games",eControl_MiniGames); - -#ifdef _XBOX_ONE - if(!ProfileManager.IsFullVersion()) m_buttons[(int)eControl_PlayGame].setLabel(IDS_PLAY_TRIAL_GAME); - app.SetReachedMainMenu(); -#endif - - m_buttons[static_cast(eControl_Leaderboards)].init(IDS_LEADERBOARDS,eControl_Leaderboards); - m_buttons[static_cast(eControl_Achievements)].init( (UIString)IDS_ACHIEVEMENTS,eControl_Achievements); - m_buttons[static_cast(eControl_HelpAndOptions)].init(IDS_HELP_AND_OPTIONS,eControl_HelpAndOptions); - if(ProfileManager.IsFullVersion()) - { - m_bTrialVersion=false; - m_buttons[static_cast(eControl_UnlockOrDLC)].init(IDS_DOWNLOADABLECONTENT,eControl_UnlockOrDLC); - } - else - { - m_bTrialVersion=true; - m_buttons[static_cast(eControl_UnlockOrDLC)].init(IDS_UNLOCK_FULL_GAME,eControl_UnlockOrDLC); - } - -#ifndef _DURANGO - m_buttons[static_cast(eControl_Exit)].init(app.GetString(IDS_EXIT_GAME),eControl_Exit); -#else - m_buttons[(int)eControl_XboxHelp].init(IDS_XBOX_HELP_APP, eControl_XboxHelp); -#endif - -#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) - // Not allowed to exit from a PS3 game from the game - have to use the PS button - removeControl( &m_buttons[(int)eControl_Exit], false ); - // We don't have a way to display trophies/achievements, so remove the button - removeControl( &m_buttons[(int)eControl_Achievements], false ); - m_bLaunchFullVersionPurchase=false; -#endif -#ifdef _DURANGO - // Allowed to not have achievements in the menu - removeControl( &m_buttons[(int)eControl_Achievements], false ); - // Not allowed to exit from a Xbox One game from the game - have to use the Home button - //removeControl( &m_buttons[(int)eControl_Exit], false ); - m_bWaitingForDLCInfo=false; -#endif - - doHorizontalResizeCheck(); - - m_splash = L""; - - wstring filename = L"splashes.txt"; - if( app.hasArchiveFile(filename) ) - { - byteArray splashesArray = app.getArchiveFile(filename); - ByteArrayInputStream bais(splashesArray); - InputStreamReader isr( &bais ); - BufferedReader br( &isr ); - - wstring line = L""; - while ( !(line = br.readLine()).empty() ) - { - line = trimString( line ); - if (line.length() > 0) - { - m_splashes.push_back(line); - } - } - - br.close(); - } - - m_bIgnorePress=false; - m_bLoadTrialOnNetworkManagerReady = false; - - // 4J Stu - Clear out any loaded game rules - app.setLevelGenerationOptions(nullptr); - - // 4J Stu - Reset the leaving game flag so that we correctly handle signouts while in the menus - g_NetworkManager.ResetLeavingGame(); - -#if TO_BE_IMPLEMENTED - // Fix for #45154 - Frontend: DLC: Content can only be downloaded from the frontend if you have not joined/exited multiplayer - XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW); -#endif -} - -UIScene_MainMenu::~UIScene_MainMenu() -{ - m_parentLayer->removeComponent(eUIComponent_Panorama); - m_parentLayer->removeComponent(eUIComponent_Logo); -} - -void UIScene_MainMenu::updateTooltips() -{ - int iX = -1; - int iA = -1; - if(!m_bIgnorePress) - { - iA = IDS_TOOLTIPS_SELECT; - -#ifdef _XBOX_ONE - iX = IDS_TOOLTIPS_CHOOSE_USER; -#elif defined __PSVITA__ - if(ProfileManager.IsFullVersion()) - { - iX = IDS_TOOLTIP_CHANGE_NETWORK_MODE; - } -#endif - } - ui.SetTooltips( DEFAULT_XUI_MENU_USER, iA, -1, iX); -} - -void UIScene_MainMenu::updateComponents() -{ - m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); - m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); -} - -void UIScene_MainMenu::handleGainFocus(bool navBack) -{ - UIScene::handleGainFocus(navBack); - ui.ShowPlayerDisplayname(false); - m_bIgnorePress=false; - - if (eNavigateWhenReady >= 0) - { - return; - } - - // 4J-JEV: This needs to come before SetLockedProfile(-1) as it wipes the XbLive contexts. - if (!navBack) - { - for (int iPad = 0; iPad < MAX_LOCAL_PLAYERS; iPad++) - { - // For returning to menus after exiting a game. - if (ProfileManager.IsSignedIn(iPad) ) - { - ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MENUS, false); - } - } - } - ProfileManager.SetLockedProfile(-1); - - m_bIgnorePress = false; - updateTooltips(); - -#ifdef _DURANGO - ProfileManager.ClearGameUsers(); -#endif - - if(navBack && ProfileManager.IsFullVersion()) - { - // Replace the Unlock Full Game with Downloadable Content - m_buttons[static_cast(eControl_UnlockOrDLC)].setLabel(IDS_DOWNLOADABLECONTENT); - } - -#if TO_BE_IMPLEMENTED - // Fix for #45154 - Frontend: DLC: Content can only be downloaded from the frontend if you have not joined/exited multiplayer - XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW); - m_Timer.SetShow(FALSE); -#endif - m_controlTimer.setVisible( false ); - - // 4J-PB - remove the "hobo humping" message legal say we can't have, and the 1080p one for Vita -#ifdef __PSVITA__ - int splashIndex = eSplashRandomStart + 2 + random->nextInt( (int)m_splashes.size() - (eSplashRandomStart + 2) ); -#else - int splashIndex = eSplashRandomStart + 1 + random->nextInt( static_cast(m_splashes.size()) - (eSplashRandomStart + 1) ); -#endif - - // Override splash text on certain dates - SYSTEMTIME LocalSysTime; - GetLocalTime( &LocalSysTime ); - if (LocalSysTime.wMonth == 11 && LocalSysTime.wDay == 9) - { - splashIndex = eSplashHappyBirthdayEx; - } - else if (LocalSysTime.wMonth == 6 && LocalSysTime.wDay == 1) - { - splashIndex = eSplashHappyBirthdayNotch; - } - else if (LocalSysTime.wMonth == 12 && LocalSysTime.wDay == 24) // the Java game shows this on Christmas Eve, so we will too - { - splashIndex = eSplashMerryXmas; - } - else if (LocalSysTime.wMonth == 1 && LocalSysTime.wDay == 1) - { - splashIndex = eSplashHappyNewYear; - } - //splashIndex = 47; // Very short string - //splashIndex = 194; // Very long string - //splashIndex = 295; // Coloured - //splashIndex = 296; // Noise - m_splash = m_splashes.at( splashIndex ); -} - -wstring UIScene_MainMenu::getMoviePath() -{ - return L"MainMenu"; -} - -void UIScene_MainMenu::handleReload() -{ -#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) - // Not allowed to exit from a PS3 game from the game - have to use the PS button - removeControl( &m_buttons[(int)eControl_Exit], false ); - // We don't have a way to display trophies/achievements, so remove the button - removeControl( &m_buttons[(int)eControl_Achievements], false ); -#endif -#ifdef _DURANGO - // Allowed to not have achievements in the menu - removeControl( &m_buttons[(int)eControl_Achievements], false ); -#endif -} - -void UIScene_MainMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) -{ - //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); - - if ( m_bIgnorePress || (eNavigateWhenReady >= 0) ) return; - -#if defined (__ORBIS__) || defined (__PSVITA__) - // ignore all players except player 0 - it's their profile that is currently being used - if(iPad!=0) return; -#endif - - ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); - - switch(key) - { - case ACTION_MENU_OK: -#ifdef __ORBIS__ - case ACTION_MENU_TOUCHPAD_PRESS: -#endif - if(pressed) - { - ProfileManager.SetPrimaryPad(iPad); - ProfileManager.SetLockedProfile(-1); - sendInputToMovie(key, repeat, pressed, released); - } - break; -#ifdef _XBOX_ONE - case ACTION_MENU_X: - if(pressed) - { - m_bIgnorePress = true; - ProfileManager.RequestSignInUI(false, false, false, false, false, ChooseUser_SignInReturned, this, iPad); - } - break; -#endif -#ifdef __PSVITA__ - case ACTION_MENU_X: - if(pressed && ProfileManager.IsFullVersion()) - { - UINT uiIDA[2]; - uiIDA[0]=IDS__NETWORK_PSN; - uiIDA[1]=IDS_NETWORK_ADHOC; - ui.RequestErrorMessage(IDS_SELECT_NETWORK_MODE_TITLE, IDS_SELECT_NETWORK_MODE_TEXT, uiIDA, 2, XUSER_INDEX_ANY, &UIScene_MainMenu::SelectNetworkModeReturned,this); - } - break; -#endif - - case ACTION_MENU_UP: - case ACTION_MENU_DOWN: - sendInputToMovie(key, repeat, pressed, released); - break; - } -} - -void UIScene_MainMenu::handlePress(F64 controlId, F64 childId) -{ - int primaryPad = ProfileManager.GetPrimaryPad(); - -#ifdef _XBOX_ONE - int (*signInReturnedFunc) (LPVOID,const bool, const int iPad, const int iController) = nullptr; -#else - int (*signInReturnedFunc) (LPVOID,const bool, const int iPad) = nullptr; -#endif - - switch(static_cast(controlId)) - { - case eControl_PlayGame: -#ifdef __ORBIS__ - { - m_bIgnorePress=true; - - //CD - Added for audio - ui.PlayUISFX(eSFX_Press); - - ProfileManager.RefreshChatAndContentRestrictions(RefreshChatAndContentRestrictionsReturned_PlayGame, this); - } -#else - m_eAction=eAction_RunGame; - //CD - Added for audio - ui.PlayUISFX(eSFX_Press); - - signInReturnedFunc = &UIScene_MainMenu::CreateLoad_SignInReturned; -#endif - break; - case eControl_MiniGames: - #ifdef __ORBIS__ - { - m_bIgnorePress=true; - - //CD - Added for audio - ui.PlayUISFX(eSFX_Press); - - ProfileManager.RefreshChatAndContentRestrictions(RefreshChatAndContentRestrictionsReturned_PlayGame, this); - } -#else - m_eAction=eAction_RunGame; - //CD - Added for audio - ui.PlayUISFX(eSFX_Press); - - signInReturnedFunc = &UIScene_MainMenu::CreateLoad_SignInReturned; -#endif - break; - case eControl_Leaderboards: - //CD - Added for audio - ui.PlayUISFX(eSFX_Press); -#ifdef __ORBIS__ - ProfileManager.RefreshChatAndContentRestrictions(RefreshChatAndContentRestrictionsReturned_Leaderboards, this); -#else - m_eAction=eAction_RunLeaderboards; - signInReturnedFunc = &UIScene_MainMenu::Leaderboards_SignInReturned; -#endif - break; - case eControl_Achievements: - //CD - Added for audio - ui.PlayUISFX(eSFX_Press); - - m_eAction=eAction_RunAchievements; - signInReturnedFunc = &UIScene_MainMenu::Achievements_SignInReturned; - break; - case eControl_HelpAndOptions: - //CD - Added for audio - ui.PlayUISFX(eSFX_Press); - - m_eAction=eAction_RunHelpAndOptions; - signInReturnedFunc = &UIScene_MainMenu::HelpAndOptions_SignInReturned; - break; - case eControl_UnlockOrDLC: - //CD - Added for audio - ui.PlayUISFX(eSFX_Press); - - m_eAction=eAction_RunUnlockOrDLC; - signInReturnedFunc = &UIScene_MainMenu::UnlockFullGame_SignInReturned; - break; - case eControl_Exit: - //CD - Added for audio - ui.PlayUISFX(eSFX_Press); - - if( ProfileManager.IsFullVersion() ) - { - UINT uiIDA[2]; - uiIDA[0]=IDS_CANCEL; - uiIDA[1]=IDS_OK; - ui.RequestErrorMessage(IDS_WINDOWS_EXIT, IDS_WARNING_ARCADE_TEXT, uiIDA, 2, XUSER_INDEX_ANY,&UIScene_MainMenu::ExitGameReturned,this); - } - else - { -#ifdef _XBOX -#ifdef _XBOX_ONE - ui.ShowPlayerDisplayname(true); -#endif - ui.NavigateToScene(primaryPad,eUIScene_TrialExitUpsell); -#endif - } - break; - -#ifdef _DURANGO - case eControl_XboxHelp: - ui.PlayUISFX(eSFX_Press); - - m_eAction=eAction_RunXboxHelp; - signInReturnedFunc = &UIScene_MainMenu::XboxHelp_SignInReturned; - break; -#endif - - default: DEBUG_BREAK(); - } - - bool confirmUser = false; - - // Note: if no sign in returned func, assume this isn't required - if (signInReturnedFunc != nullptr) - { - if(ProfileManager.IsSignedIn(primaryPad)) - { - if (confirmUser) - { - ProfileManager.RequestSignInUI(false, false, true, false, true, signInReturnedFunc, this, primaryPad); - } - else - { - RunAction(primaryPad); - } - } - else - { - // Ask user to sign in - UINT uiIDA[2]; - uiIDA[0]=IDS_CONFIRM_OK; - uiIDA[1]=IDS_CONFIRM_CANCEL; - ui.RequestErrorMessage(IDS_MUST_SIGN_IN_TITLE, IDS_MUST_SIGN_IN_TEXT, uiIDA, 2, primaryPad, &UIScene_MainMenu::MustSignInReturned, this); - } - } -} - -// Run current action -void UIScene_MainMenu::RunAction(int iPad) -{ - switch(m_eAction) - { - case eAction_RunGame: - RunPlayGame(iPad); - break; - case eAction_RunLeaderboards: - RunLeaderboards(iPad); - break; - case eAction_RunAchievements: - RunAchievements(iPad); - break; - case eAction_RunHelpAndOptions: - RunHelpAndOptions(iPad); - break; - case eAction_RunUnlockOrDLC: - RunUnlockOrDLC(iPad); - break; -#ifdef _DURANGO - case eAction_RunXboxHelp: - // 4J: Launch the dummy xbox help application. - WXS::User^ user = ProfileManager.GetUser(ProfileManager.GetPrimaryPad()); - Windows::Xbox::ApplicationModel::Help::Show(user); - break; -#endif - } -} - -void UIScene_MainMenu::customDraw(IggyCustomDrawCallbackRegion *region) -{ - if(wcscmp((wchar_t *)region->name,L"Splash")==0) - { - PIXBeginNamedEvent(0,"Custom draw splash"); - customDrawSplash(region); - PIXEndNamedEvent(); - } -} - -void UIScene_MainMenu::customDrawSplash(IggyCustomDrawCallbackRegion *region) -{ - Minecraft *pMinecraft = Minecraft::GetInstance(); - - // 4J Stu - Move this to the ctor when the main menu is not the first scene we navigate to - ScreenSizeCalculator ssc(pMinecraft->options, pMinecraft->width_phys, pMinecraft->height_phys); - m_fScreenWidth=static_cast(pMinecraft->width_phys); - m_fRawWidth=static_cast(ssc.rawWidth); - m_fScreenHeight=static_cast(pMinecraft->height_phys); - m_fRawHeight=static_cast(ssc.rawHeight); - - - // Setup GDraw, normal game render states and matrices - CustomDrawData *customDrawRegion = ui.setupCustomDraw(this,region); - delete customDrawRegion; - - - Font *font = pMinecraft->font; - - // build and render with the game call - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - - glPushMatrix(); - - float width = region->x1 - region->x0; - float height = region->y1 - region->y0; - float xo = width/2; - float yo = height; - - glTranslatef(xo, yo, 0); - - glRotatef(-17, 0, 0, 1); - float sss = 1.8f - Mth::abs(Mth::sin(System::currentTimeMillis() % 1000 / 1000.0f * PI * 2) * 0.1f); - sss*=(m_fScreenWidth/m_fRawWidth); - - sss = sss * 100 / (font->width(m_splash) + 8 * 4); - glScalef(sss, sss, sss); - //drawCenteredString(font, splash, 0, -8, 0xffff00); - font->drawShadow(m_splash, 0 - (font->width(m_splash)) / 2, -8, 0xffff00); - glPopMatrix(); - - glDisable(GL_RESCALE_NORMAL); - - glEnable(GL_DEPTH_TEST); - - - // Finish GDraw and anything else that needs to be finalised - ui.endCustomDraw(region); -} - -int UIScene_MainMenu::MustSignInReturned(void *pParam, int iPad, C4JStorage::EMessageResult result) -{ - UIScene_MainMenu* pClass = static_cast(pParam); - - if(result==C4JStorage::EMessage_ResultAccept) - { - // we need to specify local game here to display local and LIVE profiles in the list - switch(pClass->m_eAction) - { - case eAction_RunGame: ProfileManager.RequestSignInUI(false, true, false, false, true, &UIScene_MainMenu::CreateLoad_SignInReturned, pClass, iPad ); break; - case eAction_RunHelpAndOptions: ProfileManager.RequestSignInUI(false, false, true, false, true, &UIScene_MainMenu::HelpAndOptions_SignInReturned, pClass, iPad ); break; - case eAction_RunLeaderboards: ProfileManager.RequestSignInUI(false, false, true, false, true, &UIScene_MainMenu::Leaderboards_SignInReturned, pClass, iPad ); break; - case eAction_RunAchievements: ProfileManager.RequestSignInUI(false, false, true, false, true, &UIScene_MainMenu::Achievements_SignInReturned, pClass, iPad ); break; - case eAction_RunUnlockOrDLC: ProfileManager.RequestSignInUI(false, false, true, false, true, &UIScene_MainMenu::UnlockFullGame_SignInReturned, pClass, iPad ); break; -#ifdef _DURANGO - case eAction_RunXboxHelp: ProfileManager.RequestSignInUI(false, false, true, false, true, &UIScene_MainMenu::XboxHelp_SignInReturned, pClass, iPad ); break; -#endif - } - } - else - { - pClass->m_bIgnorePress=false; - // unlock the profile - ProfileManager.SetLockedProfile(-1); - for(int i=0;im_eAction) - { - case eAction_RunLeaderboardsPSN: - SQRNetworkManager_PS3::AttemptPSNSignIn(&UIScene_MainMenu::Leaderboards_SignInReturned, pClass); - break; - case eAction_RunGamePSN: - SQRNetworkManager_PS3::AttemptPSNSignIn(&UIScene_MainMenu::CreateLoad_SignInReturned, pClass); - break; - case eAction_RunUnlockOrDLCPSN: - SQRNetworkManager_PS3::AttemptPSNSignIn(&UIScene_MainMenu::UnlockFullGame_SignInReturned, pClass); - break; - } -#elif defined __PSVITA__ - switch(pClass->m_eAction) - { - case eAction_RunLeaderboardsPSN: - //CD - Must force Ad-Hoc off if they want leaderboard PSN sign-in - //Save settings change - app.SetGameSettings(0, eGameSetting_PSVita_NetworkModeAdhoc, 0); - //Force off - CGameNetworkManager::setAdhocMode(false); - //Now Sign-in - SQRNetworkManager_Vita::AttemptPSNSignIn(&UIScene_MainMenu::Leaderboards_SignInReturned, pClass); - break; - case eAction_RunGamePSN: - if(CGameNetworkManager::usingAdhocMode()) - { - SQRNetworkManager_AdHoc_Vita::AttemptAdhocSignIn(&UIScene_MainMenu::CreateLoad_SignInReturned, pClass); - } - else - { - SQRNetworkManager_Vita::AttemptPSNSignIn(&UIScene_MainMenu::CreateLoad_SignInReturned, pClass); - - } - break; - case eAction_RunUnlockOrDLCPSN: - //CD - Must force Ad-Hoc off if they want commerce PSN sign-in - //Save settings change - app.SetGameSettings(0, eGameSetting_PSVita_NetworkModeAdhoc, 0); - //Force off - CGameNetworkManager::setAdhocMode(false); - //Now Sign-in - SQRNetworkManager_Vita::AttemptPSNSignIn(&UIScene_MainMenu::UnlockFullGame_SignInReturned, pClass); - break; - } -#else - switch(pClass->m_eAction) - { - case eAction_RunLeaderboardsPSN: - SQRNetworkManager_Orbis::AttemptPSNSignIn(&UIScene_MainMenu::Leaderboards_SignInReturned, pClass, true, iPad); - break; - case eAction_RunGamePSN: - SQRNetworkManager_Orbis::AttemptPSNSignIn(&UIScene_MainMenu::CreateLoad_SignInReturned, pClass, true, iPad); - break; - case eAction_RunUnlockOrDLCPSN: - SQRNetworkManager_Orbis::AttemptPSNSignIn(&UIScene_MainMenu::UnlockFullGame_SignInReturned, pClass, true, iPad); - break; - } - -#endif - } - else - { - if( pClass->m_eAction == eAction_RunGamePSN ) - { - if( result == C4JStorage::EMessage_Cancelled) - CreateLoad_SignInReturned(pClass, false, 0); - else - CreateLoad_SignInReturned(pClass, true, 0); - } - else - { - pClass->m_bIgnorePress=false; - } - } - - return 0; -} -#endif - -#ifdef _XBOX_ONE -int UIScene_MainMenu::HelpAndOptions_SignInReturned(void *pParam,bool bContinue,int iPad, int iController) -#else -int UIScene_MainMenu::HelpAndOptions_SignInReturned(void *pParam,bool bContinue,int iPad) -#endif -{ - UIScene_MainMenu *pClass = static_cast(pParam); - - if(bContinue) - { - // 4J-JEV: Don't we only need to update rich-presence if the sign-in status changes. - ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MENUS, false); - -#if TO_BE_IMPLEMENTED - if(app.GetTMSDLCInfoRead()) -#endif - { - ProfileManager.SetLockedProfile(ProfileManager.GetPrimaryPad()); -#ifdef _XBOX_ONE - ui.ShowPlayerDisplayname(true); -#endif - proceedToScene(iPad, eUIScene_HelpAndOptionsMenu); - } -#if TO_BE_IMPLEMENTED - else - { - // Changing to async TMS calls - app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_HelpAndOptions); - - // block all input - pClass->m_bIgnorePress=true; - // We want to hide everything in this scene and display a timer until we get a completion for the TMS files - for(int i=0;im_Buttons[i].SetShow(FALSE); - } - - pClass->updateTooltips(); - - pClass->m_Timer.SetShow(TRUE); - } -#endif - } - else - { - pClass->m_bIgnorePress=false; - // unlock the profile - ProfileManager.SetLockedProfile(-1); - for(int i=0;im_bIgnorePress = false; - pClass->updateTooltips(); - return 0; -} -#endif - -#ifdef _XBOX_ONE -int UIScene_MainMenu::CreateLoad_SignInReturned(void *pParam, bool bContinue, int iPad, int iController) -#else -int UIScene_MainMenu::CreateLoad_SignInReturned(void *pParam, bool bContinue, int iPad) -#endif -{ - UIScene_MainMenu* pClass = static_cast(pParam); - - if(bContinue) - { - // 4J-JEV: We only need to update rich-presence if the sign-in status changes. - ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MENUS, false); - - UINT uiIDA[1] = { IDS_OK }; - - if(ProfileManager.IsGuest(ProfileManager.GetPrimaryPad())) - { - pClass->m_bIgnorePress=false; - ui.RequestErrorMessage(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); - } - else - { - ProfileManager.SetLockedProfile(ProfileManager.GetPrimaryPad()); - - - // change the minecraft player name - Minecraft::GetInstance()->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); - - if(ProfileManager.IsFullVersion()) - { - bool bSignedInLive = ProfileManager.IsSignedInLive(iPad); -#ifdef __PSVITA__ - if(CGameNetworkManager::usingAdhocMode()) - { - if(SQRNetworkManager_AdHoc_Vita::GetAdhocStatus()) - { - bSignedInLive = true; - } - else - { - // adhoc mode, but we didn't make the connection, turn off adhoc mode, and just go with whatever the regular online status is - CGameNetworkManager::setAdhocMode(false); - bSignedInLive = ProfileManager.IsSignedInLive(iPad); - } - } -#endif - - // Check if we're signed in to LIVE - if(bSignedInLive) - { - // 4J-PB - Need to check for installed DLC - if(!app.DLCInstallProcessCompleted()) app.StartInstallDLCProcess(iPad); - - if(ProfileManager.IsGuest(iPad)) - { - pClass->m_bIgnorePress=false; - ui.RequestErrorMessage(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); - } - else - { - // 4J Stu - Not relevant to PS3 -#ifdef _XBOX_ONE -// if(app.GetTMSDLCInfoRead() && app.GetBanListRead(iPad)) - if(app.GetBanListRead(iPad)) - { - Minecraft *pMinecraft=Minecraft::GetInstance(); - pMinecraft->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); - - // ensure we've applied this player's settings - app.ApplyGameSettingsChanged(iPad); - -#ifdef _XBOX_ONE - ui.ShowPlayerDisplayname(true); -#endif - proceedToScene(ProfileManager.GetPrimaryPad(), eUIScene_LoadCreateJoinMenu); - } - else - { - app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_RunPlayGame); - - // block all input - pClass->m_bIgnorePress=true; - // We want to hide everything in this scene and display a timer until we get a completion for the TMS files - // for(int i=0;iupdateTooltips(); - - pClass->m_controlTimer.setVisible( true ); - } -#endif -#if TO_BE_IMPLEMENTED - // check if all the TMS files are loaded - if(app.GetTMSDLCInfoRead() && app.GetTMSXUIDsFileRead() && app.GetBanListRead(iPad)) - { - if(StorageManager.SetSaveDevice(&UIScene_MainMenu::DeviceSelectReturned,pClass)==true) - { - // save device already selected - - // ensure we've applied this player's settings - app.ApplyGameSettingsChanged(ProfileManager.GetPrimaryPad()); - // check for DLC - // start timer to track DLC check finished - pClass->m_Timer.SetShow(TRUE); - XuiSetTimer(pClass->m_hObj,DLC_INSTALLED_TIMER_ID,DLC_INSTALLED_TIMER_TIME); - //app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_MultiGameJoinLoad); - } - } - else - { - // Changing to async TMS calls - app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_RunPlayGame); - - // block all input - pClass->m_bIgnorePress=true; - // We want to hide everything in this scene and display a timer until we get a completion for the TMS files - for(int i=0;im_Buttons[i].SetShow(FALSE); - } - - updateTooltips(); - - pClass->m_Timer.SetShow(TRUE); - } -#else - Minecraft *pMinecraft=Minecraft::GetInstance(); - pMinecraft->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); - - // ensure we've applied this player's settings - app.ApplyGameSettingsChanged(iPad); - -#ifdef _XBOX_ONE - ui.ShowPlayerDisplayname(true); -#endif - proceedToScene(ProfileManager.GetPrimaryPad(), eUIScene_LoadCreateJoinMenu); -#endif - } - } - else - { -#if TO_BE_IMPLEMENTED - // offline - ProfileManager.DisplayOfflineProfile(&CScene_Main::CreateLoad_OfflineProfileReturned,pClass, ProfileManager.GetPrimaryPad() ); -#else - app.DebugPrintf("Offline Profile returned not implemented\n"); -#ifdef _XBOX_ONE - ui.ShowPlayerDisplayname(true); -#endif - proceedToScene(ProfileManager.GetPrimaryPad(), eUIScene_LoadCreateJoinMenu); -#endif - } - } - else - { - // 4J-PB - if this is the trial game, we can't have any networking - // Can't apply the player's settings here - they haven't come back from the QuerySignInStatud call above yet. - // Need to let them action in the main loop when they come in - // ensure we've applied this player's settings - //app.ApplyGameSettingsChanged(iPad); - -#if defined(__PS3__) || defined(__ORBIS__) || defined( __PSVITA__) - // ensure we've applied this player's settings - we do have them on PS3 - app.ApplyGameSettingsChanged(iPad); -#endif - -#ifdef __ORBIS__ - if(!g_NetworkManager.IsReadyToPlayOrIdle()) - { - pClass->m_bLoadTrialOnNetworkManagerReady = true; - ui.NavigateToScene(iPad, eUIScene_Timer); - } - else -#endif - { - // go straight in to the trial level - LoadTrial(); - } - } - } - } - else - { - pClass->m_bIgnorePress=false; - - // unlock the profile - ProfileManager.SetLockedProfile(-1); - for(int i=0;i(pParam); - - if(bContinue) - { - // 4J-JEV: We only need to update rich-presence if the sign-in status changes. - ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MENUS, false); - - UINT uiIDA[1] = { IDS_OK }; - - // guests can't look at leaderboards - if(ProfileManager.IsGuest(ProfileManager.GetPrimaryPad())) - { - pClass->m_bIgnorePress=false; - ui.RequestErrorMessage(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); - } - else if(!ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad())) - { - pClass->m_bIgnorePress=false; - ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1); - } - else - { - bool bContentRestricted=false; -#if defined(__PS3__) || defined(__PSVITA__) - ProfileManager.GetChatAndContentRestrictions(iPad,true,nullptr,&bContentRestricted,nullptr); -#endif - if(bContentRestricted) - { - pClass->m_bIgnorePress=false; -#if !(defined(_XBOX) || defined(_WINDOWS64) || defined(_XBOX_ONE) ) // 4J Stu - Temp to get the win build running, but so we check this for other platforms - // you can't see leaderboards - UINT uiIDA[1]; - uiIDA[0]=IDS_CONFIRM_OK; - ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad()); -#endif - } - else - { - ProfileManager.SetLockedProfile(ProfileManager.GetPrimaryPad()); -#ifdef _XBOX_ONE - ui.ShowPlayerDisplayname(true); -#endif - proceedToScene(ProfileManager.GetPrimaryPad(), eUIScene_LeaderboardsMenu); - } - } - } - else - { - pClass->m_bIgnorePress=false; - // unlock the profile - ProfileManager.SetLockedProfile(-1); - for(int i=0;i(pParam); - - if (bContinue) - { - pClass->m_bIgnorePress=false; - // 4J-JEV: We only need to update rich-presence if the sign-in status changes. - ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MENUS, false); - - XShowAchievementsUI( ProfileManager.GetPrimaryPad() ); - } - else - { - pClass->m_bIgnorePress=false; - // unlock the profile - ProfileManager.SetLockedProfile(-1); - for(int i=0;i(pParam); - - if (bContinue) - { - // 4J-JEV: We only need to update rich-presence if the sign-in status changes. - ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MENUS, false); - - pClass->RunUnlockOrDLC(iPad); - } - else - { - pClass->m_bIgnorePress=false; - // unlock the profile - ProfileManager.SetLockedProfile(-1); - for(int i=0;im_errorCode = ProfileManager.getNPAvailability(ProfileManager.GetPrimaryPad()); - - bool bPatchAvailable; - switch(pClass->m_errorCode) - { - case SCE_NP_ERROR_LATEST_PATCH_PKG_EXIST: - case SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED: - bPatchAvailable=true; - break; - default: - bPatchAvailable=false; - break; - } - - if(!bPatchAvailable) - { - pClass->m_eAction=eAction_RunGame; - signInReturnedFunc = &UIScene_MainMenu::CreateLoad_SignInReturned; - } - else - { - pClass->m_bRunGameChosen=true; - pClass->m_bErrorDialogRunning=true; - int32_t ret=sceErrorDialogInitialize(); - if ( ret==SCE_OK ) - { - SceErrorDialogParam param; - sceErrorDialogParamInitialize( ¶m ); - // 4J-PB - We want to display the option to get the patch now - param.errorCode = SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED;//pClass->m_errorCode; - ret = sceUserServiceGetInitialUser( ¶m.userId ); - if ( ret == SCE_OK ) - { - ret=sceErrorDialogOpen( ¶m ); - } - return; - } - -// UINT uiIDA[1]; -// uiIDA[0]=IDS_OK; -// ui.RequestMessageBox(IDS_PATCH_AVAILABLE_TITLE, IDS_PATCH_AVAILABLE_TEXT, uiIDA, 1, XUSER_INDEX_ANY,nullptr,pClass); - } - - // Check if PSN is unavailable because of age restriction - if (pClass->m_errorCode == SCE_NP_ERROR_AGE_RESTRICTION) - { - UINT uiIDA[1]; - uiIDA[0]=IDS_PRO_NOTONLINE_DECLINE; - ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(), &UIScene_MainMenu::PlayOfflineReturned, pClass); - - return; - } - - bool confirmUser = false; - - // Note: if no sign in returned func, assume this isn't required - if (signInReturnedFunc != nullptr) - { - if(ProfileManager.IsSignedIn(primaryPad)) - { - if (confirmUser) - { - ProfileManager.RequestSignInUI(false, false, true, false, true, signInReturnedFunc, pClass, primaryPad); - } - else - { - pClass->RunAction(primaryPad); - } - } - else - { - // Ask user to sign in - UINT uiIDA[2]; - uiIDA[0]=IDS_CONFIRM_OK; - uiIDA[1]=IDS_CONFIRM_CANCEL; - ui.RequestErrorMessage(IDS_MUST_SIGN_IN_TITLE, IDS_MUST_SIGN_IN_TEXT, uiIDA, 2, primaryPad, &UIScene_MainMenu::MustSignInReturned, pClass); - } - } -} - -void UIScene_MainMenu::RefreshChatAndContentRestrictionsReturned_Leaderboards(void *pParam) -{ - int primaryPad = ProfileManager.GetPrimaryPad(); - - UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; - - int (*signInReturnedFunc) (LPVOID,const bool, const int iPad) = nullptr; - - // 4J-PB - Check if there is a patch for the game - pClass->m_errorCode = ProfileManager.getNPAvailability(ProfileManager.GetPrimaryPad()); - - bool bPatchAvailable; - switch(pClass->m_errorCode) - { - case SCE_NP_ERROR_LATEST_PATCH_PKG_EXIST: - case SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED: - bPatchAvailable=true; - break; - default: - bPatchAvailable=false; - break; - } - - if(!bPatchAvailable) - { - pClass->m_eAction=eAction_RunLeaderboards; - signInReturnedFunc = &UIScene_MainMenu::Leaderboards_SignInReturned; - } - else - { - int32_t ret=sceErrorDialogInitialize(); - pClass->m_bErrorDialogRunning=true; - if ( ret==SCE_OK ) - { - SceErrorDialogParam param; - sceErrorDialogParamInitialize( ¶m ); - // 4J-PB - We want to display the option to get the patch now - param.errorCode = SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED;//pClass->m_errorCode; - ret = sceUserServiceGetInitialUser( ¶m.userId ); - if ( ret == SCE_OK ) - { - ret=sceErrorDialogOpen( ¶m ); - } - } - -// UINT uiIDA[1]; -// uiIDA[0]=IDS_OK; -// ui.RequestMessageBox(IDS_PATCH_AVAILABLE_TITLE, IDS_PATCH_AVAILABLE_TEXT, uiIDA, 1, XUSER_INDEX_ANY,nullptr,pClass); - } - - bool confirmUser = false; - - // Update error code - pClass->m_errorCode = ProfileManager.getNPAvailability(ProfileManager.GetPrimaryPad()); - - // Check if PSN is unavailable because of age restriction - if (pClass->m_errorCode == SCE_NP_ERROR_AGE_RESTRICTION) - { - UINT uiIDA[1]; - uiIDA[0] = IDS_CONFIRM_OK; - ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(), nullptr, pClass); - - return; - } - - // Note: if no sign in returned func, assume this isn't required - if (signInReturnedFunc != nullptr) - { - if(ProfileManager.IsSignedIn(primaryPad)) - { - if (confirmUser) - { - ProfileManager.RequestSignInUI(false, false, true, false, true, signInReturnedFunc, pClass, primaryPad); - } - else - { - pClass->RunAction(primaryPad); - } - } - else - { - // Ask user to sign in - UINT uiIDA[2]; - uiIDA[0]=IDS_CONFIRM_OK; - uiIDA[1]=IDS_CONFIRM_CANCEL; - ui.RequestErrorMessage(IDS_MUST_SIGN_IN_TITLE, IDS_MUST_SIGN_IN_TEXT, uiIDA, 2, primaryPad, &UIScene_MainMenu::MustSignInReturned, pClass); - } - } -} - -int UIScene_MainMenu::PlayOfflineReturned(void *pParam, int iPad, C4JStorage::EMessageResult result) -{ - UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; - - if(result==C4JStorage::EMessage_ResultAccept) - { - if (pClass->m_eAction == eAction_RunGame) - { - CreateLoad_SignInReturned(pClass, true, 0); - } - else - { - pClass->m_bIgnorePress=false; - } - } - else - { - pClass->m_bIgnorePress=false; - } - - return 0; -} -#endif - -void UIScene_MainMenu::RunPlayGame(int iPad) -{ - Minecraft *pMinecraft=Minecraft::GetInstance(); - - // clear the remembered signed in users so their profiles get read again - app.ClearSignInChangeUsersMask(); - - app.ReleaseSaveThumbnail(); - - if(ProfileManager.IsGuest(iPad)) - { - UINT uiIDA[1]; - uiIDA[0]=IDS_OK; - - m_bIgnorePress=false; - ui.RequestErrorMessage(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); - } - else - { - ProfileManager.SetLockedProfile(iPad); - - // If the player was signed in before selecting play, we'll not have read the profile yet, so query the sign-in status to get this to happen - ProfileManager.QuerySigninStatus(); - - // 4J-PB - Need to check for installed DLC - if(!app.DLCInstallProcessCompleted()) app.StartInstallDLCProcess(iPad); - - if(ProfileManager.IsFullVersion()) - { - // are we offline? - bool bSignedInLive = ProfileManager.IsSignedInLive(iPad); -#ifdef __PSVITA__ - if(app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_PSVita_NetworkModeAdhoc) == true) - { - CGameNetworkManager::setAdhocMode(true); - bSignedInLive = SQRNetworkManager_AdHoc_Vita::GetAdhocStatus(); - app.DebugPrintf("Adhoc mode signed in : %s\n", bSignedInLive ? "true" : "false"); - } - else - { - CGameNetworkManager::setAdhocMode(false); - app.DebugPrintf("PSN mode signed in : %s\n", bSignedInLive ? "true" : "false"); - } - -#endif //__PSVITA__ - - if(!bSignedInLive) - { -#if defined(__PS3__) || defined __PSVITA__ - // enable input again - m_bIgnorePress=false; - - // Not sure why 360 doesn't need this, but leaving as __PS3__ only for now until we see that it does. Without this, on a PS3 offline game, the primary player just gets the default Player1234 type name - pMinecraft->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); - - m_eAction=eAction_RunGamePSN; - // get them to sign in to online - UINT uiIDA[2]; - uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; - uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; - -#ifdef __PSVITA__ - if(CGameNetworkManager::usingAdhocMode()) - { - uiIDA[0]=IDS_NETWORK_ADHOC; - // this should be "Connect to adhoc network" - ui.RequestErrorMessage(IDS_PRO_NOTADHOCONLINE_TITLE, IDS_PRO_NOTADHOCONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&UIScene_MainMenu::MustSignInReturnedPSN,this); - } - else - { - /* 4J-PB - Add this after release - // Determine why they're not "signed in live" - if (ProfileManager.IsSignedInPSN(iPad)) - { - m_eAction=eAction_RunGame; - // Signed in to PSN but not connected (no internet access) - - UINT uiIDA[1]; - uiIDA[0] = IDS_PRO_NOTONLINE_DECLINE; - ui.RequestMessageBox( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad, UIScene_MainMenu::PlayOfflineReturned, this, app.GetStringTable()); - } - else - { - m_eAction=eAction_RunGamePSN; - // Not signed in to PSN - ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, iPad, &UIScene_MainMenu::MustSignInReturnedPSN, this, app.GetStringTable()); - return; - } */ - ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&UIScene_MainMenu::MustSignInReturnedPSN,this); - - } -#else - - ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, iPad, &UIScene_MainMenu::MustSignInReturnedPSN, this); -#endif - -#elif defined __ORBIS__ - - // Determine why they're not "signed in live" - if (ProfileManager.isSignedInPSN(iPad)) - { - m_eAction=eAction_RunGame; - // Signed in to PSN but not connected (no internet access) - assert(!ProfileManager.isConnectedToPSN(iPad)); - - UINT uiIDA[1]; - uiIDA[0] = IDS_PRO_NOTONLINE_DECLINE; - ui.RequestErrorMessage( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad, UIScene_MainMenu::PlayOfflineReturned, this); - } - else - { - m_eAction=eAction_RunGamePSN; - // Not signed in to PSN - UINT uiIDA[2]; - uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; - uiIDA[1] = IDS_PRO_NOTONLINE_DECLINE; - ui.RequestAlertMessage( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, iPad, &UIScene_MainMenu::MustSignInReturnedPSN, this); - return; - } -#else - ProfileManager.SetLockedProfile(iPad); -#ifdef _XBOX_ONE - ui.ShowPlayerDisplayname(true); -#endif - proceedToScene(ProfileManager.GetPrimaryPad(), eUIScene_LoadCreateJoinMenu); -#endif - } - else - { -#ifdef _XBOX_ONE - if(!app.GetBanListRead(iPad)) - { - app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_RunPlayGame); - - // block all input - m_bIgnorePress=true; - // We want to hide everything in this scene and display a timer until we get a completion for the TMS files -// for(int i=0;iuser->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); - // save device already selected - - // ensure we've applied this player's settings - app.ApplyGameSettingsChanged(iPad); - // check for DLC - // start timer to track DLC check finished - m_Timer.SetShow(TRUE); - XuiSetTimer(m_hObj,DLC_INSTALLED_TIMER_ID,DLC_INSTALLED_TIMER_TIME); - //app.NavigateToScene(iPad,eUIScene_MultiGameJoinLoad); - } - } - else - { - // Changing to async TMS calls - app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_RunPlayGame); - - // block all input - m_bIgnorePress=true; - // We want to hide everything in this scene and display a timer until we get a completion for the TMS files - for(int i=0;iuser->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); - - // ensure we've applied this player's settings - app.ApplyGameSettingsChanged(iPad); - -#ifdef _XBOX_ONE - ui.ShowPlayerDisplayname(true); -#endif - proceedToScene(ProfileManager.GetPrimaryPad(), eUIScene_LoadCreateJoinMenu); -#endif - } - } - else - { - // 4J-PB - if this is the trial game, we can't have any networking - // go straight in to the trial level - // change the minecraft player name - Minecraft::GetInstance()->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); - - // Can't apply the player's settings here - they haven't come back from the QuerySignInStatud call above yet. - // Need to let them action in the main loop when they come in - // ensure we've applied this player's settings - //app.ApplyGameSettingsChanged(iPad); - -#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) - // ensure we've applied this player's settings - we do have them on PS3 - app.ApplyGameSettingsChanged(iPad); -#endif - -#ifdef __ORBIS__ - if(!g_NetworkManager.IsReadyToPlayOrIdle()) - { - m_bLoadTrialOnNetworkManagerReady = true; - ui.NavigateToScene(iPad, eUIScene_Timer); - } - else -#endif - { - LoadTrial(); - } - } - } -} - -void UIScene_MainMenu::RunLeaderboards(int iPad) -{ - UINT uiIDA[1]; - uiIDA[0]=IDS_OK; - - // guests can't look at leaderboards - if(ProfileManager.IsGuest(iPad)) - { - ui.RequestErrorMessage(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); - } - else if(!ProfileManager.IsSignedInLive(iPad)) - { -#if defined __PS3__ || defined __PSVITA__ - m_eAction=eAction_RunLeaderboardsPSN; - // get them to sign in to online - UINT uiIDA[1]; - uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; - ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(),&UIScene_MainMenu::MustSignInReturnedPSN,this); - -/* 4J-PB - Add this after release -#elif defined __PSVITA__ - m_eAction=eAction_RunLeaderboardsPSN; - // Determine why they're not "signed in live" - if (ProfileManager.IsSignedInPSN(iPad)) - { - // Signed in to PSN but not connected (no internet access) - UINT uiIDA[1]; - uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; - ui.RequestMessageBox(IDS_PRO_CURRENTLY_NOT_ONLINE_TITLE, IDS_PRO_PSNOFFLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(), &UIScene_MainMenu::MustSignInReturnedPSN, this, app.GetStringTable()); - } - else - { - // Not signed in to PSN - UINT uiIDA[1]; - uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; - ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(), &UIScene_MainMenu::MustSignInReturnedPSN, this, app.GetStringTable()); - return; - }*/ -#elif defined __ORBIS__ - m_eAction=eAction_RunLeaderboardsPSN; - // Determine why they're not "signed in live" - if (ProfileManager.isSignedInPSN(iPad)) - { - // Signed in to PSN but not connected (no internet access) - assert(!ProfileManager.isConnectedToPSN(iPad)); - - UINT uiIDA[1]; - uiIDA[0] = IDS_OK; - ui.RequestErrorMessage( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad); - } - else - { - // Not signed in to PSN - UINT uiIDA[1]; - uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; - ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(), &UIScene_MainMenu::MustSignInReturnedPSN, this); - return; - } -#else - ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1); -#endif - } - else - { - // we're supposed to check for parental control restrictions before showing leaderboards - // The title enforces the user's NP parental control setting for age-based content - //restriction in network communications. - // If age restrictions are in place and the user's age does not meet - // the age restriction of the title's online service content rating (CERO, ESRB, PEGI, etc.), then the title must - //display a message such as the following and disallow online service for this user. - - bool bContentRestricted=false; -#if defined(__PS3__) || defined(__PSVITA__) - ProfileManager.GetChatAndContentRestrictions(iPad,true,nullptr,&bContentRestricted,nullptr); -#endif - if(bContentRestricted) - { -#if !(defined(_XBOX) || defined(_WINDOWS64) || defined(_XBOX_ONE)) // 4J Stu - Temp to get the win build running, but so we check this for other platforms - // you can't see leaderboards - UINT uiIDA[1]; - uiIDA[0]=IDS_CONFIRM_OK; - ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(),nullptr,this); -#endif - } - else - { - ProfileManager.SetLockedProfile(iPad); - // If the player was signed in before selecting play, we'll not have read the profile yet, so query the sign-in status to get this to happen - ProfileManager.QuerySigninStatus(); - -#ifdef _XBOX_ONE - ui.ShowPlayerDisplayname(true); -#endif - proceedToScene(iPad, eUIScene_LeaderboardsMenu); - } - } -} -void UIScene_MainMenu::RunUnlockOrDLC(int iPad) -{ - UINT uiIDA[1]; - uiIDA[0]=IDS_OK; - - // Check if this means downloadable content - if(ProfileManager.IsFullVersion()) - { -#ifdef __ORBIS__ - // 4J-PB - Check if there is a patch for the game - m_errorCode = ProfileManager.getNPAvailability(ProfileManager.GetPrimaryPad()); - - bool bPatchAvailable; - switch(m_errorCode) - { - case SCE_NP_ERROR_LATEST_PATCH_PKG_EXIST: - case SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED: - bPatchAvailable=true; - break; - default: - bPatchAvailable=false; - break; - } - - if(bPatchAvailable) - { - m_bIgnorePress=false; - - int32_t ret=sceErrorDialogInitialize(); - m_bErrorDialogRunning=true; - if ( ret==SCE_OK ) - { - SceErrorDialogParam param; - sceErrorDialogParamInitialize( ¶m ); - // 4J-PB - We want to display the option to get the patch now - param.errorCode = SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED;//pClass->m_errorCode; - ret = sceUserServiceGetInitialUser( ¶m.userId ); - if ( ret == SCE_OK ) - { - ret=sceErrorDialogOpen( ¶m ); - } - } - -// UINT uiIDA[1]; -// uiIDA[0]=IDS_OK; -// ui.RequestMessageBox(IDS_PATCH_AVAILABLE_TITLE, IDS_PATCH_AVAILABLE_TEXT, uiIDA, 1, XUSER_INDEX_ANY,nullptr,this); - return; - } - - // Check if PSN is unavailable because of age restriction - if (m_errorCode == SCE_NP_ERROR_AGE_RESTRICTION) - { - m_bIgnorePress=false; - UINT uiIDA[1]; - uiIDA[0] = IDS_OK; - ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(), nullptr, this); - - return; - } -#endif - // downloadable content - if(ProfileManager.IsSignedInLive(iPad)) - { - if(ProfileManager.IsGuest(iPad)) - { - m_bIgnorePress=false; - ui.RequestErrorMessage(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); - } - else - { - - // If the player was signed in before selecting play, we'll not have read the profile yet, so query the sign-in status to get this to happen - ProfileManager.QuerySigninStatus(); - -#if defined _XBOX_ONE - if(app.GetTMSDLCInfoRead()) -#endif - { - bool bContentRestricted=false; -#if defined(__PS3__) || defined(__PSVITA__) - ProfileManager.GetChatAndContentRestrictions(iPad,true,nullptr,&bContentRestricted,nullptr); -#endif - if(bContentRestricted) - { - m_bIgnorePress=false; -#if !(defined(_XBOX) || defined(_WINDOWS64) || defined(_XBOX_ONE)) // 4J Stu - Temp to get the win build running, but so we check this for other platforms - // you can't see the store - UINT uiIDA[1]; - uiIDA[0]=IDS_CONFIRM_OK; - ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(),nullptr,this); -#endif - } - else - { - ProfileManager.SetLockedProfile(iPad); -#ifdef _XBOX_ONE - ui.ShowPlayerDisplayname(true); -#endif - proceedToScene(ProfileManager.GetPrimaryPad(), eUIScene_DLCMainMenu); - } - } -#if defined _XBOX_ONE - else - { - // Changing to async TMS calls - app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_DLCMain); - - // block all input - m_bIgnorePress=true; - // We want to hide everything in this scene and display a timer until we get a completion for the TMS files -// for(int i=0;iRecordUpsellPresented(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID); - ProfileManager.DisplayFullVersionPurchase(false,iPad,eSen_UpsellID_Full_Version_Of_Game); -#endif - } - } -} - -void UIScene_MainMenu::tick() -{ - UIScene::tick(); - - if ( (eNavigateWhenReady >= 0) ) - { - - int lockedProfile = ProfileManager.GetLockedProfile(); - -#ifdef _DURANGO - // 4J-JEV: DLC menu contains text localised to system language which we can't change. - // We need to switch to this language in-case it uses a different font. - if (eNavigateWhenReady == eUIScene_DLCMainMenu) setLanguageOverride(false); - - bool isSignedIn; - C4JStorage::eOptionsCallback status; - bool pendingFontChange; - if (lockedProfile >= 0) - { - isSignedIn = ProfileManager.IsSignedIn(lockedProfile); - status = app.GetOptionsCallbackStatus(lockedProfile); - pendingFontChange = ui.PendingFontChange(); - - if(status == C4JStorage::eOptions_Callback_Idle) - { - // make sure the TMS banned list data is ditched - the player may have gone in to help & options, backed out, and signed out - app.InvalidateBannedList(lockedProfile); - - // need to ditch any DLCOffers info - StorageManager.ClearDLCOffers(); - app.ClearAndResetDLCDownloadQueue(); - app.ClearDLCInstalled(); - } - } - - if ( (lockedProfile >= 0) - && isSignedIn - && ((status == C4JStorage::eOptions_Callback_Read)||(status == C4JStorage::eOptions_Callback_Write)) - && !pendingFontChange - ) -#endif - { - app.DebugPrintf("[MainMenu] Navigating away from MainMenu.\n"); - ui.NavigateToScene(lockedProfile, eNavigateWhenReady); - eNavigateWhenReady = static_cast(-1); - } -#ifdef _DURANGO - else - { - app.DebugPrintf("[MainMenu] Delaying navigation: lockedProfile=%i, %s, status=%ls, %s.\n", - lockedProfile, - isSignedIn ? "SignedIn" : "SignedOut", - app.toStringOptionsStatus(status).c_str(), - pendingFontChange ? "Pending font change" : "font OK"); - } -#endif - } - -#if defined(__PS3__) || defined (__ORBIS__) || defined(__PSVITA__) - if(m_bLaunchFullVersionPurchase) - { - int iCommerceState=app.GetCommerceState(); - // 4J-PB - if there's a commerce error - store down, player can't access store - let the DisplayFullVersionPurchase show the error - if((iCommerceState==CConsoleMinecraftApp::eCommerce_State_Online) || (iCommerceState==CConsoleMinecraftApp::eCommerce_State_Error)) - { - m_bLaunchFullVersionPurchase=false; - m_bIgnorePress=false; - updateTooltips(); - - // 4J-PB - need to check this user can access the store - bool bContentRestricted=false; - ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,nullptr,&bContentRestricted,nullptr); - if(bContentRestricted) - { - UINT uiIDA[1]; - uiIDA[0]=IDS_CONFIRM_OK; - ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad()); - } - else - { - TelemetryManager->RecordUpsellPresented(ProfileManager.GetPrimaryPad(), eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID); - ProfileManager.DisplayFullVersionPurchase(false,ProfileManager.GetPrimaryPad(),eSen_UpsellID_Full_Version_Of_Game); - } - } - } - - // 4J-PB - check for a trial version changing to a full version - if(m_bTrialVersion) - { - if(ProfileManager.IsFullVersion()) - { - m_bTrialVersion=false; - m_buttons[(int)eControl_UnlockOrDLC].init(app.GetString(IDS_DOWNLOADABLECONTENT),eControl_UnlockOrDLC); - } - } -#endif - -#if defined _XBOX_ONE - if(m_bWaitingForDLCInfo) - { - if(app.GetTMSDLCInfoRead()) - { - m_bWaitingForDLCInfo=false; - ProfileManager.SetLockedProfile(m_iPad); - proceedToScene(ProfileManager.GetPrimaryPad(), eUIScene_DLCMainMenu); - } - } - - if(g_NetworkManager.ShouldMessageForFullSession()) - { - UINT uiIDA[1]; - uiIDA[0]=IDS_CONFIRM_OK; - ui.RequestErrorMessage( IDS_CONNECTION_FAILED, IDS_IN_PARTY_SESSION_FULL, uiIDA,1,ProfileManager.GetPrimaryPad()); - } -#endif - -#ifdef __ORBIS__ - - // process the error dialog (for a patch being available) - // SQRNetworkManager_Orbis::tickErrorDialog also runs the error dialog, so wrap this so this doesn't terminate a signin dialog - if(m_bErrorDialogRunning) - { - SceErrorDialogStatus stat = sceErrorDialogUpdateStatus(); - if( stat == SCE_ERROR_DIALOG_STATUS_FINISHED ) - { - sceErrorDialogTerminate(); - // if m_bRunGameChosen is true, we're here after selecting play game, and we should let the user continue with an offline game - if(m_bRunGameChosen) - { - m_bRunGameChosen=false; - m_eAction = eAction_RunGame; - - // give the option of continuing offline - UINT uiIDA[1]; - uiIDA[0]=IDS_PRO_NOTONLINE_DECLINE; - ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION_PATCH_AVAILABLE, uiIDA, 1, ProfileManager.GetPrimaryPad(), &UIScene_MainMenu::PlayOfflineReturned, this); - - } - m_bErrorDialogRunning=false; - } - } - - if(m_bLoadTrialOnNetworkManagerReady && g_NetworkManager.IsReadyToPlayOrIdle()) - { - m_bLoadTrialOnNetworkManagerReady = false; - LoadTrial(); - } - -#endif -} - -void UIScene_MainMenu::RunAchievements(int iPad) -{ -#if TO_BE_IMPLEMENTED - UINT uiIDA[1]; - uiIDA[0]=IDS_OK; - - // guests can't look at achievements - if(ProfileManager.IsGuest(iPad)) - { - ui.RequestErrorMessage(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); - } - else - { - XShowAchievementsUI( iPad ); - } -#endif - ui.NavigateToScene(iPad, eUIScene_AchievementsMenu); -} - -void UIScene_MainMenu::RunHelpAndOptions(int iPad) -{ - if(ProfileManager.IsGuest(iPad)) - { - UINT uiIDA[1]; - uiIDA[0]=IDS_OK; - ui.RequestErrorMessage(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); - } - else - { - // If the player was signed in before selecting play, we'll not have read the profile yet, so query the sign-in status to get this to happen - ProfileManager.QuerySigninStatus(); - -#if TO_BE_IMPLEMENTED - // 4J-PB - You can be offline and still can go into help and options - if(app.GetTMSDLCInfoRead() || !ProfileManager.IsSignedInLive(iPad)) -#endif - { - ProfileManager.SetLockedProfile(iPad); -#ifdef _XBOX_ONE - ui.ShowPlayerDisplayname(true); -#endif - proceedToScene(iPad, eUIScene_HelpAndOptionsMenu); - } -#if TO_BE_IMPLEMENTED - else - { - // Changing to async TMS calls - app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_HelpAndOptions); - - // block all input - m_bIgnorePress=true; - // We want to hide everything in this scene and display a timer until we get a completion for the TMS files - for(int i=0;iseed = 0; - param->saveData = nullptr; - param->settings = app.GetGameHostOption( eGameHostOption_Tutorial ) | app.GetGameHostOption(eGameHostOption_DisableSaving); - - vector *generators = app.getLevelGenerators(); - param->levelGen = generators->at(0); - - LoadingInputParams *loadingParams = new LoadingInputParams(); - loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc; - loadingParams->lpParam = static_cast(param); - - UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); - completionData->bShowBackground=TRUE; - completionData->bShowLogo=TRUE; - completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes; - completionData->iPad = ProfileManager.GetPrimaryPad(); - loadingParams->completionData = completionData; - - ui.ShowTrialTimer(true); - -#ifdef _XBOX_ONE - ui.ShowPlayerDisplayname(true); -#endif - ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); -} - -void UIScene_MainMenu::handleUnlockFullVersion() -{ - m_buttons[static_cast(eControl_UnlockOrDLC)].setLabel(IDS_DOWNLOADABLECONTENT,true); -} - - -#ifdef __PSVITA__ -int UIScene_MainMenu::SelectNetworkModeReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) -{ - UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; - - if(result==C4JStorage::EMessage_ResultAccept) - { - app.DebugPrintf("Setting network mode to PSN\n"); - app.SetGameSettings(0, eGameSetting_PSVita_NetworkModeAdhoc, 0); - } - else if(result==C4JStorage::EMessage_ResultDecline) - { - app.DebugPrintf("Setting network mode to Adhoc\n"); - app.SetGameSettings(0, eGameSetting_PSVita_NetworkModeAdhoc, 1); - } - pClass->updateTooltips(); - return 0; -} -#endif //__PSVITA__ +#include "stdafx.h" +#include "../../../Minecraft.World/Mth.h" +#include "../../../Minecraft.World/StringHelpers.h" +#include "../../../Minecraft.World/Random.h" +#include "../../User.h" +#include "../../MinecraftServer.h" +#include "UI.h" +#include "UIScene_MainMenu.h" +#ifdef __ORBIS__ +#include +#endif + +Random *UIScene_MainMenu::random = new Random(); + +EUIScene UIScene_MainMenu::eNavigateWhenReady = static_cast(-1); + +UIScene_MainMenu::UIScene_MainMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ +#ifdef __ORBIS + //m_ePatchCheckState=ePatchCheck_Idle; + m_bRunGameChosen=false; + m_bErrorDialogRunning=false; +#endif + + + // Setup all the Iggy references we need for this scene + initialiseMovie(); + + parentLayer->addComponent(iPad,eUIComponent_Panorama); + parentLayer->addComponent(iPad,eUIComponent_Logo); + + m_eAction=eAction_None; + m_bIgnorePress=false; + + + m_buttons[static_cast(eControl_PlayGame)].init(IDS_PLAY_GAME,eControl_PlayGame); + m_buttons[(int)eControl_MiniGames].init(L"Mini Games",eControl_MiniGames); + +#ifdef _XBOX_ONE + if(!ProfileManager.IsFullVersion()) m_buttons[(int)eControl_PlayGame].setLabel(IDS_PLAY_TRIAL_GAME); + app.SetReachedMainMenu(); +#endif + + m_buttons[static_cast(eControl_Leaderboards)].init(IDS_LEADERBOARDS,eControl_Leaderboards); + m_buttons[static_cast(eControl_Achievements)].init( (UIString)IDS_ACHIEVEMENTS,eControl_Achievements); + m_buttons[static_cast(eControl_HelpAndOptions)].init(IDS_HELP_AND_OPTIONS,eControl_HelpAndOptions); + if(ProfileManager.IsFullVersion()) + { + m_bTrialVersion=false; + m_buttons[static_cast(eControl_UnlockOrDLC)].init(IDS_DOWNLOADABLECONTENT,eControl_UnlockOrDLC); + } + else + { + m_bTrialVersion=true; + m_buttons[static_cast(eControl_UnlockOrDLC)].init(IDS_UNLOCK_FULL_GAME,eControl_UnlockOrDLC); + } + +#ifndef _DURANGO + m_buttons[static_cast(eControl_Exit)].init(app.GetString(IDS_EXIT_GAME),eControl_Exit); +#else + m_buttons[(int)eControl_XboxHelp].init(IDS_XBOX_HELP_APP, eControl_XboxHelp); +#endif + + removeControl( &m_buttons[(int)eControl_MiniGames], false ); + int controlType = app.GetGameSettings(m_iPad, eGameSetting_ControlType); + if (controlType == 3 || controlType == 4) + { + // ps3, ps4 + removeControl( &m_buttons[(int)eControl_Exit], false ); + // We don't have a way to display trophies/achievements, so remove the button + removeControl( &m_buttons[(int)eControl_Achievements], false ); + } + else if (controlType == 1) + { + // xbox one + removeControl( &m_buttons[(int)eControl_Achievements], false ); + } + else if (controlType == 5) + { + // wiiU + removeControl( &m_buttons[(int)eControl_Leaderboards], false ); + } + +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + m_bLaunchFullVersionPurchase=false; +#endif +#ifdef _DURANGO + // Allowed to not have achievements in the menu + //removeControl( &m_buttons[(int)eControl_Achievements], false ); + // Not allowed to exit from a Xbox One game from the game - have to use the Home button + //removeControl( &m_buttons[(int)eControl_Exit], false ); + m_bWaitingForDLCInfo=false; +#endif + + doHorizontalResizeCheck(); + + m_splash = L""; + + wstring filename = L"splashes.txt"; + if( app.hasArchiveFile(filename) ) + { + byteArray splashesArray = app.getArchiveFile(filename); + ByteArrayInputStream bais(splashesArray); + InputStreamReader isr( &bais ); + BufferedReader br( &isr ); + + wstring line = L""; + while ( !(line = br.readLine()).empty() ) + { + line = trimString( line ); + if (line.length() > 0) + { + m_splashes.push_back(line); + } + } + + br.close(); + } + + m_bIgnorePress=false; + m_bLoadTrialOnNetworkManagerReady = false; + + // 4J Stu - Clear out any loaded game rules + app.setLevelGenerationOptions(nullptr); + + // 4J Stu - Reset the leaving game flag so that we correctly handle signouts while in the menus + g_NetworkManager.ResetLeavingGame(); + +#if TO_BE_IMPLEMENTED + // Fix for #45154 - Frontend: DLC: Content can only be downloaded from the frontend if you have not joined/exited multiplayer + XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW); +#endif +} + +UIScene_MainMenu::~UIScene_MainMenu() +{ + m_parentLayer->removeComponent(eUIComponent_Panorama); + m_parentLayer->removeComponent(eUIComponent_Logo); +} + +void UIScene_MainMenu::updateTooltips() +{ + int iX = -1; + int iA = -1; + if(!m_bIgnorePress) + { + iA = IDS_TOOLTIPS_SELECT; + +#ifdef _XBOX_ONE + iX = IDS_TOOLTIPS_CHOOSE_USER; +#elif defined __PSVITA__ + if(ProfileManager.IsFullVersion()) + { + iX = IDS_TOOLTIP_CHANGE_NETWORK_MODE; + } +#endif + } + ui.SetTooltips( DEFAULT_XUI_MENU_USER, iA, -1, iX); +} + +void UIScene_MainMenu::updateComponents() +{ + m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); + m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); +} + +void UIScene_MainMenu::handleGainFocus(bool navBack) +{ + UIScene::handleGainFocus(navBack); + handleReload(); + ui.ShowPlayerDisplayname(false); + m_bIgnorePress=false; + + if (eNavigateWhenReady >= 0) + { + return; + } + + // 4J-JEV: This needs to come before SetLockedProfile(-1) as it wipes the XbLive contexts. + if (!navBack) + { + for (int iPad = 0; iPad < MAX_LOCAL_PLAYERS; iPad++) + { + // For returning to menus after exiting a game. + if (ProfileManager.IsSignedIn(iPad) ) + { + ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MENUS, false); + } + } + } + ProfileManager.SetLockedProfile(-1); + + m_bIgnorePress = false; + updateTooltips(); + +#ifdef _DURANGO + ProfileManager.ClearGameUsers(); +#endif + + if(navBack && ProfileManager.IsFullVersion()) + { + // Replace the Unlock Full Game with Downloadable Content + m_buttons[static_cast(eControl_UnlockOrDLC)].setLabel(IDS_DOWNLOADABLECONTENT); + } + +#if TO_BE_IMPLEMENTED + // Fix for #45154 - Frontend: DLC: Content can only be downloaded from the frontend if you have not joined/exited multiplayer + XBackgroundDownloadSetMode(XBACKGROUND_DOWNLOAD_MODE_ALWAYS_ALLOW); + m_Timer.SetShow(FALSE); +#endif + m_controlTimer.setVisible( false ); + + // 4J-PB - remove the "hobo humping" message legal say we can't have, and the 1080p one for Vita +#ifdef __PSVITA__ + int splashIndex = eSplashRandomStart + 2 + random->nextInt( (int)m_splashes.size() - (eSplashRandomStart + 2) ); +#else + int splashIndex = eSplashRandomStart + 1 + random->nextInt( static_cast(m_splashes.size()) - (eSplashRandomStart + 1) ); +#endif + + // Override splash text on certain dates + SYSTEMTIME LocalSysTime; + GetLocalTime( &LocalSysTime ); + if (LocalSysTime.wMonth == 11 && LocalSysTime.wDay == 9) + { + splashIndex = eSplashHappyBirthdayEx; + } + else if (LocalSysTime.wMonth == 6 && LocalSysTime.wDay == 1) + { + splashIndex = eSplashHappyBirthdayNotch; + } + else if (LocalSysTime.wMonth == 12 && LocalSysTime.wDay == 24) // the Java game shows this on Christmas Eve, so we will too + { + splashIndex = eSplashMerryXmas; + } + else if (LocalSysTime.wMonth == 1 && LocalSysTime.wDay == 1) + { + splashIndex = eSplashHappyNewYear; + } + //splashIndex = 47; // Very short string + //splashIndex = 194; // Very long string + //splashIndex = 295; // Coloured + //splashIndex = 296; // Noise + m_splash = m_splashes.at( splashIndex ); +} + +wstring UIScene_MainMenu::getMoviePath() +{ + return L"MainMenu"; +} + +void UIScene_MainMenu::handleReload() +{ + removeControl( &m_buttons[(int)eControl_MiniGames], false ); + int controlType = app.GetGameSettings(m_iPad, eGameSetting_ControlType); + if (controlType == 3 || controlType == 4) + { + // ps3, ps4 + removeControl( &m_buttons[(int)eControl_Exit], false ); + // We don't have a way to display trophies/achievements, so remove the button + removeControl( &m_buttons[(int)eControl_Achievements], false ); + } + else if (controlType == 1) + { + // xbox one + removeControl( &m_buttons[(int)eControl_Achievements], false ); + } + else if (controlType == 5) + { + // wiiu + removeControl( &m_buttons[(int)eControl_Leaderboards], false ); + } +} + +void UIScene_MainMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + //app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE"); + + if ( m_bIgnorePress || (eNavigateWhenReady >= 0) ) return; + +#if defined (__ORBIS__) || defined (__PSVITA__) + // ignore all players except player 0 - it's their profile that is currently being used + if(iPad!=0) return; +#endif + + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + + switch(key) + { + case ACTION_MENU_OK: +#ifdef __ORBIS__ + case ACTION_MENU_TOUCHPAD_PRESS: +#endif + if(pressed) + { + ProfileManager.SetPrimaryPad(iPad); + ProfileManager.SetLockedProfile(-1); + sendInputToMovie(key, repeat, pressed, released); + } + break; +#ifdef _XBOX_ONE + case ACTION_MENU_X: + if(pressed) + { + m_bIgnorePress = true; + ProfileManager.RequestSignInUI(false, false, false, false, false, ChooseUser_SignInReturned, this, iPad); + } + break; +#endif +#ifdef __PSVITA__ + case ACTION_MENU_X: + if(pressed && ProfileManager.IsFullVersion()) + { + UINT uiIDA[2]; + uiIDA[0]=IDS__NETWORK_PSN; + uiIDA[1]=IDS_NETWORK_ADHOC; + ui.RequestErrorMessage(IDS_SELECT_NETWORK_MODE_TITLE, IDS_SELECT_NETWORK_MODE_TEXT, uiIDA, 2, XUSER_INDEX_ANY, &UIScene_MainMenu::SelectNetworkModeReturned,this); + } + break; +#endif + + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + sendInputToMovie(key, repeat, pressed, released); + break; + } +} + +void UIScene_MainMenu::handlePress(F64 controlId, F64 childId) +{ + int primaryPad = ProfileManager.GetPrimaryPad(); + +#ifdef _XBOX_ONE + int (*signInReturnedFunc) (LPVOID,const bool, const int iPad, const int iController) = nullptr; +#else + int (*signInReturnedFunc) (LPVOID,const bool, const int iPad) = nullptr; +#endif + + switch(static_cast(controlId)) + { + case eControl_PlayGame: +#ifdef __ORBIS__ + { + m_bIgnorePress=true; + + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + ProfileManager.RefreshChatAndContentRestrictions(RefreshChatAndContentRestrictionsReturned_PlayGame, this); + } +#else + m_eAction=eAction_RunGame; + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + signInReturnedFunc = &UIScene_MainMenu::CreateLoad_SignInReturned; +#endif + break; + case eControl_MiniGames: + #ifdef __ORBIS__ + { + m_bIgnorePress=true; + + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + ProfileManager.RefreshChatAndContentRestrictions(RefreshChatAndContentRestrictionsReturned_PlayGame, this); + } +#else + m_eAction=eAction_RunGame; + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + signInReturnedFunc = &UIScene_MainMenu::CreateLoad_SignInReturned; +#endif + break; + case eControl_Leaderboards: + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); +#ifdef __ORBIS__ + ProfileManager.RefreshChatAndContentRestrictions(RefreshChatAndContentRestrictionsReturned_Leaderboards, this); +#else + m_eAction=eAction_RunLeaderboards; + signInReturnedFunc = &UIScene_MainMenu::Leaderboards_SignInReturned; +#endif + break; + case eControl_Achievements: + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + m_eAction=eAction_RunAchievements; + signInReturnedFunc = &UIScene_MainMenu::Achievements_SignInReturned; + break; + case eControl_HelpAndOptions: + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + m_eAction=eAction_RunHelpAndOptions; + signInReturnedFunc = &UIScene_MainMenu::HelpAndOptions_SignInReturned; + break; + case eControl_UnlockOrDLC: + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + m_eAction=eAction_RunUnlockOrDLC; + signInReturnedFunc = &UIScene_MainMenu::UnlockFullGame_SignInReturned; + break; + case eControl_Exit: + //CD - Added for audio + ui.PlayUISFX(eSFX_Press); + + if( ProfileManager.IsFullVersion() ) + { + UINT uiIDA[2]; + uiIDA[0]=IDS_CANCEL; + uiIDA[1]=IDS_OK; + ui.RequestErrorMessage(IDS_WINDOWS_EXIT, IDS_WARNING_ARCADE_TEXT, uiIDA, 2, XUSER_INDEX_ANY,&UIScene_MainMenu::ExitGameReturned,this); + } + else + { +#ifdef _XBOX +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + ui.NavigateToScene(primaryPad,eUIScene_TrialExitUpsell); +#endif + } + break; + +#ifdef _DURANGO + case eControl_XboxHelp: + ui.PlayUISFX(eSFX_Press); + + m_eAction=eAction_RunXboxHelp; + signInReturnedFunc = &UIScene_MainMenu::XboxHelp_SignInReturned; + break; +#endif + + default: DEBUG_BREAK(); + } + + bool confirmUser = false; + + // Note: if no sign in returned func, assume this isn't required + if (signInReturnedFunc != nullptr) + { + if(ProfileManager.IsSignedIn(primaryPad)) + { + if (confirmUser) + { + ProfileManager.RequestSignInUI(false, false, true, false, true, signInReturnedFunc, this, primaryPad); + } + else + { + RunAction(primaryPad); + } + } + else + { + // Ask user to sign in + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + ui.RequestErrorMessage(IDS_MUST_SIGN_IN_TITLE, IDS_MUST_SIGN_IN_TEXT, uiIDA, 2, primaryPad, &UIScene_MainMenu::MustSignInReturned, this); + } + } +} + +// Run current action +void UIScene_MainMenu::RunAction(int iPad) +{ + switch(m_eAction) + { + case eAction_RunGame: + RunPlayGame(iPad); + break; + case eAction_RunLeaderboards: + RunLeaderboards(iPad); + break; + case eAction_RunAchievements: + RunAchievements(iPad); + break; + case eAction_RunHelpAndOptions: + RunHelpAndOptions(iPad); + break; + case eAction_RunUnlockOrDLC: + RunUnlockOrDLC(iPad); + break; +#ifdef _DURANGO + case eAction_RunXboxHelp: + // 4J: Launch the dummy xbox help application. + WXS::User^ user = ProfileManager.GetUser(ProfileManager.GetPrimaryPad()); + Windows::Xbox::ApplicationModel::Help::Show(user); + break; +#endif + } +} + +void UIScene_MainMenu::customDraw(IggyCustomDrawCallbackRegion *region) +{ + if(wcscmp((wchar_t *)region->name,L"Splash")==0) + { + PIXBeginNamedEvent(0,"Custom draw splash"); + customDrawSplash(region); + PIXEndNamedEvent(); + } +} + +void UIScene_MainMenu::customDrawSplash(IggyCustomDrawCallbackRegion *region) +{ + Minecraft *pMinecraft = Minecraft::GetInstance(); + + // 4J Stu - Move this to the ctor when the main menu is not the first scene we navigate to + ScreenSizeCalculator ssc(pMinecraft->options, pMinecraft->width_phys, pMinecraft->height_phys); + m_fScreenWidth=static_cast(pMinecraft->width_phys); + m_fRawWidth=static_cast(ssc.rawWidth); + m_fScreenHeight=static_cast(pMinecraft->height_phys); + m_fRawHeight=static_cast(ssc.rawHeight); + + + // Setup GDraw, normal game render states and matrices + CustomDrawData *customDrawRegion = ui.setupCustomDraw(this,region); + delete customDrawRegion; + + + Font *font = pMinecraft->font; + + // build and render with the game call + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + + glPushMatrix(); + + float width = region->x1 - region->x0; + float height = region->y1 - region->y0; + float xo = width/2; + float yo = height; + + glTranslatef(xo, yo, 0); + + glRotatef(-17, 0, 0, 1); + float sss = 1.8f - Mth::abs(Mth::sin(System::currentTimeMillis() % 1000 / 1000.0f * PI * 2) * 0.1f); + sss*=(m_fScreenWidth/m_fRawWidth); + + sss = sss * 100 / (font->width(m_splash) + 8 * 4); + glScalef(sss, sss, sss); + //drawCenteredString(font, splash, 0, -8, 0xffff00); + font->drawShadow(m_splash, 0 - (font->width(m_splash)) / 2, -8, 0xffff00); + glPopMatrix(); + + glDisable(GL_RESCALE_NORMAL); + + glEnable(GL_DEPTH_TEST); + + + // Finish GDraw and anything else that needs to be finalised + ui.endCustomDraw(region); +} + +int UIScene_MainMenu::MustSignInReturned(void *pParam, int iPad, C4JStorage::EMessageResult result) +{ + UIScene_MainMenu* pClass = static_cast(pParam); + + if(result==C4JStorage::EMessage_ResultAccept) + { + // we need to specify local game here to display local and LIVE profiles in the list + switch(pClass->m_eAction) + { + case eAction_RunGame: ProfileManager.RequestSignInUI(false, true, false, false, true, &UIScene_MainMenu::CreateLoad_SignInReturned, pClass, iPad ); break; + case eAction_RunHelpAndOptions: ProfileManager.RequestSignInUI(false, false, true, false, true, &UIScene_MainMenu::HelpAndOptions_SignInReturned, pClass, iPad ); break; + case eAction_RunLeaderboards: ProfileManager.RequestSignInUI(false, false, true, false, true, &UIScene_MainMenu::Leaderboards_SignInReturned, pClass, iPad ); break; + case eAction_RunAchievements: ProfileManager.RequestSignInUI(false, false, true, false, true, &UIScene_MainMenu::Achievements_SignInReturned, pClass, iPad ); break; + case eAction_RunUnlockOrDLC: ProfileManager.RequestSignInUI(false, false, true, false, true, &UIScene_MainMenu::UnlockFullGame_SignInReturned, pClass, iPad ); break; +#ifdef _DURANGO + case eAction_RunXboxHelp: ProfileManager.RequestSignInUI(false, false, true, false, true, &UIScene_MainMenu::XboxHelp_SignInReturned, pClass, iPad ); break; +#endif + } + } + else + { + pClass->m_bIgnorePress=false; + // unlock the profile + ProfileManager.SetLockedProfile(-1); + for(int i=0;im_eAction) + { + case eAction_RunLeaderboardsPSN: + SQRNetworkManager_PS3::AttemptPSNSignIn(&UIScene_MainMenu::Leaderboards_SignInReturned, pClass); + break; + case eAction_RunGamePSN: + SQRNetworkManager_PS3::AttemptPSNSignIn(&UIScene_MainMenu::CreateLoad_SignInReturned, pClass); + break; + case eAction_RunUnlockOrDLCPSN: + SQRNetworkManager_PS3::AttemptPSNSignIn(&UIScene_MainMenu::UnlockFullGame_SignInReturned, pClass); + break; + } +#elif defined __PSVITA__ + switch(pClass->m_eAction) + { + case eAction_RunLeaderboardsPSN: + //CD - Must force Ad-Hoc off if they want leaderboard PSN sign-in + //Save settings change + app.SetGameSettings(0, eGameSetting_PSVita_NetworkModeAdhoc, 0); + //Force off + CGameNetworkManager::setAdhocMode(false); + //Now Sign-in + SQRNetworkManager_Vita::AttemptPSNSignIn(&UIScene_MainMenu::Leaderboards_SignInReturned, pClass); + break; + case eAction_RunGamePSN: + if(CGameNetworkManager::usingAdhocMode()) + { + SQRNetworkManager_AdHoc_Vita::AttemptAdhocSignIn(&UIScene_MainMenu::CreateLoad_SignInReturned, pClass); + } + else + { + SQRNetworkManager_Vita::AttemptPSNSignIn(&UIScene_MainMenu::CreateLoad_SignInReturned, pClass); + + } + break; + case eAction_RunUnlockOrDLCPSN: + //CD - Must force Ad-Hoc off if they want commerce PSN sign-in + //Save settings change + app.SetGameSettings(0, eGameSetting_PSVita_NetworkModeAdhoc, 0); + //Force off + CGameNetworkManager::setAdhocMode(false); + //Now Sign-in + SQRNetworkManager_Vita::AttemptPSNSignIn(&UIScene_MainMenu::UnlockFullGame_SignInReturned, pClass); + break; + } +#else + switch(pClass->m_eAction) + { + case eAction_RunLeaderboardsPSN: + SQRNetworkManager_Orbis::AttemptPSNSignIn(&UIScene_MainMenu::Leaderboards_SignInReturned, pClass, true, iPad); + break; + case eAction_RunGamePSN: + SQRNetworkManager_Orbis::AttemptPSNSignIn(&UIScene_MainMenu::CreateLoad_SignInReturned, pClass, true, iPad); + break; + case eAction_RunUnlockOrDLCPSN: + SQRNetworkManager_Orbis::AttemptPSNSignIn(&UIScene_MainMenu::UnlockFullGame_SignInReturned, pClass, true, iPad); + break; + } + +#endif + } + else + { + if( pClass->m_eAction == eAction_RunGamePSN ) + { + if( result == C4JStorage::EMessage_Cancelled) + CreateLoad_SignInReturned(pClass, false, 0); + else + CreateLoad_SignInReturned(pClass, true, 0); + } + else + { + pClass->m_bIgnorePress=false; + } + } + + return 0; +} +#endif + +#ifdef _XBOX_ONE +int UIScene_MainMenu::HelpAndOptions_SignInReturned(void *pParam,bool bContinue,int iPad, int iController) +#else +int UIScene_MainMenu::HelpAndOptions_SignInReturned(void *pParam,bool bContinue,int iPad) +#endif +{ + UIScene_MainMenu *pClass = static_cast(pParam); + + if(bContinue) + { + // 4J-JEV: Don't we only need to update rich-presence if the sign-in status changes. + ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MENUS, false); + +#if TO_BE_IMPLEMENTED + if(app.GetTMSDLCInfoRead()) +#endif + { + ProfileManager.SetLockedProfile(ProfileManager.GetPrimaryPad()); +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + proceedToScene(iPad, eUIScene_HelpAndOptionsMenu); + } +#if TO_BE_IMPLEMENTED + else + { + // Changing to async TMS calls + app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_HelpAndOptions); + + // block all input + pClass->m_bIgnorePress=true; + // We want to hide everything in this scene and display a timer until we get a completion for the TMS files + for(int i=0;im_Buttons[i].SetShow(FALSE); + } + + pClass->updateTooltips(); + + pClass->m_Timer.SetShow(TRUE); + } +#endif + } + else + { + pClass->m_bIgnorePress=false; + // unlock the profile + ProfileManager.SetLockedProfile(-1); + for(int i=0;im_bIgnorePress = false; + pClass->updateTooltips(); + return 0; +} +#endif + +#ifdef _XBOX_ONE +int UIScene_MainMenu::CreateLoad_SignInReturned(void *pParam, bool bContinue, int iPad, int iController) +#else +int UIScene_MainMenu::CreateLoad_SignInReturned(void *pParam, bool bContinue, int iPad) +#endif +{ + UIScene_MainMenu* pClass = static_cast(pParam); + + if(bContinue) + { + // 4J-JEV: We only need to update rich-presence if the sign-in status changes. + ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MENUS, false); + + UINT uiIDA[1] = { IDS_OK }; + + if(ProfileManager.IsGuest(ProfileManager.GetPrimaryPad())) + { + pClass->m_bIgnorePress=false; + ui.RequestErrorMessage(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); + } + else + { + ProfileManager.SetLockedProfile(ProfileManager.GetPrimaryPad()); + + + // change the minecraft player name + Minecraft::GetInstance()->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); + + if(ProfileManager.IsFullVersion()) + { + bool bSignedInLive = ProfileManager.IsSignedInLive(iPad); +#ifdef __PSVITA__ + if(CGameNetworkManager::usingAdhocMode()) + { + if(SQRNetworkManager_AdHoc_Vita::GetAdhocStatus()) + { + bSignedInLive = true; + } + else + { + // adhoc mode, but we didn't make the connection, turn off adhoc mode, and just go with whatever the regular online status is + CGameNetworkManager::setAdhocMode(false); + bSignedInLive = ProfileManager.IsSignedInLive(iPad); + } + } +#endif + + // Check if we're signed in to LIVE + if(bSignedInLive) + { + // 4J-PB - Need to check for installed DLC + if(!app.DLCInstallProcessCompleted()) app.StartInstallDLCProcess(iPad); + + if(ProfileManager.IsGuest(iPad)) + { + pClass->m_bIgnorePress=false; + ui.RequestErrorMessage(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); + } + else + { + // 4J Stu - Not relevant to PS3 +#ifdef _XBOX_ONE +// if(app.GetTMSDLCInfoRead() && app.GetBanListRead(iPad)) + if(app.GetBanListRead(iPad)) + { + Minecraft *pMinecraft=Minecraft::GetInstance(); + pMinecraft->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); + + // ensure we've applied this player's settings + app.ApplyGameSettingsChanged(iPad); + +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + proceedToScene(ProfileManager.GetPrimaryPad(), eUIScene_LoadCreateJoinMenu); + } + else + { + app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_RunPlayGame); + + // block all input + pClass->m_bIgnorePress=true; + // We want to hide everything in this scene and display a timer until we get a completion for the TMS files + // for(int i=0;iupdateTooltips(); + + pClass->m_controlTimer.setVisible( true ); + } +#endif +#if TO_BE_IMPLEMENTED + // check if all the TMS files are loaded + if(app.GetTMSDLCInfoRead() && app.GetTMSXUIDsFileRead() && app.GetBanListRead(iPad)) + { + if(StorageManager.SetSaveDevice(&UIScene_MainMenu::DeviceSelectReturned,pClass)==true) + { + // save device already selected + + // ensure we've applied this player's settings + app.ApplyGameSettingsChanged(ProfileManager.GetPrimaryPad()); + // check for DLC + // start timer to track DLC check finished + pClass->m_Timer.SetShow(TRUE); + XuiSetTimer(pClass->m_hObj,DLC_INSTALLED_TIMER_ID,DLC_INSTALLED_TIMER_TIME); + //app.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_MultiGameJoinLoad); + } + } + else + { + // Changing to async TMS calls + app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_RunPlayGame); + + // block all input + pClass->m_bIgnorePress=true; + // We want to hide everything in this scene and display a timer until we get a completion for the TMS files + for(int i=0;im_Buttons[i].SetShow(FALSE); + } + + updateTooltips(); + + pClass->m_Timer.SetShow(TRUE); + } +#else + Minecraft *pMinecraft=Minecraft::GetInstance(); + pMinecraft->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); + + // ensure we've applied this player's settings + app.ApplyGameSettingsChanged(iPad); + +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + proceedToScene(ProfileManager.GetPrimaryPad(), eUIScene_LoadCreateJoinMenu); +#endif + } + } + else + { +#if TO_BE_IMPLEMENTED + // offline + ProfileManager.DisplayOfflineProfile(&CScene_Main::CreateLoad_OfflineProfileReturned,pClass, ProfileManager.GetPrimaryPad() ); +#else + app.DebugPrintf("Offline Profile returned not implemented\n"); +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + proceedToScene(ProfileManager.GetPrimaryPad(), eUIScene_LoadCreateJoinMenu); +#endif + } + } + else + { + // 4J-PB - if this is the trial game, we can't have any networking + // Can't apply the player's settings here - they haven't come back from the QuerySignInStatud call above yet. + // Need to let them action in the main loop when they come in + // ensure we've applied this player's settings + //app.ApplyGameSettingsChanged(iPad); + +#if defined(__PS3__) || defined(__ORBIS__) || defined( __PSVITA__) + // ensure we've applied this player's settings - we do have them on PS3 + app.ApplyGameSettingsChanged(iPad); +#endif + +#ifdef __ORBIS__ + if(!g_NetworkManager.IsReadyToPlayOrIdle()) + { + pClass->m_bLoadTrialOnNetworkManagerReady = true; + ui.NavigateToScene(iPad, eUIScene_Timer); + } + else +#endif + { + // go straight in to the trial level + LoadTrial(); + } + } + } + } + else + { + pClass->m_bIgnorePress=false; + + // unlock the profile + ProfileManager.SetLockedProfile(-1); + for(int i=0;i(pParam); + + if(bContinue) + { + // 4J-JEV: We only need to update rich-presence if the sign-in status changes. + ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MENUS, false); + + UINT uiIDA[1] = { IDS_OK }; + + // guests can't look at leaderboards + if(ProfileManager.IsGuest(ProfileManager.GetPrimaryPad())) + { + pClass->m_bIgnorePress=false; + ui.RequestErrorMessage(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); + } + else if(!ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad())) + { + pClass->m_bIgnorePress=false; + ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1); + } + else + { + bool bContentRestricted=false; +#if defined(__PS3__) || defined(__PSVITA__) + ProfileManager.GetChatAndContentRestrictions(iPad,true,nullptr,&bContentRestricted,nullptr); +#endif + if(bContentRestricted) + { + pClass->m_bIgnorePress=false; +#if !(defined(_XBOX) || defined(_WINDOWS64) || defined(_XBOX_ONE) ) // 4J Stu - Temp to get the win build running, but so we check this for other platforms + // you can't see leaderboards + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad()); +#endif + } + else + { + ProfileManager.SetLockedProfile(ProfileManager.GetPrimaryPad()); +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + proceedToScene(ProfileManager.GetPrimaryPad(), eUIScene_LeaderboardsMenu); + } + } + } + else + { + pClass->m_bIgnorePress=false; + // unlock the profile + ProfileManager.SetLockedProfile(-1); + for(int i=0;i(pParam); + + if (bContinue) + { + pClass->m_bIgnorePress=false; + // 4J-JEV: We only need to update rich-presence if the sign-in status changes. + ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MENUS, false); + + XShowAchievementsUI( ProfileManager.GetPrimaryPad() ); + } + else + { + pClass->m_bIgnorePress=false; + // unlock the profile + ProfileManager.SetLockedProfile(-1); + for(int i=0;i(pParam); + + if (bContinue) + { + // 4J-JEV: We only need to update rich-presence if the sign-in status changes. + ProfileManager.SetCurrentGameActivity(iPad, CONTEXT_PRESENCE_MENUS, false); + + pClass->RunUnlockOrDLC(iPad); + } + else + { + pClass->m_bIgnorePress=false; + // unlock the profile + ProfileManager.SetLockedProfile(-1); + for(int i=0;im_errorCode = ProfileManager.getNPAvailability(ProfileManager.GetPrimaryPad()); + + bool bPatchAvailable; + switch(pClass->m_errorCode) + { + case SCE_NP_ERROR_LATEST_PATCH_PKG_EXIST: + case SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED: + bPatchAvailable=true; + break; + default: + bPatchAvailable=false; + break; + } + + if(!bPatchAvailable) + { + pClass->m_eAction=eAction_RunGame; + signInReturnedFunc = &UIScene_MainMenu::CreateLoad_SignInReturned; + } + else + { + pClass->m_bRunGameChosen=true; + pClass->m_bErrorDialogRunning=true; + int32_t ret=sceErrorDialogInitialize(); + if ( ret==SCE_OK ) + { + SceErrorDialogParam param; + sceErrorDialogParamInitialize( ¶m ); + // 4J-PB - We want to display the option to get the patch now + param.errorCode = SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED;//pClass->m_errorCode; + ret = sceUserServiceGetInitialUser( ¶m.userId ); + if ( ret == SCE_OK ) + { + ret=sceErrorDialogOpen( ¶m ); + } + return; + } + +// UINT uiIDA[1]; +// uiIDA[0]=IDS_OK; +// ui.RequestMessageBox(IDS_PATCH_AVAILABLE_TITLE, IDS_PATCH_AVAILABLE_TEXT, uiIDA, 1, XUSER_INDEX_ANY,nullptr,pClass); + } + + // Check if PSN is unavailable because of age restriction + if (pClass->m_errorCode == SCE_NP_ERROR_AGE_RESTRICTION) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_PRO_NOTONLINE_DECLINE; + ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(), &UIScene_MainMenu::PlayOfflineReturned, pClass); + + return; + } + + bool confirmUser = false; + + // Note: if no sign in returned func, assume this isn't required + if (signInReturnedFunc != nullptr) + { + if(ProfileManager.IsSignedIn(primaryPad)) + { + if (confirmUser) + { + ProfileManager.RequestSignInUI(false, false, true, false, true, signInReturnedFunc, pClass, primaryPad); + } + else + { + pClass->RunAction(primaryPad); + } + } + else + { + // Ask user to sign in + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + ui.RequestErrorMessage(IDS_MUST_SIGN_IN_TITLE, IDS_MUST_SIGN_IN_TEXT, uiIDA, 2, primaryPad, &UIScene_MainMenu::MustSignInReturned, pClass); + } + } +} + +void UIScene_MainMenu::RefreshChatAndContentRestrictionsReturned_Leaderboards(void *pParam) +{ + int primaryPad = ProfileManager.GetPrimaryPad(); + + UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; + + int (*signInReturnedFunc) (LPVOID,const bool, const int iPad) = nullptr; + + // 4J-PB - Check if there is a patch for the game + pClass->m_errorCode = ProfileManager.getNPAvailability(ProfileManager.GetPrimaryPad()); + + bool bPatchAvailable; + switch(pClass->m_errorCode) + { + case SCE_NP_ERROR_LATEST_PATCH_PKG_EXIST: + case SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED: + bPatchAvailable=true; + break; + default: + bPatchAvailable=false; + break; + } + + if(!bPatchAvailable) + { + pClass->m_eAction=eAction_RunLeaderboards; + signInReturnedFunc = &UIScene_MainMenu::Leaderboards_SignInReturned; + } + else + { + int32_t ret=sceErrorDialogInitialize(); + pClass->m_bErrorDialogRunning=true; + if ( ret==SCE_OK ) + { + SceErrorDialogParam param; + sceErrorDialogParamInitialize( ¶m ); + // 4J-PB - We want to display the option to get the patch now + param.errorCode = SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED;//pClass->m_errorCode; + ret = sceUserServiceGetInitialUser( ¶m.userId ); + if ( ret == SCE_OK ) + { + ret=sceErrorDialogOpen( ¶m ); + } + } + +// UINT uiIDA[1]; +// uiIDA[0]=IDS_OK; +// ui.RequestMessageBox(IDS_PATCH_AVAILABLE_TITLE, IDS_PATCH_AVAILABLE_TEXT, uiIDA, 1, XUSER_INDEX_ANY,nullptr,pClass); + } + + bool confirmUser = false; + + // Update error code + pClass->m_errorCode = ProfileManager.getNPAvailability(ProfileManager.GetPrimaryPad()); + + // Check if PSN is unavailable because of age restriction + if (pClass->m_errorCode == SCE_NP_ERROR_AGE_RESTRICTION) + { + UINT uiIDA[1]; + uiIDA[0] = IDS_CONFIRM_OK; + ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(), nullptr, pClass); + + return; + } + + // Note: if no sign in returned func, assume this isn't required + if (signInReturnedFunc != nullptr) + { + if(ProfileManager.IsSignedIn(primaryPad)) + { + if (confirmUser) + { + ProfileManager.RequestSignInUI(false, false, true, false, true, signInReturnedFunc, pClass, primaryPad); + } + else + { + pClass->RunAction(primaryPad); + } + } + else + { + // Ask user to sign in + UINT uiIDA[2]; + uiIDA[0]=IDS_CONFIRM_OK; + uiIDA[1]=IDS_CONFIRM_CANCEL; + ui.RequestErrorMessage(IDS_MUST_SIGN_IN_TITLE, IDS_MUST_SIGN_IN_TEXT, uiIDA, 2, primaryPad, &UIScene_MainMenu::MustSignInReturned, pClass); + } + } +} + +int UIScene_MainMenu::PlayOfflineReturned(void *pParam, int iPad, C4JStorage::EMessageResult result) +{ + UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; + + if(result==C4JStorage::EMessage_ResultAccept) + { + if (pClass->m_eAction == eAction_RunGame) + { + CreateLoad_SignInReturned(pClass, true, 0); + } + else + { + pClass->m_bIgnorePress=false; + } + } + else + { + pClass->m_bIgnorePress=false; + } + + return 0; +} +#endif + +void UIScene_MainMenu::RunPlayGame(int iPad) +{ + Minecraft *pMinecraft=Minecraft::GetInstance(); + + // clear the remembered signed in users so their profiles get read again + app.ClearSignInChangeUsersMask(); + + app.ReleaseSaveThumbnail(); + + if(ProfileManager.IsGuest(iPad)) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + + m_bIgnorePress=false; + ui.RequestErrorMessage(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); + } + else + { + ProfileManager.SetLockedProfile(iPad); + + // If the player was signed in before selecting play, we'll not have read the profile yet, so query the sign-in status to get this to happen + ProfileManager.QuerySigninStatus(); + + // 4J-PB - Need to check for installed DLC + if(!app.DLCInstallProcessCompleted()) app.StartInstallDLCProcess(iPad); + + if(ProfileManager.IsFullVersion()) + { + // are we offline? + bool bSignedInLive = ProfileManager.IsSignedInLive(iPad); +#ifdef __PSVITA__ + if(app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_PSVita_NetworkModeAdhoc) == true) + { + CGameNetworkManager::setAdhocMode(true); + bSignedInLive = SQRNetworkManager_AdHoc_Vita::GetAdhocStatus(); + app.DebugPrintf("Adhoc mode signed in : %s\n", bSignedInLive ? "true" : "false"); + } + else + { + CGameNetworkManager::setAdhocMode(false); + app.DebugPrintf("PSN mode signed in : %s\n", bSignedInLive ? "true" : "false"); + } + +#endif //__PSVITA__ + + if(!bSignedInLive) + { +#if defined(__PS3__) || defined __PSVITA__ + // enable input again + m_bIgnorePress=false; + + // Not sure why 360 doesn't need this, but leaving as __PS3__ only for now until we see that it does. Without this, on a PS3 offline game, the primary player just gets the default Player1234 type name + pMinecraft->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); + + m_eAction=eAction_RunGamePSN; + // get them to sign in to online + UINT uiIDA[2]; + uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; + uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE; + +#ifdef __PSVITA__ + if(CGameNetworkManager::usingAdhocMode()) + { + uiIDA[0]=IDS_NETWORK_ADHOC; + // this should be "Connect to adhoc network" + ui.RequestErrorMessage(IDS_PRO_NOTADHOCONLINE_TITLE, IDS_PRO_NOTADHOCONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&UIScene_MainMenu::MustSignInReturnedPSN,this); + } + else + { + /* 4J-PB - Add this after release + // Determine why they're not "signed in live" + if (ProfileManager.IsSignedInPSN(iPad)) + { + m_eAction=eAction_RunGame; + // Signed in to PSN but not connected (no internet access) + + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_DECLINE; + ui.RequestMessageBox( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad, UIScene_MainMenu::PlayOfflineReturned, this, app.GetStringTable()); + } + else + { + m_eAction=eAction_RunGamePSN; + // Not signed in to PSN + ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, iPad, &UIScene_MainMenu::MustSignInReturnedPSN, this, app.GetStringTable()); + return; + } */ + ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&UIScene_MainMenu::MustSignInReturnedPSN,this); + + } +#else + + ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, iPad, &UIScene_MainMenu::MustSignInReturnedPSN, this); +#endif + +#elif defined __ORBIS__ + + // Determine why they're not "signed in live" + if (ProfileManager.isSignedInPSN(iPad)) + { + m_eAction=eAction_RunGame; + // Signed in to PSN but not connected (no internet access) + assert(!ProfileManager.isConnectedToPSN(iPad)); + + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_DECLINE; + ui.RequestErrorMessage( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad, UIScene_MainMenu::PlayOfflineReturned, this); + } + else + { + m_eAction=eAction_RunGamePSN; + // Not signed in to PSN + UINT uiIDA[2]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + uiIDA[1] = IDS_PRO_NOTONLINE_DECLINE; + ui.RequestAlertMessage( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, iPad, &UIScene_MainMenu::MustSignInReturnedPSN, this); + return; + } +#else + ProfileManager.SetLockedProfile(iPad); +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + proceedToScene(ProfileManager.GetPrimaryPad(), eUIScene_LoadCreateJoinMenu); +#endif + } + else + { +#ifdef _XBOX_ONE + if(!app.GetBanListRead(iPad)) + { + app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_RunPlayGame); + + // block all input + m_bIgnorePress=true; + // We want to hide everything in this scene and display a timer until we get a completion for the TMS files +// for(int i=0;iuser->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); + // save device already selected + + // ensure we've applied this player's settings + app.ApplyGameSettingsChanged(iPad); + // check for DLC + // start timer to track DLC check finished + m_Timer.SetShow(TRUE); + XuiSetTimer(m_hObj,DLC_INSTALLED_TIMER_ID,DLC_INSTALLED_TIMER_TIME); + //app.NavigateToScene(iPad,eUIScene_MultiGameJoinLoad); + } + } + else + { + // Changing to async TMS calls + app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_RunPlayGame); + + // block all input + m_bIgnorePress=true; + // We want to hide everything in this scene and display a timer until we get a completion for the TMS files + for(int i=0;iuser->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); + + // ensure we've applied this player's settings + app.ApplyGameSettingsChanged(iPad); + +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + proceedToScene(ProfileManager.GetPrimaryPad(), eUIScene_LoadCreateJoinMenu); +#endif + } + } + else + { + // 4J-PB - if this is the trial game, we can't have any networking + // go straight in to the trial level + // change the minecraft player name + Minecraft::GetInstance()->user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad())); + + // Can't apply the player's settings here - they haven't come back from the QuerySignInStatud call above yet. + // Need to let them action in the main loop when they come in + // ensure we've applied this player's settings + //app.ApplyGameSettingsChanged(iPad); + +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + // ensure we've applied this player's settings - we do have them on PS3 + app.ApplyGameSettingsChanged(iPad); +#endif + +#ifdef __ORBIS__ + if(!g_NetworkManager.IsReadyToPlayOrIdle()) + { + m_bLoadTrialOnNetworkManagerReady = true; + ui.NavigateToScene(iPad, eUIScene_Timer); + } + else +#endif + { + LoadTrial(); + } + } + } +} + +void UIScene_MainMenu::RunLeaderboards(int iPad) +{ + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + + // guests can't look at leaderboards + if(ProfileManager.IsGuest(iPad)) + { + ui.RequestErrorMessage(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); + } + else if(!ProfileManager.IsSignedInLive(iPad)) + { +#if defined __PS3__ || defined __PSVITA__ + m_eAction=eAction_RunLeaderboardsPSN; + // get them to sign in to online + UINT uiIDA[1]; + uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(),&UIScene_MainMenu::MustSignInReturnedPSN,this); + +/* 4J-PB - Add this after release +#elif defined __PSVITA__ + m_eAction=eAction_RunLeaderboardsPSN; + // Determine why they're not "signed in live" + if (ProfileManager.IsSignedInPSN(iPad)) + { + // Signed in to PSN but not connected (no internet access) + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestMessageBox(IDS_PRO_CURRENTLY_NOT_ONLINE_TITLE, IDS_PRO_PSNOFFLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(), &UIScene_MainMenu::MustSignInReturnedPSN, this, app.GetStringTable()); + } + else + { + // Not signed in to PSN + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(), &UIScene_MainMenu::MustSignInReturnedPSN, this, app.GetStringTable()); + return; + }*/ +#elif defined __ORBIS__ + m_eAction=eAction_RunLeaderboardsPSN; + // Determine why they're not "signed in live" + if (ProfileManager.isSignedInPSN(iPad)) + { + // Signed in to PSN but not connected (no internet access) + assert(!ProfileManager.isConnectedToPSN(iPad)); + + UINT uiIDA[1]; + uiIDA[0] = IDS_OK; + ui.RequestErrorMessage( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPad); + } + else + { + // Not signed in to PSN + UINT uiIDA[1]; + uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; + ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(), &UIScene_MainMenu::MustSignInReturnedPSN, this); + return; + } +#else + ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_XBOXLIVE_NOTIFICATION, uiIDA, 1); +#endif + } + else + { + // we're supposed to check for parental control restrictions before showing leaderboards + // The title enforces the user's NP parental control setting for age-based content + //restriction in network communications. + // If age restrictions are in place and the user's age does not meet + // the age restriction of the title's online service content rating (CERO, ESRB, PEGI, etc.), then the title must + //display a message such as the following and disallow online service for this user. + + bool bContentRestricted=false; +#if defined(__PS3__) || defined(__PSVITA__) + ProfileManager.GetChatAndContentRestrictions(iPad,true,nullptr,&bContentRestricted,nullptr); +#endif + if(bContentRestricted) + { +#if !(defined(_XBOX) || defined(_WINDOWS64) || defined(_XBOX_ONE)) // 4J Stu - Temp to get the win build running, but so we check this for other platforms + // you can't see leaderboards + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(),nullptr,this); +#endif + } + else + { + ProfileManager.SetLockedProfile(iPad); + // If the player was signed in before selecting play, we'll not have read the profile yet, so query the sign-in status to get this to happen + ProfileManager.QuerySigninStatus(); + +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + proceedToScene(iPad, eUIScene_LeaderboardsMenu); + } + } +} +void UIScene_MainMenu::RunUnlockOrDLC(int iPad) +{ + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + + // Check if this means downloadable content + if(ProfileManager.IsFullVersion()) + { +#ifdef __ORBIS__ + // 4J-PB - Check if there is a patch for the game + m_errorCode = ProfileManager.getNPAvailability(ProfileManager.GetPrimaryPad()); + + bool bPatchAvailable; + switch(m_errorCode) + { + case SCE_NP_ERROR_LATEST_PATCH_PKG_EXIST: + case SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED: + bPatchAvailable=true; + break; + default: + bPatchAvailable=false; + break; + } + + if(bPatchAvailable) + { + m_bIgnorePress=false; + + int32_t ret=sceErrorDialogInitialize(); + m_bErrorDialogRunning=true; + if ( ret==SCE_OK ) + { + SceErrorDialogParam param; + sceErrorDialogParamInitialize( ¶m ); + // 4J-PB - We want to display the option to get the patch now + param.errorCode = SCE_NP_ERROR_LATEST_PATCH_PKG_DOWNLOADED;//pClass->m_errorCode; + ret = sceUserServiceGetInitialUser( ¶m.userId ); + if ( ret == SCE_OK ) + { + ret=sceErrorDialogOpen( ¶m ); + } + } + +// UINT uiIDA[1]; +// uiIDA[0]=IDS_OK; +// ui.RequestMessageBox(IDS_PATCH_AVAILABLE_TITLE, IDS_PATCH_AVAILABLE_TEXT, uiIDA, 1, XUSER_INDEX_ANY,nullptr,this); + return; + } + + // Check if PSN is unavailable because of age restriction + if (m_errorCode == SCE_NP_ERROR_AGE_RESTRICTION) + { + m_bIgnorePress=false; + UINT uiIDA[1]; + uiIDA[0] = IDS_OK; + ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(), nullptr, this); + + return; + } +#endif + // downloadable content + if(ProfileManager.IsSignedInLive(iPad)) + { + if(ProfileManager.IsGuest(iPad)) + { + m_bIgnorePress=false; + ui.RequestErrorMessage(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); + } + else + { + + // If the player was signed in before selecting play, we'll not have read the profile yet, so query the sign-in status to get this to happen + ProfileManager.QuerySigninStatus(); + +#if defined _XBOX_ONE + if(app.GetTMSDLCInfoRead()) +#endif + { + bool bContentRestricted=false; +#if defined(__PS3__) || defined(__PSVITA__) + ProfileManager.GetChatAndContentRestrictions(iPad,true,nullptr,&bContentRestricted,nullptr); +#endif + if(bContentRestricted) + { + m_bIgnorePress=false; +#if !(defined(_XBOX) || defined(_WINDOWS64) || defined(_XBOX_ONE)) // 4J Stu - Temp to get the win build running, but so we check this for other platforms + // you can't see the store + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad(),nullptr,this); +#endif + } + else + { + ProfileManager.SetLockedProfile(iPad); +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + proceedToScene(ProfileManager.GetPrimaryPad(), eUIScene_DLCMainMenu); + } + } +#if defined _XBOX_ONE + else + { + // Changing to async TMS calls + app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_DLCMain); + + // block all input + m_bIgnorePress=true; + // We want to hide everything in this scene and display a timer until we get a completion for the TMS files +// for(int i=0;iRecordUpsellPresented(iPad, eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID); + ProfileManager.DisplayFullVersionPurchase(false,iPad,eSen_UpsellID_Full_Version_Of_Game); +#endif + } + } +} + +void UIScene_MainMenu::tick() +{ + UIScene::tick(); + + if ( (eNavigateWhenReady >= 0) ) + { + + int lockedProfile = ProfileManager.GetLockedProfile(); + +#ifdef _DURANGO + // 4J-JEV: DLC menu contains text localised to system language which we can't change. + // We need to switch to this language in-case it uses a different font. + if (eNavigateWhenReady == eUIScene_DLCMainMenu) setLanguageOverride(false); + + bool isSignedIn; + C4JStorage::eOptionsCallback status; + bool pendingFontChange; + if (lockedProfile >= 0) + { + isSignedIn = ProfileManager.IsSignedIn(lockedProfile); + status = app.GetOptionsCallbackStatus(lockedProfile); + pendingFontChange = ui.PendingFontChange(); + + if(status == C4JStorage::eOptions_Callback_Idle) + { + // make sure the TMS banned list data is ditched - the player may have gone in to help & options, backed out, and signed out + app.InvalidateBannedList(lockedProfile); + + // need to ditch any DLCOffers info + StorageManager.ClearDLCOffers(); + app.ClearAndResetDLCDownloadQueue(); + app.ClearDLCInstalled(); + } + } + + if ( (lockedProfile >= 0) + && isSignedIn + && ((status == C4JStorage::eOptions_Callback_Read)||(status == C4JStorage::eOptions_Callback_Write)) + && !pendingFontChange + ) +#endif + { + app.DebugPrintf("[MainMenu] Navigating away from MainMenu.\n"); + ui.NavigateToScene(lockedProfile, eNavigateWhenReady); + eNavigateWhenReady = static_cast(-1); + } +#ifdef _DURANGO + else + { + app.DebugPrintf("[MainMenu] Delaying navigation: lockedProfile=%i, %s, status=%ls, %s.\n", + lockedProfile, + isSignedIn ? "SignedIn" : "SignedOut", + app.toStringOptionsStatus(status).c_str(), + pendingFontChange ? "Pending font change" : "font OK"); + } +#endif + } + +#if defined(__PS3__) || defined (__ORBIS__) || defined(__PSVITA__) + if(m_bLaunchFullVersionPurchase) + { + int iCommerceState=app.GetCommerceState(); + // 4J-PB - if there's a commerce error - store down, player can't access store - let the DisplayFullVersionPurchase show the error + if((iCommerceState==CConsoleMinecraftApp::eCommerce_State_Online) || (iCommerceState==CConsoleMinecraftApp::eCommerce_State_Error)) + { + m_bLaunchFullVersionPurchase=false; + m_bIgnorePress=false; + updateTooltips(); + + // 4J-PB - need to check this user can access the store + bool bContentRestricted=false; + ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),true,nullptr,&bContentRestricted,nullptr); + if(bContentRestricted) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, ProfileManager.GetPrimaryPad()); + } + else + { + TelemetryManager->RecordUpsellPresented(ProfileManager.GetPrimaryPad(), eSen_UpsellID_Full_Version_Of_Game, app.m_dwOfferID); + ProfileManager.DisplayFullVersionPurchase(false,ProfileManager.GetPrimaryPad(),eSen_UpsellID_Full_Version_Of_Game); + } + } + } + + // 4J-PB - check for a trial version changing to a full version + if(m_bTrialVersion) + { + if(ProfileManager.IsFullVersion()) + { + m_bTrialVersion=false; + m_buttons[(int)eControl_UnlockOrDLC].init(app.GetString(IDS_DOWNLOADABLECONTENT),eControl_UnlockOrDLC); + } + } +#endif + +#if defined _XBOX_ONE + if(m_bWaitingForDLCInfo) + { + if(app.GetTMSDLCInfoRead()) + { + m_bWaitingForDLCInfo=false; + ProfileManager.SetLockedProfile(m_iPad); + proceedToScene(ProfileManager.GetPrimaryPad(), eUIScene_DLCMainMenu); + } + } + + if(g_NetworkManager.ShouldMessageForFullSession()) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_CONFIRM_OK; + ui.RequestErrorMessage( IDS_CONNECTION_FAILED, IDS_IN_PARTY_SESSION_FULL, uiIDA,1,ProfileManager.GetPrimaryPad()); + } +#endif + +#ifdef __ORBIS__ + + // process the error dialog (for a patch being available) + // SQRNetworkManager_Orbis::tickErrorDialog also runs the error dialog, so wrap this so this doesn't terminate a signin dialog + if(m_bErrorDialogRunning) + { + SceErrorDialogStatus stat = sceErrorDialogUpdateStatus(); + if( stat == SCE_ERROR_DIALOG_STATUS_FINISHED ) + { + sceErrorDialogTerminate(); + // if m_bRunGameChosen is true, we're here after selecting play game, and we should let the user continue with an offline game + if(m_bRunGameChosen) + { + m_bRunGameChosen=false; + m_eAction = eAction_RunGame; + + // give the option of continuing offline + UINT uiIDA[1]; + uiIDA[0]=IDS_PRO_NOTONLINE_DECLINE; + ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION_PATCH_AVAILABLE, uiIDA, 1, ProfileManager.GetPrimaryPad(), &UIScene_MainMenu::PlayOfflineReturned, this); + + } + m_bErrorDialogRunning=false; + } + } + + if(m_bLoadTrialOnNetworkManagerReady && g_NetworkManager.IsReadyToPlayOrIdle()) + { + m_bLoadTrialOnNetworkManagerReady = false; + LoadTrial(); + } + +#endif +} + +void UIScene_MainMenu::RunAchievements(int iPad) +{ +#if TO_BE_IMPLEMENTED + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + + // guests can't look at achievements + if(ProfileManager.IsGuest(iPad)) + { + ui.RequestErrorMessage(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); + } + else + { + XShowAchievementsUI( iPad ); + } +#endif + ui.NavigateToScene(iPad, eUIScene_AchievementsMenu); +} + +void UIScene_MainMenu::RunHelpAndOptions(int iPad) +{ + if(ProfileManager.IsGuest(iPad)) + { + UINT uiIDA[1]; + uiIDA[0]=IDS_OK; + ui.RequestErrorMessage(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1); + } + else + { + // If the player was signed in before selecting play, we'll not have read the profile yet, so query the sign-in status to get this to happen + ProfileManager.QuerySigninStatus(); + +#if TO_BE_IMPLEMENTED + // 4J-PB - You can be offline and still can go into help and options + if(app.GetTMSDLCInfoRead() || !ProfileManager.IsSignedInLive(iPad)) +#endif + { + ProfileManager.SetLockedProfile(iPad); +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + proceedToScene(iPad, eUIScene_HelpAndOptionsMenu); + } +#if TO_BE_IMPLEMENTED + else + { + // Changing to async TMS calls + app.SetTMSAction(iPad,eTMSAction_TMSPP_RetrieveFiles_HelpAndOptions); + + // block all input + m_bIgnorePress=true; + // We want to hide everything in this scene and display a timer until we get a completion for the TMS files + for(int i=0;iseed = 0; + param->saveData = nullptr; + param->settings = app.GetGameHostOption( eGameHostOption_Tutorial ) | app.GetGameHostOption(eGameHostOption_DisableSaving); + + vector *generators = app.getLevelGenerators(); + param->levelGen = generators->at(0); + + LoadingInputParams *loadingParams = new LoadingInputParams(); + loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc; + loadingParams->lpParam = static_cast(param); + + UIFullscreenProgressCompletionData *completionData = new UIFullscreenProgressCompletionData(); + completionData->bShowBackground=TRUE; + completionData->bShowLogo=TRUE; + completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes; + completionData->iPad = ProfileManager.GetPrimaryPad(); + loadingParams->completionData = completionData; + + ui.ShowTrialTimer(true); + +#ifdef _XBOX_ONE + ui.ShowPlayerDisplayname(true); +#endif + ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_FullscreenProgress, loadingParams); +} + +void UIScene_MainMenu::handleUnlockFullVersion() +{ + m_buttons[static_cast(eControl_UnlockOrDLC)].setLabel(IDS_DOWNLOADABLECONTENT,true); +} + + +#ifdef __PSVITA__ +int UIScene_MainMenu::SelectNetworkModeReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) +{ + UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; + + if(result==C4JStorage::EMessage_ResultAccept) + { + app.DebugPrintf("Setting network mode to PSN\n"); + app.SetGameSettings(0, eGameSetting_PSVita_NetworkModeAdhoc, 0); + } + else if(result==C4JStorage::EMessage_ResultDecline) + { + app.DebugPrintf("Setting network mode to Adhoc\n"); + app.SetGameSettings(0, eGameSetting_PSVita_NetworkModeAdhoc, 1); + } + pClass->updateTooltips(); + return 0; +} +#endif //__PSVITA__ diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.cpp index dc0e7b19..d3100491 100644 --- a/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.cpp @@ -7,16 +7,11 @@ UIScene_SettingsAudioMenu::UIScene_SettingsAudioMenu(int iPad, void *initData, U // Setup all the Iggy references we need for this scene initialiseMovie(); - WCHAR TempString[256]; - swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_MUSIC ),app.GetGameSettings(m_iPad,eGameSetting_MusicVolume)); - m_sliderMusic.init(TempString,eControl_Music,0,100,app.GetGameSettings(m_iPad,eGameSetting_MusicVolume)); - - swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_SOUND ),app.GetGameSettings(m_iPad,eGameSetting_SoundFXVolume)); - m_sliderSound.init(TempString,eControl_Sound,0,100,app.GetGameSettings(m_iPad,eGameSetting_SoundFXVolume)); - - m_checkboxCaveSounds.init(L"Cave Sounds",eControl_CaveSounds,(app.GetGameSettings(m_iPad,eGameSetting_CaveSounds)!=0)); - - m_checkboxMinecartSounds.init(L"Minecart Sounds",eControl_MinecartSounds,(app.GetGameSettings(m_iPad,eGameSetting_MinecartSounds)!=0)); + m_bNeedsMultiListPopulate = true; + m_bInitialPopulateDone = false; + m_bPendingSliderUpdate = false; + m_iPendingSliderId = 0; + m_iPendingSliderValue = 0; doHorizontalResizeCheck(); @@ -36,14 +31,74 @@ wstring UIScene_SettingsAudioMenu::getMoviePath() { if(app.GetLocalPlayerCount() > 1) { - return L"SettingsAudioMenuSplit"; + return L"MultilistMenuSplit"; } else { - return L"SettingsAudioMenu"; + return L"MultilistMenu"; } } +void UIScene_SettingsAudioMenu::tick() +{ + if(m_bNeedsMultiListPopulate) + { + m_bNeedsMultiListPopulate = false; + m_multiList.setupControl(this, m_rootPath, "MultiList"); + m_multiList.init(eControl_MultiList); + + WCHAR TempString[256]; + int musicVol = app.GetGameSettings(m_iPad, eGameSetting_MusicVolume); + int soundVol = app.GetGameSettings(m_iPad, eGameSetting_SoundFXVolume); + bool caveSounds = app.GetGameSettings(m_iPad, eGameSetting_CaveSounds) != 0; + bool minecartSounds = app.GetGameSettings(m_iPad, eGameSetting_MinecartSounds) != 0; + bool gameChat = app.GetGameSettings(m_iPad, eGameSetting_GameChat) != 0; + + swprintf(TempString, 256, L"%ls: %d%%", app.GetString(IDS_SLIDER_MUSIC), musicVol); + m_multiList.AddNewSlider(TempString, eControl_Music, 0, 100, 1, musicVol); + + swprintf(TempString, 256, L"%ls: %d%%", app.GetString(IDS_SLIDER_SOUND), soundVol); + m_multiList.AddNewSlider(TempString, eControl_Sound, 0, 100, 1, soundVol); + m_multiList.AddNewCheckbox(app.GetString(IDS_CHECKBOX_CAVE_SOUNDS), eControl_CaveSounds, caveSounds); + m_multiList.AddNewCheckbox(app.GetString(IDS_CHECKBOX_MINECART_SOUNDS), eControl_MinecartSounds, minecartSounds); + m_multiList.AddNewCheckbox(L"Game Chat", eControl_GameChat, gameChat); + m_multiList.EnableItem(eControl_GameChat, false); + + IggyName funcDoVert = registerFastName(L"DoVerticalResizeCheck"); + IggyName funcHideDesc = registerFastName(L"HideDescription"); + IggyDataValue result; + IggyPlayerCallMethodRS(getMovie(), &result, m_rootPath, funcDoVert, 0, nullptr); + doHorizontalResizeCheck(); + IggyPlayerCallMethodRS(getMovie(), &result, m_rootPath, funcHideDesc, 0, nullptr); + m_multiList.HighlightItem(eControl_Sound); + m_multiList.HighlightItem(eControl_Music); + } + + if(m_bPendingSliderUpdate) + { + m_bPendingSliderUpdate = false; + m_multiList.SetSliderValue(m_iPendingSliderId, m_iPendingSliderValue); + + WCHAR TempString[256]; + switch(m_iPendingSliderId) + { + case eControl_Music: + app.SetGameSettings(m_iPad, eGameSetting_MusicVolume, m_iPendingSliderValue); + swprintf(TempString, 256, L"%ls: %d%%", app.GetString(IDS_SLIDER_MUSIC), m_iPendingSliderValue); + m_multiList.SetSliderLabel(eControl_Music, TempString); + break; + case eControl_Sound: + app.SetGameSettings(m_iPad, eGameSetting_SoundFXVolume, m_iPendingSliderValue); + swprintf(TempString, 256, L"%ls: %d%%", app.GetString(IDS_SLIDER_SOUND), m_iPendingSliderValue); + m_multiList.SetSliderLabel(eControl_Sound, TempString); + break; + } + } + + UIScene::tick(); + m_bInitialPopulateDone = true; +} + void UIScene_SettingsAudioMenu::updateTooltips() { ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK); @@ -76,6 +131,7 @@ void UIScene_SettingsAudioMenu::handleInput(int iPad, int key, bool repeat, bool case ACTION_MENU_CANCEL: if(pressed) { + setGameSettings(); navigateBack(); } break; @@ -96,31 +152,27 @@ void UIScene_SettingsAudioMenu::handleInput(int iPad, int key, bool repeat, bool void UIScene_SettingsAudioMenu::handleSliderMove(F64 sliderId, F64 currentValue) { - WCHAR TempString[256]; + int sliderIdInt = static_cast(sliderId); int value = static_cast(currentValue); - switch(static_cast(sliderId)) + + ui.PlayUISFX(eSFX_Scroll); + + switch(sliderIdInt) { case eControl_Music: - m_sliderMusic.handleSliderMove(value); - - app.SetGameSettings(m_iPad,eGameSetting_MusicVolume,value); - swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_MUSIC ),value); - m_sliderMusic.setLabel(TempString); - - break; case eControl_Sound: - m_sliderSound.handleSliderMove(value); - - app.SetGameSettings(m_iPad,eGameSetting_SoundFXVolume,value); - swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_SOUND ),value); - m_sliderSound.setLabel(TempString); - + m_bPendingSliderUpdate = true; + m_iPendingSliderId = sliderIdInt; + m_iPendingSliderValue = value; break; } } void UIScene_SettingsAudioMenu::handleCheckboxToggled(F64 controlId, bool selected) { + if(m_bInitialPopulateDone) + ui.PlayUISFX(eSFX_Press); + switch(static_cast(controlId)) { case eControl_CaveSounds: @@ -131,3 +183,26 @@ void UIScene_SettingsAudioMenu::handleCheckboxToggled(F64 controlId, bool select break; } } + +void UIScene_SettingsAudioMenu::handlePress(F64 controlId, F64 childId) +{ + ui.PlayUISFX(eSFX_Press); +} + +void UIScene_SettingsAudioMenu::setGameSettings() +{ + app.SetGameSettings(m_iPad, eGameSetting_MusicVolume, m_multiList.GetSliderValue(eControl_Music)); + app.SetGameSettings(m_iPad, eGameSetting_SoundFXVolume, m_multiList.GetSliderValue(eControl_Sound)); + app.SetGameSettings(m_iPad, eGameSetting_CaveSounds, m_multiList.GetCheckboxValue(eControl_CaveSounds) ? 1 : 0); + app.SetGameSettings(m_iPad, eGameSetting_MinecartSounds, m_multiList.GetCheckboxValue(eControl_MinecartSounds) ? 1 : 0); + app.SetGameSettings(m_iPad, eGameSetting_GameChat, m_multiList.GetCheckboxValue(eControl_GameChat) ? 1 : 0); +} + +void UIScene_SettingsAudioMenu::handleGainFocus(bool navBack) +{ + if(navBack) + { + m_bNeedsMultiListPopulate = true; + m_bInitialPopulateDone = false; + } +} diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.h b/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.h index fdc2bbbc..03f7bb27 100644 --- a/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.h +++ b/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.h @@ -1,26 +1,29 @@ #pragma once #include "UIScene.h" +#include "UIControl_MultiList.h" class UIScene_SettingsAudioMenu : public UIScene { private: enum EControls { - eControl_Music, - eControl_Sound, - eControl_CaveSounds, - eControl_MinecartSounds + eControl_MultiList = 0, + eControl_Music = 1, + eControl_Sound = 2, + eControl_CaveSounds = 3, + eControl_MinecartSounds = 4, + eControl_GameChat = 5 }; - UIControl_Slider m_sliderMusic, m_sliderSound; // Sliders - UIControl_CheckBox m_checkboxCaveSounds; // Checkboxes - UIControl_CheckBox m_checkboxMinecartSounds; + UIControl_MultiList m_multiList; + bool m_bNeedsMultiListPopulate; + bool m_bInitialPopulateDone; + bool m_bPendingSliderUpdate; + int m_iPendingSliderId; + int m_iPendingSliderValue; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) - UI_MAP_ELEMENT( m_sliderMusic, "Music") - UI_MAP_ELEMENT( m_sliderSound, "Sound") - UI_MAP_ELEMENT( m_checkboxCaveSounds, "CaveSounds") - UI_MAP_ELEMENT( m_checkboxMinecartSounds, "MinecartSounds") UI_END_MAP_ELEMENTS_AND_NAMES() public: @@ -29,6 +32,7 @@ public: virtual EUIScene getSceneType() { return eUIScene_SettingsAudioMenu;} + virtual void tick(); virtual void updateTooltips(); virtual void updateComponents(); @@ -40,4 +44,10 @@ public: // INPUT virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); - virtual void handleSliderMove(F64 sliderId, F64 currentValue); virtual void handleCheckboxToggled(F64 controlId, bool selected);}; \ No newline at end of file + virtual void handleSliderMove(F64 sliderId, F64 currentValue); + virtual void handleCheckboxToggled(F64 controlId, bool selected); + virtual void handlePress(F64 controlId, F64 childId); + virtual void handleGainFocus(bool navBack); + + void setGameSettings(); +}; diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp index fdd57285..1e796091 100644 --- a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp @@ -60,59 +60,16 @@ UIScene_SettingsGraphicsMenu::UIScene_SettingsGraphicsMenu(int iPad, void *initD { // Setup all the Iggy references we need for this scene initialiseMovie(); - Minecraft* pMinecraft = Minecraft::GetInstance(); - - m_bNotInGame=(Minecraft::GetInstance()->level==nullptr); - m_checkboxClouds.init(app.GetString(IDS_CHECKBOX_RENDER_CLOUDS),eControl_Clouds,(app.GetGameSettings(m_iPad,eGameSetting_Clouds)!=0)); - m_checkboxBedrockFog.init(app.GetString(IDS_CHECKBOX_RENDER_BEDROCKFOG),eControl_BedrockFog,(app.GetGameSettings(m_iPad,eGameSetting_BedrockFog)!=0)); - m_checkboxCustomSkinAnim.init(app.GetString(IDS_CHECKBOX_CUSTOM_SKIN_ANIM),eControl_CustomSkinAnim,(app.GetGameSettings(m_iPad,eGameSetting_CustomSkinAnim)!=0)); - m_checkboxVSync.init(L"VSync",eControl_VSync,(app.GetGameSettings(m_iPad,eGameSetting_VSync)!=0)); - m_checkboxExclusiveFullscreen.init(L"Fullscreen",eControl_ExclusiveFullscreen,(app.GetGameSettings(m_iPad,eGameSetting_ExclusiveFullscreen)!=0)); - - WCHAR TempString[256]; - - swprintf(TempString, 256, L"Render Distance: %d",app.GetGameSettings(m_iPad,eGameSetting_RenderDistance)); - m_sliderRenderDistance.init(TempString,eControl_RenderDistance,0,3,DistanceToLevel(app.GetGameSettings(m_iPad,eGameSetting_RenderDistance))); - - swprintf( TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_GAMMA ),app.GetGameSettings(m_iPad,eGameSetting_Gamma)); - m_sliderGamma.init(TempString,eControl_Gamma,0,100,app.GetGameSettings(m_iPad,eGameSetting_Gamma)); - - const int initialFovSlider = app.GetGameSettings(m_iPad, eGameSetting_FOV); - const int initialFovDeg = sliderValueToFov(initialFovSlider); - swprintf(TempString, 256, L"FOV: %d", initialFovDeg); - m_sliderFOV.init(TempString, eControl_FOV, 0, FOV_SLIDER_MAX, initialFovSlider); + m_bNotInGame = (Minecraft::GetInstance()->level == nullptr); + m_bNeedsMultiListPopulate = true; + m_bInitialPopulateDone = false; + m_bPendingSliderUpdate = false; + m_iPendingSliderId = 0; + m_iPendingSliderValue = 0; doHorizontalResizeCheck(); -#ifndef _WINDOWS64 - // VSync and Exclusive Fullscreen are only available on PC - removeControl(&m_checkboxVSync, true); - removeControl(&m_checkboxExclusiveFullscreen, true); -#endif - - const bool bInGame=(Minecraft::GetInstance()->level!=nullptr); - const bool bIsPrimaryPad=(ProfileManager.GetPrimaryPad()==m_iPad); - // if we're not in the game, we need to use basescene 0 - if(bInGame) - { -#ifndef _WINDOWS64 - // Console splitscreen: non-host and non-primary players can't change world-level settings - if(bIsPrimaryPad) - { - if(!g_NetworkManager.IsHost()) - { - removeControl(&m_checkboxBedrockFog, true); - } - } - else - { - removeControl(&m_checkboxBedrockFog, true); - removeControl(&m_checkboxCustomSkinAnim, true); - } -#endif - } - if(app.GetLocalPlayerCount()>1) { #if TO_BE_IMPLEMENTED @@ -129,14 +86,95 @@ wstring UIScene_SettingsGraphicsMenu::getMoviePath() { if(app.GetLocalPlayerCount() > 1) { - return L"SettingsGraphicsMenuSplit"; + return L"MultilistMenuSplit"; } else { - return L"SettingsGraphicsMenu"; + return L"MultilistMenu"; } } +void UIScene_SettingsGraphicsMenu::tick() +{ + if (m_bNeedsMultiListPopulate) + { + m_bNeedsMultiListPopulate = false; + m_multiList.setupControl(this, m_rootPath, "MultiList"); + m_multiList.init(eControl_MultiList); + + WCHAR TempString[256]; + + m_multiList.AddNewCheckbox(app.GetString(IDS_CHECKBOX_RENDER_CLOUDS), eControl_Clouds, (app.GetGameSettings(m_iPad, eGameSetting_Clouds) != 0)); + m_multiList.AddNewCheckbox(app.GetString(IDS_CHECKBOX_CUSTOM_SKIN_ANIM), eControl_CustomSkinAnim, (app.GetGameSettings(m_iPad, eGameSetting_CustomSkinAnim) != 0)); + m_multiList.AddNewCheckbox(app.GetString(IDS_CHECKBOX_RENDER_BEDROCKFOG), eControl_BedrockFog, (app.GetGameSettings(m_iPad, eGameSetting_BedrockFog) != 0)); + +#ifdef _WINDOWS64 + m_multiList.AddNewCheckbox(L"VSync", eControl_VSync, (app.GetGameSettings(m_iPad, eGameSetting_VSync) != 0)); + m_multiList.AddNewCheckbox(L"Fullscreen", eControl_ExclusiveFullscreen, (app.GetGameSettings(m_iPad, eGameSetting_ExclusiveFullscreen) != 0)); +#endif + + int gammaVal = app.GetGameSettings(m_iPad, eGameSetting_Gamma); + swprintf(TempString, 256, L"%ls: %d%%", app.GetString(IDS_SLIDER_GAMMA), gammaVal); + m_multiList.AddNewSlider(TempString, eControl_Gamma, 0, 100, 1, gammaVal); + + int renderDistLevel = DistanceToLevel(app.GetGameSettings(m_iPad, eGameSetting_RenderDistance)); + swprintf(TempString, 256, L"Render Distance: %d", LevelToDistance(renderDistLevel)); + m_multiList.AddNewSlider(TempString, eControl_RenderDistance, 0, 3, 1, renderDistLevel); + + int fovSlider = app.GetGameSettings(m_iPad, eGameSetting_FOV); + int fovDeg = sliderValueToFov(fovSlider); + swprintf(TempString, 256, L"FOV: %d", fovDeg); + m_multiList.AddNewSlider(TempString, eControl_FOV, 0, FOV_SLIDER_MAX, 1, fovSlider); + + IggyName funcDoVert = registerFastName(L"DoVerticalResizeCheck"); + IggyName funcHideDesc = registerFastName(L"HideDescription"); + IggyDataValue result; + IggyPlayerCallMethodRS(getMovie(), &result, m_rootPath, funcDoVert, 0, nullptr); + doHorizontalResizeCheck(); + IggyPlayerCallMethodRS(getMovie(), &result, m_rootPath, funcHideDesc, 0, nullptr); + m_multiList.HighlightItem(eControl_Clouds); + } + + if (m_bPendingSliderUpdate) + { + m_bPendingSliderUpdate = false; + m_multiList.SetSliderValue(m_iPendingSliderId, m_iPendingSliderValue); + + WCHAR TempString[256]; + switch (m_iPendingSliderId) + { + case eControl_RenderDistance: + { + int dist = LevelToDistance(m_iPendingSliderValue); + app.SetGameSettings(m_iPad, eGameSetting_RenderDistance, dist); + Minecraft *pMinecraft = Minecraft::GetInstance(); + pMinecraft->options->viewDistance = 3 - m_iPendingSliderValue; + swprintf(TempString, 256, L"Render Distance: %d", dist); + m_multiList.SetSliderLabel(eControl_RenderDistance, TempString); + break; + } + case eControl_Gamma: + app.SetGameSettings(m_iPad, eGameSetting_Gamma, m_iPendingSliderValue); + swprintf(TempString, 256, L"%ls: %d%%", app.GetString(IDS_SLIDER_GAMMA), m_iPendingSliderValue); + m_multiList.SetSliderLabel(eControl_Gamma, TempString); + break; + case eControl_FOV: + { + int fovDeg = sliderValueToFov(m_iPendingSliderValue); + Minecraft *pMinecraft = Minecraft::GetInstance(); + pMinecraft->gameRenderer->SetFovVal(static_cast(fovDeg)); + app.SetGameSettings(m_iPad, eGameSetting_FOV, m_iPendingSliderValue); + swprintf(TempString, 256, L"FOV: %d", fovDeg); + m_multiList.SetSliderLabel(eControl_FOV, TempString); + break; + } + } + } + + UIScene::tick(); + m_bInitialPopulateDone = true; +} + void UIScene_SettingsGraphicsMenu::updateTooltips() { ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK); @@ -144,7 +182,7 @@ void UIScene_SettingsGraphicsMenu::updateTooltips() void UIScene_SettingsGraphicsMenu::updateComponents() { - const bool bNotInGame=(Minecraft::GetInstance()->level==nullptr); + bool bNotInGame=(Minecraft::GetInstance()->level==nullptr); if(bNotInGame) { m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); @@ -168,19 +206,8 @@ void UIScene_SettingsGraphicsMenu::handleInput(int iPad, int key, bool repeat, b case ACTION_MENU_CANCEL: if(pressed) { - // check the checkboxes - app.SetGameSettings(m_iPad,eGameSetting_Clouds,m_checkboxClouds.IsChecked()?1:0); - app.SetGameSettings(m_iPad,eGameSetting_BedrockFog,m_checkboxBedrockFog.IsChecked()?1:0); - app.SetGameSettings(m_iPad,eGameSetting_CustomSkinAnim,m_checkboxCustomSkinAnim.IsChecked()?1:0); - app.SetGameSettings(m_iPad,eGameSetting_VSync,m_checkboxVSync.IsChecked()?1:0); - app.SetGameSettings(m_iPad,eGameSetting_ExclusiveFullscreen,m_checkboxExclusiveFullscreen.IsChecked()?1:0); -#ifdef _WINDOWS64 - g_bVSync = m_checkboxVSync.IsChecked(); - SetExclusiveFullscreen(m_checkboxExclusiveFullscreen.IsChecked()); -#endif - + setGameSettings(); navigateBack(); - handled = true; } break; case ACTION_MENU_OK: @@ -200,44 +227,56 @@ void UIScene_SettingsGraphicsMenu::handleInput(int iPad, int key, bool repeat, b void UIScene_SettingsGraphicsMenu::handleSliderMove(F64 sliderId, F64 currentValue) { - WCHAR TempString[256]; - const int value = static_cast(currentValue); - switch(static_cast(sliderId)) + int sliderIdInt = static_cast(sliderId); + int value = static_cast(currentValue); + + ui.PlayUISFX(eSFX_Scroll); + + switch (sliderIdInt) { case eControl_RenderDistance: - { - m_sliderRenderDistance.handleSliderMove(value); - - const int dist = LevelToDistance(value); - - app.SetGameSettings(m_iPad,eGameSetting_RenderDistance,dist); - - const Minecraft* mc = Minecraft::GetInstance(); - mc->options->viewDistance = 3 - value; - swprintf(TempString,256,L"Render Distance: %d",dist); - m_sliderRenderDistance.setLabel(TempString); - } - break; - case eControl_Gamma: - m_sliderGamma.handleSliderMove(value); - - app.SetGameSettings(m_iPad,eGameSetting_Gamma,value); - swprintf( TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_GAMMA ),value); - m_sliderGamma.setLabel(TempString); - - break; - case eControl_FOV: - { - m_sliderFOV.handleSliderMove(value); - const Minecraft* pMinecraft = Minecraft::GetInstance(); - const int fovValue = sliderValueToFov(value); - pMinecraft->gameRenderer->SetFovVal(static_cast(fovValue)); - app.SetGameSettings(m_iPad, eGameSetting_FOV, value); - swprintf(TempString, 256, L"FOV: %d", fovValue); - m_sliderFOV.setLabel(TempString); - } + m_bPendingSliderUpdate = true; + m_iPendingSliderId = sliderIdInt; + m_iPendingSliderValue = value; break; } } + +void UIScene_SettingsGraphicsMenu::handleCheckboxToggled(F64 controlId, bool selected) +{ + if (m_bInitialPopulateDone) + ui.PlayUISFX(eSFX_Press); +} + +void UIScene_SettingsGraphicsMenu::handlePress(F64 controlId, F64 childId) +{ + ui.PlayUISFX(eSFX_Press); +} + +void UIScene_SettingsGraphicsMenu::setGameSettings() +{ + app.SetGameSettings(m_iPad, eGameSetting_Clouds, m_multiList.GetCheckboxValue(eControl_Clouds) ? 1 : 0); + app.SetGameSettings(m_iPad, eGameSetting_BedrockFog, m_multiList.GetCheckboxValue(eControl_BedrockFog) ? 1 : 0); + app.SetGameSettings(m_iPad, eGameSetting_CustomSkinAnim, m_multiList.GetCheckboxValue(eControl_CustomSkinAnim) ? 1 : 0); + app.SetGameSettings(m_iPad, eGameSetting_RenderDistance, LevelToDistance(m_multiList.GetSliderValue(eControl_RenderDistance))); + app.SetGameSettings(m_iPad, eGameSetting_Gamma, m_multiList.GetSliderValue(eControl_Gamma)); + app.SetGameSettings(m_iPad, eGameSetting_FOV, m_multiList.GetSliderValue(eControl_FOV)); + +#ifdef _WINDOWS64 + app.SetGameSettings(m_iPad, eGameSetting_VSync, m_multiList.GetCheckboxValue(eControl_VSync) ? 1 : 0); + app.SetGameSettings(m_iPad, eGameSetting_ExclusiveFullscreen, m_multiList.GetCheckboxValue(eControl_ExclusiveFullscreen) ? 1 : 0); + g_bVSync = m_multiList.GetCheckboxValue(eControl_VSync); + SetExclusiveFullscreen(m_multiList.GetCheckboxValue(eControl_ExclusiveFullscreen)); +#endif +} + +void UIScene_SettingsGraphicsMenu::handleGainFocus(bool navBack) +{ + if (navBack) + { + m_bNeedsMultiListPopulate = true; + m_bInitialPopulateDone = false; + } +} diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h index d308b078..d4ac2106 100644 --- a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h +++ b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h @@ -1,44 +1,43 @@ #pragma once #include "UIScene.h" -#include "Common/UI/UIControl_CheckBox.h" -#include "Common/UI/UIControl_Slider.h" +#include "UIControl_MultiList.h" class UIScene_SettingsGraphicsMenu : public UIScene { private: enum EControls { - eControl_Clouds, - eControl_BedrockFog, - eControl_CustomSkinAnim, - eControl_VSync, - eControl_ExclusiveFullscreen, - eControl_RenderDistance, - eControl_Gamma, - eControl_FOV, + eControl_MultiList = 0, + eControl_Clouds = 1, + eControl_BedrockFog = 2, + eControl_CustomSkinAnim = 3, + eControl_VSync = 4, + eControl_ExclusiveFullscreen = 5, + eControl_RenderDistance = 6, + eControl_Gamma = 7, + eControl_FOV = 8, }; - UIControl_CheckBox m_checkboxClouds, m_checkboxBedrockFog, m_checkboxCustomSkinAnim, m_checkboxVSync, m_checkboxExclusiveFullscreen; // Checkboxes - UIControl_Slider m_sliderRenderDistance, m_sliderGamma, m_sliderFOV; // Sliders - UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) - UI_MAP_ELEMENT( m_checkboxClouds, "Clouds") - UI_MAP_ELEMENT( m_checkboxBedrockFog, "BedrockFog") - UI_MAP_ELEMENT( m_checkboxCustomSkinAnim, "CustomSkinAnim") - UI_MAP_ELEMENT( m_checkboxVSync, "VSync") - UI_MAP_ELEMENT( m_checkboxExclusiveFullscreen, "ExclusiveFullscreen") - UI_MAP_ELEMENT( m_sliderRenderDistance, "RenderDistance") - UI_MAP_ELEMENT( m_sliderGamma, "Gamma") - UI_MAP_ELEMENT(m_sliderFOV, "FOV") - UI_END_MAP_ELEMENTS_AND_NAMES() + UIControl_MultiList m_multiList; + bool m_bNeedsMultiListPopulate; + bool m_bInitialPopulateDone; + bool m_bPendingSliderUpdate; + int m_iPendingSliderId; + int m_iPendingSliderValue; bool m_bNotInGame; + + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_END_MAP_ELEMENTS_AND_NAMES() + public: UIScene_SettingsGraphicsMenu(int iPad, void *initData, UILayer *parentLayer); virtual ~UIScene_SettingsGraphicsMenu(); virtual EUIScene getSceneType() { return eUIScene_SettingsGraphicsMenu;} - + + virtual void tick(); virtual void updateTooltips(); virtual void updateComponents(); @@ -51,8 +50,13 @@ public: virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); virtual void handleSliderMove(F64 sliderId, F64 currentValue); + virtual void handleCheckboxToggled(F64 controlId, bool selected); + virtual void handlePress(F64 controlId, F64 childId); + virtual void handleGainFocus(bool navBack); + + void setGameSettings(); static int LevelToDistance(int dist); static int DistanceToLevel(int dist); -}; \ No newline at end of file +}; diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsOptionsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsOptionsMenu.cpp index e7b5bea0..f28b92fd 100644 --- a/Minecraft.Client/Common/UI/UIScene_SettingsOptionsMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_SettingsOptionsMenu.cpp @@ -2,18 +2,6 @@ #include "UI.h" #include "UIScene_SettingsOptionsMenu.h" -#if defined(_XBOX_ONE) -#define _ENABLE_LANGUAGE_SELECT -#endif - -int UIScene_SettingsOptionsMenu::m_iDifficultySettingA[4]= -{ - IDS_DIFFICULTY_PEACEFUL, - IDS_DIFFICULTY_EASY, - IDS_DIFFICULTY_NORMAL, - IDS_DIFFICULTY_HARD -}; - int UIScene_SettingsOptionsMenu::m_iDifficultyTitleSettingA[4]= { IDS_DIFFICULTY_TITLE_PEACEFUL, @@ -28,171 +16,126 @@ UIScene_SettingsOptionsMenu::UIScene_SettingsOptionsMenu(int iPad, void *initDat // Setup all the Iggy references we need for this scene initialiseMovie(); - - m_bNotInGame=(Minecraft::GetInstance()->level==nullptr); - m_checkboxVerticalSplitscreen.init(app.GetString(IDS_CHECKBOX_VERTICAL_SPLIT_SCREEN),eControl_VerticalSplitscreen,(app.GetGameSettings(m_iPad,eGameSetting_SplitScreenVertical)!=0)); - m_checkboxViewBob.init(IDS_VIEW_BOBBING,eControl_ViewBob,(app.GetGameSettings(m_iPad,eGameSetting_ViewBob)!=0)); - m_checkboxShowHints.init(IDS_HINTS,eControl_ShowHints,(app.GetGameSettings(m_iPad,eGameSetting_Hints)!=0)); - m_checkboxDeathMessages.init(app.GetString(IDS_CHECKBOX_DEATH_MESSAGES),eControl_DeathMessages,(app.GetGameSettings(m_iPad,eGameSetting_DeathMessages)!=0)); - - unsigned char ucValue=app.GetGameSettings(m_iPad,eGameSetting_Autosave); - - wchar_t autosaveLabels[9][256]; - for(unsigned int i = 0; i < 9; ++i) - { - if(i==0) - { - swprintf( autosaveLabels[i], 256, L"%ls", app.GetString( IDS_SLIDER_AUTOSAVE_OFF )); - } - else - { - swprintf( autosaveLabels[i], 256, L"%ls: %d %ls", app.GetString( IDS_SLIDER_AUTOSAVE ),i*15, app.GetString( IDS_MINUTES )); - } - - } - m_sliderAutosave.setAllPossibleLabels(9,autosaveLabels); - m_sliderAutosave.init(autosaveLabels[ucValue],eControl_Autosave,0,8,ucValue); - - WCHAR TempString[256]; - swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_SENSITIVITY_INGAME ),app.GetGameSettings(m_iPad,eGameSetting_Sensitivity_InGame)); - m_sliderSensitivity_InGame.init(TempString,eControl_Sensitivity_InGame,0,200,app.GetGameSettings(m_iPad,eGameSetting_Sensitivity_InGame)); - -#if defined(_XBOX_ONE) || defined(__ORBIS__) - removeControl(&m_sliderAutosave,true); -#endif - - ucValue = app.GetGameSettings(m_iPad,eGameSetting_Difficulty); - wchar_t difficultyLabels[4][256]; - for(unsigned int i = 0; i < 4; ++i) - { - swprintf( difficultyLabels[i], 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ),app.GetString(m_iDifficultyTitleSettingA[i])); - } - m_sliderDifficulty.setAllPossibleLabels(4,difficultyLabels); - m_sliderDifficulty.init(difficultyLabels[ucValue],eControl_Difficulty,0,3,ucValue); - - wstring wsText=app.GetString(m_iDifficultySettingA[app.GetGameSettings(m_iPad,eGameSetting_Difficulty)]); - EHTMLFontSize size = eHTMLSize_Normal; - if(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen()) - { - size = eHTMLSize_Splitscreen; - } - wchar_t startTags[64]; - swprintf(startTags,64,L"",app.GetHTMLColour(eHTMLColor_White)); - wsText= startTags + wsText; - - m_labelDifficultyText.init(wsText); - - // If you are in-game, only the game host can change in-game gamertags, and you can't change difficulty - // only the primary player gets to change the autosave and difficulty settings - bool bRemoveDifficulty=false; - bool bRemoveAutosave=false; - // bool bRemoveInGameGamertags=false; - - bool bNotInGame=(Minecraft::GetInstance()->level==nullptr); - bool bPrimaryPlayer = ProfileManager.GetPrimaryPad()==m_iPad; - if(!bPrimaryPlayer) - { - bRemoveDifficulty=true; - bRemoveAutosave=true; - // bRemoveInGameGamertags=true; - } - - if(!bNotInGame) // in the game - { - bRemoveDifficulty=true; - if(!g_NetworkManager.IsHost()) - { - bRemoveAutosave=true; - // bRemoveInGameGamertags=true; - } - } - if(bRemoveDifficulty) - { - m_labelDifficultyText.setVisible( false ); - removeControl(&m_sliderDifficulty, true); - } - - if(bRemoveAutosave) - { - removeControl(&m_sliderAutosave, true); - } - - // if(bRemoveInGameGamertags) - // { - // removeControl(&m_checkboxInGameGamertags, true); - // } - - // 4J-JEV: Changing languages in-game will produce many a bug. - // MGH - disabled the language select for the patch build, we'll re-enable afterwards - // 4J Stu - Removed it with a preprocessor def as we turn this off in various places -#ifdef _ENABLE_LANGUAGE_SELECT - if (app.GetGameStarted()) - { - removeControl( &m_buttonLanguageSelect, false ); - } - else - { - m_buttonLanguageSelect.init(IDS_LANGUAGE_SELECTOR, eControl_Languages); - } -#else - removeControl( &m_buttonLanguageSelect, false ); -#endif + m_bNotInGame = (Minecraft::GetInstance()->level==nullptr); + m_bNeedsMultiListPopulate = true; + m_bNavigateToLanguageSelector = false; + m_bInitialPopulateDone = false; + m_bPendingSliderUpdate = false; + m_iPendingSliderId = 0; + m_iPendingSliderValue = 0; doHorizontalResizeCheck(); - bool bInGame=(Minecraft::GetInstance()->level!=nullptr); - - // if we're not in the game, we need to use basescene 0 - if(bInGame) - { - // If the game has started, then you need to be the host to change the in-game gamertags - if(!bPrimaryPlayer) - { - // hide things we don't want the splitscreen player changing - removeControl(&m_checkboxVerticalSplitscreen, true); - } - } - if(app.GetLocalPlayerCount()>1) { #if TO_BE_IMPLEMENTED app.AdjustSplitscreenScene(m_hObj,&m_OriginalPosition,m_iPad); #endif } - - m_labelDifficultyText.disableReinitialisation(); } UIScene_SettingsOptionsMenu::~UIScene_SettingsOptionsMenu() { } -void UIScene_SettingsOptionsMenu::tick() -{ - UIScene::tick(); - - - // if (m_bNavigateToLanguageSelector) - // { - // m_bNavigateToLanguageSelector = false; - // setGameSettings(); - // ui.NavigateToScene(m_iPad, eUIScene_LanguageSelector); - // } -} - wstring UIScene_SettingsOptionsMenu::getMoviePath() { if(app.GetLocalPlayerCount() > 1) { - return L"SettingsOptionsMenuSplit"; + return L"MultilistMenuSplit"; } else { - return L"SettingsOptionsMenu"; + return L"MultilistMenu"; } } +void UIScene_SettingsOptionsMenu::tick() +{ + if(m_bNeedsMultiListPopulate) + { + m_bNeedsMultiListPopulate = false; + m_multiList.setupControl(this, m_rootPath, "MultiList"); + m_multiList.init(eControl_MultiList); + + m_multiList.AddNewCheckbox(app.GetString(IDS_CHECKBOX_VERTICAL_SPLIT_SCREEN), eControl_VerticalSplitscreen, (app.GetGameSettings(m_iPad,eGameSetting_SplitScreenVertical)!=0)); + m_multiList.AddNewCheckbox(app.GetString(IDS_VIEW_BOBBING), eControl_ViewBob, (app.GetGameSettings(m_iPad,eGameSetting_ViewBob)!=0)); + m_multiList.AddNewCheckbox(app.GetString(IDS_HINTS), eControl_Hints, (app.GetGameSettings(m_iPad,eGameSetting_Hints)!=0)); + m_multiList.AddNewCheckbox(app.GetString(IDS_CHECKBOX_DEATH_MESSAGES), eControl_DeathMessages, (app.GetGameSettings(m_iPad,eGameSetting_DeathMessages)!=0)); + + if(m_bNotInGame) + { + m_multiList.AddNewButton(app.GetString(IDS_LANGUAGE_SELECTOR), eControl_Languages); + } + + WCHAR TempString[256]; + + int autosaveVal = app.GetGameSettings(m_iPad,eGameSetting_Autosave); + if(autosaveVal == 0) + swprintf(TempString, 256, L"%ls", app.GetString(IDS_SLIDER_AUTOSAVE_OFF)); + else + swprintf(TempString, 256, L"%ls: %d %ls", app.GetString(IDS_SLIDER_AUTOSAVE), autosaveVal*15, app.GetString(IDS_MINUTES)); + m_multiList.AddNewSlider(TempString, eControl_Autosave, 0, 8, 1, autosaveVal); + + swprintf(TempString, 256, L"%ls: %d%%", app.GetString(IDS_SLIDER_SENSITIVITY_INGAME), app.GetGameSettings(m_iPad,eGameSetting_Sensitivity_InGame)); + m_multiList.AddNewSlider(TempString, eControl_Sensitivity_InGame, 0, 200, 1, app.GetGameSettings(m_iPad,eGameSetting_Sensitivity_InGame)); + + int diffVal = app.GetGameSettings(m_iPad,eGameSetting_Difficulty); + swprintf(TempString, 256, L"%ls: %ls", app.GetString(IDS_SLIDER_DIFFICULTY), app.GetString(m_iDifficultyTitleSettingA[diffVal])); + m_multiList.AddNewSlider(TempString, eControl_Difficulty, 0, 3, 1, diffVal); + + IggyName funcDoVert = registerFastName(L"DoVerticalResizeCheck"); + IggyName funcHideDesc = registerFastName(L"HideDescription"); + IggyDataValue result; + IggyPlayerCallMethodRS(getMovie(), &result, m_rootPath, funcDoVert, 0, nullptr); + doHorizontalResizeCheck(); + IggyPlayerCallMethodRS(getMovie(), &result, m_rootPath, funcHideDesc, 0, nullptr); + m_multiList.HighlightItem(eControl_ViewBob); + m_multiList.HighlightItem(eControl_VerticalSplitscreen); + } + + if(m_bNavigateToLanguageSelector) + { + m_bNavigateToLanguageSelector = false; + setGameSettings(); + ui.NavigateToScene(m_iPad, eUIScene_LanguageSelector); + } + + if(m_bPendingSliderUpdate) + { + m_bPendingSliderUpdate = false; + m_multiList.SetSliderValue(m_iPendingSliderId, m_iPendingSliderValue); + + WCHAR TempString[256]; + switch(m_iPendingSliderId) + { + case eControl_Autosave: + app.SetGameSettings(m_iPad, eGameSetting_Autosave, m_iPendingSliderValue); + app.SetAutosaveTimerTime(); + if(m_iPendingSliderValue == 0) + swprintf(TempString, 256, L"%ls", app.GetString(IDS_SLIDER_AUTOSAVE_OFF)); + else + swprintf(TempString, 256, L"%ls: %d %ls", app.GetString(IDS_SLIDER_AUTOSAVE), m_iPendingSliderValue*15, app.GetString(IDS_MINUTES)); + m_multiList.SetSliderLabel(eControl_Autosave, TempString); + break; + case eControl_Sensitivity_InGame: + app.SetGameSettings(m_iPad, eGameSetting_Sensitivity_InGame, m_iPendingSliderValue); + swprintf(TempString, 256, L"%ls: %d%%", app.GetString(IDS_SLIDER_SENSITIVITY_INGAME), m_iPendingSliderValue); + m_multiList.SetSliderLabel(eControl_Sensitivity_InGame, TempString); + break; + case eControl_Difficulty: + app.SetGameSettings(m_iPad, eGameSetting_Difficulty, m_iPendingSliderValue); + swprintf(TempString, 256, L"%ls: %ls", app.GetString(IDS_SLIDER_DIFFICULTY), app.GetString(m_iDifficultyTitleSettingA[m_iPendingSliderValue])); + m_multiList.SetSliderLabel(eControl_Difficulty, TempString); + break; + } + } + + UIScene::tick(); + m_bInitialPopulateDone = true; +} + void UIScene_SettingsOptionsMenu::updateTooltips() { ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK); @@ -210,20 +153,21 @@ void UIScene_SettingsOptionsMenu::updateComponents() { m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,false); - if( app.GetLocalPlayerCount() == 1 ) m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,RenderManager.IsHiDef()); + if( app.GetLocalPlayerCount() == 1 ) m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); else m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); } } void UIScene_SettingsOptionsMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) { - ui.AnimateKeyPress(iPad, key, repeat, pressed, released); + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); switch(key) { case ACTION_MENU_CANCEL: if(pressed) { setGameSettings(); + navigateBack(); } break; case ACTION_MENU_OK: @@ -246,190 +190,67 @@ void UIScene_SettingsOptionsMenu::handlePress(F64 controlId, F64 childId) //CD - Added for audio ui.PlayUISFX(eSFX_Press); - switch(static_cast(controlId)) + switch(static_cast(childId)) { - // case eControl_Languages: - // m_bNavigateToLanguageSelector = true; - // break; + case eControl_Languages: + m_bNavigateToLanguageSelector = true; + break; } } -void UIScene_SettingsOptionsMenu::handleReload() +void UIScene_SettingsOptionsMenu::handleCheckboxToggled(F64 controlId, bool selected) { - // m_bNavigateToLanguageSelector = false; - - m_checkboxViewBob.init(IDS_VIEW_BOBBING,eControl_ViewBob,(app.GetGameSettings(m_iPad,eGameSetting_ViewBob)!=0)); - m_checkboxShowHints.init(IDS_HINTS,eControl_ShowHints,(app.GetGameSettings(m_iPad,eGameSetting_Hints)!=0)); - m_checkboxDeathMessages.init(IDS_CHECKBOX_DEATH_MESSAGES,eControl_DeathMessages,(app.GetGameSettings(m_iPad,eGameSetting_DeathMessages)!=0)); - - unsigned char ucValue=app.GetGameSettings(m_iPad,eGameSetting_Autosave); - - wchar_t autosaveLabels[9][256]; - for(unsigned int i = 0; i < 9; ++i) - { - if(i==0) - { - swprintf( autosaveLabels[i], 256, L"%ls", app.GetString( IDS_SLIDER_AUTOSAVE_OFF )); - } - else - { - swprintf( autosaveLabels[i], 256, L"%ls: %d %ls", app.GetString( IDS_SLIDER_AUTOSAVE ),i*15, app.GetString( IDS_MINUTES )); - } - - } - m_sliderAutosave.setAllPossibleLabels(9,autosaveLabels); - m_sliderAutosave.init(autosaveLabels[ucValue],eControl_Autosave,0,8,ucValue); - -#if defined(_XBOX_ONE) || defined(__ORBIS__) - removeControl(&m_sliderAutosave,true); -#endif - - ucValue = app.GetGameSettings(m_iPad,eGameSetting_Difficulty); - - wchar_t difficultyLabels[4][256]; - for(unsigned int i = 0; i < 4; ++i) - { - swprintf( difficultyLabels[i], 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ),app.GetString(m_iDifficultyTitleSettingA[i])); - } - m_sliderDifficulty.setAllPossibleLabels(4,difficultyLabels); - m_sliderDifficulty.init(difficultyLabels[ucValue],eControl_Difficulty,0,3,ucValue); - - wstring wsText=app.GetString(m_iDifficultySettingA[app.GetGameSettings(m_iPad,eGameSetting_Difficulty)]); - EHTMLFontSize size = eHTMLSize_Normal; - if(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen()) - { - size = eHTMLSize_Splitscreen; - } - wchar_t startTags[64]; - swprintf(startTags,64,L"",app.GetHTMLColour(eHTMLColor_White)); - wsText= startTags + wsText; - - m_labelDifficultyText.init(wsText); - - - // If you are in-game, only the game host can change in-game gamertags, and you can't change difficulty - // only the primary player gets to change the autosave and difficulty settings - bool bRemoveDifficulty=false; - bool bRemoveAutosave=false; - // bool bRemoveInGameGamertags=false; - - bool bNotInGame=(Minecraft::GetInstance()->level==nullptr); - bool bPrimaryPlayer = ProfileManager.GetPrimaryPad()==m_iPad; - if(!bPrimaryPlayer) - { - bRemoveDifficulty=true; - bRemoveAutosave=true; - // bRemoveInGameGamertags=true; - } - - if(!bNotInGame) // in the game - { - bRemoveDifficulty=true; - if(!g_NetworkManager.IsHost()) - { - bRemoveAutosave=true; - // bRemoveInGameGamertags=true; - } - } - if(bRemoveDifficulty) - { - m_labelDifficultyText.setVisible( false ); - removeControl(&m_sliderDifficulty, true); - } - - if(bRemoveAutosave) - { - removeControl(&m_sliderAutosave, true); - } - - // MGH - disabled the language select for the patch build, we'll re-enable afterwards - // 4J Stu - Removed it with a preprocessor def as we turn this off in various places -#ifdef _ENABLE_LANGUAGE_SELECT - // 4J-JEV: Changing languages in-game will produce many a bug. - if (app.GetGameStarted()) - { - removeControl( &m_buttonLanguageSelect, false ); - } - else - { - } -#else - removeControl( &m_buttonLanguageSelect, false ); -#endif - - doHorizontalResizeCheck(); + if(m_bInitialPopulateDone) + ui.PlayUISFX(eSFX_Press); } void UIScene_SettingsOptionsMenu::handleSliderMove(F64 sliderId, F64 currentValue) { + int sliderIdInt = static_cast(sliderId); int value = static_cast(currentValue); - WCHAR TempString[256]; - switch(static_cast(sliderId)) + + ui.PlayUISFX(eSFX_Scroll); + + switch(sliderIdInt) { case eControl_Autosave: - m_sliderAutosave.handleSliderMove(value); - - app.SetGameSettings(m_iPad,eGameSetting_Autosave,value); - // Update the autosave timer - app.SetAutosaveTimerTime(); - - break; case eControl_Sensitivity_InGame: - m_sliderSensitivity_InGame.handleSliderMove(value); - - app.SetGameSettings(m_iPad,eGameSetting_Sensitivity_InGame,value); - swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_SENSITIVITY_INGAME ),value); - m_sliderSensitivity_InGame.setLabel(TempString); - - break; case eControl_Difficulty: - m_sliderDifficulty.handleSliderMove(value); - - app.SetGameSettings(m_iPad,eGameSetting_Difficulty,value); - - wstring wsText=app.GetString(m_iDifficultySettingA[value]); - EHTMLFontSize size = eHTMLSize_Normal; - if(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen()) - { - size = eHTMLSize_Splitscreen; - } - wchar_t startTags[64]; - swprintf(startTags,64,L"",app.GetHTMLColour(eHTMLColor_White)); - wsText= startTags + wsText; - m_labelDifficultyText.setLabel(wsText.c_str()); + m_bPendingSliderUpdate = true; + m_iPendingSliderId = sliderIdInt; + m_iPendingSliderValue = value; break; } } void UIScene_SettingsOptionsMenu::setGameSettings() { - // check the checkboxes - app.SetGameSettings(m_iPad,eGameSetting_ViewBob,m_checkboxViewBob.IsChecked()?1:0); - app.SetGameSettings(m_iPad,eGameSetting_Hints,m_checkboxShowHints.IsChecked()?1:0); - app.SetGameSettings(m_iPad,eGameSetting_DeathMessages,m_checkboxDeathMessages.IsChecked()?1:0); + bool bSplitChanged = (app.GetGameSettings(m_iPad,eGameSetting_SplitScreenVertical)!=(m_multiList.GetCheckboxValue(eControl_VerticalSplitscreen)?1:0)); - if(app.GetGameSettings(m_iPad,eGameSetting_SplitScreenVertical)!=(m_checkboxVerticalSplitscreen.IsChecked()?1:0)) + app.SetGameSettings(m_iPad,eGameSetting_SplitScreenVertical,m_multiList.GetCheckboxValue(eControl_VerticalSplitscreen)?1:0); + app.SetGameSettings(m_iPad,eGameSetting_ViewBob,m_multiList.GetCheckboxValue(eControl_ViewBob)?1:0); + app.SetGameSettings(m_iPad,eGameSetting_Hints,m_multiList.GetCheckboxValue(eControl_Hints)?1:0); + app.SetGameSettings(m_iPad,eGameSetting_DeathMessages,m_multiList.GetCheckboxValue(eControl_DeathMessages)?1:0); + app.SetGameSettings(m_iPad,eGameSetting_Autosave,m_multiList.GetSliderValue(eControl_Autosave)); + app.SetGameSettings(m_iPad,eGameSetting_Sensitivity_InGame,m_multiList.GetSliderValue(eControl_Sensitivity_InGame)); + app.SetGameSettings(m_iPad,eGameSetting_Difficulty,m_multiList.GetSliderValue(eControl_Difficulty)); + + if(bSplitChanged && app.GetLocalPlayerCount()==2) { - // changed - app.SetGameSettings(m_iPad,eGameSetting_SplitScreenVertical,m_checkboxVerticalSplitscreen.IsChecked()?1:0); - - // close the xui scenes, so we don't have the navigate backed to menu at the wrong place - if(app.GetLocalPlayerCount()==2) - { - ui.CloseAllPlayersScenes(); - } - else - { - navigateBack(); - } + ui.CloseAllPlayersScenes(); } - else +} + +void UIScene_SettingsOptionsMenu::handleGainFocus(bool navBack) +{ + if(navBack) { - navigateBack(); + m_bNeedsMultiListPopulate = true; + m_bInitialPopulateDone = false; } +} // handled = true; // if the splitscreen vertical/horizontal has changed, need to update the scenes // 4J-PB - don't action changes here or we might write to the profile on backing out here and then get a change in the settings all, and write again on backing out there - //app.CheckGameSettingsChanged(true,pInputData->UserIndex); -} \ No newline at end of file + //app.CheckGameSettingsChanged(true,pInputData->UserIndex); \ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsOptionsMenu.h b/Minecraft.Client/Common/UI/UIScene_SettingsOptionsMenu.h index 7359321f..1b18fc4f 100644 --- a/Minecraft.Client/Common/UI/UIScene_SettingsOptionsMenu.h +++ b/Minecraft.Client/Common/UI/UIScene_SettingsOptionsMenu.h @@ -1,44 +1,40 @@ #pragma once #include "UIScene.h" +#include "UIControl_MultiList.h" class UIScene_SettingsOptionsMenu : public UIScene { private: enum EControls { - eControl_VerticalSplitscreen, - eControl_ViewBob, - eControl_ShowHints, - eControl_DeathMessages, - eControl_Autosave, - eControl_Sensitivity_InGame, - eControl_Difficulty + eControl_MultiList = 0, + eControl_VerticalSplitscreen = 1, + eControl_ViewBob = 2, + eControl_Hints = 3, + eControl_DeathMessages = 4, + eControl_Languages = 5, + eControl_Autosave = 6, + eControl_Sensitivity_InGame = 7, + eControl_Difficulty = 8, }; -protected: - static int m_iDifficultySettingA[4]; + + UIControl_MultiList m_multiList; + bool m_bNeedsMultiListPopulate; + bool m_bNavigateToLanguageSelector; + bool m_bInitialPopulateDone; + bool m_bPendingSliderUpdate; + int m_iPendingSliderId; + int m_iPendingSliderValue; + static int m_iDifficultyTitleSettingA[4]; -private: - UIControl_CheckBox m_checkboxDeathMessages, m_checkboxViewBob, m_checkboxShowHints, m_checkboxVerticalSplitscreen; // Checkboxes - UIControl_Slider m_sliderAutosave, m_sliderDifficulty, m_sliderSensitivity_InGame; // Sliders - UIControl_Label m_labelDifficultyText; //Text - UIControl_Button m_buttonLanguageSelect; + bool m_bNotInGame; UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) - UI_MAP_ELEMENT( m_checkboxVerticalSplitscreen, "VerticalSplitscreen") - UI_MAP_ELEMENT( m_checkboxViewBob, "ViewBob") - UI_MAP_ELEMENT( m_checkboxShowHints, "ShowHints") - UI_MAP_ELEMENT( m_checkboxDeathMessages, "DeathMessages") - // UI_MAP_ELEMENT( m_checkboxMashupWorlds, "ShowMashUpWorlds") - UI_MAP_ELEMENT( m_sliderAutosave, "Autosave") - UI_MAP_ELEMENT( m_sliderDifficulty, "Difficulty") - UI_MAP_ELEMENT( m_sliderSensitivity_InGame, "Sensitivity_InGame") - UI_MAP_ELEMENT( m_labelDifficultyText, "DifficultyText") - // UI_MAP_ELEMENT( m_buttonLanguageSelect, "Languages") UI_END_MAP_ELEMENTS_AND_NAMES() - bool m_bNotInGame; + //bool m_bNotInGame; // bool m_bMashUpWorldsUnhideOption; // bool m_bNavigateToLanguageSelector; @@ -61,12 +57,9 @@ public: // INPUT virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); virtual void handlePress(F64 controlId, F64 childId); - - virtual void handleReload(); - virtual void handleSliderMove(F64 sliderId, F64 currentValue); + virtual void handleCheckboxToggled(F64 controlId, bool selected); + virtual void handleGainFocus(bool navBack); -protected: void setGameSettings(); - -}; \ No newline at end of file +}; diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.cpp index 8dca0ffa..3e54e6c0 100644 --- a/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.cpp @@ -20,67 +20,15 @@ UIScene_SettingsUIMenu::UIScene_SettingsUIMenu(int iPad, void *initData, UILayer // Setup all the Iggy references we need for this scene initialiseMovie(); m_bControlTypeChanged = false; - - m_bNotInGame=(Minecraft::GetInstance()->level==nullptr); - - m_checkboxDisplayHUD.init(app.GetString(IDS_CHECKBOX_DISPLAY_HUD),eControl_DisplayHUD,(app.GetGameSettings(m_iPad,eGameSetting_DisplayHUD)!=0)); - m_checkboxDisplayHand.init(app.GetString(IDS_CHECKBOX_DISPLAY_HAND),eControl_DisplayHand,(app.GetGameSettings(m_iPad,eGameSetting_DisplayHand)!=0)); - - m_checkboxShowTooltips.init(IDS_IN_GAME_TOOLTIPS,eControl_ShowTooltips,(app.GetGameSettings(m_iPad,eGameSetting_Tooltips)!=0)); - m_checkboxDisplayAnimatedCharacter.init(app.GetString(IDS_CHECKBOX_ANIMATED_CHARACTER),eControl_DisplayAnimatedCharacter,(app.GetGameSettings(m_iPad,eGameSetting_AnimatedCharacter)!=0)); - - m_checkboxInGameGamertags.init(IDS_IN_GAME_GAMERTAGS,eControl_InGameGamertags,(app.GetGameSettings(m_iPad,eGameSetting_GamertagsVisible)!=0)); - m_checkboxShowSplitscreenGamertags.init(app.GetString(IDS_CHECKBOX_DISPLAY_SPLITSCREENGAMERTAGS),eControl_ShowSplitscreenGamertags,(app.GetGameSettings(m_iPad,eGameSetting_DisplaySplitscreenGamertags)!=0)); - m_checkboxShowClassicCrafting.init(app.GetString(IDS_CHECKBOX_CLASSICCRAFTING), eControl_ShowClassicCrafting, (app.GetGameSettings(m_iPad, eGameSetting_ClassicCrafting) != 0)); - // label is hardcoded for now (no IDS_* yet) - - m_checkboxHideLoadCreateJoinSaveSizeBar.init(L"Hide world disk space bar", eControl_HideSaveSizeBar, (app.GetGameSettings(m_iPad, eGameSetting_HideSaveSizeBar) != 0)); - - WCHAR TempString[256]; - - swprintf( TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_INTERFACEOPACITY ),app.GetGameSettings(m_iPad,eGameSetting_InterfaceOpacity)); - m_sliderInterfaceOpacity.init(TempString,eControl_InterfaceOpacity,0,100,app.GetGameSettings(m_iPad,eGameSetting_InterfaceOpacity)); - - swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_SENSITIVITY_INMENU ),app.GetGameSettings(m_iPad,eGameSetting_Sensitivity_InMenu)); - m_sliderSensitivityInMenu.init(TempString,eControl_SensitivityInMenu,0,200,app.GetGameSettings(m_iPad,eGameSetting_Sensitivity_InMenu)); - - swprintf( (WCHAR *)TempString, 256, L"%ls: %d", app.GetString( IDS_SLIDER_UISIZE ),app.GetGameSettings(m_iPad,eGameSetting_UISize)+1); - m_sliderUISize.init(TempString,eControl_UISize,1,3,app.GetGameSettings(m_iPad,eGameSetting_UISize)+1); - - swprintf( (WCHAR *)TempString, 256, L"%ls: %d", app.GetString( IDS_SLIDER_UISIZESPLITSCREEN ),app.GetGameSettings(m_iPad,eGameSetting_UISizeSplitscreen)+1); - m_sliderUISizeSplitscreen.init(TempString,eControl_UISizeSplitscreen,1,3,app.GetGameSettings(m_iPad,eGameSetting_UISizeSplitscreen)+1); - - swprintf( (WCHAR *)TempString, 256, L"%ls: %ls", app.GetString( IDS_SLIDER_CONTROLTYPE ),app.GetString(m_iControlTypeSettingA[app.GetGameSettings(m_iPad,eGameSetting_ControlType)])); - m_sliderControlType.init(TempString,eControl_ControlType,0,5,app.GetGameSettings(m_iPad,eGameSetting_ControlType)); + m_bNotInGame = (Minecraft::GetInstance()->level == nullptr); + m_bNeedsMultiListPopulate = true; + m_bInitialPopulateDone = false; + m_bPendingSliderUpdate = false; + m_iPendingSliderId = 0; + m_iPendingSliderValue = 0; doHorizontalResizeCheck(); - bool bInGame=(Minecraft::GetInstance()->level!=nullptr); - bool bPrimaryPlayer = ProfileManager.GetPrimaryPad()==m_iPad; - bool bRemoveInGameGamertags=false; - - if(!bPrimaryPlayer) - { - bRemoveInGameGamertags=true; - } - - // if we're not in the game, we need to use basescene 0 - if(bInGame) - { - // If the game has started, then you need to be the host to change the in-game gamertags - if(!bPrimaryPlayer) - { - // hide things we don't want the splitscreen player changing - removeControl(&m_checkboxShowSplitscreenGamertags, true); - } - removeControl(&m_sliderControlType, true); - } - - if(bRemoveInGameGamertags) - { - removeControl(&m_checkboxInGameGamertags, true); - } - if(app.GetLocalPlayerCount()>1) { #if TO_BE_IMPLEMENTED @@ -89,29 +37,6 @@ UIScene_SettingsUIMenu::UIScene_SettingsUIMenu(int iPad, void *initData, UILayer } } -void UIScene_SettingsUIMenu::updateTooltips() -{ - ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT,IDS_TOOLTIPS_BACK); -} - -void UIScene_SettingsUIMenu::updateComponents() -{ - bool bNotInGame=(Minecraft::GetInstance()->level==nullptr); - if(bNotInGame) - { - m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true); - m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); - } - else - { - m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,false); - - if( app.GetLocalPlayerCount() == 1 ) m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true); - else m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false); - - } -} - UIScene_SettingsUIMenu::~UIScene_SettingsUIMenu() { } @@ -120,11 +45,149 @@ wstring UIScene_SettingsUIMenu::getMoviePath() { if(app.GetLocalPlayerCount() > 1) { - return L"SettingsUIMenuSplit"; + return L"MultilistMenuSplit"; } else { - return L"SettingsUIMenu"; + return L"MultilistMenu"; + } +} + +void UIScene_SettingsUIMenu::tick() +{ + if(m_bNeedsMultiListPopulate) + { + m_bNeedsMultiListPopulate = false; + m_multiList.setupControl(this, m_rootPath, "MultiList"); + m_multiList.init(eControl_MultiList); + + bool bPrimaryPlayer = (ProfileManager.GetPrimaryPad() == m_iPad); + bool bInGame = !m_bNotInGame; + + WCHAR TempString[256]; + + m_multiList.AddNewCheckbox(app.GetString(IDS_CHECKBOX_DISPLAY_HUD), eControl_DisplayHUD, (app.GetGameSettings(m_iPad, eGameSetting_DisplayHUD) != 0)); + m_multiList.AddNewCheckbox(app.GetString(IDS_CHECKBOX_DISPLAY_HAND), eControl_DisplayHand, (app.GetGameSettings(m_iPad, eGameSetting_DisplayHand) != 0)); + + int opacityVal = app.GetGameSettings(m_iPad, eGameSetting_InterfaceOpacity); + swprintf(TempString, 256, L"%ls: %d%%", app.GetString(IDS_SLIDER_INTERFACEOPACITY), opacityVal); + m_multiList.AddNewSlider(TempString, eControl_InterfaceOpacity, 0, 100, 1, opacityVal); + + m_multiList.AddNewCheckbox(app.GetString(IDS_IN_GAME_TOOLTIPS), eControl_ShowTooltips, (app.GetGameSettings(m_iPad, eGameSetting_Tooltips) != 0)); + m_multiList.AddNewCheckbox(app.GetString(IDS_CHECKBOX_ANIMATED_CHARACTER), eControl_DisplayAnimatedCharacter, (app.GetGameSettings(m_iPad, eGameSetting_AnimatedCharacter) != 0)); + + int sensitivityVal = app.GetGameSettings(m_iPad, eGameSetting_Sensitivity_InMenu); + swprintf(TempString, 256, L"%ls: %d%%", app.GetString(IDS_SLIDER_SENSITIVITY_INMENU), sensitivityVal); + m_multiList.AddNewSlider(TempString, eControl_SensitivityInMenu, 0, 200, 1, sensitivityVal); + + if(bPrimaryPlayer) + { + m_multiList.AddNewCheckbox(app.GetString(IDS_IN_GAME_GAMERTAGS), eControl_InGameGamertags, (app.GetGameSettings(m_iPad, eGameSetting_GamertagsVisible) != 0)); + } + + if(!bInGame || bPrimaryPlayer) + { + m_multiList.AddNewCheckbox(app.GetString(IDS_CHECKBOX_DISPLAY_SPLITSCREENGAMERTAGS), eControl_ShowSplitscreenGamertags, (app.GetGameSettings(m_iPad, eGameSetting_DisplaySplitscreenGamertags) != 0)); + } + + m_multiList.AddNewCheckbox(app.GetString(IDS_CHECKBOX_CLASSICCRAFTING), eControl_ShowClassicCrafting, (app.GetGameSettings(m_iPad, eGameSetting_ClassicCrafting) != 0)); + m_multiList.AddNewCheckbox(L"Hide world disk space bar", eControl_HideSaveSizeBar, (app.GetGameSettings(m_iPad, eGameSetting_HideSaveSizeBar) != 0)); + + int uiSizeVal = app.GetGameSettings(m_iPad, eGameSetting_UISize) + 1; + swprintf(TempString, 256, L"%ls: %d", app.GetString(IDS_SLIDER_UISIZE), uiSizeVal); + m_multiList.AddNewSlider(TempString, eControl_UISize, 1, 3, 1, uiSizeVal); + + int uiSizeSplitVal = app.GetGameSettings(m_iPad, eGameSetting_UISizeSplitscreen) + 1; + swprintf(TempString, 256, L"%ls: %d", app.GetString(IDS_SLIDER_UISIZESPLITSCREEN), uiSizeSplitVal); + m_multiList.AddNewSlider(TempString, eControl_UISizeSplitscreen, 1, 3, 1, uiSizeSplitVal); + + if(!bInGame) + { + int controlTypeVal = app.GetGameSettings(m_iPad, eGameSetting_ControlType); + swprintf(TempString, 256, L"%ls: %ls", app.GetString(IDS_SLIDER_CONTROLTYPE), app.GetString(m_iControlTypeSettingA[controlTypeVal])); + m_multiList.AddNewSlider(TempString, eControl_ControlType, 0, 5, 1, controlTypeVal); + } + + IggyName funcDoVert = registerFastName(L"DoVerticalResizeCheck"); + IggyName funcHideDesc = registerFastName(L"HideDescription"); + IggyDataValue result; + IggyPlayerCallMethodRS(getMovie(), &result, m_rootPath, funcDoVert, 0, nullptr); + doHorizontalResizeCheck(); + IggyPlayerCallMethodRS(getMovie(), &result, m_rootPath, funcHideDesc, 0, nullptr); + m_multiList.HighlightItem(eControl_DisplayHUD); + } + + if(m_bPendingSliderUpdate) + { + m_bPendingSliderUpdate = false; + m_multiList.SetSliderValue(m_iPendingSliderId, m_iPendingSliderValue); + + WCHAR TempString[256]; + switch(m_iPendingSliderId) + { + case eControl_InterfaceOpacity: + app.SetGameSettings(m_iPad, eGameSetting_InterfaceOpacity, m_iPendingSliderValue); + swprintf(TempString, 256, L"%ls: %d%%", app.GetString(IDS_SLIDER_INTERFACEOPACITY), m_iPendingSliderValue); + m_multiList.SetSliderLabel(eControl_InterfaceOpacity, TempString); + break; + case eControl_SensitivityInMenu: + app.SetGameSettings(m_iPad, eGameSetting_Sensitivity_InMenu, m_iPendingSliderValue); + swprintf(TempString, 256, L"%ls: %d%%", app.GetString(IDS_SLIDER_SENSITIVITY_INMENU), m_iPendingSliderValue); + m_multiList.SetSliderLabel(eControl_SensitivityInMenu, TempString); + break; + case eControl_UISize: + app.SetGameSettings(m_iPad, eGameSetting_UISize, m_iPendingSliderValue - 1); + ui.UpdateSelectedItemPos(m_iPad); + swprintf(TempString, 256, L"%ls: %d", app.GetString(IDS_SLIDER_UISIZE), m_iPendingSliderValue); + m_multiList.SetSliderLabel(eControl_UISize, TempString); + break; + case eControl_UISizeSplitscreen: + app.SetGameSettings(m_iPad, eGameSetting_UISizeSplitscreen, m_iPendingSliderValue - 1); + ui.UpdateSelectedItemPos(m_iPad); + swprintf(TempString, 256, L"%ls: %d", app.GetString(IDS_SLIDER_UISIZESPLITSCREEN), m_iPendingSliderValue); + m_multiList.SetSliderLabel(eControl_UISizeSplitscreen, TempString); + break; + case eControl_ControlType: + app.SetGameSettings(m_iPad, eGameSetting_ControlType, m_iPendingSliderValue); + m_bControlTypeChanged = true; + swprintf(TempString, 256, L"%ls: %ls", app.GetString(IDS_SLIDER_CONTROLTYPE), app.GetString(m_iControlTypeSettingA[m_iPendingSliderValue])); + m_multiList.SetSliderLabel(eControl_ControlType, TempString); + break; + } + } + + UIScene::tick(); + m_bInitialPopulateDone = true; +} + +void UIScene_SettingsUIMenu::updateTooltips() +{ + ui.SetTooltips(m_iPad, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK); +} + +void UIScene_SettingsUIMenu::updateComponents() +{ + bool bNotInGame = (Minecraft::GetInstance()->level == nullptr); + if(bNotInGame) + { + m_parentLayer->showComponent(m_iPad, eUIComponent_Panorama, true); + m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, true); + } + else + { + m_parentLayer->showComponent(m_iPad, eUIComponent_Panorama, false); + + if(app.GetLocalPlayerCount() == 1) m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, true); + else m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, false); + } +} + +void UIScene_SettingsUIMenu::handleGainFocus(bool navBack) +{ + if(navBack) + { + m_bNeedsMultiListPopulate = true; + m_bInitialPopulateDone = false; } } @@ -138,17 +201,7 @@ void UIScene_SettingsUIMenu::handleInput(int iPad, int key, bool repeat, bool pr if(pressed) { const bool reloadControlTypeSkin = m_bControlTypeChanged; - - // check the checkboxes - app.SetGameSettings(m_iPad,eGameSetting_DisplayHUD,m_checkboxDisplayHUD.IsChecked()?1:0); - app.SetGameSettings(m_iPad,eGameSetting_DisplayHand,m_checkboxDisplayHand.IsChecked()?1:0); - app.SetGameSettings(m_iPad,eGameSetting_Tooltips,m_checkboxShowTooltips.IsChecked()?1:0); - app.SetGameSettings(m_iPad,eGameSetting_AnimatedCharacter,m_checkboxDisplayAnimatedCharacter.IsChecked()?1:0); - app.SetGameSettings(m_iPad,eGameSetting_GamertagsVisible,m_checkboxInGameGamertags.IsChecked()?1:0); - app.SetGameSettings(m_iPad,eGameSetting_DisplaySplitscreenGamertags,m_checkboxShowSplitscreenGamertags.IsChecked()?1:0); - app.SetGameSettings(m_iPad, eGameSetting_ClassicCrafting, m_checkboxShowClassicCrafting.IsChecked() ? 1 : 0); - app.SetGameSettings(m_iPad, eGameSetting_HideSaveSizeBar, m_checkboxHideLoadCreateJoinSaveSizeBar.IsChecked() ? 1 : 0); - + setGameSettings(); navigateBack(); if(reloadControlTypeSkin) { @@ -173,64 +226,66 @@ void UIScene_SettingsUIMenu::handleInput(int iPad, int key, bool repeat, bool pr void UIScene_SettingsUIMenu::handleSliderMove(F64 sliderId, F64 currentValue) { - WCHAR TempString[256]; + int sliderIdInt = static_cast(sliderId); int value = static_cast(currentValue); - switch(static_cast(sliderId)) + + ui.PlayUISFX(eSFX_Scroll); + + switch(sliderIdInt) { case eControl_InterfaceOpacity: - m_sliderInterfaceOpacity.handleSliderMove(value); - - app.SetGameSettings(m_iPad,eGameSetting_InterfaceOpacity,value); - swprintf( TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_INTERFACEOPACITY ),value); - m_sliderInterfaceOpacity.setLabel(TempString); - - break; case eControl_SensitivityInMenu: - m_sliderSensitivityInMenu.handleSliderMove(value); - - app.SetGameSettings(m_iPad,eGameSetting_Sensitivity_InMenu,value); - swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_SENSITIVITY_INMENU ),value); - m_sliderSensitivityInMenu.setLabel(TempString); - - break; case eControl_UISize: - m_sliderUISize.handleSliderMove(value); - - swprintf( (WCHAR *)TempString, 256, L"%ls: %d", app.GetString( IDS_SLIDER_UISIZE ),value); - m_sliderUISize.setLabel(TempString); - - // is this different from the current value? - if(value != app.GetGameSettings(m_iPad,eGameSetting_UISize)+1) - { - app.SetGameSettings(m_iPad,eGameSetting_UISize,value-1); - // Apply the changes to the selected text position - ui.UpdateSelectedItemPos(m_iPad); - } - - break; case eControl_UISizeSplitscreen: - m_sliderUISizeSplitscreen.handleSliderMove(value); - - swprintf( (WCHAR *)TempString, 256, L"%ls: %d", app.GetString( IDS_SLIDER_UISIZESPLITSCREEN ),value); - m_sliderUISizeSplitscreen.setLabel(TempString); - - if(value != app.GetGameSettings(m_iPad,eGameSetting_UISizeSplitscreen)+1) - { - // slider is 1 to 3 - app.SetGameSettings(m_iPad,eGameSetting_UISizeSplitscreen,value-1); - // Apply the changes to the selected text position - ui.UpdateSelectedItemPos(m_iPad); - } - - break; case eControl_ControlType: - m_sliderControlType.handleSliderMove(value); - app.SetGameSettings(m_iPad,eGameSetting_ControlType,value); - m_bControlTypeChanged = true; - - swprintf( (WCHAR *)TempString, 256, L"%ls: %ls", app.GetString( IDS_SLIDER_CONTROLTYPE ),app.GetString(m_iControlTypeSettingA[value])); - m_sliderControlType.setLabel(TempString); - + m_bPendingSliderUpdate = true; + m_iPendingSliderId = sliderIdInt; + m_iPendingSliderValue = value; break; } } + +void UIScene_SettingsUIMenu::handleCheckboxToggled(F64 controlId, bool selected) +{ + if(m_bInitialPopulateDone) + ui.PlayUISFX(eSFX_Press); +} + +void UIScene_SettingsUIMenu::handlePress(F64 controlId, F64 childId) +{ + ui.PlayUISFX(eSFX_Press); +} + +void UIScene_SettingsUIMenu::setGameSettings() +{ + bool bPrimaryPlayer = (ProfileManager.GetPrimaryPad() == m_iPad); + bool bInGame = !m_bNotInGame; + + app.SetGameSettings(m_iPad, eGameSetting_DisplayHUD, m_multiList.GetCheckboxValue(eControl_DisplayHUD) ? 1 : 0); + app.SetGameSettings(m_iPad, eGameSetting_DisplayHand, m_multiList.GetCheckboxValue(eControl_DisplayHand) ? 1 : 0); + app.SetGameSettings(m_iPad, eGameSetting_Tooltips, m_multiList.GetCheckboxValue(eControl_ShowTooltips) ? 1 : 0); + app.SetGameSettings(m_iPad, eGameSetting_AnimatedCharacter, m_multiList.GetCheckboxValue(eControl_DisplayAnimatedCharacter) ? 1 : 0); + + if(bPrimaryPlayer) + { + app.SetGameSettings(m_iPad, eGameSetting_GamertagsVisible, m_multiList.GetCheckboxValue(eControl_InGameGamertags) ? 1 : 0); + } + + if(!bInGame || bPrimaryPlayer) + { + app.SetGameSettings(m_iPad, eGameSetting_DisplaySplitscreenGamertags, m_multiList.GetCheckboxValue(eControl_ShowSplitscreenGamertags) ? 1 : 0); + } + + app.SetGameSettings(m_iPad, eGameSetting_ClassicCrafting, m_multiList.GetCheckboxValue(eControl_ShowClassicCrafting) ? 1 : 0); + app.SetGameSettings(m_iPad, eGameSetting_HideSaveSizeBar, m_multiList.GetCheckboxValue(eControl_HideSaveSizeBar) ? 1 : 0); + + app.SetGameSettings(m_iPad, eGameSetting_InterfaceOpacity, m_multiList.GetSliderValue(eControl_InterfaceOpacity)); + app.SetGameSettings(m_iPad, eGameSetting_Sensitivity_InMenu, m_multiList.GetSliderValue(eControl_SensitivityInMenu)); + app.SetGameSettings(m_iPad, eGameSetting_UISize, m_multiList.GetSliderValue(eControl_UISize) - 1); + app.SetGameSettings(m_iPad, eGameSetting_UISizeSplitscreen, m_multiList.GetSliderValue(eControl_UISizeSplitscreen) - 1); + + if(!bInGame) + { + app.SetGameSettings(m_iPad, eGameSetting_ControlType, m_multiList.GetSliderValue(eControl_ControlType)); + } +} diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.h b/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.h index 5f12d248..97b9bfec 100644 --- a/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.h +++ b/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.h @@ -1,6 +1,7 @@ #pragma once #include "UIScene.h" +#include "UIControl_MultiList.h" class UIScene_SettingsUIMenu : public UIScene { @@ -9,52 +10,44 @@ protected: private: enum EControls { - eControl_DisplayHUD, - eControl_DisplayHand, - eControl_SensitivityInMenu, - eControl_InterfaceOpacity, - eControl_ShowTooltips, - eControl_DisplayAnimatedCharacter, - eControl_InGameGamertags, - eControl_ShowSplitscreenGamertags, - eControl_ShowClassicCrafting, - eControl_HideSaveSizeBar, - eControl_UISize, - eControl_UISizeSplitscreen, - eControl_ControlType, + eControl_MultiList = 0, + eControl_DisplayHUD = 1, + eControl_DisplayHand = 2, + eControl_ShowTooltips = 3, + eControl_DisplayAnimatedCharacter = 4, + eControl_InGameGamertags = 5, + eControl_ShowSplitscreenGamertags = 6, + eControl_ShowClassicCrafting = 7, + eControl_HideSaveSizeBar = 8, + eControl_InterfaceOpacity = 9, + eControl_SensitivityInMenu = 10, + eControl_UISize = 11, + eControl_UISizeSplitscreen = 12, + eControl_ControlType = 13, }; - UIControl_CheckBox m_checkboxDisplayHUD, m_checkboxDisplayHand, m_checkboxDisplayAnimatedCharacter, m_checkboxShowSplitscreenGamertags, m_checkboxShowClassicCrafting, m_checkboxShowTooltips, m_checkboxInGameGamertags, m_checkboxHideLoadCreateJoinSaveSizeBar; // Checkboxes - UIControl_Slider m_sliderInterfaceOpacity, m_sliderSensitivityInMenu, m_sliderUISize, m_sliderUISizeSplitscreen, m_sliderControlType; // Sliders + UIControl_MultiList m_multiList; + bool m_bNeedsMultiListPopulate; + bool m_bInitialPopulateDone; + bool m_bPendingSliderUpdate; + int m_iPendingSliderId; + int m_iPendingSliderValue; bool m_bControlTypeChanged; + bool m_bNotInGame; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) - UI_MAP_ELEMENT( m_checkboxDisplayHUD, "DisplayHUD") - UI_MAP_ELEMENT( m_checkboxDisplayHand, "DisplayHand") - UI_MAP_ELEMENT( m_sliderInterfaceOpacity, "InterfaceOpacity") - - UI_MAP_ELEMENT( m_checkboxShowTooltips, "ShowTooltips") - UI_MAP_ELEMENT( m_checkboxDisplayAnimatedCharacter, "DisplayAnimatedCharacter") - UI_MAP_ELEMENT( m_sliderSensitivityInMenu, "SensitivityInMenu") - - UI_MAP_ELEMENT( m_checkboxInGameGamertags, "InGameGamertags") - UI_MAP_ELEMENT( m_checkboxShowSplitscreenGamertags, "ShowSplitscreenGamertags") - UI_MAP_ELEMENT(m_checkboxShowClassicCrafting, "ShowClassicCrafting") - UI_MAP_ELEMENT(m_checkboxHideLoadCreateJoinSaveSizeBar, "LoadCreateJoinSaveSizeBar") - - UI_MAP_ELEMENT( m_sliderUISize, "UISize") - UI_MAP_ELEMENT( m_sliderUISizeSplitscreen, "UISizeSplitscreen") - UI_MAP_ELEMENT( m_sliderControlType, "ControlType") UI_END_MAP_ELEMENTS_AND_NAMES() - bool m_bNotInGame; public: UIScene_SettingsUIMenu(int iPad, void *initData, UILayer *parentLayer); virtual ~UIScene_SettingsUIMenu(); virtual EUIScene getSceneType() { return eUIScene_SettingsUIMenu;} - + + virtual void tick(); virtual void updateTooltips(); virtual void updateComponents(); + virtual void handleGainFocus(bool navBack); protected: // TODO: This should be pure virtual in this class @@ -65,4 +58,8 @@ public: virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); virtual void handleSliderMove(F64 sliderId, F64 currentValue); + virtual void handleCheckboxToggled(F64 controlId, bool selected); + virtual void handlePress(F64 controlId, F64 childId); + + void setGameSettings(); }; diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp index d9415cb2..a28a6091 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -430,6 +430,20 @@ void DefineActions(void) InputManager.SetGameJoypadMaps(MAP_STYLE_2,MINECRAFT_ACTION_DPAD_RIGHT, _360_JOY_BUTTON_DPAD_RIGHT); InputManager.SetGameJoypadMaps(MAP_STYLE_2,MINECRAFT_ACTION_DPAD_UP, _360_JOY_BUTTON_DPAD_UP); InputManager.SetGameJoypadMaps(MAP_STYLE_2,MINECRAFT_ACTION_DPAD_DOWN, _360_JOY_BUTTON_DPAD_DOWN); + + for (int pad = 0; pad < 4; pad++) + { + InputManager.AddMapButtonSwap(pad, 1, 0, _360_JOY_BUTTON_A, _360_JOY_BUTTON_B); + InputManager.AddMapButtonSwap(pad, 1, 1, _360_JOY_BUTTON_A, _360_JOY_BUTTON_B); + InputManager.AddMapButtonSwap(pad, 1, 2, _360_JOY_BUTTON_A, _360_JOY_BUTTON_B); + + if (pad == 0) + { + InputManager.AddMapButtonSwap(pad, 0, 0, _360_JOY_BUTTON_LTHUMB, _360_JOY_BUTTON_RTHUMB); + InputManager.AddMapButtonSwap(pad, 0, 1, _360_JOY_BUTTON_LTHUMB, _360_JOY_BUTTON_RTHUMB); + InputManager.AddMapButtonSwap(pad, 0, 2, _360_JOY_BUTTON_LTHUMB, _360_JOY_BUTTON_RTHUMB); + } + } } #if 0 diff --git a/Minecraft.Client/Windows64Media/loc/stringsGeneric.xml b/Minecraft.Client/Windows64Media/loc/stringsGeneric.xml index 1b8d725a..1791279a 100644 --- a/Minecraft.Client/Windows64Media/loc/stringsGeneric.xml +++ b/Minecraft.Client/Windows64Media/loc/stringsGeneric.xml @@ -1,9629 +1,9637 @@ - - - New Downloadable Content is available! Access it from the Minecraft Store button on the Main Menu. - - - - You can change the look of your character with a Skin Pack from the Minecraft Store. Select 'Minecraft Store' on the Main Menu to see what's available. - - - - Alter the gamma settings to make the game brighter or darker. - - - - If you set the game difficulty to Peaceful, your health will automatically regenerate, and no monsters will come out at night! - - - - Feed a bone to a wolf to tame it. You can then make it sit or follow you. - - - - You can drop items when in the Inventory menu by moving the cursor off the menu and pressing{*CONTROLLER_VK_A*} - - - - Sleeping in a bed at night will fast forward the game to dawn, but all players in a multiplayer game need to sleep in beds at the same time. - - - - Harvest pork chops from pigs, and cook and eat them to regain health. - - - - Harvest leather from cows, and use it to make armor. - - - - If you have an empty bucket, you can fill it with milk from a cow, or water, or lava! - - - - Use a hoe to prepare areas of ground for planting. - - - - Spiders won't attack you during the day - unless you attack them. - - - - Digging soil or sand with a spade is faster than with your hand! - - - - Eating cooked pork chops gives more health than eating raw pork chops. - - - - Make some torches to light up areas at night. Monsters will avoid the areas around these torches. - - - - Get to destinations faster with a minecart and rail! - - - - Plant some saplings and they'll grow into trees. - - - - Pigmen won't attack you, unless you attack them. - - - - You can change your game spawn point and skip to dawn by sleeping in a bed. - - - - Hit those fireballs back at the Ghast! - - - - Building a portal will allow you to travel to another dimension - The Nether. - - - - Press{*CONTROLLER_VK_B*} to drop the item currently in your hand! - - - - Use the right tool for the job! - - - - If you can't find any coal for your torches, you can always make charcoal from trees in a furnace. - - - - Digging straight down or straight up is not a great idea. - - - - Bonemeal (crafted from a Skeleton bone) can be used as a fertilizer, and can make things grow instantly! - - - - Creepers explode when they get close to you! - - - - Obsidian is created when water hits a lava source block. - - - - Lava can take minutes to disappear COMPLETELY when the source block is removed. - - - - Cobblestone is resistant to Ghast fireballs, making it useful for guarding portals. - - - - Blocks that can be used as a light source will melt snow and ice. This includes torches, glowstone, and Jack-O-Lanterns. - - - - Take caution when building structures made of wool in open air, as lightning from thunderstorms can set wool on fire. - - - - A single bucket of lava can be used in a furnace to smelt 100 blocks. - - - - The instrument played by a note block depends on the material beneath it. - - - - Zombies and Skeletons can survive daylight if they are in water. - - - - Attacking a wolf will cause any wolves in the immediate vicinity to turn hostile and attack you. This trait is also shared by Zombie Pigmen. - - - - Wolves cannot enter the Nether. - - - - Wolves won't attack Creepers. - - - - Chickens lay an egg every 5 to 10 minutes. - - - - Obsidian can only be mined with a diamond pickaxe. - - - - Creepers are the easiest obtainable source of gunpowder. - - - - Placing two chests side by side will make one large chest. - - - - Tame wolves show their health with the position of their tail. Feed them meat to heal them. - - - - Cook cactus in a furnace to get green dye. - - - - Read the What's New section in the How To Play menus to see the latest update information about the game. - - - - Stackable fences are in the game now! - - - - Some animals will follow you if you have wheat in your hand. - - - - If an animal can't move more than 20 blocks in any direction, it won't despawn. - - - - Music by C418! - - - - Notch has over a million followers on twitter! - - - - Not all Swedish people have blonde hair. Some, like Jens from Mojang, even have ginger hair! - - - - There will be an update to this game eventually! - - - - Who is Notch? - - - - Mojang has more awards than staff! - - - - Some famous people play Minecraft! - - - - deadmau5 likes Minecraft! - - - - Do not look directly at the bugs. - - - - Creepers were born from a coding bug. - - - - Is it a chicken or is it a duck? - - - - Were you at Minecon? - - - - No-one at Mojang has ever seen junkboy's face. - - - - Did you know there's a Minecraft Wiki? - - - - Mojang's new office is cool! - - - - Minecon 2013 was in Orlando, Florida, USA! - - - - .party() was excellent! - - - - Always assume rumors are false, rather than assuming they're true! - - - - {*T3*}HOW TO PLAY : BASICS{*ETW*}{*B*}{*B*} -Minecraft is a game about placing blocks to build anything you can imagine. At night monsters come out, make sure to build a shelter before that happens.{*B*}{*B*} -Use{*CONTROLLER_ACTION_LOOK*} to look around.{*B*}{*B*} -Use{*CONTROLLER_ACTION_MOVE*} to move around.{*B*}{*B*} -Press{*CONTROLLER_ACTION_JUMP*} to jump.{*B*}{*B*} -Push{*CONTROLLER_ACTION_MOVE*} forward twice in rapid succession to sprint. While you hold {*CONTROLLER_ACTION_MOVE*} forward, the character will continue to sprint unless they run out of sprint time or the Food Bar has less than{*ICON_SHANK_03*}.{*B*}{*B*} -Hold{*CONTROLLER_ACTION_ACTION*} to mine and chop using your hand or whatever you are holding. You may need to craft a tool to mine some blocks.{*B*}{*B*} -If you are holding an item in your hand, use{*CONTROLLER_ACTION_USE*} to use that item, or press{*CONTROLLER_ACTION_DROP*} to drop that item. - - - - {*T3*}HOW TO PLAY : HUD{*ETW*}{*B*}{*B*} -The HUD shows information about your status; your health, your remaining oxygen when you are under water, your hunger level (you need to eat to replenish this), and your armor if you are wearing any. If you lose some health, but have a food bar with 9 or more{*ICON_SHANK_01*} in it, your health will automatically replenish. Eating food will replenish your food bar.{*B*} -The Experience Bar is also shown here, with a numeric value to show your Experience Level, and the bar indicating how many Experience Points are required to increase your Experience Level. Experience Points are gained by collecting the Experience Orbs dropped by mobs when they die, mining certain block types, breeding animals, fishing, and smelting ores in a furnace.{*B*}{*B*} -It also shows the items that are available to use. Use{*CONTROLLER_ACTION_LEFT_SCROLL*} and{*CONTROLLER_ACTION_RIGHT_SCROLL*} to change the item in your hand. - - - - {*T3*}HOW TO PLAY : INVENTORY{*ETW*}{*B*}{*B*} -Use{*CONTROLLER_ACTION_INVENTORY*} to view your inventory.{*B*}{*B*} -This screen shows items available for use in your hand, and all the other items that you are carrying. Your armor is also shown here.{*B*}{*B*} -Use{*CONTROLLER_MENU_NAVIGATE*} to move the pointer. Use{*CONTROLLER_VK_A*} to pick an item under the pointer. If there is more than one item here this will pick them all up, or you can use{*CONTROLLER_VK_X*} to pick up just half of them.{*B*}{*B*} -Move the item with the pointer over another space in the inventory and place it there using{*CONTROLLER_VK_A*}. With multiple items on the pointer, use{*CONTROLLER_VK_A*} to place them all, or{*CONTROLLER_VK_X*} to place just one.{*B*}{*B*} -If an item you are over is armor, you will be shown a tooltip to enable a quick move of this to the right armor slot in the inventory.{*B*}{*B*} -It is possible to change the color of your Leather Armor by dying it, you can do this in the inventory menu by holding the dye in your pointer, then pressing{*CONTROLLER_VK_X*} whilst the pointer is over the piece you wish to dye. - - - - - {*T3*}HOW TO PLAY : CHEST{*ETW*}{*B*}{*B*} -Once you have crafted a Chest, you can place this in the world and then use it with{*CONTROLLER_ACTION_USE*} to store items from your inventory.{*B*}{*B*} -Use the pointer to move items between your inventory and the chest.{*B*}{*B*} -Items in the chest will be stored there for you to swap back into your inventory again later. - - - - - {*T3*}HOW TO PLAY : LARGE CHEST{*ETW*}{*B*}{*B*} -Two chests placed next to each other will be combined to form a Large Chest. This can store even more items.{*B*}{*B*} -It is used in the same way as a normal chest. - - - - - {*T3*}HOW TO PLAY : CRAFTING{*ETW*}{*B*}{*B*} -In the Crafting interface, you can combine items from your inventory to create new types of items. Use{*CONTROLLER_ACTION_CRAFTING*} to open the crafting interface.{*B*}{*B*} -Scroll through the tabs at the top using{*CONTROLLER_VK_LB*} and{*CONTROLLER_VK_RB*} to select the type of item you wish to craft, then use{*CONTROLLER_MENU_NAVIGATE*} to select the item to craft.{*B*}{*B*} -The crafting area shows the items required to craft the new item. Press{*CONTROLLER_VK_A*} to craft the item and place it in your inventory. - - - - - {*T3*}HOW TO PLAY : CRAFTING TABLE{*ETW*}{*B*}{*B*} -You can craft larger items using a Crafting Table.{*B*}{*B*} -Place the table in the world and press{*CONTROLLER_ACTION_USE*} to use it.{*B*}{*B*} -Crafting on a table works in the same way as basic crafting, but you have a larger crafting area, and a more varied selection of items to craft. - - - - - {*T3*}HOW TO PLAY : FURNACE{*ETW*}{*B*}{*B*} -A Furnace allows you to change items by firing them. For example, you can turn iron ore into iron ingots in the furnace.{*B*}{*B*} -Place the furnace in the world and press{*CONTROLLER_ACTION_USE*} to use it.{*B*}{*B*} -You need to put some fuel into the bottom of the furnace, and the item to be fired in the top. The furnace will then fire up and start working.{*B*}{*B*} -When your items have been fired, you can move them from the output area into your inventory.{*B*}{*B*} -If an item you are over is an ingredient or fuel for the furnace, you will be shown tooltips to enable a quick move of this to the furnace. - - - - - {*T3*}HOW TO PLAY : DISPENSER{*ETW*}{*B*}{*B*} -A Dispenser is used to shoot out items. You will need to place a switch, for example a lever, next to the dispenser to trigger it.{*B*}{*B*} -To fill the dispenser with items press{*CONTROLLER_ACTION_USE*}, then move the items that you want to dispense from your inventory into the dispenser.{*B*}{*B*} -Now when you use the switch, the dispenser will shoot out an item. - - - - - {*T3*}HOW TO PLAY : BREWING{*ETW*}{*B*}{*B*} -Brewing potions requires a Brewing Stand, which can be built at a crafting table. Every potion starts off with a bottle of water, which is made by filling a Glass Bottle with water from a Cauldron, or a water source.{*B*} -A Brewing Stand has three slots for bottles, so can make three potions at the same time. One ingredient can be used over all three bottles, so always brew three potions at the same time to best use your resources.{*B*} -Putting a potion ingredient in the top position at the Brewing Stand will make a base potion after a short time. This doesn't have any effect by itself, but brewing another ingredient with this base potion will give you a potion with an effect.{*B*} -Once you have this potion you can add a third ingredient to make the effect last longer (using Redstone Dust), be more intense (using Glowstone Dust), or turn into a harmful potion (using a Fermented Spider Eye).{*B*} -You can also add gunpowder to any potion to turn it into a Splash Potion, which can then be thrown. The thrown Splash Potion will cause the potion effect to apply over the area it lands in.{*B*} - -The source ingredients for potions are :-{*B*}{*B*} -* {*T2*}Nether Wart{*ETW*}{*B*} -* {*T2*}Spider Eye{*ETW*}{*B*} -* {*T2*}Sugar{*ETW*}{*B*} -* {*T2*}Ghast Tear{*ETW*}{*B*} -* {*T2*}Blaze Powder{*ETW*}{*B*} -* {*T2*}Magma Cream{*ETW*}{*B*} -* {*T2*}Glistering Melon{*ETW*}{*B*} -* {*T2*}Redstone Dust{*ETW*}{*B*} -* {*T2*}Glowstone Dust{*ETW*}{*B*} -* {*T2*}Fermented Spider Eye{*ETW*}{*B*}{*B*} - -You'll need to experiment with combinations of ingredients in order to find out all the different potions you can make. - - - - - {*T3*}HOW TO PLAY : ENCHANTING{*ETW*}{*B*}{*B*} -The Experience Points collected when a mob dies, or when certain blocks are mined or smelted in a furnace, can be used to enchant some tools, weapons, armor and books.{*B*} -When a Sword, Bow, Axe, Pickaxe, Shovel, Armor or Book is placed in the slot below the book in the Enchantment Table, the three buttons to the right of the slot will display some enchantments and their Experience Levels costs.{*B*} -If you do not have enough Experience Levels to use some of these, the cost will appear in red, otherwise it will be shown in green.{*B*}{*B*} -The actual enchantment applied is randomly selected based on the cost displayed.{*B*}{*B*} -If the Enchantment Table is surrounded by Bookshelves (up to a maximum of 15 Bookshelves), with a one block gap between the Bookcase and the Enchantment Table, the potency of the enchantments will be increased, and arcane glyphs will be seen coming from the book on the Enchantment Table.{*B*}{*B*} -All the ingredients for an Enchantment Table can be found within the villages in a world, or by mining and cultivation of the world.{*B*}{*B*} -Enchanted Books are used at the Anvil to apply enchantments to items. This gives you more control over which enchantments you would like on your items.{*B*} - - - - - {*T3*}HOW TO PLAY : FARMING ANIMALS{*ETW*}{*B*}{*B*} -If you want to keep your animals in the one place, build a fenced area of less than 20x20 blocks and have your animals inside it. This ensures they will still be there when you come back to see them. - - - - - {*T3*}HOW TO PLAY : BREEDING ANIMALS{*ETW*}{*B*}{*B*} -The animals in Minecraft can breed, and will produce baby versions of themselves!{*B*} -To get the animals to breed, you will need to feed them with the right food to get them to go into 'Love Mode'.{*B*} -Feed Wheat to a cow, mooshroom or sheep, Carrots to a pig, Wheat Seeds or Nether Wart to a chicken, or any kind of meat to a wolf, and they'll start looking for another animal of the same species near them that is also in Love Mode.{*B*} -When two animals of the same species meet, and both are in Love Mode, they will kiss for a few seconds, and then a baby animal will appear. The baby animal will follow their parents for a while before growing into a full sized animal itself.{*B*} -After being in Love Mode, an animal will not be able to enter it again for about five minutes.{*B*} -There is a limit on the number of animals it is possible to have in a world, so you may find the animals don't breed when you have a lot of them. - - - - {*T3*}HOW TO PLAY : NETHER PORTAL{*ETW*}{*B*}{*B*} -A Nether Portal allows the player to travel between the Overworld and the Nether world. The Nether world can be used to fast-travel in the Overworld - traveling one block distance in the Nether is equivalent to traveling 3 blocks in the Overworld, so when you build a portal in the Nether world and exit through it, you will be 3 times further away from your entry point.{*B*}{*B*} -A minimum of 10 Obsidian blocks are required to build the portal, and the portal needs to be 5 blocks high by 4 blocks wide by 1 block deep. Once the portal frame is built, the space inside the frame needs to be set on fire to activate it. This can be done using the Flint and Steel item, or the Fire Charge item.{*B*}{*B*} -Examples of portal construction are shown in the picture to the right. - - - - - {*T3*}HOW TO PLAY : BANNING LEVELS{*ETW*}{*B*}{*B*} -If you find offensive content within a level you are playing, you can choose to add the level to your Banned Levels list. -If you would like to do this, bring up the Pause menu, then press{*CONTROLLER_VK_RB*} to select the Ban Level tooltip. -When you attempt to join this level in future, you will be notified that the level is in your Banned Levels list, and given the option to remove it from the list and continue into the level, or back out. - - - - {*T3*}HOW TO PLAY : HOST AND PLAYER OPTIONS{*ETW*}{*B*}{*B*} - -{*T1*}Game Options{*ETW*}{*B*} -When loading or creating a world, you can press the "More Options" button to enter a menu that allows more control over your game.{*B*}{*B*} - - {*T2*}Player vs Player{*ETW*}{*B*} - When enabled, players can inflict damage on other players. This option only affects Survival mode.{*B*}{*B*} - - {*T2*}Trust Players{*ETW*}{*B*} - When disabled, players joining the game are restricted in what they can do. They are not able to mine or use items, place blocks, use doors and switches, use containers, attack players or attack animals. You can change these options for a specific player using the in-game menu.{*B*}{*B*} - - {*T2*}Fire Spreads{*ETW*}{*B*} - When enabled, fire may spread to nearby flammable blocks. This option can also be changed from within the game.{*B*}{*B*} - - {*T2*}TNT Explodes{*ETW*}{*B*} - When enabled, TNT will explode when detonated. This option can also be changed from within the game.{*B*}{*B*} - - {*T2*}Host Privileges{*ETW*}{*B*} - When enabled, the host can toggle their ability to fly, disable exhaustion, and make themselves invisible from the in-game menu. {*DISABLES_ACHIEVEMENTS*}{*B*}{*B*} - - {*T2*}Daylight Cycle{*ETW*}{*B*} - When disabled, the time of day will not change.{*B*}{*B*} - - {*T2*}Keep Inventory{*ETW*}{*B*} - When enabled, players will keep their inventory when they die.{*B*}{*B*} - - {*T2*}Mob Spawning{*ETW*}{*B*} - When disabled, mobs will not spawn naturally.{*B*}{*B*} - - {*T2*}Mob Griefing{*ETW*}{*B*} - When disabled, prevents monsters and animals from changing blocks (for example, Creeper explosions won't destroy blocks and Sheep won't remove Grass) or picking up items.{*B*}{*B*} - - {*T2*}Mob Loot{*ETW*}{*B*} - When disabled, monsters and animals will not drop loot (for example, Creepers won't drop gunpowder).{*B*}{*B*} - - {*T2*}Tile Drops{*ETW*}{*B*} - When disabled, blocks will not drop items when destroyed (for example, Stone blocks won't drop Cobblestone).{*B*}{*B*} - - {*T2*}Natural Regeneration{*ETW*}{*B*} - When disabled, players will not regenerate health naturally.{*B*}{*B*} - -{*T1*}World Generation Options{*ETW*}{*B*} -When creating a new world there are some additional options.{*B*}{*B*} - - {*T2*}Generate Structures{*ETW*}{*B*} - When enabled, structures such as Villages and Strongholds will generate in the world.{*B*}{*B*} - - {*T2*}Superflat World{*ETW*}{*B*} - When enabled, a completely flat world will be generated in the Overworld and in the Nether.{*B*}{*B*} - - {*T2*}Bonus Chest{*ETW*}{*B*} - When enabled, a chest containing some useful items will be created near the player spawn point.{*B*}{*B*} - - {*T2*}Reset Nether{*ETW*}{*B*} - When enabled, the Nether will be re-generated. This is useful if you have an older save where Nether Fortresses were not present.{*B*}{*B*} - - {*T1*}In-Game Options{*ETW*}{*B*} - While in the game a number of options can be accessed by pressing {*BACK_BUTTON*} to bring up the in-game menu.{*B*}{*B*} - - {*T2*}Host Options{*ETW*}{*B*} - The host player, and any players set as moderators can access the "Host Option" menu. In this menu they can enable and disable fire spreading and TNT exploding.{*B*}{*B*} - -{*T1*}Player Options{*ETW*}{*B*} -To modify the privileges for a player, select their name and press{*CONTROLLER_VK_A*} to bring up the player privileges menu where you can use the following options.{*B*}{*B*} - - {*T2*}Can Build And Mine{*ETW*}{*B*} - This option is only available when "Trust Players" is turned off. When this option is enabled, the player is able to interact with the world as normal. When disabled the player will not be able to place or destroy blocks, or interact with many items and blocks.{*B*}{*B*} - - {*T2*}Can Use Doors and Switches{*ETW*}{*B*} - This option is only available when "Trust Players" is turned off. When this option is disabled, the player will not be able to use doors and switches.{*B*}{*B*} - - {*T2*}Can Open Containers{*ETW*}{*B*} - This option is only available when "Trust Players" is turned off. When this option is disabled, the player will not be able to open containers, such as chests.{*B*}{*B*} - - {*T2*}Can Attack Players{*ETW*}{*B*} - This option is only available when "Trust Players" is turned off. When this option is disabled the player will not be able to cause damage to other players.{*B*}{*B*} - - {*T2*}Can Attack Animals{*ETW*}{*B*} - This option is only available when "Trust Players" is turned off. When this option is disabled the player will not be able to cause damage to animals.{*B*}{*B*} - - {*T2*}Moderator{*ETW*}{*B*} - When this option is enabled, the player is able to change privileges for other players (except the host) if "Trust Players" is turned off, kick players and they can enable and disable fire spreading and TNT exploding.{*B*}{*B*} - - {*T2*}Kick Player{*ETW*}{*B*} - {*KICK_PLAYER_DESCRIPTION*}{*B*}{*B*} - -{*T1*}Host Player Options{*ETW*}{*B*} -If "Host Privileges" is enabled the host player can modify some privileges for themselves. To modify the privileges for a player, select their name and press{*CONTROLLER_VK_A*} to bring up the player privileges menu where you can use the following options.{*B*}{*B*} - - {*T2*}Can Fly{*ETW*}{*B*} - When this option is enabled, the player is able to fly. This option is only relevant to Survival mode, as flying is enabled for all players in Creative mode.{*B*}{*B*} - - {*T2*}Disable Exhaustion{*ETW*}{*B*} - This option only affects Survival mode. When enabled, physical activities (walking/sprinting/jumping etc.) do not decrease the food bar. However, if the player becomes injured, the food bar will slowly decrease while the player is healing.{*B*}{*B*} - - {*T2*}Invisible{*ETW*}{*B*} - When this option is enabled, the player is not visible to other players and is invulnerable.{*B*}{*B*} - - {*T2*}Can Teleport{*ETW*}{*B*} - This allows the player to move players or themselves to other players in the world. - - - - - Next Page - - - - Previous Page - - - - Basics - - - - HUD - - - - Inventory - - - - Chests - - - - Crafting - - - - Furnace - - - - Dispenser - - - - Farming Animals - - - - Breeding Animals - - - - Brewing - - - - Enchantment - - - - Nether Portal - - - - Multiplayer - - - - Sharing Screenshots - - - - Banning Levels - - - - Creative Mode - - - - Host and Player Options - - - - Trading - - - - Anvil - - - - The End - - - - {*T3*}HOW TO PLAY : THE END{*ETW*}{*B*}{*B*} -The End is another dimension in the game, which is reached through an active End Portal. The End Portal can be found in a Stronghold, which is deep underground in the Overworld.{*B*} -To activate the End Portal, you'll need to put an Eye of Ender into any End Portal Frame without one.{*B*} -Once the portal is active, jump in to it to go to The End.{*B*}{*B*} -In The End you will meet the Ender Dragon, a fierce and powerful enemy, along with many Enderman, so you will have to be well prepared for the battle before going there!{*B*}{*B*} -You'll find that there are Ender Crystals on top of eight Obsidian spikes that the Ender Dragon uses to heal itself, -so the first step in the battle is to destroy each of these.{*B*} -The first few can be reached with arrows, but the later ones are protected by an Iron Fence cage, and you will need to build up to them.{*B*}{*B*} -While you are doing this, the Ender Dragon will be attacking you by flying at you and spitting Ender acid balls!{*B*} -If you approach the Egg Podium in the centre of the spikes, the Ender Dragon will fly down and attack you and this is where you can really do some damage to it!{*B*} -Avoid the acid breath, and target the Ender Dragon's eyes for the best results. If possible, bring some friends in to The End to help you with the battle!{*B*}{*B*} -Once you are in The End, your friends will be able to see the location of the End Portal within the Stronghold on their maps, -so they can easily join you. - - - - - Sprint - - - - What's New - - - - {*T3*}Changes and Additions{*ETW*}{*B*}{*B*} -- Added new items - Hardened Clay, Stained Clay, Block of Coal, Hay Bale, Activator Rail, Block of Redstone, Daylight Sensor, Dropper, Hopper, Minecart with Hopper, Minecart with TNT, Redstone Comparator, Weighted Pressure Plate, Beacon, Trapped Chest, Firework Rocket, Firework Star, Nether Star, Lead, Horse Armor, Name Tag, Horse Spawn Egg{*B*} -- Added new Mobs - Wither, Wither Skeletons, Witches, Bats, Horses, Donkeys and Mules{*B*} -- Added new terrain generation features - Witch Huts.{*B*} -- Added Beacon interface.{*B*} -- Added Horse interface.{*B*} -- Added Hopper interface.{*B*} -- Added Fireworks - Fireworks interface is accessible from the Crafting Table when you have the ingredients to craft a Firework Star or Firework Rocket.{*B*} -- Added 'Adventure Mode' - You can only break blocks with the correct tools.{*B*} -- Added lots of new sounds.{*B*} -- Mobs, items and projectiles can now pass through portals.{*B*} -- Repeaters can now be locked by powering their sides with another Repeater.{*B*} -- Zombies and Skeletons can now spawn with different weapons and armor.{*B*} -- New death messages.{*B*} -- Name mobs with a Name Tag, and rename containers to change the title when the menu is open.{*B*} -- Bonemeal no longer instantly grows everything to full size, and instead randomly grows in stages.{*B*} -- A Redstone signal describing the contents of Chests, Brewing Stands, Dispensers and Jukeboxes can be detected by placing a Redstone Comparator directly against them.{*B*} -- Dispensers can face in any direction.{*B*} -- Eating a Golden Apple gives the player extra "absorption" health for a short period.{*B*} -- The longer you remain in an area the harder the monsters that spawn in that area will be.{*B*} - - - - - {*ETB*}Welcome back! You may not have noticed but your Minecraft has just been updated.{*B*}{*B*} -There are lots of new features for you and friends to play with so here’s just a few highlights. Have a read and then go and have fun!{*B*}{*B*} -{*T1*}New Items{*ETB*} - Hardened Clay, Stained Clay, Block of Coal, Hay Bale, Activator Rail, Block of Redstone, Daylight Sensor, Dropper, Hopper, Minecart with Hopper, Minecart with TNT, Redstone Comparator, Weighted Pressure Plate, Beacon, Trapped Chest, Firework Rocket, Firework Star, Nether Star, Lead, Horse Armor, Name Tag, Horse Spawn Egg{*B*}{*B*} -{*T1*}New Mobs{*ETB*} - Wither, Wither Skeletons, Witches, Bats, Horses, Donkeys and Mules{*B*}{*B*} -{*T1*}New Features{*ETB*} - Tame and ride a horse, craft fireworks and put on a show, name animals and monsters with a Name Tag, create more advanced Redstone circuits, and new Host Options to help control what guests to your world can do!{*B*}{*B*} -{*T1*}New Tutorial World{*ETB*} – Learn how to use the old and new features in the Tutorial World. See if you can find all the secret Music Discs hidden in the world!{*B*}{*B*} - - - - - Horses - - - - {*T3*}HOW TO PLAY : HORSES{*ETW*}{*B*}{*B*} -Horses and Donkeys are found mainly in open plains. Mules are the offspring of a Donkey and a Horse, but are infertile themselves.{*B*} -All adult Horses, Donkeys and Mules can be ridden. However only Horses can be armored, and only Mules and Donkeys may be equipped with saddlebags for transporting items.{*B*}{*B*} -Horses, Donkeys and Mules must be tamed before they can be used. A horse is tamed by attempting to ride it, and managing to stay on the horse while it attempts to throw the rider off.{*B*} -When Love Hearts appear around the horse, it is tame, and will no longer attempt to throw the player off. To steer a horse, the player must equip the horse with a Saddle.{*B*}{*B*} -Saddles can be bought from villagers or found inside Chests hidden in the world.{*B*} -Tame Donkeys and Mules can be given saddlebags by attaching a Chest. These saddlebags can then be accessed whilst riding or sneaking.{*B*}{*B*} -Horses and Donkeys (but not Mules) can be bred like other animals using Golden Apples or Golden Carrots.{*B*} -Foals will grow into adult horses over time, although feeding them Wheat or Hay will speed this up.{*B*} - - - - - Beacons - - - - {*T3*}HOW TO PLAY : BEACONS{*ETW*}{*B*}{*B*} -Active Beacons project a bright beam of light into the sky and grant powers to nearby players.{*B*} -They are crafted with Glass, Obsidian and Nether Stars, which can be obtained by defeating the Wither.{*B*}{*B*} -Beacons must be placed so that they are in sunlight during the day. Beacons must be placed on Pyramids of Iron, Gold, Emerald or Diamond.{*B*} -The material the Beacon is placed on has no effect on the power of the Beacon.{*B*}{*B*} -In the Beacon menu you can select one primary power for your Beacon. The more tiers your pyramid has the more powers you will have to choose from.{*B*} -A Beacon on a pyramid with at least four tiers also gives the option of either the Regeneration secondary power or a stronger primary power.{*B*}{*B*} -To set the powers of your Beacon you must sacrifice an Emerald, Diamond, Gold or Iron Ingot in the payment slot.{*B*} -Once set, the powers will emanate from the Beacon indefinitely.{*B*} - - - - - Fireworks - - - - {*T3*}HOW TO PLAY : FIREWORKS{*ETW*}{*B*}{*B*} -Fireworks are decorative items that can be launched by hand or from Dispensers. They are crafted using Paper, Gunpowder and optionally a number of Firework Stars.{*B*} -The colors, fade, shape, size, and effects (such as trails and twinkle) of Firework Stars can be customized by including additional ingredients when crafting.{*B*}{*B*} -To craft a Firework place Gunpowder and Paper in the 3x3 crafting grid that is shown above your inventory.{*B*} -You can optionally place multiple Firework Stars in the crafting grid to add them to the Firework.{*B*} -Filling more slots in the crafting grid with Gunpowder will increase the height at which all the Firework Stars will explode.{*B*}{*B*} -You can then take the crafted Firework out of the output slot.{*B*}{*B*} -Firework Stars can be crafted by placing Gunpowder and Dye into the crafting grid.{*B*} - - The Dye will set the color of the explosion of the Firework Star.{*B*} - - The shape of the Firework Star is set by adding either a Fire Charge, Gold Nugget, Feather or Mob Head.{*B*} - - A trail or a twinkle can be added using Diamonds or Glowstone Dust.{*B*}{*B*} -After a Firework Star has been crafted, you can set the fade color of the Firework Star by crafting it with Dye. - - - - - Hoppers - - - - {*T3*}HOW TO PLAY : HOPPERS{*ETW*}{*B*}{*B*} -Hoppers are used to insert or remove items from containers, and to automatically pick up items thrown into them.{*B*} -They can affect Brewing Stands, Chests, Dispensers, Droppers, Minecarts with Chests, Minecarts with Hoppers, as well as other Hoppers.{*B*}{*B*} -Hoppers will continuously attempt to suck items out of a suitable container placed above them. They will also attempt to insert stored items into an output container.{*B*} -If a Hopper is powered by Redstone it will become inactive and stop both sucking and inserting items.{*B*}{*B*} -A Hopper points in the direction it tries to output items. To make a Hopper point to a particular block, place the Hopper against that block whilst sneaking.{*B*} - - - - - Droppers - - - - {*T3*}HOW TO PLAY : DROPPERS{*ETW*}{*B*}{*B*} -When powered by Redstone, Droppers will drop a single random item contained within them onto the ground. Use {*CONTROLLER_ACTION_USE*} to open the Dropper and then you can load the Dropper with items from your inventory.{*B*} -If the Dropper is facing a Chest or another type of Container, the item will be placed into that instead. Long chains of Droppers can be constructed to transport items over a distance, but for this to work they will have to be alternately powered on and off. - - - - - Deals more damage than by hand. - - - - Used to dig dirt, grass, sand, gravel and snow faster than by hand. Shovels are required to dig snowballs. - - - - Required to mine stone-related blocks and ore. - - - - Used to chop wood-related blocks faster than by hand. - - - - Used to till dirt and grass blocks to prepare for crops. - - - - Wooden doors are activated by using, hitting them or with Redstone. - - - - Iron doors can only be opened by Redstone, buttons or switches. - - - - NOT USED - - - - NOT USED - - - - NOT USED - - - - NOT USED - - - - Gives the user 1 Armor when worn. - - - - Gives the user 3 Armor when worn. - - - - Gives the user 2 Armor when worn. - - - - Gives the user 1 Armor when worn. - - - - Gives the user 2 Armor when worn. - - - - Gives the user 5 Armor when worn. - - - - Gives the user 4 Armor when worn. - - - - Gives the user 1 Armor when worn. - - - - Gives the user 2 Armor when worn. - - - - Gives the user 6 Armor when worn. - - - - Gives the user 5 Armor when worn. - - - - Gives the user 2 Armor when worn. - - - - Gives the user 2 Armor when worn. - - - - Gives the user 5 Armor when worn. - - - - Gives the user 3 Armor when worn. - - - - Gives the user 1 Armor when worn. - - - - Gives the user 3 Armor when worn. - - - - Gives the user 8 Armor when worn. - - - - Gives the user 6 Armor when worn. - - - - Gives the user 3 Armor when worn. - - - - A shiny ingot which can be used to craft tools made from this material. Created by smelting ore in a furnace. - - - - Allows ingots, gems, or dyes to be crafted into placeable blocks. Can be used as an expensive building block or compact storage of the ore. - - - - Used to send an electrical charge when stepped on by a player, an animal, or a monster. Wooden Pressure Plates can also be activated by dropping something on them. - - - - Used for compact staircases. - - - - Used for making long staircases. Two slabs placed on top of each other will create a normal-sized double slab block. - - - - Used for making long staircases. Two slabs placed on top of each other will create a normal-sized double slab block. - - - - Used to create light. Torches also melt snow and ice. - - - - Used as a building material and can be crafted into many things. Can be crafted from any form of wood. - - - - Used as a building material. Is not influenced by gravity like normal Sand. - - - - Used as a building material. - - - - Used to craft torches, arrows, signs, ladders, fences and as handles for tools and weapons. - - - - Used to forward time from any time at night to morning if all the players in the world are in bed, and changes the spawn point of the player. -The colors of the bed are always the same, regardless of the colors of wool used. - - - - Allows you to craft a more varied selection of items than the normal crafting. - - - - Allows you to smelt ore, create charcoal and glass, and cook fish and porkchops. - - - - Stores blocks and items inside. Place two chests side by side to create a larger chest with double the capacity. - - - - Used as a barrier that cannot be jumped over. Counts as 1.5 blocks high for players, animals and monsters, but 1 block high for other blocks. - - - - Used to climb vertically. - - - - Activated by using, hitting them or with redstone. They function as normal doors, but are a one by one block and lay flat on the ground. - - - - Shows text entered by you or other players. - - - - Used to create brighter light than torches. Melts snow/ice and can be used underwater. - - - - Used to cause explosions. Activated after placing by igniting with Flint and Steel item, or with an electrical charge. - - - - Used to hold mushroom stew. You keep the bowl when the stew has been eaten. - - - - Used to hold and transport water, lava and milk. - - - - Used to hold and transport water. - - - - Used to hold and transport lava. - - - - Used to hold and transport milk. - - - - Used to create fire, ignite TNT, and open a portal once it has been built. - - - - Used to catch fish. - - - - Displays positions of the Sun and Moon. - - - - Points to your start point. - - - - Will create an image of an area explored while held. This can be used for path-finding. - - - - When used becomes a map of the part of the world that you are in, and gets filled in as you explore. - - - - Allows for ranged attacks by using arrows. - - - - Used as ammunition for bows. - - - - Dropped by the Wither, used in crafting Beacons. - - - - When activated, create colorful explosions. The color, effect, shape and fade are determined by the Firework Star used when the Firework is created. - - - - Used to determine the color, effect and shape of a Firework. - - - - Used in Redstone circuits to maintain, compare, or subtract signal strength, or to measure certain block states. - - - - Is a type of Minecart that acts as a moving TNT block. - - - - Is a block that outputs a Redstone signal based on sunlight (or lack of sunlight). - - - - Is a special type of Minecart that functions similarly to a Hopper. It will collect items lying on tracks and from containers above it. - - - - A special type of Armor that can be equipped to a horse. Provides 5 Armor. - - - - A special type of Armor that can be equipped to a horse. Provides 7 Armor. - - - - A special type of Armor that can be equipped to a horse. Provides 11 Armor. - - - - Used to leash mobs to the player or Fence posts. - - - - Used to name mobs in the world. - - - - Restores 2.5{*ICON_SHANK_01*}. - - - - Restores 1{*ICON_SHANK_01*}. Can be used 6 times. - - - - Restores 1{*ICON_SHANK_01*}. - - - - Restores 1{*ICON_SHANK_01*}. - - - - Restores 3{*ICON_SHANK_01*}. - - - - Restores 1{*ICON_SHANK_01*}, or can be cooked in a furnace. Eating this can cause you to be poisoned. - - - - Restores 3{*ICON_SHANK_01*}. Created by cooking raw chicken in a furnace. - - - - Restores 1.5{*ICON_SHANK_01*}, or can be cooked in a furnace. - - - - Restores 4{*ICON_SHANK_01*}. Created by cooking raw beef in a furnace. - - - - Restores 1.5{*ICON_SHANK_01*}, or can be cooked in a furnace. - - - - Restores 4{*ICON_SHANK_01*}. Created by cooking a raw porkchop in a furnace. - - - - Restores 1{*ICON_SHANK_01*}, or can be cooked in a furnace. Can be fed to an Ocelot to tame it. - - - - Restores 2.5{*ICON_SHANK_01*}. Created by cooking a raw fish in a furnace. - - - - Restores 2{*ICON_SHANK_01*}, and can be crafted into a golden apple. - - - - Restores 2{*ICON_SHANK_01*}, and regenerates health for 4 seconds. Crafted from an apple and gold nuggets. - - - - Restores 2{*ICON_SHANK_01*}. Eating this can cause you to be poisoned. - - - - Used in the cake recipe, and as an ingredient for brewing potions. - - - - Used to send an electrical charge by being turned on or off. Stays in the on or off state until pressed again. - - - - Constantly sends an electrical charge, or can be used as a receiver/transmitter when connected to the side of a block. -Can also be used for low-level lighting. - - - - Used in Redstone circuits as repeater, a delayer, and/or a diode. - - - - Used to send an electrical charge by being pressed. Stays activated for approximately a second before shutting off again. - - - - Used to hold and shoot out items in a random order when given a Redstone charge. - - - - Plays a note when triggered. Hit it to change the pitch of the note. Placing this on top of different blocks will change the type of instrument. - - - - Used to guide minecarts. - - - - When powered, accelerates minecarts that pass over it. When unpowered, causes minecarts to stop on it. - - - - Functions like a Pressure Plate (sends a Redstone signal when powered) but can only be activated by a Minecart. - - - - Used to transport you, an animal, or a monster along rails. - - - - Used to transport goods along rails. - - - - Will move along rails and can push other minecarts when coal is put in it. - - - - Used to travel in water more quickly than swimming. - - - - Collected from sheep, and can be colored with dyes. - - - - Used as a building material and can be colored with dyes. This recipe is not recommended because Wool can be easily obtained from Sheep. - - - - Used as a dye to create black wool. - - - - Used as a dye to create green wool. - - - - Used as a dye to create brown wool, as an ingredient in cookies, or to grow Cocoa Pods. - - - - Used as a dye to create silver wool. - - - - Used as a dye to create yellow wool. - - - - Used as a dye to create red wool. - - - - Used to instantly grow crops, trees, tall grass, huge mushrooms and flowers, and can be used in dye recipes. - - - - Used as a dye to create pink wool. - - - - Used as a dye to create orange wool. - - - - Used as a dye to create lime wool. - - - - Used as a dye to create gray wool. - - - - Used as a dye to create light gray wool. -(Note: light gray dye can also be made by combining gray dye with bone meal, letting you make four light gray dyes from every ink sac instead of three.) - - - - Used as a dye to create light blue wool. - - - - Used as a dye to create cyan wool. - - - - Used as a dye to create purple wool. - - - - Used as a dye to create magenta wool. - - - - Used as dye to create Blue Wool. - - - - Plays Music Discs. - - - - Use these to create very strong tools, weapons or armor. - - - - Used to create brighter light than torches. Melts snow/ice and can be used underwater. - - - - Used to create books and maps. - - - - Can be used to create bookshelves or enchanted to make Enchanted Books. - - - - Allows the creation of more powerful enchantments when placed around the Enchantment Table. - - - - Used as decoration. - - - - Can be mined with an iron pickaxe or better, then smelted in a furnace to produce gold ingots. - - - - Can be mined with a stone pickaxe or better, then smelted in a furnace to produce iron ingots. - - - - Can be mined with a pickaxe to collect coal. - - - - Can be mined with a stone pickaxe or better to collect lapis lazuli. - - - - Can be mined with an iron pickaxe or better to collect diamonds. - - - - Can be mined with an iron pickaxe or better to collect redstone dust. - - - - Can be mined with a pickaxe to collect cobblestone. - - - - Causes players and mobs to bounce when they jump on it. - - - - Collected using a shovel. Can be used for construction. - - - - Can be planted and it will eventually grow into a tree. - - - - This cannot be broken. - - - - Sets fire to anything that touches it. Can be collected in a bucket. - - - - Collected using a shovel. Can be smelted into glass using the furnace. Is affected by gravity if there is no other tile underneath it. - - - - Collected using a shovel. Sometimes produces flint when dug up. Is affected by gravity if there is no other tile underneath it. - - - - Chopped using an axe, and can be crafted into planks or used as a fuel. - - - - Created in a furnace by smelting sand. Can be used for construction, but will break if you try to mine it. - - - - Mined from stone using a pickaxe. Can be used to construct a furnace or stone tools. - - - - Baked from clay in a furnace. - - - - Can be baked into bricks in a furnace. - - - - When broken drops clay balls which can be baked into bricks in a furnace. - - - - A compact way to store snowballs. - - - - Can be dug with a shovel to create snowballs. - - - - Sometimes produces wheat seeds when broken. - - - - Can be crafted into a dye. - - - - Can be crafted with a bowl to make stew. - - - - Can only be mined with a diamond pickaxe. Is produced by the meeting of water and still lava, and is used to build a portal. - - - - Spawns monsters into the world. - - - - Is placed on the ground to carry an electrical charge. When brewed with a potion it will increase the duration of the effect. - - - - When fully grown, crops can be harvested to collect wheat. - - - - Ground that has been prepared ready to plant seeds. - - - - Can be cooked in a furnace to create a green dye. - - - - Can be crafted to create sugar. - - - - Can be worn as a helmet or crafted with a torch to create a Jack-O-Lantern. It is also the main ingredient in Pumpkin Pie. - - - - Burns forever if set alight. - - - - Slows the movement of anything walking over it. - - - - Standing in the portal allows you to pass between the Overworld and the Nether. - - - - Used as a fuel in a furnace, or crafted to make a torch. - - - - Collected by killing a spider, and can be crafted into a Bow or Fishing Rod, or placed on the ground to create Tripwire. - - - - Collected by killing a chicken, and can be crafted into an arrow. - - - - Collected by killing a Creeper, and can be crafted into TNT or used as an ingredient for brewing potions. - - - - Can be planted in farmland to grow crops. Make sure there's enough light for the seeds to grow! - - - - Harvested from crops, and can be used to craft food items. - - - - Collected by digging gravel, and can be used to craft a flint and steel. - - - - When used on a pig it allows you to ride the pig. The pig can then be steered using a Carrot on a Stick. - - - - Collected by digging snow, and can be thrown. - - - - Collected by killing a cow, and can be crafted into armor or used to make Books. - - - - Collected by killing a Slime, and used as an ingredient for brewing potions or crafted to make Sticky Pistons. - - - - Dropped randomly by chickens, and can be crafted into food items. - - - - Collected by mining Glowstone, and can be crafted to make Glowstone blocks again or brewed with a potion to increase the potency of the effect. - - - - Collected by killing a Skeleton. Can be crafted into bone meal. Can be fed to a wolf to tame it. - - - - Collected by getting a Skeleton to kill a Creeper. Can be played in a jukebox. - - - - An invisible, but solid block. - - - - Extinguishes fire and helps crops grow. Can be collected in a bucket. - - - - When broken sometimes drops a sapling which can then be replanted to grow into a tree. - - - - Found in dungeons, can be used for construction and decoration. - - - - Used to obtain wool from sheep and harvest leaf blocks. - - - - When powered (using a button, a lever, a pressure plate, a redstone torch, or redstone with any one of these), a piston extends if it can and pushes blocks. - - - - When powered (using a button, a lever, a pressure plate, a redstone torch, or redstone with any one of these), a piston extends if it can and pushes blocks. When it retracts it pulls back the block touching the extended part of the piston. - - - - Made from Stone blocks, and commonly found in Strongholds. - - - - Used as a barrier, similar to fences. - - - - Similar to a door, but used primarily with fences. - - - - Can be crafted from Melon Slices. - - - - Transparent blocks that can be used as an alternative to Glass Blocks. - - - - Can be planted to grow pumpkins. - - - - Can be planted to grow melons. - - - - Dropped by Enderman when they die. When thrown, the player will be teleported to the position the Ender Pearl lands at, and will lose some health. - - - - A block of dirt with grass growing on top. Collected using a shovel. Can be used for construction. - - - - Can be used for construction and decoration. - - - - Slows movement when walking through it. Can be destroyed using shears to collect string. - - - - Spawns a Silverfish when destroyed. May also spawn Silverfish if nearby to another Silverfish being attacked. - - - - Grows over time when placed. Can be collected using shears. Can be climbed like a ladder. - - - - Slippery when walked on. Turns into water if above another block when destroyed. Melts if close enough to a light source or when placed in The Nether. - - - - Can be used as decoration. - - - - Used in potion brewing, and for locating Strongholds. Dropped by Blazes who tend to be found near or in Nether Fortresses. - - - - Used in potion brewing. Dropped by Ghasts when they die. - - - - Dropped by Zombie Pigmen when they die. Zombie Pigmen can be found in the Nether. Used as an ingredient for brewing potions. - - - - Used in potion brewing. This can be found naturally growing in Nether Fortresses. It can also be planted on Soul Sand. - - - - When used, can have various effects, depending on what it is used on. - - - - Can be filled with water, and used as the starting ingredient for a potion in the Brewing Stand. - - - - This is a poisonous food and brewing item. Dropped when a Spider or Cave Spider is killed by a player. - - - - Used in potion brewing, mainly to create potions with a negative effect. - - - - Used in potion brewing, or crafted with other items to make Eye of Ender or Magma Cream. - - - - Used in potion brewing. - - - - Used for making Potions and Splash Potions. - - - - Filled with water by rain or with a bucket of water, and can then be used to fill Glass Bottles with water. - - - - When thrown, will show the direction to an End Portal. When twelve of these are placed in the End Portal Frames, the End Portal will be activated. - - - - Used in potion brewing. - - - - Similar to Grass Blocks, but very good for growing mushrooms on. - - - - Floats on water, and can be walked on. - - - - Used to build Nether Fortresses. Immune to Ghast's fireballs. - - - - Used in Nether Fortresses. - - - - Found in Nether Fortresses, and will drop Nether Wart when broken. - - - - This allows players to enchant Swords, Pickaxes, Axes, Shovels, Bows and Armor, using the player's Experience Points. - - - - This can be activated using twelve Eye of Ender, and will allow the player to travel to The End dimension. - - - - Used to form an End Portal. - - - - A block type found in The End. It has a very high blast resistance, so is useful for building with. - - - - This block is created by the defeat of the Dragon in The End. - - - - When thrown, it drops Experience Orbs which increase your experience points when collected. - - - - Useful for setting things on fire, or for indiscriminately starting fires when fired from a Dispenser. - - - - These are similar to a display case, and will display the item or block placed in it. - - - - When thrown can spawn a creature of the type indicated. - - - - Used for making long staircases. Two slabs placed on top of each other will create a normal-sized double slab block. - - - - Used for making long staircases. Two slabs placed on top of each other will create a normal-sized double slab block. - - - - Created by smelting Netherrack in a furnace. Can be crafted into Nether Brick blocks. - - - - When powered they emit light. - - - - Can be farmed to collect Cocoa Beans. - - - - Mob Heads can be placed as a decoration, or worn as a mask in the helmet slot. - - - - Used to execute commands. - - - - Projects a beam of light into the sky and can provide Status Effects to nearby players. - - - - Stores blocks and items inside. Place two chest side by side to create a larger chest with double capacity. The trapped chest also creates a Redstone charge when opened. - - - - Provides a Redstone charge. The charge will be stronger if more items are on the plate. - - - - Provides a Redstone charge. The charge will be stronger if more items are on the plate. Requires more weight than the light plate. - - - - Used as a redstone power source. Can be crafted back into Redstone. - - - - Used to catch items or to transfer items into and out of containers. - - - - A type of rail that can enable or disable Minecarts with Hoppers and trigger Minecarts with TNT. - - - - Used to hold and drop items, or push items into another container, when given a Redstone charge. - - - - Colorful blocks crafted by dyeing Hardened clay. - - - - Can be fed to Horses, Donkeys or Mules to heal up to 10 Hearts. Speeds up the growth of foals. - - - - Created by smelting Clay in a furnace. - - - - Crafted from glass and a dye. - - - - Crafted from Stained Glass - - - - A compact way of storing Coal. Can be used as fuel in a Furnace. - - - - Squid - - - - Drops ink sacs when killed. - - - - Cow - - - - Drops leather when killed. Can also be milked with a bucket. - - - - Sheep - - - - Drops wool when sheared (if it has not already been sheared). Can be dyed to make its wool a different color. - - - - Chicken - - - - Drops feathers when killed, and also randomly lays eggs. - - - - Pig - - - - Drops porkchops when killed. Can be ridden by using a saddle. - - - - Wolf - - - - Docile until attacked, when they will attack you back. Can be tamed using bones which causes the wolf to follow you around and attack anything that attacks you. - - - - Creeper - - - - Explodes if you get too close! - - - - Skeleton - - - - Fires arrows at you. Drops arrows when killed. - - - - Spider - - - - Attacks you when you are close to it. Can climb walls. Drops string when killed. - - - - Zombie - - - - Attacks you when you are close to it. - - - - Zombie Pigman - - - - Initially docile, but will attack in groups if you attack one. - - - - Ghast - - - - Fires flaming balls at you that explode on contact. - - - - Slime - - - - Split into smaller Slimes when damaged. - - - - Enderman - - - - Will attack you if you look at it. Can also move blocks around. - - - - Silverfish - - - - Attracts nearby hidden Silverfish when attacked. Hides in stone blocks. - - - - Cave Spider - - - - Has a venomous bite. - - - - Mooshroom - - - - Makes mushroom stew when used with a bowl. Drops mushrooms and becomes a normal cow when sheared. - - - - Snow Golem - - - - The Snow Golem can be created by players using snow blocks and a pumpkin. They will throw snowballs at their creators enemies. - - - - Ender Dragon - - - - This is a large black dragon found in The End. - - - - Blaze - - - - These are enemies found in the Nether, mostly inside Nether Fortresses. They will drop Blaze Rods when killed. - - - - Magma Cube - - - - These can be found in The Nether. Similar to Slimes, they will break up into smaller versions when killed. - - - - Villager - - - - Ocelot - - - - These can be found in Jungles. They can be tamed by feeding them Raw Fish. You will need to let the Ocelot approach you though, since any sudden movements will scare it away. - - - - Iron Golem - - - - Appear in Villages to protect them, and can be created using Iron Blocks and Pumpkins. - - - - Bat - - - - These flying creatures are found in caverns or other large enclosed spaces. - - - - Witch - - - - These enemies can be found in swamps and attack you by throwing Potions. They drop Potions when killed. - - - - Horse - - - - These animals can be tamed and can then be ridden. - - - - Donkey - - - - These animals can be tamed and can then be ridden. They can have a chest attached. - - - - Mule - - - - Born when a Horse and a Donkey breed. These animals can be tamed and can then be ridden and carry chests. - - - - Zombie Horse - - - - Skeleton Horse - - - - Wither - - - - These are crafted from Wither Skulls and Soul Sand. They fire exploding skulls at you. - - - - Explosives Animator - - - - Concept Artist - - - - Number Crunching and Statistics - - - - Bully Coordinator - - - - Original Design and Code by - - - - Project Manager/Producer - - - - Rest of Mojang Office - - - - Lead Game Programmer Minecraft PC - - - - Ninja Coder - - - - CEO - - - - White Collar Worker - - - - Customer Support - - - - Office DJ - - - - Designer/Programmer Minecraft - Pocket Edition - - - - Developer - - - - Chief Architect - - - - Art Developer - - - - Game Crafter - - - - Director of Fun - - - - Music and Sounds - - - - Programming - - - - Art - - - - QA - - - - Executive Producer - - - - Lead Producer - - - - Producer - - - - Test Lead - - - - Lead Tester - - - - Design Team - - - - Development Team - - - - Release Management - - - - Director, XBLA Publishing - - - - Business Development - - - - Portfolio Director - - - - Product Manager - - - - Marketing - - - - Community Manager - - - - Europe Localization Team - - - - Redmond Localization Team - - - - Asia Localization Team - - - - User Research Team - - - - MGS Central Teams - - - - Milestone Acceptance Tester - - - - Special Thanks - - - - Test Manager - - - - Senior Test Lead - - - - SDET - - - - Project STE - - - - Additional STE - - - - Test Associates - - - - Jon KÃ¥gström - - - - Tobias Möllstam - - - - Risë Lugo - - - - Wooden Sword - - - - Stone Sword - - - - Iron Sword - - - - Diamond Sword - - - - Golden Sword - - - - Wooden Shovel - - - - Stone Shovel - - - - Iron Shovel - - - - Diamond Shovel - - - - Golden Shovel - - - - Wooden Pickaxe - - - - Stone Pickaxe - - - - Iron Pickaxe - - - - Diamond Pickaxe - - - - Golden Pickaxe - - - - Wooden Axe - - - - Stone Axe - - - - Iron Axe - - - - Diamond Axe - - - - Golden Axe - - - - Wooden Hoe - - - - Stone Hoe - - - - Iron Hoe - - - - Diamond Hoe - - - - Golden Hoe - - - - Oak Door - - - - Iron Door - - - - Chain Helmet - - - - Chain Chestplate - - - - Chain Leggings - - - - Chain Boots - - - - Leather Cap - - - - Iron Helmet - - - - Diamond Helmet - - - - Golden Helmet - - - - Leather Tunic - - - - Iron Chestplate - - - - Diamond Chestplate - - - - Golden Chestplate - - - - Leather Pants - - - - Iron Leggings - - - - Diamond Leggings - - - - Golden Leggings - - - - Leather Boots - - - - Iron Boots - - - - Diamond Boots - - - - Golden Boots - - - - Iron Ingot - - - - Gold Ingot - - - - Bucket - - - - Water Bucket - - - - Lava Bucket - - - - Flint and Steel - - - - Apple - - - - Bow - - - - Arrow - - - - Coal - - - - Charcoal - - - - Diamond - - - - Stick - - - - Bowl - - - - Mushroom Stew - - - - String - - - - Feather - - - - Gunpowder - - - - Seeds - - - - Wheat - - - - Bread - - - - Flint - - - - Raw Porkchop - - - - Cooked Porkchop - - - - Painting - - - - Golden Apple - - - - Sign - - - - Minecart - - - - Saddle - - - - Redstone - - - - Snowball - - - - Boat - - - - Leather - - - - Milk Bucket - - - - Brick - - - - Clay - - - - Sugar Canes - - - - Paper - - - - Book - - - - Slimeball - - - - Minecart with Chest - - - - Minecart with Furnace - - - - Egg - - - - Compass - - - - Fishing Rod - - - - Clock - - - - Glowstone Dust - - - - Raw Fish - - - - Cooked Fish - - - - Dye Powder - - - - Ink Sac - - - - Rose Red - - - - Cactus Green - - - - Cocoa Beans - - - - Lapis Lazuli - - - - Purple Dye - - - - Cyan Dye - - - - Light Gray Dye - - - - Gray Dye - - - - Pink Dye - - - - Lime Dye - - - - Dandelion Yellow - - - - Light Blue Dye - - - - Magenta Dye - - - - Orange Dye - - - - Bone Meal - - - - Bone - - - - Sugar - - - - Cake - - - - Bed - - - - Redstone Repeater - - - - Cookie - - - - Map - - - - Empty Map - - - - Music Disc - "13" - - - - Music Disc - "cat" - - - - Music Disc - "blocks" - - - - Music Disc - "chirp" - - - - Music Disc - "far" - - - - Music Disc - "mall" - - - - Music Disc - "mellohi" - - - - Music Disc - "stal" - - - - Music Disc - "strad" - - - - Music Disc - "ward" - - - - Music Disc - "11" - - - - Music Disc - "where are we now" - - - - Shears - - - - Pumpkin Seeds - - - - Melon Seeds - - - - Raw Chicken - - - - Cooked Chicken - - - - Raw Beef - - - - Steak - - - - Rotten Flesh - - - - Ender Pearl - - - - Melon Slice - - - - Blaze Rod - - - - Ghast Tear - - - - Gold Nugget - - - - Nether Wart - - - - {*splash*}{*prefix*}Potion {*postfix*} - - - - Glass Bottle - - - - Water Bottle - - - - Spider Eye - - - - Fermented Spider Eye - - - - Blaze Powder - - - - Magma Cream - - - - Brewing Stand - - - - Cauldron - - - - Eye of Ender - - - - Glistering Melon - - - - Bottle o' Enchanting - - - - Fire Charge - - - - Fire Charge (Charcoal) - - - - Fire Charge (Coal) - - - - Item Frame - - - - Spawn {*CREATURE*} - - - - Nether Brick - - - - Skull - - - - Skeleton Skull - - - - Wither Skeleton Skull - - - - Zombie Head - - - - Head - - - - %s's Head - - - - Creeper Head - - - - Nether Star - - - - Firework Rocket - - - - Firework Star - - - - Redstone Comparator - - - - Minecart with TNT - - - - Minecart with Hopper - - - - Iron Horse Armor - - - - Gold Horse Armor - - - - Diamond Horse Armor - - - - Lead - - - - Name Tag - - - - Stone - - - - Slime Block - - - - Grass Block - - - - Dirt - - - - Cobblestone - - - - Oak Planks - - - - Spruce Planks - - - - Birch Planks - - - - Jungle Planks - - - - Planks (any type) - - - - Sapling - - - - Oak Sapling - - - - Spruce Sapling - - - - Birch Sapling - - - - Jungle Tree Sapling - - - - Bedrock - - - - Barrier - - - - Water - - - - Lava - - - - Sand - - - - Sandstone - - - - Gravel - - - - Gold Ore - - - - Iron Ore - - - - Coal Ore - - - - Wood - - - - Oak Wood - - - - Spruce Wood - - - - Birch Wood - - - - Jungle Wood - - - - Oak - - - - Spruce - - - - Birch - - - - Leaves - - - - Oak Leaves - - - - Spruce Leaves - - - - Birch Leaves - - - - Jungle Leaves - - - - Sponge - - - - Glass - - - - Wool - - - - Black Wool - - - - Red Wool - - - - Green Wool - - - - Brown Wool - - - - Blue Wool - - - - Purple Wool - - - - Cyan Wool - - - - Light Gray Wool - - - - Gray Wool - - - - Pink Wool - - - - Lime Wool - - - - Yellow Wool - - - - Light Blue Wool - - - - Magenta Wool - - - - Orange Wool - - - - White Wool - - - - Dandelion - - - - Poppy - - - - Mushroom - - - - Block of Gold - - - - A compact way of storing Gold. - - - - A compact way of storing Iron. - - - - Block of Iron - - - - Stone Slab - - - - Stone Slab - - - - Sandstone Slab - - - - Oak Wood Slab - - - - Cobblestone Slab - - - - Bricks Slab - - - - Stone Bricks Slab - - - - Oak Wood Slab - - - - Spruce Wood Slab - - - - Birch Wood Slab - - - - Jungle Wood Slab - - - - Nether Brick Slab - - - - Bricks - - - - TNT - - - - Bookshelf - - - - Moss Stone - - - - Obsidian - - - - Torch - - - - Torch (Coal) - - - - Torch (Charcoal) - - - - Fire - - - - Monster Spawner - - - - Oak Wood Stairs - - - - Chest - - - - Redstone Dust - - - - Diamond Ore - - - - Block of Diamond - - - - A compact way of storing Diamonds. - - - - Crafting Table - - - - Crops - - - - Farmland - - - - Furnace - - - - Sign - - - - Oak Door - - - - Ladder - - - - Rail - - - - Powered Rail - - - - Detector Rail - - - - Stone Stairs - - - - Lever - - - - Pressure Plate - - - - Iron Door - - - - Redstone Ore - - - - Redstone Torch - - - - Button - - - - Snow - - - - Ice - - - - Cactus - - - - Clay - - - - Sugar Cane - - - - Jukebox - - - - Oak Fence - - - - Pumpkin - - - - Jack-O-Lantern - - - - Netherrack - - - - Soul Sand - - - - Glowstone - - - - Portal - - - - Lapis Lazuli Ore - - - - Lapis Lazuli Block - - - - A compact way of storing Lapis Lazuli. - - - - Dispenser - - - - Note Block - - - - Cake - - - - Bed - - - - Web - - - - Tall Grass - - - - Dead Bush - - - - Diode - - - - Locked Chest - - - - Trapdoor - - - - Wool (any color) - - - - Piston - - - - Sticky Piston - - - - Silverfish Block - - - - Stone Bricks - - - - Mossy Stone Bricks - - - - Cracked Stone Bricks - - - - Chiseled Stone Bricks - - - - Mushroom - - - - Mushroom - - - - Iron Bars - - - - Glass Pane - - - - Melon - - - - Pumpkin Stem - - - - Melon Stem - - - - Vines - - - - Oak Fence Gate - - - - Brick Stairs - - - - Stone Brick Stairs - - - - Silverfish Stone - - - - Silverfish Cobblestone - - - - Silverfish Stone Brick - - - - Mycelium - - - - Lily Pad - - - - Nether Brick - - - - Nether Brick Fence - - - - Nether Brick Stairs - - - - Nether Wart - - - - Enchantment Table - - - - Brewing Stand - - - - Cauldron - - - - End Portal - - - - End Portal Frame - - - - End Stone - - - - Dragon Egg - - - - Shrub - - - - Fern - - - - Sandstone Stairs - - - - Spruce Wood Stairs - - - - Birch Wood Stairs - - - - Jungle Wood Stairs - - - - Redstone Lamp - - - - Cocoa - - - - Skull - - - - Command Block - - - - Beacon - - - - Trapped Chest - - - - Weighted Pressure Plate (Light) - - - - Weighted Pressure Plate (Heavy) - - - - Redstone Comparator - - - - Daylight Sensor - - - - Block of Redstone - - - - Hopper - - - - Activator Rail - - - - Dropper - - - - Stained Clay - - - - Hay Bale - - - - Hardened Clay - - - - Block of Coal - - - - Black Stained Clay - - - - Red Stained Clay - - - - Green Stained Clay - - - - Brown Stained Clay - - - - Blue Stained Clay - - - - Purple Stained Clay - - - - Cyan Stained Clay - - - - Light Gray Stained Clay - - - - Gray Stained Clay - - - - Pink Stained Clay - - - - Lime Stained Clay - - - - Yellow Stained Clay - - - - Light Blue Stained Clay - - - - Magenta Stained Clay - - - - Orange Stained Clay - - - - White Stained Clay - - - - Stained Glass - - - - Black Stained Glass - - - - Red Stained Glass - - - - Green Stained Glass - - - - Brown Stained Glass - - - - Blue Stained Glass - - - - Purple Stained Glass - - - - Cyan Stained Glass - - - - Light Gray Stained Glass - - - - Gray Stained Glass - - - - Pink Stained Glass - - - - Lime Stained Glass - - - - Yellow Stained Glass - - - - Light Blue Stained Glass - - - - Magenta Stained Glass - - - - Orange Stained Glass - - - - White Stained Glass - - - - Stained Glass Pane - - - - Black Stained Glass Pane - - - - Red Stained Glass Pane - - - - Green Stained Glass Pane - - - - Brown Stained Glass Pane - - - - Blue Stained Glass Pane - - - - Purple Stained Glass Pane - - - - Cyan Stained Glass Pane - - - - Light Gray Stained Glass Pane - - - - Gray Stained Glass Pane - - - - Pink Stained Glass Pane - - - - Lime Stained Glass Pane - - - - Yellow Stained Glass Pane - - - - Light Blue Stained Glass Pane - - - - Magenta Stained Glass Pane - - - - Orange Stained Glass Pane - - - - White Stained Glass Pane - - - - Small Ball - - - - Large Ball - - - - Star-shaped - - - - Creeper-shaped - - - - Burst - - - - Unknown Shape - - - - Black - - - - Red - - - - Green - - - - Brown - - - - Blue - - - - Purple - - - - Cyan - - - - Light Gray - - - - Gray - - - - Pink - - - - Lime - - - - Yellow - - - - Light Blue - - - - Magenta - - - - Orange - - - - White - - - - Custom - - - - Fade to - - - - Twinkle - - - - Trail - - - - Flight Duration: - - - - Current Controls - - - - Layout - - - - Move/Sprint - - - - Look - - - - Pause - - - - Jump - - - - Jump/Fly Up - - - - Inventory - - - - Cycle Held Item - - - - Action - - - - Use - - - - Crafting - - - - Drop - - - - Sneak - - - - Sneak/Fly Down - - - - Change Camera Mode - - - - Players/Invite - - - - Movement (When Flying) - - - - Layout 1 - - - - Layout 2 - - - - Layout 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {*B*}Press{*CONTROLLER_VK_A*} to continue. - - - - {*B*}Press{*CONTROLLER_VK_A*} to start the tutorial.{*B*} -Press{*CONTROLLER_VK_B*} if you think you are ready to play on your own. - - - - Minecraft is a game about placing blocks to build anything you can imagine. -At night monsters come out, make sure to build a shelter before that happens. - - - - Use{*CONTROLLER_ACTION_LOOK*} to look up, down and around. - - - - Use{*CONTROLLER_ACTION_MOVE*} to move around. - - - - To sprint, push{*CONTROLLER_ACTION_MOVE*} forward twice quickly. While you hold{*CONTROLLER_ACTION_MOVE*} forward, the character will continue to sprint unless they run out of sprint time or food. - - - - Press{*CONTROLLER_ACTION_JUMP*} to jump. - - - - Hold{*CONTROLLER_ACTION_ACTION*} to mine and chop using your hand or whatever you are holding. You may need to craft a tool to mine some blocks... - - - - Hold{*CONTROLLER_ACTION_ACTION*} to chop down 4 blocks of wood (tree trunks).{*B*}When a block breaks you can pick it up by standing near to the floating item that appears, causing it to appear in your inventory. - - - - Press{*CONTROLLER_ACTION_CRAFTING*} to open the crafting interface. - - - - As you collect and craft more items, your inventory will fill up.{*B*} -Press{*CONTROLLER_ACTION_INVENTORY*} to open the inventory. - - - - As you move around, mine and attack, you will deplete your food bar{*ICON_SHANK_01*}. Sprinting and sprint jumping use a lot more food than walking and jumping normally. - - - - If you lose some health, but have a food bar with 9 or more{*ICON_SHANK_01*} in it, your health will automatically replenish. Eating food will replenish your food bar. - - - - With a food item in your hand, hold{*CONTROLLER_ACTION_USE*} to eat it and replenish your food bar. You cannot eat if your food bar is full. - - - - Your food bar is low, and you have lost some health. Eat the steak in your inventory to replenish your food bar and start healing.{*ICON*}364{*/ICON*} - - - - The wood that you have collected can be crafted into planks. Open the crafting interface to craft them.{*PlanksIcon*} - - - - A lot of crafting can involve multiple steps. Now that you have some planks there are more items that you can craft. Create a crafting table.{*CraftingTableIcon*} - - - - To make collecting blocks faster you can build tools designed for the job. Some tools have a handle made of sticks. Craft some sticks now.{*SticksIcon*} - - - - Use{*CONTROLLER_ACTION_LEFT_SCROLL*} and{*CONTROLLER_ACTION_RIGHT_SCROLL*} to change the current held item. - - - - Use{*CONTROLLER_ACTION_USE*} to use items, interact with objects and place some items. Items that have been placed can be picked up again by mining them with the right tool. - - - - With the crafting table selected, point the crosshair where you want it and use{*CONTROLLER_ACTION_USE*} to place a crafting table. - - - - Point the crosshair at the crafting table and press{*CONTROLLER_ACTION_USE*} to open it. - - - - A shovel helps dig soft blocks, like dirt and snow, faster. As you collect more materials you can craft tools that work faster and last longer. Create a wooden shovel.{*WoodenShovelIcon*} - - - - An axe helps chop wood and wooden tiles, faster. As you collect more materials you can craft tools that work faster and last longer. Create a wooden axe.{*WoodenHatchetIcon*} - - - - A pickaxe helps dig hard blocks, like stone and ore, faster. As you collect more materials you can craft tools that work faster and last longer, and allow you to mine harder materials. Create a wooden pickaxe.{*WoodenPickaxeIcon*} - - - - Open the container - - - - Night time can approach quickly, and it is dangerous to be outside unprepared. You can craft armor and weapons, but it is sensible to have a safe shelter. - - - - Nearby there is an abandoned Miner's shelter that you can complete to be safe overnight. - - - - You will need to collect the resources to complete the shelter. Walls and roof can be made of any tile type, but you will want to create a door, some windows and lighting. - - - - Use your pickaxe to mine some stone blocks. Stone blocks will produce cobblestone when mined. If you collect 8 cobblestone blocks you can build a furnace. You may need to dig through some dirt to reach the stone, so use your shovel for this.{*StoneIcon*} - - - - You have collected enough cobblestone to build a furnace. Use your crafting table to create one. - - - - Use{*CONTROLLER_ACTION_USE*} to place the furnace in the world, and then open it. - - - - Use the furnace to create some charcoal. If you are waiting for it to finish how about using the time to collect more materials to finish the shelter? - - - - Use the furnace to create some glass. If you are waiting for it to finish how about using the time to collect more materials to finish the shelter? - - - - A good shelter will have a door so that you can easily go in and out without having to mine and replace the walls. Craft a wooden door now.{*WoodenDoorIcon*} - - - - Use{*CONTROLLER_ACTION_USE*} to place the door. You can use{*CONTROLLER_ACTION_USE*} to open and close a wooden door in the world. - - - - It can get very dark at night, so you will want some lighting inside your shelter so that you can see. Craft a torch now from sticks and charcoal using the crafting interface.{*TorchIcon*} - - - - You have completed the first part of the tutorial. - - - - {*B*} -Press{*CONTROLLER_VK_A*} to continue with the tutorial.{*B*} -Press{*CONTROLLER_VK_B*} if you think you are ready to play on your own. - - - - This is your inventory. It shows items available for use in your hand, and all the other items that you are carrying. Your armor is also shown here. - - - - {*B*} -Press{*CONTROLLER_VK_A*} to continue.{*B*} -Press{*CONTROLLER_VK_B*} if you already know how to use the inventory. - - - - Use{*CONTROLLER_MENU_NAVIGATE*} to move the pointer. Use{*CONTROLLER_VK_A*} to pick an item under the pointer. -If there is more than one item here this will pick them all up, or you can use{*CONTROLLER_VK_X*} to pick up just half of them. - - - - Move this item with the pointer over another space in the inventory and place it down using{*CONTROLLER_VK_A*}. -With multiple items on the pointer, use{*CONTROLLER_VK_A*} to place them all, or{*CONTROLLER_VK_X*} to place just one. - - - - If you move the pointer outside the edge of the interface with an item on the pointer, you can drop the item. - - - - If you want more information about an item, move the pointer over the item and press{*CONTROLLER_ACTION_MENU_PAGEDOWN*} . - - - - Press{*CONTROLLER_VK_B*} now to exit the inventory. - - - - This is the creative mode inventory. It shows items available for use in your hand, and all the other items that you can choose from. - - - - {*B*} -Press{*CONTROLLER_VK_A*} to continue.{*B*} -Press{*CONTROLLER_VK_B*} if you already know how to use the creative mode inventory. - - - - Use{*CONTROLLER_MENU_NAVIGATE*} to move the pointer. -When on the item list, use{*CONTROLLER_VK_A*} to pick an item under the pointer, and use{*CONTROLLER_VK_Y*} to pick up a full stack of that item. - - - - The pointer will automatically move over a space in the use row. You can place it down using{*CONTROLLER_VK_A*}. Once you have placed the item, the pointer will return to the item list where you can select another item. - - - - If you move the pointer outside the edge of the interface with an item on the pointer, you can drop the item into the world. To clear all items in the quick select bar, press{*CONTROLLER_VK_X*}. - - - - Scroll through the Group Type tabs at the top using{*CONTROLLER_VK_LB*} and{*CONTROLLER_VK_RB*} to select the group type of the item you wish to pickup. - - - - If you want more information about an item, move the pointer over the item and press{*CONTROLLER_ACTION_MENU_PAGEDOWN*} . - - - - Press{*CONTROLLER_VK_B*} now to exit the creative mode inventory. - - - - This is the crafting interface. This interface allows you to combine the items you've collected to make new items. - - - - {*B*}Press{*CONTROLLER_VK_A*} to continue.{*B*} -Press{*CONTROLLER_VK_B*} if you already know how to craft. - - - - {*B*} -Press{*CONTROLLER_VK_X*} to show the item description. - - - - {*B*} -Press{*CONTROLLER_VK_X*} to show the ingredients required to make the current item. - - - - {*B*} -Press{*CONTROLLER_VK_X*} to show the inventory again. - - - - Scroll through the Group Type tabs at the top using{*CONTROLLER_VK_LB*} and{*CONTROLLER_VK_RB*} to select the group type of the item you wish to craft, then use{*CONTROLLER_MENU_NAVIGATE*} to select the item to craft. - - - - The crafting area shows the items you require in order to craft the new item. Press{*CONTROLLER_VK_A*} to craft the item and place it in your inventory. - - - - You can craft a larger selection of items using a crafting table. Crafting on a table works in the same way as basic crafting, but you have a larger crafting area allowing more combinations of ingredients. - - - - The bottom right part of the crafting interface shows your inventory. This area can also show a description of the currently selected item, and the ingredients required to craft it. - - - - The description of the currently selected item is now displayed. The description can give you an idea of what the item can be used for. - - - - The list of ingredients required to craft the selected item are now displayed. - - - - The wood that you have collected can be crafted into planks. Select the planks icon and press{*CONTROLLER_VK_A*} to create them.{*PlanksIcon*} - - - - Now you have built a crafting table you should place it in the world to enable you to build a larger selection of items.{*B*} -Press{*CONTROLLER_VK_B*} now to exit the crafting interface. - - - - Press{*CONTROLLER_VK_LB*} and{*CONTROLLER_VK_RB*} to change to the group type of the items you wish to craft. Select the tools group.{*ToolsIcon*} - - - - Press{*CONTROLLER_VK_LB*} and{*CONTROLLER_VK_RB*} to change to the group type of the items you wish to craft. Select the structures group.{*StructuresIcon*} - - - - Use{*CONTROLLER_MENU_NAVIGATE*} to change to the item you wish to craft. Some items have multiple versions depending on the materials used. Select the wooden shovel.{*WoodenShovelIcon*} - - - - A lot of crafting can involve multiple steps. Now that you have some planks there are more items that you can craft. Use{*CONTROLLER_MENU_NAVIGATE*} to change to the item you wish to craft. Select the crafting table.{*CraftingTableIcon*} - - - - With the tools you have built you are off to a great start, and are able to collect a variety of different materials more efficiently.{*B*} -Press{*CONTROLLER_VK_B*} now to exit the crafting interface. - - - - Some items can not be created using the crafting table, but require a furnace. Craft a furnace now.{*FurnaceIcon*} - - - - Place the furnace you have crafted in the world. You will want to put this inside your shelter.{*B*} -Press{*CONTROLLER_VK_B*} now to exit the crafting interface. - - - - This is the furnace interface. A furnace allows you to change items by firing them. For example, you can turn iron ore into iron ingots in the furnace. - - - - {*B*} -Press{*CONTROLLER_VK_A*} to continue.{*B*} -Press{*CONTROLLER_VK_B*} if you already know how to use a furnace. - - - - You need to put some fuel into the bottom slot of the furnace, and the item to be changed in the top slot. The furnace will then fire up and start working, putting the result in the right-hand slot. - - - - Many wooden items can be used as fuels, but not everything burns for the same time. You may also discover other items in the world that can be used as a fuel. - - - - When your items have been fired, you can move them from the output area into your inventory. You should experiment with different ingredients to see what you can make. - - - - If you use wood as the ingredient then you can make charcoal. Put some fuel in the furnace and wood in the ingredient slot. It can take some time for the furnace to create the charcoal, so feel free to do something else and come back to check the progress. - - - - Charcoal can be used as a fuel, as well as being crafted into a torch with a stick. - - - - Placing sand in the ingredient slot allows you to make glass. Create some glass blocks to use as windows in your shelter. - - - - This is the brewing interface. You can use this to create potions that have a variety of different effects. - - - - {*B*} -Press{*CONTROLLER_VK_A*} to continue.{*B*} -Press{*CONTROLLER_VK_B*} if you already know how to use the brewing stand. - - - - You brew potions by placing an ingredient in the top slot, and a potion or water bottle in the bottom slots (up to 3 can be brewed at one time). Once a valid combination is entered the brewing process will start and create the potion after a short time. - - - - All potions start with a Water Bottle. Most potions are created by first using a Nether Wart to make an Awkward Potion, and will require at least one more ingredient to make the final potion. - - - - Once you have a potion you can modify its effects. Adding Redstone Dust increases the duration of its effect and adding Glowstone Dust can make its effect more powerful. - - - - Adding Fermented Spider Eye corrupts the potion and can turn it into a potion with the opposite effect, and adding Gunpowder turns the potion into a Splash Potion which can be thrown to apply its affect to a nearby area. - - - - Create a Potion of Fire Resistance by first adding Nether Wart to a Water Bottle, and then adding Magma Cream. - - - - Press{*CONTROLLER_VK_B*} now to exit the brewing interface. - - - - In this area there is a Brewing Stand, a Cauldron and a chest full of items for brewing. - - - - {*B*} -Press{*CONTROLLER_VK_A*} to learn more about brewing and potions.{*B*} -Press{*CONTROLLER_VK_B*} if you already know about brewing and potions. - - - - The first step in brewing a potion is to create a Water Bottle. Take a Glass Bottle from the chest. - - - - You can fill a glass bottle from a Cauldron that has water in it, or from a block of water. Fill your glass bottle now by pointing at a water source and pressing{*CONTROLLER_ACTION_USE*}. - - - - If a cauldron becomes empty, you can refill it with a Water Bucket. - - - - Use the Brewing Stand to create a Potion of Fire Resistance. You will need a Water Bottle, Nether Wart and Magma Cream. - - - - With a potion in your hand, hold{*CONTROLLER_ACTION_USE*} to use it. For a normal potion you will drink it and apply the effect to yourself, and for a Splash potion you will throw it and apply the effect to creatures near where it hits. -Splash potions can be created by adding gunpowder to normal potions. - - - - Use your Potion of Fire Resistance on yourself. - - - - Now that you are resistant to fire and lava, you should see if there are places you can get to that you couldn't before. - - - - This is the enchanting interface which you can use to add enchantments to weapons, armor and some tools. - - - - {*B*} -Press{*CONTROLLER_VK_A*} to learn more about the enchanting interface.{*B*} -Press{*CONTROLLER_VK_B*} if you already know about the enchanting interface. - - - - To enchant an item, first place it in the enchanting slot. Weapons, armor and some tools can be enchanted to add special effects such as improved damage resistance or increasing the number of items produced when mining a block. - - - - When an item is placed in the enchanting slot, the buttons on the right will change to show a selection of random enchantments. - - - - The number on the button represents the cost in experience levels to apply that enchantment to the item. If you do not have a high enough level the button will be disabled. - - - - Select an enchantment and press{*CONTROLLER_VK_A*} to enchant the item. This will decrease your experience level by the cost of the enchantment. - - - - Although the enchantments are all random, some of the better enchantments are only available when you have a high experience level and have lots of bookcases around the Enchantment Table to increase its power. - - - - In this area there is an Enchantment Table and some other items to help you learn about enchanting. - - - - {*B*} -Press{*CONTROLLER_VK_A*} to learn more about enchanting.{*B*} -Press{*CONTROLLER_VK_B*} if you already know about enchanting. - - - - Using an Enchantment Table allows you to add special effects such as increasing the number of items produced when mining a block, or improved damage resistance for weapons, armor and some tools. - - - - Placing bookcases around the Enchantment Table increases its power and allows access to higher level enchantments. - - - - Enchanting items costs Experience Levels, which can be built up by collecting Experience Orbs which are produced by killing monsters and animals, mining ores, breeding animals, fishing and smelting/cooking some things in a furnace. - - - - You can also build experience levels using a Bottle O' Enchanting, which, when thrown, creates Experience Orbs around where it lands. These orbs can then be collected. - - - - In the chests in this area you can find some enchanted items, Bottles O' Enchanting, and some items that have yet to be enchanted for you to experiment with at the Enchantment Table. - - - - You are now riding in a minecart. To exit the minecart, point the cursor at it and press{*CONTROLLER_ACTION_USE*} .{*MinecartIcon*} - - - - {*B*} -Press{*CONTROLLER_VK_A*} to learn more about minecarts.{*B*} -Press{*CONTROLLER_VK_B*} if you already know about minecarts. - - - - A minecart runs on rails. You can also craft a powered minecart with a furnace and a minecart with a chest in it.{*RailIcon*} - - - - You can also craft powered rails, which take power from redstone torches and circuits to accelerate the cart. These can be connected to switches, levers and pressure plates to make complex systems.{*PoweredRailIcon*} - - - - You are now sailing a boat. To exit the boat, point the cursor at it and press{*CONTROLLER_ACTION_USE*} .{*BoatIcon*} - - - - {*B*} -Press{*CONTROLLER_VK_A*} to learn more about boats.{*B*} -Press{*CONTROLLER_VK_B*} if you already know about boats. - - - - A boat allows you to travel quicker over water. You can steer it using{*CONTROLLER_ACTION_MOVE*} and{*CONTROLLER_ACTION_LOOK*}.{*BoatIcon*} - - - - You are now using a fishing rod. Press{*CONTROLLER_ACTION_USE*} to use it.{*FishingRodIcon*} - - - - {*B*} -Press{*CONTROLLER_VK_A*} to learn more about fishing.{*B*} -Press{*CONTROLLER_VK_B*} if you already know about fishing. - - - - Press{*CONTROLLER_ACTION_USE*} to cast your line and start fishing. Press{*CONTROLLER_ACTION_USE*} again to reel in the fishing line.{*FishingRodIcon*} - - - - If you wait until the float sinks below the surface of the water before reeling in you can catch a fish. Fish can be eaten raw, or cooked by a furnace, to restore health.{*FishIcon*} - - - - As with many other tools a fishing rod has a fixed number of uses. Those uses are not limited to catching fish though. You should experiment with it to see what else can be caught or activated...{*FishingRodIcon*} - - - - This is a bed. Press{*CONTROLLER_ACTION_USE*} while pointing at it at night to sleep through the night and awake in the morning.{*ICON*}355{*/ICON*} - - - - {*B*} -Press{*CONTROLLER_VK_A*} to learn more about beds.{*B*} -Press{*CONTROLLER_VK_B*} if you already know about beds. - - - - A bed should be placed in a safe, well-lit place so that monsters do not wake you in the middle of the night. Once you have used a bed, if you die you will respawn at that bed. -{*ICON*}355{*/ICON*} - - - - If there are other players in your game, everyone must be in a bed at the same time to be able to sleep. -{*ICON*}355{*/ICON*} - - - - In this area there are some simple Redstone and Piston circuits, and a chest with more items to extend these circuits. - - - - {*B*} -Press{*CONTROLLER_VK_A*} to learn more about Redstone circuits and Pistons.{*B*} -Press{*CONTROLLER_VK_B*} if you already know about Redstone circuits and Pistons. - - - - Levers, Buttons, Pressure Plates and Redstone Torches can all provide power to circuits, either by directly attaching them to the item you want to activate or by connecting them with Redstone dust. - - - - The position and direction that you place a power source can change how it affects the surrounding blocks. For example a Redstone torch on the side of a block can be turned off if the block is powered by another source. - - - - Redstone dust is collected by mining redstone ore with a pickaxe made of Iron, Diamond or Gold. You can use it to carry power up to 15 blocks, and it can travel up or down one block in height. -{*ICON*}331{*/ICON*} - - - - Redstone repeaters can be used to extend the distance that the power is carried, or put a delay in a circuit. -{*ICON*}356{*/ICON*} - - - - When powered, a Piston will extend, pushing up to 12 blocks. When they retract, Sticky Pistons can pull back one block of most types. -{*ICON*}33{*/ICON*} - - - - In the chest in this area there are some components for making circuits with pistons. Try using or completing the circuits in this area, or put together your own. There are more examples outside the tutorial area. - - - - In this area there is a Portal to the Nether! - - - - {*B*} -Press{*CONTROLLER_VK_A*} to learn more about Portals and The Nether.{*B*} -Press{*CONTROLLER_VK_B*} if you already know about Portals and The Nether. - - - - Portals are created by placing Obsidian blocks into a frame four blocks wide and five blocks tall. The corner blocks are not required. - - - - To activate a Nether Portal, set fire to the Obsidian blocks inside the frame with a Flint and Steel. Portals can be deactivated if their frame is broken, an explosion happens nearby or a liquid flows through them. - - - - To use a Nether Portal, stand inside it. Your screen will go purple and a sound will play. After a few seconds you will be transported to another dimension. - - - - The Nether can be a dangerous place, full of lava, but can be useful to collect Netherrack which burns forever when lit, and Glowstone which produces light. - - - - The Nether world can be used to fast-travel in the Overworld - traveling one block distance in the Nether is equivalent to traveling 3 blocks in the Overworld. - - - - You are now in Creative mode. - - - - {*B*} -Press{*CONTROLLER_VK_A*} to learn more about Creative mode.{*B*} -Press{*CONTROLLER_VK_B*} if you already know about Creative mode. - - - - When in Creative mode you have in infinite number of all available items and blocks, you can destroy blocks with one click without a tool, you are invulnerable and you can fly. - - - - Press{*CONTROLLER_ACTION_CRAFTING*} to open the creative inventory interface. - - - - Make your way to the opposite side of this hole to continue. - - - - You have now completed the Creative mode tutorial. - - - - In this area a farm has been set up. Farming enables you to create a renewable source of food and other items. - - - - {*B*} -Press{*CONTROLLER_VK_A*} to learn more about farming.{*B*} -Press{*CONTROLLER_VK_B*} if you already know about farming. - - - - Wheat, Pumpkins and Melons are grown from seeds. Wheat seeds are collected by breaking Tall Grass or harvesting wheat, and Pumpkin and Melon seeds are crafted from Pumpkins and Melons respectively. - - - - Before planting seeds the dirt blocks need to be turned into Farmland by using a Hoe. A nearby source of water will help keep the Farmland hydrated and make the crops grow faster, as will keeping the area lit. - - - - Wheat goes through several stages when growing, and is ready to be harvested when it appears darker.{*ICON*}59:7{*/ICON*} - - - - Pumpkins and Melons also need a block next to where you planted the seed for the fruit to grow once the stem has fully grown. - - - - Sugarcane must be planted on a Grass, Dirt or Sand block that is right next to water block. Chopping a Sugarcane block will also drop all blocks that are above it.{*ICON*}83{*/ICON*} - - - - Cacti must be planted on Sand, and will grow up to three blocks high. Like Sugarcane, destroying the lowest block will also allow you to collect the blocks that are above it.{*ICON*}81{*/ICON*} - - - - Mushrooms should be planted in a dimly lit area, and will spread to nearby dimly lit blocks.{*ICON*}39{*/ICON*} - - - - Bonemeal can be used to grow crops to their fully grown state, or grow Mushrooms into Huge Mushrooms.{*ICON*}351:15{*/ICON*} - - - - You have now completed the farming tutorial. - - - - In this area animals have been penned in. You can breed animals to produce baby versions of themselves. - - - - {*B*} -Press{*CONTROLLER_VK_A*} to learn more about animals and breeding.{*B*} -Press{*CONTROLLER_VK_B*} if you already know about animals and breeding. - - - - To get the animals to breed, you will need to feed them with the right food to get them to go into 'Love Mode'. - - - - Feed Wheat to a cow, mooshroom or sheep, Carrots to pigs, Wheat Seeds or Nether Wart to a chicken, or any kind of meat to a wolf, and they'll start looking for another animal of the same species near them that is also in Love Mode. - - - - When two animals of the same species meet, and both are in Love Mode, they will kiss for a few seconds, and then a baby animal will appear. The baby animal will follow their parents for a while before growing into a full sized animal itself. - - - - After being in Love Mode, an animal will not be able to enter it again for about five minutes. - - - - Some animals will follow you if you are holding their food in your hand. This makes it easier to group animals together to breed them.{*ICON*}296{*/ICON*} - - - - Wild wolves can be tamed by giving them bones. Once tamed Love Hearts will appear around them. Tamed wolves will follow the player and defend them if they haven't been commanded to sit. - - - - You have now completed the animal and breeding tutorial. - - - - In this area are some pumpkins and blocks to make a Snow Golem and an Iron Golem. - - - - {*B*} -Press{*CONTROLLER_VK_A*} to learn more about Golems.{*B*} -Press{*CONTROLLER_VK_B*} if you already know about Golems. - - - - Golems are created by placing a pumpkin on top of a stack of blocks. - - - - Snow Golems are created with two Snow Blocks, one of top of the other, with a pumpkin on top. Snow Golems throw snowballs at your enemies. - - - - Iron Golems are created with four Iron Blocks in the pattern shown, with a pumpkin on top of the middle block. Iron Golems attack your enemies. - - - - Iron Golems also appear naturally to protect villages, and will attack you if you attack any villagers. - - - - You cannot leave this area until you have completed the tutorial. - - - - Different tools are better for different materials. You should use a shovel to mine soft materials like earth and sand. - - - - Different tools are better for different materials. You should use an axe to chop tree trunks. - - - - Different tools are better for different materials. You should use a pickaxe to mine stone and ore. You may need to make your pickaxe from better materials to get resources from some blocks. - - - - Certain tools are better for attacking enemies. Consider using a sword to attack. - - - - Hint: Hold {*CONTROLLER_ACTION_ACTION*}to mine and chop using your hand or whatever you are holding. You may need to craft a tool to mine some blocks... - - - - The tool you are using has become damaged. Every time you use a tool it becomes damaged, and will eventually break. The colored bar below the item in your inventory shows the current damage state. - - - - Hold{*CONTROLLER_ACTION_JUMP*} to swim up. - - - - In this area there is a minecart on a track. To enter the minecart, point the cursor at it and press{*CONTROLLER_ACTION_USE*}. Use{*CONTROLLER_ACTION_USE*} on the button to make the minecart move. - - - - In the chest beside the river there is a boat. To use the boat, point the cursor at water and press{*CONTROLLER_ACTION_USE*}. Use{*CONTROLLER_ACTION_USE*} while pointing at the boat to enter it. - - - - In the chest beside the pond there is a fishing rod. Take the fishing rod from the chest and select it as the current item in your hand to use it. - - - - This more advanced piston mechanism creates a self-repairing bridge! Push the button to activate, then investigate how the components interact to learn more. - - - - If you move the pointer outside of the interface while carrying an item, you can drop that item. - - - - You do not have all the ingredients required to make this item. The box on the bottom left shows the ingredients required to craft this. - - - - Congratulations, you have completed the tutorial. Time in the game is now passing normally, and you don't have long until night time and the monsters come out! Finish your shelter! - - - - {*EXIT_PICTURE*} When you are ready to explore further, there is a stairway in this area near the Miner's shelter that leads to a small castle. - - - - Reminder: - - - - - - - - New features have been added to the game in the latest version, including new areas in the tutorial world. - - - - {*B*}Press{*CONTROLLER_VK_A*} to play through the tutorial as normal.{*B*} -Press{*CONTROLLER_VK_B*} to skip the main tutorial. - - - - In this area you will find areas setup to help you learn about fishing, boats, pistons and redstone. - - - - Outside of this area you will find examples of buildings, farming, minecarts and tracks, enchanting, brewing, trading, smithing and more! - - - - Your food bar has depleted to a level where you will no longer heal. - - - - {*B*} -Press{*CONTROLLER_VK_A*} to learn more about the food bar and eating food.{*B*} -Press{*CONTROLLER_VK_B*} if you already know about the food bar and eating food. - - - - This is the horse inventory interface. - - - - {*B*}Press{*CONTROLLER_VK_A*} to continue. -{*B*}Press{*CONTROLLER_VK_B*} if you already know how to use the horse inventory. - - - - The horse inventory allows you to transfer, or equip items to your Horse, Donkey or Mule. - - - - Saddle your Horse by placing a Saddle in the saddle slot. Horses can be given armor by placing Horse Armor in the armor slot. - - - - You can also transfer items between your own inventory and the saddlebags strapped to Donkeys and Mules in this menu. - - - - You have found a Horse. - - - - You have found a Donkey. - - - - You have found a Mule. - - - - {*B*}Press{*CONTROLLER_VK_A*} to learn more about Horses, Donkeys and Mules. -{*B*}Press{*CONTROLLER_VK_B*} if you already know about Horses, Donkeys and Mules. - - - - Horses and Donkeys are found mainly in open plains. Mules can be bred from a Donkey and a Horse, but are infertile themselves. - - - - All adult Horses, Donkeys and Mules can be ridden. However only Horses can be armored, and only Mules and Donkeys may be equipped with saddlebags for transporting items. - - - - Horses, Donkeys and Mules must be tamed before they can be used. A horse is tamed by attempting to ride it, and managing to stay on the horse while it attempts to throw the rider off. - - - - When tamed Love Hearts will appear around them and they will no longer buck the player off. - - - - Try to ride this horse now. Use {*CONTROLLER_ACTION_USE*} with no items or tools in your hand to mount it. - - - - To steer a horse they must then be equipped with a saddle, which can be bought from villagers or found inside chests hidden in the world. - - - - Tame Donkeys and Mules can be given saddlebags by attaching a chest. These bags can be accessed whilst riding or when sneaking. - - - - Horses and Donkeys (but not Mules) can be bred like other animals using Golden Apples or Golden Carrots. Foals will grow into adult horses over time, although feeding them wheat or hay will speed this up. - - - - You can try to tame the Horses and Donkeys here, and there are Saddles, Horse Armor and other useful items for Horses in chests around here too. - - - - This is the Beacon interface, which you can use to choose powers for your Beacon to grant. - - - - {*B*} -Press{*CONTROLLER_VK_A*} to continue.{*B*} -Press{*CONTROLLER_VK_B*} if you already know how to use the Beacon interface. - - - - In the Beacon menu you can select 1 primary power for your Beacon. The more tiers your pyramid has the more powers you will have to choose from. - - - - A Beacon on a pyramid with at least 4 tiers grants an additional option of either the Regeneration secondary power or a stronger primary power. - - - - To set the powers of your Beacon you must sacrifice an Emerald, Diamond, Gold or Iron Ingot in the payment slot. Once set, the powers will emanate from the Beacon indefinitely. - - - - At the top of this pyramid there is an inactivate Beacon. - - - - {*B*} -Press{*CONTROLLER_VK_A*} to learn more about Beacons.{*B*} -Press{*CONTROLLER_VK_B*} if you already know about Beacons. - - - - Active Beacons project a bright beam of light into the sky and grant powers to nearby players. They are crafted with Glass, Obsidian and Nether Stars, which can be obtained by defeating the Wither. - - - - Beacons must be placed so that they are in sunlight during the day. Beacons must be placed on Pyramids of Iron, Gold, Emerald or Diamond. However the choice of material has no effect on the power of the beacon. - - - - Try using the Beacon to set the powers it grants, you can use the Iron Ingots provided as the necessary payment. - - - - This room contains Hoppers - - - - {*B*} -Press{*CONTROLLER_VK_A*} to learn more about Hoppers.{*B*} -Press{*CONTROLLER_VK_B*} if you already know about Hoppers. - - - - Hoppers are used to insert or remove items from containers, and to automatically pick-up items thrown into them. - - - - They can affect Brewing Stands, Chests, Dispensers, Droppers, Minecarts with Chests, Minecarts with Hoppers, as well as other Hoppers. - - - - Hoppers will continuously attempt to suck items out of suitable container placed above them. It will also attempt to insert stored items into an output container. - - - - However if a Hopper is powered by Redstone it will become inactive and stop both sucking and inserting items. - - - - A Hopper points in the direction it tries to output items. To make a Hopper point to a particular block, place the Hopper against that block whilst sneaking. - - - - There are various useful Hopper layouts for you to see and experiment with in this room. - - - - This is the Firework interface, which you can use to craft Fireworks and Firework Stars. - - - - {*B*} -Press{*CONTROLLER_VK_A*} to continue.{*B*} -Press{*CONTROLLER_VK_B*} if you already know how to use the Firework interface. - - - - To craft a Firework, place Gunpowder and Paper in the 3x3 crafting grid that is shown above your inventory. - - - - You can optionally place multiple Firework Stars in the crafting grid to add them to the Firework. - - - - Filling more slots in the crafting grid with Gunpowder will increase the height at which all the Firework Stars will explode. - - - - You can then take the crafted Firework out of the output slot when you wish to craft it. - - - - Firework Stars can be crafted by placing Gunpowder and Dye into the crafting grid. - - - - The Dye will set the color of the explosion of the Firework Star. - - - - The shape of the Firework Star is set by adding either a Fire Charge, Gold Nugget, Feather or Mob Head. - - - - A trail or a twinkle can be added using Diamonds or Glowstone Dust. - - - - After a Firework Star has been crafted, you can set the fade color of the Firework Star by crafting it with Dye. - - - - Contained within the chests here there are various items used in the creation of FIREWORKS! - - - - {*B*} -Press{*CONTROLLER_VK_A*} to learn more about Fireworks. {*B*} -Press{*CONTROLLER_VK_B*} if you already know about Fireworks. - - - - Fireworks are decorative items that can be launched by hand or from Dispensers. They are crafted using Paper, Gunpowder and optionally a number of Firework Stars. - - - - The colors, fade, shape, size, and effects (such as trails and twinkles) of Firework Stars can be customized by including additional ingredients when crafting. - - - - Try crafting a Firework at the Crafting Table using an assortment of ingredients from the chests. - - - - Select - - - - Use - - - - Back - - - - Exit - - - - Cancel - - - - Cancel Join - - - - Refresh Online Games List - - - - Party Games - - - - All Games - - - - Change Group - - - - Show Inventory - - - - Show Description - - - - Show Ingredients - - - - Crafting - - - - Create - - - - Take/Place - - - - Take - - - - Take All - - - - Take Half - - - - Place - - - - Place All - - - - Place One - - - - Drop - - - - Drop All - - - - Drop One - - - - Swap - - - - Quick Move - - - - Clear Quick Select - - - - What's This? - - - - Share To Facebook - - - - Change Filter - - - - Send Friend Request - - - - Page Down - - - - Page Up - - - - Next - - - - Previous - - - - Kick Player - - - - Dye - - - - Mine - - - - Feed - - - - Tame - - - - Heal - - - - Sit - - - - Follow Me - - - - Eject - - - - Empty - - - - Saddle - - - - Place - - - - Hit - - - - Milk - - - - Collect - - - - Eat - - - - Sleep - - - - Wake Up - - - - Play - - - - Ride - - - - Sail - - - - Grow - - - - Swim Up - - - - Open - - - - Change Pitch - - - - Detonate - - - - Read - - - - Hang - - - - Throw - - - - Plant - - - - Till - - - - Harvest - - - - Continue - - - - Unlock Full Game - - - - Delete Save - - - - Delete - - - - Options - - - - Invite Friends - - - - Accept - - - - Shear - - - - Ban Level - - - - Select Skin - - - - Ignite - - - - Navigate - - - - Install Full Version - - - - Install Trial Version - - - - Install - - - - Reinstall - - - - Save Options - - - - Execute Command - - - - Creative - - - - Move Ingredient - - - - Move Fuel - - - - Move Tool - - - - Move Armor - - - - Move Weapon - - - - Equip - - - - Draw - - - - Release - - - - Privileges - - - - Block - - - - Page Up - - - - Page Down - - - - Love Mode - - - - Drink - - - - Rotate - - - - Hide - - - - Clear All Slots - - - - Mount - - - - Dismount - - - - Attach Chest - - - - Launch - - - - Leash - - - - Release - - - - Attach - - - - Name - - - - OK - - - - Cancel - - - - Minecraft Store - - - - Are you sure you want to leave your current game and join the new one? Any unsaved progress will be lost. - - - - Exit Game - - - - Save Game - - - - Exit Without Saving - - - - Are you sure you want to overwrite any previous save for this world with the current version of this world? - - - - Are you sure you want to exit without saving? You will lose all progress in this world! - - - - Start Game - - - - Damaged Save - - - - This save is corrupt or damaged. Would you like to delete it? - - - - Are you sure you want to exit to the main menu and disconnect all players from the game? Any unsaved progress will be lost. - - - - Exit and save - - - - Exit without saving - - - - Are you sure you want to exit to the main menu? Any unsaved progress will be lost. - - - - Are you sure you want to exit to the main menu? Your progress will be lost! - - - - Create New World - - - - Play Tutorial - - - - Tutorial - - - - Name Your World - - - - Enter a name for your world - - - - Input the seed for your world generation - - - - Load Saved World - - - - Press START to join game - - - - Exiting the game - - - - An error occurred. Exiting to the main menu. - - - - Connection failed - - - - Connection lost - - - - Connection to the server was lost. Exiting to the main menu. - - - - Disconnected by the server - - - - You were kicked from the game - - - - You were kicked from the game for flying - - - - Connection attempt took too long - - - - The server is full - - - - The host has exited the game. - - - - You cannot join this game as you are not friends with anybody in the game. - - - - You cannot join this game as you have previously been kicked by the host. - - - - You cannot join this game as the player you are trying to join is running an older version of the game. - - - - You cannot join this game as the player you are trying to join is running a newer version of the game. - - - - New World - - - - Award Unlocked! - - - - Hurray - you've been awarded a gamerpic featuring Steve from Minecraft! - - - - Hurray - you've been awarded a gamerpic featuring a Creeper! - - - - Unlock Full Game - - - - You're playing the trial game, but you'll need the full game to be able to save your game. -Would you like to unlock the full game now? - - - - Please wait - - - - No results - - - - Filter: - - - - Friends - - - - My Score - - - - Overall - - - - Entries: - - - - Rank - - - - Preparing to Save Level - - - - Preparing Chunks... - - - - Finalizing... - - - - Building Terrain - - - - Simulating world for a bit - - - - Initializing server - - - - Generating spawn area - - - - Loading spawn area - - - - Entering The Nether - - - - Leaving The Nether - - - - Respawning - - - - Generating level - - - - Loading level - - - - Saving players - - - - Connecting to host - - - - Downloading terrain - - - - Switching to offline game - - - - Please wait while the host saves the game - - - - Entering The END - - - - Leaving The END - - - - Finding Seed for the World Generator - - - - This bed is occupied - - - - You can only sleep at night - - - - %s is sleeping in a bed. To skip to dawn, all players need to sleep in beds at the same time. - - - - Your home bed was missing or obstructed - - - - You may not rest now, there are monsters nearby - - - - You are sleeping in a bed. To skip to dawn, all players need to sleep in beds at the same time. - - - - Tools and Weapons - - - - Weapons - - - - Food - - - - Structures - - - - Armor - - - - Mechanisms - - - - Transport - - - - Decorations - - - - Building Blocks - - - - Redstone & Transportation - - - - Miscellaneous - - - - Brewing - - - - Tools, Weapons & Armor - - - - Materials - - - - Signed out - - - - Difficulty - - - - Control Type - - - - Music - - - - Sound - - - - Gamma - - - - Game Sensitivity - - - - Interface Sensitivity - - - - Peaceful - - - - Easy - - - - Normal - - - - Hard - - - - Keyboard & Mouse - - - - Xbox One - - - - Xbox 360 - - - - PlayStation Vita - - - - PlayStation 3 - - - - PlayStation 4 - - - - Wii U - - - - Nintendo Switch - - - - In this mode, the player regains health over time, and there are no enemies in the environment. - - - - In this mode, enemies spawn in the environment, but will do less damage to the player than in the Normal mode. - - - - In this mode, enemies spawn in the environment and will do a standard amount of damage to the player. - - - - In this mode, enemies will spawn in the environment, and will do a great deal of damage to the player. Watch out for the Creepers too, since they are unlikely to cancel their exploding attack when you move away from them! - - - - Trial Timeout - - - - Game full - - - - Failed to join game as there are no spaces left - - - - Enter Sign Text - - - - Enter a line of text for your sign - - - - Enter Title - - - - Enter a title for your post - - - - Enter Caption - - - - Enter a caption for your post - - - - Enter Description - - - - Enter a description for your post - - - - Inventory - - - - Ingredients - - - - Brewing Stand - - - - Chest - - - - Enchant - - - - Furnace - - - - Ingredient - - - - Fuel - - - - Dispenser - - - - Horse - - - - Dropper - - - - Hopper - - - - Beacon - - - - Primary Power - - - - Secondary Power - - - - Minecart - - - - There are no downloadable content offers of this type available for this title at the moment. - - - - %s has joined the game. - - - - %s has left the game. - - - - %s was kicked from the game. - - - - Are you sure you want to delete this save game? - - - - Awaiting approval - - - - Censored - - - - Now playing: - - - - Reset Settings - - - - Are you sure you would like to reset your settings to their default values? - - - - Loading Error - - - - %s's Game - - - - Unknown host game - - - - Guest signed out - - - - A guest player has signed out causing all guest players to be removed from the game. - - - - Sign in - - - - You are not signed in. In order to play this game, you will need to be signed in. Do you want to sign in now? - - - - Multiplayer not allowed - - - - Failed to create game - - - - Auto Selected - - - - No Pack: Default Skins - - - - Favorite Skins - - - - Banned Level - - - - The game you are joining is in your banned level list. -If you choose to join this game, the level will be removed from your banned level list. - - - - Ban This Level? - - - - Are you sure you want to add this level to your banned level list? -Selecting OK will also exit this game. - - - - Remove from Banned List - - - - Autosave Interval - - - - Autosave Interval: OFF - - - - Mins - - - - Can't Place Here! - - - - Placing lava close to the level spawn point is not allowed due to the possibility of instant death for spawning players. - - - - Interface Opacity - - - - Preparing to Autosave Level - - - - HUD Size - - - - HUD Size (Splitscreen) - - - - Seed - - - - Unlock Skin Pack - - - - To use the skin you have selected, you need to unlock this skin pack. -Would you like to unlock this skin pack now? - - - - Unlock Texture Pack - - - - To use this texture pack for your world, you need to unlock it. -Would you like to unlock it now? - - - - Trial Texture Pack - - - - You are using a trial version of the texture pack. You will not be able to save this world unless you unlock the full version. -Would you like to unlock the full version of the texture pack? - - - - Texture Pack Not Present - - - - Unlock Full Version - - - - Download Trial Version - - - - Download Full Version - - - - This world uses a mash-up pack or texture pack you don't have! -Would you like to install the mash-up pack or texture pack now? - - - - Get Trial Version - - - - Get Full Version - - - - Kick player - - - - Are you sure you want to kick this player from the game? They will not be able to rejoin until you restart the world. - - - - Gamerpics Packs - - - - Themes - - - - Skins Packs - - - - Allow friends of friends - - - - You cannot join this game because it has been limited to players who are friends of the host. - - - - Can't Join Game - - - - Selected - - - - Selected skin: - - - - Corrupt Downloadable Content - - - - This downloadable content is corrupt and cannot be used. You need to delete it, then re-install it from the Minecraft Store menu. - - - - Some of your downloadable content is corrupt and cannot be used. You need to delete them, then re-install them from the Minecraft Store menu. - - - - Your game mode has been changed - - - - Rename Your World - - - - Enter the new name for your world - - - - Game Mode: Survival - - - - Game Mode: Creative - - - - Game Mode: Adventure - - - - Game Mode: Hardcore - - - - Survival - - - - Creative - - - - Adventure - - - - Hardcore - - - - Created in Survival Mode - - - - Created in Creative Mode - - - - Render Clouds - - - - Cave Sounds - - - - Minecart Sounds - - - - What would you like to do with this save game? - - - - Rename Save - - - - Autosaving in %d... - - - - On - - - - Off - - - - Normal - - - - Superflat - - - - Enter a seed to generate the same terrain again. Leave blank for a random world. - - - - When enabled, the game will be an online game. - - - - When enabled, only invited players can join. - - - - When enabled, friends of people on your Friends List can join the game. - - - - When enabled, players can inflict damage on other players. Only affects Survival mode. - - - - When disabled, players joining the game cannot build or mine until authorised. - - - - When enabled, fire may spread to nearby flammable blocks. - - - - When enabled, TNT will explode when activated. - - - - When enabled, the Nether world will be re-generated. This is useful if you have an older save where Nether Fortresses were not present. - - - - When enabled, structures such as Villages and Strongholds will generate in the world. - - - - When enabled, a completely flat world will be generated in the Overworld and in the Nether. - - - - When enabled, a chest containing some useful items will be created near the player spawn point. - - - - When disabled, prevents monsters and animals from changing blocks (for example, Creeper explosions won't destroy blocks and Sheep won't remove Grass) or picking up items. - - - - When enabled, players will keep their inventory when they die. - - - - When disabled, mobs will not spawn naturally. - - - - When disabled, monsters and animals will not drop loot (for example, Creepers won't drop gunpowder). - - - - When disabled, blocks will not drop items when destroyed (for example, Stone blocks won't drop Cobblestone). - - - - When disabled, players will not regenerate health naturally. - - - - When disabled, the time of day will not change. - - - - Skin Packs - - - - Themes - - - - Gamerpics - - - - Avatar Items - - - - Texture Packs - - - - Mash-Up Packs - - - - {*PLAYER*} went up in flames - - - - {*PLAYER*} burned to death - - - - {*PLAYER*} tried to swim in lava - - - - {*PLAYER*} suffocated in a wall - - - - {*PLAYER*} drowned - - - - {*PLAYER*} starved to death - - - - {*PLAYER*} was pricked to death - - - - {*PLAYER*} hit the ground too hard - - - - {*PLAYER*} fell out of the world - - - - {*PLAYER*} died - - - - {*PLAYER*} blew up - - - - {*PLAYER*} was killed by magic - - - - {*PLAYER*} was killed by Ender Dragon breath - - - - {*PLAYER*} was slain by {*SOURCE*} - - - - {*PLAYER*} was slain by {*SOURCE*} - - - - {*PLAYER*} was shot by {*SOURCE*} - - - - {*PLAYER*} was fireballed by {*SOURCE*} - - - - {*PLAYER*} was pummeled by {*SOURCE*} - - - - {*PLAYER*} was killed by {*SOURCE*} using magic - - - - {*PLAYER*} fell off a ladder - - - - {*PLAYER*} fell off some vines - - - - {*PLAYER*} fell out of the water - - - - {*PLAYER*} fell from a high place - - - - {*PLAYER*} was doomed to fall by {*SOURCE*} - - - - {*PLAYER*} was doomed to fall by {*SOURCE*} - - - - {*PLAYER*} was doomed to fall by {*SOURCE*} using {*ITEM*} - - - - {*PLAYER*} fell too far and was finished by {*SOURCE*} - - - - {*PLAYER*} fell too far and was finished by {*SOURCE*} using {*ITEM*} - - - - {*PLAYER*} walked into fire whilst fighting {*SOURCE*} - - - - {*PLAYER*} was burnt to a crisp whilst fighting {*SOURCE*} - - - - {*PLAYER*} tried to swim in lava to escape {*SOURCE*} - - - - {*PLAYER*} drowned whilst trying to escape {*SOURCE*} - - - - {*PLAYER*} walked into a cactus whilst trying to escape {*SOURCE*} - - - - {*PLAYER*} was blown up by {*SOURCE*} - - - - {*PLAYER*} withered away - - - - {*PLAYER*} was slain by {*SOURCE*} using {*ITEM*} - - - - {*PLAYER*} was shot by {*SOURCE*} using {*ITEM*} - - - - {*PLAYER*} was fireballed by {*SOURCE*} using {*ITEM*} - - - - {*PLAYER*} was pummeled by {*SOURCE*} using {*ITEM*} - - - - {*PLAYER*} was killed by {*SOURCE*} using {*ITEM*} - - - - Bedrock Fog - - - - Display HUD - - - - Display Hand - - - - Death Messages - - - - dead. - - - - Animated Character - - - - Custom Skin Animation - - - - You can no longer mine or use items - - - - You can now mine and use items - - - - You can no longer place blocks - - - - You can now place blocks - - - - You can now use doors and switches - - - - You can no longer use doors and switches - - - - You can now use containers (e.g. chests) - - - - You can no longer use containers (e.g. chests) - - - - You can no longer attack mobs - - - - You can now attack mobs - - - - You can no longer attack players - - - - You can now attack players - - - - You can no longer attack animals - - - - You can now attack animals - - - - You are now a moderator - - - - You are no longer a moderator - - - - You can now fly - - - - You can no longer fly - - - - You will no longer get exhausted - - - - You will now get exhausted - - - - You are now invisible - - - - You are no longer invisible - - - - You are now invulnerable - - - - You are no longer invulnerable - - - - %d MSP - - - - Ender Dragon - - - - %s has entered The End - - - - %s has left The End - - - - -{*C3*}I see the player you mean.{*EF*}{*B*}{*B*} -{*C2*}{*PLAYER*}?{*EF*}{*B*}{*B*} -{*C3*}Yes. Take care. It has reached a higher level now. It can read our thoughts.{*EF*}{*B*}{*B*} -{*C2*}That doesn't matter. It thinks we are part of the game.{*EF*}{*B*}{*B*} -{*C3*}I like this player. It played well. It did not give up.{*EF*}{*B*}{*B*} -{*C2*}It is reading our thoughts as though they were words on a screen.{*EF*}{*B*}{*B*} -{*C3*}That is how it chooses to imagine many things, when it is deep in the dream of a game.{*EF*}{*B*}{*B*} -{*C2*}Words make a wonderful interface. Very flexible. And less terrifying than staring at the reality behind the screen.{*EF*}{*B*}{*B*} -{*C3*}They used to hear voices. Before players could read. Back in the days when those who did not play called the players witches, and warlocks. And players dreamed they flew through the air, on sticks powered by demons.{*EF*}{*B*}{*B*} -{*C2*}What did this player dream?{*EF*}{*B*}{*B*} -{*C3*}This player dreamed of sunlight and trees. Of fire and water. It dreamed it created. And it dreamed it destroyed. It dreamed it hunted, and was hunted. It dreamed of shelter.{*EF*}{*B*}{*B*} -{*C2*}Hah, the original interface. A million years old, and it still works. But what true structure did this player create, in the reality behind the screen?{*EF*}{*B*}{*B*} -{*C3*}It worked, with a million others, to sculpt a true world in a fold of the {*EF*}{*NOISE*}{*C3*}, and created a {*EF*}{*NOISE*}{*C3*} for {*EF*}{*NOISE*}{*C3*}, in the {*EF*}{*NOISE*}{*C3*}.{*EF*}{*B*}{*B*} -{*C2*}It cannot read that thought.{*EF*}{*B*}{*B*} -{*C3*}No. It has not yet achieved the highest level. That, it must achieve in the long dream of life, not the short dream of a game.{*EF*}{*B*}{*B*} -{*C2*}Does it know that we love it? That the universe is kind?{*EF*}{*B*}{*B*} -{*C3*}Sometimes, through the noise of its thoughts, it hears the universe, yes.{*EF*}{*B*}{*B*} -{*C2*}But there are times it is sad, in the long dream. It creates worlds that have no summer, and it shivers under a black sun, and it takes its sad creation for reality.{*EF*}{*B*}{*B*} -{*C3*}To cure it of sorrow would destroy it. The sorrow is part of its own private task. We cannot interfere.{*EF*}{*B*}{*B*} -{*C2*}Sometimes when they are deep in dreams, I want to tell them, they are building true worlds in reality. Sometimes I want to tell them of their importance to the universe. Sometimes, when they have not made a true connection in a while, I want to help them to speak the word they fear.{*EF*}{*B*}{*B*} -{*C3*}It reads our thoughts.{*EF*}{*B*}{*B*} -{*C2*}Sometimes I do not care. Sometimes I wish to tell them, this world you take for truth is merely {*EF*}{*NOISE*}{*C2*} and {*EF*}{*NOISE*}{*C2*}, I wish to tell them that they are {*EF*}{*NOISE*}{*C2*} in the {*EF*}{*NOISE*}{*C2*}. They see so little of reality, in their long dream.{*EF*}{*B*}{*B*} -{*C3*}And yet they play the game.{*EF*}{*B*}{*B*} -{*C2*}But it would be so easy to tell them...{*EF*}{*B*}{*B*} -{*C3*}Too strong for this dream. To tell them how to live is to prevent them living.{*EF*}{*B*}{*B*} -{*C2*}I will not tell the player how to live.{*EF*}{*B*}{*B*} -{*C3*}The player is growing restless.{*EF*}{*B*}{*B*} -{*C2*}I will tell the player a story.{*EF*}{*B*}{*B*} -{*C3*}But not the truth.{*EF*}{*B*}{*B*} -{*C2*}No. A story that contains the truth safely, in a cage of words. Not the naked truth that can burn over any distance.{*EF*}{*B*}{*B*} -{*C3*}Give it a body, again.{*EF*}{*B*}{*B*} -{*C2*}Yes. Player...{*EF*}{*B*}{*B*} -{*C3*}Use its name.{*EF*}{*B*}{*B*} -{*C2*}{*PLAYER*}. Player of games.{*EF*}{*B*}{*B*} -{*C3*}Good.{*EF*}{*B*}{*B*} - - - - - -{*C2*}Take a breath, now. Take another. Feel air in your lungs. Let your limbs return. Yes, move your fingers. Have a body again, under gravity, in air. Respawn in the long dream. There you are. Your body touching the universe again at every point, as though you were separate things. As though we were separate things.{*EF*}{*B*}{*B*} -{*C3*}Who are we? Once we were called the spirit of the mountain. Father sun, mother moon. Ancestral spirits, animal spirits. Jinn. Ghosts. The green man. Then gods, demons. Angels. Poltergeists. Aliens, extraterrestrials. Leptons, quarks. The words change. We do not change.{*EF*}{*B*}{*B*} -{*C2*}We are the universe. We are everything you think isn't you. You are looking at us now, through your skin and your eyes. And why does the universe touch your skin, and throw light on you? To see you, player. To know you. And to be known. I shall tell you a story.{*EF*}{*B*}{*B*} -{*C2*}Once upon a time, there was a player.{*EF*}{*B*}{*B*} -{*C3*}The player was you, {*PLAYER*}.{*EF*}{*B*}{*B*} -{*C2*}Sometimes it thought itself human, on the thin crust of a spinning globe of molten rock. The ball of molten rock circled a ball of blazing gas that was three hundred and thirty thousand times more massive than it. They were so far apart that light took eight minutes to cross the gap. The light was information from a star, and it could burn your skin from a hundred and fifty million kilometres away.{*EF*}{*B*}{*B*} -{*C2*}Sometimes the player dreamed it was a miner, on the surface of a world that was flat, and infinite. The sun was a square of white. The days were short; there was much to do; and death was a temporary inconvenience.{*EF*}{*B*}{*B*} -{*C3*}Sometimes the player dreamed it was lost in a story.{*EF*}{*B*}{*B*} -{*C2*}Sometimes the player dreamed it was other things, in other places. Sometimes these dreams were disturbing. Sometimes very beautiful indeed. Sometimes the player woke from one dream into another, then woke from that into a third.{*EF*}{*B*}{*B*} -{*C3*}Sometimes the player dreamed it watched words on a screen.{*EF*}{*B*}{*B*} -{*C2*}Let's go back.{*EF*}{*B*}{*B*} -{*C2*}The atoms of the player were scattered in the grass, in the rivers, in the air, in the ground. A woman gathered the atoms; she drank and ate and inhaled; and the woman assembled the player, in her body.{*EF*}{*B*}{*B*} -{*C2*}And the player awoke, from the warm, dark world of its mother's body, into the long dream.{*EF*}{*B*}{*B*} -{*C2*}And the player was a new story, never told before, written in letters of DNA. And the player was a new program, never run before, generated by a sourcecode a billion years old. And the player was a new human, never alive before, made from nothing but milk and love.{*EF*}{*B*}{*B*} -{*C3*}You are the player. The story. The program. The human. Made from nothing but milk and love.{*EF*}{*B*}{*B*} -{*C2*}Let's go further back.{*EF*}{*B*}{*B*} -{*C2*}The seven billion billion billion atoms of the player's body were created, long before this game, in the heart of a star. So the player, too, is information from a star. And the player moves through a story, which is a forest of information planted by a man called Julian, on a flat, infinite world created by a man called Markus, that exists inside a small, private world created by the player, who inhabits a universe created by...{*EF*}{*B*}{*B*} -{*C3*}Shush. Sometimes the player created a small, private world that was soft and warm and simple. Sometimes hard, and cold, and complicated. Sometimes it built a model of the universe in its head; flecks of energy, moving through vast empty spaces. Sometimes it called those flecks "electrons" and "protons".{*EF*}{*B*}{*B*} - - - - - -{*C2*}Sometimes it called them "planets" and "stars".{*EF*}{*B*}{*B*} -{*C2*}Sometimes it believed it was in a universe that was made of energy that was made of offs and ons; zeros and ones; lines of code. Sometimes it believed it was playing a game. Sometimes it believed it was reading words on a screen.{*EF*}{*B*}{*B*} -{*C3*}You are the player, reading words...{*EF*}{*B*}{*B*} -{*C2*}Shush... Sometimes the player read lines of code on a screen. Decoded them into words; decoded words into meaning; decoded meaning into feelings, emotions, theories, ideas, and the player started to breathe faster and deeper and realised it was alive, it was alive, those thousand deaths had not been real, the player was alive{*EF*}{*B*}{*B*} -{*C3*}You. You. You are alive.{*EF*}{*B*}{*B*} -{*C2*}and sometimes the player believed the universe had spoken to it through the sunlight that came through the shuffling leaves of the summer trees{*EF*}{*B*}{*B*} -{*C3*}and sometimes the player believed the universe had spoken to it through the light that fell from the crisp night sky of winter, where a fleck of light in the corner of the player's eye might be a star a million times as massive as the sun, boiling its planets to plasma in order to be visible for a moment to the player, walking home at the far side of the universe, suddenly smelling food, almost at the familiar door, about to dream again{*EF*}{*B*}{*B*} -{*C2*}and sometimes the player believed the universe had spoken to it through the zeros and ones, through the electricity of the world, through the scrolling words on a screen at the end of a dream{*EF*}{*B*}{*B*} -{*C3*}and the universe said I love you{*EF*}{*B*}{*B*} -{*C2*}and the universe said you have played the game well{*EF*}{*B*}{*B*} -{*C3*}and the universe said everything you need is within you{*EF*}{*B*}{*B*} -{*C2*}and the universe said you are stronger than you know{*EF*}{*B*}{*B*} -{*C3*}and the universe said you are the daylight{*EF*}{*B*}{*B*} -{*C2*}and the universe said you are the night{*EF*}{*B*}{*B*} -{*C3*}and the universe said the darkness you fight is within you{*EF*}{*B*}{*B*} -{*C2*}and the universe said the light you seek is within you{*EF*}{*B*}{*B*} -{*C3*}and the universe said you are not alone{*EF*}{*B*}{*B*} -{*C2*}and the universe said you are not separate from every other thing{*EF*}{*B*}{*B*} -{*C3*}and the universe said you are the universe tasting itself, talking to itself, reading its own code{*EF*}{*B*}{*B*} -{*C2*}and the universe said I love you because you are love.{*EF*}{*B*}{*B*} -{*C3*}And the game was over and the player woke up from the dream. And the player began a new dream. And the player dreamed again, dreamed better. And the player was the universe. And the player was love.{*EF*}{*B*}{*B*} -{*C3*}You are the player.{*EF*}{*B*}{*B*} -{*C2*}Wake up.{*EF*} - - - - - Reset Nether - - - - Are you sure you want to reset the Nether in this savegame to its default state? You will lose anything you have built in the Nether! - - - - Reset Nether - - - - Don't Reset Nether - - - - Can't shear this Mooshroom at the moment. The maximum number of Pigs, Sheep, Cows, Cats and Horses has been reached. - - - - Can't use Spawn Egg at the moment. The maximum number of Pigs, Sheep, Cows, Cats and Horses has been reached. - - - - Can't use Spawn Egg at the moment. The maximum number of Mooshrooms has been reached. - - - - Can't use Spawn Egg at the moment. The maximum number of Wolves in a world has been reached. - - - - Can't use Spawn Egg at the moment. The maximum number of Chickens in a world has been reached. - - - - Can't use Spawn Egg at the moment. The maximum number of Squid in a world has been reached. - - - - Can't use Spawn Egg at the moment. The maximum number of Bats in a world has been reached. - - - - Can't use Spawn Egg at the moment. The maximum number of enemies in a world has been reached. - - - - Can't use Spawn Egg at the moment. The maximum number of villagers in a world has been reached. - - - - The maximum number of Paintings/Item Frames in a world has been reached. - - - - You can't spawn enemies in Peaceful mode. - - - - This animal can't enter Love Mode. The maximum number of breeding Pigs, Sheep, Cows, Cats and Horses has been reached. - - - - This animal can't enter Love Mode. The maximum number of breeding Wolves has been reached. - - - - This animal can't enter Love Mode. The maximum number of breeding Chickens has been reached. - - - - This animal can't enter Love Mode. The maximum number of breeding horses has been reached. - - - - This animal can't enter Love Mode. The maximum number of breeding Mooshrooms has been reached. - - - - The maximum number of Boats in a world has been reached. - - - - The maximum number of Mob Heads in a world has been reached. - - - - Invert Look - - - - Southpaw - - - - You Died! - - - - Respawn - - - - Downloadable Content Offers - - - - Change Skin - - - - How To Play - - - - Controls - - - - Settings - - - - Languages - - - - Credits - - - - Reinstall Content - - - - Debug Settings - - - - Fire Spreads - - - - TNT Explodes - - - - Player vs Player - - - - Trust Players - - - - Host Privileges - - - - Generate Structures - - - - Superflat World - - - - Bonus Chest - - - - World Options - - - - Game Options - - - - Mob Griefing - - - - Keep Inventory - - - - Mob Spawning - - - - Mob Loot - - - - Tile Drops - - - - Natural Regeneration - - - - Daylight Cycle - - - - Can Build and Mine - - - - Can Use Doors and Switches - - - - Can Open Containers - - - - Can Attack Players - - - - Can Attack Animals - - - - Moderator - - - - Kick Player - - - - Can Fly - - - - Disable Exhaustion - - - - Invisible - - - - Host Options - - - - Players/Invite - - - - Online Game - - - - Invite Only - - - - More Options - - - - Load - - - - New World - - - - World Name - - - - Seed for the World Generator - - - - Leave blank for a random seed - - - - Players - - - - Join Game - - - - Start Game - - - - No Games Found - - - - Play Game - - - - Leaderboards - - - - Help & Options - - - - Unlock Full Game - - - - Resume Game - - - - Save Game - - - - Difficulty: - - - - Game Type: - - - - Structures: - - - - Level Type: - - - - PvP: - - - - Trust Players: - - - - TNT: - - - - Fire Spreads: - - - - Reinstall Theme - - - - Reinstall Gamerpic 1 - - - - Reinstall Gamerpic 2 - - - - Reinstall Avatar Item 1 - - - - Reinstall Avatar Item 2 - - - - Reinstall Avatar Item 3 - - - - Game Options - - - - Audio - - - - Control - - - - Graphics - - - - User Interface - - - - Reset to Defaults - - - - View Bobbing - - - - Hints - - - - In-Game Tooltips - - - - Vertical Splitscreen - - - - Done - - - - Edit sign message: - - - - Fill in the details to accompany your screenshot - - - - Caption - - - - Screenshot from in-game - - - - Edit sign message: - - - - The classic Minecraft textures, icons and user interface! - - - - Show all Mash-up Worlds - - - - No Effects - - - - Speed - - - - Slowness - - - - Haste - - - - Mining Fatigue - - - - Strength - - - - Weakness - - - - Instant Health - - - - Instant Damage - - - - Jump Boost - - - - Nausea - - - - Regeneration - - - - Resistance - - - - Fire Resistance - - - - Water Breathing - - - - Invisibility - - - - Blindness - - - - Night Vision - - - - Hunger - - - - Poison - - - - Wither - - - - Health Boost - - - - Absorption - - - - Saturation - - - - of Swiftness - - - - of Slowness - - - - of Haste - - - - of Dullness - - - - of Strength - - - - of Weakness - - - - of Healing - - - - of Harming - - - - of Leaping - - - - of Nausea - - - - of Regeneration - - - - of Resistance - - - - of Fire Resistance - - - - of Water Breathing - - - - of Invisibility - - - - of Blindness - - - - of Night Vision - - - - of Hunger - - - - of Poison - - - - of Decay - - - - of Health Boost - - - - of Absorption - - - - of Saturation - - - - - - - - - II - - - - III - - - - IV - - - - Splash - - - - Mundane - - - - Uninteresting - - - - Bland - - - - Clear - - - - Milky - - - - Diffuse - - - - Artless - - - - Thin - - - - Awkward - - - - Flat - - - - Bulky - - - - Bungling - - - - Buttered - - - - Smooth - - - - Suave - - - - Debonair - - - - Thick - - - - Elegant - - - - Fancy - - - - Charming - - - - Dashing - - - - Refined - - - - Cordial - - - - Sparkling - - - - Potent - - - - Foul - - - - Odorless - - - - Rank - - - - Harsh - - - - Acrid - - - - Gross - - - - Stinky - - - - Used as the base of all potions. Use in a brewing stand to create potions. - - - - Has no effects, can be used in a brewing stand to create potions by adding more ingredients. - - - - Increases affected players, animals and monsters movement speed, and players sprinting speed, jumping length and field of view. - - - - Reduces affected players, animals and monsters movement speed, and players sprinting speed, jumping length and field of view. - - - - Increase the damage caused by affected players and monsters when attacking. - - - - Reduces the damage cause by affected players and monsters when attacking. - - - - Instantly increases the affected players, animals and monsters health. - - - - Instantly reduces the affected players, animals and monsters health. - - - - Restores health to the affected players, animals and monsters over time. - - - - Makes the affected players, animals and monsters immune to damage from fire, lava, and ranged Blaze attacks. - - - - Reduces health of the affected players, animals and monsters over time. - - - - Allows affected players to breathe normally underwater. - - - - Increases the jump height of the affected player. - - - - When Applied: - - - - Horse Jump Strength - - - - Zombie Reinforcements - - - - Max Health - - - - Mob Follow Range - - - - Knockback Resistance - - - - Speed - - - - Attack Damage - - - - Sharpness - - - - Smite - - - - Bane of Arthropods - - - - Knockback - - - - Fire Aspect - - - - Protection - - - - Fire Protection - - - - Feather Falling - - - - Blast Protection - - - - Projectile Protection - - - - Respiration - - - - Aqua Affinity - - - - Depth Strider - - - - Efficiency - - - - Silk Touch - - - - Unbreaking - - - - Looting - - - - Fortune - - - - Power - - - - Flame - - - - Punch - - - - Infinity - - - - I - - - - II - - - - III - - - - IV - - - - V - - - - VI - - - - VII - - - - VIII - - - - IX - - - - X - - - - Can be mined with an Iron pickaxe or better to collect Emeralds. - - - - Similar to a Chest except that items placed in an Ender Chest are available in every one of the player's Ender Chests, even in different dimensions. - - - - Is activated when an entity passes through a connected Tripwire. - - - - Activates a connected Tripwire Hook when an entity passes through it. - - - - A compact way of storing Emeralds. - - - - A wall made of Cobblestone. - - - - Can be used to repair weapons, tools and armor. - - - - Smelted in a furnace to produce Nether Quartz. - - - - Used as a decoration. - - - - Can be traded with villagers. - - - - Used as a decoration. Flowers, Saplings, Cacti and Mushrooms can be planted in it. - - - - Restores 2{*ICON_SHANK_01*}, and can be crafted into a golden carrot. Can be planted in farmland. - - - - Restores 0.5{*ICON_SHANK_01*}, or can be cooked in a furnace. This can be planted in farmland. - - - - Restores 3{*ICON_SHANK_01*}. Created by cooking a potato in a furnace. - - - - Restores 1{*ICON_SHANK_01*}. Eating this can cause you to become poisoned. - - - - Restores 3{*ICON_SHANK_01*}. Crafted from a carrot and gold nuggets. - - - - Used to control a saddled pig when riding on it. - - - - Restores 4{*ICON_SHANK_01*}. - - - - Used with an Anvil to enchant weapons, tools or armor. - - - - Created by mining Nether Quartz Ore. Can be crafted into a Block of Quartz. - - - - Crafted from Wool. Used as a decoration. - - - - Emerald - - - - Flower Pot - - - - Carrot - - - - Potato - - - - Baked Potato - - - - Poisonous Potato - - - - Golden Carrot - - - - Carrot on a Stick - - - - Pumpkin Pie - - - - Enchanted Book - - - - Nether Quartz - - - - Emerald Ore - - - - Ender Chest - - - - Tripwire Hook - - - - Tripwire - - - - Block of Emerald - - - - Cobblestone Wall - - - - Mossy Cobblestone Wall - - - - Flower Pot - - - - Carrots - - - - Potatoes - - - - Anvil - - - - Anvil - - - - Slightly Damaged Anvil - - - - Very Damaged Anvil - - - - Nether Quartz Ore - - - - Block of Quartz - - - - Chiseled Quartz Block - - - - Pillar Quartz Block - - - - Quartz Stairs - - - - Carpet - - - - Black Carpet - - - - Red Carpet - - - - Green Carpet - - - - Brown Carpet - - - - Blue Carpet - - - - Purple Carpet - - - - Cyan Carpet - - - - Light Gray Carpet - - - - Gray Carpet - - - - Pink Carpet - - - - Lime Carpet - - - - Yellow Carpet - - - - Light Blue Carpet - - - - Magenta Carpet - - - - Orange Carpet - - - - White Carpet - - - - Chiseled Sandstone - - - - Smooth Sandstone - - - - {*PLAYER*} was killed trying to hurt {*SOURCE*} - - - - {*PLAYER*} was squashed by a falling Anvil. - - - - {*PLAYER*} was squashed by a falling block. - - - - Teleported {*PLAYER*} to {*DESTINATION*} - - - - {*PLAYER*} teleported you to their position - - - - {*PLAYER*} teleported to you - - - - Thorns - - - - Quartz Slab - - - - Makes dark areas appear as if in daylight, even under water. - - - - Makes affected players, animals and monsters invisible. - - - - Repair & Name - - - - Enchantment Cost: %d - - - - Too Expensive! - - - - Rename - - - - You have: - - - - Required Items For Trade - - - - {*VILLAGER_TYPE*} offers %s - - - - Repair - - - - Trade - - - - Dye collar - - - - - This is the Anvil interface, which you can use to rename, repair and apply enchantments to weapons, armor, or tools, at the cost of Experience Levels. - - - - - - {*B*} - Press{*CONTROLLER_VK_A*} to learn more about the Anvil interface.{*B*} - Press{*CONTROLLER_VK_B*} if you already know the Anvil interface. - - - - - - To begin working on an item, place it in the first input slot. - - - - - - When the correct raw material is placed in the second input slot (e.g. Iron Ingots for a damaged Iron Sword), the proposed repair appears in the output slot. - - - - - - Alternatively, a second identical item can be placed into the second slot to combine the two items. - - - - - - To enchant items on the Anvil, place an Enchanted Book in the second input slot. - - - - - - The number of Experience Levels that the work will cost is shown beneath the output. If you do not have enough Experience Levels, the repair cannot be completed. - - - - - - It is possible to rename the item by editing the name shown in the textbox. - - - - - - Picking up the repaired item will consume both items used by the Anvil and decrease your Experience Level by the given amount. - - - - - - In this area there is an Anvil and a Chest containing tools and weapons to work on. - - - - - - {*B*} - Press{*CONTROLLER_VK_A*} to learn more about the Anvil.{*B*} - Press{*CONTROLLER_VK_B*} if you already know about the Anvil. - - - - - - Using an Anvil, weapons and tools can be repaired to restore their durability, renamed, or enchanted with Enchanted Books. - - - - - - Enchanted Books can be found inside Chests within dungeons, or enchanted from normal Books at the Enchantment Table. - - - - - - Using the Anvil costs Experience Levels, and each use has a chance to damage the Anvil. - - - - - - The type of work to be done, value of the item, number of enchantments, and amount of prior work all affect the cost of repair. - - - - - - Renaming an item changes the displayed name for all players and permanently reduces the prior work cost. - - - - - - In the Chest in this area you will find damaged Pickaxes, raw materials, Bottles O' Enchanting, and Enchanted Books to experiment with. - - - - - - This is the trading interface which displays trades that can be made with a villager. - - - - - - {*B*} - Press{*CONTROLLER_VK_A*} to learn more about the trading interface.{*B*} - Press{*CONTROLLER_VK_B*} if you already know the trading interface. - - - - - - All trades that the villager is willing to make at the moment are displayed along the top. - - - - - - Trades will appear red and be unavailable if you do not have the required items. - - - - - - The amount and type of items you are giving to the villager are shown in the two boxes on the left. - - - - - - You can see the total number of the items required for the trade in the two boxes on the left. - - - - - - Press{*CONTROLLER_VK_A*} to trade the items the villager requires for the item on offer. - - - - - - In this area there is a villager and a Chest containing Paper to purchase items. - - - - - - {*B*} - Press{*CONTROLLER_VK_A*} to learn more about trading.{*B*} - Press{*CONTROLLER_VK_B*} if you already know about trading. - - - - - - Players can trade items from their inventory with villagers. - - - - - - The trades a villager is likely to offer depends on their profession. - - - - - - Performing a mix of trades will randomly add to or update the villager's available trades. - - - - - - Trades that have been used frequently may be removed temporarily, but the villager will always offer at least one trade. - - - - - - Take some Paper from the Chest and try trading with the villager here. - - - - - - In this area there are two Ender Chests. - - - - - - {*B*} - Press{*CONTROLLER_VK_A*} to learn more about Ender Chests.{*B*} - Press{*CONTROLLER_VK_B*} if you already know about Ender Chests. - - - - - - All Ender Chests in a world are linked, even across dimensions. Items placed into an Ender Chest are accessible in any other Ender Chest. - - - - - - However, the contents of the Ender Chests are different for each player. - - - - - - This allows players to store items in any Ender Chest, and retrieve them from other Ender Chests in different positions in the world. You can try this now by placing items in either Ender Chest. - - - - - Restores 2{*ICON_SHANK_01*}, regenerates health for 30 seconds, and grants fire resistance and damage resistance for 5 minutes. Crafted from an apple and gold blocks. - - - - Can Teleport - - - - Teleport - - - - Teleport To Player - - - - Teleport To Me - - - - Can Disable Exhaustion - - - - Can Become Invisible - - - - You can now enable invisibility - - - - You can no longer enable invisibility - - - - You can now enable flying - - - - You can no longer enable flying - - - - You can now disable exhaustion - - - - You can no longer disable exhaustion - - - - You can now teleport - - - - You can no longer teleport - - - - {*T3*}HOW TO PLAY : ANVIL{*ETW*}{*B*}{*B*} -Experience Levels can be used to repair, enchant or rename items with the Anvil.{*B*} -All items can be renamed, although only items with durability can be repaired or have enchantments from Enchanted Books applied to them.{*B*} -An item can be repaired by placing it in one of the input slots on the left, along with either some raw materials of the item, like Iron Ingots for an Iron Sword, or combined with another item of the same type.{*B*} -Combining items is more efficient when done with an Anvil, and additionally, if either of the items were enchanted, the finished product may have enchantments from either of the inputs.{*B*} -Enchanted Books can apply enchantments to items by combining them at an Anvil if the Book's enchantment is suitable. Enchanted Books can be found in Chests within dungeons, or enchanted from normal Books at the Enchantment Table.{*B*} -There is a chance that the Anvil will be damaged with each use and after enough punishment it will be destroyed.{*B*} - - - - - {*T3*}HOW TO PLAY : TRADING{*ETW*}{*B*}{*B*} -It is possible to trade items with villagers. Each villager has a profession; they can be Farmers, Butchers, Blacksmiths, Librarians or Priests, and this affects the type of items they might trade.{*B*} -You can find a list of all the trades a villager is offering in the trading menu. A villager may modify or add to its trades whenever a player trades with it, although a trade might become temporarily disabled if it is used too frequently.{*B*} -Trades usually involve buying or selling a number of items for emeralds.{*B*} -If you do not have the items required for a trade, the items are shown in red.{*B*} - - - - - {*T3*}HOW TO PLAY : ENDER CHEST {*ETW*}{*B*}{*B*} -All Ender Chests in a world are linked. Items placed into an Ender Chest are accessible in any other. However, the contents of the Ender Chests are different for each player. This allows players to store items in any Ender Chest, and retrieve them from other Ender Chests in different positions in the world. - - - - - Farmer - - - - Librarian - - - - Priest - - - - Blacksmith - - - - Butcher - - - - Found in villages, villagers will offer to sell items to the player depending on their profession. - - - - Large Chest - - - - - You can also create Enchanted Books at the Enchantment Table, which can be used later at the Anvil to apply their enchantment to an item. - - - - - - Tripwire Hooks will also provide constant power to a circuit while something is triggering the string between them. - - - - - - Once tamed, a wolf will always have its collar on. The color of their collar can be changed by dying it. - - - - - Carrots and Potatoes are farmed by planting Carrots or Potatoes, and are ready for harvesting when the vegetable is visible above the ground. - - - - - Additionally, pigs can be saddled and then ridden by players. They are controlled by tempting them with a Carrot on a Stick. - - - - - - If necessary you can slowly move your minecart along using {*CONTROLLER_ACTION_MOVE*}. This helps to start the minecart by getting it onto a powered rail. - - - - - You cannot join this game as split-screen is only supported when in High Definition mode. Sign out all other players if you wish to join. - - - - Cure - - - - Acacia Wood - - - - Dark Oak Wood - - - - Acacia Planks - - - - Dark Oak Planks - - - - Acacia Wood Stairs - - - - Dark Oak Wood Stairs - - - - Acacia Wood Slab - - - - Dark Oak Wood Slab - - - - Dark Oak Wood Slab - - - - Iron Trapdoor - - - - Spruce Door - - - - Birch Door - - - - Jungle Door - - - - Acacia Door - - - - Dark Oak Door - - - - Spruce Fence - - - - Birch Fence - - - - Jungle Fence - - - - Acacia Fence - - - - Dark Oak Fence - - - - Spruce Fence Gate - - - - Birch Fence Gate - - - - Jungle Fence Gate - - - - Acacia Fence Gate - - - - Dark Oak Fence Gate - - - - Spruce Door - - - - Birch Door - - - - Jungle Door - - - - Acacia Door - - - - Dark Oak Door - - - Armor Stand - - - - Can be equipped to display armor and other decorative items such as mob heads. - - - - Rabbit - - - - A harmless creature. May drop a rabbit hide or a rabbit's foot when killed. - - - - Rabbit Hide - - - - Used in crafting leather. - - - - Rabbit's Foot - - - - Used as an ingredient for brewing potions. - - - - Raw Rabbit - - - - Restores 0.5{*ICON_SHANK_01*}, or can be cooked in a furnace. - - - - Cooked Rabbit - - - - Restores 2.5{*ICON_SHANK_01*}. Used to cook up some rabbit stew. - - - - Raw Mutton - - - - Restores 1{*ICON_SHANK_01*}, or can be cooked in a furnace. - - - - Cooked Mutton - - - - Restores 3{*ICON_SHANK_01*}. Created by cooking raw mutton in a furnace. - - - - Acacia Sapling - - - - Dark Oak Sapling - - - - Acacia Leaves - - - - Dark Oak Leaves - - - - Red Sandstone - - - - Red Sandstone Stairs - - - - Prismarine Crystal - - - - Sea Lantern - - - - Exit Minecraft - - - - Prismarine - - - - Dark Prismarine - - - - Prismarine Bricks - - - - Prismarine Shard - - - - Rare decorative stone that can be found in Ocean Monuments. Can be crafted from Prismarine shards. - - - - A rarer form of Prismarine that can be found in Ocean Monuments. Can be crafted with Prismarine shards and an Ink Sac. - - - - Decorative Prismarine brick that can be found in Ocean Monuments. Can be crafted from Prismarine shards. - - - - Obtained from Sea Lanterns or by defeating Guardians and Elder Guardians. Can be used in crafting Sea Lanterns. - - - - Dropped by Guardians and Elder Guardians. Can be used in crafting Prismarine and Sea Lanterns. - - - - Rabbit Stew - - - - Tall Grass - - - - Large Fern - - - - Lilac - - - - Rose Bush - - - - Peony - - - - Packed Ice - - - - Sunflower - - - - A solid unmeltable block of ice that can have objects placed on it. - - - - Red colored Sandstone. It is not influenced by gravity like normal Sand. - - - - Underwater light sources that can be found in Ocean Monuments. Can be crafted from Prismarine shards and Prismarine crystals. - - - - Rare decorative stone that can be found in Ocean Monuments. Can be crafted from Prismarine shards. - - - - Double tall grass that can sometimes drop seeds. - - - - Chiseled Red Sandstone - - - - Smooth Red Sandstone - - - - Podzol - - - - Coarse Dirt - - - - Similar to Dirt Blocks, but very good for growing mushrooms on. - - - - A special type of dirt that does not grow grass. - - - - Granite - - - - Polished Granite - - - - Andesite - - - - Polished Andesite - - - - Diorite - - - - Polished Diorite - - - - Can be mined with a pickaxe to collect granite. - - - - Can be crafted from granite for a polished look. - - - - Can be mined with a pickaxe to collect andesite. - - - - Can be crafted from andesite for a polished look. - - - - Can be mined with a pickaxe to collect diorite. - - - - Can be crafted from diorite for a polished look. - - - - Red Sand - - - - Wet Sponge - - - - Can be dried in a furnace, allowing the sponge to be reused. - - - - Raw Salmon - - - - Cooked Salmon - - - - Clownfish - - - - Pufferfish - - - - Restores 1{*ICON_SHANK_01*}, or can be cooked in a furnace. Can be fed to an ocelot to tame it. - - - - Restores 3{*ICON_SHANK_01*}. Created by cooking a raw salmon in a furnace. - - - - Restores 0.5{*ICON_SHANK_01*}. - - - - Restores 0.5{*ICON_SHANK_01*} however it is poisonous. Can also be used as an ingredient in brewing potions. - - - - Blue Orchid - - - - Allium - - - - Azure Bluet - - - - Red Tulip - - - - Orange Tulip - - - - White Tulip - - - - Pink Tulip - - - - Oxeye Daisy - - - - A common red flower that can be used to craft red dye. - - - - A rare blue flower that can be used to craft light blue dye. - - - - A rare magenta flower that can be used to craft magenta dye. - - - - A small white flower that can be used to craft light gray dye. - - - - A small red flower that can be used to craft red dye. - - - - A small orange flower that can be used to craft orange dye. - - - - A small white flower that can be used to craft light gray dye. - - - - A small pink flower that can be used to craft pink dye. - - - - A common white and yellow flower that can be used to craft light gray dye. - - - - A tall yellow flower that can be used to craft yellow dye. - - - - A tall purple flower that can be used to craft magenta dye. - - - - A tall fern that can sometimes drop seeds. - - - - A tall red flower that can be used to craft red dye. - - - - A tall green and pink flower that can be used to craft pink dye. - - - - Endermite - - - - Guardian - - - - Elder Guardian - - - - Written Book - - - - A book signed by the author (cannot be written in). - - - - Book and Quill - - - - A Book that can be written in. - - - - Next Page - - - - Previous Page - - - - Add Page - - - - Exit Book - - - - Are you sure you want to exit this book and the changes you've made? - - - - Lure - - - - Luck of the Sea - - - Red Sandstone Slab - - - Elytra - - - Taking Inventory - Open your inventory. - - Getting Wood - Punch a tree until a block of wood pops out. - - Benchmarking - Craft a Workbench with four blocks of Wooden Planks. - - Time to Mine! - Use Planks and Sticks to make a Pickaxe. - - Hot Topic - Construct a Furnace out of eight Cobblestone blocks. - - Acquire Hardware - Smelt an Iron Ingot. - - Time to Farm! - Make a Hoe. - - Bake Bread - Turn Wheat into Bread. - - The Lie - Bake a Cake using: Wheat, Sugar, Milk and Eggs. - - Getting an Upgrade - Construct a better pickaxe. - - Delicious Fish - Catch and cook Fish! - - On A Rail - Travel by Minecart to a point at least 500m in a single direction from where you started. - - Time to Strike! - Use Planks and Sticks to make a Sword. - - Monster Hunter - Attack and destroy a monster. - - Cow Tipper - Harvest some leather. - - When Pigs Fly - Use a Saddle to ride a Pig, and then have the Pig get hurt from fall damage while riding it. - - Leader of the Pack - Befriend five Wolves. - - MOAR Tools - Construct one type of each tool. - - Dispense With This - Construct a dispenser. - - Into The Nether - Construct a Nether Portal. - - Pork Chop - Cook and eat a Pork Chop. - - Passing the Time - Play for 100 days. - - Archer - Kill a Creeper with Arrows. - - Sniper Duel - Kill a Skeleton with an Arrow from more than 50 meters. - - DIAMONDS! - Acquire diamonds with your iron tools. - - Return to Sender - Destroy a Ghast with a Fireball. - - Into Fire - Relieve a Blaze of its rod. - - Local Brewery - Brew a potion. - - The End? - Enter an End Portal. - - The End. - Kill the Enderdragon. - - Enchanter - Construct an Enchantment Table. - - Overkill - Deal nine hearts of damage in a single hit. - - Librarian - Build some Bookshelves to improve your Enchantment Table. - - Adventuring Time - Discover all biomes. - - Repopulation - Breed two Cows with Wheat. - - Diamonds to you! - Throw diamonds to another player. - - The Haggler - Mine or purchase 30 Emeralds. - - Pot Planter - Craft and place a Flower pot. - - It's a Sign! - Craft and place a sign. - - Iron Belly - Stop starvation using rotten flesh. - - Have a Shearful Day - Use Shears to obtain Wool from a Sheep. - - Rainbow Collection - Gather all 16 colors of Wool. - - Stayin' Frosty - Swim in Lava while having the Fire Resistance effect. - - Chestful of Cobblestone - Mine 1,728 Cobblestone and place it in a Chest. - - Renewable Energy - Smelt Wood Trunks using Charcoal to make more Charcoal. - - Music to my Ears - Play a Music Disc in a Jukebox. - - Body Guard - Create an Iron Golem. - - Iron Man - Wear a full suit of Iron Armor. - - Zombie Doctor - Cure a Zombie Villager. - - Lion Tamer - Tame an ocelot. - - Hold {*CONTROLLER_VK_Y*} to view - - Classic Crafting - - - Restores 5{*ICON_SHANK_01*}. - - + + + New Downloadable Content is available! Access it from the Minecraft Store button on the Main Menu. + + + + You can change the look of your character with a Skin Pack from the Minecraft Store. Select 'Minecraft Store' on the Main Menu to see what's available. + + + + Alter the gamma settings to make the game brighter or darker. + + + + If you set the game difficulty to Peaceful, your health will automatically regenerate, and no monsters will come out at night! + + + + Feed a bone to a wolf to tame it. You can then make it sit or follow you. + + + + You can drop items when in the Inventory menu by moving the cursor off the menu and pressing{*CONTROLLER_VK_A*} + + + + Sleeping in a bed at night will fast forward the game to dawn, but all players in a multiplayer game need to sleep in beds at the same time. + + + + Harvest pork chops from pigs, and cook and eat them to regain health. + + + + Harvest leather from cows, and use it to make armor. + + + + If you have an empty bucket, you can fill it with milk from a cow, or water, or lava! + + + + Use a hoe to prepare areas of ground for planting. + + + + Spiders won't attack you during the day - unless you attack them. + + + + Digging soil or sand with a spade is faster than with your hand! + + + + Eating cooked pork chops gives more health than eating raw pork chops. + + + + Make some torches to light up areas at night. Monsters will avoid the areas around these torches. + + + + Get to destinations faster with a minecart and rail! + + + + Plant some saplings and they'll grow into trees. + + + + Pigmen won't attack you, unless you attack them. + + + + You can change your game spawn point and skip to dawn by sleeping in a bed. + + + + Hit those fireballs back at the Ghast! + + + + Building a portal will allow you to travel to another dimension - The Nether. + + + + Press{*CONTROLLER_VK_B*} to drop the item currently in your hand! + + + + Use the right tool for the job! + + + + If you can't find any coal for your torches, you can always make charcoal from trees in a furnace. + + + + Digging straight down or straight up is not a great idea. + + + + Bonemeal (crafted from a Skeleton bone) can be used as a fertilizer, and can make things grow instantly! + + + + Creepers explode when they get close to you! + + + + Obsidian is created when water hits a lava source block. + + + + Lava can take minutes to disappear COMPLETELY when the source block is removed. + + + + Cobblestone is resistant to Ghast fireballs, making it useful for guarding portals. + + + + Blocks that can be used as a light source will melt snow and ice. This includes torches, glowstone, and Jack-O-Lanterns. + + + + Take caution when building structures made of wool in open air, as lightning from thunderstorms can set wool on fire. + + + + A single bucket of lava can be used in a furnace to smelt 100 blocks. + + + + The instrument played by a note block depends on the material beneath it. + + + + Zombies and Skeletons can survive daylight if they are in water. + + + + Attacking a wolf will cause any wolves in the immediate vicinity to turn hostile and attack you. This trait is also shared by Zombie Pigmen. + + + + Wolves cannot enter the Nether. + + + + Wolves won't attack Creepers. + + + + Chickens lay an egg every 5 to 10 minutes. + + + + Obsidian can only be mined with a diamond pickaxe. + + + + Creepers are the easiest obtainable source of gunpowder. + + + + Placing two chests side by side will make one large chest. + + + + Tame wolves show their health with the position of their tail. Feed them meat to heal them. + + + + Cook cactus in a furnace to get green dye. + + + + Read the What's New section in the How To Play menus to see the latest update information about the game. + + + + Stackable fences are in the game now! + + + + Some animals will follow you if you have wheat in your hand. + + + + If an animal can't move more than 20 blocks in any direction, it won't despawn. + + + + Music by C418! + + + + Notch has over a million followers on twitter! + + + + Not all Swedish people have blonde hair. Some, like Jens from Mojang, even have ginger hair! + + + + There will be an update to this game eventually! + + + + Who is Notch? + + + + Mojang has more awards than staff! + + + + Some famous people play Minecraft! + + + + deadmau5 likes Minecraft! + + + + Do not look directly at the bugs. + + + + Creepers were born from a coding bug. + + + + Is it a chicken or is it a duck? + + + + Were you at Minecon? + + + + No-one at Mojang has ever seen junkboy's face. + + + + Did you know there's a Minecraft Wiki? + + + + Mojang's new office is cool! + + + + Minecon 2013 was in Orlando, Florida, USA! + + + + .party() was excellent! + + + + Always assume rumors are false, rather than assuming they're true! + + + + {*T3*}HOW TO PLAY : BASICS{*ETW*}{*B*}{*B*} +Minecraft is a game about placing blocks to build anything you can imagine. At night monsters come out, make sure to build a shelter before that happens.{*B*}{*B*} +Use{*CONTROLLER_ACTION_LOOK*} to look around.{*B*}{*B*} +Use{*CONTROLLER_ACTION_MOVE*} to move around.{*B*}{*B*} +Press{*CONTROLLER_ACTION_JUMP*} to jump.{*B*}{*B*} +Push{*CONTROLLER_ACTION_MOVE*} forward twice in rapid succession to sprint. While you hold {*CONTROLLER_ACTION_MOVE*} forward, the character will continue to sprint unless they run out of sprint time or the Food Bar has less than{*ICON_SHANK_03*}.{*B*}{*B*} +Hold{*CONTROLLER_ACTION_ACTION*} to mine and chop using your hand or whatever you are holding. You may need to craft a tool to mine some blocks.{*B*}{*B*} +If you are holding an item in your hand, use{*CONTROLLER_ACTION_USE*} to use that item, or press{*CONTROLLER_ACTION_DROP*} to drop that item. + + + + {*T3*}HOW TO PLAY : HUD{*ETW*}{*B*}{*B*} +The HUD shows information about your status; your health, your remaining oxygen when you are under water, your hunger level (you need to eat to replenish this), and your armor if you are wearing any. If you lose some health, but have a food bar with 9 or more{*ICON_SHANK_01*} in it, your health will automatically replenish. Eating food will replenish your food bar.{*B*} +The Experience Bar is also shown here, with a numeric value to show your Experience Level, and the bar indicating how many Experience Points are required to increase your Experience Level. Experience Points are gained by collecting the Experience Orbs dropped by mobs when they die, mining certain block types, breeding animals, fishing, and smelting ores in a furnace.{*B*}{*B*} +It also shows the items that are available to use. Use{*CONTROLLER_ACTION_LEFT_SCROLL*} and{*CONTROLLER_ACTION_RIGHT_SCROLL*} to change the item in your hand. + + + + {*T3*}HOW TO PLAY : INVENTORY{*ETW*}{*B*}{*B*} +Use{*CONTROLLER_ACTION_INVENTORY*} to view your inventory.{*B*}{*B*} +This screen shows items available for use in your hand, and all the other items that you are carrying. Your armor is also shown here.{*B*}{*B*} +Use{*CONTROLLER_MENU_NAVIGATE*} to move the pointer. Use{*CONTROLLER_VK_A*} to pick an item under the pointer. If there is more than one item here this will pick them all up, or you can use{*CONTROLLER_VK_X*} to pick up just half of them.{*B*}{*B*} +Move the item with the pointer over another space in the inventory and place it there using{*CONTROLLER_VK_A*}. With multiple items on the pointer, use{*CONTROLLER_VK_A*} to place them all, or{*CONTROLLER_VK_X*} to place just one.{*B*}{*B*} +If an item you are over is armor, you will be shown a tooltip to enable a quick move of this to the right armor slot in the inventory.{*B*}{*B*} +It is possible to change the color of your Leather Armor by dying it, you can do this in the inventory menu by holding the dye in your pointer, then pressing{*CONTROLLER_VK_X*} whilst the pointer is over the piece you wish to dye. + + + + + {*T3*}HOW TO PLAY : CHEST{*ETW*}{*B*}{*B*} +Once you have crafted a Chest, you can place this in the world and then use it with{*CONTROLLER_ACTION_USE*} to store items from your inventory.{*B*}{*B*} +Use the pointer to move items between your inventory and the chest.{*B*}{*B*} +Items in the chest will be stored there for you to swap back into your inventory again later. + + + + + {*T3*}HOW TO PLAY : LARGE CHEST{*ETW*}{*B*}{*B*} +Two chests placed next to each other will be combined to form a Large Chest. This can store even more items.{*B*}{*B*} +It is used in the same way as a normal chest. + + + + + {*T3*}HOW TO PLAY : CRAFTING{*ETW*}{*B*}{*B*} +In the Crafting interface, you can combine items from your inventory to create new types of items. Use{*CONTROLLER_ACTION_CRAFTING*} to open the crafting interface.{*B*}{*B*} +Scroll through the tabs at the top using{*CONTROLLER_VK_LB*} and{*CONTROLLER_VK_RB*} to select the type of item you wish to craft, then use{*CONTROLLER_MENU_NAVIGATE*} to select the item to craft.{*B*}{*B*} +The crafting area shows the items required to craft the new item. Press{*CONTROLLER_VK_A*} to craft the item and place it in your inventory. + + + + + {*T3*}HOW TO PLAY : CRAFTING TABLE{*ETW*}{*B*}{*B*} +You can craft larger items using a Crafting Table.{*B*}{*B*} +Place the table in the world and press{*CONTROLLER_ACTION_USE*} to use it.{*B*}{*B*} +Crafting on a table works in the same way as basic crafting, but you have a larger crafting area, and a more varied selection of items to craft. + + + + + {*T3*}HOW TO PLAY : FURNACE{*ETW*}{*B*}{*B*} +A Furnace allows you to change items by firing them. For example, you can turn iron ore into iron ingots in the furnace.{*B*}{*B*} +Place the furnace in the world and press{*CONTROLLER_ACTION_USE*} to use it.{*B*}{*B*} +You need to put some fuel into the bottom of the furnace, and the item to be fired in the top. The furnace will then fire up and start working.{*B*}{*B*} +When your items have been fired, you can move them from the output area into your inventory.{*B*}{*B*} +If an item you are over is an ingredient or fuel for the furnace, you will be shown tooltips to enable a quick move of this to the furnace. + + + + + {*T3*}HOW TO PLAY : DISPENSER{*ETW*}{*B*}{*B*} +A Dispenser is used to shoot out items. You will need to place a switch, for example a lever, next to the dispenser to trigger it.{*B*}{*B*} +To fill the dispenser with items press{*CONTROLLER_ACTION_USE*}, then move the items that you want to dispense from your inventory into the dispenser.{*B*}{*B*} +Now when you use the switch, the dispenser will shoot out an item. + + + + + {*T3*}HOW TO PLAY : BREWING{*ETW*}{*B*}{*B*} +Brewing potions requires a Brewing Stand, which can be built at a crafting table. Every potion starts off with a bottle of water, which is made by filling a Glass Bottle with water from a Cauldron, or a water source.{*B*} +A Brewing Stand has three slots for bottles, so can make three potions at the same time. One ingredient can be used over all three bottles, so always brew three potions at the same time to best use your resources.{*B*} +Putting a potion ingredient in the top position at the Brewing Stand will make a base potion after a short time. This doesn't have any effect by itself, but brewing another ingredient with this base potion will give you a potion with an effect.{*B*} +Once you have this potion you can add a third ingredient to make the effect last longer (using Redstone Dust), be more intense (using Glowstone Dust), or turn into a harmful potion (using a Fermented Spider Eye).{*B*} +You can also add gunpowder to any potion to turn it into a Splash Potion, which can then be thrown. The thrown Splash Potion will cause the potion effect to apply over the area it lands in.{*B*} + +The source ingredients for potions are :-{*B*}{*B*} +* {*T2*}Nether Wart{*ETW*}{*B*} +* {*T2*}Spider Eye{*ETW*}{*B*} +* {*T2*}Sugar{*ETW*}{*B*} +* {*T2*}Ghast Tear{*ETW*}{*B*} +* {*T2*}Blaze Powder{*ETW*}{*B*} +* {*T2*}Magma Cream{*ETW*}{*B*} +* {*T2*}Glistering Melon{*ETW*}{*B*} +* {*T2*}Redstone Dust{*ETW*}{*B*} +* {*T2*}Glowstone Dust{*ETW*}{*B*} +* {*T2*}Fermented Spider Eye{*ETW*}{*B*}{*B*} + +You'll need to experiment with combinations of ingredients in order to find out all the different potions you can make. + + + + + {*T3*}HOW TO PLAY : ENCHANTING{*ETW*}{*B*}{*B*} +The Experience Points collected when a mob dies, or when certain blocks are mined or smelted in a furnace, can be used to enchant some tools, weapons, armor and books.{*B*} +When a Sword, Bow, Axe, Pickaxe, Shovel, Armor or Book is placed in the slot below the book in the Enchantment Table, the three buttons to the right of the slot will display some enchantments and their Experience Levels costs.{*B*} +If you do not have enough Experience Levels to use some of these, the cost will appear in red, otherwise it will be shown in green.{*B*}{*B*} +The actual enchantment applied is randomly selected based on the cost displayed.{*B*}{*B*} +If the Enchantment Table is surrounded by Bookshelves (up to a maximum of 15 Bookshelves), with a one block gap between the Bookcase and the Enchantment Table, the potency of the enchantments will be increased, and arcane glyphs will be seen coming from the book on the Enchantment Table.{*B*}{*B*} +All the ingredients for an Enchantment Table can be found within the villages in a world, or by mining and cultivation of the world.{*B*}{*B*} +Enchanted Books are used at the Anvil to apply enchantments to items. This gives you more control over which enchantments you would like on your items.{*B*} + + + + + {*T3*}HOW TO PLAY : FARMING ANIMALS{*ETW*}{*B*}{*B*} +If you want to keep your animals in the one place, build a fenced area of less than 20x20 blocks and have your animals inside it. This ensures they will still be there when you come back to see them. + + + + + {*T3*}HOW TO PLAY : BREEDING ANIMALS{*ETW*}{*B*}{*B*} +The animals in Minecraft can breed, and will produce baby versions of themselves!{*B*} +To get the animals to breed, you will need to feed them with the right food to get them to go into 'Love Mode'.{*B*} +Feed Wheat to a cow, mooshroom or sheep, Carrots to a pig, Wheat Seeds or Nether Wart to a chicken, or any kind of meat to a wolf, and they'll start looking for another animal of the same species near them that is also in Love Mode.{*B*} +When two animals of the same species meet, and both are in Love Mode, they will kiss for a few seconds, and then a baby animal will appear. The baby animal will follow their parents for a while before growing into a full sized animal itself.{*B*} +After being in Love Mode, an animal will not be able to enter it again for about five minutes.{*B*} +There is a limit on the number of animals it is possible to have in a world, so you may find the animals don't breed when you have a lot of them. + + + + {*T3*}HOW TO PLAY : NETHER PORTAL{*ETW*}{*B*}{*B*} +A Nether Portal allows the player to travel between the Overworld and the Nether world. The Nether world can be used to fast-travel in the Overworld - traveling one block distance in the Nether is equivalent to traveling 3 blocks in the Overworld, so when you build a portal in the Nether world and exit through it, you will be 3 times further away from your entry point.{*B*}{*B*} +A minimum of 10 Obsidian blocks are required to build the portal, and the portal needs to be 5 blocks high by 4 blocks wide by 1 block deep. Once the portal frame is built, the space inside the frame needs to be set on fire to activate it. This can be done using the Flint and Steel item, or the Fire Charge item.{*B*}{*B*} +Examples of portal construction are shown in the picture to the right. + + + + + {*T3*}HOW TO PLAY : BANNING LEVELS{*ETW*}{*B*}{*B*} +If you find offensive content within a level you are playing, you can choose to add the level to your Banned Levels list. +If you would like to do this, bring up the Pause menu, then press{*CONTROLLER_VK_RB*} to select the Ban Level tooltip. +When you attempt to join this level in future, you will be notified that the level is in your Banned Levels list, and given the option to remove it from the list and continue into the level, or back out. + + + + {*T3*}HOW TO PLAY : HOST AND PLAYER OPTIONS{*ETW*}{*B*}{*B*} + +{*T1*}Game Options{*ETW*}{*B*} +When loading or creating a world, you can press the "More Options" button to enter a menu that allows more control over your game.{*B*}{*B*} + + {*T2*}Player vs Player{*ETW*}{*B*} + When enabled, players can inflict damage on other players. This option only affects Survival mode.{*B*}{*B*} + + {*T2*}Trust Players{*ETW*}{*B*} + When disabled, players joining the game are restricted in what they can do. They are not able to mine or use items, place blocks, use doors and switches, use containers, attack players or attack animals. You can change these options for a specific player using the in-game menu.{*B*}{*B*} + + {*T2*}Fire Spreads{*ETW*}{*B*} + When enabled, fire may spread to nearby flammable blocks. This option can also be changed from within the game.{*B*}{*B*} + + {*T2*}TNT Explodes{*ETW*}{*B*} + When enabled, TNT will explode when detonated. This option can also be changed from within the game.{*B*}{*B*} + + {*T2*}Host Privileges{*ETW*}{*B*} + When enabled, the host can toggle their ability to fly, disable exhaustion, and make themselves invisible from the in-game menu. {*DISABLES_ACHIEVEMENTS*}{*B*}{*B*} + + {*T2*}Daylight Cycle{*ETW*}{*B*} + When disabled, the time of day will not change.{*B*}{*B*} + + {*T2*}Keep Inventory{*ETW*}{*B*} + When enabled, players will keep their inventory when they die.{*B*}{*B*} + + {*T2*}Mob Spawning{*ETW*}{*B*} + When disabled, mobs will not spawn naturally.{*B*}{*B*} + + {*T2*}Mob Griefing{*ETW*}{*B*} + When disabled, prevents monsters and animals from changing blocks (for example, Creeper explosions won't destroy blocks and Sheep won't remove Grass) or picking up items.{*B*}{*B*} + + {*T2*}Mob Loot{*ETW*}{*B*} + When disabled, monsters and animals will not drop loot (for example, Creepers won't drop gunpowder).{*B*}{*B*} + + {*T2*}Tile Drops{*ETW*}{*B*} + When disabled, blocks will not drop items when destroyed (for example, Stone blocks won't drop Cobblestone).{*B*}{*B*} + + {*T2*}Natural Regeneration{*ETW*}{*B*} + When disabled, players will not regenerate health naturally.{*B*}{*B*} + +{*T1*}World Generation Options{*ETW*}{*B*} +When creating a new world there are some additional options.{*B*}{*B*} + + {*T2*}Generate Structures{*ETW*}{*B*} + When enabled, structures such as Villages and Strongholds will generate in the world.{*B*}{*B*} + + {*T2*}Superflat World{*ETW*}{*B*} + When enabled, a completely flat world will be generated in the Overworld and in the Nether.{*B*}{*B*} + + {*T2*}Bonus Chest{*ETW*}{*B*} + When enabled, a chest containing some useful items will be created near the player spawn point.{*B*}{*B*} + + {*T2*}Reset Nether{*ETW*}{*B*} + When enabled, the Nether will be re-generated. This is useful if you have an older save where Nether Fortresses were not present.{*B*}{*B*} + + {*T1*}In-Game Options{*ETW*}{*B*} + While in the game a number of options can be accessed by pressing {*BACK_BUTTON*} to bring up the in-game menu.{*B*}{*B*} + + {*T2*}Host Options{*ETW*}{*B*} + The host player, and any players set as moderators can access the "Host Option" menu. In this menu they can enable and disable fire spreading and TNT exploding.{*B*}{*B*} + +{*T1*}Player Options{*ETW*}{*B*} +To modify the privileges for a player, select their name and press{*CONTROLLER_VK_A*} to bring up the player privileges menu where you can use the following options.{*B*}{*B*} + + {*T2*}Can Build And Mine{*ETW*}{*B*} + This option is only available when "Trust Players" is turned off. When this option is enabled, the player is able to interact with the world as normal. When disabled the player will not be able to place or destroy blocks, or interact with many items and blocks.{*B*}{*B*} + + {*T2*}Can Use Doors and Switches{*ETW*}{*B*} + This option is only available when "Trust Players" is turned off. When this option is disabled, the player will not be able to use doors and switches.{*B*}{*B*} + + {*T2*}Can Open Containers{*ETW*}{*B*} + This option is only available when "Trust Players" is turned off. When this option is disabled, the player will not be able to open containers, such as chests.{*B*}{*B*} + + {*T2*}Can Attack Players{*ETW*}{*B*} + This option is only available when "Trust Players" is turned off. When this option is disabled the player will not be able to cause damage to other players.{*B*}{*B*} + + {*T2*}Can Attack Animals{*ETW*}{*B*} + This option is only available when "Trust Players" is turned off. When this option is disabled the player will not be able to cause damage to animals.{*B*}{*B*} + + {*T2*}Moderator{*ETW*}{*B*} + When this option is enabled, the player is able to change privileges for other players (except the host) if "Trust Players" is turned off, kick players and they can enable and disable fire spreading and TNT exploding.{*B*}{*B*} + + {*T2*}Kick Player{*ETW*}{*B*} + {*KICK_PLAYER_DESCRIPTION*}{*B*}{*B*} + +{*T1*}Host Player Options{*ETW*}{*B*} +If "Host Privileges" is enabled the host player can modify some privileges for themselves. To modify the privileges for a player, select their name and press{*CONTROLLER_VK_A*} to bring up the player privileges menu where you can use the following options.{*B*}{*B*} + + {*T2*}Can Fly{*ETW*}{*B*} + When this option is enabled, the player is able to fly. This option is only relevant to Survival mode, as flying is enabled for all players in Creative mode.{*B*}{*B*} + + {*T2*}Disable Exhaustion{*ETW*}{*B*} + This option only affects Survival mode. When enabled, physical activities (walking/sprinting/jumping etc.) do not decrease the food bar. However, if the player becomes injured, the food bar will slowly decrease while the player is healing.{*B*}{*B*} + + {*T2*}Invisible{*ETW*}{*B*} + When this option is enabled, the player is not visible to other players and is invulnerable.{*B*}{*B*} + + {*T2*}Can Teleport{*ETW*}{*B*} + This allows the player to move players or themselves to other players in the world. + + + + + Next Page + + + + Previous Page + + + + Basics + + + + HUD + + + + Inventory + + + + Chests + + + + Crafting + + + + Furnace + + + + Dispenser + + + + Farming Animals + + + + Breeding Animals + + + + Brewing + + + + Enchantment + + + + Nether Portal + + + + Multiplayer + + + + Sharing Screenshots + + + + Banning Levels + + + + Creative Mode + + + + Host and Player Options + + + + Trading + + + + Anvil + + + + The End + + + + {*T3*}HOW TO PLAY : THE END{*ETW*}{*B*}{*B*} +The End is another dimension in the game, which is reached through an active End Portal. The End Portal can be found in a Stronghold, which is deep underground in the Overworld.{*B*} +To activate the End Portal, you'll need to put an Eye of Ender into any End Portal Frame without one.{*B*} +Once the portal is active, jump in to it to go to The End.{*B*}{*B*} +In The End you will meet the Ender Dragon, a fierce and powerful enemy, along with many Enderman, so you will have to be well prepared for the battle before going there!{*B*}{*B*} +You'll find that there are Ender Crystals on top of eight Obsidian spikes that the Ender Dragon uses to heal itself, +so the first step in the battle is to destroy each of these.{*B*} +The first few can be reached with arrows, but the later ones are protected by an Iron Fence cage, and you will need to build up to them.{*B*}{*B*} +While you are doing this, the Ender Dragon will be attacking you by flying at you and spitting Ender acid balls!{*B*} +If you approach the Egg Podium in the centre of the spikes, the Ender Dragon will fly down and attack you and this is where you can really do some damage to it!{*B*} +Avoid the acid breath, and target the Ender Dragon's eyes for the best results. If possible, bring some friends in to The End to help you with the battle!{*B*}{*B*} +Once you are in The End, your friends will be able to see the location of the End Portal within the Stronghold on their maps, +so they can easily join you. + + + + + Sprint + + + + What's New + + + + {*T3*}Changes and Additions{*ETW*}{*B*}{*B*} +- Added new items - Hardened Clay, Stained Clay, Block of Coal, Hay Bale, Activator Rail, Block of Redstone, Daylight Sensor, Dropper, Hopper, Minecart with Hopper, Minecart with TNT, Redstone Comparator, Weighted Pressure Plate, Beacon, Trapped Chest, Firework Rocket, Firework Star, Nether Star, Lead, Horse Armor, Name Tag, Horse Spawn Egg{*B*} +- Added new Mobs - Wither, Wither Skeletons, Witches, Bats, Horses, Donkeys and Mules{*B*} +- Added new terrain generation features - Witch Huts.{*B*} +- Added Beacon interface.{*B*} +- Added Horse interface.{*B*} +- Added Hopper interface.{*B*} +- Added Fireworks - Fireworks interface is accessible from the Crafting Table when you have the ingredients to craft a Firework Star or Firework Rocket.{*B*} +- Added 'Adventure Mode' - You can only break blocks with the correct tools.{*B*} +- Added lots of new sounds.{*B*} +- Mobs, items and projectiles can now pass through portals.{*B*} +- Repeaters can now be locked by powering their sides with another Repeater.{*B*} +- Zombies and Skeletons can now spawn with different weapons and armor.{*B*} +- New death messages.{*B*} +- Name mobs with a Name Tag, and rename containers to change the title when the menu is open.{*B*} +- Bonemeal no longer instantly grows everything to full size, and instead randomly grows in stages.{*B*} +- A Redstone signal describing the contents of Chests, Brewing Stands, Dispensers and Jukeboxes can be detected by placing a Redstone Comparator directly against them.{*B*} +- Dispensers can face in any direction.{*B*} +- Eating a Golden Apple gives the player extra "absorption" health for a short period.{*B*} +- The longer you remain in an area the harder the monsters that spawn in that area will be.{*B*} + + + + + {*ETB*}Welcome back! You may not have noticed but your Minecraft has just been updated.{*B*}{*B*} +There are lots of new features for you and friends to play with so here’s just a few highlights. Have a read and then go and have fun!{*B*}{*B*} +{*T1*}New Items{*ETB*} - Hardened Clay, Stained Clay, Block of Coal, Hay Bale, Activator Rail, Block of Redstone, Daylight Sensor, Dropper, Hopper, Minecart with Hopper, Minecart with TNT, Redstone Comparator, Weighted Pressure Plate, Beacon, Trapped Chest, Firework Rocket, Firework Star, Nether Star, Lead, Horse Armor, Name Tag, Horse Spawn Egg{*B*}{*B*} +{*T1*}New Mobs{*ETB*} - Wither, Wither Skeletons, Witches, Bats, Horses, Donkeys and Mules{*B*}{*B*} +{*T1*}New Features{*ETB*} - Tame and ride a horse, craft fireworks and put on a show, name animals and monsters with a Name Tag, create more advanced Redstone circuits, and new Host Options to help control what guests to your world can do!{*B*}{*B*} +{*T1*}New Tutorial World{*ETB*} – Learn how to use the old and new features in the Tutorial World. See if you can find all the secret Music Discs hidden in the world!{*B*}{*B*} + + + + + Horses + + + + {*T3*}HOW TO PLAY : HORSES{*ETW*}{*B*}{*B*} +Horses and Donkeys are found mainly in open plains. Mules are the offspring of a Donkey and a Horse, but are infertile themselves.{*B*} +All adult Horses, Donkeys and Mules can be ridden. However only Horses can be armored, and only Mules and Donkeys may be equipped with saddlebags for transporting items.{*B*}{*B*} +Horses, Donkeys and Mules must be tamed before they can be used. A horse is tamed by attempting to ride it, and managing to stay on the horse while it attempts to throw the rider off.{*B*} +When Love Hearts appear around the horse, it is tame, and will no longer attempt to throw the player off. To steer a horse, the player must equip the horse with a Saddle.{*B*}{*B*} +Saddles can be bought from villagers or found inside Chests hidden in the world.{*B*} +Tame Donkeys and Mules can be given saddlebags by attaching a Chest. These saddlebags can then be accessed whilst riding or sneaking.{*B*}{*B*} +Horses and Donkeys (but not Mules) can be bred like other animals using Golden Apples or Golden Carrots.{*B*} +Foals will grow into adult horses over time, although feeding them Wheat or Hay will speed this up.{*B*} + + + + + Beacons + + + + {*T3*}HOW TO PLAY : BEACONS{*ETW*}{*B*}{*B*} +Active Beacons project a bright beam of light into the sky and grant powers to nearby players.{*B*} +They are crafted with Glass, Obsidian and Nether Stars, which can be obtained by defeating the Wither.{*B*}{*B*} +Beacons must be placed so that they are in sunlight during the day. Beacons must be placed on Pyramids of Iron, Gold, Emerald or Diamond.{*B*} +The material the Beacon is placed on has no effect on the power of the Beacon.{*B*}{*B*} +In the Beacon menu you can select one primary power for your Beacon. The more tiers your pyramid has the more powers you will have to choose from.{*B*} +A Beacon on a pyramid with at least four tiers also gives the option of either the Regeneration secondary power or a stronger primary power.{*B*}{*B*} +To set the powers of your Beacon you must sacrifice an Emerald, Diamond, Gold or Iron Ingot in the payment slot.{*B*} +Once set, the powers will emanate from the Beacon indefinitely.{*B*} + + + + + Fireworks + + + + {*T3*}HOW TO PLAY : FIREWORKS{*ETW*}{*B*}{*B*} +Fireworks are decorative items that can be launched by hand or from Dispensers. They are crafted using Paper, Gunpowder and optionally a number of Firework Stars.{*B*} +The colors, fade, shape, size, and effects (such as trails and twinkle) of Firework Stars can be customized by including additional ingredients when crafting.{*B*}{*B*} +To craft a Firework place Gunpowder and Paper in the 3x3 crafting grid that is shown above your inventory.{*B*} +You can optionally place multiple Firework Stars in the crafting grid to add them to the Firework.{*B*} +Filling more slots in the crafting grid with Gunpowder will increase the height at which all the Firework Stars will explode.{*B*}{*B*} +You can then take the crafted Firework out of the output slot.{*B*}{*B*} +Firework Stars can be crafted by placing Gunpowder and Dye into the crafting grid.{*B*} + - The Dye will set the color of the explosion of the Firework Star.{*B*} + - The shape of the Firework Star is set by adding either a Fire Charge, Gold Nugget, Feather or Mob Head.{*B*} + - A trail or a twinkle can be added using Diamonds or Glowstone Dust.{*B*}{*B*} +After a Firework Star has been crafted, you can set the fade color of the Firework Star by crafting it with Dye. + + + + + Hoppers + + + + {*T3*}HOW TO PLAY : HOPPERS{*ETW*}{*B*}{*B*} +Hoppers are used to insert or remove items from containers, and to automatically pick up items thrown into them.{*B*} +They can affect Brewing Stands, Chests, Dispensers, Droppers, Minecarts with Chests, Minecarts with Hoppers, as well as other Hoppers.{*B*}{*B*} +Hoppers will continuously attempt to suck items out of a suitable container placed above them. They will also attempt to insert stored items into an output container.{*B*} +If a Hopper is powered by Redstone it will become inactive and stop both sucking and inserting items.{*B*}{*B*} +A Hopper points in the direction it tries to output items. To make a Hopper point to a particular block, place the Hopper against that block whilst sneaking.{*B*} + + + + + Droppers + + + + {*T3*}HOW TO PLAY : DROPPERS{*ETW*}{*B*}{*B*} +When powered by Redstone, Droppers will drop a single random item contained within them onto the ground. Use {*CONTROLLER_ACTION_USE*} to open the Dropper and then you can load the Dropper with items from your inventory.{*B*} +If the Dropper is facing a Chest or another type of Container, the item will be placed into that instead. Long chains of Droppers can be constructed to transport items over a distance, but for this to work they will have to be alternately powered on and off. + + + + + Deals more damage than by hand. + + + + Used to dig dirt, grass, sand, gravel and snow faster than by hand. Shovels are required to dig snowballs. + + + + Required to mine stone-related blocks and ore. + + + + Used to chop wood-related blocks faster than by hand. + + + + Used to till dirt and grass blocks to prepare for crops. + + + + Wooden doors are activated by using, hitting them or with Redstone. + + + + Iron doors can only be opened by Redstone, buttons or switches. + + + + NOT USED + + + + NOT USED + + + + NOT USED + + + + NOT USED + + + + Gives the user 1 Armor when worn. + + + + Gives the user 3 Armor when worn. + + + + Gives the user 2 Armor when worn. + + + + Gives the user 1 Armor when worn. + + + + Gives the user 2 Armor when worn. + + + + Gives the user 5 Armor when worn. + + + + Gives the user 4 Armor when worn. + + + + Gives the user 1 Armor when worn. + + + + Gives the user 2 Armor when worn. + + + + Gives the user 6 Armor when worn. + + + + Gives the user 5 Armor when worn. + + + + Gives the user 2 Armor when worn. + + + + Gives the user 2 Armor when worn. + + + + Gives the user 5 Armor when worn. + + + + Gives the user 3 Armor when worn. + + + + Gives the user 1 Armor when worn. + + + + Gives the user 3 Armor when worn. + + + + Gives the user 8 Armor when worn. + + + + Gives the user 6 Armor when worn. + + + + Gives the user 3 Armor when worn. + + + + A shiny ingot which can be used to craft tools made from this material. Created by smelting ore in a furnace. + + + + Allows ingots, gems, or dyes to be crafted into placeable blocks. Can be used as an expensive building block or compact storage of the ore. + + + + Used to send an electrical charge when stepped on by a player, an animal, or a monster. Wooden Pressure Plates can also be activated by dropping something on them. + + + + Used for compact staircases. + + + + Used for making long staircases. Two slabs placed on top of each other will create a normal-sized double slab block. + + + + Used for making long staircases. Two slabs placed on top of each other will create a normal-sized double slab block. + + + + Used to create light. Torches also melt snow and ice. + + + + Used as a building material and can be crafted into many things. Can be crafted from any form of wood. + + + + Used as a building material. Is not influenced by gravity like normal Sand. + + + + Used as a building material. + + + + Used to craft torches, arrows, signs, ladders, fences and as handles for tools and weapons. + + + + Used to forward time from any time at night to morning if all the players in the world are in bed, and changes the spawn point of the player. +The colors of the bed are always the same, regardless of the colors of wool used. + + + + Allows you to craft a more varied selection of items than the normal crafting. + + + + Allows you to smelt ore, create charcoal and glass, and cook fish and porkchops. + + + + Stores blocks and items inside. Place two chests side by side to create a larger chest with double the capacity. + + + + Used as a barrier that cannot be jumped over. Counts as 1.5 blocks high for players, animals and monsters, but 1 block high for other blocks. + + + + Used to climb vertically. + + + + Activated by using, hitting them or with redstone. They function as normal doors, but are a one by one block and lay flat on the ground. + + + + Shows text entered by you or other players. + + + + Used to create brighter light than torches. Melts snow/ice and can be used underwater. + + + + Used to cause explosions. Activated after placing by igniting with Flint and Steel item, or with an electrical charge. + + + + Used to hold mushroom stew. You keep the bowl when the stew has been eaten. + + + + Used to hold and transport water, lava and milk. + + + + Used to hold and transport water. + + + + Used to hold and transport lava. + + + + Used to hold and transport milk. + + + + Used to create fire, ignite TNT, and open a portal once it has been built. + + + + Used to catch fish. + + + + Displays positions of the Sun and Moon. + + + + Points to your start point. + + + + Will create an image of an area explored while held. This can be used for path-finding. + + + + When used becomes a map of the part of the world that you are in, and gets filled in as you explore. + + + + Allows for ranged attacks by using arrows. + + + + Used as ammunition for bows. + + + + Dropped by the Wither, used in crafting Beacons. + + + + When activated, create colorful explosions. The color, effect, shape and fade are determined by the Firework Star used when the Firework is created. + + + + Used to determine the color, effect and shape of a Firework. + + + + Used in Redstone circuits to maintain, compare, or subtract signal strength, or to measure certain block states. + + + + Is a type of Minecart that acts as a moving TNT block. + + + + Is a block that outputs a Redstone signal based on sunlight (or lack of sunlight). + + + + Is a special type of Minecart that functions similarly to a Hopper. It will collect items lying on tracks and from containers above it. + + + + A special type of Armor that can be equipped to a horse. Provides 5 Armor. + + + + A special type of Armor that can be equipped to a horse. Provides 7 Armor. + + + + A special type of Armor that can be equipped to a horse. Provides 11 Armor. + + + + Used to leash mobs to the player or Fence posts. + + + + Used to name mobs in the world. + + + + Restores 2.5{*ICON_SHANK_01*}. + + + + Restores 1{*ICON_SHANK_01*}. Can be used 6 times. + + + + Restores 1{*ICON_SHANK_01*}. + + + + Restores 1{*ICON_SHANK_01*}. + + + + Restores 3{*ICON_SHANK_01*}. + + + + Restores 1{*ICON_SHANK_01*}, or can be cooked in a furnace. Eating this can cause you to be poisoned. + + + + Restores 3{*ICON_SHANK_01*}. Created by cooking raw chicken in a furnace. + + + + Restores 1.5{*ICON_SHANK_01*}, or can be cooked in a furnace. + + + + Restores 4{*ICON_SHANK_01*}. Created by cooking raw beef in a furnace. + + + + Restores 1.5{*ICON_SHANK_01*}, or can be cooked in a furnace. + + + + Restores 4{*ICON_SHANK_01*}. Created by cooking a raw porkchop in a furnace. + + + + Restores 1{*ICON_SHANK_01*}, or can be cooked in a furnace. Can be fed to an Ocelot to tame it. + + + + Restores 2.5{*ICON_SHANK_01*}. Created by cooking a raw fish in a furnace. + + + + Restores 2{*ICON_SHANK_01*}, and can be crafted into a golden apple. + + + + Restores 2{*ICON_SHANK_01*}, and regenerates health for 4 seconds. Crafted from an apple and gold nuggets. + + + + Restores 2{*ICON_SHANK_01*}. Eating this can cause you to be poisoned. + + + + Used in the cake recipe, and as an ingredient for brewing potions. + + + + Used to send an electrical charge by being turned on or off. Stays in the on or off state until pressed again. + + + + Constantly sends an electrical charge, or can be used as a receiver/transmitter when connected to the side of a block. +Can also be used for low-level lighting. + + + + Used in Redstone circuits as repeater, a delayer, and/or a diode. + + + + Used to send an electrical charge by being pressed. Stays activated for approximately a second before shutting off again. + + + + Used to hold and shoot out items in a random order when given a Redstone charge. + + + + Plays a note when triggered. Hit it to change the pitch of the note. Placing this on top of different blocks will change the type of instrument. + + + + Used to guide minecarts. + + + + When powered, accelerates minecarts that pass over it. When unpowered, causes minecarts to stop on it. + + + + Functions like a Pressure Plate (sends a Redstone signal when powered) but can only be activated by a Minecart. + + + + Used to transport you, an animal, or a monster along rails. + + + + Used to transport goods along rails. + + + + Will move along rails and can push other minecarts when coal is put in it. + + + + Used to travel in water more quickly than swimming. + + + + Collected from sheep, and can be colored with dyes. + + + + Used as a building material and can be colored with dyes. This recipe is not recommended because Wool can be easily obtained from Sheep. + + + + Used as a dye to create black wool. + + + + Used as a dye to create green wool. + + + + Used as a dye to create brown wool, as an ingredient in cookies, or to grow Cocoa Pods. + + + + Used as a dye to create silver wool. + + + + Used as a dye to create yellow wool. + + + + Used as a dye to create red wool. + + + + Used to instantly grow crops, trees, tall grass, huge mushrooms and flowers, and can be used in dye recipes. + + + + Used as a dye to create pink wool. + + + + Used as a dye to create orange wool. + + + + Used as a dye to create lime wool. + + + + Used as a dye to create gray wool. + + + + Used as a dye to create light gray wool. +(Note: light gray dye can also be made by combining gray dye with bone meal, letting you make four light gray dyes from every ink sac instead of three.) + + + + Used as a dye to create light blue wool. + + + + Used as a dye to create cyan wool. + + + + Used as a dye to create purple wool. + + + + Used as a dye to create magenta wool. + + + + Used as dye to create Blue Wool. + + + + Plays Music Discs. + + + + Use these to create very strong tools, weapons or armor. + + + + Used to create brighter light than torches. Melts snow/ice and can be used underwater. + + + + Used to create books and maps. + + + + Can be used to create bookshelves or enchanted to make Enchanted Books. + + + + Allows the creation of more powerful enchantments when placed around the Enchantment Table. + + + + Used as decoration. + + + + Can be mined with an iron pickaxe or better, then smelted in a furnace to produce gold ingots. + + + + Can be mined with a stone pickaxe or better, then smelted in a furnace to produce iron ingots. + + + + Can be mined with a pickaxe to collect coal. + + + + Can be mined with a stone pickaxe or better to collect lapis lazuli. + + + + Can be mined with an iron pickaxe or better to collect diamonds. + + + + Can be mined with an iron pickaxe or better to collect redstone dust. + + + + Can be mined with a pickaxe to collect cobblestone. + + + + Causes players and mobs to bounce when they jump on it. + + + + Collected using a shovel. Can be used for construction. + + + + Can be planted and it will eventually grow into a tree. + + + + This cannot be broken. + + + + Sets fire to anything that touches it. Can be collected in a bucket. + + + + Collected using a shovel. Can be smelted into glass using the furnace. Is affected by gravity if there is no other tile underneath it. + + + + Collected using a shovel. Sometimes produces flint when dug up. Is affected by gravity if there is no other tile underneath it. + + + + Chopped using an axe, and can be crafted into planks or used as a fuel. + + + + Created in a furnace by smelting sand. Can be used for construction, but will break if you try to mine it. + + + + Mined from stone using a pickaxe. Can be used to construct a furnace or stone tools. + + + + Baked from clay in a furnace. + + + + Can be baked into bricks in a furnace. + + + + When broken drops clay balls which can be baked into bricks in a furnace. + + + + A compact way to store snowballs. + + + + Can be dug with a shovel to create snowballs. + + + + Sometimes produces wheat seeds when broken. + + + + Can be crafted into a dye. + + + + Can be crafted with a bowl to make stew. + + + + Can only be mined with a diamond pickaxe. Is produced by the meeting of water and still lava, and is used to build a portal. + + + + Spawns monsters into the world. + + + + Is placed on the ground to carry an electrical charge. When brewed with a potion it will increase the duration of the effect. + + + + When fully grown, crops can be harvested to collect wheat. + + + + Ground that has been prepared ready to plant seeds. + + + + Can be cooked in a furnace to create a green dye. + + + + Can be crafted to create sugar. + + + + Can be worn as a helmet or crafted with a torch to create a Jack-O-Lantern. It is also the main ingredient in Pumpkin Pie. + + + + Burns forever if set alight. + + + + Slows the movement of anything walking over it. + + + + Standing in the portal allows you to pass between the Overworld and the Nether. + + + + Used as a fuel in a furnace, or crafted to make a torch. + + + + Collected by killing a spider, and can be crafted into a Bow or Fishing Rod, or placed on the ground to create Tripwire. + + + + Collected by killing a chicken, and can be crafted into an arrow. + + + + Collected by killing a Creeper, and can be crafted into TNT or used as an ingredient for brewing potions. + + + + Can be planted in farmland to grow crops. Make sure there's enough light for the seeds to grow! + + + + Harvested from crops, and can be used to craft food items. + + + + Collected by digging gravel, and can be used to craft a flint and steel. + + + + When used on a pig it allows you to ride the pig. The pig can then be steered using a Carrot on a Stick. + + + + Collected by digging snow, and can be thrown. + + + + Collected by killing a cow, and can be crafted into armor or used to make Books. + + + + Collected by killing a Slime, and used as an ingredient for brewing potions or crafted to make Sticky Pistons. + + + + Dropped randomly by chickens, and can be crafted into food items. + + + + Collected by mining Glowstone, and can be crafted to make Glowstone blocks again or brewed with a potion to increase the potency of the effect. + + + + Collected by killing a Skeleton. Can be crafted into bone meal. Can be fed to a wolf to tame it. + + + + Collected by getting a Skeleton to kill a Creeper. Can be played in a jukebox. + + + + An invisible, but solid block. + + + + Extinguishes fire and helps crops grow. Can be collected in a bucket. + + + + When broken sometimes drops a sapling which can then be replanted to grow into a tree. + + + + Found in dungeons, can be used for construction and decoration. + + + + Used to obtain wool from sheep and harvest leaf blocks. + + + + When powered (using a button, a lever, a pressure plate, a redstone torch, or redstone with any one of these), a piston extends if it can and pushes blocks. + + + + When powered (using a button, a lever, a pressure plate, a redstone torch, or redstone with any one of these), a piston extends if it can and pushes blocks. When it retracts it pulls back the block touching the extended part of the piston. + + + + Made from Stone blocks, and commonly found in Strongholds. + + + + Used as a barrier, similar to fences. + + + + Similar to a door, but used primarily with fences. + + + + Can be crafted from Melon Slices. + + + + Transparent blocks that can be used as an alternative to Glass Blocks. + + + + Can be planted to grow pumpkins. + + + + Can be planted to grow melons. + + + + Dropped by Enderman when they die. When thrown, the player will be teleported to the position the Ender Pearl lands at, and will lose some health. + + + + A block of dirt with grass growing on top. Collected using a shovel. Can be used for construction. + + + + Can be used for construction and decoration. + + + + Slows movement when walking through it. Can be destroyed using shears to collect string. + + + + Spawns a Silverfish when destroyed. May also spawn Silverfish if nearby to another Silverfish being attacked. + + + + Grows over time when placed. Can be collected using shears. Can be climbed like a ladder. + + + + Slippery when walked on. Turns into water if above another block when destroyed. Melts if close enough to a light source or when placed in The Nether. + + + + Can be used as decoration. + + + + Used in potion brewing, and for locating Strongholds. Dropped by Blazes who tend to be found near or in Nether Fortresses. + + + + Used in potion brewing. Dropped by Ghasts when they die. + + + + Dropped by Zombie Pigmen when they die. Zombie Pigmen can be found in the Nether. Used as an ingredient for brewing potions. + + + + Used in potion brewing. This can be found naturally growing in Nether Fortresses. It can also be planted on Soul Sand. + + + + When used, can have various effects, depending on what it is used on. + + + + Can be filled with water, and used as the starting ingredient for a potion in the Brewing Stand. + + + + This is a poisonous food and brewing item. Dropped when a Spider or Cave Spider is killed by a player. + + + + Used in potion brewing, mainly to create potions with a negative effect. + + + + Used in potion brewing, or crafted with other items to make Eye of Ender or Magma Cream. + + + + Used in potion brewing. + + + + Used for making Potions and Splash Potions. + + + + Filled with water by rain or with a bucket of water, and can then be used to fill Glass Bottles with water. + + + + When thrown, will show the direction to an End Portal. When twelve of these are placed in the End Portal Frames, the End Portal will be activated. + + + + Used in potion brewing. + + + + Similar to Grass Blocks, but very good for growing mushrooms on. + + + + Floats on water, and can be walked on. + + + + Used to build Nether Fortresses. Immune to Ghast's fireballs. + + + + Used in Nether Fortresses. + + + + Found in Nether Fortresses, and will drop Nether Wart when broken. + + + + This allows players to enchant Swords, Pickaxes, Axes, Shovels, Bows and Armor, using the player's Experience Points. + + + + This can be activated using twelve Eye of Ender, and will allow the player to travel to The End dimension. + + + + Used to form an End Portal. + + + + A block type found in The End. It has a very high blast resistance, so is useful for building with. + + + + This block is created by the defeat of the Dragon in The End. + + + + When thrown, it drops Experience Orbs which increase your experience points when collected. + + + + Useful for setting things on fire, or for indiscriminately starting fires when fired from a Dispenser. + + + + These are similar to a display case, and will display the item or block placed in it. + + + + When thrown can spawn a creature of the type indicated. + + + + Used for making long staircases. Two slabs placed on top of each other will create a normal-sized double slab block. + + + + Used for making long staircases. Two slabs placed on top of each other will create a normal-sized double slab block. + + + + Created by smelting Netherrack in a furnace. Can be crafted into Nether Brick blocks. + + + + When powered they emit light. + + + + Can be farmed to collect Cocoa Beans. + + + + Mob Heads can be placed as a decoration, or worn as a mask in the helmet slot. + + + + Used to execute commands. + + + + Projects a beam of light into the sky and can provide Status Effects to nearby players. + + + + Stores blocks and items inside. Place two chest side by side to create a larger chest with double capacity. The trapped chest also creates a Redstone charge when opened. + + + + Provides a Redstone charge. The charge will be stronger if more items are on the plate. + + + + Provides a Redstone charge. The charge will be stronger if more items are on the plate. Requires more weight than the light plate. + + + + Used as a redstone power source. Can be crafted back into Redstone. + + + + Used to catch items or to transfer items into and out of containers. + + + + A type of rail that can enable or disable Minecarts with Hoppers and trigger Minecarts with TNT. + + + + Used to hold and drop items, or push items into another container, when given a Redstone charge. + + + + Colorful blocks crafted by dyeing Hardened clay. + + + + Can be fed to Horses, Donkeys or Mules to heal up to 10 Hearts. Speeds up the growth of foals. + + + + Created by smelting Clay in a furnace. + + + + Crafted from glass and a dye. + + + + Crafted from Stained Glass + + + + A compact way of storing Coal. Can be used as fuel in a Furnace. + + + + Squid + + + + Drops ink sacs when killed. + + + + Cow + + + + Drops leather when killed. Can also be milked with a bucket. + + + + Sheep + + + + Drops wool when sheared (if it has not already been sheared). Can be dyed to make its wool a different color. + + + + Chicken + + + + Drops feathers when killed, and also randomly lays eggs. + + + + Pig + + + + Drops porkchops when killed. Can be ridden by using a saddle. + + + + Wolf + + + + Docile until attacked, when they will attack you back. Can be tamed using bones which causes the wolf to follow you around and attack anything that attacks you. + + + + Creeper + + + + Explodes if you get too close! + + + + Skeleton + + + + Fires arrows at you. Drops arrows when killed. + + + + Spider + + + + Attacks you when you are close to it. Can climb walls. Drops string when killed. + + + + Zombie + + + + Attacks you when you are close to it. + + + + Zombie Pigman + + + + Initially docile, but will attack in groups if you attack one. + + + + Ghast + + + + Fires flaming balls at you that explode on contact. + + + + Slime + + + + Split into smaller Slimes when damaged. + + + + Enderman + + + + Will attack you if you look at it. Can also move blocks around. + + + + Silverfish + + + + Attracts nearby hidden Silverfish when attacked. Hides in stone blocks. + + + + Cave Spider + + + + Has a venomous bite. + + + + Mooshroom + + + + Makes mushroom stew when used with a bowl. Drops mushrooms and becomes a normal cow when sheared. + + + + Snow Golem + + + + The Snow Golem can be created by players using snow blocks and a pumpkin. They will throw snowballs at their creators enemies. + + + + Ender Dragon + + + + This is a large black dragon found in The End. + + + + Blaze + + + + These are enemies found in the Nether, mostly inside Nether Fortresses. They will drop Blaze Rods when killed. + + + + Magma Cube + + + + These can be found in The Nether. Similar to Slimes, they will break up into smaller versions when killed. + + + + Villager + + + + Ocelot + + + + These can be found in Jungles. They can be tamed by feeding them Raw Fish. You will need to let the Ocelot approach you though, since any sudden movements will scare it away. + + + + Iron Golem + + + + Appear in Villages to protect them, and can be created using Iron Blocks and Pumpkins. + + + + Bat + + + + These flying creatures are found in caverns or other large enclosed spaces. + + + + Witch + + + + These enemies can be found in swamps and attack you by throwing Potions. They drop Potions when killed. + + + + Horse + + + + These animals can be tamed and can then be ridden. + + + + Donkey + + + + These animals can be tamed and can then be ridden. They can have a chest attached. + + + + Mule + + + + Born when a Horse and a Donkey breed. These animals can be tamed and can then be ridden and carry chests. + + + + Zombie Horse + + + + Skeleton Horse + + + + Wither + + + + These are crafted from Wither Skulls and Soul Sand. They fire exploding skulls at you. + + + + Explosives Animator + + + + Concept Artist + + + + Number Crunching and Statistics + + + + Bully Coordinator + + + + Original Design and Code by + + + + Project Manager/Producer + + + + Rest of Mojang Office + + + + Lead Game Programmer Minecraft PC + + + + Ninja Coder + + + + CEO + + + + White Collar Worker + + + + Customer Support + + + + Office DJ + + + + Designer/Programmer Minecraft - Pocket Edition + + + + Developer + + + + Chief Architect + + + + Art Developer + + + + Game Crafter + + + + Director of Fun + + + + Music and Sounds + + + + Programming + + + + Art + + + + QA + + + + Executive Producer + + + + Lead Producer + + + + Producer + + + + Test Lead + + + + Lead Tester + + + + Design Team + + + + Development Team + + + + Release Management + + + + Director, XBLA Publishing + + + + Business Development + + + + Portfolio Director + + + + Product Manager + + + + Marketing + + + + Community Manager + + + + Europe Localization Team + + + + Redmond Localization Team + + + + Asia Localization Team + + + + User Research Team + + + + MGS Central Teams + + + + Milestone Acceptance Tester + + + + Special Thanks + + + + Test Manager + + + + Senior Test Lead + + + + SDET + + + + Project STE + + + + Additional STE + + + + Test Associates + + + + Jon KÃ¥gström + + + + Tobias Möllstam + + + + Risë Lugo + + + + Wooden Sword + + + + Stone Sword + + + + Iron Sword + + + + Diamond Sword + + + + Golden Sword + + + + Wooden Shovel + + + + Stone Shovel + + + + Iron Shovel + + + + Diamond Shovel + + + + Golden Shovel + + + + Wooden Pickaxe + + + + Stone Pickaxe + + + + Iron Pickaxe + + + + Diamond Pickaxe + + + + Golden Pickaxe + + + + Wooden Axe + + + + Stone Axe + + + + Iron Axe + + + + Diamond Axe + + + + Golden Axe + + + + Wooden Hoe + + + + Stone Hoe + + + + Iron Hoe + + + + Diamond Hoe + + + + Golden Hoe + + + + Oak Door + + + + Iron Door + + + + Chain Helmet + + + + Chain Chestplate + + + + Chain Leggings + + + + Chain Boots + + + + Leather Cap + + + + Iron Helmet + + + + Diamond Helmet + + + + Golden Helmet + + + + Leather Tunic + + + + Iron Chestplate + + + + Diamond Chestplate + + + + Golden Chestplate + + + + Leather Pants + + + + Iron Leggings + + + + Diamond Leggings + + + + Golden Leggings + + + + Leather Boots + + + + Iron Boots + + + + Diamond Boots + + + + Golden Boots + + + + Iron Ingot + + + + Gold Ingot + + + + Bucket + + + + Water Bucket + + + + Lava Bucket + + + + Flint and Steel + + + + Apple + + + + Bow + + + + Arrow + + + + Coal + + + + Charcoal + + + + Diamond + + + + Stick + + + + Bowl + + + + Mushroom Stew + + + + String + + + + Feather + + + + Gunpowder + + + + Seeds + + + + Wheat + + + + Bread + + + + Flint + + + + Raw Porkchop + + + + Cooked Porkchop + + + + Painting + + + + Golden Apple + + + + Sign + + + + Minecart + + + + Saddle + + + + Redstone + + + + Snowball + + + + Boat + + + + Leather + + + + Milk Bucket + + + + Brick + + + + Clay + + + + Sugar Canes + + + + Paper + + + + Book + + + + Slimeball + + + + Minecart with Chest + + + + Minecart with Furnace + + + + Egg + + + + Compass + + + + Fishing Rod + + + + Clock + + + + Glowstone Dust + + + + Raw Fish + + + + Cooked Fish + + + + Dye Powder + + + + Ink Sac + + + + Rose Red + + + + Cactus Green + + + + Cocoa Beans + + + + Lapis Lazuli + + + + Purple Dye + + + + Cyan Dye + + + + Light Gray Dye + + + + Gray Dye + + + + Pink Dye + + + + Lime Dye + + + + Dandelion Yellow + + + + Light Blue Dye + + + + Magenta Dye + + + + Orange Dye + + + + Bone Meal + + + + Bone + + + + Sugar + + + + Cake + + + + Bed + + + + Redstone Repeater + + + + Cookie + + + + Map + + + + Empty Map + + + + Music Disc - "13" + + + + Music Disc - "cat" + + + + Music Disc - "blocks" + + + + Music Disc - "chirp" + + + + Music Disc - "far" + + + + Music Disc - "mall" + + + + Music Disc - "mellohi" + + + + Music Disc - "stal" + + + + Music Disc - "strad" + + + + Music Disc - "ward" + + + + Music Disc - "11" + + + + Music Disc - "where are we now" + + + + Shears + + + + Pumpkin Seeds + + + + Melon Seeds + + + + Raw Chicken + + + + Cooked Chicken + + + + Raw Beef + + + + Steak + + + + Rotten Flesh + + + + Ender Pearl + + + + Melon Slice + + + + Blaze Rod + + + + Ghast Tear + + + + Gold Nugget + + + + Nether Wart + + + + {*splash*}{*prefix*}Potion {*postfix*} + + + + Glass Bottle + + + + Water Bottle + + + + Spider Eye + + + + Fermented Spider Eye + + + + Blaze Powder + + + + Magma Cream + + + + Brewing Stand + + + + Cauldron + + + + Eye of Ender + + + + Glistering Melon + + + + Bottle o' Enchanting + + + + Fire Charge + + + + Fire Charge (Charcoal) + + + + Fire Charge (Coal) + + + + Item Frame + + + + Spawn {*CREATURE*} + + + + Nether Brick + + + + Skull + + + + Skeleton Skull + + + + Wither Skeleton Skull + + + + Zombie Head + + + + Head + + + + %s's Head + + + + Creeper Head + + + + Nether Star + + + + Firework Rocket + + + + Firework Star + + + + Redstone Comparator + + + + Minecart with TNT + + + + Minecart with Hopper + + + + Iron Horse Armor + + + + Gold Horse Armor + + + + Diamond Horse Armor + + + + Lead + + + + Name Tag + + + + Stone + + + + Slime Block + + + + Grass Block + + + + Dirt + + + + Cobblestone + + + + Oak Planks + + + + Spruce Planks + + + + Birch Planks + + + + Jungle Planks + + + + Planks (any type) + + + + Sapling + + + + Oak Sapling + + + + Spruce Sapling + + + + Birch Sapling + + + + Jungle Tree Sapling + + + + Bedrock + + + + Barrier + + + + Water + + + + Lava + + + + Sand + + + + Sandstone + + + + Gravel + + + + Gold Ore + + + + Iron Ore + + + + Coal Ore + + + + Wood + + + + Oak Wood + + + + Spruce Wood + + + + Birch Wood + + + + Jungle Wood + + + + Oak + + + + Spruce + + + + Birch + + + + Leaves + + + + Oak Leaves + + + + Spruce Leaves + + + + Birch Leaves + + + + Jungle Leaves + + + + Sponge + + + + Glass + + + + Wool + + + + Black Wool + + + + Red Wool + + + + Green Wool + + + + Brown Wool + + + + Blue Wool + + + + Purple Wool + + + + Cyan Wool + + + + Light Gray Wool + + + + Gray Wool + + + + Pink Wool + + + + Lime Wool + + + + Yellow Wool + + + + Light Blue Wool + + + + Magenta Wool + + + + Orange Wool + + + + White Wool + + + + Dandelion + + + + Poppy + + + + Mushroom + + + + Block of Gold + + + + A compact way of storing Gold. + + + + A compact way of storing Iron. + + + + Block of Iron + + + + Stone Slab + + + + Stone Slab + + + + Sandstone Slab + + + + Oak Wood Slab + + + + Cobblestone Slab + + + + Bricks Slab + + + + Stone Bricks Slab + + + + Oak Wood Slab + + + + Spruce Wood Slab + + + + Birch Wood Slab + + + + Jungle Wood Slab + + + + Nether Brick Slab + + + + Bricks + + + + TNT + + + + Bookshelf + + + + Moss Stone + + + + Obsidian + + + + Torch + + + + Torch (Coal) + + + + Torch (Charcoal) + + + + Fire + + + + Monster Spawner + + + + Oak Wood Stairs + + + + Chest + + + + Redstone Dust + + + + Diamond Ore + + + + Block of Diamond + + + + A compact way of storing Diamonds. + + + + Crafting Table + + + + Crops + + + + Farmland + + + + Furnace + + + + Sign + + + + Oak Door + + + + Ladder + + + + Rail + + + + Powered Rail + + + + Detector Rail + + + + Stone Stairs + + + + Lever + + + + Pressure Plate + + + + Iron Door + + + + Redstone Ore + + + + Redstone Torch + + + + Button + + + + Snow + + + + Ice + + + + Cactus + + + + Clay + + + + Sugar Cane + + + + Jukebox + + + + Oak Fence + + + + Pumpkin + + + + Jack-O-Lantern + + + + Netherrack + + + + Soul Sand + + + + Glowstone + + + + Portal + + + + Lapis Lazuli Ore + + + + Lapis Lazuli Block + + + + A compact way of storing Lapis Lazuli. + + + + Dispenser + + + + Note Block + + + + Cake + + + + Bed + + + + Web + + + + Tall Grass + + + + Dead Bush + + + + Diode + + + + Locked Chest + + + + Trapdoor + + + + Wool (any color) + + + + Piston + + + + Sticky Piston + + + + Silverfish Block + + + + Stone Bricks + + + + Mossy Stone Bricks + + + + Cracked Stone Bricks + + + + Chiseled Stone Bricks + + + + Mushroom + + + + Mushroom + + + + Iron Bars + + + + Glass Pane + + + + Melon + + + + Pumpkin Stem + + + + Melon Stem + + + + Vines + + + + Oak Fence Gate + + + + Brick Stairs + + + + Stone Brick Stairs + + + + Silverfish Stone + + + + Silverfish Cobblestone + + + + Silverfish Stone Brick + + + + Mycelium + + + + Lily Pad + + + + Nether Brick + + + + Nether Brick Fence + + + + Nether Brick Stairs + + + + Nether Wart + + + + Enchantment Table + + + + Brewing Stand + + + + Cauldron + + + + End Portal + + + + End Portal Frame + + + + End Stone + + + + Dragon Egg + + + + Shrub + + + + Fern + + + + Sandstone Stairs + + + + Spruce Wood Stairs + + + + Birch Wood Stairs + + + + Jungle Wood Stairs + + + + Redstone Lamp + + + + Cocoa + + + + Skull + + + + Command Block + + + + Beacon + + + + Trapped Chest + + + + Weighted Pressure Plate (Light) + + + + Weighted Pressure Plate (Heavy) + + + + Redstone Comparator + + + + Daylight Sensor + + + + Block of Redstone + + + + Hopper + + + + Activator Rail + + + + Dropper + + + + Stained Clay + + + + Hay Bale + + + + Hardened Clay + + + + Block of Coal + + + + Black Stained Clay + + + + Red Stained Clay + + + + Green Stained Clay + + + + Brown Stained Clay + + + + Blue Stained Clay + + + + Purple Stained Clay + + + + Cyan Stained Clay + + + + Light Gray Stained Clay + + + + Gray Stained Clay + + + + Pink Stained Clay + + + + Lime Stained Clay + + + + Yellow Stained Clay + + + + Light Blue Stained Clay + + + + Magenta Stained Clay + + + + Orange Stained Clay + + + + White Stained Clay + + + + Stained Glass + + + + Black Stained Glass + + + + Red Stained Glass + + + + Green Stained Glass + + + + Brown Stained Glass + + + + Blue Stained Glass + + + + Purple Stained Glass + + + + Cyan Stained Glass + + + + Light Gray Stained Glass + + + + Gray Stained Glass + + + + Pink Stained Glass + + + + Lime Stained Glass + + + + Yellow Stained Glass + + + + Light Blue Stained Glass + + + + Magenta Stained Glass + + + + Orange Stained Glass + + + + White Stained Glass + + + + Stained Glass Pane + + + + Black Stained Glass Pane + + + + Red Stained Glass Pane + + + + Green Stained Glass Pane + + + + Brown Stained Glass Pane + + + + Blue Stained Glass Pane + + + + Purple Stained Glass Pane + + + + Cyan Stained Glass Pane + + + + Light Gray Stained Glass Pane + + + + Gray Stained Glass Pane + + + + Pink Stained Glass Pane + + + + Lime Stained Glass Pane + + + + Yellow Stained Glass Pane + + + + Light Blue Stained Glass Pane + + + + Magenta Stained Glass Pane + + + + Orange Stained Glass Pane + + + + White Stained Glass Pane + + + + Small Ball + + + + Large Ball + + + + Star-shaped + + + + Creeper-shaped + + + + Burst + + + + Unknown Shape + + + + Black + + + + Red + + + + Green + + + + Brown + + + + Blue + + + + Purple + + + + Cyan + + + + Light Gray + + + + Gray + + + + Pink + + + + Lime + + + + Yellow + + + + Light Blue + + + + Magenta + + + + Orange + + + + White + + + + Custom + + + + Fade to + + + + Twinkle + + + + Trail + + + + Flight Duration: + + + + Current Controls + + + + Layout + + + + Move/Sprint + + + + Look + + + + Pause + + + + Jump + + + + Jump/Fly Up + + + + Inventory + + + + Cycle Held Item + + + + Action + + + + Use + + + + Crafting + + + + Drop + + + + Sneak + + + + Sneak/Fly Down + + + + Change Camera Mode + + + + Players/Invite + + + + Movement (When Flying) + + + + Layout 1 + + + + Layout 2 + + + + Layout 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {*B*}Press{*CONTROLLER_VK_A*} to continue. + + + + {*B*}Press{*CONTROLLER_VK_A*} to start the tutorial.{*B*} +Press{*CONTROLLER_VK_B*} if you think you are ready to play on your own. + + + + Minecraft is a game about placing blocks to build anything you can imagine. +At night monsters come out, make sure to build a shelter before that happens. + + + + Use{*CONTROLLER_ACTION_LOOK*} to look up, down and around. + + + + Use{*CONTROLLER_ACTION_MOVE*} to move around. + + + + To sprint, push{*CONTROLLER_ACTION_MOVE*} forward twice quickly. While you hold{*CONTROLLER_ACTION_MOVE*} forward, the character will continue to sprint unless they run out of sprint time or food. + + + + Press{*CONTROLLER_ACTION_JUMP*} to jump. + + + + Hold{*CONTROLLER_ACTION_ACTION*} to mine and chop using your hand or whatever you are holding. You may need to craft a tool to mine some blocks... + + + + Hold{*CONTROLLER_ACTION_ACTION*} to chop down 4 blocks of wood (tree trunks).{*B*}When a block breaks you can pick it up by standing near to the floating item that appears, causing it to appear in your inventory. + + + + Press{*CONTROLLER_ACTION_CRAFTING*} to open the crafting interface. + + + + As you collect and craft more items, your inventory will fill up.{*B*} +Press{*CONTROLLER_ACTION_INVENTORY*} to open the inventory. + + + + As you move around, mine and attack, you will deplete your food bar{*ICON_SHANK_01*}. Sprinting and sprint jumping use a lot more food than walking and jumping normally. + + + + If you lose some health, but have a food bar with 9 or more{*ICON_SHANK_01*} in it, your health will automatically replenish. Eating food will replenish your food bar. + + + + With a food item in your hand, hold{*CONTROLLER_ACTION_USE*} to eat it and replenish your food bar. You cannot eat if your food bar is full. + + + + Your food bar is low, and you have lost some health. Eat the steak in your inventory to replenish your food bar and start healing.{*ICON*}364{*/ICON*} + + + + The wood that you have collected can be crafted into planks. Open the crafting interface to craft them.{*PlanksIcon*} + + + + A lot of crafting can involve multiple steps. Now that you have some planks there are more items that you can craft. Create a crafting table.{*CraftingTableIcon*} + + + + To make collecting blocks faster you can build tools designed for the job. Some tools have a handle made of sticks. Craft some sticks now.{*SticksIcon*} + + + + Use{*CONTROLLER_ACTION_LEFT_SCROLL*} and{*CONTROLLER_ACTION_RIGHT_SCROLL*} to change the current held item. + + + + Use{*CONTROLLER_ACTION_USE*} to use items, interact with objects and place some items. Items that have been placed can be picked up again by mining them with the right tool. + + + + With the crafting table selected, point the crosshair where you want it and use{*CONTROLLER_ACTION_USE*} to place a crafting table. + + + + Point the crosshair at the crafting table and press{*CONTROLLER_ACTION_USE*} to open it. + + + + A shovel helps dig soft blocks, like dirt and snow, faster. As you collect more materials you can craft tools that work faster and last longer. Create a wooden shovel.{*WoodenShovelIcon*} + + + + An axe helps chop wood and wooden tiles, faster. As you collect more materials you can craft tools that work faster and last longer. Create a wooden axe.{*WoodenHatchetIcon*} + + + + A pickaxe helps dig hard blocks, like stone and ore, faster. As you collect more materials you can craft tools that work faster and last longer, and allow you to mine harder materials. Create a wooden pickaxe.{*WoodenPickaxeIcon*} + + + + Open the container + + + + Night time can approach quickly, and it is dangerous to be outside unprepared. You can craft armor and weapons, but it is sensible to have a safe shelter. + + + + Nearby there is an abandoned Miner's shelter that you can complete to be safe overnight. + + + + You will need to collect the resources to complete the shelter. Walls and roof can be made of any tile type, but you will want to create a door, some windows and lighting. + + + + Use your pickaxe to mine some stone blocks. Stone blocks will produce cobblestone when mined. If you collect 8 cobblestone blocks you can build a furnace. You may need to dig through some dirt to reach the stone, so use your shovel for this.{*StoneIcon*} + + + + You have collected enough cobblestone to build a furnace. Use your crafting table to create one. + + + + Use{*CONTROLLER_ACTION_USE*} to place the furnace in the world, and then open it. + + + + Use the furnace to create some charcoal. If you are waiting for it to finish how about using the time to collect more materials to finish the shelter? + + + + Use the furnace to create some glass. If you are waiting for it to finish how about using the time to collect more materials to finish the shelter? + + + + A good shelter will have a door so that you can easily go in and out without having to mine and replace the walls. Craft a wooden door now.{*WoodenDoorIcon*} + + + + Use{*CONTROLLER_ACTION_USE*} to place the door. You can use{*CONTROLLER_ACTION_USE*} to open and close a wooden door in the world. + + + + It can get very dark at night, so you will want some lighting inside your shelter so that you can see. Craft a torch now from sticks and charcoal using the crafting interface.{*TorchIcon*} + + + + You have completed the first part of the tutorial. + + + + {*B*} +Press{*CONTROLLER_VK_A*} to continue with the tutorial.{*B*} +Press{*CONTROLLER_VK_B*} if you think you are ready to play on your own. + + + + This is your inventory. It shows items available for use in your hand, and all the other items that you are carrying. Your armor is also shown here. + + + + {*B*} +Press{*CONTROLLER_VK_A*} to continue.{*B*} +Press{*CONTROLLER_VK_B*} if you already know how to use the inventory. + + + + Use{*CONTROLLER_MENU_NAVIGATE*} to move the pointer. Use{*CONTROLLER_VK_A*} to pick an item under the pointer. +If there is more than one item here this will pick them all up, or you can use{*CONTROLLER_VK_X*} to pick up just half of them. + + + + Move this item with the pointer over another space in the inventory and place it down using{*CONTROLLER_VK_A*}. +With multiple items on the pointer, use{*CONTROLLER_VK_A*} to place them all, or{*CONTROLLER_VK_X*} to place just one. + + + + If you move the pointer outside the edge of the interface with an item on the pointer, you can drop the item. + + + + If you want more information about an item, move the pointer over the item and press{*CONTROLLER_ACTION_MENU_PAGEDOWN*} . + + + + Press{*CONTROLLER_VK_B*} now to exit the inventory. + + + + This is the creative mode inventory. It shows items available for use in your hand, and all the other items that you can choose from. + + + + {*B*} +Press{*CONTROLLER_VK_A*} to continue.{*B*} +Press{*CONTROLLER_VK_B*} if you already know how to use the creative mode inventory. + + + + Use{*CONTROLLER_MENU_NAVIGATE*} to move the pointer. +When on the item list, use{*CONTROLLER_VK_A*} to pick an item under the pointer, and use{*CONTROLLER_VK_Y*} to pick up a full stack of that item. + + + + The pointer will automatically move over a space in the use row. You can place it down using{*CONTROLLER_VK_A*}. Once you have placed the item, the pointer will return to the item list where you can select another item. + + + + If you move the pointer outside the edge of the interface with an item on the pointer, you can drop the item into the world. To clear all items in the quick select bar, press{*CONTROLLER_VK_X*}. + + + + Scroll through the Group Type tabs at the top using{*CONTROLLER_VK_LB*} and{*CONTROLLER_VK_RB*} to select the group type of the item you wish to pickup. + + + + If you want more information about an item, move the pointer over the item and press{*CONTROLLER_ACTION_MENU_PAGEDOWN*} . + + + + Press{*CONTROLLER_VK_B*} now to exit the creative mode inventory. + + + + This is the crafting interface. This interface allows you to combine the items you've collected to make new items. + + + + {*B*}Press{*CONTROLLER_VK_A*} to continue.{*B*} +Press{*CONTROLLER_VK_B*} if you already know how to craft. + + + + {*B*} +Press{*CONTROLLER_VK_X*} to show the item description. + + + + {*B*} +Press{*CONTROLLER_VK_X*} to show the ingredients required to make the current item. + + + + {*B*} +Press{*CONTROLLER_VK_X*} to show the inventory again. + + + + Scroll through the Group Type tabs at the top using{*CONTROLLER_VK_LB*} and{*CONTROLLER_VK_RB*} to select the group type of the item you wish to craft, then use{*CONTROLLER_MENU_NAVIGATE*} to select the item to craft. + + + + The crafting area shows the items you require in order to craft the new item. Press{*CONTROLLER_VK_A*} to craft the item and place it in your inventory. + + + + You can craft a larger selection of items using a crafting table. Crafting on a table works in the same way as basic crafting, but you have a larger crafting area allowing more combinations of ingredients. + + + + The bottom right part of the crafting interface shows your inventory. This area can also show a description of the currently selected item, and the ingredients required to craft it. + + + + The description of the currently selected item is now displayed. The description can give you an idea of what the item can be used for. + + + + The list of ingredients required to craft the selected item are now displayed. + + + + The wood that you have collected can be crafted into planks. Select the planks icon and press{*CONTROLLER_VK_A*} to create them.{*PlanksIcon*} + + + + Now you have built a crafting table you should place it in the world to enable you to build a larger selection of items.{*B*} +Press{*CONTROLLER_VK_B*} now to exit the crafting interface. + + + + Press{*CONTROLLER_VK_LB*} and{*CONTROLLER_VK_RB*} to change to the group type of the items you wish to craft. Select the tools group.{*ToolsIcon*} + + + + Press{*CONTROLLER_VK_LB*} and{*CONTROLLER_VK_RB*} to change to the group type of the items you wish to craft. Select the structures group.{*StructuresIcon*} + + + + Use{*CONTROLLER_MENU_NAVIGATE*} to change to the item you wish to craft. Some items have multiple versions depending on the materials used. Select the wooden shovel.{*WoodenShovelIcon*} + + + + A lot of crafting can involve multiple steps. Now that you have some planks there are more items that you can craft. Use{*CONTROLLER_MENU_NAVIGATE*} to change to the item you wish to craft. Select the crafting table.{*CraftingTableIcon*} + + + + With the tools you have built you are off to a great start, and are able to collect a variety of different materials more efficiently.{*B*} +Press{*CONTROLLER_VK_B*} now to exit the crafting interface. + + + + Some items can not be created using the crafting table, but require a furnace. Craft a furnace now.{*FurnaceIcon*} + + + + Place the furnace you have crafted in the world. You will want to put this inside your shelter.{*B*} +Press{*CONTROLLER_VK_B*} now to exit the crafting interface. + + + + This is the furnace interface. A furnace allows you to change items by firing them. For example, you can turn iron ore into iron ingots in the furnace. + + + + {*B*} +Press{*CONTROLLER_VK_A*} to continue.{*B*} +Press{*CONTROLLER_VK_B*} if you already know how to use a furnace. + + + + You need to put some fuel into the bottom slot of the furnace, and the item to be changed in the top slot. The furnace will then fire up and start working, putting the result in the right-hand slot. + + + + Many wooden items can be used as fuels, but not everything burns for the same time. You may also discover other items in the world that can be used as a fuel. + + + + When your items have been fired, you can move them from the output area into your inventory. You should experiment with different ingredients to see what you can make. + + + + If you use wood as the ingredient then you can make charcoal. Put some fuel in the furnace and wood in the ingredient slot. It can take some time for the furnace to create the charcoal, so feel free to do something else and come back to check the progress. + + + + Charcoal can be used as a fuel, as well as being crafted into a torch with a stick. + + + + Placing sand in the ingredient slot allows you to make glass. Create some glass blocks to use as windows in your shelter. + + + + This is the brewing interface. You can use this to create potions that have a variety of different effects. + + + + {*B*} +Press{*CONTROLLER_VK_A*} to continue.{*B*} +Press{*CONTROLLER_VK_B*} if you already know how to use the brewing stand. + + + + You brew potions by placing an ingredient in the top slot, and a potion or water bottle in the bottom slots (up to 3 can be brewed at one time). Once a valid combination is entered the brewing process will start and create the potion after a short time. + + + + All potions start with a Water Bottle. Most potions are created by first using a Nether Wart to make an Awkward Potion, and will require at least one more ingredient to make the final potion. + + + + Once you have a potion you can modify its effects. Adding Redstone Dust increases the duration of its effect and adding Glowstone Dust can make its effect more powerful. + + + + Adding Fermented Spider Eye corrupts the potion and can turn it into a potion with the opposite effect, and adding Gunpowder turns the potion into a Splash Potion which can be thrown to apply its affect to a nearby area. + + + + Create a Potion of Fire Resistance by first adding Nether Wart to a Water Bottle, and then adding Magma Cream. + + + + Press{*CONTROLLER_VK_B*} now to exit the brewing interface. + + + + In this area there is a Brewing Stand, a Cauldron and a chest full of items for brewing. + + + + {*B*} +Press{*CONTROLLER_VK_A*} to learn more about brewing and potions.{*B*} +Press{*CONTROLLER_VK_B*} if you already know about brewing and potions. + + + + The first step in brewing a potion is to create a Water Bottle. Take a Glass Bottle from the chest. + + + + You can fill a glass bottle from a Cauldron that has water in it, or from a block of water. Fill your glass bottle now by pointing at a water source and pressing{*CONTROLLER_ACTION_USE*}. + + + + If a cauldron becomes empty, you can refill it with a Water Bucket. + + + + Use the Brewing Stand to create a Potion of Fire Resistance. You will need a Water Bottle, Nether Wart and Magma Cream. + + + + With a potion in your hand, hold{*CONTROLLER_ACTION_USE*} to use it. For a normal potion you will drink it and apply the effect to yourself, and for a Splash potion you will throw it and apply the effect to creatures near where it hits. +Splash potions can be created by adding gunpowder to normal potions. + + + + Use your Potion of Fire Resistance on yourself. + + + + Now that you are resistant to fire and lava, you should see if there are places you can get to that you couldn't before. + + + + This is the enchanting interface which you can use to add enchantments to weapons, armor and some tools. + + + + {*B*} +Press{*CONTROLLER_VK_A*} to learn more about the enchanting interface.{*B*} +Press{*CONTROLLER_VK_B*} if you already know about the enchanting interface. + + + + To enchant an item, first place it in the enchanting slot. Weapons, armor and some tools can be enchanted to add special effects such as improved damage resistance or increasing the number of items produced when mining a block. + + + + When an item is placed in the enchanting slot, the buttons on the right will change to show a selection of random enchantments. + + + + The number on the button represents the cost in experience levels to apply that enchantment to the item. If you do not have a high enough level the button will be disabled. + + + + Select an enchantment and press{*CONTROLLER_VK_A*} to enchant the item. This will decrease your experience level by the cost of the enchantment. + + + + Although the enchantments are all random, some of the better enchantments are only available when you have a high experience level and have lots of bookcases around the Enchantment Table to increase its power. + + + + In this area there is an Enchantment Table and some other items to help you learn about enchanting. + + + + {*B*} +Press{*CONTROLLER_VK_A*} to learn more about enchanting.{*B*} +Press{*CONTROLLER_VK_B*} if you already know about enchanting. + + + + Using an Enchantment Table allows you to add special effects such as increasing the number of items produced when mining a block, or improved damage resistance for weapons, armor and some tools. + + + + Placing bookcases around the Enchantment Table increases its power and allows access to higher level enchantments. + + + + Enchanting items costs Experience Levels, which can be built up by collecting Experience Orbs which are produced by killing monsters and animals, mining ores, breeding animals, fishing and smelting/cooking some things in a furnace. + + + + You can also build experience levels using a Bottle O' Enchanting, which, when thrown, creates Experience Orbs around where it lands. These orbs can then be collected. + + + + In the chests in this area you can find some enchanted items, Bottles O' Enchanting, and some items that have yet to be enchanted for you to experiment with at the Enchantment Table. + + + + You are now riding in a minecart. To exit the minecart, point the cursor at it and press{*CONTROLLER_ACTION_USE*} .{*MinecartIcon*} + + + + {*B*} +Press{*CONTROLLER_VK_A*} to learn more about minecarts.{*B*} +Press{*CONTROLLER_VK_B*} if you already know about minecarts. + + + + A minecart runs on rails. You can also craft a powered minecart with a furnace and a minecart with a chest in it.{*RailIcon*} + + + + You can also craft powered rails, which take power from redstone torches and circuits to accelerate the cart. These can be connected to switches, levers and pressure plates to make complex systems.{*PoweredRailIcon*} + + + + You are now sailing a boat. To exit the boat, point the cursor at it and press{*CONTROLLER_ACTION_USE*} .{*BoatIcon*} + + + + {*B*} +Press{*CONTROLLER_VK_A*} to learn more about boats.{*B*} +Press{*CONTROLLER_VK_B*} if you already know about boats. + + + + A boat allows you to travel quicker over water. You can steer it using{*CONTROLLER_ACTION_MOVE*} and{*CONTROLLER_ACTION_LOOK*}.{*BoatIcon*} + + + + You are now using a fishing rod. Press{*CONTROLLER_ACTION_USE*} to use it.{*FishingRodIcon*} + + + + {*B*} +Press{*CONTROLLER_VK_A*} to learn more about fishing.{*B*} +Press{*CONTROLLER_VK_B*} if you already know about fishing. + + + + Press{*CONTROLLER_ACTION_USE*} to cast your line and start fishing. Press{*CONTROLLER_ACTION_USE*} again to reel in the fishing line.{*FishingRodIcon*} + + + + If you wait until the float sinks below the surface of the water before reeling in you can catch a fish. Fish can be eaten raw, or cooked by a furnace, to restore health.{*FishIcon*} + + + + As with many other tools a fishing rod has a fixed number of uses. Those uses are not limited to catching fish though. You should experiment with it to see what else can be caught or activated...{*FishingRodIcon*} + + + + This is a bed. Press{*CONTROLLER_ACTION_USE*} while pointing at it at night to sleep through the night and awake in the morning.{*ICON*}355{*/ICON*} + + + + {*B*} +Press{*CONTROLLER_VK_A*} to learn more about beds.{*B*} +Press{*CONTROLLER_VK_B*} if you already know about beds. + + + + A bed should be placed in a safe, well-lit place so that monsters do not wake you in the middle of the night. Once you have used a bed, if you die you will respawn at that bed. +{*ICON*}355{*/ICON*} + + + + If there are other players in your game, everyone must be in a bed at the same time to be able to sleep. +{*ICON*}355{*/ICON*} + + + + In this area there are some simple Redstone and Piston circuits, and a chest with more items to extend these circuits. + + + + {*B*} +Press{*CONTROLLER_VK_A*} to learn more about Redstone circuits and Pistons.{*B*} +Press{*CONTROLLER_VK_B*} if you already know about Redstone circuits and Pistons. + + + + Levers, Buttons, Pressure Plates and Redstone Torches can all provide power to circuits, either by directly attaching them to the item you want to activate or by connecting them with Redstone dust. + + + + The position and direction that you place a power source can change how it affects the surrounding blocks. For example a Redstone torch on the side of a block can be turned off if the block is powered by another source. + + + + Redstone dust is collected by mining redstone ore with a pickaxe made of Iron, Diamond or Gold. You can use it to carry power up to 15 blocks, and it can travel up or down one block in height. +{*ICON*}331{*/ICON*} + + + + Redstone repeaters can be used to extend the distance that the power is carried, or put a delay in a circuit. +{*ICON*}356{*/ICON*} + + + + When powered, a Piston will extend, pushing up to 12 blocks. When they retract, Sticky Pistons can pull back one block of most types. +{*ICON*}33{*/ICON*} + + + + In the chest in this area there are some components for making circuits with pistons. Try using or completing the circuits in this area, or put together your own. There are more examples outside the tutorial area. + + + + In this area there is a Portal to the Nether! + + + + {*B*} +Press{*CONTROLLER_VK_A*} to learn more about Portals and The Nether.{*B*} +Press{*CONTROLLER_VK_B*} if you already know about Portals and The Nether. + + + + Portals are created by placing Obsidian blocks into a frame four blocks wide and five blocks tall. The corner blocks are not required. + + + + To activate a Nether Portal, set fire to the Obsidian blocks inside the frame with a Flint and Steel. Portals can be deactivated if their frame is broken, an explosion happens nearby or a liquid flows through them. + + + + To use a Nether Portal, stand inside it. Your screen will go purple and a sound will play. After a few seconds you will be transported to another dimension. + + + + The Nether can be a dangerous place, full of lava, but can be useful to collect Netherrack which burns forever when lit, and Glowstone which produces light. + + + + The Nether world can be used to fast-travel in the Overworld - traveling one block distance in the Nether is equivalent to traveling 3 blocks in the Overworld. + + + + You are now in Creative mode. + + + + {*B*} +Press{*CONTROLLER_VK_A*} to learn more about Creative mode.{*B*} +Press{*CONTROLLER_VK_B*} if you already know about Creative mode. + + + + When in Creative mode you have in infinite number of all available items and blocks, you can destroy blocks with one click without a tool, you are invulnerable and you can fly. + + + + Press{*CONTROLLER_ACTION_CRAFTING*} to open the creative inventory interface. + + + + Make your way to the opposite side of this hole to continue. + + + + You have now completed the Creative mode tutorial. + + + + In this area a farm has been set up. Farming enables you to create a renewable source of food and other items. + + + + {*B*} +Press{*CONTROLLER_VK_A*} to learn more about farming.{*B*} +Press{*CONTROLLER_VK_B*} if you already know about farming. + + + + Wheat, Pumpkins and Melons are grown from seeds. Wheat seeds are collected by breaking Tall Grass or harvesting wheat, and Pumpkin and Melon seeds are crafted from Pumpkins and Melons respectively. + + + + Before planting seeds the dirt blocks need to be turned into Farmland by using a Hoe. A nearby source of water will help keep the Farmland hydrated and make the crops grow faster, as will keeping the area lit. + + + + Wheat goes through several stages when growing, and is ready to be harvested when it appears darker.{*ICON*}59:7{*/ICON*} + + + + Pumpkins and Melons also need a block next to where you planted the seed for the fruit to grow once the stem has fully grown. + + + + Sugarcane must be planted on a Grass, Dirt or Sand block that is right next to water block. Chopping a Sugarcane block will also drop all blocks that are above it.{*ICON*}83{*/ICON*} + + + + Cacti must be planted on Sand, and will grow up to three blocks high. Like Sugarcane, destroying the lowest block will also allow you to collect the blocks that are above it.{*ICON*}81{*/ICON*} + + + + Mushrooms should be planted in a dimly lit area, and will spread to nearby dimly lit blocks.{*ICON*}39{*/ICON*} + + + + Bonemeal can be used to grow crops to their fully grown state, or grow Mushrooms into Huge Mushrooms.{*ICON*}351:15{*/ICON*} + + + + You have now completed the farming tutorial. + + + + In this area animals have been penned in. You can breed animals to produce baby versions of themselves. + + + + {*B*} +Press{*CONTROLLER_VK_A*} to learn more about animals and breeding.{*B*} +Press{*CONTROLLER_VK_B*} if you already know about animals and breeding. + + + + To get the animals to breed, you will need to feed them with the right food to get them to go into 'Love Mode'. + + + + Feed Wheat to a cow, mooshroom or sheep, Carrots to pigs, Wheat Seeds or Nether Wart to a chicken, or any kind of meat to a wolf, and they'll start looking for another animal of the same species near them that is also in Love Mode. + + + + When two animals of the same species meet, and both are in Love Mode, they will kiss for a few seconds, and then a baby animal will appear. The baby animal will follow their parents for a while before growing into a full sized animal itself. + + + + After being in Love Mode, an animal will not be able to enter it again for about five minutes. + + + + Some animals will follow you if you are holding their food in your hand. This makes it easier to group animals together to breed them.{*ICON*}296{*/ICON*} + + + + Wild wolves can be tamed by giving them bones. Once tamed Love Hearts will appear around them. Tamed wolves will follow the player and defend them if they haven't been commanded to sit. + + + + You have now completed the animal and breeding tutorial. + + + + In this area are some pumpkins and blocks to make a Snow Golem and an Iron Golem. + + + + {*B*} +Press{*CONTROLLER_VK_A*} to learn more about Golems.{*B*} +Press{*CONTROLLER_VK_B*} if you already know about Golems. + + + + Golems are created by placing a pumpkin on top of a stack of blocks. + + + + Snow Golems are created with two Snow Blocks, one of top of the other, with a pumpkin on top. Snow Golems throw snowballs at your enemies. + + + + Iron Golems are created with four Iron Blocks in the pattern shown, with a pumpkin on top of the middle block. Iron Golems attack your enemies. + + + + Iron Golems also appear naturally to protect villages, and will attack you if you attack any villagers. + + + + You cannot leave this area until you have completed the tutorial. + + + + Different tools are better for different materials. You should use a shovel to mine soft materials like earth and sand. + + + + Different tools are better for different materials. You should use an axe to chop tree trunks. + + + + Different tools are better for different materials. You should use a pickaxe to mine stone and ore. You may need to make your pickaxe from better materials to get resources from some blocks. + + + + Certain tools are better for attacking enemies. Consider using a sword to attack. + + + + Hint: Hold {*CONTROLLER_ACTION_ACTION*}to mine and chop using your hand or whatever you are holding. You may need to craft a tool to mine some blocks... + + + + The tool you are using has become damaged. Every time you use a tool it becomes damaged, and will eventually break. The colored bar below the item in your inventory shows the current damage state. + + + + Hold{*CONTROLLER_ACTION_JUMP*} to swim up. + + + + In this area there is a minecart on a track. To enter the minecart, point the cursor at it and press{*CONTROLLER_ACTION_USE*}. Use{*CONTROLLER_ACTION_USE*} on the button to make the minecart move. + + + + In the chest beside the river there is a boat. To use the boat, point the cursor at water and press{*CONTROLLER_ACTION_USE*}. Use{*CONTROLLER_ACTION_USE*} while pointing at the boat to enter it. + + + + In the chest beside the pond there is a fishing rod. Take the fishing rod from the chest and select it as the current item in your hand to use it. + + + + This more advanced piston mechanism creates a self-repairing bridge! Push the button to activate, then investigate how the components interact to learn more. + + + + If you move the pointer outside of the interface while carrying an item, you can drop that item. + + + + You do not have all the ingredients required to make this item. The box on the bottom left shows the ingredients required to craft this. + + + + Congratulations, you have completed the tutorial. Time in the game is now passing normally, and you don't have long until night time and the monsters come out! Finish your shelter! + + + + {*EXIT_PICTURE*} When you are ready to explore further, there is a stairway in this area near the Miner's shelter that leads to a small castle. + + + + Reminder: + + + + + + + + New features have been added to the game in the latest version, including new areas in the tutorial world. + + + + {*B*}Press{*CONTROLLER_VK_A*} to play through the tutorial as normal.{*B*} +Press{*CONTROLLER_VK_B*} to skip the main tutorial. + + + + In this area you will find areas setup to help you learn about fishing, boats, pistons and redstone. + + + + Outside of this area you will find examples of buildings, farming, minecarts and tracks, enchanting, brewing, trading, smithing and more! + + + + Your food bar has depleted to a level where you will no longer heal. + + + + {*B*} +Press{*CONTROLLER_VK_A*} to learn more about the food bar and eating food.{*B*} +Press{*CONTROLLER_VK_B*} if you already know about the food bar and eating food. + + + + This is the horse inventory interface. + + + + {*B*}Press{*CONTROLLER_VK_A*} to continue. +{*B*}Press{*CONTROLLER_VK_B*} if you already know how to use the horse inventory. + + + + The horse inventory allows you to transfer, or equip items to your Horse, Donkey or Mule. + + + + Saddle your Horse by placing a Saddle in the saddle slot. Horses can be given armor by placing Horse Armor in the armor slot. + + + + You can also transfer items between your own inventory and the saddlebags strapped to Donkeys and Mules in this menu. + + + + You have found a Horse. + + + + You have found a Donkey. + + + + You have found a Mule. + + + + {*B*}Press{*CONTROLLER_VK_A*} to learn more about Horses, Donkeys and Mules. +{*B*}Press{*CONTROLLER_VK_B*} if you already know about Horses, Donkeys and Mules. + + + + Horses and Donkeys are found mainly in open plains. Mules can be bred from a Donkey and a Horse, but are infertile themselves. + + + + All adult Horses, Donkeys and Mules can be ridden. However only Horses can be armored, and only Mules and Donkeys may be equipped with saddlebags for transporting items. + + + + Horses, Donkeys and Mules must be tamed before they can be used. A horse is tamed by attempting to ride it, and managing to stay on the horse while it attempts to throw the rider off. + + + + When tamed Love Hearts will appear around them and they will no longer buck the player off. + + + + Try to ride this horse now. Use {*CONTROLLER_ACTION_USE*} with no items or tools in your hand to mount it. + + + + To steer a horse they must then be equipped with a saddle, which can be bought from villagers or found inside chests hidden in the world. + + + + Tame Donkeys and Mules can be given saddlebags by attaching a chest. These bags can be accessed whilst riding or when sneaking. + + + + Horses and Donkeys (but not Mules) can be bred like other animals using Golden Apples or Golden Carrots. Foals will grow into adult horses over time, although feeding them wheat or hay will speed this up. + + + + You can try to tame the Horses and Donkeys here, and there are Saddles, Horse Armor and other useful items for Horses in chests around here too. + + + + This is the Beacon interface, which you can use to choose powers for your Beacon to grant. + + + + {*B*} +Press{*CONTROLLER_VK_A*} to continue.{*B*} +Press{*CONTROLLER_VK_B*} if you already know how to use the Beacon interface. + + + + In the Beacon menu you can select 1 primary power for your Beacon. The more tiers your pyramid has the more powers you will have to choose from. + + + + A Beacon on a pyramid with at least 4 tiers grants an additional option of either the Regeneration secondary power or a stronger primary power. + + + + To set the powers of your Beacon you must sacrifice an Emerald, Diamond, Gold or Iron Ingot in the payment slot. Once set, the powers will emanate from the Beacon indefinitely. + + + + At the top of this pyramid there is an inactivate Beacon. + + + + {*B*} +Press{*CONTROLLER_VK_A*} to learn more about Beacons.{*B*} +Press{*CONTROLLER_VK_B*} if you already know about Beacons. + + + + Active Beacons project a bright beam of light into the sky and grant powers to nearby players. They are crafted with Glass, Obsidian and Nether Stars, which can be obtained by defeating the Wither. + + + + Beacons must be placed so that they are in sunlight during the day. Beacons must be placed on Pyramids of Iron, Gold, Emerald or Diamond. However the choice of material has no effect on the power of the beacon. + + + + Try using the Beacon to set the powers it grants, you can use the Iron Ingots provided as the necessary payment. + + + + This room contains Hoppers + + + + {*B*} +Press{*CONTROLLER_VK_A*} to learn more about Hoppers.{*B*} +Press{*CONTROLLER_VK_B*} if you already know about Hoppers. + + + + Hoppers are used to insert or remove items from containers, and to automatically pick-up items thrown into them. + + + + They can affect Brewing Stands, Chests, Dispensers, Droppers, Minecarts with Chests, Minecarts with Hoppers, as well as other Hoppers. + + + + Hoppers will continuously attempt to suck items out of suitable container placed above them. It will also attempt to insert stored items into an output container. + + + + However if a Hopper is powered by Redstone it will become inactive and stop both sucking and inserting items. + + + + A Hopper points in the direction it tries to output items. To make a Hopper point to a particular block, place the Hopper against that block whilst sneaking. + + + + There are various useful Hopper layouts for you to see and experiment with in this room. + + + + This is the Firework interface, which you can use to craft Fireworks and Firework Stars. + + + + {*B*} +Press{*CONTROLLER_VK_A*} to continue.{*B*} +Press{*CONTROLLER_VK_B*} if you already know how to use the Firework interface. + + + + To craft a Firework, place Gunpowder and Paper in the 3x3 crafting grid that is shown above your inventory. + + + + You can optionally place multiple Firework Stars in the crafting grid to add them to the Firework. + + + + Filling more slots in the crafting grid with Gunpowder will increase the height at which all the Firework Stars will explode. + + + + You can then take the crafted Firework out of the output slot when you wish to craft it. + + + + Firework Stars can be crafted by placing Gunpowder and Dye into the crafting grid. + + + + The Dye will set the color of the explosion of the Firework Star. + + + + The shape of the Firework Star is set by adding either a Fire Charge, Gold Nugget, Feather or Mob Head. + + + + A trail or a twinkle can be added using Diamonds or Glowstone Dust. + + + + After a Firework Star has been crafted, you can set the fade color of the Firework Star by crafting it with Dye. + + + + Contained within the chests here there are various items used in the creation of FIREWORKS! + + + + {*B*} +Press{*CONTROLLER_VK_A*} to learn more about Fireworks. {*B*} +Press{*CONTROLLER_VK_B*} if you already know about Fireworks. + + + + Fireworks are decorative items that can be launched by hand or from Dispensers. They are crafted using Paper, Gunpowder and optionally a number of Firework Stars. + + + + The colors, fade, shape, size, and effects (such as trails and twinkles) of Firework Stars can be customized by including additional ingredients when crafting. + + + + Try crafting a Firework at the Crafting Table using an assortment of ingredients from the chests. + + + + Select + + + + Use + + + + Back + + + + Exit + + + + Cancel + + + + Cancel Join + + + + Refresh Online Games List + + + + Party Games + + + + All Games + + + + Change Group + + + + Show Inventory + + + + Show Description + + + + Show Ingredients + + + + Crafting + + + + Create + + + + Take/Place + + + + Take + + + + Take All + + + + Take Half + + + + Place + + + + Place All + + + + Place One + + + + Drop + + + + Drop All + + + + Drop One + + + + Swap + + + + Quick Move + + + + Clear Quick Select + + + + What's This? + + + + Share To Facebook + + + + Change Filter + + + + Send Friend Request + + + + Page Down + + + + Page Up + + + + Next + + + + Previous + + + + Kick Player + + + + Dye + + + + Mine + + + + Feed + + + + Tame + + + + Heal + + + + Sit + + + + Follow Me + + + + Eject + + + + Empty + + + + Saddle + + + + Place + + + + Hit + + + + Milk + + + + Collect + + + + Eat + + + + Sleep + + + + Wake Up + + + + Play + + + + Ride + + + + Sail + + + + Grow + + + + Swim Up + + + + Open + + + + Change Pitch + + + + Detonate + + + + Read + + + + Hang + + + + Throw + + + + Plant + + + + Till + + + + Harvest + + + + Continue + + + + Unlock Full Game + + + + Delete Save + + + + Delete + + + + Options + + + + Invite Friends + + + + Accept + + + + Shear + + + + Ban Level + + + + Select Skin + + + + Ignite + + + + Navigate + + + + Install Full Version + + + + Install Trial Version + + + + Install + + + + Reinstall + + + + Save Options + + + + Execute Command + + + + Creative + + + + Move Ingredient + + + + Move Fuel + + + + Move Tool + + + + Move Armor + + + + Move Weapon + + + + Equip + + + + Draw + + + + Release + + + + Privileges + + + + Block + + + + Page Up + + + + Page Down + + + + Love Mode + + + + Drink + + + + Rotate + + + + Hide + + + + Clear All Slots + + + + Mount + + + + Dismount + + + + Attach Chest + + + + Launch + + + + Leash + + + + Release + + + + Attach + + + + Name + + + + OK + + + + Cancel + + + + Minecraft Store + + + + Are you sure you want to leave your current game and join the new one? Any unsaved progress will be lost. + + + + Exit Game + + + + Save Game + + + + Exit Without Saving + + + + Are you sure you want to overwrite any previous save for this world with the current version of this world? + + + + Are you sure you want to exit without saving? You will lose all progress in this world! + + + + Start Game + + + + Damaged Save + + + + This save is corrupt or damaged. Would you like to delete it? + + + + Are you sure you want to exit to the main menu and disconnect all players from the game? Any unsaved progress will be lost. + + + + Exit and save + + + + Exit without saving + + + + Are you sure you want to exit to the main menu? Any unsaved progress will be lost. + + + + Are you sure you want to exit to the main menu? Your progress will be lost! + + + + Create New World + + + + Play Tutorial + + + + Tutorial + + + + Name Your World + + + + Enter a name for your world + + + + Input the seed for your world generation + + + + Load Saved World + + + + Press START to join game + + + + Exiting the game + + + + An error occurred. Exiting to the main menu. + + + + Connection failed + + + + Connection lost + + + + Connection to the server was lost. Exiting to the main menu. + + + + Disconnected by the server + + + + You were kicked from the game + + + + You were kicked from the game for flying + + + + Connection attempt took too long + + + + The server is full + + + + The host has exited the game. + + + + You cannot join this game as you are not friends with anybody in the game. + + + + You cannot join this game as you have previously been kicked by the host. + + + + You cannot join this game as the player you are trying to join is running an older version of the game. + + + + You cannot join this game as the player you are trying to join is running a newer version of the game. + + + + New World + + + + Award Unlocked! + + + + Hurray - you've been awarded a gamerpic featuring Steve from Minecraft! + + + + Hurray - you've been awarded a gamerpic featuring a Creeper! + + + + Unlock Full Game + + + + You're playing the trial game, but you'll need the full game to be able to save your game. +Would you like to unlock the full game now? + + + + Please wait + + + + No results + + + + Filter: + + + + Friends + + + + My Score + + + + Overall + + + + Entries: + + + + Rank + + + + Preparing to Save Level + + + + Preparing Chunks... + + + + Finalizing... + + + + Building Terrain + + + + Simulating world for a bit + + + + Initializing server + + + + Generating spawn area + + + + Loading spawn area + + + + Entering The Nether + + + + Leaving The Nether + + + + Respawning + + + + Generating level + + + + Loading level + + + + Saving players + + + + Connecting to host + + + + Downloading terrain + + + + Switching to offline game + + + + Please wait while the host saves the game + + + + Entering The END + + + + Leaving The END + + + + Finding Seed for the World Generator + + + + This bed is occupied + + + + You can only sleep at night + + + + %s is sleeping in a bed. To skip to dawn, all players need to sleep in beds at the same time. + + + + Your home bed was missing or obstructed + + + + You may not rest now, there are monsters nearby + + + + You are sleeping in a bed. To skip to dawn, all players need to sleep in beds at the same time. + + + + Tools and Weapons + + + + Weapons + + + + Food + + + + Structures + + + + Armor + + + + Mechanisms + + + + Transport + + + + Decorations + + + + Building Blocks + + + + Redstone & Transportation + + + + Miscellaneous + + + + Brewing + + + + Tools, Weapons & Armor + + + + Materials + + + + Signed out + + + + Difficulty + + + + Control Type + + + + Music + + + + Sound + + + + Gamma + + + + Game Sensitivity + + + + Interface Sensitivity + + + + Peaceful + + + + Easy + + + + Normal + + + + Hard + + + + Keyboard & Mouse + + + + Xbox One + + + + Xbox 360 + + + + PlayStation Vita + + + + PlayStation 3 + + + + PlayStation 4 + + + + Wii U + + + + Nintendo Switch + + + + In this mode, the player regains health over time, and there are no enemies in the environment. + + + + In this mode, enemies spawn in the environment, but will do less damage to the player than in the Normal mode. + + + + In this mode, enemies spawn in the environment and will do a standard amount of damage to the player. + + + + In this mode, enemies will spawn in the environment, and will do a great deal of damage to the player. Watch out for the Creepers too, since they are unlikely to cancel their exploding attack when you move away from them! + + + + Trial Timeout + + + + Game full + + + + Failed to join game as there are no spaces left + + + + Enter Sign Text + + + + Enter a line of text for your sign + + + + Enter Title + + + + Enter a title for your post + + + + Enter Caption + + + + Enter a caption for your post + + + + Enter Description + + + + Enter a description for your post + + + + Inventory + + + + Ingredients + + + + Brewing Stand + + + + Chest + + + + Enchant + + + + Furnace + + + + Ingredient + + + + Fuel + + + + Dispenser + + + + Horse + + + + Dropper + + + + Hopper + + + + Beacon + + + + Primary Power + + + + Secondary Power + + + + Minecart + + + + There are no downloadable content offers of this type available for this title at the moment. + + + + %s has joined the game. + + + + %s has left the game. + + + + %s was kicked from the game. + + + + Are you sure you want to delete this save game? + + + + Awaiting approval + + + + Censored + + + + Now playing: + + + + Reset Settings + + + + Are you sure you would like to reset your settings to their default values? + + + + Loading Error + + + + %s's Game + + + + Unknown host game + + + + Guest signed out + + + + A guest player has signed out causing all guest players to be removed from the game. + + + + Sign in + + + + You are not signed in. In order to play this game, you will need to be signed in. Do you want to sign in now? + + + + Multiplayer not allowed + + + + Failed to create game + + + + Auto Selected + + + + No Pack: Default Skins + + + + Favorite Skins + + + + Banned Level + + + + The game you are joining is in your banned level list. +If you choose to join this game, the level will be removed from your banned level list. + + + + Ban This Level? + + + + Are you sure you want to add this level to your banned level list? +Selecting OK will also exit this game. + + + + Remove from Banned List + + + + Autosave Interval + + + + Autosave Interval: OFF + + + + Mins + + + + Can't Place Here! + + + + Placing lava close to the level spawn point is not allowed due to the possibility of instant death for spawning players. + + + + Interface Opacity + + + + Preparing to Autosave Level + + + + HUD Size + + + + HUD Size (Splitscreen) + + + + Seed + + + + Unlock Skin Pack + + + + To use the skin you have selected, you need to unlock this skin pack. +Would you like to unlock this skin pack now? + + + + Unlock Texture Pack + + + + To use this texture pack for your world, you need to unlock it. +Would you like to unlock it now? + + + + Trial Texture Pack + + + + You are using a trial version of the texture pack. You will not be able to save this world unless you unlock the full version. +Would you like to unlock the full version of the texture pack? + + + + Texture Pack Not Present + + + + Unlock Full Version + + + + Download Trial Version + + + + Download Full Version + + + + This world uses a mash-up pack or texture pack you don't have! +Would you like to install the mash-up pack or texture pack now? + + + + Get Trial Version + + + + Get Full Version + + + + Kick player + + + + Are you sure you want to kick this player from the game? They will not be able to rejoin until you restart the world. + + + + Gamerpics Packs + + + + Themes + + + + Skins Packs + + + + Allow friends of friends + + + + You cannot join this game because it has been limited to players who are friends of the host. + + + + Can't Join Game + + + + Selected + + + + Selected skin: + + + + Corrupt Downloadable Content + + + + This downloadable content is corrupt and cannot be used. You need to delete it, then re-install it from the Minecraft Store menu. + + + + Some of your downloadable content is corrupt and cannot be used. You need to delete them, then re-install them from the Minecraft Store menu. + + + + Your game mode has been changed + + + + Rename Your World + + + + Enter the new name for your world + + + + Game Mode: Survival + + + + Game Mode: Creative + + + + Game Mode: Adventure + + + + Game Mode: Hardcore + + + + Survival + + + + Creative + + + + Adventure + + + + Hardcore + + + + Created in Survival Mode + + + + Created in Creative Mode + + + + Render Clouds + + + + Cave Sounds + + + + Minecart Sounds + + + + What would you like to do with this save game? + + + + Rename Save + + + + Autosaving in %d... + + + + On + + + + Off + + + + Normal + + + + Superflat + + + + Enter a seed to generate the same terrain again. Leave blank for a random world. + + + + When enabled, the game will be an online game. + + + + When enabled, only invited players can join. + + + + When enabled, friends of people on your Friends List can join the game. + + + + When enabled, players can inflict damage on other players. Only affects Survival mode. + + + + When disabled, players joining the game cannot build or mine until authorised. + + + + When enabled, fire may spread to nearby flammable blocks. + + + + When enabled, TNT will explode when activated. + + + + When enabled, the Nether world will be re-generated. This is useful if you have an older save where Nether Fortresses were not present. + + + + When enabled, structures such as Villages and Strongholds will generate in the world. + + + + When enabled, a completely flat world will be generated in the Overworld and in the Nether. + + + + When enabled, a chest containing some useful items will be created near the player spawn point. + + + + When disabled, prevents monsters and animals from changing blocks (for example, Creeper explosions won't destroy blocks and Sheep won't remove Grass) or picking up items. + + + + When enabled, players will keep their inventory when they die. + + + + When disabled, mobs will not spawn naturally. + + + + When disabled, monsters and animals will not drop loot (for example, Creepers won't drop gunpowder). + + + + When disabled, blocks will not drop items when destroyed (for example, Stone blocks won't drop Cobblestone). + + + + When disabled, players will not regenerate health naturally. + + + + When disabled, the time of day will not change. + + + + Skin Packs + + + + Themes + + + + Gamerpics + + + + Avatar Items + + + + Texture Packs + + + + Mash-Up Packs + + + + {*PLAYER*} went up in flames + + + + {*PLAYER*} burned to death + + + + {*PLAYER*} tried to swim in lava + + + + {*PLAYER*} suffocated in a wall + + + + {*PLAYER*} drowned + + + + {*PLAYER*} starved to death + + + + {*PLAYER*} was pricked to death + + + + {*PLAYER*} hit the ground too hard + + + + {*PLAYER*} fell out of the world + + + + {*PLAYER*} died + + + + {*PLAYER*} blew up + + + + {*PLAYER*} was killed by magic + + + + {*PLAYER*} was killed by Ender Dragon breath + + + + {*PLAYER*} was slain by {*SOURCE*} + + + + {*PLAYER*} was slain by {*SOURCE*} + + + + {*PLAYER*} was shot by {*SOURCE*} + + + + {*PLAYER*} was fireballed by {*SOURCE*} + + + + {*PLAYER*} was pummeled by {*SOURCE*} + + + + {*PLAYER*} was killed by {*SOURCE*} using magic + + + + {*PLAYER*} fell off a ladder + + + + {*PLAYER*} fell off some vines + + + + {*PLAYER*} fell out of the water + + + + {*PLAYER*} fell from a high place + + + + {*PLAYER*} was doomed to fall by {*SOURCE*} + + + + {*PLAYER*} was doomed to fall by {*SOURCE*} + + + + {*PLAYER*} was doomed to fall by {*SOURCE*} using {*ITEM*} + + + + {*PLAYER*} fell too far and was finished by {*SOURCE*} + + + + {*PLAYER*} fell too far and was finished by {*SOURCE*} using {*ITEM*} + + + + {*PLAYER*} walked into fire whilst fighting {*SOURCE*} + + + + {*PLAYER*} was burnt to a crisp whilst fighting {*SOURCE*} + + + + {*PLAYER*} tried to swim in lava to escape {*SOURCE*} + + + + {*PLAYER*} drowned whilst trying to escape {*SOURCE*} + + + + {*PLAYER*} walked into a cactus whilst trying to escape {*SOURCE*} + + + + {*PLAYER*} was blown up by {*SOURCE*} + + + + {*PLAYER*} withered away + + + + {*PLAYER*} was slain by {*SOURCE*} using {*ITEM*} + + + + {*PLAYER*} was shot by {*SOURCE*} using {*ITEM*} + + + + {*PLAYER*} was fireballed by {*SOURCE*} using {*ITEM*} + + + + {*PLAYER*} was pummeled by {*SOURCE*} using {*ITEM*} + + + + {*PLAYER*} was killed by {*SOURCE*} using {*ITEM*} + + + + Bedrock Fog + + + + Display HUD + + + + Display Hand + + + + Death Messages + + + + dead. + + + + Animated Character + + + + Custom Skin Animation + + + + You can no longer mine or use items + + + + You can now mine and use items + + + + You can no longer place blocks + + + + You can now place blocks + + + + You can now use doors and switches + + + + You can no longer use doors and switches + + + + You can now use containers (e.g. chests) + + + + You can no longer use containers (e.g. chests) + + + + You can no longer attack mobs + + + + You can now attack mobs + + + + You can no longer attack players + + + + You can now attack players + + + + You can no longer attack animals + + + + You can now attack animals + + + + You are now a moderator + + + + You are no longer a moderator + + + + You can now fly + + + + You can no longer fly + + + + You will no longer get exhausted + + + + You will now get exhausted + + + + You are now invisible + + + + You are no longer invisible + + + + You are now invulnerable + + + + You are no longer invulnerable + + + + %d MSP + + + + Ender Dragon + + + + %s has entered The End + + + + %s has left The End + + + + +{*C3*}I see the player you mean.{*EF*}{*B*}{*B*} +{*C2*}{*PLAYER*}?{*EF*}{*B*}{*B*} +{*C3*}Yes. Take care. It has reached a higher level now. It can read our thoughts.{*EF*}{*B*}{*B*} +{*C2*}That doesn't matter. It thinks we are part of the game.{*EF*}{*B*}{*B*} +{*C3*}I like this player. It played well. It did not give up.{*EF*}{*B*}{*B*} +{*C2*}It is reading our thoughts as though they were words on a screen.{*EF*}{*B*}{*B*} +{*C3*}That is how it chooses to imagine many things, when it is deep in the dream of a game.{*EF*}{*B*}{*B*} +{*C2*}Words make a wonderful interface. Very flexible. And less terrifying than staring at the reality behind the screen.{*EF*}{*B*}{*B*} +{*C3*}They used to hear voices. Before players could read. Back in the days when those who did not play called the players witches, and warlocks. And players dreamed they flew through the air, on sticks powered by demons.{*EF*}{*B*}{*B*} +{*C2*}What did this player dream?{*EF*}{*B*}{*B*} +{*C3*}This player dreamed of sunlight and trees. Of fire and water. It dreamed it created. And it dreamed it destroyed. It dreamed it hunted, and was hunted. It dreamed of shelter.{*EF*}{*B*}{*B*} +{*C2*}Hah, the original interface. A million years old, and it still works. But what true structure did this player create, in the reality behind the screen?{*EF*}{*B*}{*B*} +{*C3*}It worked, with a million others, to sculpt a true world in a fold of the {*EF*}{*NOISE*}{*C3*}, and created a {*EF*}{*NOISE*}{*C3*} for {*EF*}{*NOISE*}{*C3*}, in the {*EF*}{*NOISE*}{*C3*}.{*EF*}{*B*}{*B*} +{*C2*}It cannot read that thought.{*EF*}{*B*}{*B*} +{*C3*}No. It has not yet achieved the highest level. That, it must achieve in the long dream of life, not the short dream of a game.{*EF*}{*B*}{*B*} +{*C2*}Does it know that we love it? That the universe is kind?{*EF*}{*B*}{*B*} +{*C3*}Sometimes, through the noise of its thoughts, it hears the universe, yes.{*EF*}{*B*}{*B*} +{*C2*}But there are times it is sad, in the long dream. It creates worlds that have no summer, and it shivers under a black sun, and it takes its sad creation for reality.{*EF*}{*B*}{*B*} +{*C3*}To cure it of sorrow would destroy it. The sorrow is part of its own private task. We cannot interfere.{*EF*}{*B*}{*B*} +{*C2*}Sometimes when they are deep in dreams, I want to tell them, they are building true worlds in reality. Sometimes I want to tell them of their importance to the universe. Sometimes, when they have not made a true connection in a while, I want to help them to speak the word they fear.{*EF*}{*B*}{*B*} +{*C3*}It reads our thoughts.{*EF*}{*B*}{*B*} +{*C2*}Sometimes I do not care. Sometimes I wish to tell them, this world you take for truth is merely {*EF*}{*NOISE*}{*C2*} and {*EF*}{*NOISE*}{*C2*}, I wish to tell them that they are {*EF*}{*NOISE*}{*C2*} in the {*EF*}{*NOISE*}{*C2*}. They see so little of reality, in their long dream.{*EF*}{*B*}{*B*} +{*C3*}And yet they play the game.{*EF*}{*B*}{*B*} +{*C2*}But it would be so easy to tell them...{*EF*}{*B*}{*B*} +{*C3*}Too strong for this dream. To tell them how to live is to prevent them living.{*EF*}{*B*}{*B*} +{*C2*}I will not tell the player how to live.{*EF*}{*B*}{*B*} +{*C3*}The player is growing restless.{*EF*}{*B*}{*B*} +{*C2*}I will tell the player a story.{*EF*}{*B*}{*B*} +{*C3*}But not the truth.{*EF*}{*B*}{*B*} +{*C2*}No. A story that contains the truth safely, in a cage of words. Not the naked truth that can burn over any distance.{*EF*}{*B*}{*B*} +{*C3*}Give it a body, again.{*EF*}{*B*}{*B*} +{*C2*}Yes. Player...{*EF*}{*B*}{*B*} +{*C3*}Use its name.{*EF*}{*B*}{*B*} +{*C2*}{*PLAYER*}. Player of games.{*EF*}{*B*}{*B*} +{*C3*}Good.{*EF*}{*B*}{*B*} + + + + + +{*C2*}Take a breath, now. Take another. Feel air in your lungs. Let your limbs return. Yes, move your fingers. Have a body again, under gravity, in air. Respawn in the long dream. There you are. Your body touching the universe again at every point, as though you were separate things. As though we were separate things.{*EF*}{*B*}{*B*} +{*C3*}Who are we? Once we were called the spirit of the mountain. Father sun, mother moon. Ancestral spirits, animal spirits. Jinn. Ghosts. The green man. Then gods, demons. Angels. Poltergeists. Aliens, extraterrestrials. Leptons, quarks. The words change. We do not change.{*EF*}{*B*}{*B*} +{*C2*}We are the universe. We are everything you think isn't you. You are looking at us now, through your skin and your eyes. And why does the universe touch your skin, and throw light on you? To see you, player. To know you. And to be known. I shall tell you a story.{*EF*}{*B*}{*B*} +{*C2*}Once upon a time, there was a player.{*EF*}{*B*}{*B*} +{*C3*}The player was you, {*PLAYER*}.{*EF*}{*B*}{*B*} +{*C2*}Sometimes it thought itself human, on the thin crust of a spinning globe of molten rock. The ball of molten rock circled a ball of blazing gas that was three hundred and thirty thousand times more massive than it. They were so far apart that light took eight minutes to cross the gap. The light was information from a star, and it could burn your skin from a hundred and fifty million kilometres away.{*EF*}{*B*}{*B*} +{*C2*}Sometimes the player dreamed it was a miner, on the surface of a world that was flat, and infinite. The sun was a square of white. The days were short; there was much to do; and death was a temporary inconvenience.{*EF*}{*B*}{*B*} +{*C3*}Sometimes the player dreamed it was lost in a story.{*EF*}{*B*}{*B*} +{*C2*}Sometimes the player dreamed it was other things, in other places. Sometimes these dreams were disturbing. Sometimes very beautiful indeed. Sometimes the player woke from one dream into another, then woke from that into a third.{*EF*}{*B*}{*B*} +{*C3*}Sometimes the player dreamed it watched words on a screen.{*EF*}{*B*}{*B*} +{*C2*}Let's go back.{*EF*}{*B*}{*B*} +{*C2*}The atoms of the player were scattered in the grass, in the rivers, in the air, in the ground. A woman gathered the atoms; she drank and ate and inhaled; and the woman assembled the player, in her body.{*EF*}{*B*}{*B*} +{*C2*}And the player awoke, from the warm, dark world of its mother's body, into the long dream.{*EF*}{*B*}{*B*} +{*C2*}And the player was a new story, never told before, written in letters of DNA. And the player was a new program, never run before, generated by a sourcecode a billion years old. And the player was a new human, never alive before, made from nothing but milk and love.{*EF*}{*B*}{*B*} +{*C3*}You are the player. The story. The program. The human. Made from nothing but milk and love.{*EF*}{*B*}{*B*} +{*C2*}Let's go further back.{*EF*}{*B*}{*B*} +{*C2*}The seven billion billion billion atoms of the player's body were created, long before this game, in the heart of a star. So the player, too, is information from a star. And the player moves through a story, which is a forest of information planted by a man called Julian, on a flat, infinite world created by a man called Markus, that exists inside a small, private world created by the player, who inhabits a universe created by...{*EF*}{*B*}{*B*} +{*C3*}Shush. Sometimes the player created a small, private world that was soft and warm and simple. Sometimes hard, and cold, and complicated. Sometimes it built a model of the universe in its head; flecks of energy, moving through vast empty spaces. Sometimes it called those flecks "electrons" and "protons".{*EF*}{*B*}{*B*} + + + + + +{*C2*}Sometimes it called them "planets" and "stars".{*EF*}{*B*}{*B*} +{*C2*}Sometimes it believed it was in a universe that was made of energy that was made of offs and ons; zeros and ones; lines of code. Sometimes it believed it was playing a game. Sometimes it believed it was reading words on a screen.{*EF*}{*B*}{*B*} +{*C3*}You are the player, reading words...{*EF*}{*B*}{*B*} +{*C2*}Shush... Sometimes the player read lines of code on a screen. Decoded them into words; decoded words into meaning; decoded meaning into feelings, emotions, theories, ideas, and the player started to breathe faster and deeper and realised it was alive, it was alive, those thousand deaths had not been real, the player was alive{*EF*}{*B*}{*B*} +{*C3*}You. You. You are alive.{*EF*}{*B*}{*B*} +{*C2*}and sometimes the player believed the universe had spoken to it through the sunlight that came through the shuffling leaves of the summer trees{*EF*}{*B*}{*B*} +{*C3*}and sometimes the player believed the universe had spoken to it through the light that fell from the crisp night sky of winter, where a fleck of light in the corner of the player's eye might be a star a million times as massive as the sun, boiling its planets to plasma in order to be visible for a moment to the player, walking home at the far side of the universe, suddenly smelling food, almost at the familiar door, about to dream again{*EF*}{*B*}{*B*} +{*C2*}and sometimes the player believed the universe had spoken to it through the zeros and ones, through the electricity of the world, through the scrolling words on a screen at the end of a dream{*EF*}{*B*}{*B*} +{*C3*}and the universe said I love you{*EF*}{*B*}{*B*} +{*C2*}and the universe said you have played the game well{*EF*}{*B*}{*B*} +{*C3*}and the universe said everything you need is within you{*EF*}{*B*}{*B*} +{*C2*}and the universe said you are stronger than you know{*EF*}{*B*}{*B*} +{*C3*}and the universe said you are the daylight{*EF*}{*B*}{*B*} +{*C2*}and the universe said you are the night{*EF*}{*B*}{*B*} +{*C3*}and the universe said the darkness you fight is within you{*EF*}{*B*}{*B*} +{*C2*}and the universe said the light you seek is within you{*EF*}{*B*}{*B*} +{*C3*}and the universe said you are not alone{*EF*}{*B*}{*B*} +{*C2*}and the universe said you are not separate from every other thing{*EF*}{*B*}{*B*} +{*C3*}and the universe said you are the universe tasting itself, talking to itself, reading its own code{*EF*}{*B*}{*B*} +{*C2*}and the universe said I love you because you are love.{*EF*}{*B*}{*B*} +{*C3*}And the game was over and the player woke up from the dream. And the player began a new dream. And the player dreamed again, dreamed better. And the player was the universe. And the player was love.{*EF*}{*B*}{*B*} +{*C3*}You are the player.{*EF*}{*B*}{*B*} +{*C2*}Wake up.{*EF*} + + + + + Reset Nether + + + + Are you sure you want to reset the Nether in this savegame to its default state? You will lose anything you have built in the Nether! + + + + Reset Nether + + + + Don't Reset Nether + + + + Can't shear this Mooshroom at the moment. The maximum number of Pigs, Sheep, Cows, Cats and Horses has been reached. + + + + Can't use Spawn Egg at the moment. The maximum number of Pigs, Sheep, Cows, Cats and Horses has been reached. + + + + Can't use Spawn Egg at the moment. The maximum number of Mooshrooms has been reached. + + + + Can't use Spawn Egg at the moment. The maximum number of Wolves in a world has been reached. + + + + Can't use Spawn Egg at the moment. The maximum number of Chickens in a world has been reached. + + + + Can't use Spawn Egg at the moment. The maximum number of Squid in a world has been reached. + + + + Can't use Spawn Egg at the moment. The maximum number of Bats in a world has been reached. + + + + Can't use Spawn Egg at the moment. The maximum number of enemies in a world has been reached. + + + + Can't use Spawn Egg at the moment. The maximum number of villagers in a world has been reached. + + + + The maximum number of Paintings/Item Frames in a world has been reached. + + + + You can't spawn enemies in Peaceful mode. + + + + This animal can't enter Love Mode. The maximum number of breeding Pigs, Sheep, Cows, Cats and Horses has been reached. + + + + This animal can't enter Love Mode. The maximum number of breeding Wolves has been reached. + + + + This animal can't enter Love Mode. The maximum number of breeding Chickens has been reached. + + + + This animal can't enter Love Mode. The maximum number of breeding horses has been reached. + + + + This animal can't enter Love Mode. The maximum number of breeding Mooshrooms has been reached. + + + + The maximum number of Boats in a world has been reached. + + + + The maximum number of Mob Heads in a world has been reached. + + + + Invert Look + + + + Southpaw + + + + You Died! + + + + Respawn + + + + Downloadable Content Offers + + + + Change Skin + + + + How To Play + + + + Controls + + + + Settings + + + + Languages + + + + Credits + + + + Reinstall Content + + + + Debug Settings + + + + Fire Spreads + + + + TNT Explodes + + + + Player vs Player + + + + Trust Players + + + + Host Privileges + + + + Generate Structures + + + + Superflat World + + + + Bonus Chest + + + + World Options + + + + Game Options + + + + Mob Griefing + + + + Keep Inventory + + + + Mob Spawning + + + + Mob Loot + + + + Tile Drops + + + + Natural Regeneration + + + + Daylight Cycle + + + + Can Build and Mine + + + + Can Use Doors and Switches + + + + Can Open Containers + + + + Can Attack Players + + + + Can Attack Animals + + + + Moderator + + + + Kick Player + + + + Can Fly + + + + Disable Exhaustion + + + + Invisible + + + + Host Options + + + + Players/Invite + + + + Online Game + + + + Invite Only + + + + More Options + + + + Load + + + + New World + + + + World Name + + + + Seed for the World Generator + + + + Leave blank for a random seed + + + + Players + + + + Join Game + + + + Start Game + + + + No Games Found + + + + Play Game + + + + Leaderboards + + + + Help & Options + + + + Unlock Full Game + + + + Resume Game + + + + Save Game + + + + Difficulty: + + + + Game Type: + + + + Structures: + + + + Level Type: + + + + PvP: + + + + Trust Players: + + + + TNT: + + + + Fire Spreads: + + + + Reinstall Theme + + + + Reinstall Gamerpic 1 + + + + Reinstall Gamerpic 2 + + + + Reinstall Avatar Item 1 + + + + Reinstall Avatar Item 2 + + + + Reinstall Avatar Item 3 + + + + Game Options + + + + Audio + + + + Control + + + + Graphics + + + + User Interface + + + + Reset to Defaults + + + + View Bobbing + + + + Hints + + + + In-Game Tooltips + + + + Vertical Splitscreen + + + + Done + + + + Edit sign message: + + + + Fill in the details to accompany your screenshot + + + + Caption + + + + Screenshot from in-game + + + + Edit sign message: + + + + The classic Minecraft textures, icons and user interface! + + + + Show all Mash-up Worlds + + + + No Effects + + + + Speed + + + + Slowness + + + + Haste + + + + Mining Fatigue + + + + Strength + + + + Weakness + + + + Instant Health + + + + Instant Damage + + + + Jump Boost + + + + Nausea + + + + Regeneration + + + + Resistance + + + + Fire Resistance + + + + Water Breathing + + + + Invisibility + + + + Blindness + + + + Night Vision + + + + Hunger + + + + Poison + + + + Wither + + + + Health Boost + + + + Absorption + + + + Saturation + + + + of Swiftness + + + + of Slowness + + + + of Haste + + + + of Dullness + + + + of Strength + + + + of Weakness + + + + of Healing + + + + of Harming + + + + of Leaping + + + + of Nausea + + + + of Regeneration + + + + of Resistance + + + + of Fire Resistance + + + + of Water Breathing + + + + of Invisibility + + + + of Blindness + + + + of Night Vision + + + + of Hunger + + + + of Poison + + + + of Decay + + + + of Health Boost + + + + of Absorption + + + + of Saturation + + + + + + + + + II + + + + III + + + + IV + + + + Splash + + + + Mundane + + + + Uninteresting + + + + Bland + + + + Clear + + + + Milky + + + + Diffuse + + + + Artless + + + + Thin + + + + Awkward + + + + Flat + + + + Bulky + + + + Bungling + + + + Buttered + + + + Smooth + + + + Suave + + + + Debonair + + + + Thick + + + + Elegant + + + + Fancy + + + + Charming + + + + Dashing + + + + Refined + + + + Cordial + + + + Sparkling + + + + Potent + + + + Foul + + + + Odorless + + + + Rank + + + + Harsh + + + + Acrid + + + + Gross + + + + Stinky + + + + Used as the base of all potions. Use in a brewing stand to create potions. + + + + Has no effects, can be used in a brewing stand to create potions by adding more ingredients. + + + + Increases affected players, animals and monsters movement speed, and players sprinting speed, jumping length and field of view. + + + + Reduces affected players, animals and monsters movement speed, and players sprinting speed, jumping length and field of view. + + + + Increase the damage caused by affected players and monsters when attacking. + + + + Reduces the damage cause by affected players and monsters when attacking. + + + + Instantly increases the affected players, animals and monsters health. + + + + Instantly reduces the affected players, animals and monsters health. + + + + Restores health to the affected players, animals and monsters over time. + + + + Makes the affected players, animals and monsters immune to damage from fire, lava, and ranged Blaze attacks. + + + + Reduces health of the affected players, animals and monsters over time. + + + + Allows affected players to breathe normally underwater. + + + + Increases the jump height of the affected player. + + + + When Applied: + + + + Horse Jump Strength + + + + Zombie Reinforcements + + + + Max Health + + + + Mob Follow Range + + + + Knockback Resistance + + + + Speed + + + + Attack Damage + + + + Sharpness + + + + Smite + + + + Bane of Arthropods + + + + Knockback + + + + Fire Aspect + + + + Protection + + + + Fire Protection + + + + Feather Falling + + + + Blast Protection + + + + Projectile Protection + + + + Respiration + + + + Aqua Affinity + + + + Depth Strider + + + + Efficiency + + + + Silk Touch + + + + Unbreaking + + + + Looting + + + + Fortune + + + + Power + + + + Flame + + + + Punch + + + + Infinity + + + + I + + + + II + + + + III + + + + IV + + + + V + + + + VI + + + + VII + + + + VIII + + + + IX + + + + X + + + + Can be mined with an Iron pickaxe or better to collect Emeralds. + + + + Similar to a Chest except that items placed in an Ender Chest are available in every one of the player's Ender Chests, even in different dimensions. + + + + Is activated when an entity passes through a connected Tripwire. + + + + Activates a connected Tripwire Hook when an entity passes through it. + + + + A compact way of storing Emeralds. + + + + A wall made of Cobblestone. + + + + Can be used to repair weapons, tools and armor. + + + + Smelted in a furnace to produce Nether Quartz. + + + + Used as a decoration. + + + + Can be traded with villagers. + + + + Used as a decoration. Flowers, Saplings, Cacti and Mushrooms can be planted in it. + + + + Restores 2{*ICON_SHANK_01*}, and can be crafted into a golden carrot. Can be planted in farmland. + + + + Restores 0.5{*ICON_SHANK_01*}, or can be cooked in a furnace. This can be planted in farmland. + + + + Restores 3{*ICON_SHANK_01*}. Created by cooking a potato in a furnace. + + + + Restores 1{*ICON_SHANK_01*}. Eating this can cause you to become poisoned. + + + + Restores 3{*ICON_SHANK_01*}. Crafted from a carrot and gold nuggets. + + + + Used to control a saddled pig when riding on it. + + + + Restores 4{*ICON_SHANK_01*}. + + + + Used with an Anvil to enchant weapons, tools or armor. + + + + Created by mining Nether Quartz Ore. Can be crafted into a Block of Quartz. + + + + Crafted from Wool. Used as a decoration. + + + + Emerald + + + + Flower Pot + + + + Carrot + + + + Potato + + + + Baked Potato + + + + Poisonous Potato + + + + Golden Carrot + + + + Carrot on a Stick + + + + Pumpkin Pie + + + + Enchanted Book + + + + Nether Quartz + + + + Emerald Ore + + + + Ender Chest + + + + Tripwire Hook + + + + Tripwire + + + + Block of Emerald + + + + Cobblestone Wall + + + + Mossy Cobblestone Wall + + + + Flower Pot + + + + Carrots + + + + Potatoes + + + + Anvil + + + + Anvil + + + + Slightly Damaged Anvil + + + + Very Damaged Anvil + + + + Nether Quartz Ore + + + + Block of Quartz + + + + Chiseled Quartz Block + + + + Pillar Quartz Block + + + + Quartz Stairs + + + + Carpet + + + + Black Carpet + + + + Red Carpet + + + + Green Carpet + + + + Brown Carpet + + + + Blue Carpet + + + + Purple Carpet + + + + Cyan Carpet + + + + Light Gray Carpet + + + + Gray Carpet + + + + Pink Carpet + + + + Lime Carpet + + + + Yellow Carpet + + + + Light Blue Carpet + + + + Magenta Carpet + + + + Orange Carpet + + + + White Carpet + + + + Chiseled Sandstone + + + + Smooth Sandstone + + + + {*PLAYER*} was killed trying to hurt {*SOURCE*} + + + + {*PLAYER*} was squashed by a falling Anvil. + + + + {*PLAYER*} was squashed by a falling block. + + + + Teleported {*PLAYER*} to {*DESTINATION*} + + + + {*PLAYER*} teleported you to their position + + + + {*PLAYER*} teleported to you + + + + Thorns + + + + Quartz Slab + + + + Makes dark areas appear as if in daylight, even under water. + + + + Makes affected players, animals and monsters invisible. + + + + Repair & Name + + + + Enchantment Cost: %d + + + + Too Expensive! + + + + Rename + + + + You have: + + + + Required Items For Trade + + + + {*VILLAGER_TYPE*} offers %s + + + + Repair + + + + Trade + + + + Dye collar + + + + + This is the Anvil interface, which you can use to rename, repair and apply enchantments to weapons, armor, or tools, at the cost of Experience Levels. + + + + + + {*B*} + Press{*CONTROLLER_VK_A*} to learn more about the Anvil interface.{*B*} + Press{*CONTROLLER_VK_B*} if you already know the Anvil interface. + + + + + + To begin working on an item, place it in the first input slot. + + + + + + When the correct raw material is placed in the second input slot (e.g. Iron Ingots for a damaged Iron Sword), the proposed repair appears in the output slot. + + + + + + Alternatively, a second identical item can be placed into the second slot to combine the two items. + + + + + + To enchant items on the Anvil, place an Enchanted Book in the second input slot. + + + + + + The number of Experience Levels that the work will cost is shown beneath the output. If you do not have enough Experience Levels, the repair cannot be completed. + + + + + + It is possible to rename the item by editing the name shown in the textbox. + + + + + + Picking up the repaired item will consume both items used by the Anvil and decrease your Experience Level by the given amount. + + + + + + In this area there is an Anvil and a Chest containing tools and weapons to work on. + + + + + + {*B*} + Press{*CONTROLLER_VK_A*} to learn more about the Anvil.{*B*} + Press{*CONTROLLER_VK_B*} if you already know about the Anvil. + + + + + + Using an Anvil, weapons and tools can be repaired to restore their durability, renamed, or enchanted with Enchanted Books. + + + + + + Enchanted Books can be found inside Chests within dungeons, or enchanted from normal Books at the Enchantment Table. + + + + + + Using the Anvil costs Experience Levels, and each use has a chance to damage the Anvil. + + + + + + The type of work to be done, value of the item, number of enchantments, and amount of prior work all affect the cost of repair. + + + + + + Renaming an item changes the displayed name for all players and permanently reduces the prior work cost. + + + + + + In the Chest in this area you will find damaged Pickaxes, raw materials, Bottles O' Enchanting, and Enchanted Books to experiment with. + + + + + + This is the trading interface which displays trades that can be made with a villager. + + + + + + {*B*} + Press{*CONTROLLER_VK_A*} to learn more about the trading interface.{*B*} + Press{*CONTROLLER_VK_B*} if you already know the trading interface. + + + + + + All trades that the villager is willing to make at the moment are displayed along the top. + + + + + + Trades will appear red and be unavailable if you do not have the required items. + + + + + + The amount and type of items you are giving to the villager are shown in the two boxes on the left. + + + + + + You can see the total number of the items required for the trade in the two boxes on the left. + + + + + + Press{*CONTROLLER_VK_A*} to trade the items the villager requires for the item on offer. + + + + + + In this area there is a villager and a Chest containing Paper to purchase items. + + + + + + {*B*} + Press{*CONTROLLER_VK_A*} to learn more about trading.{*B*} + Press{*CONTROLLER_VK_B*} if you already know about trading. + + + + + + Players can trade items from their inventory with villagers. + + + + + + The trades a villager is likely to offer depends on their profession. + + + + + + Performing a mix of trades will randomly add to or update the villager's available trades. + + + + + + Trades that have been used frequently may be removed temporarily, but the villager will always offer at least one trade. + + + + + + Take some Paper from the Chest and try trading with the villager here. + + + + + + In this area there are two Ender Chests. + + + + + + {*B*} + Press{*CONTROLLER_VK_A*} to learn more about Ender Chests.{*B*} + Press{*CONTROLLER_VK_B*} if you already know about Ender Chests. + + + + + + All Ender Chests in a world are linked, even across dimensions. Items placed into an Ender Chest are accessible in any other Ender Chest. + + + + + + However, the contents of the Ender Chests are different for each player. + + + + + + This allows players to store items in any Ender Chest, and retrieve them from other Ender Chests in different positions in the world. You can try this now by placing items in either Ender Chest. + + + + + Restores 2{*ICON_SHANK_01*}, regenerates health for 30 seconds, and grants fire resistance and damage resistance for 5 minutes. Crafted from an apple and gold blocks. + + + + Can Teleport + + + + Teleport + + + + Teleport To Player + + + + Teleport To Me + + + + Can Disable Exhaustion + + + + Can Become Invisible + + + + You can now enable invisibility + + + + You can no longer enable invisibility + + + + You can now enable flying + + + + You can no longer enable flying + + + + You can now disable exhaustion + + + + You can no longer disable exhaustion + + + + You can now teleport + + + + You can no longer teleport + + + + {*T3*}HOW TO PLAY : ANVIL{*ETW*}{*B*}{*B*} +Experience Levels can be used to repair, enchant or rename items with the Anvil.{*B*} +All items can be renamed, although only items with durability can be repaired or have enchantments from Enchanted Books applied to them.{*B*} +An item can be repaired by placing it in one of the input slots on the left, along with either some raw materials of the item, like Iron Ingots for an Iron Sword, or combined with another item of the same type.{*B*} +Combining items is more efficient when done with an Anvil, and additionally, if either of the items were enchanted, the finished product may have enchantments from either of the inputs.{*B*} +Enchanted Books can apply enchantments to items by combining them at an Anvil if the Book's enchantment is suitable. Enchanted Books can be found in Chests within dungeons, or enchanted from normal Books at the Enchantment Table.{*B*} +There is a chance that the Anvil will be damaged with each use and after enough punishment it will be destroyed.{*B*} + + + + + {*T3*}HOW TO PLAY : TRADING{*ETW*}{*B*}{*B*} +It is possible to trade items with villagers. Each villager has a profession; they can be Farmers, Butchers, Blacksmiths, Librarians or Priests, and this affects the type of items they might trade.{*B*} +You can find a list of all the trades a villager is offering in the trading menu. A villager may modify or add to its trades whenever a player trades with it, although a trade might become temporarily disabled if it is used too frequently.{*B*} +Trades usually involve buying or selling a number of items for emeralds.{*B*} +If you do not have the items required for a trade, the items are shown in red.{*B*} + + + + + {*T3*}HOW TO PLAY : ENDER CHEST {*ETW*}{*B*}{*B*} +All Ender Chests in a world are linked. Items placed into an Ender Chest are accessible in any other. However, the contents of the Ender Chests are different for each player. This allows players to store items in any Ender Chest, and retrieve them from other Ender Chests in different positions in the world. + + + + + Farmer + + + + Librarian + + + + Priest + + + + Blacksmith + + + + Butcher + + + + Found in villages, villagers will offer to sell items to the player depending on their profession. + + + + Large Chest + + + + + You can also create Enchanted Books at the Enchantment Table, which can be used later at the Anvil to apply their enchantment to an item. + + + + + + Tripwire Hooks will also provide constant power to a circuit while something is triggering the string between them. + + + + + + Once tamed, a wolf will always have its collar on. The color of their collar can be changed by dying it. + + + + + Carrots and Potatoes are farmed by planting Carrots or Potatoes, and are ready for harvesting when the vegetable is visible above the ground. + + + + + Additionally, pigs can be saddled and then ridden by players. They are controlled by tempting them with a Carrot on a Stick. + + + + + + If necessary you can slowly move your minecart along using {*CONTROLLER_ACTION_MOVE*}. This helps to start the minecart by getting it onto a powered rail. + + + + + You cannot join this game as split-screen is only supported when in High Definition mode. Sign out all other players if you wish to join. + + + + Cure + + + + Acacia Wood + + + + Dark Oak Wood + + + + Acacia Planks + + + + Dark Oak Planks + + + + Acacia Wood Stairs + + + + Dark Oak Wood Stairs + + + + Acacia Wood Slab + + + + Dark Oak Wood Slab + + + + Dark Oak Wood Slab + + + + Iron Trapdoor + + + + Spruce Door + + + + Birch Door + + + + Jungle Door + + + + Acacia Door + + + + Dark Oak Door + + + + Spruce Fence + + + + Birch Fence + + + + Jungle Fence + + + + Acacia Fence + + + + Dark Oak Fence + + + + Spruce Fence Gate + + + + Birch Fence Gate + + + + Jungle Fence Gate + + + + Acacia Fence Gate + + + + Dark Oak Fence Gate + + + + Spruce Door + + + + Birch Door + + + + Jungle Door + + + + Acacia Door + + + + Dark Oak Door + + + Armor Stand + + + + Can be equipped to display armor and other decorative items such as mob heads. + + + + Rabbit + + + + A harmless creature. May drop a rabbit hide or a rabbit's foot when killed. + + + + Rabbit Hide + + + + Used in crafting leather. + + + + Rabbit's Foot + + + + Used as an ingredient for brewing potions. + + + + Raw Rabbit + + + + Restores 0.5{*ICON_SHANK_01*}, or can be cooked in a furnace. + + + + Cooked Rabbit + + + + Restores 2.5{*ICON_SHANK_01*}. Used to cook up some rabbit stew. + + + + Raw Mutton + + + + Restores 1{*ICON_SHANK_01*}, or can be cooked in a furnace. + + + + Cooked Mutton + + + + Restores 3{*ICON_SHANK_01*}. Created by cooking raw mutton in a furnace. + + + + Acacia Sapling + + + + Dark Oak Sapling + + + + Acacia Leaves + + + + Dark Oak Leaves + + + + Red Sandstone + + + + Red Sandstone Stairs + + + + Prismarine Crystal + + + + Sea Lantern + + + + Exit Minecraft + + + + Prismarine + + + + Dark Prismarine + + + + Prismarine Bricks + + + + Prismarine Shard + + + + Rare decorative stone that can be found in Ocean Monuments. Can be crafted from Prismarine shards. + + + + A rarer form of Prismarine that can be found in Ocean Monuments. Can be crafted with Prismarine shards and an Ink Sac. + + + + Decorative Prismarine brick that can be found in Ocean Monuments. Can be crafted from Prismarine shards. + + + + Obtained from Sea Lanterns or by defeating Guardians and Elder Guardians. Can be used in crafting Sea Lanterns. + + + + Dropped by Guardians and Elder Guardians. Can be used in crafting Prismarine and Sea Lanterns. + + + + Rabbit Stew + + + + Tall Grass + + + + Large Fern + + + + Lilac + + + + Rose Bush + + + + Peony + + + + Packed Ice + + + + Sunflower + + + + A solid unmeltable block of ice that can have objects placed on it. + + + + Red colored Sandstone. It is not influenced by gravity like normal Sand. + + + + Underwater light sources that can be found in Ocean Monuments. Can be crafted from Prismarine shards and Prismarine crystals. + + + + Rare decorative stone that can be found in Ocean Monuments. Can be crafted from Prismarine shards. + + + + Double tall grass that can sometimes drop seeds. + + + + Chiseled Red Sandstone + + + + Smooth Red Sandstone + + + + Podzol + + + + Coarse Dirt + + + + Similar to Dirt Blocks, but very good for growing mushrooms on. + + + + A special type of dirt that does not grow grass. + + + + Granite + + + + Polished Granite + + + + Andesite + + + + Polished Andesite + + + + Diorite + + + + Polished Diorite + + + + Can be mined with a pickaxe to collect granite. + + + + Can be crafted from granite for a polished look. + + + + Can be mined with a pickaxe to collect andesite. + + + + Can be crafted from andesite for a polished look. + + + + Can be mined with a pickaxe to collect diorite. + + + + Can be crafted from diorite for a polished look. + + + + Red Sand + + + + Wet Sponge + + + + Can be dried in a furnace, allowing the sponge to be reused. + + + + Raw Salmon + + + + Cooked Salmon + + + + Clownfish + + + + Pufferfish + + + + Restores 1{*ICON_SHANK_01*}, or can be cooked in a furnace. Can be fed to an ocelot to tame it. + + + + Restores 3{*ICON_SHANK_01*}. Created by cooking a raw salmon in a furnace. + + + + Restores 0.5{*ICON_SHANK_01*}. + + + + Restores 0.5{*ICON_SHANK_01*} however it is poisonous. Can also be used as an ingredient in brewing potions. + + + + Blue Orchid + + + + Allium + + + + Azure Bluet + + + + Red Tulip + + + + Orange Tulip + + + + White Tulip + + + + Pink Tulip + + + + Oxeye Daisy + + + + A common red flower that can be used to craft red dye. + + + + A rare blue flower that can be used to craft light blue dye. + + + + A rare magenta flower that can be used to craft magenta dye. + + + + A small white flower that can be used to craft light gray dye. + + + + A small red flower that can be used to craft red dye. + + + + A small orange flower that can be used to craft orange dye. + + + + A small white flower that can be used to craft light gray dye. + + + + A small pink flower that can be used to craft pink dye. + + + + A common white and yellow flower that can be used to craft light gray dye. + + + + A tall yellow flower that can be used to craft yellow dye. + + + + A tall purple flower that can be used to craft magenta dye. + + + + A tall fern that can sometimes drop seeds. + + + + A tall red flower that can be used to craft red dye. + + + + A tall green and pink flower that can be used to craft pink dye. + + + + Endermite + + + + Guardian + + + + Elder Guardian + + + + Written Book + + + + A book signed by the author (cannot be written in). + + + + Book and Quill + + + + A Book that can be written in. + + + + Next Page + + + + Previous Page + + + + Add Page + + + + Exit Book + + + + Are you sure you want to exit this book and the changes you've made? + + + + Lure + + + + Luck of the Sea + + + Red Sandstone Slab + + + Elytra + + + Taking Inventory + Open your inventory. + + Getting Wood + Punch a tree until a block of wood pops out. + + Benchmarking + Craft a Workbench with four blocks of Wooden Planks. + + Time to Mine! + Use Planks and Sticks to make a Pickaxe. + + Hot Topic + Construct a Furnace out of eight Cobblestone blocks. + + Acquire Hardware + Smelt an Iron Ingot. + + Time to Farm! + Make a Hoe. + + Bake Bread + Turn Wheat into Bread. + + The Lie + Bake a Cake using: Wheat, Sugar, Milk and Eggs. + + Getting an Upgrade + Construct a better pickaxe. + + Delicious Fish + Catch and cook Fish! + + On A Rail + Travel by Minecart to a point at least 500m in a single direction from where you started. + + Time to Strike! + Use Planks and Sticks to make a Sword. + + Monster Hunter + Attack and destroy a monster. + + Cow Tipper + Harvest some leather. + + When Pigs Fly + Use a Saddle to ride a Pig, and then have the Pig get hurt from fall damage while riding it. + + Leader of the Pack + Befriend five Wolves. + + MOAR Tools + Construct one type of each tool. + + Dispense With This + Construct a dispenser. + + Into The Nether + Construct a Nether Portal. + + Pork Chop + Cook and eat a Pork Chop. + + Passing the Time + Play for 100 days. + + Archer + Kill a Creeper with Arrows. + + Sniper Duel + Kill a Skeleton with an Arrow from more than 50 meters. + + DIAMONDS! + Acquire diamonds with your iron tools. + + Return to Sender + Destroy a Ghast with a Fireball. + + Into Fire + Relieve a Blaze of its rod. + + Local Brewery + Brew a potion. + + The End? + Enter an End Portal. + + The End. + Kill the Enderdragon. + + Enchanter + Construct an Enchantment Table. + + Overkill + Deal nine hearts of damage in a single hit. + + Librarian + Build some Bookshelves to improve your Enchantment Table. + + Adventuring Time + Discover all biomes. + + Repopulation + Breed two Cows with Wheat. + + Diamonds to you! + Throw diamonds to another player. + + The Haggler + Mine or purchase 30 Emeralds. + + Pot Planter + Craft and place a Flower pot. + + It's a Sign! + Craft and place a sign. + + Iron Belly + Stop starvation using rotten flesh. + + Have a Shearful Day + Use Shears to obtain Wool from a Sheep. + + Rainbow Collection + Gather all 16 colors of Wool. + + Stayin' Frosty + Swim in Lava while having the Fire Resistance effect. + + Chestful of Cobblestone + Mine 1,728 Cobblestone and place it in a Chest. + + Renewable Energy + Smelt Wood Trunks using Charcoal to make more Charcoal. + + Music to my Ears + Play a Music Disc in a Jukebox. + + Body Guard + Create an Iron Golem. + + Iron Man + Wear a full suit of Iron Armor. + + Zombie Doctor + Cure a Zombie Villager. + + Lion Tamer + Tame an ocelot. + + Hold {*CONTROLLER_VK_Y*} to view + + Classic Crafting + + + Restores 5{*ICON_SHANK_01*}. + + + + Safe Sprint] + + + + Swap + + diff --git a/Minecraft.Client/Windows64Media/old_strings.h b/Minecraft.Client/Windows64Media/old_strings.h index f87d6e69..de893827 100644 --- a/Minecraft.Client/Windows64Media/old_strings.h +++ b/Minecraft.Client/Windows64Media/old_strings.h @@ -2482,3 +2482,5 @@ #define IDS_RICHPRESENCESTATE_BREWING 2284 #define IDS_RICHPRESENCESTATE_ANVIL 2285 #define IDS_RICHPRESENCESTATE_TRADING 2286 +#define IDS_SAFE_SPRINT 2288 +#define IDS_SWAP 2289 diff --git a/Minecraft.World/Layer.cpp b/Minecraft.World/Layer.cpp index 52010d59..62091d81 100644 --- a/Minecraft.World/Layer.cpp +++ b/Minecraft.World/Layer.cpp @@ -71,7 +71,7 @@ LayerArray Layer::getDefaultLayers(int64_t seed, LevelType* levelType, void* sup riverLayerFinal = make_shared(seed, riverLayerFinal, 0x3E8); shared_ptr biomeLayer = make_shared(seed, baseLayer, 0xC8, levelType, superflatConfig); - biomeLayer = ZoomLayer::zoom(seed, biomeLayer, 0x3E8, 2); + biomeLayer = ZoomLayer::zoom(seed, biomeLayer, 0x3E8, 0); biomeLayer = make_shared(seed, biomeLayer, 0x3E8); biomeLayer = make_shared(seed, biomeLayer, hillsNoise, 0x3E8); biomeLayer = make_shared(seed, biomeLayer, 0x3E9);