Decompiled source of BRC Archipelago v1.0.3
plugins/Archipelago.dll
Decompiled 5 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using Archipelago.BRC.Apps; using Archipelago.BRC.Components; using Archipelago.BRC.Patches; using Archipelago.BRC.Properties; using Archipelago.BRC.Stages; using Archipelago.BRC.Structures; using Archipelago.MultiClient.Net; using Archipelago.MultiClient.Net.BounceFeatures.DeathLink; using Archipelago.MultiClient.Net.Enums; using Archipelago.MultiClient.Net.Helpers; using Archipelago.MultiClient.Net.Models; using Archipelago.MultiClient.Net.Packets; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using DG.Tweening; using HarmonyLib; using Microsoft.CodeAnalysis; using ModLocalizer; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Reptile; using Reptile.Phone; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; using brc_styleswapmod; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("Archipelago")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Connect to an Archipelago server to play Bomb Rush Cyberfunk randomizer.")] [assembly: AssemblyFileVersion("0.9.0.0")] [assembly: AssemblyInformationalVersion("0.9.0+071a9a34a137e1aee39f0e9fc920f4ff49728bf1")] [assembly: AssemblyProduct("Archipelago")] [assembly: AssemblyTitle("Archipelago")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.9.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Archipelago.BRC { [BepInPlugin("trpg.brc.archipelago", "Archipelago", "1.0.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Core : BaseUnityPlugin { public const string PluginGUID = "trpg.brc.archipelago"; public const string PluginName = "Archipelago"; public const string PluginVersion = "1.0.3"; internal static GameVersion TargetGameVersion; public static Core Instance; public Data Data = new Data(); public UIManager UIManager = new UIManager(); public PhoneManager PhoneManager = new PhoneManager(); public Multiworld Multiworld = new Multiworld(); public LocationManager LocationManager = new LocationManager(); public SaveManager SaveManager = new SaveManager(); public StageManager stageManager = null; public static ManualLogSource Logger = Logger.CreateLogSource("Archipelago"); public static ConfigEntry<string> configDefaultName; public static ConfigEntry<string> configDefaultAddress; public static ConfigEntry<string> configDefaultPassword; public static ConfigEntry<Color> configColorPlayerSelf; public static ConfigEntry<Color> configColorPlayerOther; public static ConfigEntry<Color> configColorItemAdvancement; public static ConfigEntry<Color> configColorItemNeverExclude; public static ConfigEntry<Color> configColorItemFiller; public static ConfigEntry<Color> configColorItemTrap; public static ConfigEntry<Color> configColorLocation; public static ConfigEntry<bool> configPlayerOtherNotifs; public static ConfigEntry<bool> configDontSavePhotos; internal static bool isQuickStyleSwapLoaded = false; internal static bool isSlopCrewLoaded = false; internal static int forbiddenModsLoaded = 0; internal static string forbiddenGUIDs = string.Empty; private readonly List<string> forbiddenMods = new List<string> { "QuickGraffiti", "com.Dragsun.FastCypher", "dance.tari.bombrushcyberfunk.customgraffiti", "TombRush" }; public PluginLocalizer Localizer { get; private set; } public static GameFontType MainFont { get; private set; } public static GameFontType MainFontEnglish { get; private set; } public static GameFontType PhoneFont { get; private set; } public static bool FailScoreEncounters { get; private set; } = false; private void CheckForbiddenMods() { forbiddenModsLoaded = 0; forbiddenGUIDs = string.Empty; foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos) { if (forbiddenMods.Contains(pluginInfo.Value.Metadata.GUID)) { forbiddenModsLoaded++; Logger.LogWarning((object)("A forbidden mod is loaded. (\"" + pluginInfo.Value.Metadata.GUID + "\")")); if (forbiddenGUIDs == string.Empty) { forbiddenGUIDs = "\"" + pluginInfo.Value.Metadata.GUID + "\""; } else { forbiddenGUIDs = (forbiddenGUIDs = forbiddenGUIDs + ", \"" + pluginInfo.Value.Metadata.GUID + "\""); } } } } private void Awake() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown //IL_04c1: Unknown result type (might be due to invalid IL or missing references) //IL_04cb: Expected O, but got Unknown //IL_04d3: Unknown result type (might be due to invalid IL or missing references) //IL_04dd: Expected O, but got Unknown //IL_0569: Unknown result type (might be due to invalid IL or missing references) //IL_059c: Unknown result type (might be due to invalid IL or missing references) //IL_05cf: Unknown result type (might be due to invalid IL or missing references) //IL_0602: Unknown result type (might be due to invalid IL or missing references) //IL_0635: Unknown result type (might be due to invalid IL or missing references) //IL_0668: Unknown result type (might be due to invalid IL or missing references) //IL_069b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Instance != (Object)null) { Object.Destroy((Object)(object)this); } Instance = this; TargetGameVersion = ScriptableObject.CreateInstance<GameVersion>(); TargetGameVersion.major = 1; TargetGameVersion.minor = 0; TargetGameVersion.repositoryRevision = 20381; string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); Localizer = new PluginLocalizer("Archipelago", Path.Combine(directoryName, "Languages"), (SystemLanguage)10); Localizer.OnLanguageChanged += new OnLanguageChangedDelegate(UIManager.UpdateLanguage); Localizer.OnInitializationFinished += (OnInitializationFinishedDelegate)delegate { MainFont = Localizer.LoadFontTypeAndRemoveUnusedFonts((GameFontTypes)3); MainFontEnglish = Localizer.LoadFontTypeEnglishOnly((GameFontTypes)3); PhoneFont = Localizer.LoadFontTypeAndRemoveUnusedFonts((GameFontTypes)30); }; Harmony val = new Harmony("Archipelago"); val.PatchAll(typeof(AppCamera_WaitForPhotoSavingComplete)); val.PatchAll(typeof(AppGraffiti_OnHoldDown_Patch)); val.PatchAll(typeof(AppGraffiti_OnHoldUp_Patch)); val.PatchAll(typeof(AppGraffiti_OnPressDown_Patch)); val.PatchAll(typeof(AppGraffiti_OnPressRight_Patch)); val.PatchAll(typeof(AppGraffiti_OnPressUp_Patch)); val.PatchAll(typeof(AppGraffiti_OnReleaseRight_Patch)); val.PatchAll(typeof(AppGraffiti_OpenInfo_Patch)); val.PatchAll(typeof(AppGraffiti_RefreshList_Patch)); val.PatchAll(typeof(BaseModule_HandleStageFullyLoaded_Patch)); val.PatchAll(typeof(BaseModule_SaveBeforeStageExit_Patch)); val.PatchAll(typeof(BaseModule_QuitCurrentGameSession_Patch)); val.PatchAll(typeof(BaseModule_StartNewGame_Patch)); val.PatchAll(typeof(CharacterSelect_PopulateListOfSelectableCharacters_Patch)); val.PatchAll(typeof(Collectable_PickupCollectable_Patch)); val.PatchAll(typeof(DieAbility_OnStartAbility_Patch)); val.PatchAll(typeof(DynamicPickup_PickupPickup_Patch)); val.PatchAll(typeof(Encounter_SetEncounterState_Patch)); val.PatchAll(typeof(GameplayEvent_UnlockCameraAppForPlayer_Patch)); val.PatchAll(typeof(GameplayEvent_UnlockCharacterImpl_Patch)); val.PatchAll(typeof(GraffitiGame_OnDestroy_Patch)); val.PatchAll(typeof(GraffitiGame_SetState_Patch)); val.PatchAll(typeof(GraffitiGame_SetStateVisual_Patch)); val.PatchAll(typeof(GraffitiInfoPanel_Show_Patch)); val.PatchAll(typeof(GraffitiScrollButton_SetContent_Patch)); val.PatchAll(typeof(GraffitiSpot_GiveRep_Patch)); val.PatchAll(typeof(GraffitiSpot_SpawnRep_Patch)); val.PatchAll(typeof(HomescreenButton_SetContent_Patch)); val.PatchAll(typeof(LocalizationLookupTable_GetLocalizationValueFromSubgroup_Patch)); val.PatchAll(typeof(PhoneScrollUnlockableButton_SetContent_Patch)); val.PatchAll(typeof(PhotoObjectiveProgressable_MadePhotograph_Patch)); val.PatchAll(typeof(PhotosManager_SavePhoto_Patch)); val.PatchAll(typeof(PhotosManager_IsPhotoStorageFull)); val.PatchAll(typeof(Player_ChangeHP_Patch)); val.PatchAll(typeof(Player_CheckNPCTriggerForConversation_Patch)); val.PatchAll(typeof(Player_OnTriggerEnter_Patch)); val.PatchAll(typeof(Player_OnTriggerExit_Patch)); val.PatchAll(typeof(Player_StartGraffitiMode_Patch)); val.PatchAll(typeof(ScoreEncounter_StartMainEvent_Patch)); val.PatchAll(typeof(SaveManager_SaveCurrentSaveSlot_Patch)); val.PatchAll(typeof(SaveSlotData_UnlockCharacter_Patch)); val.PatchAll(typeof(SaveSlotMenu_OnPressedPopupDeleteButton_Patch)); val.PatchAll(typeof(SaveSlotMenu_ShowDeleteSaveSlotPopup_Patch)); val.PatchAll(typeof(TextMeshProGameTextLocalizer_GetRawDialogueTextValue_Patch)); val.PatchAll(typeof(Type_GetType_Patch)); val.PatchAll(typeof(UIManager_InstantiateMainMenuSceneUI_Patch)); val.PatchAll(typeof(UIManager_HideDieMenu_Patch)); val.PatchAll(typeof(UIManager_ShowDieMenu_Patch)); val.PatchAll(typeof(VendingMachine_RewardIsValid_Patch)); val.PatchAll(typeof(VersionUIHandler_SetVersionText_Patch)); foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos) { if (pluginInfo.Value.Metadata.GUID == "com.yuril.brc_styleswapmod") { isQuickStyleSwapLoaded = true; Logger.LogInfo((object)"QuickStyleSwap is loaded. Applying SwapStyle patch."); val.PatchAll(typeof(brc_styleswapmodPlugin_SwapStyle_Patch)); } else if (pluginInfo.Value.Metadata.GUID == "SlopCrew.Plugin") { isSlopCrewLoaded = true; } } Core.OnCoreInitialized += new OnCoreInitializedHandler(SaveManager.GetSavePath); Core.OnCoreInitialized += new OnCoreInitializedHandler(CheckForbiddenMods); configDefaultName = ((BaseUnityPlugin)this).Config.Bind<string>("Defaults", "defaultName", "Red", "The default name used when opening the connection menu for a slate with no save data."); configDefaultAddress = ((BaseUnityPlugin)this).Config.Bind<string>("Defaults", "defaultAddress", "archipelago.gg", "The default address used when opening the connection menu for a slate with no save data."); configDefaultPassword = ((BaseUnityPlugin)this).Config.Bind<string>("Defaults", "defaultPassword", "", "The default password used when opening the connection menu for a slate with no save data."); configColorPlayerSelf = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "colorPlayerSelf", new Color(0.93f, 0f, 0.93f), "The color used to represent you."); configColorPlayerOther = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "colorPlayerOther", new Color(0.98f, 0.98f, 0.92f), "The color used to represent other players."); configColorItemAdvancement = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "colorItemAdvancement", new Color(0.69f, 0.6f, 0.94f), "The color used to represent items that are important for progression."); configColorItemNeverExclude = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "colorItemNeverExclude", new Color(0.43f, 0.55f, 0.91f), "The color used to represent items that are useful."); configColorItemFiller = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "colorItemFiller", new Color(0f, 0.93f, 0.93f), "The color used to represent items that are not very important."); configColorItemTrap = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "colorItemTrap", new Color(0.98f, 0.5f, 0.45f), "The color used to represent items that are traps."); configColorLocation = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "colorLocation", new Color(0f, 1f, 0.5f), "The color used to represent locations."); configPlayerOtherNotifs = ((BaseUnityPlugin)this).Config.Bind<bool>("Notifications", "otherPlayerNotifs", true, "Get phone notifications when collecting items that belong to other players."); configDontSavePhotos = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "dontSavePhotos", false, "Don't save photos taken with the Camera app. Only takes effect when playing randomizer."); } } public class Data { public long index; public string host_name; public string slot_name; public string password; public HashSet<string> @checked = new HashSet<string>(); public Logic logic = Logic.Glitchless; public bool skipIntro = true; public bool skipDreams = false; public bool skipHands = false; public int totalRep = 1400; public bool endingRep = false; public ScoreDifficulty scoreDifficulty = ScoreDifficulty.Normal; public HashSet<string> to_lock = new HashSet<string> { "OVERWHELMME", "QUICK BING", "WHOLE SIXER", "Graffo Le Fou", "WILD STRUXXA", "Bombing by FireMan" }; public bool limitedGraffiti = false; public SGraffiti sGraffiti = SGraffiti.Separate; public Dictionary<string, int> grafUses = new Dictionary<string, int>(); public int sMax = 5; public bool junkPhotos = false; public int fakeRep = 0; public int sprayCount = 0; public MoveStyle startingMovestyle = (MoveStyle)2; public bool skateboardUnlocked = true; public bool inlineUnlocked = false; public bool bmxUnlocked = false; public Characters firstCharacter = (Characters)(-1); public bool dummyUnlocked = false; public int damageMultiplier = 1; public bool deathLink = false; } public class LocationManager { public Dictionary<string, long> locations = new Dictionary<string, long>(); public List<AItem> itemQueue = new List<AItem>(); public List<Notification> notifQueue = new List<Notification>(); public void CheckLocation(string loc, bool playSound = true) { if (!Core.Instance.Data.@checked.Contains(loc)) { Core.Instance.Data.@checked.Add(loc); } if (locations.ContainsKey(loc) && Core.Instance.Multiworld.Authenticated) { Core.Logger.LogInfo((object)$"Checking location \"{loc}\" | {locations[loc]}"); Core.Instance.Multiworld.Session.Locations.CompleteLocationChecks(new long[1] { locations[loc] }); if (playSound && !Core.Instance.Data.@checked.Contains(loc)) { Core.Instance.UIManager.PlaySfxGameplay((SfxCollectionID)23, (AudioClipID)371); } } else { Core.Logger.LogWarning((object)("Location \"" + loc + "\" does not exist.")); } } public void GetItem(AItem item, bool playSound = true) { //IL_073f: Unknown result type (might be due to invalid IL or missing references) //IL_0744: Unknown result type (might be due to invalid IL or missing references) //IL_0750: Unknown result type (might be due to invalid IL or missing references) //IL_0756: Invalid comparison between Unknown and I4 //IL_076f: Unknown result type (might be due to invalid IL or missing references) //IL_0772: Invalid comparison between Unknown and I4 //IL_0768: Unknown result type (might be due to invalid IL or missing references) //IL_076a: Unknown result type (might be due to invalid IL or missing references) //IL_0794: Unknown result type (might be due to invalid IL or missing references) //IL_08d2: Unknown result type (might be due to invalid IL or missing references) //IL_03b6: Unknown result type (might be due to invalid IL or missing references) Core.Instance.PhoneManager.appArchipelago.UpdateText(); if (playSound) { Core.Instance.UIManager.PlaySfxGameplay((SfxCollectionID)23, (AudioClipID)371); } if (item is BRCItem bRCItem && item.player_name == Core.Instance.Data.slot_name) { switch (bRCItem.type) { case BRCType.Music: { string name = bRCItem.item_name.Substring(7, bRCItem.item_name.Length - 8); MusicTrack musicTrack = GetMusicTrack(GetMusicAssetName(name)); Core.Instance.SaveManager.CurrentSaveSlot.GetUnlockableDataByUid(((AUnlockable)musicTrack).Uid).IsUnlocked = true; Core.Instance.PhoneManager.Phone.GetAppInstance<AppMusicPlayer>().GameMusicPlayer.AddMusicTrack(musicTrack); if (!bRCItem.received) { notifQueue.Add(new Notification("AppMusicPlayer", Core.Instance.Localizer.GetRawTextValue((Subgroups)0, "COLLECTIBLE_MUSIC") + " (" + musicTrack.Title + ")", (AUnlockable)(object)musicTrack)); } break; } case BRCType.GraffitiM: case BRCType.GraffitiL: case BRCType.GraffitiXL: { string name = ((bRCItem.type != BRCType.GraffitiXL) ? bRCItem.item_name.Substring(14, bRCItem.item_name.Length - 15) : bRCItem.item_name.Substring(15, bRCItem.item_name.Length - 16)); if (bRCItem.type == BRCType.GraffitiM) { Core.Instance.stageManager.YesGraffiti((GraffitiSize)1); } else if (bRCItem.type == BRCType.GraffitiL) { Core.Instance.stageManager.YesGraffiti((GraffitiSize)2); } else if (bRCItem.type == BRCType.GraffitiXL) { Core.Instance.stageManager.YesGraffiti((GraffitiSize)3); } if (Core.Instance.Data.to_lock.Contains(name)) { Core.Instance.Data.to_lock.Remove(name); } GraffitiAppEntry unlockable = WorldHandler.instance.graffitiArtInfo.FindByTitle(name).unlockable; if (!Core.Instance.Data.limitedGraffiti || (Core.Instance.Data.limitedGraffiti && (!Core.Instance.Data.grafUses.ContainsKey(((AUnlockable)unlockable).Uid) || (Core.Instance.Data.grafUses.ContainsKey(((AUnlockable)unlockable).Uid) && !bRCItem.received)))) { Core.Instance.SaveManager.CurrentSaveSlot.GetUnlockableDataByUid(((AUnlockable)unlockable).Uid).IsUnlocked = true; } if (Core.Instance.Data.limitedGraffiti && (!Core.Instance.Data.grafUses.ContainsKey(((AUnlockable)unlockable).Uid) || (Core.Instance.Data.grafUses.ContainsKey(((AUnlockable)unlockable).Uid) && !bRCItem.received))) { Core.Instance.Data.grafUses[((AUnlockable)unlockable).Uid] = 0; } if (!bRCItem.received) { notifQueue.Add(new Notification("AppGraffiti", string.Format("{0} ({1} - {2})", Core.Instance.Localizer.GetRawTextValue((Subgroups)0, "COLLECTIBLE_GRAFFITI"), unlockable.Size, unlockable.Title), (AUnlockable)(object)unlockable)); } break; } case BRCType.Skateboard: { string name = bRCItem.item_name.Substring(12, bRCItem.item_name.Length - 13); Core.Instance.Data.skateboardUnlocked = true; if (Core.Instance.stageManager is HideoutManager) { ((HideoutManager)Core.Instance.stageManager).SetSkateboardGarage(open: true); } MoveStyleSkin skateboardSkin = GetSkateboardSkin(GetSkateboardAssetName(name)); Core.Instance.SaveManager.CurrentSaveSlot.GetUnlockableDataByUid(((AUnlockable)skateboardSkin).Uid).IsUnlocked = true; if (!bRCItem.received) { notifQueue.Add(new Notification("AppArchipelago", Core.Instance.Localizer.GetRawTextValue((Subgroups)0, "VALUE_MOVESTYLE_SKATEBOARD") + " " + bRCItem.item_name.Substring(11), null)); } break; } case BRCType.InlineSkates: { string name = bRCItem.item_name.Substring(15, bRCItem.item_name.Length - 16); Core.Instance.Data.inlineUnlocked = true; if (Core.Instance.stageManager is HideoutManager) { ((HideoutManager)Core.Instance.stageManager).SetInlineGarage(open: true); } MoveStyleSkin inlineSkin = GetInlineSkin(GetInlineAssetName(name)); Core.Instance.SaveManager.CurrentSaveSlot.GetUnlockableDataByUid(((AUnlockable)inlineSkin).Uid).IsUnlocked = true; if (!bRCItem.received) { notifQueue.Add(new Notification("AppArchipelago", Core.Instance.Localizer.GetRawTextValue((Subgroups)0, "VALUE_MOVESTYLE_INLINE") + " " + bRCItem.item_name.Substring(14), null)); } break; } case BRCType.BMX: { string name = bRCItem.item_name.Substring(5, bRCItem.item_name.Length - 6); Core.Instance.Data.bmxUnlocked = true; if (Core.Instance.stageManager is HideoutManager) { ((HideoutManager)Core.Instance.stageManager).SetBMXGarage(open: true); } MoveStyleSkin bMXSkin = GetBMXSkin(GetBMXAssetName(name)); Core.Instance.SaveManager.CurrentSaveSlot.GetUnlockableDataByUid(((AUnlockable)bMXSkin).Uid).IsUnlocked = true; if (!bRCItem.received) { notifQueue.Add(new Notification("AppArchipelago", Core.Instance.Localizer.GetRawTextValue((Subgroups)0, "VALUE_MOVESTYLE_BMX") + " " + bRCItem.item_name.Substring(4), null)); } break; } case BRCType.Outfit: { string name = bRCItem.item_name.Substring(8, bRCItem.item_name.Length - 9); OutfitUnlockable outfitUnlockable = GetOutfitUnlockable(GetOutfitAssetName(name)); Core.Instance.SaveManager.CurrentSaveSlot.GetUnlockableDataByUid(((AUnlockable)outfitUnlockable).Uid).IsUnlocked = true; if (!bRCItem.received) { notifQueue.Add(new Notification("AppArchipelago", Core.Instance.Localizer.GetRawTextValue((Subgroups)0, "COLLECTIBLE_OUTFIT") + " " + bRCItem.item_name.Substring(7), null)); } break; } case BRCType.Character: { Core.Instance.SaveManager.CurrentSaveSlot.characterSelectLocked = false; Characters val = NameToCharacter(bRCItem.item_name); if ((int)Core.Instance.Data.firstCharacter == -1) { Core.Instance.Data.firstCharacter = val; } if ((int)val == 8) { Core.Instance.Data.dummyUnlocked = true; } Core.Instance.SaveManager.UnlockCharacter(val); if (Core.Instance.Data.limitedGraffiti) { if (Core.Instance.Data.sGraffiti == SGraffiti.Separate) { if (!Core.Instance.Data.grafUses.ContainsKey(((object)(Characters)(ref val)).ToString()) || (Core.Instance.Data.grafUses.ContainsKey(((object)(Characters)(ref val)).ToString()) && !bRCItem.received)) { Core.Instance.Data.grafUses[((object)(Characters)(ref val)).ToString()] = 0; } } else if (Core.Instance.Data.sMax < 5 * Core.Instance.SaveManager.CountCharactersUnlocked()) { Core.Instance.Data.sMax += 5; } } ((App)Core.Instance.PhoneManager.Phone.GetAppInstance<AppGraffiti>()).OnAppRefresh(); if (!bRCItem.received) { notifQueue.Add(new Notification("AppArchipelago", Core.Instance.Localizer.GetCharacterName(val), null)); } break; } case BRCType.REP: { int num = int.Parse(bRCItem.item_name.Substring(0, bRCItem.item_name.Length - 4)); Core.Instance.Data.fakeRep += num; if (Core.Instance.BaseModule.IsPlayingInStage) { Traverse.Create((object)WorldHandler.instance.GetCurrentPlayer()).Field<float>("rep").Value = Core.Instance.Data.fakeRep; Core.Instance.SaveManager.CurrentSaveSlot.GetCurrentStageProgress().reputation = Core.Instance.Data.fakeRep; foreach (RandoRequirement requirementCollider in Core.Instance.stageManager.requirementColliders) { if ((requirementCollider.Needs == RequirementNeeds.REP || requirementCollider.Needs == RequirementNeeds.Both) && Core.Instance.Data.fakeRep >= requirementCollider.Rep) { requirementCollider.EnableTrigger(RequirementNeeds.REP); } } } if (!bRCItem.received) { notifQueue.Add(new Notification("AppArchipelago", bRCItem.item_name, null)); } break; } case BRCType.Camera: WorldHandler.instance.GetCurrentPlayer().LockCameraApp(false); if (!bRCItem.received) { notifQueue.Add(new Notification("AppArchipelago", bRCItem.item_name, null)); } break; } Core.Instance.SaveManager.SaveCurrentSaveSlot(); } else if (item is APItem aPItem) { notifQueue.Add(new Notification("AppArchipelago", aPItem.item_name + " (" + aPItem.player_name + ")", null)); } else { notifQueue.Add(new Notification("AppArchipelago", item.item_name + " (" + item.player_name + ")", null)); } } public void CountAndCheckSpray() { if (Core.Instance.Data.sprayCount < 389) { Core.Instance.Data.sprayCount++; } Core.Logger.LogInfo((object)$"Spray count is {Core.Instance.Data.sprayCount}"); if (Core.Instance.Data.sprayCount == 389) { CheckLocation("graf389"); } else if (Core.Instance.Data.sprayCount % 5 == 0) { CheckLocation($"graf{Core.Instance.Data.sprayCount}"); } } public BRCType GetItemType(string name) { if (name.Contains("Music (")) { return BRCType.Music; } if (name.Contains("Graffiti (M")) { return BRCType.GraffitiM; } if (name.Contains("Graffiti (L")) { return BRCType.GraffitiL; } if (name.Contains("Graffiti (XL")) { return BRCType.GraffitiXL; } if (name.Contains("Skateboard (")) { return BRCType.Skateboard; } if (name.Contains("Inline Skates (")) { return BRCType.InlineSkates; } if (name.Contains("BMX (")) { return BRCType.BMX; } if (name.Contains("Outfit (")) { return BRCType.Outfit; } if (name.Contains(" REP")) { return BRCType.REP; } if (name.Contains("Camera")) { return BRCType.Camera; } return BRCType.Character; } public MusicTrack GetMusicTrack(string name) { return Core.Instance.Assets.LoadAssetFromBundle<MusicTrack>("coreassets", "assets/games/phone/appassets/musicplayer/musictrackunlocks/musictrack_" + name + ".asset"); } public string GetMusicAssetName(string name) { return name switch { "GET ENUF" => "getenuf", "Chuckin Up" => "chuckinup", "Spectres" => "spectres", "You Can Say Hi" => "youcansayhi", "JACK DA FUNK" => "jackdafunk", "Feel The Funk (Computer Love)" => "feelthefunk", "Big City Life" => "bigcitylife", "I Wanna Kno" => "wannakno", "Plume" => "plume", "Two Days Off" => "twodaysoff", "Scraped On The Way Out" => "scrapedonthewayout", "Last Hoorah" => "lasthoorah", "State of Mind" => "stateofmind", "AGUA" => "agua", "Condensed milk" => "condensedmilk", "Light Switch" => "lightswitch", "Hair Dun Nails Dun" => "hairdunnailsdun", "Precious Thing" => "preciousthing", "Next To Me" => "nexttome", "Refuse" => "refuse", "Iridium" => "iridium", "Funk Express" => "funkexpress", "In The Pocket" => "inthepocket", "Bounce Upon A Time" => "bounceuponatime", "hwbouths" => "hwbouths", "Morning Glow" => "morningglow", "Chromebies" => "chromebies", "watchyaback!" => "watchyaback", "Anime Break" => "missingbreak", "DA PEOPLE" => "dapeople", "Trinitron" => "trinitron", "Operator" => "operator", "Sunshine Popping Mixtape" => "chapter1mixtape", "House Cats Mixtape" => "chapter2mixtape", "Breaking Machine Mixtape" => "chapter3mixtape", "Beastmode Hip Hop Mixtape" => "chapter4mixtape", _ => "?", }; } public MoveStyleSkin GetSkateboardSkin(string name) { return Core.Instance.Assets.LoadAssetFromBundle<MoveStyleSkin>("in_game_assets", "assets/common assets/vfx/unlockables/skateboardunlockables/" + name + ".asset"); } public string GetSkateboardAssetName(string name) { return name switch { "Devon" => "SkateboardDeck2", "Terrence" => "SkateboardDeck3", "Maceo" => "SkateboardDeck4", "Lazer Accuracy" => "SkateboardDeck5", "Death Boogie" => "SkateboardDeck6", "Sylk" => "SkateboardDeck7", "Taiga" => "SkateboardDeck8", "Just Swell" => "SkateboardDeck9", "Mantra" => "SkateboardDeck10", _ => "?", }; } public MoveStyleSkin GetInlineSkin(string name) { return Core.Instance.Assets.LoadAssetFromBundle<MoveStyleSkin>("in_game_assets", "assets/common assets/vfx/unlockables/inlineunlockables/" + name + ".asset"); } public string GetInlineAssetName(string name) { return name switch { "Glaciers" => "InlineSkates2", "Sweet Royale" => "InlineSkates3", "Strawberry Missiles" => "InlineSkates4", "Ice Cold Killers" => "InlineSkates5", "Red Industry" => "InlineSkates6", "Mech Adversary" => "InlineSkates7", "Orange Blasters" => "InlineSkates8", "ck" => "InlineSkates9", "Sharpshooters" => "InlineSkates10", _ => "?", }; } public MoveStyleSkin GetBMXSkin(string name) { return Core.Instance.Assets.LoadAssetFromBundle<MoveStyleSkin>("in_game_assets", "assets/common assets/vfx/unlockables/bmxunlockables/" + name + ".asset"); } public string GetBMXAssetName(string name) { return name switch { "Mr. Taupe" => "BMXBike2", "Gum" => "BMXBike3", "Steel Wheeler" => "BMXBike4", "oyo" => "BMXBike5", "Rigid No.6" => "BMXBike6", "Ceremony" => "BMXBike7", "XXX" => "BMXBike8", "Terrazza" => "BMXBike9", "Dedication" => "BMXBike10", _ => "?", }; } public OutfitUnlockable GetOutfitUnlockable(string name) { return Core.Instance.Assets.LoadAssetFromBundle<OutfitUnlockable>("in_game_assets", "assets/common assets/vfx/unlockables/playeroutfits/" + name + ".asset"); } public string GetOutfitAssetName(string name) { return name switch { "Red - Autumn" => "MetalheadOutfit3", "Red - Winter" => "MetalheadOutfit4", "Tryce - Autumn" => "BlockGuyOutfit3", "Tryce - Winter" => "BlockGuyOutfit4", "Bel - Autumn" => "SpacegirlOutfit3", "Bel - Winter" => "SpacegirlOutfit4", "Vinyl - Autumn" => "VinylOutfit3", "Vinyl - Winter" => "VinylOutfit4", "Solace - Autumn" => "DummyOutfit3", "Solace - Winter" => "DummyOutfit4", "Felix - Autumn" => "LegendFaceOutfit3", "Felix - Winter" => "LegendFaceOutfit4", "Rave - Autumn" => "AngelOutfit3", "Rave - Winter" => "AngelOutfit4", "Mesh - Autumn" => "WideKidOutfit3", "Mesh - Winter" => "WideKidOutfit4", "Shine - Autumn" => "BunGirlOutfit3", "Shine - Winter" => "BunGirlOutfit4", "Rise - Autumn" => "PufferGirlOutfit3", "Rise - Winter" => "PufferGirlOutfit4", "Coil - Autumn" => "RingDudeOutfit3", "Coil - Winter" => "RingDudeOutfit4", _ => "?", }; } public Characters NameToCharacter(string name) { //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) return (Characters)(name switch { "Tryce" => 4, "Bel" => 5, "Vinyl" => 0, "Solace" => 8, "Felix" => 15, "Rave" => 6, "Mesh" => 19, "Shine" => 22, "Rise" => 21, "Coil" => 2, "Frank" => 1, "Rietveld" => 14, "DJ Cyber" => 9, "Eclipse" => 10, "DOT.EXE" => 7, "Devil Theory" => 11, "Flesh Prince" => 13, "Futurism" => 20, "Oldhead" => 16, _ => 3, }); } public Color GetAPItemColor(ItemFlags flag) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected I4, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) return (Color)((flag - 1) switch { 0 => Core.configColorItemAdvancement.Value, 1 => Core.configColorItemNeverExclude.Value, 3 => Core.configColorItemTrap.Value, _ => Core.configColorItemFiller.Value, }); } } public class Multiworld { public static int[] AP_VERSION = new int[3] { 0, 5, 0 }; public bool Authenticated; public ArchipelagoSession Session; public static List<string> messages = new List<string>(); public DeathLinkService DeathLinkService = null; public bool DeathLinkKilling = false; public string DeathLinkReason { get; private set; } public void TryGetSlotDataValue(ref int option, Dictionary<string, object> slotData, string key, int defaultValue) { try { option = int.Parse(slotData[key].ToString()); } catch (KeyNotFoundException) { Core.Logger.LogWarning((object)$"No key found for option \"{key}\". Using default value ({defaultValue})"); option = defaultValue; } } public void TryGetSlotDataValue(ref bool option, Dictionary<string, object> slotData, string key, bool defaultValue) { try { option = bool.Parse(slotData[key].ToString()); } catch (KeyNotFoundException) { Core.Logger.LogWarning((object)$"No key found for option \"{key}\". Using default value ({defaultValue})"); option = defaultValue; } } public void TryGetSlotDataValue(ref Logic option, Dictionary<string, object> slotData, string key, Logic defaultValue) { try { option = (Logic)int.Parse(slotData[key].ToString()); } catch (KeyNotFoundException) { Core.Logger.LogWarning((object)$"No key found for option \"{key}\". Using default value ({defaultValue})"); option = defaultValue; } } public void TryGetSlotDataValue(ref MoveStyle option, Dictionary<string, object> slotData, string key, MoveStyle defaultValue) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected I4, but got Unknown try { option = (MoveStyle)int.Parse(slotData[key].ToString()); } catch (KeyNotFoundException) { Core.Logger.LogWarning((object)$"No key found for option \"{key}\". Using default value ({defaultValue})"); option = (MoveStyle)(int)defaultValue; } } public void TryGetSlotDataValue(ref SGraffiti option, Dictionary<string, object> slotData, string key, SGraffiti defaultValue) { try { option = (SGraffiti)int.Parse(slotData[key].ToString()); } catch (KeyNotFoundException) { Core.Logger.LogWarning((object)$"No key found for option \"{key}\". Using default value ({defaultValue})"); option = defaultValue; } } public void TryGetSlotDataValue(ref ScoreDifficulty option, Dictionary<string, object> slotData, string key, ScoreDifficulty defaultValue) { try { option = (ScoreDifficulty)int.Parse(slotData[key].ToString()); } catch (KeyNotFoundException) { Core.Logger.LogWarning((object)$"No key found for option \"{key}\". Using default value ({defaultValue})"); option = defaultValue; } } public bool Connect(int slotId, string name, string address, string password = null) { //IL_0564: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Expected O, but got Unknown //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Expected O, but got Unknown //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Expected O, but got Unknown //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Expected O, but got Unknown //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Invalid comparison between Unknown and I4 //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03ad: Invalid comparison between Unknown and I4 //IL_03f3: Unknown result type (might be due to invalid IL or missing references) //IL_03f9: Invalid comparison between Unknown and I4 //IL_0471: Unknown result type (might be due to invalid IL or missing references) if (Authenticated) { return true; } if (slotId == -1) { return false; } if (Core.forbiddenModsLoaded > 0) { if (Core.forbiddenModsLoaded == 1) { Core.Instance.UIManager.SetResult("A forbidden mod is loaded. (" + Core.forbiddenGUIDs + ")"); } else { Core.Instance.UIManager.SetResult($"A forbidden mod is loaded. ({Core.forbiddenModsLoaded} mods)"); } Core.Logger.LogWarning((object)("A forbidden mod is loaded. (" + Core.forbiddenGUIDs + ")")); Core.Instance.UIManager.slotButtons[slotId].ChangeState(APSlotButton.SlotState.Disconnected); Core.Instance.UIManager.SetStatus(APSlotButton.SlotState.Disconnected); return false; } Core.Logger.LogInfo((object)$"Attempting connection - Slot: {slotId} | Name: {name}"); Session = ArchipelagoSessionFactory.CreateSession(address, 38281); Session.Socket.SocketClosed += new SocketClosedHandler(SocketClosed); Session.Socket.ErrorReceived += new ErrorReceivedHandler(ErrorReceived); Session.Socket.PacketReceived += new PacketReceivedHandler(PacketReceived); Session.Items.ItemReceived += new ItemReceivedHandler(ItemReceived); LoginResult val = Session.TryConnectAndLogin("Bomb Rush Cyberfunk", name, (ItemsHandlingFlags)7, new Version(AP_VERSION[0], AP_VERSION[1], AP_VERSION[2]), (string[])null, (string)null, (password == "") ? null : password, true); LoginSuccessful val2 = (LoginSuccessful)(object)((val is LoginSuccessful) ? val : null); if (val2 != null) { TryGetSlotDataValue(ref Core.Instance.Data.logic, val2.SlotData, "logic", Logic.Glitchless); TryGetSlotDataValue(ref Core.Instance.Data.skipIntro, val2.SlotData, "skip_intro", defaultValue: true); TryGetSlotDataValue(ref Core.Instance.Data.skipDreams, val2.SlotData, "skip_dreams", defaultValue: false); TryGetSlotDataValue(ref Core.Instance.Data.skipHands, val2.SlotData, "skip_statue_hands", defaultValue: false); TryGetSlotDataValue(ref Core.Instance.Data.totalRep, val2.SlotData, "total_rep", 1400); TryGetSlotDataValue(ref Core.Instance.Data.endingRep, val2.SlotData, "extra_rep_required", defaultValue: false); TryGetSlotDataValue(ref Core.Instance.Data.startingMovestyle, val2.SlotData, "starting_movestyle", (MoveStyle)2); TryGetSlotDataValue(ref Core.Instance.Data.junkPhotos, val2.SlotData, "skip_polo_photos", defaultValue: false); TryGetSlotDataValue(ref Core.Instance.Data.limitedGraffiti, val2.SlotData, "limited_graffiti", defaultValue: false); TryGetSlotDataValue(ref Core.Instance.Data.sGraffiti, val2.SlotData, "small_graffiti_uses", SGraffiti.Separate); if (!Core.Instance.SaveManager.DataExists(slotId)) { if ((int)Core.Instance.Data.startingMovestyle == 2) { Core.Instance.Data.skateboardUnlocked = true; Core.Instance.Data.inlineUnlocked = false; Core.Instance.Data.bmxUnlocked = false; } else if ((int)Core.Instance.Data.startingMovestyle == 3) { Core.Instance.Data.skateboardUnlocked = false; Core.Instance.Data.inlineUnlocked = true; Core.Instance.Data.bmxUnlocked = false; } else if ((int)Core.Instance.Data.startingMovestyle == 1) { Core.Instance.Data.skateboardUnlocked = false; Core.Instance.Data.inlineUnlocked = false; Core.Instance.Data.bmxUnlocked = true; } if (Core.Instance.Data.limitedGraffiti) { if (Core.Instance.Data.sGraffiti == SGraffiti.Separate) { Dictionary<string, int> grafUses = Core.Instance.Data.grafUses; Characters val3 = (Characters)3; grafUses[((object)(Characters)(ref val3)).ToString()] = 0; } else { Core.Instance.Data.grafUses["S"] = 0; } } TryGetSlotDataValue(ref Core.Instance.Data.damageMultiplier, val2.SlotData, "damage_multiplier", 1); TryGetSlotDataValue(ref Core.Instance.Data.scoreDifficulty, val2.SlotData, "score_difficulty", ScoreDifficulty.Normal); try { Core.configDontSavePhotos.Value = bool.Parse(val2.SlotData["dont_save_photos"].ToString()); } catch (KeyNotFoundException) { Core.Logger.LogWarning((object)"No key found for option \"dont_save_photos\". Ignored."); } TryGetSlotDataValue(ref Core.Instance.Data.deathLink, val2.SlotData, "death_link", defaultValue: false); } Core.Instance.LocationManager.locations = ((JToken)(JObject)val2.SlotData["locations"]).ToObject<Dictionary<string, long>>(); Authenticated = true; if (Core.Instance.Data.deathLink) { EnableDeathLink(); } messages.Clear(); Core.Instance.Data.slot_name = name; Core.Instance.Data.host_name = address; Core.Instance.Data.password = password; Core.Instance.Data.fakeRep = 0; Core.Instance.SaveManager.currentSlot = slotId; Core.Instance.SaveManager.SaveData(); Core.Instance.UIManager.slotButtons[slotId].ChangeState(APSlotButton.SlotState.Connected); Core.Instance.UIManager.SetResult("Successfully connected to server as player \"" + name + "\"."); Core.Instance.UIManager.SetStatus(APSlotButton.SlotState.Connected); ((Component)Core.Instance.UIManager.APMenuChat).gameObject.SetActive(true); Core.Logger.LogInfo((object)("Successfully connected to server as player \"" + name + "\".")); } else { LoginFailure val4 = (LoginFailure)(object)((val is LoginFailure) ? val : null); if (val4 != null) { Authenticated = false; Core.Logger.LogError((object)string.Join("\n", val4.Errors)); Core.Instance.UIManager.SetResult(string.Join("\n", val4.Errors)); Session.Socket.DisconnectAsync(); Session = null; DeathLinkService = null; Core.Instance.UIManager.slotButtons[slotId].ChangeState(APSlotButton.SlotState.Disconnected); Core.Instance.UIManager.SetStatus(APSlotButton.SlotState.Disconnected); } } return val.Successful; } public void Disconnect() { if (Session != null && Session.Socket != null) { Session.Socket.DisconnectAsync(); } messages.Clear(); ((Component)Core.Instance.UIManager.APMenuChat).gameObject.SetActive(false); Session = null; DeathLinkService = null; Authenticated = false; } public void SocketClosed(string reason) { Core.Logger.LogError((object)("Lost connection to Archipelago server. " + reason)); Disconnect(); } public void ErrorReceived(Exception e, string message) { Core.Logger.LogError((object)message); if (e != null) { Core.Logger.LogError((object)e.ToString()); } } public void PacketReceived(ArchipelagoPacketBase packet) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Expected I4, but got Unknown //IL_0416: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Expected I4, but got Unknown //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) if ((int)packet.PacketType != 6) { return; } if (messages.Count >= PhoneManager.maxMessages) { messages.RemoveAt(0); } PrintJsonPacket val = (PrintJsonPacket)(object)((packet is PrintJsonPacket) ? packet : null); string text = ""; string text2 = "<color=#FFFFFFFF>"; if (Core.configPlayerOtherNotifs.Value && val.Data[0].Type == (JsonMessagePartType?)1 && Session.Players.GetPlayerName(int.Parse(val.Data[0].Text)) == Core.Instance.Data.slot_name && val.Data[1].Text == " sent ") { string itemName = Session.Items.GetItemName(long.Parse(val.Data[2].Text), Session.Players.GetPlayerInfo(val.Data[2].Player.Value).Game); string playerAlias = Session.Players.GetPlayerAlias(int.Parse(val.Data[4].Text)); Core.Instance.LocationManager.notifQueue.Add(new Notification("AppArchipelago", itemName + " (" + playerAlias + ")", null)); } JsonMessagePart[] data = val.Data; foreach (JsonMessagePart val2 in data) { switch (val2.Type) { case 0L: { text2 = ((!(Session.Players.GetPlayerName(int.Parse(val2.Text)) == Core.Instance.Data.slot_name)) ? ("<color=#" + ColorUtility.ToHtmlStringRGBA(Core.configColorPlayerOther.Value) + ">") : ("<color=#" + ColorUtility.ToHtmlStringRGBA(Core.configColorPlayerSelf.Value) + ">")); if (int.TryParse(val2.Text, out var result3)) { string text5 = Session.Players.GetPlayerAlias(result3) ?? $"Slot: {result3}"; text = text + text2 + text5 + "</color>"; } else { text = text + text2 + val2.Text + "</color>"; } break; } case 2L: { text2 = val2.Flags switch { 0L => "<color=#" + ColorUtility.ToHtmlStringRGBA(Core.configColorItemAdvancement.Value) + ">", 1L => "<color=#" + ColorUtility.ToHtmlStringRGBA(Core.configColorItemNeverExclude.Value) + ">", 3L => "<color=#" + ColorUtility.ToHtmlStringRGBA(Core.configColorItemTrap.Value) + ">", _ => "<color=#" + ColorUtility.ToHtmlStringRGBA(Core.configColorItemFiller.Value) + ">", }; if (long.TryParse(val2.Text, out var result2)) { string text4 = Session.Items.GetItemName(result2, Session.Players.GetPlayerInfo(val2.Player.Value).Game) ?? $"Item: {result2}"; text = text + text2 + text4 + "</color>"; } else { text = text + text2 + val2.Text + "</color>"; } break; } case 4L: { text2 = "<color=#" + ColorUtility.ToHtmlStringRGBA(Core.configColorLocation.Value) + ">"; if (long.TryParse(val2.Text, out var result)) { string text3 = Session.Locations.GetLocationNameFromId(result, Session.Players.GetPlayerInfo(val2.Player.Value).Game) ?? $"Location: {result}"; text = text + text2 + text3 + "</color>"; } else { text = text + text2 + val2.Text + "</color>"; } break; } default: text += val2.Text; break; } } messages.Add(text); ((TMP_Text)Core.Instance.UIManager.APMenuChat).text = string.Join("\n", messages.ToArray()); if ((Object)(object)Core.Instance.PhoneManager.appArchipelago != (Object)null) { Core.Instance.PhoneManager.appArchipelago.UpdateText(); } } public void ItemReceived(ReceivedItemsHelper helper) { ItemInfo val = helper.PeekItem(); if (helper.Index > Core.Instance.Data.index) { string text = ((Session.Players.GetPlayerAlias(PlayerInfo.op_Implicit(val.Player)) == "") ? "?" : Session.Players.GetPlayerAlias(PlayerInfo.op_Implicit(val.Player))); string text2 = $"Received item: {val.ItemName} | Type: {Core.Instance.LocationManager.GetItemType(val.ItemName)}"; if (text != Core.Instance.Data.slot_name) { text2 = text2 + " | Player: " + text; } Core.Logger.LogInfo((object)text2); } BRCItem item = new BRCItem { item_name = val.ItemName, type = Core.Instance.LocationManager.GetItemType(val.ItemName), player_name = Core.Instance.Data.slot_name, received = (helper.Index <= Core.Instance.Data.index) }; Core.Instance.LocationManager.itemQueue.Add(item); if (helper.Index > Core.Instance.Data.index) { Core.Instance.Data.index++; } helper.DequeueItem(); } public void GetRandomHint() { if (Authenticated) { ReadOnlyCollection<long> allMissingLocations = Session.Locations.AllMissingLocations; IEnumerable<long> second = from h in ((IDataStorageWrapper)Session.DataStorage).GetHints((int?)null, (int?)null) where h.FindingPlayer == Session.ConnectionInfo.Slot select h.LocationId; long[] array = allMissingLocations.Except(second).ToArray(); if (array.Any()) { long num = array[Random.Range(0, array.Length)]; Session.Locations.ScoutLocationsAsync(true, new long[1] { num }); Core.Instance.LocationManager.notifQueue.Add(new Notification("AppArchipelago", Core.Instance.Localizer.GetRawTextValue((Subgroups)0, "APP_HINT"), null)); } else { Core.Logger.LogWarning((object)"No locations available to hint."); } } } public void EnableDeathLink() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown if (Session != null) { if (DeathLinkService == null) { DeathLinkService = DeathLinkProvider.CreateDeathLinkService(Session); DeathLinkService.OnDeathLinkReceived += new DeathLinkReceivedHandler(DeathLinkReceived); } DeathLinkService.EnableDeathLink(); } } public void DisableDeathLink() { if (DeathLinkService != null) { DeathLinkService.DisableDeathLink(); } } public void DeathLinkReceived(DeathLink dl) { if (Core.Instance.BaseModule.IsPlayingInStage && !Core.Instance.BaseModule.IsLoading && !DeathLinkKilling) { DeathLinkKilling = true; string text = dl.Cause; if (text == null) { text = dl.Source + " has died."; } DeathLinkReason = text; } else { Core.Logger.LogWarning((object)"Received DeathLink, but player cannot be killed right now."); } } public void SendCompletion() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown if (Authenticated) { StatusUpdatePacket val = new StatusUpdatePacket { Status = (ArchipelagoClientState)30 }; Session.Socket.SendPacket((ArchipelagoPacketBase)(object)val); } } } public class PhoneManager { public static int maxMessages = 8; public AppArchipelago appArchipelago; public AppEncounter appEncounter; public Phone Phone { get { if (Core.Instance.BaseModule.IsPlayingInStage) { return Traverse.Create((object)WorldHandler.instance.GetCurrentPlayer()).Field<Phone>("phone").Value; } return null; } } public static Color PhoneBlue => new Color(0.224f, 0.302f, 0.624f); public static Color PhoneYellow => new Color(0.882f, 0.953f, 0.345f); public static Color PhoneOrange => new Color(0.978f, 0.424f, 0.216f); public void DoAppSetup() { //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Expected O, but got Unknown //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_03d0: Unknown result type (might be due to invalid IL or missing references) //IL_05ac: Unknown result type (might be due to invalid IL or missing references) //IL_05b7: Unknown result type (might be due to invalid IL or missing references) //IL_05bc: Unknown result type (might be due to invalid IL or missing references) //IL_05c8: Unknown result type (might be due to invalid IL or missing references) //IL_05d3: Expected O, but got Unknown //IL_0601: Unknown result type (might be due to invalid IL or missing references) //IL_0622: Unknown result type (might be due to invalid IL or missing references) //IL_0650: Unknown result type (might be due to invalid IL or missing references) //IL_069b: Unknown result type (might be due to invalid IL or missing references) //IL_074c: Unknown result type (might be due to invalid IL or missing references) //IL_07c7: Unknown result type (might be due to invalid IL or missing references) //IL_07f3: Unknown result type (might be due to invalid IL or missing references) //IL_082f: Unknown result type (might be due to invalid IL or missing references) //IL_088b: Unknown result type (might be due to invalid IL or missing references) //IL_09e3: Unknown result type (might be due to invalid IL or missing references) //IL_0a44: Unknown result type (might be due to invalid IL or missing references) //IL_0b7f: Unknown result type (might be due to invalid IL or missing references) //IL_0bf7: Unknown result type (might be due to invalid IL or missing references) //IL_0c8f: Unknown result type (might be due to invalid IL or missing references) //IL_0d9b: Unknown result type (might be due to invalid IL or missing references) //IL_0dea: Unknown result type (might be due to invalid IL or missing references) //IL_0ea0: Unknown result type (might be due to invalid IL or missing references) //IL_0eca: Unknown result type (might be due to invalid IL or missing references) //IL_0f6c: Unknown result type (might be due to invalid IL or missing references) //IL_100a: Unknown result type (might be due to invalid IL or missing references) //IL_10a7: Unknown result type (might be due to invalid IL or missing references) //IL_115b: Unknown result type (might be due to invalid IL or missing references) //IL_11fd: Unknown result type (might be due to invalid IL or missing references) if (Core.Instance.BaseModule.IsPlayingInStage && !((Object)(object)appArchipelago != (Object)null)) { appArchipelago = Object.Instantiate<GameObject>(((Component)((Component)((Component)Phone).GetComponentInChildren<AppEmail>(true)).transform).gameObject, ((Component)((Component)Phone).GetComponentInChildren<AppEmail>(true)).transform.parent).AddComponent<AppArchipelago>(); ((Object)((Component)appArchipelago).gameObject).name = "AppArchipelago"; Object.DestroyImmediate((Object)(object)((Component)appArchipelago).GetComponent<AppEmail>()); Traverse val = Traverse.Create((object)appArchipelago); val.Method("Awake", Array.Empty<object>()).GetValue(); val.Field<Phone>("<MyPhone>k__BackingField").Value = Phone; val.Field<AUnlockable[]>("m_Unlockables").Value = (AUnlockable[])(object)new AUnlockable[0]; Object.DestroyImmediate((Object)(object)((Component)((Transform)((App)appArchipelago).Content).Find("EmailScroll")).gameObject); Object.DestroyImmediate((Object)(object)((Component)((Transform)((App)appArchipelago).Content).Find("MessagePanel")).gameObject); Object.Destroy((Object)(object)((Component)((Transform)((App)appArchipelago).Content).Find("Overlay")).GetComponentInChildren<TMProLocalizationAddOn>()); appArchipelago.title = ((Component)((Transform)((App)appArchipelago).Content).Find("Overlay")).GetComponentInChildren<TextMeshProUGUI>(); ((TMP_Text)appArchipelago.title).text = Core.Instance.Localizer.GetRawTextValue((Subgroups)0, "APP_ARCHIPELAGO_HEADER_DEFAULT"); Image componentInChildren = ((Component)((Transform)((App)appArchipelago).Content).Find("Overlay").Find("Icons").Find("AppIcon")).GetComponentInChildren<Image>(); componentInChildren.sprite = UIManager.bundle.LoadAsset<Sprite>("assets/archipelago.png"); GameObject val2 = new GameObject { name = "Messages", layer = 24 }; val2.transform.parent = ((Component)((App)appArchipelago).Content).transform; val2.transform.localPosition = Vector3.zero; val2.transform.SetAsFirstSibling(); appArchipelago.text = val2.AddComponent<TextMeshProUGUI>(); appArchipelago.UpdateText(); ((TMP_Text)appArchipelago.text).fontSize = 68f; ((TMP_Text)appArchipelago.text).font = UIManager.font; ((TMP_Text)appArchipelago.text).alignment = (TextAlignmentOptions)1025; ((TMP_Text)appArchipelago.text).enableWordWrapping = true; ((TMP_Text)appArchipelago.text).transform.localPosition = new Vector3(0f, 250f, 0f); ((TMP_Text)appArchipelago.text).transform.localScale = Vector3.one; ((Component)appArchipelago.text).GetComponent<RectTransform>().sizeDelta = new Vector2(1000f, 1560f); TMProFontLocalizer val3 = ((Component)appArchipelago.text).gameObject.AddComponent<TMProFontLocalizer>(); Traverse val4 = Traverse.Create((object)val3); val4.Field<TextMeshProUGUI>("textMesh").Value = appArchipelago.text; val4.Field<GameFontType>("gameFontType").Value = Core.MainFont; appArchipelago.chatBackground = Object.Instantiate<GameObject>(((Component)((Transform)((App)Phone.GetAppInstance<AppHomeScreen>()).Content).Find("BottomView").Find("ButtonContainer").Find("Selector") .Find("Background")).gameObject, (Transform)(object)((App)appArchipelago).Content); appArchipelago.chatBackground.transform.localPosition = new Vector3(100f, -650f, 0f); ((Object)appArchipelago.chatBackground).name = "Chat Bottom"; appEncounter = Object.Instantiate<GameObject>(((Component)appArchipelago).gameObject, ((Component)appArchipelago).transform.parent).AddComponent<AppEncounter>(); ((Object)((Component)appEncounter).gameObject).name = "AppEncounter"; Object.Destroy((Object)(object)((Component)appEncounter).GetComponent<AppArchipelago>()); Traverse val5 = Traverse.Create((object)appEncounter); val5.Method("Awake", Array.Empty<object>()).GetValue(); val5.Field<Phone>("<MyPhone>k__BackingField").Value = Phone; val5.Field<AUnlockable[]>("m_Unlockables").Value = (AUnlockable[])(object)new AUnlockable[0]; ((Component)((Transform)((App)appEncounter).Content).Find("Overlay").Find("Icons").Find("AppIcon")).GetComponent<Image>().sprite = UIManager.bundle.LoadAsset<Sprite>("assets/encounter.png"); appEncounter.headerText = ((Component)((Transform)((App)appEncounter).Content).Find("Overlay")).GetComponentInChildren<TextMeshProUGUI>(); ((TMP_Text)appEncounter.headerText).text = Core.Instance.Localizer.GetRawTextValue((Subgroups)0, "APP_ENCOUNTER_HEADER"); appEncounter.Init(); Object.Destroy((Object)(object)((Component)((Transform)((App)appEncounter).Content).Find("Messages")).gameObject); GameObject gameObject = ((Component)((Transform)((App)appEncounter).Content).Find("Chat Bottom")).gameObject; ((Object)gameObject).name = "Text Background"; gameObject.transform.Rotate(0f, 0f, 180f); gameObject.transform.localPosition = new Vector3(-100f, 500f, 0f); GameObject val6 = new GameObject { name = "Background Image", layer = 24 }; val6.transform.SetParent((Transform)(object)((App)appEncounter).Content); val6.transform.localPosition = new Vector3(250f, -250f, 0f); val6.transform.localScale = new Vector3(12f, 12f, 12f); val6.AddComponent<Image>().sprite = UIManager.bundle.LoadAsset<Sprite>("assets/encounter_large.png"); ((Graphic)val6.GetComponent<Image>()).color = PhoneBlue; GameObject val7 = Object.Instantiate<GameObject>(appArchipelago.chatBackground, (Transform)(object)((App)appEncounter).Content); Object.DestroyImmediate((Object)(object)val7.GetComponent<Image>()); val7.transform.localPosition = new Vector3(75f, 500f, 0f); ((Object)val7).name = "Current Encounter"; appEncounter.currentText = val7.AddComponent<TextMeshProUGUI>(); Traverse val8 = Traverse.Create((object)((Component)appEncounter.currentText).gameObject.AddComponent<TMProFontLocalizer>()); val8.Field<GameFontType>("gameFontType").Value = Core.PhoneFont; val8.Field<TextMeshProUGUI>("textMesh").Value = appEncounter.currentText; ((TMP_Text)appEncounter.currentText).alignment = (TextAlignmentOptions)513; ((TMP_Text)appEncounter.currentText).fontSize = 80f; ((Graphic)appEncounter.currentText).color = PhoneYellow; ((TMP_Text)appEncounter.currentText).text = Core.Instance.Localizer.GetRawTextValue((Subgroups)0, "APP_ENCOUNTER_TOP"); appEncounter.messageText = Object.Instantiate<GameObject>(((Component)appEncounter.currentText).gameObject, (Transform)(object)((App)appEncounter).Content).GetComponent<TextMeshProUGUI>(); ((Component)appEncounter.messageText).GetComponent<RectTransform>().sizeDelta = new Vector2(-200f, 1f); ((TMP_Text)appEncounter.messageText).alignment = (TextAlignmentOptions)257; ((Graphic)appEncounter.messageText).color = Color.white; ((TMP_Text)appEncounter.messageText).enableWordWrapping = true; ((TMP_Text)appEncounter.messageText).transform.localPosition = new Vector3(0f, -550f, 0f); appEncounter.confirmText = Object.Instantiate<GameObject>(((Component)appEncounter.currentText).gameObject, (Transform)(object)((App)appEncounter).Content).GetComponent<TextMeshProUGUI>(); ((TMP_Text)appEncounter.confirmText).alignment = (TextAlignmentOptions)516; ((Graphic)appEncounter.confirmText).color = PhoneOrange; ((TMP_Text)appEncounter.confirmText).text = Core.Instance.Localizer.GetRawTextValue((Subgroups)0, "APP_ENCOUNTER_CONFIRM"); appEncounter.confirmArrow = Object.Instantiate<GameObject>(((Component)((Transform)((App)appEncounter).Content).Find("Overlay").Find("Icons").Find("Arrow")).gameObject, (Transform)(object)((App)appEncounter).Content); appEncounter.confirmArrow.transform.Rotate(0f, 0f, 180f); ((Object)appEncounter.confirmArrow).name = "Arrow Right"; appArchipelago.headerArrow = ((Component)((Transform)((App)appArchipelago).Content).Find("Overlay").Find("Icons").Find("Arrow")).gameObject; appArchipelago.arrowRight = Object.Instantiate<GameObject>(appArchipelago.headerArrow, (Transform)(object)((App)appArchipelago).Content); appArchipelago.arrowRight.transform.Rotate(0f, 0f, 180f); appArchipelago.arrowRight.transform.localPosition = new Vector3(450f, -650f, 0f); ((Object)appArchipelago.arrowRight).name = "Arrow Right"; GameObject val9 = Object.Instantiate<GameObject>(appArchipelago.chatBackground, (Transform)(object)((App)appArchipelago).Content); Object.DestroyImmediate((Object)(object)val9.GetComponent<Image>()); val9.transform.localPosition = new Vector3(-180f, -650f, 0f); ((Object)val9).name = "Chat Swap Text"; appArchipelago.chatSwap = val9.AddComponent<TextMeshProUGUI>(); val8 = Traverse.Create((object)((Component)appArchipelago.chatSwap).gameObject.AddComponent<TMProFontLocalizer>()); val8.Field<GameFontType>("gameFontType").Value = Core.PhoneFont; val8.Field<TextMeshProUGUI>("textMesh").Value = appArchipelago.chatSwap; ((TMP_Text)appArchipelago.chatSwap).alignment = (TextAlignmentOptions)516; ((TMP_Text)appArchipelago.chatSwap).fontSize = 70f; ((TMP_Text)appArchipelago.chatSwap).text = Core.Instance.Localizer.GetRawTextValue((Subgroups)0, "APP_ARCHIPELAGO_NAVIGATION_OPTIONS"); appArchipelago.optionsBackground = Object.Instantiate<GameObject>(appArchipelago.chatBackground.gameObject, (Transform)(object)((App)appArchipelago).Content); appArchipelago.optionsBackground.transform.Rotate(0f, 0f, 180f); appArchipelago.optionsBackground.transform.localPosition = new Vector3(-90f, -650f, 0f); ((Object)appArchipelago.optionsBackground).name = "Options Bottom"; appArchipelago.optionsBackground.SetActive(false); appArchipelago.arrowLeft = Object.Instantiate<GameObject>(appArchipelago.headerArrow, (Transform)(object)((App)appArchipelago).Content); appArchipelago.arrowLeft.transform.localPosition = new Vector3(-440f, -650f, 0f); ((Object)appArchipelago.arrowLeft).name = "Arrow Left"; appArchipelago.arrowLeft.SetActive(false); appArchipelago.optionsSwap = Object.Instantiate<GameObject>(((Component)appArchipelago.chatSwap).gameObject, (Transform)(object)((App)appArchipelago).Content).GetComponent<TextMeshProUGUI>(); ((TMP_Text)appArchipelago.optionsSwap).alignment = (TextAlignmentOptions)513; ((TMP_Text)appArchipelago.optionsSwap).transform.localPosition = new Vector3(200f, -650f, 0f); ((TMP_Text)appArchipelago.optionsSwap).text = "Chat"; ((Object)((Component)appArchipelago.optionsSwap).gameObject).name = "Options Swap Text"; ((Component)appArchipelago.optionsSwap).gameObject.SetActive(false); appArchipelago.optionCurrentText = Object.Instantiate<GameObject>(((Component)appArchipelago.text).gameObject, (Transform)(object)((App)appArchipelago).Content).GetComponent<TextMeshProUGUI>(); ((TMP_Text)appArchipelago.optionCurrentText).alignment = (TextAlignmentOptions)513; ((TMP_Text)appArchipelago.optionCurrentText).enableAutoSizing = true; ((TMP_Text)appArchipelago.optionCurrentText).fontSizeMax = 90f; ((TMP_Text)appArchipelago.optionCurrentText).fontSizeMin = 70f; ((TMP_Text)appArchipelago.optionCurrentText).lineSpacing = 24f; ((TMP_Text)appArchipelago.optionCurrentText).transform.localPosition = new Vector3(0f, 50f, 0f); Traverse.Create((object)((Component)appArchipelago.optionCurrentText).GetComponent<TMProFontLocalizer>()).Field<GameFontType>("gameFontType").Value = Core.PhoneFont; ((Component)appArchipelago.optionCurrentText).GetComponent<RectTransform>().sizeDelta = new Vector2(900f, 1560f); ((Object)((Component)appArchipelago.optionCurrentText).gameObject).name = "Current Option"; ((Component)appArchipelago.optionCurrentText).gameObject.SetActive(false); appArchipelago.optionPrevText = Object.Instantiate<GameObject>(((Component)appArchipelago.optionCurrentText).gameObject, (Transform)(object)((App)appArchipelago).Content).GetComponent<TextMeshProUGUI>(); ((TMP_Text)appArchipelago.optionPrevText).alignment = (TextAlignmentOptions)8194; ((TMP_Text)appArchipelago.optionPrevText).enableAutoSizing = false; ((TMP_Text)appArchipelago.optionPrevText).fontSize = 60f; ((Graphic)appArchipelago.optionPrevText).color = PhoneBlue; ((TMP_Text)appArchipelago.optionPrevText).transform.localPosition = new Vector3(0f, 500f, 0f); ((Object)((Component)appArchipelago.optionPrevText).gameObject).name = "Prev Option"; ((Component)appArchipelago.optionPrevText).gameObject.SetActive(false); appArchipelago.optionNextText = Object.Instantiate<GameObject>(((Component)appArchipelago.optionPrevText).gameObject, (Transform)(object)((App)appArchipelago).Content).GetComponent<TextMeshProUGUI>(); ((TMP_Text)appArchipelago.optionNextText).alignment = (TextAlignmentOptions)1026; ((TMP_Text)appArchipelago.optionNextText).transform.localPosition = new Vector3(0f, 350f, 0f); ((Object)((Component)appArchipelago.optionNextText).gameObject).name = "Next Option"; ((Component)appArchipelago.optionNextText).gameObject.SetActive(false); appArchipelago.optionChangeText = Object.Instantiate<GameObject>(((Component)appArchipelago.chatSwap).gameObject, (Transform)(object)((App)appArchipelago).Content).GetComponent<TextMeshProUGUI>(); ((TMP_Text)appArchipelago.optionChangeText).text = Core.Instance.Localizer.GetRawTextValue((Subgroups)0, "APP_ARCHIPELAGO_NAVIGATION_CHANGE"); ((Graphic)appArchipelago.optionChangeText).color = PhoneOrange; ((TMP_Text)appArchipelago.optionChangeText).fontSize = 65f; ((Object)((Component)appArchipelago.optionChangeText).gameObject).name = "Option Change Text"; ((Component)appArchipelago.optionChangeText).gameObject.SetActive(false); appArchipelago.optionChangeArrow = Object.Instantiate<GameObject>(appArchipelago.arrowRight.gameObject, (Transform)(object)((App)appArchipelago).Content); appArchipelago.optionChangeArrow.transform.localScale = new Vector3(0.75f, 0.75f, 0.75f); ((Object)appArchipelago.optionChangeArrow.gameObject).name = "Option Change Arrow"; appArchipelago.optionChangeArrow.gameObject.SetActive(false); appArchipelago.optionDownArrow = Object.Instantiate<GameObject>(((Component)((Transform)((App)Phone.GetAppInstance<AppHomeScreen>()).Content).Find("BottomView").Find("OtherElements").Find("ArrowsContainer") .Find("ArrowDown")).gameObject, (Transform)(object)((App)appArchipelago).Content); appArchipelago.optionDownArrow.transform.localPosition = new Vector3(0f, -500f, 0f); ((Object)appArchipelago.optionDownArrow).name = "Arrow Down"; appArchipelago.optionDownArrow.gameObject.SetActive(false); appArchipelago.optionUpArrow = Object.Instantiate<GameObject>(appArchipelago.optionDownArrow, (Transform)(object)((App)appArchipelago).Content); appArchipelago.optionUpArrow.transform.Rotate(0f, 0f, 180f); appArchipelago.optionUpArrow.transform.localPosition = new Vector3(0f, 600f, 0f); ((Object)appArchipelago.optionUpArrow).name = "Arrow Up"; appArchipelago.optionUpArrow.gameObject.SetActive(false); HomeScreenApp val10 = ScriptableObject.CreateInstance<HomeScreenApp>(); ((Object)val10).name = "AppEncounter"; Traverse val11 = Traverse.Create((object)val10); val11.Field<HomeScreenAppType>("appType").Value = (HomeScreenAppType)0; val11.Field<string>("m_AppName").Value = "AppEncounter"; val11.Field<string>("m_DisplayName").Value = "APP_ENCOUNTER_HEADER"; val11.Field<Sprite>("m_AppIcon").Value = UIManager.bundle.LoadAsset<Sprite>("assets/encounter.png"); HomeScreenApp val12 = ScriptableObject.CreateInstance<HomeScreenApp>(); ((Object)val12).name = "AppArchipelago"; Traverse val13 = Traverse.Create((object)val12); val13.Field<HomeScreenAppType>("appType").Value = (HomeScreenAppType)0; val13.Field<string>("m_AppName").Value = "AppArchipelago"; val13.Field<string>("m_DisplayName").Value = "APP_ARCHIPELAGO_HEADER_DEFAULT"; val13.Field<Sprite>("m_AppIcon").Value = UIManager.bundle.LoadAsset<Sprite>("assets/archipelago.png"); Traverse.Create((object)Phone).Field<Dictionary<string, App>>("<AppInstances>k__BackingField").Value.Add("AppEncounter", (App)(object)appEncounter); Traverse.Create((object)Phone.GetAppInstance<AppHomeScreen>()).Method("AddApp", new object[1] { val10 }).GetValue(); Traverse.Create((object)Phone).Field<Dictionary<string, App>>("<AppInstances>k__BackingField").Value.Add("AppArchipelago", (App)(object)appArchipelago); Traverse.Create((object)Phone.GetAppInstance<AppHomeScreen>()).Method("AddApp", new object[1] { val12 }).GetValue(); GameObject gameObject2 = ((Component)val.Property("Notification", (object[])null).Field<GameObject>("appNotificationPanel_Main").Value.transform.parent).gameObject; GameObject gameObject3 = ((Component)val.Property("Notification", (object[])null).Field<GameObject>("appNotificationPanel_Outside").Value.transform.parent).gameObject; GameObject val14 = Object.Instantiate<GameObject>(((Component)gameObject2.transform.Find("GraffitiNotification")).gameObject, gameObject2.transform); GameObject val15 = Object.Instantiate<GameObject>(((Component)gameObject3.transform.Find("GraffitiNotification")).gameObject, gameObject3.transform); val14.GetComponentInChildren<Image>().sprite = UIManager.bundle.LoadAsset<Sprite>("assets/notification.png"); ((Component)val15.transform.Find("ActionImage")).GetComponent<Image>().sprite = UIManager.bundle.LoadAsset<Sprite>("assets/notification.png"); val.Property("Notification", (object[])null).Field<GameObject>("appNotificationPanel_Main").Value = val14; val.Property("Notification", (object[])null).Field<GameObject>("appNotificationPanel_Outside").Value = val15; val.Property("Notification", (object[])null).Field<TextMeshProUGUI>("topBarText_Main").Value = val14.GetComponentInChildren<TextMeshProUGUI>(); val.Property("Notification", (object[])null).Field<TextMeshProUGUI>("topBarText_Outside").Value = val15.GetComponentInChildren<TextMeshProUGUI>(); } } } internal static class Requirements { public const int grafSLimit = 5; public const int grafMLimit = 7; public const int grafLLimit = 6; public const int grafXLLimit = 4; public static RepValues HideoutStoryRep = new RepValues(20, 20); public static RepValues DownhillChallenge1Rep = new RepValues(30, 50); public static RepValues DownhillChallenge2Rep = new RepValues(38, 58); public static RepValues DownhillChallenge3Rep = new RepValues(45, 65); public static RepValues DownhillCrewWallRep = new RepValues(70, 90); public static ScoreValues DownhillCrewBattleScore = new ScoreValues(60000, 750000, 1500000, 2250000, 3000000); public static RepValues DownhillOldheadRep = new RepValues(100, 120); public static ScoreValues DownhillRaveScore = new ScoreValues(50000, 375000, 750000, 1500000, 3000000); public static RepValues SquareEclipseRep = new RepValues(60, 180); public static RepValues SquareOldheadRep = new RepValues(120, 380); public static RepValues TowerChallenge1Rep = new RepValues(8, 188); public static RepValues TowerChallenge2Rep = new RepValues(20, 200); public static ScoreValues TowerChallenge2Score = new ScoreValues(25000, 50000, 100000, 250000, 400000); public static RepValues TowerChallenge3Rep = new RepValues(40, 220); public static RepValues TowerEscherRep = new RepValues(80, 260); public static RepValues TowerCrewWallRep = new RepValues(100, 280); public static ScoreValues TowerCrewBattleScore = new ScoreValues(150000, 1250000, 2500000, 3500000, 5000000); public static RepValues TowerOldhead1Rep = new RepValues(70, 250); public static RepValues TowerOldhead2Rep = new RepValues(140, 320); public static ScoreValues TowerMeshScore = new ScoreValues(70000, 125000, 250000, 500000, 700000); public static RepValues MallChallenge1Rep = new RepValues(54, 434); public static RepValues MallChallenge2Rep = new RepValues(62, 442); public static RepValues MallChallenge3Rep = new RepValues(70, 450); public static RepValues MallChallenge4Rep = new RepValues(78, 458); public static ScoreValues MallChallenge4Score = new ScoreValues(100000, 375000, 750000, 1500000, 2500000); public static RepValues MallCrewWallRep = new RepValues(111, 491); public static ScoreValues MallCrewBattleScore = new ScoreValues(300000, 1500000, 3000000, 5000000, 6500000); public static RepValues MallOldhead1Rep = new RepValues(150, 530); public static RepValues MallOldhead2Rep = new RepValues(200, 580); public static RepValues PyramidGateRep = new RepValues(40, 620); public static RepValues PyramidChallenge1Rep = new RepValues(50, 630); public static ScoreValues PyramidChallenge1Score = new ScoreValues(70000, 200000, 400000, 700000, 900000); public static RepValues PyramidChallenge2Rep = new RepValues(60, 640); public static RepValues PyramidChallenge3Rep = new RepValues(70, 650); public static ScoreValues PyramidChallenge3Score = new ScoreValues(100000, 250000, 500000, 800000, 1100000); public static RepValues PyramidChallenge4Rep = new RepValues(80, 660); public static RepValues PyramidCrewRep = new RepValues(150, 730); public static ScoreValues PyramidCrewBattleScore = new ScoreValues(450000, 1500000, 3000000, 5000000, 7500000); public static RepValues PyramidOldheadRep = new RepValues(200, 780); public static RepValues OsakaSmokeRep = new RepValues(70, 850); public static RepValues OsakaChallenge1Rep = new RepValues(84, 864); public static RepValues OsakaChallenge2Rep = new RepValues(100, 880); public static RepValues OsakaChallenge3Rep = new RepValues(140, 920); public static ScoreValues OsakaChallenge3Score = new ScoreValues(60000, 100000, 200000, 350000, 500000); public static RepValues OsakaCrewRep = new RepValues(180, 960); public static ScoreValues OsakaCrewBattleScore = new ScoreValues(600000, 2000000, 4000000, 5500000, 7000000); public static RepValues OsakaOldheadRep = new RepValues(155, 935); public static void OverrideCharacterIfInvalid(ref Characters character) { List<Characters> list = new List<Characters> { (Characters)25, (Characters)15, (Characters)17, (Characters)18 }; if (!Enum.IsDefined(typeof(Characters), character)) { character = (Characters)3; } else if (list.Contains(character)) { character = (Characters)3; } } public static int? GetNPCNewRep(Stage stage, NPC npc) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected I4, but got Unknown switch (stage - 4) { case 0: return ((Object)((Component)npc).transform.parent).name switch { "WallrunsChallenge" => DownhillChallenge1Rep.newValue, "ManualChallenge" => DownhillChallenge2Rep.newValue, "CornersScoreChallenge" => DownhillChallenge3Rep.newValue, "Crew_Wall" => DownhillCrewWallRep.newValue, "OldHeadWall" => DownhillOldheadRep.newValue, _ => null, }; case 7: { string name2 = ((Object)((Component)npc).transform).name; string text2 = name2; if (!(text2 == "NPC_EclipseCrew")) { if (text2 == "NPC_oldhead") { return SquareOldheadRep.newValue; } return null; } return SquareEclipseRep.newValue; } case 8: switch (((Object)((Component)npc).transform.parent).name) { case "UpsideGrind_Challenge": return TowerChallenge1Rep.newValue; case "Manual_Challenge ": return TowerChallenge2Rep.newValue; case "Score_Challenge": return TowerChallenge3Rep.newValue; case "Chapter2": { string name = ((Object)((Component)npc).transform).name; string text = name; if (!(text == "CombatEncounter_SniperCaptain")) { if (text == "NPC_TowerGuard") { return TowerCrewWallRep.newValue; } return null; } return TowerEscherRep.newValue; } case "OldHeadWall": return ((GameplayEvent)npc).requirement switch { 70 => TowerOldhead1Rep.newValue, 140 => TowerOldhead2Rep.newValue, _ => null, }; default: return null; } case 2: switch (((Object)((Component)npc).transform.parent).name) { case "Palms_Challenge": return MallChallenge1Rep.newValue; case "Slidepads_Challenge": return MallChallenge2Rep.newValue; case "Fish_Challenge ": return MallChallenge3Rep.newValue; case "Tricks_Challenge": return MallChallenge4Rep.newValue; case "Chapter3": if (((Object)((Component)npc).transform).name == "NPC_Crew_GUARDING") { return MallCrewWallRep.newValue; } return null; case "Oldhead1": return MallOldhead2Rep.newValue; case "Oldhead2": return MallOldhead1Rep.newValue; default: return null; } case 5: switch (((Object)((Component)npc).transform.parent).name) { case "Chapter4": if (((Object)((Component)npc).transform).name == "NPC_OnDoor") { return PyramidGateRep.newValue; } if (((Object)((Component)npc).transform).name == "NPC_Crew_CrewBattle_Starter") { return PyramidCrewRep.newValue; } return null; case "Tricks_ScoreChallenge": return PyramidChallenge1Rep.newValue; case "RaceChallenge": return PyramidChallenge2Rep.newValue; case "Tricks2_ScoreChallenge": return PyramidChallenge3Rep.newValue; case "Manual_Challenge": return PyramidChallenge4Rep.newValue; case "OldHeadWall": return PyramidOldheadRep.newValue; default: return null; } case 3: switch (((Object)((Component)npc).transform.parent).name) { case "Chapter5": if (((Object)((Component)npc).transform).name == "NPC_Crew_GateGuard") { return OsakaSmokeRep.newValue; } return null; case "Race_Challenge": return OsakaChallenge1Rep.newValue; case "WallrunsChallenge": return OsakaChallenge2Rep.newValue; case "ScoreChallenge": return OsakaChallenge3Rep.newValue; case "OldHeadWall": case "OldHeadWall2": return OsakaOldheadRep.newValue; case "CrewBattle": return OsakaCrewRep.newValue; default: return null; } default: return null; } } public static ScoreValues GetEncounterNewScore(Stage stage, ScoreEncounter encounter) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected I4, but got Unknown switch (stage - 4) { case 0: { string name2 = ((Object)encounter).name; string text2 = name2; if (!(text2 == "ScoreEncounterBazaar")) { if (text2 == "CrewBattle_ScoreEncounter") { return DownhillCrewBattleScore; } return null; } return DownhillRaveScore; } case 8: return ((Object)((Component)encounter).transform.parent).name switch { "Score_Challenge" => TowerChallenge2Score, "Score_Challenge " => TowerMeshScore, "Chapter2" => TowerCrewBattleScore, _ => null, }; case 2: { string name3 = ((Object)encounter).name; string text3 = name3; if (!(text3 == "ScoreEncounter_Tricks")) { if (text3 == "CrewBattle_ScoreEncounter") { return MallCrewBattleScore; } return null; } return MallChallenge4Score; } case 5: return ((Object)encounter).name switch { "ScoreEncounter_Tricks1" => PyramidChallenge1Score, "ScoreEncounter_Tricks2" => PyramidChallenge3Score, "CrewBattle_ScoreEncounter" => PyramidCrewBattleScore, _ => null, }; case 3: { string name = ((Object)encounter).name; string text = name; if (!(text == "ScoreEncounter")) { if (text == "ScoreEncounter_CrewBattle") { return OsakaCrewBattleScore; } return null; } return OsakaChallenge3Score; } default: return null; } } public static Values GetLocalizedTextRepValues(string key) { switch (key) { case "Dialogue_hideout_54": case "Dialogue_hideout_56": return HideoutStoryRep; case "Dialogue_downhill_8": return DownhillChallenge1Rep; case "Dialogue_downhill_21": return DownhillChallenge2Rep; case "Dialogue_downhill_33": return DownhillChallenge3Rep; case "Dialogue_downhill_45": case "Dialogue_downhill_49": return DownhillCrewWallRep; case "Dialogue_downhill_215": return DownhillRaveScore; case "Dialogue_downhill_254": return DownhillOldheadRep; case "Dialogue_tower_72A": return TowerChallenge2Score; case "Dialogue_tower_82": return TowerCrewWallRep; case "Dialogue_tower_205": return TowerOldhead1Rep; case "Dialogue_tower_245": case "Dialogue_tower_246": return TowerOldhead2Rep; case "Dialogue_square_51": return SquareOldheadRep; case "Dialogue_Mall_32": return MallChallenge1Rep; case "Dialogue_Mall_61": return MallChallenge3Rep; case "Dialogue_Mall_76": case "Dialogue_Mall_86": case "Dialogue_Mall_87": case "Dialogue_Mall_88": case "Dialogue_Mall_89": case "Dialogue_Mall_91": case "Dialogue_Mall_92": return MallChallenge4Score; case "Dialogue_Mall_96": case "Dialogue_Mall_103": return MallCrewWallRep; case "Dialogue_Mall_205": return MallOldhead2Rep; case "Dialogue_Mall_216": return MallOldhead1Rep; case "Dialogue_pyramid_5": case "Dialogue_pyramid_7": return PyramidGateRep; case "Dialogue_pyramid_71": case "Dialogue_pyramid_74": case "Dialogue_pyramid_75": return PyramidCrewRep; case "Dialogue_pyramid_209": return PyramidOldheadRep; case "Dialogue_osaka_57": return OsakaCrewRep; case "Dialogue_osaka_263": case "Dialogue_osaka_274": return OsakaOldheadRep; case "NOTIFICATION_DOWNHILL_REPFRANKSHIDEOUT": return DownhillCrewWallRep; case "NOTIFICATION_PYRAMID_REPCREWBATTLE": return PyramidCrewRep; case "NOTIFICATION_OSAKA_REPCREWBATTLE": return OsakaCrewRep; default: return null; } } } public class SaveManager { private string m_FolderPath; public int currentSlot = -1; public SaveSlotData CurrentSaveSlot => Core.Instance.SaveManager.CurrentSaveSlot; public string FolderPath => m_FolderPath; public void GetSavePath() { m_FolderPath = Traverse.Create((object)Core.Instance.BaseModule).Field("saveManager").Field("storage") .Field<string>("storageDirectory") .Value; } public bool DataExists(int slot = -1) { int num = slot; if (num == -1) { num = currentSlot; } string path = Path.Combine(FolderPath, $"archipelago{num}.json"); return File.Exists(path); } public void SaveData(int slot = -1) { int num = slot; if (num == -1) { num = currentSlot; } string path = Path.Combine(FolderPath, $"archipelago{num}.json"); byte[] bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject((object)Core.Instance.Data)); File.WriteAllBytes(path, bytes); } public void LoadData(int slot = -1) { int num = slot; if (num == -1) { num = currentSlot; } string text = Path.Combine(FolderPath, $"archipelago{num}.json"); if (File.Exists(text)) { using (StreamReader streamReader = new StreamReader(text)) { Core.Instance.Data = JsonConvert.DeserializeObject<Data>(streamReader.ReadToEnd()); } Core.Logger.LogInfo((object)("Loaded from " + text)); } else { Core.Logger.LogWarning((object)("File at " + text + " doesn't exist. Resetting data.")); Core.Instance.Data = new Data(); } } public void DeleteData(int slot = -1) { int num = slot; if (num == -1) { num = currentSlot; } string text = Path.Combine(FolderPath, $"archipelago{num}.json"); if (File.Exists(text)) { File.Delete(text); } Core.Instance.Data = new Data(); Core.Logger.LogInfo((object)("Deleted data at " + text)); } public void UnlockCharacter(Characters character) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) CurrentSaveSlot.GetCharacterProgress(character).unlocked = true; Core.Instance.SaveManager.SaveCurrentSaveSlot(); } public void UnlockMaps() { StageProgress[] allStageProgress = CurrentSaveSlot.GetAllStageProgress(); foreach (StageProgress val in allStageProgress) { val.mapFound = true; } } public bool IsAnyGraffitiUnlocked(GraffitiSize size) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_001a: Unknown result type (might be due to invalid IL or missing references) if ((int)size == 0) { return true; } bool result = false; foreach (GraffitiArt item in WorldHandler.instance.graffitiArtInfo.FindBySize(size)) { if (CurrentSaveSlot.GetUnlockableDataByUid(((AUnlockable)item.unlockable).Uid).IsUnlocked) { result = true; break; } } return result; } public int CountCharactersUnlocked() { int num = 0; CharacterProgress[] value = Traverse.Create((object)CurrentSaveSlot).Field<CharacterProgress[]>("totalCharacterProgress").Value; for (int i = 0; i < value.Length; i++) { if (value[i].unlocked) { num++; } } return num; } } public class UIManager { public static AssetBundle bundle = AssetBundle.LoadFromMemory(Resources.archipelago); public TextMeshProMenuButton SaveSlotOneButton; public TextMeshProMenuButton SaveSlotTwoButton; public TextMeshProMenuButton SaveSlotThreeButton; public APSlotButton APSlotOneButton; public APSlotButton APSlotTwoButton; public APSlotButton APSlotThreeButton; public List<APSlotButton> slotButtons = new List<APSlotButton>(); public SaveSlotMenu ssm; public UIAnimationController uiac; public GameObject SelectionBarImage; public TextMeshProUGUI APMenuHeaderText; public TextMeshProUGUI APMenuNameLabel; public TextMeshProUGUI APMenuAddressLabel; public TextMeshProUGUI APMenuPasswordLabel; public TMP_InputField APMenuNameInput; public TMP_InputField APMenuAddressInput; public TMP_InputField APMenuPasswordInput; public TextMeshProUGUI APMenuStatus; public TextMeshProUGUI APMenuLocations; public const int maxLocations = 247; public TextMeshProUGUI APMenuResult; public TextMeshProUGUI APMenuChat; public int connectingSlot = -1; public SelectEnlargeButton APMenuConnectButton; public SelectEnlargeButton APMenuCancelButton; public static TMP_FontAsset font; public static Color menuOrange => new Color(1f, 0.54f, 0f); public void FindSaveSlotMenu() { if (!((Object)(object)ssm != (Object)null)) { ssm = Traverse.Create((object)Core.Instance.UIManager).Field<SaveSlotMenu>("saveSlotsMenu").Value; } } public void FindUIAnimController() { if (!((Object)(object)uiac != (Object)null)) { uiac = Traverse.Create((object)ssm).Field<UIAnimationController[]>("menuAnimations").Value[0]; } } public void CreateAPButtons() { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Expected O, but got Unknown //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Expected O, but got Unknown //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_0345: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Unknown result type (might be due to invalid IL or missing references) //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_0370: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: Unknown result type (might be due to invalid IL or missing references) //IL_0435: Unknown result type (might be due to invalid IL or missing references) //IL_043a: Unknown result type (might be due to invalid IL or missing references) //IL_044e: Unknown result type (might be due to invalid IL or missing references) //IL_0472: Unknown result type (might be due to invalid IL or missing references) //IL_0477: Unknown result type (might be due to invalid IL or missing references) //IL_047b: Unknown result type (might be due to invalid IL or missing references) //IL_0495: Unknown result type (might be due to invalid IL or missing references) //IL_04d1: Unknown result type (might be due to invalid IL or missing references) //IL_0508: Unknown result type (might be due to invalid IL or missing references) //IL_050d: Unknown result type (might be due to invalid IL or missing references) //IL_0511: Unknown result type (might be due to invalid IL or missing references) //IL_0523: Unknown result type (might be due to invalid IL or missing references) //IL_0528: Unknown result type (might be due to invalid IL or missing references) //IL_053f: Unknown result type (might be due to invalid IL or missing references) //IL_0551: Unknown result type (might be due to invalid IL or missing references) //IL_0556: Unknown result type (might be due to invalid IL or missing references) //IL_0576: Unknown result type (might be due to invalid IL or missing references) //IL_05cb: Unknown result type (might be due to invalid IL or missing references) //IL_05d0: Unknown result type (might be due to invalid IL or missing references) //IL_05d4: Unknown result type (might be due to invalid IL or missing references) //IL_05e6: Unknown result type (might be due to invalid IL or missing references) //IL_05eb: Unknown result type (might be due to invalid IL or missing references) //IL_060b: Unknown result type (might be due to invalid IL or missing references) //IL_0660: Unknown result type (might be due to invalid IL or missing references) //IL_0665: Unknown result type (might be due to invalid IL or missing references) //IL_0669: Unknown result type (might be due to invalid IL or missing references) //IL_067b: Unknown result type (might be due to invalid IL or missing references) //IL_0680: Unknown result type (might be due to invalid IL or missing references) //IL_06a0: Unknown result type (might be due to invalid IL or missing references) //IL_06fd: Unknown result type (might be due to invalid IL or missing references) //IL_0724: Unknown result type (might be due to invalid IL or missing references) //IL_0729: Unknown result type (might be due to invalid IL or missing references) //IL_072d: Unknown result type (might be due to invalid IL or missing references) //IL_073f: Unknown result type (might be due to invalid IL or missing references) //IL_0744: Unknown result type (might be due to invalid IL or missing references) //IL_0764: Unknown result type (might be due to invalid IL or missing references) //IL_07a9: Unknown result type (might be due to invalid IL or missing references) //IL_07ae: Unknown result type (might be due to invalid IL or missing references) //IL_07bd: Unknown result type (might be due to invalid IL or missing references) //IL_07d7: Unknown result type (might be due to invalid IL or missing references) //IL_081c: Unknown result type (might be due to invalid IL or missing references) //IL_0821: Unknown result type (might be due to invalid IL or missing references) //IL_0830: Unknown result type (might be due to invalid IL or missing references) //IL_084a: Unknown result type (might be due to invalid IL or missing references) //IL_0886: Unknown result type (might be due to invalid IL or missing references) //IL_08ad: Unknown result type (might be due to invalid IL or missing references) //IL_08b2: Unknown result type (might be due to invalid IL or missing references) //IL_08b6: Unknown result type (might be due to invalid IL or missing references) //IL_08c8: Unknown result type (might be due to invalid IL or missing references) //IL_08cd: Unknown result type (might be due to invalid IL or missing references) //IL_08ed: Unknown result type (might be due to invalid IL or missing references) //IL_0936: Unknown result type (might be due to invalid IL or missing references) //IL_095d: Unknown result type (might be due to invalid IL or missing references) //IL_0962: Unknown result type (might be due to invalid IL or missing references) //IL_0966: Unknown result type (might be due to invalid IL or missing references) //IL_0978: Unknown result type (might be due to invalid IL or missing references) //IL_097d: Unknown result type (might be due to invalid IL or missing references) //IL_099d: Unknown result type (might be due to invalid IL or missing references) //IL_09f9: Unknown result type (might be due to invalid IL or missing references) //IL_0a20: Unknown result type (might be due to invalid IL or missing references) //IL_0a25: Unknown result type (might be due to invalid IL or missing references) //IL_0a34: Unknown result type (might be due to invalid IL or missing references) //IL_0a4e: Unknown result type (might be due to invalid IL or missing references) //IL_0ad4: Unknown result type (might be due to invalid IL or missing references) //IL_0af9: Unknown result type (might be due
plugins/Archipelago.MultiClient.Net.dll
Decompiled 5 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.WebSockets; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Text; using System.Threading; using System.Threading.Tasks; using Archipelago.MultiClient.Net.ConcurrentCollection; using Archipelago.MultiClient.Net.Converters; using Archipelago.MultiClient.Net.DataPackage; using Archipelago.MultiClient.Net.Enums; using Archipelago.MultiClient.Net.Exceptions; using Archipelago.MultiClient.Net.Extensions; using Archipelago.MultiClient.Net.Helpers; using Archipelago.MultiClient.Net.MessageLog.Messages; using Archipelago.MultiClient.Net.MessageLog.Parts; using Archipelago.MultiClient.Net.Models; using Archipelago.MultiClient.Net.Packets; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: ComVisible(false)] [assembly: Guid("35a803ad-85ed-42e9-b1e3-c6b72096f0c1")] [assembly: InternalsVisibleTo("Archipelago.MultiClient.Net.Tests")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] [assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")] [assembly: AssemblyCompany("Jarno Westhof, Hussein Farran, Zach Parks")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyDescription("A client library for use with .NET based prog-langs for interfacing with Archipelago hosts.")] [assembly: AssemblyFileVersion("6.2.0.0")] [assembly: AssemblyInformationalVersion("6.2.0+b5d4eff8263e17e3f0728b4c87f7392b12e63156")] [assembly: AssemblyProduct("Archipelago.MultiClient.Net")] [assembly: AssemblyTitle("Archipelago.MultiClient.Net")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/ArchipelagoMW/Archipelago.MultiClient.Net")] [assembly: AssemblyVersion("6.2.0.0")] internal interface IConcurrentHashSet<T> { bool TryAdd(T item); bool Contains(T item); void UnionWith(T[] otherSet); T[] ToArray(); ReadOnlyCollection<T> AsToReadOnlyCollection(); ReadOnlyCollection<T> AsToReadOnlyCollectionExcept(IConcurrentHashSet<T> otherSet); } namespace Archipelago.MultiClient.Net { [Serializable] public abstract class ArchipelagoPacketBase { [JsonIgnore] internal JObject jobject; [JsonProperty("cmd")] [JsonConverter(typeof(StringEnumConverter))] public abstract ArchipelagoPacketType PacketType { get; } public JObject ToJObject() { return jobject; } } public interface IArchipelagoSession : IArchipelagoSessionActions { IArchipelagoSocketHelper Socket { get; } IReceivedItemsHelper Items { get; } ILocationCheckHelper Locations { get; } IPlayerHelper Players { get; } IDataStorageHelper DataStorage { get; } IConnectionInfoProvider ConnectionInfo { get; } IRoomStateHelper RoomState { get; } IMessageLogHelper MessageLog { get; } Task<RoomInfoPacket> ConnectAsync(); Task<LoginResult> LoginAsync(string game, string name, ItemsHandlingFlags itemsHandlingFlags, Version version = null, string[] tags = null, string uuid = null, string password = null, bool requestSlotData = true); LoginResult TryConnectAndLogin(string game, string name, ItemsHandlingFlags itemsHandlingFlags, Version version = null, string[] tags = null, string uuid = null, string password = null, bool requestSlotData = true); } public class ArchipelagoSession : IArchipelagoSession, IArchipelagoSessionActions { private const int ArchipelagoConnectionTimeoutInSeconds = 4; private ConnectionInfoHelper connectionInfo; private TaskCompletionSource<LoginResult> loginResultTask = new TaskCompletionSource<LoginResult>(); private TaskCompletionSource<RoomInfoPacket> roomInfoPacketTask = new TaskCompletionSource<RoomInfoPacket>(); public IArchipelagoSocketHelper Socket { get; } public IReceivedItemsHelper Items { get; } public ILocationCheckHelper Locations { get; } public IPlayerHelper Players { get; } public IDataStorageHelper DataStorage { get; } public IConnectionInfoProvider ConnectionInfo => connectionInfo; public IRoomStateHelper RoomState { get; } public IMessageLogHelper MessageLog { get; } internal ArchipelagoSession(IArchipelagoSocketHelper socket, IReceivedItemsHelper items, ILocationCheckHelper locations, IPlayerHelper players, IRoomStateHelper roomState, ConnectionInfoHelper connectionInfoHelper, IDataStorageHelper dataStorage, IMessageLogHelper messageLog) { Socket = socket; Items = items; Locations = locations; Players = players; RoomState = roomState; connectionInfo = connectionInfoHelper; DataStorage = dataStorage; MessageLog = messageLog; socket.PacketReceived += Socket_PacketReceived; } private void Socket_PacketReceived(ArchipelagoPacketBase packet) { if (!(packet is ConnectedPacket) && !(packet is ConnectionRefusedPacket)) { if (packet is RoomInfoPacket result) { roomInfoPacketTask.TrySetResult(result); } return; } if (packet is ConnectedPacket && RoomState.Version != null && RoomState.Version >= new Version(0, 3, 8)) { LogUsedVersion(); } loginResultTask.TrySetResult(LoginResult.FromPacket(packet)); } private void LogUsedVersion() { try { string fileVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion; Socket.SendPacketAsync(new SetPacket { Key = ".NetUsedVersions", DefaultValue = (JToken)(object)JObject.FromObject((object)new Dictionary<string, bool>()), Operations = new OperationSpecification[1] { Operation.Update(new Dictionary<string, bool> { { ConnectionInfo.Game + ":" + fileVersion + ":NET45", true } }) } }); } catch { } } public Task<RoomInfoPacket> ConnectAsync() { roomInfoPacketTask = new TaskCompletionSource<RoomInfoPacket>(); Task.Factory.StartNew(delegate { try { Task task = Socket.ConnectAsync(); task.Wait(TimeSpan.FromSeconds(4.0)); if (!task.IsCompleted) { roomInfoPacketTask.TrySetCanceled(); } } catch (AggregateException) { roomInfoPacketTask.TrySetCanceled(); } }); return roomInfoPacketTask.Task; } public Task<LoginResult> LoginAsync(string game, string name, ItemsHandlingFlags itemsHandlingFlags, Version version = null, string[] tags = null, string uuid = null, string password = null, bool requestSlotData = true) { loginResultTask = new TaskCompletionSource<LoginResult>(); if (!roomInfoPacketTask.Task.IsCompleted) { loginResultTask = new TaskCompletionSource<LoginResult>(); loginResultTask.TrySetResult(new LoginFailure("You are not connected, run ConnectAsync() first")); return loginResultTask.Task; } connectionInfo.SetConnectionParameters(game, tags, itemsHandlingFlags, uuid); try { Socket.SendPacket(BuildConnectPacket(name, password, version, requestSlotData)); } catch (ArchipelagoSocketClosedException) { loginResultTask.TrySetResult(new LoginFailure("You are not connected, run ConnectAsync() first")); return loginResultTask.Task; } SetResultAfterTimeout(loginResultTask, 4, new LoginFailure("Connection timed out.")); return loginResultTask.Task; } private static void SetResultAfterTimeout<T>(TaskCompletionSource<T> task, int timeoutInSeconds, T result) { new CancellationTokenSource(TimeSpan.FromSeconds(timeoutInSeconds)).Token.Register(delegate { task.TrySetResult(result); }); } public LoginResult TryConnectAndLogin(string game, string name, ItemsHandlingFlags itemsHandlingFlags, Version version = null, string[] tags = null, string uuid = null, string password = null, bool requestSlotData = true) { Task<RoomInfoPacket> task = ConnectAsync(); try { task.Wait(TimeSpan.FromSeconds(4.0)); } catch (AggregateException ex) { if (ex.GetBaseException() is OperationCanceledException) { return new LoginFailure("Connection timed out."); } return new LoginFailure(ex.GetBaseException().Message); } if (!task.IsCompleted) { return new LoginFailure("Connection timed out."); } return LoginAsync(game, name, itemsHandlingFlags, version, tags, uuid, password, requestSlotData).Result; } private ConnectPacket BuildConnectPacket(string name, string password, Version version, bool requestSlotData) { return new ConnectPacket { Game = ConnectionInfo.Game, Name = name, Password = password, Tags = ConnectionInfo.Tags, Uuid = ConnectionInfo.Uuid, Version = ((version != null) ? new NetworkVersion(version) : new NetworkVersion(0, 4, 0)), ItemsHandling = ConnectionInfo.ItemsHandlingFlags, RequestSlotData = requestSlotData }; } public void Say(string message) { Socket.SendPacket(new SayPacket { Text = message }); } public void SetClientState(ArchipelagoClientState state) { Socket.SendPacket(new StatusUpdatePacket { Status = state }); } public void SetGoalAchieved() { SetClientState(ArchipelagoClientState.ClientGoal); } } public interface IArchipelagoSessionActions { void Say(string message); void SetClientState(ArchipelagoClientState state); void SetGoalAchieved(); } public static class ArchipelagoSessionFactory { public static ArchipelagoSession CreateSession(Uri uri) { ArchipelagoSocketHelper socket = new ArchipelagoSocketHelper(uri); DataPackageCache cache = new DataPackageCache(socket); ConnectionInfoHelper connectionInfoHelper = new ConnectionInfoHelper(socket); PlayerHelper playerHelper = new PlayerHelper(socket, connectionInfoHelper); ItemInfoResolver itemInfoResolver = new ItemInfoResolver(cache, connectionInfoHelper); LocationCheckHelper locationCheckHelper = new LocationCheckHelper(socket, itemInfoResolver, connectionInfoHelper, playerHelper); ReceivedItemsHelper items = new ReceivedItemsHelper(socket, locationCheckHelper, itemInfoResolver, connectionInfoHelper, playerHelper); RoomStateHelper roomState = new RoomStateHelper(socket, locationCheckHelper); DataStorageHelper dataStorage = new DataStorageHelper(socket, connectionInfoHelper); MessageLogHelper messageLog = new MessageLogHelper(socket, itemInfoResolver, playerHelper, connectionInfoHelper); return new ArchipelagoSession(socket, items, locationCheckHelper, playerHelper, roomState, connectionInfoHelper, dataStorage, messageLog); } public static ArchipelagoSession CreateSession(string hostname, int port = 38281) { return CreateSession(ParseUri(hostname, port)); } internal static Uri ParseUri(string hostname, int port) { string text = hostname; if (!text.StartsWith("ws://") && !text.StartsWith("wss://")) { text = "unspecified://" + text; } if (!text.Substring(text.IndexOf("://", StringComparison.Ordinal) + 3).Contains(":")) { text += $":{port}"; } if (text.EndsWith(":")) { text += port; } return new Uri(text); } } public abstract class LoginResult { public abstract bool Successful { get; } public static LoginResult FromPacket(ArchipelagoPacketBase packet) { if (!(packet is ConnectedPacket connectedPacket)) { if (packet is ConnectionRefusedPacket connectionRefusedPacket) { return new LoginFailure(connectionRefusedPacket); } throw new ArgumentOutOfRangeException("packet", "packet is not a connection result packet"); } return new LoginSuccessful(connectedPacket); } } public class LoginSuccessful : LoginResult { public override bool Successful => true; public int Team { get; } public int Slot { get; } public Dictionary<string, object> SlotData { get; } public LoginSuccessful(ConnectedPacket connectedPacket) { Team = connectedPacket.Team; Slot = connectedPacket.Slot; SlotData = connectedPacket.SlotData; } } public class LoginFailure : LoginResult { public override bool Successful => false; public ConnectionRefusedError[] ErrorCodes { get; } public string[] Errors { get; } public LoginFailure(ConnectionRefusedPacket connectionRefusedPacket) { if (connectionRefusedPacket.Errors != null) { ErrorCodes = connectionRefusedPacket.Errors.ToArray(); Errors = ErrorCodes.Select(GetErrorMessage).ToArray(); } else { ErrorCodes = new ConnectionRefusedError[0]; Errors = new string[0]; } } public LoginFailure(string message) { ErrorCodes = new ConnectionRefusedError[0]; Errors = new string[1] { message }; } private static string GetErrorMessage(ConnectionRefusedError errorCode) { return errorCode switch { ConnectionRefusedError.InvalidSlot => "The slot name did not match any slot on the server.", ConnectionRefusedError.InvalidGame => "The slot is set to a different game on the server.", ConnectionRefusedError.SlotAlreadyTaken => "The slot already has a connection with a different uuid established.", ConnectionRefusedError.IncompatibleVersion => "The client and server version mismatch.", ConnectionRefusedError.InvalidPassword => "The password is invalid.", ConnectionRefusedError.InvalidItemsHandling => "The item handling flags provided are invalid.", _ => $"Unknown error: {errorCode}.", }; } } internal class TwoWayLookup<TA, TB> : IEnumerable<KeyValuePair<TB, TA>>, IEnumerable { private readonly Dictionary<TA, TB> aToB = new Dictionary<TA, TB>(); private readonly Dictionary<TB, TA> bToA = new Dictionary<TB, TA>(); public TA this[TB b] => bToA[b]; public TB this[TA a] => aToB[a]; public void Add(TA a, TB b) { aToB[a] = b; bToA[b] = a; } public void Add(TB b, TA a) { Add(a, b); } public bool TryGetValue(TA a, out TB b) { return aToB.TryGetValue(a, out b); } public bool TryGetValue(TB b, out TA a) { return bToA.TryGetValue(b, out a); } public IEnumerator<KeyValuePair<TB, TA>> GetEnumerator() { return bToA.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } } namespace Archipelago.MultiClient.Net.Packets { public class BouncedPacket : BouncePacket { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Bounced; } public class BouncePacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Bounce; [JsonProperty("games")] public List<string> Games { get; set; } = new List<string>(); [JsonProperty("slots")] public List<int> Slots { get; set; } = new List<int>(); [JsonProperty("tags")] public List<string> Tags { get; set; } = new List<string>(); [JsonProperty("data")] public Dictionary<string, JToken> Data { get; set; } } public class ConnectedPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Connected; [JsonProperty("team")] public int Team { get; set; } [JsonProperty("slot")] public int Slot { get; set; } [JsonProperty("players")] public NetworkPlayer[] Players { get; set; } [JsonProperty("missing_locations")] public long[] MissingChecks { get; set; } [JsonProperty("checked_locations")] public long[] LocationsChecked { get; set; } [JsonProperty("slot_data")] public Dictionary<string, object> SlotData { get; set; } [JsonProperty("slot_info")] public Dictionary<int, NetworkSlot> SlotInfo { get; set; } [JsonProperty("hint_points")] public int? HintPoints { get; set; } } public class ConnectionRefusedPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.ConnectionRefused; [JsonProperty("errors", ItemConverterType = typeof(StringEnumConverter))] public ConnectionRefusedError[] Errors { get; set; } } public class ConnectPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Connect; [JsonProperty("password")] public string Password { get; set; } [JsonProperty("game")] public string Game { get; set; } [JsonProperty("name")] public string Name { get; set; } [JsonProperty("uuid")] public string Uuid { get; set; } [JsonProperty("version")] public NetworkVersion Version { get; set; } [JsonProperty("tags")] public string[] Tags { get; set; } [JsonProperty("items_handling")] public ItemsHandlingFlags ItemsHandling { get; set; } [JsonProperty("slot_data")] public bool RequestSlotData { get; set; } } public class ConnectUpdatePacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.ConnectUpdate; [JsonProperty("tags")] public string[] Tags { get; set; } [JsonProperty("items_handling")] public ItemsHandlingFlags? ItemsHandling { get; set; } } public class DataPackagePacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.DataPackage; [JsonProperty("data")] public Archipelago.MultiClient.Net.Models.DataPackage DataPackage { get; set; } } public class GetDataPackagePacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.GetDataPackage; [JsonProperty("games")] public string[] Games { get; set; } } public class GetPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Get; [JsonProperty("keys")] public string[] Keys { get; set; } } public class InvalidPacketPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.InvalidPacket; [JsonProperty("type")] public InvalidPacketErrorType ErrorType { get; set; } [JsonProperty("text")] public string ErrorText { get; set; } [JsonProperty("original_cmd")] public ArchipelagoPacketType OriginalCmd { get; set; } } public class LocationChecksPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.LocationChecks; [JsonProperty("locations")] public long[] Locations { get; set; } } public class LocationInfoPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.LocationInfo; [JsonProperty("locations")] public NetworkItem[] Locations { get; set; } } public class LocationScoutsPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.LocationScouts; [JsonProperty("locations")] public long[] Locations { get; set; } [JsonProperty("create_as_hint")] public int CreateAsHint { get; set; } } public class PrintJsonPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.PrintJSON; [JsonProperty("data")] public JsonMessagePart[] Data { get; set; } [JsonProperty("type")] [JsonConverter(typeof(StringEnumConverter))] public JsonMessageType? MessageType { get; set; } } public class ItemPrintJsonPacket : PrintJsonPacket { [JsonProperty("receiving")] public int ReceivingPlayer { get; set; } [JsonProperty("item")] public NetworkItem Item { get; set; } } public class ItemCheatPrintJsonPacket : PrintJsonPacket { [JsonProperty("receiving")] public int ReceivingPlayer { get; set; } [JsonProperty("item")] public NetworkItem Item { get; set; } [JsonProperty("team")] public int Team { get; set; } } public class HintPrintJsonPacket : PrintJsonPacket { [JsonProperty("receiving")] public int ReceivingPlayer { get; set; } [JsonProperty("item")] public NetworkItem Item { get; set; } [JsonProperty("found")] public bool? Found { get; set; } } public class JoinPrintJsonPacket : PrintJsonPacket { [JsonProperty("team")] public int Team { get; set; } [JsonProperty("slot")] public int Slot { get; set; } [JsonProperty("tags")] public string[] Tags { get; set; } } public class LeavePrintJsonPacket : PrintJsonPacket { [JsonProperty("team")] public int Team { get; set; } [JsonProperty("slot")] public int Slot { get; set; } } public class ChatPrintJsonPacket : PrintJsonPacket { [JsonProperty("team")] public int Team { get; set; } [JsonProperty("slot")] public int Slot { get; set; } [JsonProperty("message")] public string Message { get; set; } } public class ServerChatPrintJsonPacket : PrintJsonPacket { [JsonProperty("message")] public string Message { get; set; } } public class TutorialPrintJsonPacket : PrintJsonPacket { } public class TagsChangedPrintJsonPacket : PrintJsonPacket { [JsonProperty("team")] public int Team { get; set; } [JsonProperty("slot")] public int Slot { get; set; } [JsonProperty("tags")] public string[] Tags { get; set; } } public class CommandResultPrintJsonPacket : PrintJsonPacket { } public class AdminCommandResultPrintJsonPacket : PrintJsonPacket { } public class GoalPrintJsonPacket : PrintJsonPacket { [JsonProperty("team")] public int Team { get; set; } [JsonProperty("slot")] public int Slot { get; set; } } public class ReleasePrintJsonPacket : PrintJsonPacket { [JsonProperty("team")] public int Team { get; set; } [JsonProperty("slot")] public int Slot { get; set; } } public class CollectPrintJsonPacket : PrintJsonPacket { [JsonProperty("team")] public int Team { get; set; } [JsonProperty("slot")] public int Slot { get; set; } } public class CountdownPrintJsonPacket : PrintJsonPacket { [JsonProperty("countdown")] public int RemainingSeconds { get; set; } } public class ReceivedItemsPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.ReceivedItems; [JsonProperty("index")] public int Index { get; set; } [JsonProperty("items")] public NetworkItem[] Items { get; set; } } public class RetrievedPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Retrieved; [JsonProperty("keys")] public Dictionary<string, JToken> Data { get; set; } } public class RoomInfoPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.RoomInfo; [JsonProperty("version")] public NetworkVersion Version { get; set; } [JsonProperty("generator_version")] public NetworkVersion GeneratorVersion { get; set; } [JsonProperty("tags")] public string[] Tags { get; set; } [JsonProperty("password")] public bool Password { get; set; } [JsonProperty("permissions")] public Dictionary<string, Permissions> Permissions { get; set; } [JsonProperty("hint_cost")] public int HintCostPercentage { get; set; } [JsonProperty("location_check_points")] public int LocationCheckPoints { get; set; } [JsonProperty("players")] public NetworkPlayer[] Players { get; set; } [JsonProperty("games")] public string[] Games { get; set; } [JsonProperty("datapackage_checksums")] public Dictionary<string, string> DataPackageChecksums { get; set; } [JsonProperty("seed_name")] public string SeedName { get; set; } [JsonProperty("time")] public double Timestamp { get; set; } } public class RoomUpdatePacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.RoomUpdate; [JsonProperty("tags")] public string[] Tags { get; set; } [JsonProperty("password")] public bool? Password { get; set; } [JsonProperty("permissions")] public Dictionary<string, Permissions> Permissions { get; set; } = new Dictionary<string, Permissions>(); [JsonProperty("hint_cost")] public int? HintCostPercentage { get; set; } [JsonProperty("location_check_points")] public int? LocationCheckPoints { get; set; } [JsonProperty("players")] public NetworkPlayer[] Players { get; set; } [JsonProperty("hint_points")] public int? HintPoints { get; set; } [JsonProperty("checked_locations")] public long[] CheckedLocations { get; set; } } public class SayPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Say; [JsonProperty("text")] public string Text { get; set; } } public class SetNotifyPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.SetNotify; [JsonProperty("keys")] public string[] Keys { get; set; } } public class SetPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Set; [JsonProperty("key")] public string Key { get; set; } [JsonProperty("default")] public JToken DefaultValue { get; set; } [JsonProperty("operations")] public OperationSpecification[] Operations { get; set; } [JsonProperty("want_reply")] public bool WantReply { get; set; } [JsonExtensionData] public Dictionary<string, JToken> AdditionalArguments { get; set; } [OnDeserialized] internal void OnDeserializedMethod(StreamingContext context) { AdditionalArguments?.Remove("cmd"); } } public class SetReplyPacket : SetPacket { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.SetReply; [JsonProperty("value")] public JToken Value { get; set; } [JsonProperty("original_value")] public JToken OriginalValue { get; set; } } public class StatusUpdatePacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.StatusUpdate; [JsonProperty("status")] public ArchipelagoClientState Status { get; set; } } public class SyncPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Sync; } internal class UnknownPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Unknown; } } namespace Archipelago.MultiClient.Net.Models { public struct Color : IEquatable<Color> { public static Color Red = new Color(byte.MaxValue, 0, 0); public static Color Green = new Color(0, 128, 0); public static Color Yellow = new Color(byte.MaxValue, byte.MaxValue, 0); public static Color Blue = new Color(0, 0, byte.MaxValue); public static Color Magenta = new Color(byte.MaxValue, 0, byte.MaxValue); public static Color Cyan = new Color(0, byte.MaxValue, byte.MaxValue); public static Color Black = new Color(0, 0, 0); public static Color White = new Color(byte.MaxValue, byte.MaxValue, byte.MaxValue); public static Color SlateBlue = new Color(106, 90, 205); public static Color Salmon = new Color(250, 128, 114); public static Color Plum = new Color(221, 160, 221); public byte R { get; set; } public byte G { get; set; } public byte B { get; set; } public Color(byte r, byte g, byte b) { R = r; G = g; B = b; } public override bool Equals(object obj) { if (obj is Color color && R == color.R && G == color.G) { return B == color.B; } return false; } public bool Equals(Color other) { if (R == other.R && G == other.G) { return B == other.B; } return false; } public override int GetHashCode() { return ((-1520100960 * -1521134295 + R.GetHashCode()) * -1521134295 + G.GetHashCode()) * -1521134295 + B.GetHashCode(); } public static bool operator ==(Color left, Color right) { return left.Equals(right); } public static bool operator !=(Color left, Color right) { return !(left == right); } } public class DataPackage { [JsonProperty("games")] public Dictionary<string, GameData> Games { get; set; } = new Dictionary<string, GameData>(); } public class DataStorageElement { internal DataStorageElementContext Context; internal List<OperationSpecification> Operations = new List<OperationSpecification>(0); internal DataStorageHelper.DataStorageUpdatedHandler Callbacks; internal Dictionary<string, JToken> AdditionalArguments = new Dictionary<string, JToken>(0); private JToken cachedValue; public event DataStorageHelper.DataStorageUpdatedHandler OnValueChanged { add { Context.AddHandler(Context.Key, value); } remove { Context.RemoveHandler(Context.Key, value); } } internal DataStorageElement(DataStorageElementContext context) { Context = context; } internal DataStorageElement(OperationType operationType, JToken value) { Operations = new List<OperationSpecification>(1) { new OperationSpecification { OperationType = operationType, Value = value } }; } internal DataStorageElement(DataStorageElement source, OperationType operationType, JToken value) : this(source.Context) { Operations = source.Operations.ToList(); Callbacks = source.Callbacks; AdditionalArguments = source.AdditionalArguments; Operations.Add(new OperationSpecification { OperationType = operationType, Value = value }); } internal DataStorageElement(DataStorageElement source, Callback callback) : this(source.Context) { Operations = source.Operations.ToList(); Callbacks = source.Callbacks; AdditionalArguments = source.AdditionalArguments; Callbacks = (DataStorageHelper.DataStorageUpdatedHandler)Delegate.Combine(Callbacks, callback.Method); } internal DataStorageElement(DataStorageElement source, AdditionalArgument additionalArgument) : this(source.Context) { Operations = source.Operations.ToList(); Callbacks = source.Callbacks; AdditionalArguments = source.AdditionalArguments; AdditionalArguments[additionalArgument.Key] = additionalArgument.Value; } public static DataStorageElement operator ++(DataStorageElement a) { return new DataStorageElement(a, OperationType.Add, JToken.op_Implicit(1)); } public static DataStorageElement operator --(DataStorageElement a) { return new DataStorageElement(a, OperationType.Add, JToken.op_Implicit(-1)); } public static DataStorageElement operator +(DataStorageElement a, int b) { return new DataStorageElement(a, OperationType.Add, JToken.op_Implicit(b)); } public static DataStorageElement operator +(DataStorageElement a, long b) { return new DataStorageElement(a, OperationType.Add, JToken.op_Implicit(b)); } public static DataStorageElement operator +(DataStorageElement a, float b) { return new DataStorageElement(a, OperationType.Add, JToken.op_Implicit(b)); } public static DataStorageElement operator +(DataStorageElement a, double b) { return new DataStorageElement(a, OperationType.Add, JToken.op_Implicit(b)); } public static DataStorageElement operator +(DataStorageElement a, decimal b) { return new DataStorageElement(a, OperationType.Add, JToken.op_Implicit(b)); } public static DataStorageElement operator +(DataStorageElement a, string b) { return new DataStorageElement(a, OperationType.Add, JToken.op_Implicit(b)); } public static DataStorageElement operator +(DataStorageElement a, JToken b) { return new DataStorageElement(a, OperationType.Add, b); } public static DataStorageElement operator +(DataStorageElement a, IEnumerable b) { return new DataStorageElement(a, OperationType.Add, (JToken)(object)JArray.FromObject((object)b)); } public static DataStorageElement operator +(DataStorageElement a, OperationSpecification s) { return new DataStorageElement(a, s.OperationType, s.Value); } public static DataStorageElement operator +(DataStorageElement a, Callback c) { return new DataStorageElement(a, c); } public static DataStorageElement operator +(DataStorageElement a, AdditionalArgument arg) { return new DataStorageElement(a, arg); } public static DataStorageElement operator *(DataStorageElement a, int b) { return new DataStorageElement(a, OperationType.Mul, JToken.op_Implicit(b)); } public static DataStorageElement operator *(DataStorageElement a, long b) { return new DataStorageElement(a, OperationType.Mul, JToken.op_Implicit(b)); } public static DataStorageElement operator *(DataStorageElement a, float b) { return new DataStorageElement(a, OperationType.Mul, JToken.op_Implicit(b)); } public static DataStorageElement operator *(DataStorageElement a, double b) { return new DataStorageElement(a, OperationType.Mul, JToken.op_Implicit(b)); } public static DataStorageElement operator *(DataStorageElement a, decimal b) { return new DataStorageElement(a, OperationType.Mul, JToken.op_Implicit(b)); } public static DataStorageElement operator %(DataStorageElement a, int b) { return new DataStorageElement(a, OperationType.Mod, JToken.op_Implicit(b)); } public static DataStorageElement operator %(DataStorageElement a, long b) { return new DataStorageElement(a, OperationType.Mod, JToken.op_Implicit(b)); } public static DataStorageElement operator %(DataStorageElement a, float b) { return new DataStorageElement(a, OperationType.Mod, JToken.op_Implicit(b)); } public static DataStorageElement operator %(DataStorageElement a, double b) { return new DataStorageElement(a, OperationType.Mod, JToken.op_Implicit(b)); } public static DataStorageElement operator %(DataStorageElement a, decimal b) { return new DataStorageElement(a, OperationType.Mod, JToken.op_Implicit(b)); } public static DataStorageElement operator ^(DataStorageElement a, int b) { return new DataStorageElement(a, OperationType.Pow, JToken.op_Implicit(b)); } public static DataStorageElement operator ^(DataStorageElement a, long b) { return new DataStorageElement(a, OperationType.Pow, JToken.op_Implicit(b)); } public static DataStorageElement operator ^(DataStorageElement a, float b) { return new DataStorageElement(a, OperationType.Pow, JToken.op_Implicit(b)); } public static DataStorageElement operator ^(DataStorageElement a, double b) { return new DataStorageElement(a, OperationType.Pow, JToken.op_Implicit(b)); } public static DataStorageElement operator ^(DataStorageElement a, decimal b) { return new DataStorageElement(a, OperationType.Pow, JToken.op_Implicit(b)); } public static DataStorageElement operator -(DataStorageElement a, int b) { return new DataStorageElement(a, OperationType.Add, JToken.FromObject((object)(-b))); } public static DataStorageElement operator -(DataStorageElement a, long b) { return new DataStorageElement(a, OperationType.Add, JToken.FromObject((object)(-b))); } public static DataStorageElement operator -(DataStorageElement a, float b) { return new DataStorageElement(a, OperationType.Add, JToken.FromObject((object)(0f - b))); } public static DataStorageElement operator -(DataStorageElement a, double b) { return new DataStorageElement(a, OperationType.Add, JToken.FromObject((object)(0.0 - b))); } public static DataStorageElement operator -(DataStorageElement a, decimal b) { return new DataStorageElement(a, OperationType.Add, JToken.FromObject((object)(-b))); } public static DataStorageElement operator /(DataStorageElement a, int b) { return new DataStorageElement(a, OperationType.Mul, JToken.FromObject((object)(1m / (decimal)b))); } public static DataStorageElement operator /(DataStorageElement a, long b) { return new DataStorageElement(a, OperationType.Mul, JToken.FromObject((object)(1m / (decimal)b))); } public static DataStorageElement operator /(DataStorageElement a, float b) { return new DataStorageElement(a, OperationType.Mul, JToken.FromObject((object)(1.0 / (double)b))); } public static DataStorageElement operator /(DataStorageElement a, double b) { return new DataStorageElement(a, OperationType.Mul, JToken.FromObject((object)(1.0 / b))); } public static DataStorageElement operator /(DataStorageElement a, decimal b) { return new DataStorageElement(a, OperationType.Mul, JToken.FromObject((object)(1m / b))); } public static implicit operator DataStorageElement(bool b) { return new DataStorageElement(OperationType.Replace, JToken.op_Implicit(b)); } public static implicit operator DataStorageElement(int i) { return new DataStorageElement(OperationType.Replace, JToken.op_Implicit(i)); } public static implicit operator DataStorageElement(long l) { return new DataStorageElement(OperationType.Replace, JToken.op_Implicit(l)); } public static implicit operator DataStorageElement(decimal m) { return new DataStorageElement(OperationType.Replace, JToken.op_Implicit(m)); } public static implicit operator DataStorageElement(double d) { return new DataStorageElement(OperationType.Replace, JToken.op_Implicit(d)); } public static implicit operator DataStorageElement(float f) { return new DataStorageElement(OperationType.Replace, JToken.op_Implicit(f)); } public static implicit operator DataStorageElement(string s) { if (s != null) { return new DataStorageElement(OperationType.Replace, JToken.op_Implicit(s)); } return new DataStorageElement(OperationType.Replace, (JToken)(object)JValue.CreateNull()); } public static implicit operator DataStorageElement(JToken o) { return new DataStorageElement(OperationType.Replace, o); } public static implicit operator DataStorageElement(Array a) { return new DataStorageElement(OperationType.Replace, (JToken)(object)JArray.FromObject((object)a)); } public static implicit operator DataStorageElement(List<bool> l) { return new DataStorageElement(OperationType.Replace, (JToken)(object)JArray.FromObject((object)l)); } public static implicit operator DataStorageElement(List<int> l) { return new DataStorageElement(OperationType.Replace, (JToken)(object)JArray.FromObject((object)l)); } public static implicit operator DataStorageElement(List<long> l) { return new DataStorageElement(OperationType.Replace, (JToken)(object)JArray.FromObject((object)l)); } public static implicit operator DataStorageElement(List<decimal> l) { return new DataStorageElement(OperationType.Replace, (JToken)(object)JArray.FromObject((object)l)); } public static implicit operator DataStorageElement(List<double> l) { return new DataStorageElement(OperationType.Replace, (JToken)(object)JArray.FromObject((object)l)); } public static implicit operator DataStorageElement(List<float> l) { return new DataStorageElement(OperationType.Replace, (JToken)(object)JArray.FromObject((object)l)); } public static implicit operator DataStorageElement(List<string> l) { return new DataStorageElement(OperationType.Replace, (JToken)(object)JArray.FromObject((object)l)); } public static implicit operator DataStorageElement(List<object> l) { return new DataStorageElement(OperationType.Replace, (JToken)(object)JArray.FromObject((object)l)); } public static implicit operator bool(DataStorageElement e) { return RetrieveAndReturnBoolValue<bool>(e); } public static implicit operator bool?(DataStorageElement e) { return RetrieveAndReturnBoolValue<bool?>(e); } public static implicit operator int(DataStorageElement e) { return RetrieveAndReturnDecimalValue<int>(e); } public static implicit operator int?(DataStorageElement e) { return RetrieveAndReturnDecimalValue<int?>(e); } public static implicit operator long(DataStorageElement e) { return RetrieveAndReturnDecimalValue<long>(e); } public static implicit operator long?(DataStorageElement e) { return RetrieveAndReturnDecimalValue<long?>(e); } public static implicit operator float(DataStorageElement e) { return RetrieveAndReturnDecimalValue<float>(e); } public static implicit operator float?(DataStorageElement e) { return RetrieveAndReturnDecimalValue<float?>(e); } public static implicit operator double(DataStorageElement e) { return RetrieveAndReturnDecimalValue<double>(e); } public static implicit operator double?(DataStorageElement e) { return RetrieveAndReturnDecimalValue<double?>(e); } public static implicit operator decimal(DataStorageElement e) { return RetrieveAndReturnDecimalValue<decimal>(e); } public static implicit operator decimal?(DataStorageElement e) { return RetrieveAndReturnDecimalValue<decimal?>(e); } public static implicit operator string(DataStorageElement e) { return RetrieveAndReturnStringValue(e); } public static implicit operator bool[](DataStorageElement e) { return RetrieveAndReturnArrayValue<bool[]>(e); } public static implicit operator int[](DataStorageElement e) { return RetrieveAndReturnArrayValue<int[]>(e); } public static implicit operator long[](DataStorageElement e) { return RetrieveAndReturnArrayValue<long[]>(e); } public static implicit operator decimal[](DataStorageElement e) { return RetrieveAndReturnArrayValue<decimal[]>(e); } public static implicit operator double[](DataStorageElement e) { return RetrieveAndReturnArrayValue<double[]>(e); } public static implicit operator float[](DataStorageElement e) { return RetrieveAndReturnArrayValue<float[]>(e); } public static implicit operator string[](DataStorageElement e) { return RetrieveAndReturnArrayValue<string[]>(e); } public static implicit operator object[](DataStorageElement e) { return RetrieveAndReturnArrayValue<object[]>(e); } public static implicit operator List<bool>(DataStorageElement e) { return RetrieveAndReturnArrayValue<List<bool>>(e); } public static implicit operator List<int>(DataStorageElement e) { return RetrieveAndReturnArrayValue<List<int>>(e); } public static implicit operator List<long>(DataStorageElement e) { return RetrieveAndReturnArrayValue<List<long>>(e); } public static implicit operator List<decimal>(DataStorageElement e) { return RetrieveAndReturnArrayValue<List<decimal>>(e); } public static implicit operator List<double>(DataStorageElement e) { return RetrieveAndReturnArrayValue<List<double>>(e); } public static implicit operator List<float>(DataStorageElement e) { return RetrieveAndReturnArrayValue<List<float>>(e); } public static implicit operator List<string>(DataStorageElement e) { return RetrieveAndReturnArrayValue<List<string>>(e); } public static implicit operator List<object>(DataStorageElement e) { return RetrieveAndReturnArrayValue<List<object>>(e); } public static implicit operator Array(DataStorageElement e) { return RetrieveAndReturnArrayValue<Array>(e); } public static implicit operator JArray(DataStorageElement e) { return RetrieveAndReturnArrayValue<JArray>(e); } public static implicit operator JToken(DataStorageElement e) { return e.Context.GetData(e.Context.Key); } public static DataStorageElement operator +(DataStorageElement a, BigInteger b) { return new DataStorageElement(a, OperationType.Add, JToken.Parse(b.ToString())); } public static DataStorageElement operator *(DataStorageElement a, BigInteger b) { return new DataStorageElement(a, OperationType.Mul, JToken.Parse(b.ToString())); } public static DataStorageElement operator %(DataStorageElement a, BigInteger b) { return new DataStorageElement(a, OperationType.Mod, JToken.Parse(b.ToString())); } public static DataStorageElement operator ^(DataStorageElement a, BigInteger b) { return new DataStorageElement(a, OperationType.Pow, JToken.Parse(b.ToString())); } public static DataStorageElement operator -(DataStorageElement a, BigInteger b) { return new DataStorageElement(a, OperationType.Add, JToken.Parse((-b).ToString())); } public static DataStorageElement operator /(DataStorageElement a, BigInteger b) { throw new InvalidOperationException("DataStorage[Key] / BigInterger is not supported, due to loss of precision when using integer division"); } public static implicit operator DataStorageElement(BigInteger bi) { return new DataStorageElement(OperationType.Replace, JToken.Parse(bi.ToString())); } public static implicit operator BigInteger(DataStorageElement e) { return RetrieveAndReturnBigIntegerValue<BigInteger>(e); } public static implicit operator BigInteger?(DataStorageElement e) { return RetrieveAndReturnBigIntegerValue<BigInteger?>(e); } private static T RetrieveAndReturnBigIntegerValue<T>(DataStorageElement e) { if (e.cachedValue != null) { if (!BigInteger.TryParse(((object)e.cachedValue).ToString(), out var result)) { return default(T); } return (T)Convert.ChangeType(result, IsNullable<T>() ? Nullable.GetUnderlyingType(typeof(T)) : typeof(T)); } BigInteger result2; BigInteger? bigInteger = (BigInteger.TryParse(((object)e.Context.GetData(e.Context.Key)).ToString(), out result2) ? new BigInteger?(result2) : null); if (!bigInteger.HasValue && !IsNullable<T>()) { bigInteger = Activator.CreateInstance<BigInteger>(); } foreach (OperationSpecification operation in e.Operations) { if (operation.OperationType == OperationType.Floor || operation.OperationType == OperationType.Ceil) { continue; } if (!BigInteger.TryParse(((object)operation.Value).ToString(), NumberStyles.AllowLeadingSign, null, out var result3)) { throw new InvalidOperationException($"DataStorage[Key] cannot be converted to BigInterger as its value its not an integer number, value: {operation.Value}"); } switch (operation.OperationType) { case OperationType.Replace: bigInteger = result3; break; case OperationType.Add: bigInteger += result3; break; case OperationType.Mul: bigInteger *= result3; break; case OperationType.Mod: bigInteger %= result3; break; case OperationType.Pow: bigInteger = BigInteger.Pow(bigInteger.Value, (int)operation.Value); break; case OperationType.Max: { BigInteger value = result3; BigInteger? bigInteger2 = bigInteger; if (value > bigInteger2) { bigInteger = result3; } break; } case OperationType.Min: { BigInteger value = result3; BigInteger? bigInteger2 = bigInteger; if (value < bigInteger2) { bigInteger = result3; } break; } case OperationType.Xor: bigInteger ^= result3; break; case OperationType.Or: bigInteger |= result3; break; case OperationType.And: bigInteger &= result3; break; case OperationType.LeftShift: bigInteger <<= (int)operation.Value; break; case OperationType.RightShift: bigInteger >>= (int)operation.Value; break; } } e.cachedValue = JToken.Parse(bigInteger.ToString()); if (!bigInteger.HasValue) { return default(T); } return (T)Convert.ChangeType(bigInteger.Value, IsNullable<T>() ? Nullable.GetUnderlyingType(typeof(T)) : typeof(T)); } public void Initialize(JToken value) { Context.Initialize(Context.Key, value); } public void Initialize(IEnumerable value) { Context.Initialize(Context.Key, (JToken)(object)JArray.FromObject((object)value)); } public Task<T> GetAsync<T>() { return GetAsync().ContinueWith((Task<JToken> r) => r.Result.ToObject<T>()); } public Task<JToken> GetAsync() { return Context.GetAsync(Context.Key); } private static T RetrieveAndReturnArrayValue<T>(DataStorageElement e) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Invalid comparison between Unknown and I4 //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Invalid comparison between Unknown and I4 //IL_00d7: Unknown result type (might be due to invalid IL or missing references) if (e.cachedValue != null) { return ((JToken)(JArray)e.cachedValue).ToObject<T>(); } JArray val = (JArray)(((object)e.Context.GetData(e.Context.Key).ToObject<JArray>()) ?? ((object)new JArray())); foreach (OperationSpecification operation in e.Operations) { switch (operation.OperationType) { case OperationType.Add: if ((int)operation.Value.Type != 2) { throw new InvalidOperationException($"Cannot perform operation {OperationType.Add} on Array value, with a non Array value: {operation.Value}"); } ((JContainer)val).Merge((object)operation.Value); break; case OperationType.Replace: if ((int)operation.Value.Type != 2) { throw new InvalidOperationException($"Cannot replace Array value, with a non Array value: {operation.Value}"); } val = (JArray)(((object)operation.Value.ToObject<JArray>()) ?? ((object)new JArray())); break; default: throw new InvalidOperationException($"Cannot perform operation {operation.OperationType} on Array value"); } } e.cachedValue = (JToken)(object)val; return ((JToken)val).ToObject<T>(); } private static string RetrieveAndReturnStringValue(DataStorageElement e) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Invalid comparison between Unknown and I4 if (e.cachedValue != null) { return (string)e.cachedValue; } JToken val = e.Context.GetData(e.Context.Key); string text = (((int)val.Type == 10) ? null : ((object)val).ToString()); foreach (OperationSpecification operation in e.Operations) { switch (operation.OperationType) { case OperationType.Add: text += (string)operation.Value; break; case OperationType.Mul: if ((int)operation.Value.Type != 6) { throw new InvalidOperationException($"Cannot perform operation {OperationType.Mul} on string value, with a non interger value: {operation.Value}"); } text = string.Concat(Enumerable.Repeat(text, (int)operation.Value)); break; case OperationType.Replace: text = (string)operation.Value; break; default: throw new InvalidOperationException($"Cannot perform operation {operation.OperationType} on string value"); } } if (text == null) { e.cachedValue = (JToken)(object)JValue.CreateNull(); } else { e.cachedValue = JToken.op_Implicit(text); } return (string)e.cachedValue; } private static T RetrieveAndReturnBoolValue<T>(DataStorageElement e) { if (e.cachedValue != null) { return e.cachedValue.ToObject<T>(); } bool? flag = e.Context.GetData(e.Context.Key).ToObject<bool?>() ?? ((bool?)Activator.CreateInstance(typeof(T))); foreach (OperationSpecification operation in e.Operations) { if (operation.OperationType == OperationType.Replace) { flag = (bool?)operation.Value; continue; } throw new InvalidOperationException($"Cannot perform operation {operation.OperationType} on boolean value"); } e.cachedValue = JToken.op_Implicit(flag); if (!flag.HasValue) { return default(T); } return (T)Convert.ChangeType(flag.Value, IsNullable<T>() ? Nullable.GetUnderlyingType(typeof(T)) : typeof(T)); } private static T RetrieveAndReturnDecimalValue<T>(DataStorageElement e) { if (e.cachedValue != null) { return e.cachedValue.ToObject<T>(); } decimal? num = e.Context.GetData(e.Context.Key).ToObject<decimal?>(); if (!num.HasValue && !IsNullable<T>()) { num = Activator.CreateInstance<decimal>(); } foreach (OperationSpecification operation in e.Operations) { switch (operation.OperationType) { case OperationType.Replace: num = (decimal)operation.Value; break; case OperationType.Add: num += (decimal?)(decimal)operation.Value; break; case OperationType.Mul: num *= (decimal?)(decimal)operation.Value; break; case OperationType.Mod: num %= (decimal?)(decimal)operation.Value; break; case OperationType.Pow: num = (decimal)Math.Pow((double)num.Value, (double)operation.Value); break; case OperationType.Max: num = Math.Max(num.Value, (decimal)operation.Value); break; case OperationType.Min: num = Math.Min(num.Value, (decimal)operation.Value); break; case OperationType.Xor: num = (long)num.Value ^ (long)operation.Value; break; case OperationType.Or: num = (long)num.Value | (long)operation.Value; break; case OperationType.And: num = (long)num.Value & (long)operation.Value; break; case OperationType.LeftShift: num = (long)num.Value << (int)operation.Value; break; case OperationType.RightShift: num = (long)num.Value >> (int)operation.Value; break; case OperationType.Floor: num = Math.Floor(num.Value); break; case OperationType.Ceil: num = Math.Ceiling(num.Value); break; } } e.cachedValue = JToken.op_Implicit(num); if (!num.HasValue) { return default(T); } return (T)Convert.ChangeType(num.Value, IsNullable<T>() ? Nullable.GetUnderlyingType(typeof(T)) : typeof(T)); } private static bool IsNullable<T>() { if (typeof(T).IsGenericType) { return typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>).GetGenericTypeDefinition(); } return false; } public T To<T>() { if (Operations.Count != 0) { throw new InvalidOperationException("DataStorageElement.To<T>() cannot be used together with other operations on the DataStorageElement"); } return Context.GetData(Context.Key).ToObject<T>(); } public override string ToString() { return (Context?.ToString() ?? "(null)") + ", (" + ListOperations() + ")"; } private string ListOperations() { if (Operations != null) { return string.Join(", ", Operations.Select((OperationSpecification o) => o.ToString()).ToArray()); } return "none"; } } internal class DataStorageElementContext { internal string Key { get; set; } internal Action<string, DataStorageHelper.DataStorageUpdatedHandler> AddHandler { get; set; } internal Action<string, DataStorageHelper.DataStorageUpdatedHandler> RemoveHandler { get; set; } internal Func<string, JToken> GetData { get; set; } internal Action<string, JToken> Initialize { get; set; } internal Func<string, Task<JToken>> GetAsync { get; set; } public override string ToString() { return "Key: " + Key; } } public class GameData { [JsonProperty("location_name_to_id")] public Dictionary<string, long> LocationLookup { get; set; } = new Dictionary<string, long>(); [JsonProperty("item_name_to_id")] public Dictionary<string, long> ItemLookup { get; set; } = new Dictionary<string, long>(); [Obsolete("use Checksum instead")] [JsonProperty("version")] public int Version { get; set; } [JsonProperty("checksum")] public string Checksum { get; set; } } public class Hint { [JsonProperty("receiving_player")] public int ReceivingPlayer { get; set; } [JsonProperty("finding_player")] public int FindingPlayer { get; set; } [JsonProperty("item")] public long ItemId { get; set; } [JsonProperty("location")] public long LocationId { get; set; } [JsonProperty("item_flags")] public ItemFlags ItemFlags { get; set; } [JsonProperty("found")] public bool Found { get; set; } [JsonProperty("entrance")] public string Entrance { get; set; } } public class ItemInfo { private readonly IItemInfoResolver itemInfoResolver; public long ItemId { get; } public long LocationId { get; } public PlayerInfo Player { get; } public ItemFlags Flags { get; } public string ItemName => itemInfoResolver.GetItemName(ItemId, ItemGame); public string ItemDisplayName => ItemName ?? $"Item: {ItemId}"; public string LocationName => itemInfoResolver.GetLocationName(LocationId, LocationGame); public string LocationDisplayName => LocationName ?? $"Location: {LocationId}"; public string ItemGame { get; } public string LocationGame { get; } public ItemInfo(NetworkItem item, string receiverGame, string senderGame, IItemInfoResolver itemInfoResolver, PlayerInfo player) { this.itemInfoResolver = itemInfoResolver; ItemGame = receiverGame; LocationGame = senderGame; ItemId = item.Item; LocationId = item.Location; Flags = item.Flags; Player = player; } public SerializableItemInfo ToSerializable() { return new SerializableItemInfo { IsScout = (GetType() == typeof(ScoutedItemInfo)), ItemId = ItemId, LocationId = LocationId, PlayerSlot = Player, Player = Player, Flags = Flags, ItemGame = ItemGame, ItemName = ItemName, LocationGame = LocationGame, LocationName = LocationName }; } } public class ScoutedItemInfo : ItemInfo { public new PlayerInfo Player => base.Player; public ScoutedItemInfo(NetworkItem item, string receiverGame, string senderGame, IItemInfoResolver itemInfoResolver, PlayerInfo player) : base(item, receiverGame, senderGame, itemInfoResolver, player) { } } public class JsonMessagePart { [JsonProperty("type")] [JsonConverter(typeof(StringEnumConverter), new object[] { typeof(SnakeCaseNamingStrategy) })] public JsonMessagePartType? Type { get; set; } [JsonProperty("color")] [JsonConverter(typeof(StringEnumConverter), new object[] { typeof(SnakeCaseNamingStrategy) })] public JsonMessagePartColor? Color { get; set; } [JsonProperty("text")] public string Text { get; set; } [JsonProperty("player")] public int? Player { get; set; } [JsonProperty("flags")] public ItemFlags? Flags { get; set; } } public struct NetworkItem { [JsonProperty("item")] public long Item { get; set; } [JsonProperty("location")] public long Location { get; set; } [JsonProperty("player")] public int Player { get; set; } [JsonProperty("flags")] public ItemFlags Flags { get; set; } } public struct NetworkPlayer { [JsonProperty("team")] public int Team { get; set; } [JsonProperty("slot")] public int Slot { get; set; } [JsonProperty("alias")] public string Alias { get; set; } [JsonProperty("name")] public string Name { get; set; } } public struct NetworkSlot { [JsonProperty("name")] public string Name { get; set; } [JsonProperty("game")] public string Game { get; set; } [JsonProperty("type")] public SlotType Type { get; set; } [JsonProperty("group_members")] public int[] GroupMembers { get; set; } } public class NetworkVersion { [JsonProperty("major")] public int Major { get; set; } [JsonProperty("minor")] public int Minor { get; set; } [JsonProperty("build")] public int Build { get; set; } [JsonProperty("class")] public string Class => "Version"; public NetworkVersion() { } public NetworkVersion(int major, int minor, int build) { Major = major; Minor = minor; Build = build; } public NetworkVersion(Version version) { Major = version.Major; Minor = version.Minor; Build = version.Build; } public Version ToVersion() { return new Version(Major, Minor, Build); } } public class OperationSpecification { [JsonProperty("operation")] [JsonConverter(typeof(StringEnumConverter), new object[] { typeof(SnakeCaseNamingStrategy) })] public OperationType OperationType; [JsonProperty("value")] public JToken Value { get; set; } public override string ToString() { return $"{OperationType}: {Value}"; } } public static class Operation { public static OperationSpecification Min(int i) { return new OperationSpecification { OperationType = OperationType.Min, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Min(long i) { return new OperationSpecification { OperationType = OperationType.Min, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Min(float i) { return new OperationSpecification { OperationType = OperationType.Min, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Min(double i) { return new OperationSpecification { OperationType = OperationType.Min, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Min(decimal i) { return new OperationSpecification { OperationType = OperationType.Min, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Min(JToken i) { return new OperationSpecification { OperationType = OperationType.Min, Value = i }; } public static OperationSpecification Min(BigInteger i) { return new OperationSpecification { OperationType = OperationType.Min, Value = JToken.Parse(i.ToString()) }; } public static OperationSpecification Max(int i) { return new OperationSpecification { OperationType = OperationType.Max, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Max(long i) { return new OperationSpecification { OperationType = OperationType.Max, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Max(float i) { return new OperationSpecification { OperationType = OperationType.Max, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Max(double i) { return new OperationSpecification { OperationType = OperationType.Max, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Max(decimal i) { return new OperationSpecification { OperationType = OperationType.Max, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Max(JToken i) { return new OperationSpecification { OperationType = OperationType.Max, Value = i }; } public static OperationSpecification Max(BigInteger i) { return new OperationSpecification { OperationType = OperationType.Max, Value = JToken.Parse(i.ToString()) }; } public static OperationSpecification Remove(JToken value) { return new OperationSpecification { OperationType = OperationType.Remove, Value = value }; } public static OperationSpecification Pop(int value) { return new OperationSpecification { OperationType = OperationType.Pop, Value = JToken.op_Implicit(value) }; } public static OperationSpecification Pop(JToken value) { return new OperationSpecification { OperationType = OperationType.Pop, Value = value }; } public static OperationSpecification Update(IDictionary dictionary) { return new OperationSpecification { OperationType = OperationType.Update, Value = (JToken)(object)JObject.FromObject((object)dictionary) }; } public static OperationSpecification Floor() { return new OperationSpecification { OperationType = OperationType.Floor, Value = null }; } public static OperationSpecification Ceiling() { return new OperationSpecification { OperationType = OperationType.Ceil, Value = null }; } } public static class Bitwise { public static OperationSpecification Xor(long i) { return new OperationSpecification { OperationType = OperationType.Xor, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Xor(BigInteger i) { return new OperationSpecification { OperationType = OperationType.Xor, Value = JToken.Parse(i.ToString()) }; } public static OperationSpecification Or(long i) { return new OperationSpecification { OperationType = OperationType.Or, Value = JToken.op_Implicit(i) }; } public static OperationSpecification Or(BigInteger i) { return new OperationSpecification { OperationType = OperationType.Or, Value = JToken.Parse(i.ToString()) }; } public static OperationSpecification And(long i) { return new OperationSpecification { OperationType = OperationType.And, Value = JToken.op_Implicit(i) }; } public static OperationSpecification And(BigInteger i) { return new OperationSpecification { OperationType = OperationType.And, Value = JToken.Parse(i.ToString()) }; } public static OperationSpecification LeftShift(long i) { return new OperationSpecification { OperationType = OperationType.LeftShift, Value = JToken.op_Implicit(i) }; } public static OperationSpecification RightShift(long i) { return new OperationSpecification { OperationType = OperationType.RightShift, Value = JToken.op_Implicit(i) }; } } public class Callback { internal DataStorageHelper.DataStorageUpdatedHandler Method { get; set; } private Callback() { } public static Callback Add(DataStorageHelper.DataStorageUpdatedHandler callback) { return new Callback { Method = callback }; } } public class AdditionalArgument { internal string Key { get; set; } internal JToken Value { get; set; } private AdditionalArgument() { } public static AdditionalArgument Add(string name, JToken value) { return new AdditionalArgument { Key = name, Value = value }; } } public class MinimalSerializableItemInfo { public long ItemId { get; set; } public long LocationId { get; set; } public int PlayerSlot { get; set; } public ItemFlags Flags { get; set; } public string ItemGame { get; set; } public string LocationGame { get; set; } } public class SerializableItemInfo : MinimalSerializableItemInfo { public bool IsScout { get; set; } public PlayerInfo Player { get; set; } public string ItemName { get; set; } public string LocationName { get; set; } [JsonIgnore] public string ItemDisplayName => ItemName ?? $"Item: {base.ItemId}"; [JsonIgnore] public string LocationDisplayName => LocationName ?? $"Location: {base.LocationId}"; public string ToJson(bool full = false) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown MinimalSerializableItemInfo minimalSerializableItemInfo = this; if (!full) { minimalSerializableItemInfo = new MinimalSerializableItemInfo { ItemId = base.ItemId, LocationId = base.LocationId, PlayerSlot = base.PlayerSlot, Flags = base.Flags }; if (IsScout) { minimalSerializableItemInfo.ItemGame = base.ItemGame; } else { minimalSerializableItemInfo.LocationGame = base.LocationGame; } } JsonSerializerSettings val = new JsonSerializerSettings { NullValueHandling = (NullValueHandling)1, Formatting = (Formatting)0 }; return JsonConvert.SerializeObject((object)minimalSerializableItemInfo, val); } public static SerializableItemInfo FromJson(string json, IArchipelagoSession session = null) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown ItemInfoStreamingContext additional = ((session != null) ? new ItemInfoStreamingContext { Items = session.Items, Locations = session.Locations, PlayerHelper = session.Players, ConnectionInfo = session.ConnectionInfo } : null); JsonSerializerSettings val = new JsonSerializerSettings { Context = new StreamingContext(StreamingContextStates.Other, additional) }; return JsonConvert.DeserializeObject<SerializableItemInfo>(json, val); } [OnDeserialized] internal void OnDeserializedMethod(StreamingContext streamingContext) { if (base.ItemGame == null && base.LocationGame != null) { IsScout = false; } else if (base.ItemGame != null && base.LocationGame == null) { IsScout = true; } if (streamingContext.Context is ItemInfoStreamingContext itemInfoStreamingContext) { if (IsScout && base.LocationGame == null) { base.LocationGame = itemInfoStreamingContext.ConnectionInfo.Game; } else if (!IsScout && base.ItemGame == null) { base.ItemGame = itemInfoStreamingContext.ConnectionInfo.Game; } if (ItemName == null) { ItemName = itemInfoStreamingContext.Items.GetItemName(base.ItemId, base.ItemGame); } if (LocationName == null) { LocationName = itemInfoStreamingContext.Locations.GetLocationNameFromId(base.LocationId, base.LocationGame); } if (Player == null) { Player = itemInfoStreamingContext.PlayerHelper.GetPlayerInfo(base.PlayerSlot); } } } } internal class ItemInfoStreamingContext { public IReceivedItemsHelper Items { get; set; } public ILocationCheckHelper Locations { get; set; } public IPlayerHelper PlayerHelper { get; set; } public IConnectionInfoProvider ConnectionInfo { get; set; } } } namespace Archipelago.MultiClient.Net.MessageLog.Parts { public class EntranceMessagePart : MessagePart { internal EntranceMessagePart(JsonMessagePart messagePart) : base(MessagePartType.Entrance, messagePart, Color.Blue) { base.Text = messagePart.Text; } } public class ItemMessagePart : MessagePart { public ItemFlags Flags { get; } public long ItemId { get; } public int Player { get; } internal ItemMessagePart(IPlayerHelper players, IItemInfoResolver items, JsonMessagePart part) : base(MessagePartType.Item, part) { Flags = part.Flags.GetValueOrDefault(); base.Color = GetColor(Flags); Player = part.Player.GetValueOrDefault(); string game = (players.GetPlayerInfo(Player) ?? new PlayerInfo()).Game; JsonMessagePartType? type = part.Type; if (type.HasValue) { switch (type.GetValueOrDefault()) { case JsonMessagePartType.ItemId: ItemId = long.Parse(part.Text); base.Text = items.GetItemName(ItemId, game) ?? $"Item: {ItemId}"; break; case JsonMessagePartType.ItemName: ItemId = 0L; base.Text = part.Text; break; } } } private static Color GetColor(ItemFlags flags) { if (HasFlag(flags, ItemFlags.Advancement)) { return Color.Plum; } if (HasFlag(flags, ItemFlags.NeverExclude)) { return Color.SlateBlue; } if (HasFlag(flags, ItemFlags.Trap)) { return Color.Salmon; } return Color.Cyan; } private static bool HasFlag(ItemFlags flags, ItemFlags flag) { return flags.HasFlag(flag); } } public class LocationMessagePart : MessagePart { public long LocationId { get; } public int Player { get; } internal LocationMessagePart(IPlayerHelper players, IItemInfoResolver itemInfoResolver, JsonMessagePart part) : base(MessagePartType.Location, part, Color.Green) { Player = part.Player.GetValueOrDefault(); string game = (players.GetPlayerInfo(Player) ?? new PlayerInfo()).Game; JsonMessagePartType? type = part.Type; if (type.HasValue) { switch (type.GetValueOrDefault()) { case JsonMessagePartType.LocationId: LocationId = long.Parse(part.Text); base.Text = itemInfoResolver.GetLocationName(LocationId, game) ?? $"Location: {LocationId}"; break; case JsonMessagePartType.LocationName: LocationId = itemInfoResolver.GetLocationId(part.Text, game); base.Text = part.Text; break; } } } } public class MessagePart { public string Text { get; internal set; } public MessagePartType Type { get; internal set; } public Color Color { get; internal set; } public bool IsBackgroundColor { get; internal set; } internal MessagePart(MessagePartType type, JsonMessagePart messagePart, Color? color = null) { Type = type; Text = messagePart.Text; if (color.HasValue) { Color = color.Value; } else if (messagePart.Color.HasValue) { Color = GetColor(messagePart.Color.Value); IsBackgroundColor = messagePart.Color.Value >= JsonMessagePartColor.BlackBg; } else { Color = Color.White; } } private static Color GetColor(JsonMessagePartColor color) { switch (color) { case JsonMessagePartColor.Red: case JsonMessagePartColor.RedBg: return Color.Red; case JsonMessagePartColor.Green: case JsonMessagePartColor.GreenBg: return Color.Green; case JsonMessagePartColor.Yellow: case JsonMessagePartColor.YellowBg: return Color.Yellow; case JsonMessagePartColor.Blue: case JsonMessagePartColor.BlueBg: return Color.Blue; case JsonMessagePartColor.Magenta: case JsonMessagePartColor.MagentaBg: return Color.Magenta; case JsonMessagePartColor.Cyan: case JsonMessagePartColor.CyanBg: return Color.Cyan; case JsonMessagePartColor.Black: case JsonMessagePartColor.BlackBg: return Color.Black; case JsonMessagePartColor.White: case JsonMessagePartColor.WhiteBg: return Color.White; default: return Color.White; } } public override string ToString() { return Text; } } public enum MessagePartType { Text, Player, Item, Location, Entrance } public class PlayerMessagePart : MessagePart { public bool IsActivePlayer { get; } public int SlotId { get; } internal PlayerMessagePart(IPlayerHelper players, IConnectionInfoProvider connectionInfo, JsonMessagePart part) : base(MessagePartType.Player, part) { switch (part.Type) { case JsonMessagePartType.PlayerId: SlotId = int.Parse(part.Text); IsActivePlayer = SlotId == connectionInfo.Slot; base.Text = players.GetPlayerAlias(SlotId) ?? $"Player {SlotId}"; break; case JsonMessagePartType.PlayerName: SlotId = 0; IsActivePlayer = false; base.Text = part.Text; break; } base.Color = GetColor(IsActivePlayer); } private static Color GetColor(bool isActivePlayer) { if (isActivePlayer) { return Color.Magenta; } return Color.Yellow; } } } namespace Archipelago.MultiClient.Net.MessageLog.Messages { public class AdminCommandResultLogMessage : LogMessage { internal AdminCommandResultLogMessage(MessagePart[] parts) : base(parts) { } } public class ChatLogMessage : PlayerSpecificLogMessage { public string Message { get; } internal ChatLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot, string message) : base(parts, players, connectionInfo, team, slot) { Message = message; } } public class CollectLogMessage : PlayerSpecificLogMessage { internal CollectLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot) : base(parts, players, connectionInfo, team, slot) { } } public class CommandResultLogMessage : LogMessage { internal CommandResultLogMessage(MessagePart[] parts) : base(parts) { } } public class CountdownLogMessage : LogMessage { public int RemainingSeconds { get; } internal CountdownLogMessage(MessagePart[] parts, int remainingSeconds) : base(parts) { RemainingSeconds = remainingSeconds; } } public class GoalLogMessage : PlayerSpecificLogMessage { internal GoalLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot) : base(parts, players, connectionInfo, team, slot) { } } public class HintItemSendLogMessage : ItemSendLogMessage { public bool IsFound { get; } internal HintItemSendLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int receiver, int sender, NetworkItem item, bool found, IItemInfoResolver itemInfoResolver) : base(parts, players, connectionInfo, receiver, sender, item, itemInfoResolver) { IsFound = found; } } public class ItemCheatLogMessage : ItemSendLogMessage { internal ItemCheatLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot, NetworkItem item, IItemInfoResolver itemInfoResolver) : base(parts, players, connectionInfo, slot, 0, item, team, itemInfoResolver) { } } public class ItemSendLogMessage : LogMessage { public PlayerInfo Receiver { get; } public PlayerInfo Sender { get; } public bool IsReceiverTheActivePlayer { get; } public bool IsSenderTheActivePlayer { get; } public bool IsRelatedToActivePlayer { get; } public ItemInfo Item { get; } internal ItemSendLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int receiver, int sender, NetworkItem item, IItemInfoResolver itemInfoResolver) : this(parts, players, connectionInfo, receiver, sender, item, connectionInfo.Team, itemInfoResolver) { } internal ItemSendLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int receiver, int sender, NetworkItem item, int team, IItemInfoResolver itemInfoResolver) : base(parts) { IsReceiverTheActivePlayer = connectionInfo.Team == team && connectionInfo.Slot == receiver; IsSenderTheActivePlayer = connectionInfo.Team == team && connectionInfo.Slot == sender; Receiver = players.GetPlayerInfo(team, receiver) ?? new PlayerInfo(); Sender = players.GetPlayerInfo(team, sender) ?? new PlayerInfo(); PlayerInfo player = players.GetPlayerInfo(team, item.Player) ?? new PlayerInfo(); IsRelatedToActivePlayer = IsReceiverTheActivePlayer || IsSenderTheActivePlayer || Receiver.IsSharingGroupWith(connectionInfo.Team, connectionInfo.Slot) || Sender.IsSharingGroupWith(connectionInfo.Team, connectionInfo.Slot); Item = new ItemInfo(item, Receiver.Game, Sender.Game, itemInfoResolver, player); } } public class JoinLogMessage : PlayerSpecificLogMessage { public string[] Tags { get; } internal JoinLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot, string[] tags) : base(parts, players, connectionInfo, team, slot) { Tags = tags; } } public class LeaveLogMessage : PlayerSpecificLogMessage { internal LeaveLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot) : base(parts, players, connectionInfo, team, slot) { } } public class LogMessage { public MessagePart[] Parts { get; } internal LogMessage(MessagePart[] parts) { Parts = parts; } public override string ToString() { if (Parts.Length == 1) { return Parts[0].Text; } StringBuilder stringBuilder = new StringBuilder(); MessagePart[] parts = Parts; foreach (MessagePart messagePart in parts) { stringBuilder.Append(messagePart.Text); } return stringBuilder.ToString(); } } public abstract class PlayerSpecificLogMessage : LogMessage { public PlayerInfo Player { get; } public bool IsActivePlayer { get; } public bool IsRelatedToActivePlayer { get; } internal PlayerSpecificLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot) : base(parts) { ReadOnlyDictionary<int, ReadOnlyCollection<PlayerInfo>> players2 = players.Players; IsActivePlayer = connectionInfo.Team == team && connectionInfo.Slot == slot; Player = ((players2.Count > team && players2[team].Count > slot) ? players2[team][slot] : new PlayerInfo()); IsRelatedToActivePlayer = IsActivePlayer || Player.IsSharingGroupWith(connectionInfo.Team, connectionInfo.Slot); } } public class ReleaseLogMessage : PlayerSpecificLogMessage { internal ReleaseLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot) : base(parts, players, connectionInfo, team, slot) { } } public class ServerChatLogMessage : LogMessage { public string Message { get; } internal ServerChatLogMessage(MessagePart[] parts, string message) : base(parts) { Message = message; } } public class TagsChangedLogMessage : PlayerSpecificLogMessage { public string[] Tags { get; } internal TagsChangedLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot, string[] tags) : base(parts, players, connectionInfo, team, slot) { Tags = tags; } } public class TutorialLogMessage : LogMessage { internal TutorialLogMessage(MessagePart[] parts) : base(parts) { } } } namespace Archipelago.MultiClient.Net.Helpers { public class ArchipelagoSocketHelper : BaseArchipelagoSocketHelper<ClientWebSocket>, IArchipelagoSocketHelper { public Uri Uri { get; } internal ArchipelagoSocketHelper(Uri hostUri) : base(CreateWebSocket(), 1024) { Uri = hostUri; SecurityProtocolType securityProtocolType = SecurityProtocolType.Tls13; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | securityProtocolType; } private static ClientWebSocket CreateWebSocket() { return new ClientWebSocket(); } public async Task ConnectAsync() { await ConnectToProvidedUri(Uri); StartPolling(); } private async Task ConnectToProvidedUri(Uri uri) { if (uri.Scheme != "unspecified") { try { await Socket.ConnectAsync(uri, CancellationToken.None); return; } catch (Exception e) { OnError(e); throw; } } List<Exception> errors = new List<Exception>(0); try { await Socket.ConnectAsync(uri.AsWss(), CancellationToken.None); if (Socket.State == WebSocketState.Open) { return; } } catch (Exception item) { errors.Add(item); Socket = CreateWebSocket(); } try { await Socket.ConnectAsync(uri.AsWs(), CancellationToken.None); } catch (Exception item2) { errors.Add(item2); OnError(new AggregateException(errors)); throw; } } } public class BaseArchipelagoSocketHelper<T> where T : WebSocket { private static readonly ArchipelagoPacketConverter Converter = new ArchipelagoPacketConverter(); private readonly BlockingCollection<Tuple<ArchipelagoPacketBase, TaskCompletionSource<bool>>> sendQueue = new BlockingCollection<Tuple<ArchipelagoPacketBase, TaskCompletionSource<bool>>>(); internal T Socket; private readonly int bufferSize; public bool Connected { get { if (Socket.State != WebSocketState.Open) { return Socket.State == WebSocketState.CloseReceived; } return true; } } public event ArchipelagoSocketHelperDelagates.PacketReceivedHandler PacketReceived; public event ArchipelagoSocketHelperDelagates.PacketsSentHandler PacketsSent; public event ArchipelagoSocketHelperDelagates.ErrorReceivedHandler ErrorReceived; public event ArchipelagoSocketHelperDelagates.SocketClosedHandler SocketClosed; public event ArchipelagoSocketHelperDelagates.SocketOpenedHandler SocketOpened; internal BaseArchipelagoSocketHelper(T socket, int bufferSize = 1024) { Socket = socket; this.bufferSize = bufferSize; } internal void StartPolling() { if (this.SocketOpened != null) { this.SocketOpened(); } Task.Run((Func<Task?>)PollingLoop); Task.Run((Func<Task?>)SendLoop); } private async Task PollingLoop() { byte[] buffer = new byte[bufferSize]; while (Socket.State == WebSocketState.Open) { string message = null; try { message = await ReadMessageAsync(buffer); } catch (Exception e) { OnError(e); } OnMessageReceived(message); await Task.Delay(20); } } private async Task SendLoop() { while (Socket.State == WebSocketState.Open) { try { await HandleSendBuffer(); } catch (Exception e) { OnError(e); } await Task.Delay(20); } } private async Task<string> ReadMessageAsync(byte[] buffer) { using MemoryStream readStream = new MemoryStream(buffer.Length); WebSocketReceiveResult result; do { result = await Socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); if (result.MessageType == WebSocketMessageType.Close) { try { await Socket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); } catch { } OnSocketClosed(); } else { readStream.Write(buffer, 0, result.Count); } } while (!result.EndOfMessage); return Encoding.UTF8.GetString(readStream.ToArray()); } public async Task DisconnectAsync() { await Socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closure requested by client", CancellationToken.None); OnSocketClosed(); } public void SendPacket(ArchipelagoPacketBase packet) { SendMultiplePackets(new List<ArchipelagoPacketBase> { packet }); } public void SendMultiplePackets(List<ArchipelagoPacketBase> packets) { SendMultiplePackets(packets.ToArray()); } public void SendMultiplePackets(params ArchipelagoPacketBase[] packets) { SendMultiplePacketsAsync(packets).Wait(); } public Task SendPacketAsync(ArchipelagoPacketBase packet) { return SendMultiplePacketsAsync(new List<ArchipelagoPacketBase> { packet }); } public Task SendMultiplePacketsAsync(List<ArchipelagoPacketBase> packets) { return SendMultiplePacketsAsync(packets.ToArray()); } public Task SendMultiplePacketsAsync(params ArchipelagoPacketBase[] packets) { TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>(); foreach (ArchipelagoPacketBase item in packets) { sendQueue.Add(new Tuple<ArchipelagoPacketBase, TaskCompletionSource<bool>>(item, taskCompletionSource)); } return taskCompletionSource.Task; } private async Task HandleSendBuffer() { List<ArchipelagoPacketBase> list = new List<ArchipelagoPacketBase>(); List<TaskCompletionSource<bool>> tasks = new List<TaskCompletionSource<bool>>(); Tuple<ArchipelagoPacketBase, TaskCompletionSource<bool>> tuple = sendQueue.Take(); list.Add(tuple.Item1); tasks.Add(tuple.Item2); Tuple<ArchipelagoPacketBase, TaskCompletionSource<bool>> item; while (sendQueue.TryTake(out item)) { list.Add(item.Item1); tasks.Add(item.Item2); } if (!list.Any()) { return; } if (Socket.State != WebSocketState.Open) { throw new ArchipelagoSocketClosedException(); } ArchipelagoPacketBase[] packets = list.ToArray(); string s = JsonConvert.SerializeObject((object)packets); byte[] messageBuffer = Encoding.UTF8.GetBytes(s); int messagesCount = (int)Math.Ceiling((double)messageBuffer.Length / (double)bufferSize); for (int i = 0; i < messagesCount; i++) { int num = bufferSize * i; int num2 = bufferSize; bool endOfMessage = i + 1 == messagesCount; if (num2 * (i + 1) > messageBuffer.Length) { num2 = messageBuffer.Length - num; } await Socket.SendAsync(new ArraySegment<byte>(messageBuffer, num, num2), WebSocketMessageType.Text, endOfMessage, CancellationToken.None); } foreach (TaskCompletionSource<bool> item2 in tasks) { item2.TrySetResult(result: true); } OnPacketSend(packets); } private void OnPacketSend(ArchipelagoPacketBase[] packets) { try { if (this.PacketsSent != null) { this.PacketsSent(packets); } } catch (Exception e) { OnError(e); } } private void OnSocketClosed() { try { if (this.SocketClosed != null) { this.SocketClosed(""); } } catch (Exception e) { OnError(e); } } private void OnMessageReceived(string message) { try { if (string.IsNullOrEmpty(message) || this.PacketReceived == null) { return; } List<ArchipelagoPacketBase> list = null; try { list = JsonConvert.DeserializeObject<List<ArchipelagoPacketBase>>(message, (JsonConverter[])(object)new JsonConverter[1] { Converter }); } catch (Exception e) { OnError(e); } if (list == null) { return; } foreach (ArchipelagoPacketBase item in list) { this.PacketReceived(item); } } catch (Exception e2) { OnError(e2); } } protected void OnError(Exception e) { try { if (this.ErrorReceived != null) { this.ErrorReceived(e, e.Message); } } catch (Exception ex) { Console.Out.WriteLine("Error occured during reporting of errorOuter Errror: " + e.Message + " " + e.StackTrace + "Inner Errror: " + ex.Message + " " + ex.StackTrace); } } } public interface IConnectionInfoProvider { string Game { get; } int Team { get; } int Slot { get; } string[] Tags { get; } ItemsHandlingFlags ItemsHandlingFlags { get; } string Uuid { get; } void UpdateConnectionOptions(string[] tags); void UpdateConnectionOptions(ItemsHandlingFlags itemsHandlingFlags); void UpdateConnectionOptions(string[] tags, ItemsHandlingFlags itemsHandlingFlags); } public class ConnectionInfoHelper : IConnectionInfoProvider { private readonly IArchipelagoSocketHelper socket; public string Game { get; private set; } public int Team { get; private set; } public int Slot { get; private set; } public string[] Tags { get; internal set; } public ItemsHandlingFlags ItemsHandlingFlags { get; internal set; } public string Uuid { get; private set; } internal ConnectionInfoHelper(IArchipelagoSocketHelper socket) { this.socket = socket; Reset(); socket.PacketReceived += PacketReceived; } private void PacketReceived(ArchipelagoPacketBase packet) { if (!(packet is ConnectedPacket connectedPacket)) { if (packet is ConnectionRefusedPacket) { Reset(); } return; } Team = connectedPacket.Team; Slot = connectedPacket.Slot; if (connectedPacket.SlotInfo != null && connectedPacket.SlotInfo.ContainsKey(Slot)) { Game = connectedPacket.SlotInfo[Slot].Game; } } internal void SetConnectionParameters(string game, string[] tags, ItemsHandlingFlags itemsHandlingFlags, string uuid) { Game = game; Tags = tags ?? new string[0]; ItemsHandlingFlags = itemsHandlingFlags; Uuid = uuid ?? Guid.NewGuid().ToString(); } private void Reset() { Game = null; Team = -1; Slot = -1; Tags = new string[0]; ItemsHandlingFlags = ItemsHandlingFlags.NoItems; Uuid = null; } public void UpdateConnectionOptions(string[] tags) { UpdateConnectionOptions(tags, ItemsHandlingFlags); } public void UpdateConnectionOptions(ItemsHandlingFlags itemsHandlingFlags) { UpdateConnectionOptions(Tags, ItemsHandlingFlags); } public void UpdateConnectionOptions(string[] tags, ItemsHandlingFlags itemsHandlingFlags) { SetConnectionParameters(Game, tags, itemsHandlingFlags, Uuid); socket.SendPacket(new ConnectUpdatePacket { Tags = Tags, ItemsHandling = ItemsHandlingFlags }); } } public interface IDataStorageHelper : IDataStorageWrapper { DataStorageElement this[Scope scope, string key] { get; set; } DataStorageElement this[string key] { get; set; } } public class DataStorageHelper : IDataStorageHelper, IDataStorageWrapper { public delegate void DataStorageUpdatedHandler(JToken originalValue, JToken newValue, Dictionary<string, JToken> additionalArguments); private readonly Dictionary<string, DataStorageUpdatedHandler> onValueChangedEventHandlers = new Dictionary<string, DataStorageUpdatedHandler>(); private readonly Dictionary<Guid, DataStorageUpdatedHandler> operationSpecificCallbacks = new Dictionary<Guid, DataStorageUpdatedHandler>(); private readonly Dictionary<string, TaskCompletionSource<JToken>> asyncRetrievalTasks = new Dictionary<string, TaskCompletionSource<JToken>>(); private readonly IArchipelagoSocketHelper socket; private readonly IConnectionInfoProvider connectionInfoProvider; public DataStorageElement this[Scope scope, string key] { get { return this[AddScope(scope, key)]; } set { this[AddScope(scope, key)] = value; } } public DataStorageElement this[string key] { get { return new DataStorageElement(GetContextForKey(key)); } set { SetValue(key, value); } } internal DataStorageHelper(IArchipelagoSocketHelper socket, IConnectionInfoProvider connectionInfoProvider) { this.socket = socket; this.connectionInfoProvider = connectionInfoProvider; socket.PacketReceived += OnPacketReceived; } private void OnPacketReceived(ArchipelagoPacketBase packet) { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Invalid comparison between Unknown and I4 if (!(packet is RetrievedPacket retrievedPacket)) { if (packet is SetReplyPacket setReplyPacket) { if (setReplyPacket.AdditionalArguments != null && setReplyPacket.AdditionalArguments.ContainsKey("Reference") && (int)setReplyPacket.AdditionalArguments["Reference"].Type == 15 && operationSpecificCallbacks.TryGetValue((Guid)setReplyPacket.AdditionalArguments["Reference"], out var value)) { value(setReplyPacket.OriginalValue, setReplyPacket.Value, setReplyPacket.AdditionalArguments); operationSpecificCallbacks.Remove((Guid)setReplyPacket.AdditionalArguments["Reference"]); } if (onValueChangedEventHandlers.TryGetValue(setReplyPacket.Key, out var value2)) { value2(setReplyPacket.OriginalValue, setReplyPacket.Value, setReplyPacket.AdditionalArguments); } } return; } foreach (KeyValuePair<string, JToken> datum in retrievedPacket.Data) { if (asyncRetrievalTasks.TryGetValue(datum.Key, out var value3)) { value3.TrySetResult(datum.Value); asyncRetrievalTasks.Remove(datum.Key); } } } private Task<JToken> GetAsync(string key) { if (asyncRetrievalTasks.TryGetValue(key, out var value)) { return value.Task; } TaskCompletionSource<JToken> taskCompletionSource = new TaskCompletionSource<JToken>(); asyncRetrievalTasks[key] = taskCompletionSource; socket.SendPacketAsync(new GetPacket { Keys = new string[1] { key } }); return taskCompletionSource.Task; } private void Initialize(string key, JToken value) { socket.SendPacketAsync(new SetPacket { Key = key, DefaultValue = value, Operations = new OperationSpecification[1] { new OperationSpecification { OperationType = OperationType.Default } } }); } private JToken GetValue(string key) { Task<JToken> async = GetAsync(key); if (!async.Wait(TimeSpan.FromSeconds(2.0))) { throw new TimeoutException("Timed out retrieving data for key `" + key + "`. This may be due to an attempt to retrieve a value from the DataStorageHelper in a synchronous fashion from within a PacketReceived handler. When using the DataStorageHelper from within code which runs on the websocket thread then use the asynchronous getters. Ex: `DataStorageHelper[\"" + key + "\"].GetAsync().ContinueWith(x => {});`Be aware that DataStorageHelper calls tend to cause packet responses, so making a call from within a PacketReceived handler may cause an infinite loop."); } return async.Result; } private void SetValue(string key, DataStorageElement e) { if (key.StartsWith("_read_")) { throw new InvalidOperationException("DataStorage write operation on readonly key '" + key + "' is not allowed"); } if (e == null) { e = new DataStorageElement(OperationType.Replace, (JToken)(object)JValue.CreateNull()); } if (e.Context == null) { e.Context = GetContextForKey(key); } else if (e.Context.Key != key) { e.Operations.Insert(0, new OperationSpecification { OperationType = OperationType.Replace, Value = GetValue(e.Context.Key) }); } Dictionary<string, JToken> dictionary = e.AdditionalArguments ?? new Dictionary<string, JToken>(0); if (e.Callbacks != null) { Guid guid = Guid.NewGuid(); operationSpecificCallbacks[guid] = e.Callbacks; dictionary["Reference"] = JToken.FromObject((object)guid); socket.SendPacketAsync(new SetPacket { Key = key, Operations = e.Operations.ToArray(), WantReply = true, AdditionalArguments = dictionary }); } else { socket.SendPacketAsync(new SetPacket { Key = key, Operations = e.Operations.ToArray(), AdditionalArguments = dictionary }); } } private DataStorageElementContext GetContextForKey(string key) { return new DataStorageElementContext { Key = key, GetData = GetValue, GetAsync = GetAsync, Initialize = Initialize, AddHandler = AddHandler, RemoveHandler = RemoveHandler }; } private void AddHandler(string key, DataStorageUpdatedHandler handler) { if (onValueChangedEventHandlers.ContainsKey(key)) { Dictionary<string, DataStorageUpdatedHandler> dictionary = onValueChangedEventHandlers; dictionary[key] = (DataStorageUpdatedHandler)Delegate.Combine(dictionary[key], handler); } else { onValueChangedEventHandlers[key] = handler; } socket.SendPacketAsync(new SetNotifyPacket { Keys = new string[1] { key } }); } private void RemoveHandler(string key, DataStorageUpdatedHandler handler) { if (onValueChangedEventHandlers.ContainsKey(key)) { Dictionary<string, DataStorageUpdatedHandler> dictionary = onValueChangedEventHandlers; dictionary[key] = (DataStorageUpdatedHandler)Delegate.Remove(dictionary[key], handler); if (onValueChangedEventHandlers[key] == null) { onValueChangedEventHandlers.Remove(key); } } } private string AddScope(Scope scope, string key) { return scope switch { Scope.Global => key, Scope.Game => $"{scope}:{connectionInfoProvider.Game}:{key}", Scope.Team => $"{scope}:{connectionInfoProvider.Team}:{key}", Scope.Slot => $"{scope}:{connectionInfoProvider.Slot}:{key}", Scope.ReadOnly => "_read_" + key, _ => throw new ArgumentOutOfRangeException("scope", scope, "Invalid scope for key " + key), }; } private DataStorageElement GetHintsElement(int? slot = null, int? team = null) { return this[Scope.ReadOnly, $"hints_{team ?? connectionInfoProvider.Team}_{slot ?? connectionInfoProvider.Slot}"]; } private DataStorageElement GetSlotDataElement(int? slot = null) { return this[Scope.ReadOnly, $"slot_data_{slot ?? connectionInfoProvider.Slot}"]; } private DataStorageElement GetItemNameGroupsElement(string game = null) { return this[Scope.ReadOnly, "item_name_groups_" + (game ?? connectionInfoProvider.Game)]; } private DataStorageElement GetLocationNameGroupsElement(string game = null) { return this[Scope.ReadOnly, "location_name_groups_" + (game ?? connectionInfoProvider.Game)]; } private DataStorageElement GetClientStatusElement(int? slot = null, int? team = null) { return this[Scope.ReadOnly, $"client_status_{team ?? connectionInfoProvider.Team}_{slot ?? connectionInfoProvider.Slot}"]; } public Hint[] GetHints(int? slot = null, int? team = null) { return GetHintsElement(slot, team).To<Hint[]>(); } public Task<Hint[]> GetHintsAsync(int? slot = null, int? team = null) { return GetHintsElement(slot, team).GetAsync<Hint[]>(); } public void TrackHints(Action<Hint[]> onHintsUpdated, bool retrieveCurrentlyUnlockedHints = true, int? slot = null, int? team = null) { GetHintsElement(slot, team).OnValueChanged += delegate(JToken _, JToken newValue, Dictionary<string, JToken> x) { onHintsUpdated(newValue.ToObject<Hint[]>()); }; if (retrieveCurrentlyUnlockedHints) { GetHintsAsync(slot, team).ContinueWith(delegate(Task<Hint[]> t) { onHintsUpdated(t.Result); }); } } public Dictionary<string, object> GetSlotData(int? slot = null) { return GetSlotDataElement(slot).To<Dictionary<string, object>>(); } public Task<Dictionary<string, object>> GetSlotDataAsync(int? slot = null) { return GetSlotDataElement(slot).GetAsync<Dictionary<string, object>>(); } public Dictionary<string, string[]> GetItemNameGroups(string game = null) { return GetItemNameGroupsElement(game).To<Dictionary<string, string[]>>(); } public Task<Dictionary<string, string[]>> GetItemNameGroupsAsync(string game = null) { return GetItemNameGroupsElement(game).GetAsync<Dictionary<string, string[]>>(); } public Dictionary<string, string[]> GetLocationNameGroups(string game = null) { return GetLocationNameGroupsElement(game).To<Dictionary<string, string[]>>(); } public Task<Dictionary<string, string[]>> GetLocationNameGroupsAsync(string game = null) { return GetLocationNameGroupsElement(game).GetAsync<Dictionary<string, string[]>>(); } public ArchipelagoClientState GetClientStatus(int? slot = null, int? team = null) { return GetClientStatusElement(slot, team).To<ArchipelagoClientState?>().GetValueOrDefault(); } public Task<ArchipelagoClientState> GetClientStatusAsync(int? slot = null, int? team = null) { return GetClientStatusElement(slot, team).GetAsync<ArchipelagoClientState?>().ContinueWith((Task<ArchipelagoClientState?> r) => r.Result.GetValueOrDefault()); }