Decompiled source of PeaksOfArchipelago v1.7.1
PeaksOfArchipelago.dll
Decompiled a week 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.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Threading.Tasks; using Archipelago.MultiClient.Net; using Archipelago.MultiClient.Net.BounceFeatures.DeathLink; using Archipelago.MultiClient.Net.Enums; using Archipelago.MultiClient.Net.Helpers; using Archipelago.MultiClient.Net.MessageLog.Messages; using Archipelago.MultiClient.Net.MessageLog.Parts; using Archipelago.MultiClient.Net.Models; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using POKModManager; using PeaksOfArchipelago; using Rewired; using Steamworks; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("PeaksOfArchipelago")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.7.1.0")] [assembly: AssemblyInformationalVersion("1.7.1+23f497084d3ea430ef0e5a98eea83574e8b771da")] [assembly: AssemblyProduct("Peaks Of Archipelago")] [assembly: AssemblyTitle("PeaksOfArchipelago")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.7.1.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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; } } } internal class Traps : MonoBehaviour { private enum Trap { Birds, Night, Holds, Gravity, OneTime } private enum SingleTimeTrap { Ropes, Chalk, Coffee, Seeds } [CompilerGenerated] private sealed class <BirdsTrap>d__22 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Traps <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <BirdsTrap>d__22(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; if ((Object)(object)<>4__this.hunter != (Object)null && (Object)(object)<>4__this.crow != (Object)null) { <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; } UIHandler.instance.AddChatMessage("Something went wrong, please report this to the dev :) \n (you can keep playing)"); logger.LogInfo((object)"birds are null?"); break; case 1: <>1__state = -1; UIHandler.instance.Notify("You've awakened the birds's wrath"); logger.LogInfo((object)"activating birds"); ((Component)<>4__this.hunter).gameObject.SetActive(true); ((Component)<>4__this.crow).gameObject.SetActive(true); <>4__this.birdTrapRunning = true; <>4__this.hunter.InitiateBird(); <>4__this.crow.InitiateBird(); <>2__current = <>4__this.StartTimer("Birds!", 30f); <>1__state = 2; return true; case 2: <>1__state = -1; <>4__this.birdTrapRunning = false; logger.LogInfo((object)"deactivating birds"); ((Component)<>4__this.hunter).gameObject.SetActive(false); ((Component)<>4__this.crow).gameObject.SetActive(false); break; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <CrimpsTrap>d__23 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Traps <>4__this; private GameObject[] <array>5__1; private int <i>5__2; private int <i>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CrimpsTrap>d__23(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <array>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; <>4__this.holdsTrapRunning = true; <array>5__1 = GameObject.FindGameObjectsWithTag("Climbable"); UIHandler.instance.Notify("All the holds seem so small today"); <i>5__2 = 0; while (<i>5__2 < <array>5__1.Length) { if (((Object)<array>5__1[<i>5__2]).name != "ClimbableSloper_Normal" && ((Object)<array>5__1[<i>5__2]).name != "ClimbableSloper_Slippery" && ((Object)<array>5__1[<i>5__2]).name != "ClimbableSloper_Easy" && ((Object)<array>5__1[<i>5__2]).name != "ClimbableSloper_Rain" && ((Object)<array>5__1[<i>5__2]).name != "ClimbableSloper_Rain_Brick") { <array>5__1[<i>5__2].tag = "ClimbableMicroHold"; } <i>5__2++; } <>2__current = <>4__this.StartTimer("Oops, all crimps!", 30f); <>1__state = 2; return true; case 2: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 3; return true; case 3: <>1__state = -1; <i>5__3 = 0; while (<i>5__3 < <array>5__1.Length) { if (((Object)<array>5__1[<i>5__3]).name != "ClimbableSloper_Normal" && ((Object)<array>5__1[<i>5__3]).name != "ClimbableSloper_Slippery" && ((Object)<array>5__1[<i>5__3]).name != "ClimbableSloper_Easy" && ((Object)<array>5__1[<i>5__3]).name != "ClimbableSloper_Rain" && ((Object)<array>5__1[<i>5__3]).name != "ClimbableSloper_Rain_Brick") { <array>5__1[<i>5__3].tag = "Climbable"; } <i>5__3++; } <>4__this.holdsTrapRunning = false; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <GravityTrap>d__26 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Traps <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <GravityTrap>d__26(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; UIHandler.instance.Notify("How much porridge did ye have for breakfast?"); <>4__this.gravityTrapRunning = true; Physics.gravity = new Vector3(0f, -10.692901f, 0f); <>2__current = <>4__this.StartTimer("Feeling Heavy", 30f); <>1__state = 2; return true; case 2: <>1__state = -1; Physics.gravity = new Vector3(0f, -9.81f, 0f); <>4__this.gravityTrapRunning = false; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <NightTrap>d__21 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Traps <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <NightTrap>d__21(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; UIHandler.instance.Notify("Sudden Eclipse"); logger.LogInfo((object)"Starting Night Trap"); GameManager.control.alps_statue_sundown_InUse = true; Object.FindObjectOfType<EnterPeakScene>().PublicSetSundown(); GameManager.control.alps_statue_sundown_InUse = false; if (playerData.items.lamp) { <>4__this.oilLamp.lampObj.SetActive(true); ((MonoBehaviour)<>4__this.oilLamp).StartCoroutine("StartOilLamp", (object)false); } <>4__this.nightTrapRunning = true; <>2__current = <>4__this.StartTimer("Eclipse", 60f); <>1__state = 2; return true; case 2: <>1__state = -1; <>4__this.nightTrapRunning = false; if (playerData.items.lamp) { <>4__this.oilLamp.lampObj.SetActive(false); } Object.FindObjectOfType<EnterPeakScene>().PublicSetSundown(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <PitchesTrap>d__25 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Traps <>4__this; private GameObject[] <array>5__1; private int <j>5__2; private int <j>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PitchesTrap>d__25(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <array>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; UIHandler.instance.Notify("You seem to tire quicker than usual"); <>4__this.holdsTrapRunning = true; <array>5__1 = GameObject.FindGameObjectsWithTag("Climbable"); <j>5__2 = 0; while (<j>5__2 < <array>5__1.Length) { <array>5__1[<j>5__2].tag = "ClimbablePitch"; <j>5__2++; } <>2__current = <>4__this.StartTimer("Oops, all pitches!", 30f); <>1__state = 2; return true; case 2: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 3; return true; case 3: <>1__state = -1; <j>5__3 = 0; while (<j>5__3 < <array>5__1.Length) { <array>5__1[<j>5__3].tag = "Climbable"; <j>5__3++; } <>4__this.holdsTrapRunning = false; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <SlopersTrap>d__24 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Traps <>4__this; private GameObject[] <array>5__1; private string[] <array2>5__2; private int <j>5__3; private int <j>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SlopersTrap>d__24(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <array>5__1 = null; <array2>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; UIHandler.instance.Notify("Your hands feel greasy"); <>4__this.holdsTrapRunning = true; <array>5__1 = GameObject.FindGameObjectsWithTag("Climbable"); <array2>5__2 = new string[<array>5__1.Length]; <j>5__3 = 0; while (<j>5__3 < <array>5__1.Length) { <array2>5__2[<j>5__3] = ((Object)<array>5__1[<j>5__3]).name; ((Object)<array>5__1[<j>5__3]).name = "ClimbableSloper_Easy"; <j>5__3++; } <>2__current = <>4__this.StartTimer("Oops, all slopers!", 15f); <>1__state = 2; return true; case 2: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 3; return true; case 3: <>1__state = -1; <j>5__4 = 0; while (<j>5__4 < <array>5__1.Length) { ((Object)<array>5__1[<j>5__4]).name = <array2>5__2[<j>5__4]; <j>5__4++; } <>4__this.holdsTrapRunning = false; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <StartTimer>d__27 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string name; public float duration; public Traps <>4__this; private GameObject <p>5__1; private Text <t>5__2; private GameObject <c>5__3; private Image <i>5__4; private float <timer>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <StartTimer>d__27(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <p>5__1 = null; <t>5__2 = null; <c>5__3 = null; <i>5__4 = null; <>1__state = -2; } private bool MoveNext() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; <>4__this.trapList.SetActive(true); <p>5__1 = UIHandler.CreatePanel(name + " clock", new Color(0f, 0f, 0f, 0.8f), <>4__this.trapList.transform, Vector2.zero, 0.5f, 0.5f, -1f, -1f, (TextAnchor)4, vertical: false); <t>5__2 = UIHandler.CreateTextElem("name", 32, <p>5__1.transform, (TextAnchor)4); <t>5__2.text = name; <c>5__3 = UIHandler.CreateClock("clock", Color.white, <p>5__1.transform, Vector2.zero, 36f); <i>5__4 = <c>5__3.GetComponent<Image>(); <>2__current = null; <>1__state = 2; return true; case 2: <>1__state = -1; <timer>5__5 = 0f; break; case 3: <>1__state = -1; break; } if (<timer>5__5 <= 1f) { <timer>5__5 += Time.deltaTime / duration; <i>5__4.fillAmount = 1f - <timer>5__5; <>2__current = null; <>1__state = 3; return true; } Object.Destroy((Object)(object)<p>5__1); if (<>4__this.trapList.transform.childCount == 0) { <>4__this.trapList.SetActive(false); } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private Bird hunter = null; private Bird crow = null; public static ManualLogSource logger; private GameObject trapList; public static Traps instance; public static PlayerData playerData; private bool birdTrapRunning = false; private bool nightTrapRunning; private bool holdsTrapRunning; private bool gravityTrapRunning; private OilLamp oilLamp; public void Awake() { oilLamp = Object.FindObjectOfType<OilLamp>(); if (!Object.op_Implicit((Object)(object)oilLamp)) { logger.LogError((object)"Didn't find Oil Lamp!"); } hunter = GameObject.Find("SeaBird_Hunter").GetComponent<Bird>(); if (!Object.op_Implicit((Object)(object)hunter)) { logger.LogError((object)"Didn't find Hunter!"); } crow = GameObject.Find("CrowBird_Hunter").GetComponent<Bird>(); if (!Object.op_Implicit((Object)(object)crow)) { logger.LogError((object)"Didn't find Crow!"); } } public void Start() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) Color color = new Color(0f, 0f, 0f, 0.8f); Canvas obj = Object.FindObjectOfType<Canvas>(); trapList = UIHandler.CreatePanel("trap list", color, (obj != null) ? ((Component)obj).transform : null, new Vector2(10f, 10f), 0f, 0f, -1f, -1f, (TextAnchor)4); trapList.SetActive(false); } public void StartTrap() { List<Trap> list = new List<Trap>(new <>z__ReadOnlySingleElementList<Trap>(Trap.OneTime)); if (!birdTrapRunning) { list.Add(Trap.Birds); } if (!nightTrapRunning) { list.Add(Trap.Night); } if (!holdsTrapRunning) { list.Add(Trap.Holds); } if (!gravityTrapRunning) { list.Add(Trap.Gravity); } switch (list[Random.Range(0, list.Count)]) { case Trap.Birds: StartBirdTrap(); break; case Trap.Night: StartNightTrap(); break; case Trap.Holds: StartHoldsTrap(); break; case Trap.Gravity: StartGravityTrap(); break; case Trap.OneTime: StartOneTimeTrap(); break; } } public void StartGravityTrap() { ((MonoBehaviour)this).StartCoroutine(GravityTrap()); } public void StartBirdTrap() { ((MonoBehaviour)this).StartCoroutine(BirdsTrap()); } public void StartNightTrap() { ((MonoBehaviour)this).StartCoroutine(NightTrap()); } public void StartOneTimeTrap() { List<SingleTimeTrap> list = new List<SingleTimeTrap>(); if (playerData.items.rope) { list.Add(SingleTimeTrap.Ropes); } if (playerData.items.coffee) { list.Add(SingleTimeTrap.Coffee); } if (playerData.items.chalkbag) { list.AddRange(new <>z__ReadOnlyArray<SingleTimeTrap>(new SingleTimeTrap[2] { SingleTimeTrap.Chalk, SingleTimeTrap.Seeds })); } if (list.Count == 0) { UIHandler.instance.Notify("Nothing Happened..."); return; } SingleTimeTrap singleTimeTrap = list[Random.Range(0, list.Count)]; switch ((SingleTimeTrap)Random.Range(0, 4)) { case SingleTimeTrap.Ropes: { RopeAnchor val3 = Object.FindObjectOfType<RopeAnchor>(); if (!((Object)(object)val3 == (Object)null) && val3.anchorsInBackpack > 0) { val3.anchorsInBackpack--; ((MonoBehaviour)val3).StartCoroutine("RopesLeftTooltip"); UIHandler.instance.Notify("You dropped a rope"); } break; } case SingleTimeTrap.Coffee: { CoffeeDrink val2 = Object.FindObjectOfType<CoffeeDrink>(); if (!((Object)(object)val2 == (Object)null) && val2.coffeeSipsLeft > 0) { val2.coffeeSipsLeft--; ((MonoBehaviour)val2).StartCoroutine("CoffeeLeftToolTip"); UIHandler.instance.Notify("Your coffee spilled"); } break; } case SingleTimeTrap.Chalk: { ChalkBag val4 = Object.FindObjectOfType<ChalkBag>(); if (!((Object)(object)val4 == (Object)null) && val4.chalkBagUsesLeft > 0) { val4.chalkBagUsesLeft--; ((MonoBehaviour)val4).StartCoroutine("ChalkLeftToolTip", (object)false); UIHandler.instance.Notify("You found a hole in your chalk bag"); } break; } case SingleTimeTrap.Seeds: { ChalkBag val = Object.FindObjectOfType<ChalkBag>(); if (!((Object)(object)val == (Object)null) && val.birdseedsUsesLeft > 0) { val.birdseedsUsesLeft--; ((MonoBehaviour)val).StartCoroutine("ChalkLeftToolTip", (object)true); UIHandler.instance.Notify("You realise you forgot a portion of bird seeds"); } break; } } } public void StartHoldsTrap() { string[] array = new string[3] { "CrimpsTrap", "SlopersTrap", "PitchesTrap" }; ((MonoBehaviour)this).StartCoroutine(array[Random.Range(0, array.Length)]); } [IteratorStateMachine(typeof(<NightTrap>d__21))] private IEnumerator NightTrap() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <NightTrap>d__21(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<BirdsTrap>d__22))] private IEnumerator BirdsTrap() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <BirdsTrap>d__22(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<CrimpsTrap>d__23))] private IEnumerator CrimpsTrap() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <CrimpsTrap>d__23(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<SlopersTrap>d__24))] private IEnumerator SlopersTrap() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SlopersTrap>d__24(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<PitchesTrap>d__25))] private IEnumerator PitchesTrap() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PitchesTrap>d__25(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<GravityTrap>d__26))] private IEnumerator GravityTrap() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <GravityTrap>d__26(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<StartTimer>d__27))] private IEnumerator StartTimer(string name, float duration) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <StartTimer>d__27(0) { <>4__this = this, name = name, duration = duration }; } } internal class UIHandler : MonoBehaviour { [CompilerGenerated] private sealed class <FadeAndShowText>d__16 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public CanvasGroup cg; public float fadeInTime; public float stayTime; public float fadeOutTime; public UIHandler <>4__this; private float <timer>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <FadeAndShowText>d__16(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; cg.alpha = 0f; <timer>5__1 = 0f; goto IL_00c6; case 2: <>1__state = -1; goto IL_00c6; case 3: <>1__state = -1; <timer>5__1 = 0f; goto IL_0160; case 4: <>1__state = -1; goto IL_0160; case 5: { <>1__state = -1; Object.Destroy((Object)(object)((Component)cg).gameObject); return false; } IL_0160: if (<timer>5__1 < 1f) { <timer>5__1 += Time.deltaTime * fadeOutTime; cg.alpha = 1f - <timer>5__1; <>2__current = null; <>1__state = 4; return true; } cg.alpha = 0f; <>2__current = null; <>1__state = 5; return true; IL_00c6: if (<timer>5__1 < 1f) { <timer>5__1 += Time.deltaTime / fadeInTime; cg.alpha = <timer>5__1; <>2__current = null; <>1__state = 2; return true; } cg.alpha = 1f; <>2__current = (object)new WaitForSeconds(stayTime); <>1__state = 3; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public static UIHandler instance; public static ManualLogSource logger; public static Font poyFont; private Transform chatBoxTransform; private Transform unlockNotifsTransform; public GameObject canvas; private Queue<string> messages = new Queue<string>(); private void Awake() { poyFont = Object.FindObjectOfType<Text>().font; logger.LogInfo((object)poyFont); Canvas obj = Object.FindObjectOfType<Canvas>(); canvas = ((obj != null) ? ((Component)obj).gameObject : null); if ((Object)(object)canvas == (Object)null) { logger.LogError((object)"Couldn't find Canvas"); ((Behaviour)this).enabled = false; } instance = this; } private void Start() { CreateUI(); } private void Update() { if (messages.Count != 0) { CreateChatMessage(messages.Dequeue()); } } private void OnDestroy() { Transform obj = chatBoxTransform; Object.Destroy((Object)(object)((obj != null) ? ((Component)obj).gameObject : null)); Transform obj2 = unlockNotifsTransform; Object.Destroy((Object)(object)((obj2 != null) ? ((Component)obj2).gameObject : null)); } private void CreateUI() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) chatBoxTransform = CreatePanel("chatbox", new Color(0f, 0f, 0f, 0f), canvas.transform, new Vector2(-12.5f, 0f), 1f, 0.75f, 1f, 0f, (TextAnchor)8).transform; ((Component)chatBoxTransform).GetComponent<HorizontalOrVerticalLayoutGroup>().childForceExpandWidth = false; ((Component)chatBoxTransform).GetComponent<HorizontalOrVerticalLayoutGroup>().childForceExpandHeight = false; unlockNotifsTransform = CreatePanel("unlock notifications", new Color(0f, 0f, 0f, 0f), canvas.transform, Vector2.zero, 0.5f, 0.75f, 0.5f, 0.5f, (TextAnchor)4).transform; ((Component)unlockNotifsTransform).GetComponent<HorizontalOrVerticalLayoutGroup>().childForceExpandWidth = false; ((Component)unlockNotifsTransform).GetComponent<HorizontalOrVerticalLayoutGroup>().childForceExpandHeight = false; logger.LogInfo((object)"created UI"); } public void AddChatMessage(string text) { messages.Enqueue(text); } private void CreateChatMessage(string text) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) GameObject val = CreatePanel("chatmessagepanel", new Color(0f, 0f, 0f, 0.8f), chatBoxTransform, new Vector2(0f, 0f), 0f, 1f, 1f, 0f, (TextAnchor)8); CanvasGroup cg = val.AddComponent<CanvasGroup>(); Text val2 = CreateTextElem("chatmessageText", 20, val.transform, (TextAnchor)8); val2.text = text; ((MonoBehaviour)this).StartCoroutine(FadeAndShowText(cg, 0.5f, 4f, 0.5f)); } public void Notify(string text, float fadeInTime = 0.5f, float stayTime = 2f, float fadeOutTime = 0.5f) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) GameObject val = CreatePanel("textmoment", new Color(0f, 0f, 0f, 0.8f), unlockNotifsTransform, Vector2.zero, 0.5f, 0.5f, -1f, -1f, (TextAnchor)4); CanvasGroup cg = val.AddComponent<CanvasGroup>(); Text val2 = CreateTextElem("Textmomento", 32, val.transform, (TextAnchor)4); val2.text = text; ((MonoBehaviour)this).StartCoroutine(FadeAndShowText(cg, fadeInTime, stayTime, fadeOutTime)); } public void ShowTextAtPosition(string text, Vector2 offset, float fadeInTime = 0.5f, float stayTime = 2f, float fadeOutTime = 0.5f) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) GameObject val = CreatePanel("textmoment", new Color(0f, 0f, 0f, 0.8f), canvas.transform, offset, 0.5f, 0.75f, -1f, -1f, (TextAnchor)4); CanvasGroup cg = val.AddComponent<CanvasGroup>(); Text val2 = CreateTextElem("Textmomento", 32, val.transform, (TextAnchor)4); val2.text = text; ((MonoBehaviour)this).StartCoroutine(FadeAndShowText(cg, fadeInTime, stayTime, fadeOutTime)); } [IteratorStateMachine(typeof(<FadeAndShowText>d__16))] private IEnumerator FadeAndShowText(CanvasGroup cg, float fadeInTime, float stayTime, float fadeOutTime) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <FadeAndShowText>d__16(0) { <>4__this = this, cg = cg, fadeInTime = fadeInTime, stayTime = stayTime, fadeOutTime = fadeOutTime }; } public static GameObject CreatePanel(string name, Color color, Transform parent, Vector2 position, float anchorx = 0.5f, float anchory = 0.5f, float pivotx = -1f, float pivoty = -1f, TextAnchor alignment = 4, bool vertical = true) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)parent == (Object)null) { Canvas obj = Object.FindObjectOfType<Canvas>(); parent = ((obj != null) ? ((Component)obj).transform : null); } GameObject val = new GameObject(name); val.transform.SetParent(parent, false); Image val2 = val.AddComponent<Image>(); ((Graphic)val2).color = color; RectTransform val3 = val.GetComponent<RectTransform>() ?? val.AddComponent<RectTransform>(); Vector2 val4 = default(Vector2); ((Vector2)(ref val4))..ctor(anchorx, anchory); Vector2 pivot = (Vector2)((pivotx == -1f) ? val4 : new Vector2(pivotx, pivoty)); val3.anchorMax = val4; val3.anchorMin = val4; val3.anchoredPosition = position; val3.pivot = pivot; HorizontalOrVerticalLayoutGroup val5 = (HorizontalOrVerticalLayoutGroup)(vertical ? ((object)val.AddComponent<VerticalLayoutGroup>()) : ((object)val.AddComponent<HorizontalLayoutGroup>())); ((LayoutGroup)val5).childAlignment = alignment; val5.spacing = 25f; ((LayoutGroup)val5).padding.bottom = 30; ((LayoutGroup)val5).padding.right = 10; ((LayoutGroup)val5).padding.left = 10; ((LayoutGroup)val5).padding.top = 10; ContentSizeFitter val6 = val.AddComponent<ContentSizeFitter>(); val6.horizontalFit = (FitMode)2; val6.verticalFit = (FitMode)2; return val; } public static GameObject CreateClock(string name, Color color, Transform parent, Vector2 position, float size, float anchorx = 0.5f, float anchory = 0.5f, float pivotx = -1f, float pivoty = -1f) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); Image val2 = val.AddComponent<Image>(); ((Graphic)val2).color = color; val2.sprite = GenerateCircleSprite(Mathf.RoundToInt(size)); val2.type = (Type)3; val2.fillMethod = (FillMethod)4; val2.fillOrigin = 2; RectTransform val3 = val.GetComponent<RectTransform>() ?? val.AddComponent<RectTransform>(); Vector2 val4 = default(Vector2); ((Vector2)(ref val4))..ctor(anchorx, anchory); Vector2 pivot = (Vector2)((pivotx == -1f) ? val4 : new Vector2(pivotx, pivoty)); val3.anchorMax = val4; val3.anchorMin = val4; val3.pivot = pivot; val3.anchoredPosition = position; val3.sizeDelta = Vector2.one * size; return val; } public static Text CreateTextElem(string name, int fontSize, Transform parent, TextAnchor alignment = 4) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0062: 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) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); Text val2 = val.AddComponent<Text>(); if ((Object)(object)poyFont != (Object)null) { val2.font = poyFont; } else { logger.LogError((object)"No font found :("); val2.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); } val2.alignment = alignment; val2.fontSize = fontSize; ((Graphic)val2).color = Color.white; val2.lineSpacing = 3f; val2.supportRichText = true; RectTransform val3 = val.GetComponent<RectTransform>() ?? val.AddComponent<RectTransform>(); ContentSizeFitter val4 = val.AddComponent<ContentSizeFitter>(); val4.horizontalFit = (FitMode)2; val4.verticalFit = (FitMode)2; return val2; } private static Sprite GenerateCircleSprite(int size) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(size, size); Color[] array = (Color[])(object)new Color[size * size]; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor((float)(size / 2), (float)(size / 2)); float num = (float)size / 2f; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { float num2 = Vector2.Distance(new Vector2((float)j, (float)i), val2); array[i * size + j] = (Color)((num2 <= num) ? Color.white : new Color(0f, 0f, 0f, 0f)); } } val.SetPixels(array); val.Apply(); Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(0f, 0f, (float)size, (float)size); return Sprite.Create(val, val3, new Vector2(0.5f, 0.5f)); } } namespace Archipelago.MultiClient.Net { [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] internal sealed class DataStoragePropertyAttribute : Attribute { public string? SessionVariable { get; } public Scope Scope { get; } public string Key { get; } public DataStoragePropertyAttribute(string sessionVariable, Scope scope, string key) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) SessionVariable = sessionVariable; Scope = scope; Key = key; } public DataStoragePropertyAttribute(string sessionVariable, string key) : this(sessionVariable, (Scope)0, key) { } } } namespace PeaksOfArchipelago { public static class ModInfo { public const string MOD_GUID = "PeaksOfArchipelago"; public const string MOD_NAME = "Peaks Of Archipelago"; public const string MOD_DESC = "An Archipelago Implementation for Peaks Of Yore!"; public const string MOD_VERSION = "1.7.1"; } [BepInPlugin("PeaksOfArchipelago", "Peaks Of Archipelago", "1.7.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class PeaksOfArchipelago : BaseUnityPlugin { internal static ManualLogSource Logger; private void Awake() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"Plugin PeaksOfArchipelago is loaded!"); Harmony val = new Harmony("PeaksOfArchipelago_Paths"); MethodInfo methodInfo = AccessTools.PropertyGetter(AccessTools.TypeByName("POKModManager.Paths"), "GameFolder"); MethodInfo method = typeof(Patch_Paths).GetMethod("Prefix", BindingFlags.Static | BindingFlags.Public); val.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); new POKManager(true); } private void Start() { GameObject obj = GameObject.Find("Options"); object poyFont; if (obj == null) { poyFont = null; } else { Text componentInChildren = obj.GetComponentInChildren<Text>(); poyFont = ((componentInChildren != null) ? componentInChildren.font : null); } UIHandler.poyFont = (Font)poyFont; POKManager.RegisterMod((ModClass)(object)new PeaksOfArchipelagoMod(Logger), "Peaks Of Archipelago", "1.7.1", "An Archipelago Implementation for Peaks Of Yore!", true); } } public class Patch_Paths { public static bool Prefix(ref string __result) { __result = Directory.GetParent(Paths.BepInExRootPath).ToString(); return false; } } public class PeaksOfArchipelagoMod : ModClass { [HarmonyPatch(typeof(StamperPeakSummit), "StampJournal")] public class PeakSummitedPatch { private static void Prefix(StamperPeakSummit __instance) { Peaks peakFromCollectable = Utils.GetPeakFromCollectable(__instance); session.NotifyCollection(Utils.PeakToId(peakFromCollectable)); session.CompletePeakCheck(peakFromCollectable); if (GameObject.FindGameObjectWithTag("Player").GetComponent<RopeAnchor>().ropesPlacedDuringMap == 0 && peakFromCollectable >= Peaks.WalkersPillar) { session.NotifyCollection(Utils.FSPeakToId(peakFromCollectable)); session.CompleteFSPeakCheck(peakFromCollectable); } } } [HarmonyPatch(typeof(ArtefactOnPeak), "PickUpItem")] public class ArtefactOnPeakPatch { private static void Postfix(ArtefactOnPeak __instance) { Artefacts artefactFromCollectable = Utils.GetArtefactFromCollectable(__instance); session.NotifyCollection(Utils.ArtefactToId(artefactFromCollectable)); session.CompleteArtefactCheck(artefactFromCollectable); } } [HarmonyPatch(typeof(RopeCollectable), "PickUpRope")] public class RopeCollectablePatch { [CompilerGenerated] private sealed class <MyWrapper>d__2 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public IEnumerator original; public RopeCollectable __instance; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <MyWrapper>d__2(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; goto IL_0050; case 1: <>1__state = -1; goto IL_0050; case 2: { <>1__state = -1; return false; } IL_0050: if (original.MoveNext()) { <>2__current = original.Current; <>1__state = 1; return true; } UnityUtils.UndoRopeProgress(__instance); <>2__current = null; <>1__state = 2; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static void Prefix(RopeCollectable __instance) { Ropes ropeFromCollectable = Utils.GetRopeFromCollectable(__instance); session.NotifyCollection(Utils.RopeToId(ropeFromCollectable)); session.CompleteRopeCheck(ropeFromCollectable); } private static void Postfix(ref IEnumerator __result, RopeCollectable __instance) { __result = MyWrapper(__result, __instance); } [IteratorStateMachine(typeof(<MyWrapper>d__2))] private static IEnumerator MyWrapper(IEnumerator original, RopeCollectable __instance) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <MyWrapper>d__2(0) { original = original, __instance = __instance }; } } [HarmonyPatch(typeof(BirdSeedCollectable), "PickUpBirdSeed")] public class BirdSeedCollectablePatch { [CompilerGenerated] private sealed class <MyWrapper>d__2 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public IEnumerator original; public RopeCollectable __instance; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <MyWrapper>d__2(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; goto IL_0050; case 1: <>1__state = -1; goto IL_0050; case 2: { <>1__state = -1; return false; } IL_0050: if (original.MoveNext()) { <>2__current = original.Current; <>1__state = 1; return true; } <>2__current = null; <>1__state = 2; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static void Prefix(BirdSeedCollectable __instance) { BirdSeeds seedFromCollectable = Utils.GetSeedFromCollectable(__instance); session.NotifyCollection(Utils.BirdSeedToId(seedFromCollectable)); session.CompleteSeedCheck(seedFromCollectable); GameManager control = GameManager.control; control.extraBirdSeedUses--; } private static void Postfix(ref IEnumerator __result, RopeCollectable __instance) { __result = MyWrapper(__result, __instance); } [IteratorStateMachine(typeof(<MyWrapper>d__2))] private static IEnumerator MyWrapper(IEnumerator original, RopeCollectable __instance) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <MyWrapper>d__2(0) { original = original, __instance = __instance }; } } [HarmonyPatch(typeof(TimeAttack), "SetBestTime")] public class SetBestTimePatch { public static void Prefix(TimeAttack __instance) { if (!__instance.summitStamper.isCategory4) { Peaks peakFromCollectable = Utils.GetPeakFromCollectable(__instance.summitStamper); if (__instance.timer < timeAttackDefaultData.times[(int)peakFromCollectable]) { session.NotifyCollection((long)peakFromCollectable + 8000L); session.CompleteTimePBCheck(peakFromCollectable); } if (__instance.holdsMade < timeAttackDefaultData.holds[(int)peakFromCollectable]) { session.NotifyCollection((long)peakFromCollectable + 10000L); session.CompleteHoldsPBCheck(peakFromCollectable); } if (__instance.ropesUsed <= timeAttackDefaultData.ropes[(int)peakFromCollectable]) { session.NotifyCollection((long)peakFromCollectable + 9000L); session.CompleteRopesPBCheck(peakFromCollectable); } } } } [HarmonyPatch(typeof(TimeAttackSetter), "SetDefaults")] public class SetDefaultTimes { public static void Postfix(TimeAttackSetter __instance) { if (timeAttackDefaultData.holds == null) { float[] category1_defaultTimes = __instance.category1_defaultTimes; float[] category2_defaultTimes = __instance.category2_defaultTimes; float[] category3_defaultTimes = __instance.category3_defaultTimes; int num = 0; float[] array = new float[category1_defaultTimes.Length + category2_defaultTimes.Length + category3_defaultTimes.Length]; float[] array2 = category1_defaultTimes; foreach (float num2 in array2) { array[num] = num2; num++; } float[] array3 = category2_defaultTimes; foreach (float num2 in array3) { array[num] = num2; num++; } float[] array4 = category3_defaultTimes; foreach (float num2 in array4) { array[num] = num2; num++; } timeAttackDefaultData.times = array; int[] category1_defaultHolds = __instance.category1_defaultHolds; int[] category2_defaultHolds = __instance.category2_defaultHolds; int[] category3_defaultHolds = __instance.category3_defaultHolds; int num3 = 0; int[] array5 = new int[category1_defaultHolds.Length + category2_defaultHolds.Length + category3_defaultHolds.Length]; int[] array6 = category1_defaultHolds; foreach (int num4 in array6) { array5[num3] = num4; num3++; } int[] array7 = category2_defaultHolds; foreach (int num4 in array7) { array5[num3] = num4; num3++; } int[] array8 = category3_defaultHolds; foreach (int num4 in array8) { array5[num3] = num4; num3++; } timeAttackDefaultData.holds = array5; int[] category1_defaultRopes = __instance.category1_defaultRopes; int[] category2_defaultRopes = __instance.category2_defaultRopes; int[] category3_defaultRopes = __instance.category3_defaultRopes; int num5 = 0; int[] array9 = new int[category1_defaultRopes.Length + category2_defaultRopes.Length + category3_defaultRopes.Length]; int[] array10 = category1_defaultRopes; foreach (int num4 in array10) { array9[num5] = num4; num5++; } int[] array11 = category2_defaultRopes; foreach (int num4 in array11) { array9[num5] = num4; num5++; } int[] array12 = category3_defaultRopes; foreach (int num4 in array12) { array9[num5] = num4; num5++; } timeAttackDefaultData.ropes = array9; } } } [HarmonyPatch(typeof(FallingEvent), "FellToDeath")] public class FellToDeathPatch { private static void Postfix() { session.HandleDeath(); } } [HarmonyPatch(typeof(ResetPosition), "FadeToBlack")] public class ResetPositionPatch { private static void Prefix(ResetPosition __instance) { if (!__instance.isSea) { session.HandleDeath(); } } } [HarmonyPatch(typeof(ArtefactLoaderCabin), "LoadArtefacts")] public class ArtefactLoaderPatch { private static CheckList<Artefacts> savestate = new CheckList<Artefacts>(); public static void Prefix(ArtefactLoaderCabin __instance) { foreach (Artefacts value in Enum.GetValues(typeof(Artefacts))) { savestate.SetCheck(value, UnityUtils.GetGameManagerArtefactCollected(value)); UnityUtils.SetGameManagerArtefactCollected(value, session.playerData.items.artefacts.IsChecked(value)); if (session.playerData.items.artefacts.IsChecked(value)) { UnityUtils.SetGameManagerArtefactDirty(value, value: false); } } } public static void Postfix() { foreach (Artefacts value in Enum.GetValues(typeof(Artefacts))) { UnityUtils.SetGameManagerArtefactCollected(value, savestate.IsChecked(value)); if (UnityUtils.GetGameManagerArtefactCollected(value) != savestate.IsChecked(value)) { logger.LogWarning((object)$"Error: {value} should be {savestate.IsChecked(value)} but is {!savestate.IsChecked(value)}!"); } } GameManager.control.Save(); } } [HarmonyPatch(typeof(NPCEvents), "CheckProgress")] public class CheckProgressPatch { private static bool usingPipe; public static void Prefix(NPCEvents __instance) { usingPipe = GameManager.control.isUsingPipe; ItemEventsPatch.isCustomEvent = false; session.CheckWin(); session.UpdateReceivedItems(); if (session.uncollectedItems.Count != 0 && !__instance.runningEvent && session.currentScene != "TitleScreen") { logger.LogInfo((object)"starting custom event"); ItemEventsPatch.isCustomEvent = true; __instance.eventName = "AllArtefacts"; __instance.runningEvent = true; ((MonoBehaviour)__instance.npcParcelDeliverySystem).StartCoroutine("FadeScreenAndStartUnpackEvent"); } else if (session.finished && !session.seenFinishedCutScene) { ItemEventsPatch.isFinishEvent = true; session.seenFinishedCutScene = true; __instance.eventName = "CompleteGame_Base"; ((MonoBehaviour)__instance).StartCoroutine("GlowDoorEvent"); } } public static void Postfix(NPCEvents __instance) { session.SetFundamentalsBookActive(session.playerData.items.books.IsChecked(Books.Fundamentals)); GameManager.control.monocular = session.playerData.items.monocular; if (!GameManager.control.monocular) { ((MonoBehaviour)__instance).StopCoroutine("MissedMonocularTooltip"); } if (__instance.runningEvent) { switch (__instance.eventName) { case "Rope": case "RopesUpgrade": case "ArtefactMap": case "Pocketwatch": case "Crampons": case "CramponsUpgrade": case "Chalkbag": case "TimeAttack_Event1": case "Category_2": case "Category_3": case "Category_4": case "Phonograph": __instance.runningEvent = false; logger.LogInfo((object)("Blocking event: " + __instance.eventName)); ((MonoBehaviour)__instance).StopCoroutine("GlowDoorEvent"); break; case "AllArtefacts": if (!ItemEventsPatch.isCustomEvent) { __instance.runningEvent = false; logger.LogInfo((object)("Blocking event: " + __instance.eventName)); ((MonoBehaviour)__instance).StopCoroutine("GlowDoorEvent"); } break; } } if (session.playerData.items.pipe) { GameManager.control.smokingpipe = true; GameManager.control.isUsingPipe = usingPipe; __instance.cabinPipe.SetActive(true); } } } [HarmonyPatch(typeof(NPCSystem), "GivePlayerMonocular")] public class GivePlayerMonocularPatch { public static void Postfix() { GameManager.control.monocular = session.playerData.items.monocular; GameManager.control.Save(); } } [HarmonyPatch(typeof(NPCSystem), "GivePlayerCoffee")] public class GivePlayerCoffeePatch { public static void Postfix() { GameManager.control.coffee = session.playerData.items.coffee; GameManager.control.Save(); } } [HarmonyPatch(typeof(NPCSystem), "GivePlayerRope")] public class GivePlayerRopePatch { public static void Postfix(NPCSystem __instance) { Ropes rope = (Ropes)(-1); if (__instance.isStHaelga) { rope = Ropes.StHaelga; } if (__instance.isGreatGaol) { rope = Ropes.GreatGaol; } GameManager control = GameManager.control; control.ropesCollected--; RopeAnchor component = GameObject.FindGameObjectWithTag("Player").GetComponent<RopeAnchor>(); component.anchorsInBackpack--; session.NotifyCollection(Utils.RopeToId(rope)); session.CompleteRopeCheck(rope); } } [HarmonyPatch(typeof(NPC_Climber), "GivePlayerRope")] public class ClimberGivePlayerRopePatch { public static void Postfix(NPC_Climber __instance) { Ropes rope = (Ropes)(-1); if (__instance.isWaltersCrag) { rope = Ropes.WaltersCrag; } if (__instance.isWalkersPillar) { rope = Ropes.WalkersPillar; } GameManager control = GameManager.control; control.ropesCollected--; RopeAnchor component = GameObject.FindGameObjectWithTag("Player").GetComponent<RopeAnchor>(); component.anchorsInBackpack--; session.NotifyCollection(Utils.RopeToId(rope)); session.CompleteRopeCheck(rope); } } [HarmonyPatch(typeof(NPCEvents), "ItemEvents")] public class ItemEventsPatch { [CompilerGenerated] private sealed class <MyWrapper>d__8 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public IEnumerator original; public NPCEvents __instance; private List<SimpleItemInfo> <items>5__1; private List<SimpleItemInfo>.Enumerator <>s__2; private SimpleItemInfo <item>5__3; private RopeCabinDescription[] <>s__4; private int <>s__5; private RopeCabinDescription <ropeCabinDescription>5__6; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <MyWrapper>d__8(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <items>5__1 = null; <item>5__3 = default(SimpleItemInfo); <>s__4 = null; <ropeCabinDescription>5__6 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; goto IL_0053; case 1: <>1__state = -1; goto IL_0053; case 2: { <>1__state = -1; return false; } IL_0053: if (original.MoveNext()) { <>2__current = original.Current; <>1__state = 1; return true; } if (isCustomEvent) { isCustomEvent = false; GameManager.control.allArtefactsUnlocked = hasAllArtefacts; GameManager control = GameManager.control; control.ropesCollected -= 5; GameManager control2 = GameManager.control; control2.extraCoffeeUses -= 999999999; GameManager control3 = GameManager.control; control3.extraChalkUses -= 999999999; textElement.text = tempText; session.UpdateReceivedItems(); <items>5__1 = session.uncollectedItems; session.uncollectedItems = new List<SimpleItemInfo>(); <>s__2 = <items>5__1.GetEnumerator(); try { while (<>s__2.MoveNext()) { <item>5__3 = <>s__2.Current; session.UnlockById(<item>5__3.id); <item>5__3 = default(SimpleItemInfo); } } finally { ((IDisposable)<>s__2).Dispose(); } <>s__4 = Object.FindObjectsOfType<RopeCabinDescription>(); for (<>s__5 = 0; <>s__5 < <>s__4.Length; <>s__5++) { <ropeCabinDescription>5__6 = <>s__4[<>s__5]; <ropeCabinDescription>5__6.UpdateCoffeeChalk(); <ropeCabinDescription>5__6 = null; } <>s__4 = null; ArtefactLoaderCabin obj = Object.FindObjectOfType<ArtefactLoaderCabin>(); if (obj != null) { obj.LoadArtefacts(); } RopeCabinDescription obj2 = Object.FindObjectOfType<RopeCabinDescription>(); if (obj2 != null) { obj2.CheckCabinItems(); } <items>5__1 = null; } if (session.playerData.items.pipe) { GameManager.control.smokingpipe = true; GameManager.control.isUsingPipe = usingPipe; __instance.cabinPipe.SetActive(true); } <>2__current = null; <>1__state = 2; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public static bool isCustomEvent = false; public static bool isFinishEvent = false; private static bool hasAllArtefacts = false; private static string tempText = ""; private static bool usingPipe; private static Text textElement; private static void Prefix(NPCEvents __instance) { if (!isCustomEvent) { return; } usingPipe = GameManager.control.isUsingPipe; hasAllArtefacts = GameManager.control.allArtefactsUnlocked; Text componentInChildren = __instance.allArtefactsInfo.GetComponentInChildren<Text>(); tempText = componentInChildren.text; textElement = componentInChildren; string text = "You got: "; session.UpdateReceivedItems(); for (int i = 0; i < session.uncollectedItems.Count; i++) { SimpleItemInfo simpleItemInfo = session.uncollectedItems[i]; if (!(simpleItemInfo.itemName == "Trap")) { text += simpleItemInfo.itemName; if (i != session.uncollectedItems.Count - 1) { text += ", "; } } } componentInChildren.text = text; } private static void Postfix(ref IEnumerator __result, NPCEvents __instance) { __result = MyWrapper(__result, __instance); } [IteratorStateMachine(typeof(<MyWrapper>d__8))] private static IEnumerator MyWrapper(IEnumerator original, NPCEvents __instance) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <MyWrapper>d__8(0) { original = original, __instance = __instance }; } } [HarmonyPatch(typeof(Pipe), "CheckLoad")] public class PipeCheckPatch { private static bool isUsingPipe; private static void Prefix() { isUsingPipe = GameManager.control.isUsingPipe; } private static void Postfix(Pipe __instance) { if (session.playerData.items.pipe) { GameManager.control.isUsingPipe = isUsingPipe; GameManager.control.smokingpipe = true; ((Component)__instance).gameObject.SetActive(isUsingPipe); } } } [HarmonyPatch(typeof(PipeCabin), "CheckLoad")] public class PipeCheck2Patch { private static bool isUsingPipe; private static void Prefix() { isUsingPipe = GameManager.control.isUsingPipe; } private static void Postfix(PipeCabin __instance) { if (session.playerData.items.pipe) { GameManager.control.isUsingPipe = isUsingPipe; GameManager.control.smokingpipe = true; ((Component)__instance).gameObject.SetActive(true); __instance.playerPipe.SetActive(isUsingPipe); } } } [HarmonyPatch(typeof(EnterPeakScene), "Awake")] public class EnterPeakScenePatch { private static void Prefix(EnterPeakScene __instance) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (!(session.currentScene == "IceWaterfallDemo")) { string text = ((object)(PeakNames)(ref GameObject.FindGameObjectWithTag("SummitBox").GetComponent<StamperPeakSummit>().peakNames)).ToString(); logger.LogInfo((object)("Entering peak: " + text)); GameObject val = (GameObject)(((object)GameObject.Find("PeaksOfArchipelagoScriptHolder")) ?? ((object)new GameObject("PeaksOfArchipelagoScriptHolder"))); Traps instance = val.AddComponent<Traps>(); logger.LogInfo((object)"Adding traps instance"); Traps.instance = instance; Traps.playerData = session.playerData; } } } [HarmonyPatch(typeof(OilLamp), "OilLampLightUp")] public class OilLampLightUpPatch { [CompilerGenerated] private sealed class <Wrapper>d__1 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public OilLamp __instance; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Wrapper>d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; __instance.oilLampLight.intensity = 0f; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static void Postfix(OilLamp __instance, ref IEnumerator __result) { if (!session.playerData.items.lamp) { __result = Wrapper(__instance); } } [IteratorStateMachine(typeof(<Wrapper>d__1))] private static IEnumerator Wrapper(OilLamp __instance) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Wrapper>d__1(0) { __instance = __instance }; } } [HarmonyPatch(typeof(Player), "GetButton", new Type[] { typeof(string) })] public class HandPatch { private static bool Prefix(ref bool __result, string actionName) { if (actionName == "Arm Right" && !session.playerData.items.rightHand) { return false; } if (actionName == "Arm Left" && !session.playerData.items.leftHand) { return false; } return true; } } [HarmonyPatch(typeof(StatsAndAchievements), "SetAchievement")] [HarmonyPatch(typeof(StatsAndAchievements), "SetStatFloat")] [HarmonyPatch(typeof(StatsAndAchievements), "SetStatInt")] [HarmonyPatch(typeof(StatsAndAchievements), "ResetStatsAndAchievements")] public class SetAchievementPatch { private static bool Prefix() { logger.LogInfo((object)"Game wants to do something with achievements, but I say no"); return false; } } [HarmonyPatch(typeof(SteamUserStats), "SetAchievement")] [HarmonyPatch(typeof(SteamUserStats), "StoreStats")] public class SetSteamAchievementPatch { private static bool Prefix(ref bool __result) { logger.LogInfo((object)"Game wants to do something with achievements, but I say no"); __result = true; return false; } } [HarmonyPatch] public class CollectionTextPatch { [CompilerGenerated] private sealed class <TargetMethods>d__0 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IEnumerator, IDisposable { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; MethodBase IEnumerator<MethodBase>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <TargetMethods>d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = AccessTools.Method(typeof(BirdSeedCollectedText), "InitiateCollectedTextSingle", (Type[])null, (Type[])null); <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = AccessTools.Method(typeof(RopeCollectedText), "InitiateCollectedTextSingle", (Type[])null, (Type[])null); <>1__state = 2; return true; case 2: <>1__state = -1; <>2__current = AccessTools.Method(typeof(BirdSeedCollectedText), "InitiateCollectedText", (Type[])null, (Type[])null); <>1__state = 3; return true; case 3: <>1__state = -1; <>2__current = AccessTools.Method(typeof(RopeCollectedText), "InitiateCollectedText", (Type[])null, (Type[])null); <>1__state = 4; return true; case 4: <>1__state = -1; <>2__current = AccessTools.Method(typeof(ArtefactCollectedText), "InitiateCollectedText", (Type[])null, (Type[])null); <>1__state = 5; return true; case 5: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new <TargetMethods>d__0(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<MethodBase>)this).GetEnumerator(); } } [IteratorStateMachine(typeof(<TargetMethods>d__0))] private static IEnumerable<MethodBase> TargetMethods() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <TargetMethods>d__0(-2); } private static bool Prefix() { logger.LogInfo((object)"Blocking collection Text"); return false; } } [HarmonyPatch(typeof(PeakSelection), "OnMouseSpriteDown")] public class FundamentalPeakSelectionPatch { private static bool Prefix(PeakSelection __instance) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown PeakJournal val = (PeakJournal)typeof(PeakSelection).GetField("peakJournal", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance); if ((__instance.leftPage && !Utils.IsJournalPageUnlocked(val.currentPage, Books.Fundamentals, session.playerData)) || (!__instance.leftPage && !Utils.IsJournalPageUnlocked(val.currentPage + 1, Books.Fundamentals, session.playerData))) { return false; } return true; } } [HarmonyPatch(typeof(PeakSelection), "OnMouseSpriteOver")] public class FundamentalPeakSelectionColorPatch { private static void Prefix(PeakSelection __instance) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) PeakJournal val = (PeakJournal)typeof(PeakSelection).GetField("peakJournal", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance); MeshRenderer component = __instance.rightSelectOutlineOBJ.GetComponent<MeshRenderer>(); MeshRenderer component2 = __instance.leftSelectOutlineOBJ.GetComponent<MeshRenderer>(); if (__instance.leftPage && !Utils.IsJournalPageUnlocked(val.currentPage, Books.Fundamentals, session.playerData)) { ((Renderer)component2).material.color = new Color(2f, 0f, 0f); } else { ((Renderer)component2).material.color = new Color(1f, 1f, 1f, 0.349f); } if (!__instance.leftPage && !Utils.IsJournalPageUnlocked(val.currentPage + 1, Books.Fundamentals, session.playerData)) { ((Renderer)component).material.color = new Color(2f, 0f, 0f); } else { ((Renderer)component).material.color = new Color(1f, 1f, 1f, 0.349f); } } } [HarmonyPatch(typeof(PeakJournal), "PageTurnSound")] public class FundamentalJournalColorPatch { private static void Postfix(PeakJournal __instance) { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0137: 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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance.journalPageAnim.clip == (Object)(object)__instance.journalPage_TurnLeft) { __instance.backPage.color = Utils.GetJournalPageColor(__instance.currentPage, Books.Fundamentals, session.playerData); __instance.frontPage.color = Utils.GetJournalPageColor(__instance.currentPage - 1, Books.Fundamentals, session.playerData); __instance.rightPage.color = Utils.GetJournalPageColor(__instance.currentPage + 1, Books.Fundamentals, session.playerData); __instance.leftPage.color = Utils.GetJournalPageColor(__instance.currentPage - 2, Books.Fundamentals, session.playerData); } else { __instance.backPage.color = Utils.GetJournalPageColor(__instance.currentPage + 2, Books.Fundamentals, session.playerData); __instance.frontPage.color = Utils.GetJournalPageColor(__instance.currentPage + 1, Books.Fundamentals, session.playerData); __instance.rightPage.color = Utils.GetJournalPageColor(__instance.currentPage + 3, Books.Fundamentals, session.playerData); __instance.leftPage.color = Utils.GetJournalPageColor(__instance.currentPage, Books.Fundamentals, session.playerData); } } } [HarmonyPatch(typeof(PeakJournal), "UpdatePage")] public class FundamentalUpdatePagePatch { private static void Postfix(PeakJournal __instance) { //IL_001a: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) __instance.backPage.color = Utils.GetJournalPageColor(__instance.currentPage + 2, Books.Fundamentals, session.playerData); __instance.frontPage.color = Utils.GetJournalPageColor(__instance.currentPage + 1, Books.Fundamentals, session.playerData); __instance.rightPage.color = Utils.GetJournalPageColor(__instance.currentPage + 3, Books.Fundamentals, session.playerData); __instance.leftPage.color = Utils.GetJournalPageColor(__instance.currentPage, Books.Fundamentals, session.playerData); } } [HarmonyPatch(typeof(IntermediatePeakSelection), "OnMouseSpriteDown")] public class IntermediatePeakSelectionPatch { private static bool Prefix(IntermediatePeakSelection __instance) { IntermediateJournal peakJournal = __instance.peakJournal; if ((__instance.leftPage && !Utils.IsJournalPageUnlocked(peakJournal.currentPage, Books.Intermediate, session.playerData)) || (!__instance.leftPage && !Utils.IsJournalPageUnlocked(peakJournal.currentPage + 1, Books.Intermediate, session.playerData))) { return false; } return true; } } [HarmonyPatch(typeof(IntermediatePeakSelection), "OnMouseSpriteOver")] public class IntermediatePeakSelectionColorPatch { private static void Prefix(IntermediatePeakSelection __instance) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) IntermediateJournal peakJournal = __instance.peakJournal; MeshRenderer component = __instance.rightSelectOutlineOBJ.GetComponent<MeshRenderer>(); MeshRenderer component2 = __instance.leftSelectOutlineOBJ.GetComponent<MeshRenderer>(); if (__instance.leftPage && !Utils.IsJournalPageUnlocked(peakJournal.currentPage, Books.Intermediate, session.playerData)) { ((Renderer)component2).material.color = new Color(2f, 0f, 0f); } else { ((Renderer)component2).material.color = new Color(1f, 1f, 1f, 0.349f); } if (!__instance.leftPage && !Utils.IsJournalPageUnlocked(peakJournal.currentPage + 1, Books.Intermediate, session.playerData)) { ((Renderer)component).material.color = new Color(2f, 0f, 0f); } else { ((Renderer)component).material.color = new Color(1f, 1f, 1f, 0.349f); } } } [HarmonyPatch(typeof(IntermediateJournal), "PageTurnSound")] public class IntermediateJournalColorPatch { private static void Postfix(IntermediateJournal __instance) { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0137: 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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance.journalPageAnim.clip == (Object)(object)__instance.journalPage_TurnLeft) { __instance.backPage.color = Utils.GetJournalPageColor(__instance.currentPage, Books.Intermediate, session.playerData); __instance.frontPage.color = Utils.GetJournalPageColor(__instance.currentPage - 1, Books.Intermediate, session.playerData); __instance.rightPage.color = Utils.GetJournalPageColor(__instance.currentPage + 1, Books.Intermediate, session.playerData); __instance.leftPage.color = Utils.GetJournalPageColor(__instance.currentPage - 2, Books.Intermediate, session.playerData); } else { __instance.backPage.color = Utils.GetJournalPageColor(__instance.currentPage + 2, Books.Intermediate, session.playerData); __instance.frontPage.color = Utils.GetJournalPageColor(__instance.currentPage + 1, Books.Intermediate, session.playerData); __instance.rightPage.color = Utils.GetJournalPageColor(__instance.currentPage + 3, Books.Intermediate, session.playerData); __instance.leftPage.color = Utils.GetJournalPageColor(__instance.currentPage, Books.Intermediate, session.playerData); } } } [HarmonyPatch(typeof(IntermediateJournal), "UpdatePage")] public class IntermediateUpdatePagePatch { private static void Postfix(IntermediateJournal __instance) { //IL_001a: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) __instance.backPage.color = Utils.GetJournalPageColor(__instance.currentPage + 2, Books.Intermediate, session.playerData); __instance.frontPage.color = Utils.GetJournalPageColor(__instance.currentPage + 1, Books.Intermediate, session.playerData); __instance.rightPage.color = Utils.GetJournalPageColor(__instance.currentPage + 3, Books.Intermediate, session.playerData); __instance.leftPage.color = Utils.GetJournalPageColor(__instance.currentPage, Books.Intermediate, session.playerData); } } [HarmonyPatch(typeof(AdvancedPeakSelection), "OnMouseSpriteDown")] public class AdvancedPeakSelectionPatch { private static bool Prefix(AdvancedPeakSelection __instance) { AdvancedJournal peakJournal = __instance.peakJournal; if ((__instance.leftPage && !Utils.IsJournalPageUnlocked(peakJournal.currentPage, Books.Advanced, session.playerData)) || (!__instance.leftPage && !Utils.IsJournalPageUnlocked(peakJournal.currentPage + 1, Books.Advanced, session.playerData))) { return false; } return true; } } [HarmonyPatch(typeof(AdvancedPeakSelection), "OnMouseSpriteOver")] public class AdvancedPeakSelectionColorPatch { private static void Prefix(AdvancedPeakSelection __instance) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) AdvancedJournal peakJournal = __instance.peakJournal; MeshRenderer component = __instance.rightSelectOutlineOBJ.GetComponent<MeshRenderer>(); MeshRenderer component2 = __instance.leftSelectOutlineOBJ.GetComponent<MeshRenderer>(); if (__instance.leftPage && !Utils.IsJournalPageUnlocked(peakJournal.currentPage, Books.Advanced, session.playerData)) { ((Renderer)component2).material.color = new Color(2f, 0f, 0f); } else { ((Renderer)component2).material.color = new Color(1f, 1f, 1f, 0.349f); } if (!__instance.leftPage && !Utils.IsJournalPageUnlocked(peakJournal.currentPage + 1, Books.Advanced, session.playerData)) { ((Renderer)component).material.color = new Color(2f, 0f, 0f); } else { ((Renderer)component).material.color = new Color(1f, 1f, 1f, 0.349f); } } } [HarmonyPatch(typeof(AdvancedJournal), "PageTurnSound")] public class AdvancedJournalColorPatch { private static void Postfix(AdvancedJournal __instance) { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0137: 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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance.journalPageAnim.clip == (Object)(object)__instance.journalPage_TurnLeft) { __instance.backPage.color = Utils.GetJournalPageColor(__instance.currentPage, Books.Advanced, session.playerData); __instance.frontPage.color = Utils.GetJournalPageColor(__instance.currentPage - 1, Books.Advanced, session.playerData); __instance.rightPage.color = Utils.GetJournalPageColor(__instance.currentPage + 1, Books.Advanced, session.playerData); __instance.leftPage.color = Utils.GetJournalPageColor(__instance.currentPage - 2, Books.Advanced, session.playerData); } else { __instance.backPage.color = Utils.GetJournalPageColor(__instance.currentPage + 2, Books.Advanced, session.playerData); __instance.frontPage.color = Utils.GetJournalPageColor(__instance.currentPage + 1, Books.Advanced, session.playerData); __instance.rightPage.color = Utils.GetJournalPageColor(__instance.currentPage + 3, Books.Advanced, session.playerData); __instance.leftPage.color = Utils.GetJournalPageColor(__instance.currentPage, Books.Advanced, session.playerData); } } } [HarmonyPatch(typeof(AdvancedJournal), "UpdatePage")] public class AdvancedUpdatePagePatch { private static void Postfix(AdvancedJournal __instance) { //IL_001a: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) __instance.backPage.color = Utils.GetJournalPageColor(__instance.currentPage + 2, Books.Advanced, session.playerData); __instance.frontPage.color = Utils.GetJournalPageColor(__instance.currentPage + 1, Books.Advanced, session.playerData); __instance.rightPage.color = Utils.GetJournalPageColor(__instance.currentPage + 3, Books.Advanced, session.playerData); __instance.leftPage.color = Utils.GetJournalPageColor(__instance.currentPage, Books.Advanced, session.playerData); } } [HarmonyPatch(typeof(DisableCabin4Flag), "CheckFlag")] public class DisableCabin4Things { private static void Postfix(DisableCabin4Flag __instance) { __instance.solemnTempestGateway.SetActive(session.playerData.items.peaks.IsChecked(Peaks.SolemnTempest)); } } [HarmonyPatch(typeof(Category4CabinLeave), "Update")] public class BulwarkStopperPatch { private static bool Prefix(Category4CabinLeave __instance) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) ((MonoBehaviour)__instance).StopCoroutine("GlowDoor"); __instance.itemMat.SetColor("_EmissionColor", Color.black); return session.playerData.items.peaks.IsChecked(Peaks.GreatBulwark); } } [HarmonyPatch(typeof(Cabin4Map), "Update")] public class SolemnTempestLoaderTranspiler { private static bool didBulwark; private static void Prefix() { didBulwark = GameManager.control.greatbulwark; GameManager.control.greatbulwark = session.playerData.items.peaks.IsChecked(Peaks.SolemnTempest); } private static void Postfix() { GameManager.control.greatbulwark = didBulwark; } } [HarmonyPatch(typeof(StamperPeakSummit), "JournalPageUpdate")] public class StamperJournalColorPatch { private static void Postfix(StamperPeakSummit __instance) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) __instance.leftPage.color = Color.white; __instance.rightPage.color = Color.white; } } [HarmonyPatch(typeof(RopeAnchor), "Start")] public class StartTranspiler { [CompilerGenerated] private sealed class <Transpiler>d__0 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private List<CodeInstruction> <codes>5__1; private int <i>5__2; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Transpiler>d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <codes>5__1 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_008b; } <>1__state = -1; <codes>5__1 = new List<CodeInstruction>(instructions); <i>5__2 = 0; goto IL_009b; IL_008b: <i>5__2++; goto IL_009b; IL_009b: if (<i>5__2 < <codes>5__1.Count) { if (<i>5__2 == 76 || <i>5__2 == 77 || <i>5__2 == 78) { goto IL_008b; } <>2__current = <codes>5__1[<i>5__2]; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <Transpiler>d__0 <Transpiler>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <Transpiler>d__ = this; } else { <Transpiler>d__ = new <Transpiler>d__0(0); } <Transpiler>d__.instructions = <>3__instructions; return <Transpiler>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } [IteratorStateMachine(typeof(<Transpiler>d__0))] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Transpiler>d__0(-2) { <>3__instructions = instructions }; } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] public class DetachThenAttachToNewTranspiler { [CompilerGenerated] private sealed class <Transpiler>d__0 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private List<CodeInstruction> <codes>5__1; private int <i>5__2; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Transpiler>d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <codes>5__1 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_0095; } <>1__state = -1; <codes>5__1 = new List<CodeInstruction>(instructions); <i>5__2 = 0; goto IL_00a5; IL_0095: <i>5__2++; goto IL_00a5; IL_00a5: if (<i>5__2 < <codes>5__1.Count) { if (<i>5__2 == 120 || <i>5__2 == 121 || <i>5__2 == 122 || <i>5__2 == 123) { goto IL_0095; } <>2__current = <codes>5__1[<i>5__2]; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <Transpiler>d__0 <Transpiler>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <Transpiler>d__ = this; } else { <Transpiler>d__ = new <Transpiler>d__0(0); } <Transpiler>d__.instructions = <>3__instructions; return <Transpiler>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } [IteratorStateMachine(typeof(<Transpiler>d__0))] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Transpiler>d__0(-2) { <>3__instructions = instructions }; } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] public class PullOutAnchorTranspiler { [CompilerGenerated] private sealed class <Transpiler>d__0 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private List<CodeInstruction> <codes>5__1; private int <i>5__2; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Transpiler>d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <codes>5__1 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_0095; } <>1__state = -1; <codes>5__1 = new List<CodeInstruction>(instructions); <i>5__2 = 0; goto IL_00a5; IL_0095: <i>5__2++; goto IL_00a5; IL_00a5: if (<i>5__2 < <codes>5__1.Count) { if (<i>5__2 == 79 || <i>5__2 == 80 || <i>5__2 == 81 || <i>5__2 == 82) { goto IL_0095; } <>2__current = <codes>5__1[<i>5__2]; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <Transpiler>d__0 <Transpiler>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <Transpiler>d__ = this; } else { <Transpiler>d__ = new <Transpiler>d__0(0); } <Transpiler>d__.instructions = <>3__instructions; return <Transpiler>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } [IteratorStateMachine(typeof(<Transpiler>d__0))] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Transpiler>d__0(-2) { <>3__instructions = instructions }; } } [HarmonyPatch(typeof(RopeCollectable), "CheckRope")] public class CheckRopeTranspiler { [CompilerGenerated] private sealed class <Transpiler>d__0 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private List<CodeInstruction> <codes>5__1; private int <i>5__2; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Transpiler>d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <codes>5__1 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_00a4; } <>1__state = -1; <codes>5__1 = new List<CodeInstruction>(instructions); <i>5__2 = 0; goto IL_00b4; IL_00a4: <i>5__2++; goto IL_00b4; IL_00b4: if (<i>5__2 < <codes>5__1.Count) { if (<i>5__2 == 267 || <i>5__2 == 268 || <i>5__2 == 269 || <i>5__2 == 270) { goto IL_00a4; } <>2__current = <codes>5__1[<i>5__2]; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <Transpiler>d__0 <Transpiler>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <Transpiler>d__ = this; } else { <Transpiler>d__ = new <Transpiler>d__0(0); } <Transpiler>d__.instructions = <>3__instructions; return <Transpiler>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } [IteratorStateMachine(typeof(<Transpiler>d__0))] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Transpiler>d__0(-2) { <>3__instructions = instructions }; } } [HarmonyPatch(typeof(BirdSeedCollectable), "CheckBirdSeed")] public class CheckBirdSeedTranspler { [CompilerGenerated] private sealed class <Transpiler>d__0 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private List<CodeInstruction> <codes>5__1; private int <i>5__2; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Transpiler>d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <codes>5__1 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_0095; } <>1__state = -1; <codes>5__
Archipelago.MultiClient.Net.dll
Decompiled a week 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.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.Colors; 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(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("Jarno Westhof, Hussein Farran, Zach Parks")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyDescription("A client library for use with .NET based prog-langs for interfacing with Archipelago hosts.")] [assembly: AssemblyFileVersion("6.6.0.0")] [assembly: AssemblyInformationalVersion("6.6.0+75d4c5e6a52bb0c8bb1d4bc368652613509c7acb")] [assembly: AssemblyProduct("Archipelago.MultiClient.Net")] [assembly: AssemblyTitle("Archipelago.MultiClient.Net")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/ArchipelagoMW/Archipelago.MultiClient.Net")] [assembly: AssemblyVersion("6.6.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 + ":NETSTANDARD2_0", 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.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, 6, 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; } public class UpdateHintPacket : ArchipelagoPacketBase { public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.UpdateHint; [JsonProperty("player")] public int Player { get; set; } [JsonProperty("location")] public long Location { get; set; } [JsonProperty("status")] public HintStatus Status { get; set; } } } 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; } [JsonProperty("status")] public HintStatus Status { 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 bool IsReceiverRelatedToActivePlayer { get; } public ScoutedItemInfo(NetworkItem item, string receiverGame, string senderGame, IItemInfoResolver itemInfoResolver, IPlayerHelper players, PlayerInfo player) : base(item, receiverGame, senderGame, itemInfoResolver, player) { IsReceiverRelatedToActivePlayer = (players.ActivePlayer ?? new PlayerInfo()).IsRelatedTo(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; } [JsonProperty("hint_status")] public HintStatus? HintStatus { 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, Archipelago.MultiClient.Net.Colors.PaletteColor.Blue) { base.Text = messagePart.Text; } } public class HintStatusMessagePart : MessagePart { internal HintStatusMessagePart(JsonMessagePart messagePart) : base(MessagePartType.HintStatus, messagePart) { base.Text = messagePart.Text; if (messagePart.HintStatus.HasValue) { base.PaletteColor = ColorUtils.GetColor(messagePart.HintStatus.Value); } } } 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.PaletteColor = ColorUtils.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; } } } } public class LocationMessagePart : MessagePart { public long LocationId { get; } public int Player { get; } internal LocationMessagePart(IPlayerHelper players, IItemInfoResolver itemInfoResolver, JsonMessagePart part) : base(MessagePartType.Location, part, Archipelago.MultiClient.Net.Colors.PaletteColor.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 => GetColor(BuiltInPalettes.Dark); public PaletteColor? PaletteColor { get; protected set; } public bool IsBackgroundColor { get; internal set; } internal MessagePart(MessagePartType type, JsonMessagePart messagePart, PaletteColor? color = null) { Type = type; Text = messagePart.Text; if (color.HasValue) { PaletteColor = color.Value; } else if (messagePart.Color.HasValue) { PaletteColor = ColorUtils.GetColor(messagePart.Color.Value); IsBackgroundColor = messagePart.Color.Value >= JsonMessagePartColor.BlackBg; } else { PaletteColor = null; } } public T GetColor<T>(Palette<T> palette) { return palette[PaletteColor]; } public override string ToString() { return Text; } } public enum MessagePartType { Text, Player, Item, Location, Entrance, HintStatus } 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.PaletteColor = (IsActivePlayer ? Archipelago.MultiClient.Net.Colors.PaletteColor.Magenta : Archipelago.MultiClient.Net.Colors.PaletteColor.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, int team, int slot, string message) : base(parts, players, team, slot) { Message = message; } } public class CollectLogMessage : PlayerSpecificLogMessage { internal CollectLogMessage(MessagePart[] parts, IPlayerHelper players, int team, int slot) : base(parts, players, 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, int team, int slot) : base(parts, players, team, slot) { } } public class HintItemSendLogMessage : ItemSendLogMessage { public bool IsFound { get; } internal HintItemSendLogMessage(MessagePart[] parts, IPlayerHelper players, int receiver, int sender, NetworkItem item, bool found, IItemInfoResolver itemInfoResolver) : base(parts, players, receiver, sender, item, itemInfoResolver) { IsFound = found; } } public class ItemCheatLogMessage : ItemSendLogMessage { internal ItemCheatLogMessage(MessagePart[] parts, IPlayerHelper players, int team, int slot, NetworkItem item, IItemInfoResolver itemInfoResolver) : base(parts, players, slot, 0, item, team, itemInfoResolver) { } } public class ItemSendLogMessage : LogMessage { private PlayerInfo ActivePlayer { get; } public PlayerInfo Receiver { get; } public PlayerInfo Sender { get; } public bool IsReceiverTheActivePlayer => Receiver == ActivePlayer; public bool IsSenderTheActivePlayer => Sender == ActivePlayer; public bool IsRelatedToActivePlayer { get { if (!ActivePlayer.IsRelatedTo(Receiver)) { return ActivePlayer.IsRelatedTo(Sender); } return true; } } public ItemInfo Item { get; } internal ItemSendLogMessage(MessagePart[] parts, IPlayerHelper players, int receiver, int sender, NetworkItem item, IItemInfoResolver itemInfoResolver) : this(parts, players, receiver, sender, item, players.ActivePlayer.Team, itemInfoResolver) { } internal ItemSendLogMessage(MessagePart[] parts, IPlayerHelper players, int receiver, int sender, NetworkItem item, int team, IItemInfoResolver itemInfoResolver) : base(parts) { ActivePlayer = players.ActivePlayer ?? new PlayerInfo(); Receiver = players.GetPlayerInfo(team, receiver) ?? new PlayerInfo(); Sender = players.GetPlayerInfo(team, sender) ?? new PlayerInfo(); PlayerInfo player = players.GetPlayerInfo(team, item.Player) ?? new PlayerInfo(); Item = new ItemInfo(item, Receiver.Game, Sender.Game, itemInfoResolver, player); } } public class JoinLogMessage : PlayerSpecificLogMessage { public string[] Tags { get; } internal JoinLogMessage(MessagePart[] parts, IPlayerHelper players, int team, int slot, string[] tags) : base(parts, players, team, slot) { Tags = tags; } } public class LeaveLogMessage : PlayerSpecificLogMessage { internal LeaveLogMessage(MessagePart[] parts, IPlayerHelper players, int team, int slot) : base(parts, players, 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 { private PlayerInfo ActivePlayer { get; } public PlayerInfo Player { get; } public bool IsActivePlayer => Player == ActivePlayer; public bool IsRelatedToActivePlayer => ActivePlayer.IsRelatedTo(Player); internal PlayerSpecificLogMessage(MessagePart[] parts, IPlayerHelper players, int team, int slot) : base(parts) { ActivePlayer = players.ActivePlayer ?? new PlayerInfo(); Player = players.GetPlayerInfo(team, slot) ?? new PlayerInfo(); } } public class ReleaseLogMessage : PlayerSpecificLogMessage { internal ReleaseLogMessage(MessagePart[] parts, IPlayerHelper players, int team, int slot) : base(parts, players, 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, int team, int slot, string[] tags) : base(parts, players, 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; } 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); } } 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}"]; } private DataStorageElement GetRaceModeElement() { return this[Scope.ReadOnly, "race_mode"]; } 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 GetSlotData<Dictionary<string, object>>(slot); } public T GetSlotData<T>(int? slot = null) where T : class { return GetSlotDataElement(slot).To<T>(); } public Task<Dictionary<string, object>> GetSlotDataAsync(int? slot = null) { return GetSlotDataAsync<Dictionary<string, object>>(slot); } public Task<T> GetSlotDataAsync<T>(int? slot = null) where T : class { return GetSlotDataElement(slot).GetAsync<T>(); } 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()); } public void TrackClientStatus(Action<ArchipelagoClientState> onStatusUpdated, bool retrieveCurrentClientStatus = true, int? slot = null, int? team = null) { GetClientStatusElement(slot, team).OnValueChanged += delegate(JToken _, JToken newValue, Dictionary<string, JToken> x) { onStatusUpdated(newValue.ToObject<ArchipelagoClientState>()); }; if (retrieveCurrentClientStatus) { GetClientStatusAsync(slot, team).ContinueWith(delegate(Task<ArchipelagoClientState> t) { onStatusUpdated(t.Result); }); } } public bool GetRaceMode() { return GetRaceModeElement().To<int?>().GetValueOrDefault() > 0; } public Task<bool> GetRaceModeAsync() { return GetRaceModeElement().GetAsync<int?>().ContinueWith((Task<int?> t) => t.Result.GetValueOrDefault() > 0); } } public interface IDataStorageWrapper { Hint[] GetHints(int? slot = null, int? tea