Decompiled source of PeaksOfArchipelago v1.7.1

PeaksOfArchipelago.dll

Decompiled a week ago
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
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