Decompiled source of KeyWe Archipelago v1.0.3

KeyWe_Archipelago\Archipelago.MultiClient.Net.dll

Decompiled 3 weeks 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.7.0.0")]
[assembly: AssemblyInformationalVersion("6.7.0+c807746b6f1774cf1afe12af819acb078b55a333")]
[assembly: AssemblyProduct("Archipelago.MultiClient.Net")]
[assembly: AssemblyTitle("Archipelago.MultiClient.Net")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/ArchipelagoMW/Archipelago.MultiClient.Net")]
[assembly: AssemblyVersion("6.7.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);
}
public class AttemptingStringEnumConverter : StringEnumConverter
{
	public AttemptingStringEnumConverter()
	{
	}

	public AttemptingStringEnumConverter(Type namingStrategyType)
		: base(namingStrategyType)
	{
	}

	public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
	{
		try
		{
			return ((StringEnumConverter)this).ReadJson(reader, objectType, existingValue, serializer);
		}
		catch (JsonSerializationException)
		{
			return objectType.IsValueType ? Activator.CreateInstance(objectType) : null;
		}
	}
}
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; }

		IHintsHelper Hints { 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; }

		public IHintsHelper Hints { get; }

		internal ArchipelagoSession(IArchipelagoSocketHelper socket, IReceivedItemsHelper items, ILocationCheckHelper locations, IPlayerHelper players, IRoomStateHelper roomState, ConnectionInfoHelper connectionInfoHelper, IDataStorageHelper dataStorage, IMessageLogHelper messageLog, IHintsHelper createHints)
		{
			Socket = socket;
			Items = items;
			Locations = locations;
			Players = players;
			RoomState = roomState;
			connectionInfo = connectionInfoHelper;
			DataStorage = dataStorage;
			MessageLog = messageLog;
			Hints = createHints;
			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);
				}
			}
			else
			{
				loginResultTask.TrySetResult(LoginResult.FromPacket(packet));
			}
		}

		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 roomStateHelper = new RoomStateHelper(socket, locationCheckHelper);
			DataStorageHelper dataStorageHelper = new DataStorageHelper(socket, connectionInfoHelper);
			MessageLogHelper messageLog = new MessageLogHelper(socket, itemInfoResolver, playerHelper, connectionInfoHelper);
			HintsHelper createHints = new HintsHelper(socket, playerHelper, locationCheckHelper, roomStateHelper, dataStorageHelper);
			return new ArchipelagoSession(socket, items, locationCheckHelper, playerHelper, roomStateHelper, connectionInfoHelper, dataStorageHelper, messageLog, createHints);
		}

		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(AttemptingStringEnumConverter))]
		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 CreateHintsPacket : ArchipelagoPacketBase
	{
		public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.CreateHints;

		[JsonProperty("locations")]
		public long[] Locations { get; set; }

		[JsonProperty("player")]
		public int Player { get; set; }

		[JsonProperty("status")]
		public HintStatus Status { 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(AttemptingStringEnumConverter))]
		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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Invalid comparison between Unknown and I4
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Invalid comparison between Unknown and I4
			//IL_00d8: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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(AttemptingStringEnumConverter), new object[] { typeof(SnakeCaseNamingStrategy) })]
		public JsonMessagePartType? Type { get; set; }

		[JsonProperty("color")]
		[JsonConverter(typeof(AttemptingStringEnumConverter), 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(AttemptingStringEnumConverter), 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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 == 8 && ((string)setReplyPacket.AdditionalArguments["Reference"]).TryParseNGuid(out var g) && operationSpecificCallbacks.TryGetValue(g, out var value))
					{
						value(setReplyPacket.OriginalValue, setReplyPacket.Value, setReplyPacket.AdditionalArguments);
						operationSpecificCallbacks.Remove(g);
					}
					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 key2 = Guid.NewGuid();
				operationSpecificCallbacks[key2] = e.Callbacks;
				dictionary["Reference"] = JToken.op_Implicit(key2.ToString("N"));
				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>());
	

KeyWe_Archipelago\KeyWe_AP_Client.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
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.Text;
using System.Threading;
using System.Threading.Tasks;
using Archipelago.MultiClient.Net;
using Archipelago.MultiClient.Net.Converters;
using Archipelago.MultiClient.Net.Enums;
using Archipelago.MultiClient.Net.Helpers;
using Archipelago.MultiClient.Net.MessageLog.Messages;
using Archipelago.MultiClient.Net.Models;
using Archipelago.MultiClient.Net.Packets;
using BepInEx;
using ExitGames.Client.Photon;
using Global;
using Global.Online;
using HarmonyLib;
using KeyWe.Profile.ProfileDataClasses;
using KeyWe.Stats;
using KeyWe.Tournament;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("KeyWe_AP_Client")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+d79d4c9dd4ad4ba035b07c0c4741a2568b5313c9")]
[assembly: AssemblyProduct("KeyWe Archipelago Client")]
[assembly: AssemblyTitle("KeyWe_AP_Client")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public class CosmeticSyncHandler : MonoBehaviourPunCallbacks
{
	public override void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
	{
		int[] itemIDs = default(int[]);
		if (targetPlayer != PhotonNetwork.LocalPlayer && OnlineExtensions.TryGetValue<int[]>(changedProps, (object)Properties.Customization, ref itemIDs))
		{
			ApplyRemoteCosmetics(itemIDs);
		}
	}

	private void ApplyRemoteCosmetics(int[] itemIDs)
	{
		Kiwi[] array = Object.FindObjectsOfType<Kiwi>();
		foreach (Kiwi val in array)
		{
			if (!val.IsLocalPlayer)
			{
				val.Customization.Init(itemIDs, true);
			}
		}
	}
}
namespace KeyWe_AP_Client
{
	public class APConsole : MonoBehaviour
	{
		[Serializable]
		public class LogEntry
		{
			public enum State
			{
				SlideIn,
				Hold,
				FadeOut
			}

			public State state;

			public float stateTimer;

			public float offsetY;

			public float baseY;

			public float animatedY;

			public TextMeshProUGUI text;

			public Image background;

			public string message;

			public float height = 28f;

			public LogEntry(string msg)
			{
				message = msg;
			}
		}

		private const float MessageHeight = 28f;

		private const float ConsoleHeight = 280f;

		private const float SlideInTime = 0.25f;

		private const float HoldTime = 3f;

		private const float FadeOutTime = 0.5f;

		private const float SlideInOffset = -50f;

		private const float FadeUpOffset = 20f;

		private const float PaddingX = 25f;

		private const float PaddingY = 25f;

		private const float MessageSpacing = 6f;

		public static TMP_FontAsset font;

		private static readonly Dictionary<string, string> KeywordColors = new Dictionary<string, string>
		{
			{ "summer", "#00ff00" },
			{ "fall", "#ff6600" },
			{ "winter", "#3399ff" },
			{ "warning", "#ff0000" },
			{ "movement+", "#ffff00" },
			{ "respawn+", "#ffff00" },
			{ "dash+", "#ffff00" },
			{ "jump+", "#ffff00" },
			{ "swim+", "#ffff00" },
			{ "chirp+", "#ffff00" },
			{ "peck+", "#ffff00" },
			{ "random facewear", "#ff00ff" },
			{ "random hat", "#ff00ff" },
			{ "random skin", "#ff00ff" },
			{ "random footwear", "#ff00ff" },
			{ "random backwear", "#ff00ff" },
			{ "random hairstyle", "#ff00ff" },
			{ "random arms", "#ff00ff" }
		};

		private readonly Queue<Image> _backgroundPool = new Queue<Image>();

		private readonly Queue<LogEntry> _cachedEntries = new Queue<LogEntry>();

		private readonly Queue<TextMeshProUGUI> _textPool = new Queue<TextMeshProUGUI>();

		private readonly List<LogEntry> _visibleEntries = new List<LogEntry>();

		private readonly List<LogEntry> _historyEntries = new List<LogEntry>();

		private GameObject _historyPanel;

		private RectTransform _historyContent;

		private bool _showHistory;

		private ScrollRect _historyScrollRect;

		private RectTransform _historyViewport;

		private Transform _messageParent;

		private bool _showConsole = true;

		private const bool LogToFile = true;

		public static APConsole Instance { get; private set; }

		private void Update()
		{
			UpdateMessages(Time.deltaTime);
			TryAddNewMessages();
			if (Input.GetKeyDown((KeyCode)288))
			{
				ToggleConsole();
			}
			if (Input.GetKeyDown((KeyCode)289))
			{
				ToggleHistory();
			}
			if (_showHistory)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}

		public static void Create()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			if (!((Object)(object)Instance != (Object)null))
			{
				KeyWeExtensions.ForEachItem<TMP_FontAsset>((IEnumerable<TMP_FontAsset>)Resources.FindObjectsOfTypeAll<TMP_FontAsset>(), (Action<TMP_FontAsset>)delegate(TMP_FontAsset x)
				{
					Debug.Log((object)((Object)x).name);
				});
				font = Resources.FindObjectsOfTypeAll<TMP_FontAsset>().First((TMP_FontAsset x) => ((Object)x).name == "BlackHanSans-Regular SDF");
				GameObject val = new GameObject("ArchipelagoConsoleUI");
				Object.DontDestroyOnLoad((Object)val);
				Instance = val.AddComponent<APConsole>();
				Instance.BuildUI();
				Instance.Log("Welcome to KeyWe");
			}
		}

		private void UpdateMessages(float delta)
		{
			for (int num = _visibleEntries.Count - 1; num >= 0; num--)
			{
				LogEntry entry = _visibleEntries[num];
				if (AnimateEntry(entry, delta))
				{
					RecycleEntry(entry);
					_visibleEntries.RemoveAt(num);
					RecalculateBaseY();
				}
				else
				{
					UpdateEntryVisual(entry);
				}
			}
		}

		private void RecalculateBaseY()
		{
			float num = 0f;
			for (int num2 = _visibleEntries.Count - 1; num2 >= 0; num2--)
			{
				LogEntry logEntry = _visibleEntries[num2];
				logEntry.baseY = num;
				num += logEntry.height + 6f;
			}
		}

		private bool AnimateEntry(LogEntry entry, float delta)
		{
			//IL_00f3: 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)
			entry.stateTimer += delta;
			switch (entry.state)
			{
			case LogEntry.State.SlideIn:
			{
				float num3 = Mathf.Clamp01(entry.stateTimer / 0.25f);
				entry.offsetY = Mathf.Lerp(-50f, 0f, EaseOutQuad(num3));
				if (num3 >= 1f)
				{
					entry.state = LogEntry.State.Hold;
					entry.stateTimer = 0f;
				}
				break;
			}
			case LogEntry.State.Hold:
				entry.offsetY = 0f;
				if (entry.stateTimer >= 3f)
				{
					entry.state = LogEntry.State.FadeOut;
					entry.stateTimer = 0f;
				}
				break;
			case LogEntry.State.FadeOut:
			{
				float num = Mathf.Clamp01(entry.stateTimer / 0.5f);
				entry.offsetY = Mathf.Lerp(0f, 20f, num);
				float num2 = 1f - num;
				((Graphic)entry.text).color = new Color(1f, 1f, 1f, num2);
				((Graphic)entry.background).color = new Color(0f, 0f, 0f, 0.8f * num2);
				if (num >= 1f)
				{
					return true;
				}
				break;
			}
			}
			return false;
		}

		private static float EaseOutQuad(float x)
		{
			return 1f - (1f - x) * (1f - x);
		}

		private void TryAddNewMessages()
		{
			if (!_showHistory && _cachedEntries.Any())
			{
				int num = Mathf.FloorToInt(10f);
				if (_visibleEntries.Count < num)
				{
					LogEntry logEntry = _cachedEntries.Dequeue();
					logEntry.state = LogEntry.State.SlideIn;
					logEntry.stateTimer = 0f;
					logEntry.offsetY = -50f;
					logEntry.animatedY = logEntry.baseY + logEntry.offsetY;
					CreateEntryVisual(logEntry);
					_visibleEntries.Add(logEntry);
					RecalculateBaseY();
					logEntry.animatedY = logEntry.baseY + logEntry.offsetY;
				}
			}
		}

		private void AddHistoryEntryVisual(LogEntry entry)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			Image background = GetBackground();
			((Component)background).transform.SetParent((Transform)(object)_historyContent, false);
			RectTransform rectTransform = ((Graphic)background).rectTransform;
			rectTransform.anchorMin = new Vector2(0f, 1f);
			rectTransform.anchorMax = new Vector2(1f, 1f);
			rectTransform.pivot = new Vector2(0.5f, 1f);
			rectTransform.anchoredPosition = Vector2.zero;
			rectTransform.sizeDelta = new Vector2(600f, 28f);
			TextMeshProUGUI text = GetText();
			RectTransform rectTransform2 = ((TMP_Text)text).rectTransform;
			((Transform)rectTransform2).SetParent(((Component)background).transform, false);
			rectTransform2.anchorMin = new Vector2(0f, 0f);
			rectTransform2.anchorMax = new Vector2(1f, 1f);
			rectTransform2.pivot = new Vector2(0f, 0.5f);
			rectTransform2.offsetMin = new Vector2(8f, 4f);
			rectTransform2.offsetMax = new Vector2(-8f, -4f);
			entry.text = text;
			entry.background = background;
			((Graphic)text).color = Color.white;
			((Graphic)background).color = new Color(0f, 0f, 0f, 0.8f);
			((TMP_Text)text).text = Colorize(entry.message);
			Canvas.ForceUpdateCanvases();
			LayoutRebuilder.ForceRebuildLayoutImmediate(((TMP_Text)text).rectTransform);
			float preferredHeight = Mathf.Max(28f, ((TMP_Text)text).preferredHeight + 8f);
			LayoutElement val = ((Component)background).GetComponent<LayoutElement>();
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = ((Component)background).gameObject.AddComponent<LayoutElement>();
			}
			val.preferredHeight = preferredHeight;
		}

		private void CreateEntryVisual(LogEntry entry)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			Image background = GetBackground();
			((Component)background).transform.SetParent(_messageParent, false);
			RectTransform rectTransform = ((Graphic)background).rectTransform;
			rectTransform.anchorMin = new Vector2(0f, 0f);
			rectTransform.anchorMax = new Vector2(0f, 0f);
			rectTransform.pivot = new Vector2(0f, 0f);
			rectTransform.sizeDelta = new Vector2(600f, 28f);
			TextMeshProUGUI text = GetText();
			RectTransform rectTransform2 = ((TMP_Text)text).rectTransform;
			((Transform)rectTransform2).SetParent(((Component)background).transform, false);
			rectTransform2.anchorMin = new Vector2(0f, 0f);
			rectTransform2.anchorMax = new Vector2(1f, 1f);
			rectTransform2.pivot = new Vector2(0f, 0.5f);
			rectTransform2.offsetMin = new Vector2(8f, 4f);
			rectTransform2.offsetMax = new Vector2(-8f, -4f);
			entry.text = text;
			entry.background = background;
			((Graphic)text).color = new Color(1f, 1f, 1f, 1f);
			((Graphic)background).color = new Color(0f, 0f, 0f, 0.8f);
			UpdateEntryVisual(entry);
		}

		private void UpdateEntryVisual(LogEntry entry)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			((TMP_Text)entry.text).text = Colorize(entry.message);
			RectTransform rectTransform = ((Graphic)entry.background).rectTransform;
			float preferredHeight = ((TMP_Text)entry.text).preferredHeight;
			entry.height = Mathf.Max(28f, preferredHeight + 8f);
			rectTransform.sizeDelta = new Vector2(rectTransform.sizeDelta.x, entry.height);
			float num = entry.baseY + entry.offsetY;
			entry.animatedY = Mathf.Lerp(entry.animatedY, num, Time.deltaTime * 12f);
			((Graphic)entry.background).rectTransform.anchoredPosition = new Vector2(0f, entry.animatedY);
		}

		private TextMeshProUGUI GetText()
		{
			//IL_0058: 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)
			if (_textPool.Count > 0)
			{
				TextMeshProUGUI obj = _textPool.Dequeue();
				((Component)obj).gameObject.SetActive(true);
				return obj;
			}
			TextMeshProUGUI component = new GameObject("LogText", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(TextMeshProUGUI)
			}).GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).fontSize = 19f;
			((Graphic)component).color = Color.white;
			((TMP_Text)component).font = font;
			((TMP_Text)component).wordSpacing = 20f;
			((TMP_Text)component).alignment = (TextAlignmentOptions)4097;
			return component;
		}

		private Image GetBackground()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if (_backgroundPool.Count > 0)
			{
				Image obj = _backgroundPool.Dequeue();
				((Component)obj).gameObject.SetActive(true);
				return obj;
			}
			Image obj2 = new GameObject("LogBG").AddComponent<Image>();
			((Graphic)obj2).color = new Color(0f, 0f, 0f, 0.8f);
			obj2.type = (Type)1;
			return obj2;
		}

		private void RecycleEntry(LogEntry entry)
		{
			((Component)entry.text).gameObject.SetActive(false);
			((Component)entry.background).gameObject.SetActive(false);
			_textPool.Enqueue(entry.text);
			_backgroundPool.Enqueue(entry.background);
		}

		private string Colorize(string input)
		{
			if (string.IsNullOrEmpty(input) || KeywordColors.Count == 0)
			{
				return input;
			}
			StringBuilder stringBuilder = new StringBuilder(input.Length + 32);
			int num = 0;
			while (num < input.Length)
			{
				bool flag = false;
				foreach (KeyValuePair<string, string> keywordColor in KeywordColors)
				{
					string key = keywordColor.Key;
					string value = keywordColor.Value;
					if (!string.IsNullOrEmpty(key) && num + key.Length <= input.Length && string.Compare(input, num, key, 0, key.Length, ignoreCase: true, CultureInfo.InvariantCulture) == 0)
					{
						stringBuilder.Append("<color=").Append(value).Append('>');
						stringBuilder.Append(input, num, key.Length);
						stringBuilder.Append("</color>");
						num += key.Length;
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					stringBuilder.Append(input[num]);
					num++;
				}
			}
			return stringBuilder.ToString();
		}

		public void Log(string text)
		{
			LogEntry logEntry = new LogEntry(text);
			_cachedEntries.Enqueue(logEntry);
			_historyEntries.Add(logEntry);
			if ((Object)(object)_historyPanel != (Object)null && _historyPanel.activeSelf)
			{
				AddHistoryEntryVisual(logEntry);
			}
		}

		private void ToggleHistory()
		{
			_showHistory = !_showHistory;
			((Component)_messageParent).gameObject.SetActive(!_showHistory);
			_historyPanel.SetActive(_showHistory);
			if (_showHistory)
			{
				foreach (LogEntry visibleEntry in _visibleEntries)
				{
					if ((Object)(object)visibleEntry.text != (Object)null)
					{
						((Component)visibleEntry.text).gameObject.SetActive(false);
					}
					if ((Object)(object)visibleEntry.background != (Object)null)
					{
						((Component)visibleEntry.background).gameObject.SetActive(false);
					}
					_textPool.Enqueue(visibleEntry.text);
					_backgroundPool.Enqueue(visibleEntry.background);
				}
				_visibleEntries.Clear();
				_cachedEntries.Clear();
				RebuildHistory();
			}
			else
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = false;
				((Component)_messageParent).gameObject.SetActive(_showConsole);
			}
		}

		private void ToggleConsole()
		{
			_showConsole = !_showConsole;
			foreach (LogEntry visibleEntry in _visibleEntries)
			{
				if ((Object)(object)visibleEntry.background != (Object)null)
				{
					((Component)visibleEntry.background).gameObject.SetActive(_showConsole);
				}
				if ((Object)(object)visibleEntry.text != (Object)null)
				{
					((Component)visibleEntry.text).gameObject.SetActive(_showConsole);
				}
			}
			((Component)_messageParent).gameObject.SetActive(_showConsole);
			if (!_showConsole)
			{
				_showHistory = false;
				_historyPanel.SetActive(false);
			}
		}

		private void BuildUI()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Expected O, but got Unknown
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Expected O, but got Unknown
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Unknown result type (might be due to invalid IL or missing references)
			//IL_0372: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("APConsoleCanvas", new Type[3]
			{
				typeof(Canvas),
				typeof(CanvasScaler),
				typeof(GraphicRaycaster)
			});
			val.transform.SetParent(((Component)this).transform);
			Canvas component = val.GetComponent<Canvas>();
			component.renderMode = (RenderMode)0;
			component.sortingOrder = 2000;
			CanvasScaler component2 = val.GetComponent<CanvasScaler>();
			component2.uiScaleMode = (ScaleMode)1;
			component2.referenceResolution = new Vector2(1920f, 1080f);
			GameObject val2 = new GameObject("Messages", new Type[1] { typeof(RectTransform) });
			RectTransform component3 = val2.GetComponent<RectTransform>();
			((Transform)component3).SetParent(val.transform, false);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0f, 0f);
			component3.pivot = val3;
			Vector2 anchorMin = (component3.anchorMax = val3);
			component3.anchorMin = anchorMin;
			component3.anchoredPosition = new Vector2(25f, 25f);
			_messageParent = val2.transform;
			_historyPanel = new GameObject("HistoryPanel", new Type[1] { typeof(RectTransform) });
			RectTransform component4 = _historyPanel.GetComponent<RectTransform>();
			((Transform)component4).SetParent(val.transform, false);
			component4.anchorMin = new Vector2(0f, 0f);
			component4.anchorMax = new Vector2(0f, 0f);
			component4.pivot = new Vector2(0f, 0f);
			component4.anchoredPosition = new Vector2(25f, 25f);
			component4.sizeDelta = new Vector2(600f, 280f);
			_historyPanel.SetActive(false);
			_historyScrollRect = _historyPanel.AddComponent<ScrollRect>();
			_historyScrollRect.horizontal = false;
			_historyScrollRect.vertical = true;
			_historyScrollRect.scrollSensitivity = 10f;
			_historyScrollRect.movementType = (MovementType)2;
			GameObject val5 = new GameObject("Viewport", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Mask)
			});
			_historyViewport = val5.GetComponent<RectTransform>();
			val5.transform.SetParent(_historyPanel.transform, false);
			_historyViewport.anchorMin = Vector2.zero;
			_historyViewport.anchorMax = Vector2.one;
			_historyViewport.offsetMin = Vector2.zero;
			_historyViewport.offsetMax = Vector2.zero;
			Image component5 = val5.GetComponent<Image>();
			((Graphic)component5).color = Color.white;
			component5.type = (Type)0;
			((Graphic)component5).raycastTarget = true;
			val5.GetComponent<Mask>().showMaskGraphic = false;
			_historyScrollRect.viewport = _historyViewport;
			GameObject val6 = new GameObject("Content", new Type[3]
			{
				typeof(RectTransform),
				typeof(VerticalLayoutGroup),
				typeof(ContentSizeFitter)
			});
			RectTransform component6 = val6.GetComponent<RectTransform>();
			((Transform)component6).SetParent(val5.transform, false);
			component6.anchorMin = new Vector2(0f, 1f);
			component6.anchorMax = new Vector2(1f, 1f);
			component6.pivot = new Vector2(0.5f, 1f);
			component6.anchoredPosition = Vector2.zero;
			component6.sizeDelta = new Vector2(0f, 0f);
			VerticalLayoutGroup component7 = val6.GetComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)component7).childForceExpandHeight = false;
			((HorizontalOrVerticalLayoutGroup)component7).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)component7).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)component7).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)component7).spacing = 8f;
			((LayoutGroup)component7).childAlignment = (TextAnchor)0;
			ContentSizeFitter component8 = val6.GetComponent<ContentSizeFitter>();
			component8.verticalFit = (FitMode)2;
			component8.horizontalFit = (FitMode)0;
			_historyScrollRect.content = component6;
			_historyContent = component6;
		}

		private void RebuildHistory()
		{
			if ((Object)(object)_historyContent == (Object)null)
			{
				return;
			}
			for (int num = ((Transform)_historyContent).childCount - 1; num >= 0; num--)
			{
				Object.Destroy((Object)(object)((Component)((Transform)_historyContent).GetChild(num)).gameObject);
			}
			foreach (LogEntry historyEntry in _historyEntries)
			{
				AddHistoryEntryVisual(historyEntry);
			}
			Canvas.ForceUpdateCanvases();
			LayoutRebuilder.ForceRebuildLayoutImmediate(_historyContent);
			Canvas.ForceUpdateCanvases();
			_historyScrollRect.verticalNormalizedPosition = 0f;
		}
	}
	public class ArchipelagoHandler
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static MessageReceivedHandler <0>__OnMessageReceived;
		}

		private const string GameName = "KeyWe";

		public static bool IsConnected;

		public static bool IsConnecting;

		public static Action OnConnect;

		private readonly string[] _deathMessages = new string[26]
		{
			"had a skill issue (died)", "forgot to dash (died)", "didn't see the edge of the table (died)", "thought kiwis could fly (died)", "forgot their floatie (died)", "got spooked to death by Zoey", "slept on the job (died)", "got left out in the cold (died)", "got abducted by the mailflies (died)", "had an argument with a cassowary (died)",
			"popped too much bubblewrap (died)", "fell into a shipping crate (died)", "called Papa Moon an ape (died)", "lost the snowball fight (died)", "was struck by lightning", "got trapped in the bungalow basin oven (died)", "swallowed a button (died)", "got hit by a cannonball (died)", "lost Herbert (died)", "was swallowed by a pitcher plant (died)",
			"tried to hitch a ride on Bartleby (died)", "got toasted (died)", "sank in quicksand (died)", "didn't try hard enough (died)", "made a typo (died)", "forgot the 'We' (died)"
		};

		private readonly ConcurrentQueue<long> _locationsToCheck = new ConcurrentQueue<long>();

		private readonly Random _random = new Random();

		private string _lastDeath;

		private LoginSuccessful _loginSuccessful;

		private ArchipelagoSession _session;

		public SlotData SlotData;

		private string Server { get; }

		private int Port { get; }

		private string Slot { get; }

		private string Password { get; }

		private string Seed { get; set; }

		private double SlotInstance { get; set; }

		public ArchipelagoHandler(string server, int port, string slot, string password)
		{
			Server = server;
			Port = port;
			Slot = slot;
			Password = password;
			base..ctor();
		}

		private void HandleDeathLink(string source, string cause)
		{
			if (SlotData.DeathLink)
			{
				APConsole.Instance.Log(cause ?? "");
				if (!(source == Slot))
				{
					GameHandler.SomeoneElseDied = true;
					PluginMain.GameHandler.Kill();
				}
			}
		}

		private void CreateSession()
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			SlotInstance = UnixTimeConverter.ToUnixTimeStamp(DateTime.Now);
			_session = ArchipelagoSessionFactory.CreateSession(Server, Port);
			IMessageLogHelper messageLog = _session.MessageLog;
			object obj = <>O.<0>__OnMessageReceived;
			if (obj == null)
			{
				MessageReceivedHandler val = OnMessageReceived;
				<>O.<0>__OnMessageReceived = val;
				obj = (object)val;
			}
			messageLog.OnMessageReceived += (MessageReceivedHandler)obj;
			_session.Socket.SocketClosed += new SocketClosedHandler(OnSocketClosed);
			_session.Socket.PacketReceived += new PacketReceivedHandler(PacketReceived);
			_session.Items.ItemReceived += new ItemReceivedHandler(ItemReceived);
		}

		private void OnSocketClosed(string reason)
		{
			APConsole.Instance.Log("Connection closed (" + reason + ") Attempting reconnect...");
			IsConnected = false;
		}

		public void InitConnect()
		{
			IsConnecting = true;
			CreateSession();
			IsConnected = Connect();
			IsConnecting = false;
		}

		private bool Connect()
		{
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			Task<RoomInfoPacket> task = _session.ConnectAsync();
			object seed;
			if (task == null)
			{
				seed = null;
			}
			else
			{
				RoomInfoPacket result = task.Result;
				seed = ((result != null) ? result.SeedName : null);
			}
			Seed = (string)seed;
			if (Seed != null)
			{
				PluginMain.SaveDataHandler.LoadProfile(Seed, Slot);
			}
			LoginResult result2 = _session.LoginAsync("KeyWe", Slot, (ItemsHandlingFlags)7, new Version(1, 0, 0), Array.Empty<string>(), (string)null, Password, true).Result;
			if (result2.Successful)
			{
				_loginSuccessful = (LoginSuccessful)result2;
				SlotData = new SlotData(_loginSuccessful.SlotData);
				PluginMain.GameHandler.InitOnConnect();
				new Thread(RunCheckLocationsFromList).Start();
				OnConnect();
				return true;
			}
			LoginFailure val = (LoginFailure)result2;
			string text = Enumerable.Aggregate(seed: Enumerable.Aggregate(seed: $"Failed to Connect to {Server}:{Port} as {Slot}:", source: val.Errors, func: (string current, string error) => current + "\n    " + error), source: val.ErrorCodes, func: (string current, ConnectionRefusedError error) => current + $"\n    {error}");
			APConsole.Instance.Log(text);
			APConsole.Instance.Log("Attempting reconnect...");
			return false;
		}

		private void ItemReceived(ReceivedItemsHelper helper)
		{
			try
			{
				while (helper.Any())
				{
					int index = helper.Index;
					ItemInfo item = helper.DequeueItem();
					PluginMain.ItemHandler.HandleItem(index, item);
				}
			}
			catch (Exception arg)
			{
				APConsole.Instance.Log($"[ItemReceived ERROR] {arg}");
				throw;
			}
		}

		public void Release()
		{
			_session.SetGoalAchieved();
			_session.SetClientState((ArchipelagoClientState)30);
		}

		public void CheckLocations(long[] ids)
		{
			ids.ToList().ForEach(delegate(long id)
			{
				_locationsToCheck.Enqueue(id);
			});
		}

		public void CheckLocation(long id)
		{
			_locationsToCheck.Enqueue(id);
		}

		private void RunCheckLocationsFromList()
		{
			while (true)
			{
				if (_locationsToCheck.TryDequeue(out var result))
				{
					_session.Locations.CompleteLocationChecks(new long[1] { result });
				}
				else
				{
					Thread.Sleep(100);
				}
			}
		}

		public bool IsLocationChecked(long id)
		{
			return _session.Locations.AllLocationsChecked.Contains(id);
		}

		public int CountLocationsCheckedInRange(long start, long end)
		{
			return _session.Locations.AllLocationsChecked.Count((long loc) => loc >= start && loc < end);
		}

		public void UpdateTags(List<string> tags)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			ConnectUpdatePacket val = new ConnectUpdatePacket
			{
				Tags = tags.ToArray(),
				ItemsHandling = (ItemsHandlingFlags)7
			};
			_session.Socket.SendPacket((ArchipelagoPacketBase)(object)val);
		}

		private static void OnMessageReceived(LogMessage message)
		{
			APConsole.Instance.Log(((object)message).ToString() ?? string.Empty);
		}

		private void PacketReceived(ArchipelagoPacketBase packet)
		{
			BouncePacket val = (BouncePacket)(object)((packet is BouncePacket) ? packet : null);
			if (val != null)
			{
				BouncePacketReceived(val);
			}
		}

		public void SendDeath()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			BouncePacket val = new BouncePacket();
			DateTime now = DateTime.Now;
			val.Tags = new List<string>(1) { "DeathLink" };
			val.Data = new Dictionary<string, JToken>
			{
				{
					"time",
					JToken.op_Implicit(UnixTimeConverter.ToUnixTimeStamp(now))
				},
				{
					"source",
					JToken.op_Implicit(Slot)
				},
				{
					"cause",
					JToken.op_Implicit(Slot + " " + _deathMessages[_random.Next(_deathMessages.Length)])
				}
			};
			if (val.Data.TryGetValue("source", out var value))
			{
				((object)value)?.ToString();
				if (val.Data.TryGetValue("cause", out var value2))
				{
					((object)value2)?.ToString();
					if (val.Data.TryGetValue("time", out var value3))
					{
						((object)value3)?.ToString();
					}
				}
			}
			_session.Socket.SendPacket((ArchipelagoPacketBase)(object)val);
		}

		private void BouncePacketReceived(BouncePacket packet)
		{
			if (SlotData.DeathLink)
			{
				ProcessBouncePacket(packet, "DeathLink", ref _lastDeath, delegate(string source, Dictionary<string, JToken> data)
				{
					HandleDeathLink(source, ((object)data["cause"])?.ToString() ?? "Unknown");
				});
			}
		}

		private static void ProcessBouncePacket(BouncePacket packet, string tag, ref string lastTime, Action<string, Dictionary<string, JToken>> handler)
		{
			if (!packet.Tags.Contains(tag) || !packet.Data.TryGetValue("time", out var value) || lastTime == ((object)value).ToString())
			{
				return;
			}
			lastTime = ((object)value).ToString();
			if (packet.Data.TryGetValue("source", out var value2))
			{
				string arg = ((object)value2)?.ToString() ?? "Unknown";
				if (packet.Data.TryGetValue("cause", out var value3))
				{
					((object)value3)?.ToString();
				}
				handler(arg, packet.Data);
			}
		}

		public bool IsFinalLocked()
		{
			if (SaveDataHandler.ArchipelagoSaveData.CollectiblesChecked.Count((KeyValuePair<int, bool> x) => x.Value) < PluginMain.ArchipelagoHandler.SlotData.RequiredCollectibleChecks)
			{
				return true;
			}
			if (SaveDataHandler.ArchipelagoSaveData.LevelCompletions.Count((KeyValuePair<int, bool> x) => x.Value) < PluginMain.ArchipelagoHandler.SlotData.RequiredLevelCompletions)
			{
				return true;
			}
			if (Enumerable.Range(0, 9).Any((int week) => Enumerable.Range(0, 4).Count((int day) => SaveDataHandler.ArchipelagoSaveData.LevelCompletions[week * 4 + day]) < PluginMain.ArchipelagoHandler.SlotData.RequiredLevelCompletionsPerWeek))
			{
				return true;
			}
			if (SaveDataHandler.ArchipelagoSaveData.Collectibles.Count((KeyValuePair<int, bool> x) => x.Value) < PluginMain.ArchipelagoHandler.SlotData.RequiredCollectibles)
			{
				return true;
			}
			if (SaveDataHandler.ArchipelagoSaveData.OvertimeLevelCompletions.Count((KeyValuePair<int, bool> x) => x.Value) < PluginMain.ArchipelagoHandler.SlotData.RequiredOvertimeCompletions)
			{
				return true;
			}
			if (SaveDataHandler.ArchipelagoSaveData.TournamentCourseCompletions.Count((KeyValuePair<int, bool> x) => x.Value) < PluginMain.ArchipelagoHandler.SlotData.RequiredTournamentCompletions)
			{
				return true;
			}
			return false;
		}

		public string GetRequirementsString()
		{
			int num = SaveDataHandler.ArchipelagoSaveData.LevelCompletions.Count((KeyValuePair<int, bool> x) => x.Value);
			int requiredLevelCompletions = PluginMain.ArchipelagoHandler.SlotData.RequiredLevelCompletions;
			int num2 = Enumerable.Range(0, 9).Count((int week) => Enumerable.Range(0, 4).Count((int day) => SaveDataHandler.ArchipelagoSaveData.LevelCompletions[week * 4 + day]) >= PluginMain.ArchipelagoHandler.SlotData.RequiredLevelCompletionsPerWeek);
			int num3 = SaveDataHandler.ArchipelagoSaveData.Collectibles.Count((KeyValuePair<int, bool> x) => x.Value);
			int requiredCollectibles = PluginMain.ArchipelagoHandler.SlotData.RequiredCollectibles;
			int num4 = SaveDataHandler.ArchipelagoSaveData.CollectiblesChecked.Count((KeyValuePair<int, bool> x) => x.Value);
			int requiredCollectibleChecks = PluginMain.ArchipelagoHandler.SlotData.RequiredCollectibleChecks;
			int num5 = SaveDataHandler.ArchipelagoSaveData.OvertimeLevelCompletions.Count((KeyValuePair<int, bool> x) => x.Value);
			int requiredOvertimeCompletions = PluginMain.ArchipelagoHandler.SlotData.RequiredOvertimeCompletions;
			int num6 = SaveDataHandler.ArchipelagoSaveData.TournamentCourseCompletions.Count((KeyValuePair<int, bool> x) => x.Value);
			int requiredTournamentCompletions = PluginMain.ArchipelagoHandler.SlotData.RequiredTournamentCompletions;
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("Stand Your Post Requirements:");
			if (requiredLevelCompletions > 0)
			{
				stringBuilder.AppendLine($"{num}/{requiredLevelCompletions} levels complete");
			}
			if (PluginMain.ArchipelagoHandler.SlotData.RequiredLevelCompletionsPerWeek > 0)
			{
				stringBuilder.AppendLine($"{num2}/{9} weeks with {PluginMain.ArchipelagoHandler.SlotData.RequiredLevelCompletionsPerWeek} level(s) complete");
			}
			if (requiredCollectibles > 0)
			{
				stringBuilder.AppendLine($"{num3}/{requiredCollectibles} collectibles received");
			}
			if (requiredCollectibleChecks > 0)
			{
				stringBuilder.AppendLine($"{num4}/{requiredCollectibleChecks} collectible locations checked");
			}
			if (requiredOvertimeCompletions > 0)
			{
				stringBuilder.AppendLine($"{num5}/{requiredOvertimeCompletions} overtime shifts complete");
			}
			if (requiredTournamentCompletions > 0)
			{
				stringBuilder.AppendLine($"{num6}/{requiredTournamentCompletions} tournament courses complete");
			}
			return stringBuilder.ToString();
		}
	}
	public class ConnectionInfo
	{
		public string Server { get; set; }

		public ushort Port { get; set; }

		public string Slot { get; set; }

		public string Password { get; set; }
	}
	public class ConnectionInfoHandler
	{
		private static readonly string path = SaveSystem.DataRoot + "connection_info.json";

		public static void Save(string server, ushort port, string slot, string password)
		{
			string contents = JsonConvert.SerializeObject((object)new ConnectionInfo
			{
				Server = server,
				Port = port,
				Slot = slot,
				Password = password
			});
			File.WriteAllText(path, contents);
		}

		public static void Load(ref string server, ref ushort port, ref string slotName, ref string password)
		{
			ConnectionInfo connectionInfo = JsonConvert.DeserializeObject<ConnectionInfo>(File.ReadAllText(path));
			server = connectionInfo.Server;
			port = connectionInfo.Port;
			slotName = connectionInfo.Slot;
			password = connectionInfo.Password;
		}
	}
	public class Data
	{
		public static float MaxWalkSpeed = 16f;

		public static float MaxJumpHeight = 33f;

		public static float MaxSwimSpeed = 12.4f;

		public static float MaxRespawnFallSpeed = 10f;

		public static float MaxRespawnFallMoveSpeed = 13f;

		public static float MaxDashForce = 37.5f;

		public static float MaxChirpCooldown = 5f;

		public static float MinDashCooldown = 0.3f;

		public static float MinPeckCooldown = 0f;

		public static float MinChirpCooldown = 0f;

		public static float InitialWalkSpeed = 10f;

		public static float InitialDashForce = 20f;

		public static float InitialSwimSpeed = 5f;

		public static float InitialJumpHeight = 22f;

		public static float InitialRespawnFallMoveSpeed = 5f;

		public static float InitialRespawnFallSpeed = 4f;

		public static float InitialChirpCooldown = 0.6f;

		public static float InitialPeckCooldown = 0.6f;

		public static float InitialDashCooldown = 0.6f;

		public static Dictionary<string, int> OvertimeLevelNameToId = new Dictionary<string, int>
		{
			{ "Kiwis in Harmony", 0 },
			{ "Conveyer Belt Chaos", 1 },
			{ "Lunch Break", 2 },
			{ "Tank Trouble", 3 },
			{ "Cassowary Courier Course", 4 },
			{ "Bubble Wrap Testing", 5 },
			{ "Snowball Fight!", 6 },
			{ "The Sorting Room", 7 },
			{ "Cashing Out", 8 }
		};

		public static Dictionary<string, int> TournamentLevelNameToId = new Dictionary<string, int>
		{
			{ "Gumtree Grove", 0 },
			{ "Painted Cliffs", 1 },
			{ "Lake Bessy", 2 }
		};

		public static List<int> ExcludedLevels = new List<int>(4) { 16, 18, 19, 17 };

		public static List<int> ExcludedOvertimeShifts = new List<int>(1) { 3 };

		public static List<int> ExcludedTournamentCourses = new List<int>(2) { 1, 2 };

		public static Dictionary<string, int> LevelNameToId = new Dictionary<string, int>
		{
			{ "The Telegraph Desk", 0 },
			{ "The Transcription Room", 1 },
			{ "The Shipping Floor", 2 },
			{ "The Dropoff Depot", 3 },
			{ "Marauding Mailflies", 4 },
			{ "Covert Decoders", 5 },
			{ "Postal Pest Problems", 6 },
			{ "Vegetation Vexation", 7 },
			{ "Devilish Dust-Up", 8 },
			{ "A Sinking Feeling", 9 },
			{ "Bouncing Boxes (and Blimps)", 10 },
			{ "Creepin’ Kudzu", 11 },
			{ "Shipping Shake-Up", 12 },
			{ "Transcription Turmoil", 13 },
			{ "Keyboard Commotion", 14 },
			{ "Parcel Panel Puzzle", 15 },
			{ "The Night Post", 16 },
			{ "Electrical Interference", 17 },
			{ "Bobbing for Boxes", 18 },
			{ "Mechanical Mayhem", 19 },
			{ "Tricks and Telegrams", 20 },
			{ "Zoey’s Tracks of Terror", 21 },
			{ "Casso-scary", 22 },
			{ "Mail from Beyond", 23 },
			{ "Trapdoors and Tentacles", 24 },
			{ "Assembly-Line Scramble", 25 },
			{ "Dueling Crates", 26 },
			{ "Switchboard Synchrony", 27 },
			{ "Bungalow Basin Bake-Off", 28 },
			{ "Parts and Crafts", 29 },
			{ "The Hollyjostle Tinkertrack", 30 },
			{ "That’s a Wrap", 31 },
			{ "An Approaching Storm", 32 },
			{ "Bitter Cold", 33 },
			{ "Emergency Relief", 34 },
			{ "Stand Your Post", 35 }
		};
	}
	public class GameHandler : MonoBehaviour
	{
		[HarmonyPatch(typeof(Overmap))]
		public class Overmap_Patch
		{
			[HarmonyPatch("Start")]
			[HarmonyPostfix]
			public static void OnStart(Overmap __instance)
			{
				OvermapMenuOption? obj = ((IEnumerable<OvermapMenuOption>)__instance.options).FirstOrDefault((Func<OvermapMenuOption, bool>)((OvermapMenuOption o) => ((Object)o).name == "SwitchProfile"));
				if (obj != null)
				{
					((Component)obj).transform.Translate(-10000f, 0f, 0f);
				}
				OvermapMenuOption? obj2 = ((IEnumerable<OvermapMenuOption>)__instance.options).FirstOrDefault((Func<OvermapMenuOption, bool>)((OvermapMenuOption o) => (int)o.option == 2));
				if (obj2 != null)
				{
					KeyWeExtensions.SetActive((MonoBehaviour)(object)obj2, false);
				}
				OvermapMenuOption? obj3 = ((IEnumerable<OvermapMenuOption>)__instance.options).FirstOrDefault((Func<OvermapMenuOption, bool>)((OvermapMenuOption o) => (int)o.option == 3));
				if (obj3 != null)
				{
					KeyWeExtensions.SetActive((MonoBehaviour)(object)obj3, false);
				}
			}
		}

		[HarmonyPatch(typeof(Kiwi))]
		public class Kiwi_Patch
		{
			private static readonly ConditionalWeakTable<Kiwi, Action> handlers = new ConditionalWeakTable<Kiwi, Action>();

			[HarmonyPatch("Init")]
			[HarmonyPostfix]
			public static void OnInit(Kiwi __instance)
			{
				UpdateKiwiMovement(__instance);
				Action value = delegate
				{
					UpdateKiwiMovement(__instance);
				};
				handlers.Add(__instance, value);
				onReceivedMovementUpgrade = (Action)Delegate.Combine(onReceivedMovementUpgrade, (Action)delegate
				{
					UpdateKiwiMovement(__instance);
				});
			}

			[HarmonyPatch("OnDestroy")]
			[HarmonyPrefix]
			public static void OnDestroy(Kiwi __instance)
			{
				if (handlers.TryGetValue(__instance, out var value))
				{
					onReceivedMovementUpgrade = (Action)Delegate.Remove(onReceivedMovementUpgrade, value);
					handlers.Remove(__instance);
				}
			}

			[HarmonyPatch("Respawn")]
			[HarmonyPrefix]
			public static void OnRespawn(Kiwi __instance, bool inWater)
			{
				try
				{
					if (SomeoneElseDied)
					{
						SomeoneElseDied = false;
					}
					else if (!((PauseObject)__instance).IsPaused && PluginMain.ArchipelagoHandler.SlotData.DeathLink)
					{
						PluginMain.ArchipelagoHandler.SendDeath();
					}
				}
				catch (Exception ex)
				{
					APConsole.Instance.Log(ex.Message);
				}
			}
		}

		[HarmonyPatch(typeof(CourseButton))]
		public class CourseButton_Patch
		{
			[HarmonyPatch("SetData")]
			[HarmonyPrefix]
			private static void OnSetData(ref bool isLocked, int index, TournamentRecord record, TournamentLevelData data)
			{
				bool tournamentUnlocked = SaveDataHandler.ArchipelagoSaveData.TournamentUnlocked;
				if (SystemHandler.Get<DataKeeper>().Profile.CheckProgress((ProgressFlag)8192))
				{
					isLocked = tournamentUnlocked;
				}
				else if (tournamentUnlocked)
				{
					APConsole.Instance.Log("Warning: You have made an attempt to DLC protection measures. Please support the devs. They worked hard on this game. Thank you - xMcacutt");
				}
			}
		}

		[HarmonyPatch(typeof(OvertimeShiftBoard))]
		public class OvertimeShiftBoard_Patch
		{
			[HarmonyPatch("Overmap_OnRefreshScene")]
			[HarmonyPostfix]
			private static void Overmap_OnRefreshScene(OvertimeShiftBoard __instance)
			{
				KeyWeExtensions.ForEachItem<ShiftDisplay>((IEnumerable<ShiftDisplay>)__instance.topRow, (Action<ShiftDisplay>)delegate(ShiftDisplay d)
				{
					KeyWeExtensions.SetActive((MonoBehaviour)(object)d, SaveDataHandler.ArchipelagoSaveData.OvertimeSummerUnlocked);
				});
				KeyWeExtensions.ForEachItem<ShiftDisplay>((IEnumerable<ShiftDisplay>)__instance.middleRow, (Action<ShiftDisplay>)delegate(ShiftDisplay d)
				{
					KeyWeExtensions.SetActive((MonoBehaviour)(object)d, SaveDataHandler.ArchipelagoSaveData.OvertimeFallUnlocked);
				});
				KeyWeExtensions.ForEachItem<ShiftDisplay>((IEnumerable<ShiftDisplay>)__instance.bottomRow, (Action<ShiftDisplay>)delegate(ShiftDisplay d)
				{
					KeyWeExtensions.SetActive((MonoBehaviour)(object)d, SaveDataHandler.ArchipelagoSaveData.OvertimeWinterUnlocked);
				});
			}
		}

		[HarmonyPatch(typeof(OvermapSubMenu))]
		public class OvermapSubMenu_Patch
		{
			[HarmonyPatch("SetUIShowing")]
			[HarmonyPostfix]
			private static void SetUIShowing(OvermapSubMenu __instance, bool activate)
			{
				if (SaveDataHandler.ArchipelagoSaveData == null)
				{
					return;
				}
				OvertimeShiftBoard val = (OvertimeShiftBoard)(object)((__instance is OvertimeShiftBoard) ? __instance : null);
				if (val != null)
				{
					KeyWeExtensions.ForEachItem<ShiftDisplay>((IEnumerable<ShiftDisplay>)val.topRow, (Action<ShiftDisplay>)delegate(ShiftDisplay d)
					{
						KeyWeExtensions.SetActive((MonoBehaviour)(object)d, SaveDataHandler.ArchipelagoSaveData.OvertimeSummerUnlocked);
					});
					KeyWeExtensions.ForEachItem<ShiftDisplay>((IEnumerable<ShiftDisplay>)val.middleRow, (Action<ShiftDisplay>)delegate(ShiftDisplay d)
					{
						KeyWeExtensions.SetActive((MonoBehaviour)(object)d, SaveDataHandler.ArchipelagoSaveData.OvertimeFallUnlocked);
					});
					KeyWeExtensions.ForEachItem<ShiftDisplay>((IEnumerable<ShiftDisplay>)val.bottomRow, (Action<ShiftDisplay>)delegate(ShiftDisplay d)
					{
						KeyWeExtensions.SetActive((MonoBehaviour)(object)d, SaveDataHandler.ArchipelagoSaveData.OvertimeWinterUnlocked);
					});
				}
			}
		}

		[HarmonyPatch(typeof(Calendar))]
		public class Calendar_Patch
		{
			[HarmonyPatch("Day_OnSelected")]
			[HarmonyPostfix]
			public static void OnDaySelected(DayButton button)
			{
				if (!(SystemHandler.Get<DataKeeper>().Levels[(int)button.DataIndex].Name != "Stand Your Post") && button.IsLocked)
				{
					APConsole.Instance.Log(PluginMain.ArchipelagoHandler.GetRequirementsString());
				}
			}

			[HarmonyPatch("InitRewards")]
			[HarmonyPrefix]
			private static bool InitRewards(Calendar __instance)
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				LevelResults results = __instance.results;
				if (((results != null) ? results.BestResults : null) == null || !KeyWeExtensions.IsPassed(__instance.results.BestResults.Grade) || !__instance.results.BestResults.NewGrade)
				{
					return false;
				}
				LevelResults results2 = __instance.results;
				if (results2 != null)
				{
					results2.ResetData();
				}
				__instance.OnAwardsDone();
				return false;
			}

			[HarmonyPatch("SetUpButtons")]
			[HarmonyPrefix]
			public static bool OnSetUpButtons(Calendar __instance, SeasonRange range, int numLevels)
			{
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0098: Unknown result type (might be due to invalid IL or missing references)
				for (int i = 0; i < __instance.dayButtons.Length; i++)
				{
					DayButton val = __instance.dayButtons[i];
					int num = range.StartIndex + i;
					int key = range.StartIndex / 12 * 3 + i / 4;
					bool flag = !SaveDataHandler.ArchipelagoSaveData.WeeksUnlocked[key];
					if (num == 35)
					{
						flag = PluginMain.ArchipelagoHandler.IsFinalLocked();
					}
					if (i < numLevels)
					{
						LevelData val2 = __instance.dataKeeper.Levels[num];
						Sprite modeIcon = __instance.modeInfo.GetModeIcon(val2.Mode);
						bool? challengesStatus = __instance.GetChallengesStatus(num, val2);
						val.Init(((RecordBase)__instance.dataKeeper.Profile.LevelRecords[num]).HighestGrade, modeIcon, flag, (short)num, (short)i, challengesStatus);
					}
					else
					{
						val.Init((Grade)(-2), (Sprite)null, true, (short)(-1), (short)i, (bool?)null);
					}
				}
				__instance.FocusButton(range);
				return false;
			}

			[HarmonyPatch("UpdateSeason")]
			[HarmonyPrefix]
			public static bool OnUpdateSeason(Calendar __instance)
			{
				__instance.details.Hide();
				if ((Object)(object)__instance.pcFields.StartButton != (Object)null)
				{
					__instance.pcFields.StartButton.interactable = false;
				}
				DataKeeper dataKeeper = __instance.dataKeeper;
				SeasonRange val = ((dataKeeper != null) ? dataKeeper.Levels.SeasonsIndices[__instance.seasonIndex] : null);
				__instance.SetUpButtons(val, val.Count);
				__instance.isNextSeasonLocked = false;
				__instance.UpdateSeasonPlates();
				__instance.UpdatePCButtons();
				__instance.RefreshHighlightedDay();
				__instance.UpdateIntroButton();
				return false;
			}
		}

		[HarmonyPatch(typeof(ProfileData))]
		public class ProfileData_Patch
		{
			[HarmonyPatch("ChallengesCompleted")]
			[HarmonyPrefix]
			public static bool OnChallengesCompleted(ProfileData __instance, ref ushort __result, Mode mode, int levelID, ushort[] challengeIDs, ushort reward)
			{
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				ushort num = 0;
				if (challengeIDs == null)
				{
					__result = num;
					return false;
				}
				RecordBase val = default(RecordBase);
				foreach (ushort num2 in challengeIDs)
				{
					if (!__instance.IsChallengeCompleted(mode, levelID, num2, ref val) && val != null)
					{
						RecordBase val2 = val;
						if (val2.CompletedChallengeIndices == null)
						{
							val2.CompletedChallengeIndices = new List<ushort>();
						}
						val?.CompletedChallengeIndices.Add(num2);
						num += reward;
					}
				}
				__result = num;
				return false;
			}
		}

		[HarmonyPatch(typeof(DataKeeper))]
		public class DataKeeper_Patch
		{
			[HarmonyPatch("GiveReward")]
			[HarmonyPrefix]
			public static bool OnGiveReward(Grade grade, ref ushort extraStamps, LevelData levelData)
			{
				extraStamps = 0;
				return true;
			}

			[HarmonyPatch("CheckForCinematicTrigger")]
			[HarmonyPrefix]
			private static bool OnCheckForCinematicTrigger(ref Cinematics __result)
			{
				__result = (Cinematics)(-1);
				return false;
			}

			[HarmonyPatch("GetActiveSeason")]
			[HarmonyPrefix]
			public static bool GetActiveSeason(ref Season __result)
			{
				__result = (Season)2;
				return false;
			}
		}

		public static bool IsUnlocking;

		public static bool SomeoneElseDied;

		public static Action onReceivedMovementUpgrade;

		public void InitOnConnect()
		{
			((Component)this).gameObject.AddComponent<CosmeticSyncHandler>();
		}

		public void LogWearables()
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			string text = "";
			for (int i = 0; i < 7; i++)
			{
				text = text + "Category " + i + " \n";
				Customizable[] items = SystemHandler.Get<DataKeeper>().GetWearables((Categories)i).Items;
				foreach (Customizable val in items)
				{
					text = text + val.Id + " " + val.Name + "\n";
					text = text + val.Description + "\n";
					text = text + ((object)(CategoryMask)(ref val.incompatibleCategories)).ToString() + "\n";
					string text2 = text;
					RewardCategory rewardCategory = val.RewardCategory;
					text = text2 + ((object)(RewardCategory)(ref rewardCategory)).ToString() + "\n\n";
				}
				text += "\n";
			}
			File.WriteAllText(SaveSystem.DataRoot + "Help.txt", text);
		}

		public void Kill()
		{
			((MonoBehaviour)this).StartCoroutine(KillDelayed());
		}

		private IEnumerator KillDelayed()
		{
			yield return null;
			Kiwi[] array = Object.FindObjectsOfType<Kiwi>();
			foreach (Kiwi val in array)
			{
				if (val.IsLocalPlayer)
				{
					val.Respawn(false);
				}
			}
		}

		public void EquipRandom(Categories category)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			DataKeeper val = SystemHandler.Get<DataKeeper>();
			State currentState = val.CurrentState;
			if ((int)currentState != 2)
			{
				if ((int)currentState != 3)
				{
					if ((int)currentState == 7 && Data.ExcludedTournamentCourses.Contains(Data.TournamentLevelNameToId[val.CurrentLevelData.Name]))
					{
						goto IL_0082;
					}
				}
				else if (Data.ExcludedOvertimeShifts.Contains(Data.OvertimeLevelNameToId[val.CurrentLevelData.Name]))
				{
					goto IL_0082;
				}
			}
			else if (Data.ExcludedLevels.Contains(Data.LevelNameToId[val.CurrentLevelData.Name]))
			{
				goto IL_0082;
			}
			((MonoBehaviour)this).StartCoroutine(EquipRandomDelayed(category));
			return;
			IL_0082:
			APConsole.Instance.Log("Cannot equip cosmetics in this level");
		}

		private IEnumerator EquipRandomDelayed(Categories category)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			yield return null;
			DataKeeper dataKeeper = SystemHandler.Get<DataKeeper>();
			Kiwi[] array = Object.FindObjectsOfType<Kiwi>();
			if (array.Length == 0)
			{
				yield break;
			}
			Kiwi[] array2 = array;
			foreach (Kiwi val in array2)
			{
				if (!val.IsLocalPlayer)
				{
					continue;
				}
				int num = ((!PhotonNetwork.IsConnected) ? ((CommonKiwi)val).playerIndex : dataKeeper.OnlineSelectedKiwi);
				Customization customization = dataKeeper.Profile.GetCustomization(num);
				List<Customizable> list = dataKeeper.GetWearables(category).Items.Where((Customizable x) => (dataKeeper.Profile.CheckProgress((ProgressFlag)8192) || (int)x.RewardCategory != 7) && (dataKeeper.Profile.CheckProgress((ProgressFlag)256) || (int)x.RewardCategory != 3) && (int)x.RewardCategory != 5).ToList();
				if (list.Count == 0)
				{
					continue;
				}
				Customizable random = KeyWeExtensions.GetRandom<Customizable>((IEnumerable<Customizable>)list);
				int num2 = 1;
				for (int j = 0; j < 7; j++)
				{
					if (FlagsHelper.IsSet<CategoryMask>(random.IncompatibleCategories, (CategoryMask)num2))
					{
						((Customization)(ref customization)).EquipItem((Categories)j, 0u);
					}
					num2 <<= 1;
				}
				UnequipIncompatibleItems(random, num, category);
				((Customization)(ref customization)).EquipItem(category, random.Id);
				dataKeeper.SaveProfile();
				val.Customization.InitAll();
				if (PhotonNetwork.IsConnected)
				{
					Customization customization2 = dataKeeper.Profile.GetCustomization(dataKeeper.OnlineSelectedKiwi);
					int[] intItemIDs = ((Customization)(ref customization2)).IntItemIDs;
					Player localPlayer = PhotonNetwork.LocalPlayer;
					Hashtable val2 = new Hashtable();
					((Dictionary<object, object>)(object)val2).Add((object)Properties.Customization, (object)intItemIDs);
					localPlayer.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null);
				}
			}
		}

		private void UnequipIncompatibleItems(Customizable wearable, int playerIndex, Categories category)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			DataKeeper val = SystemHandler.Get<DataKeeper>();
			Customization customization = val.Profile.GetCustomization(playerIndex);
			CategoryMask val2 = (CategoryMask)(1 << (int)category);
			for (int i = 0; i < 7; i++)
			{
				Categories val3 = (Categories)i;
				bool num = val3 != category && FlagsHelper.IsSet<CategoryMask>(wearable.IncompatibleCategories, (CategoryMask)(1 << i));
				uint num2 = customization.ItemIDs[i];
				Customizable wearable2 = val.GetWearable(val3, num2);
				bool flag = wearable2 != null && FlagsHelper.IsSet<CategoryMask>(wearable2.IncompatibleCategories, val2);
				if (num || flag)
				{
					((Customization)(ref customization)).EquipItem(val3, 0u);
				}
			}
		}

		public static void UpdateKiwiMovement(Kiwi kiwi)
		{
			kiwi.walkSpeed = SaveDataHandler.ArchipelagoSaveData.WalkSpeed;
			kiwi.swimSpeed = SaveDataHandler.ArchipelagoSaveData.SwimSpeed;
			kiwi.dashing.dashForce = SaveDataHandler.ArchipelagoSaveData.DashForce;
			kiwi.dashing.DashCooldownTimer.maxTime = SaveDataHandler.ArchipelagoSaveData.DashCooldown;
			kiwi.dashing.dashCooldownTimer.Length = SaveDataHandler.ArchipelagoSaveData.DashCooldown;
			kiwi.jumping.initialSpeed = SaveDataHandler.ArchipelagoSaveData.JumpHeight;
			kiwi.jumping.maxJumpForce = SaveDataHandler.ArchipelagoSaveData.JumpHeight;
			kiwi.fallSpeed = SaveDataHandler.ArchipelagoSaveData.RespawnFallSpeed;
			kiwi.fallMovementSpeed = SaveDataHandler.ArchipelagoSaveData.RespawnFallMoveSpeed;
			kiwi.vocalTimer.maxTime = SaveDataHandler.ArchipelagoSaveData.ChirpCooldown;
			kiwi.vocalTimer.Length = SaveDataHandler.ArchipelagoSaveData.ChirpCooldown;
			kiwi.peckTimer.maxTime = SaveDataHandler.ArchipelagoSaveData.PeckCooldown;
			kiwi.peckTimer.Length = SaveDataHandler.ArchipelagoSaveData.PeckCooldown;
		}
	}
	public enum KWItem
	{
		SummerWeek1 = 1,
		SummerWeek2 = 2,
		SummerWeek3 = 3,
		FallWeek1 = 4,
		FallWeek2 = 5,
		FallWeek3 = 6,
		WinterWeek1 = 7,
		WinterWeek2 = 8,
		WinterWeek3 = 9,
		OvertimeSummer = 10,
		OvertimeFall = 11,
		OvertimeWinter = 12,
		Tournament = 13,
		Facewear = 256,
		Hat = 257,
		Skin = 258,
		Backwear = 259,
		Hairstyle = 260,
		Footwear = 261,
		Arms = 262,
		DashUp = 512,
		MoveUp = 513,
		SwimUp = 514,
		JumpUp = 515,
		RespawnUp = 516,
		ChirpUp = 517,
		PeckUp = 518,
		SecretSpiceShaker = 768,
		GlimmeringShell = 769,
		EmptyChrysalis = 770,
		TemperedLens = 771,
		WayfarersCompass = 772,
		PricklySeedPod = 773,
		AncientTooth = 774,
		CosmicFriendshipRock = 775,
		ChargedFeather = 776,
		SaltyScale = 777,
		GlowingWishbone = 778,
		Z39SoaringAuk = 779,
		PapaMoonFigurine = 780,
		MountaineersPiton = 781,
		LostLetter = 782
	}
	public class ItemHandler
	{
		public void HandleItem(int index, ItemInfo item)
		{
			try
			{
				if (index < SaveDataHandler.ArchipelagoSaveData.ItemIndex)
				{
					return;
				}
				SaveDataHandler.ArchipelagoSaveData.ItemIndex++;
				long itemId = item.ItemId;
				if (itemId > 767)
				{
					if (itemId < 783)
					{
						SaveDataHandler.ArchipelagoSaveData.Collectibles[(int)item.ItemId - 768] = true;
					}
				}
				else if (itemId > 0)
				{
					if (itemId >= 10)
					{
						long num = itemId - 10;
						if ((ulong)num <= 3uL)
						{
							switch (num)
							{
							case 0L:
								goto IL_0105;
							case 1L:
								goto IL_0115;
							case 2L:
								goto IL_0125;
							case 3L:
								goto IL_0135;
							}
						}
						long num2 = itemId - 256;
						if ((ulong)num2 <= 6uL)
						{
							switch (num2)
							{
							case 0L:
								goto IL_016f;
							case 1L:
								goto IL_017f;
							case 2L:
								goto IL_018f;
							case 3L:
								goto IL_019f;
							case 4L:
								goto IL_01af;
							case 5L:
								goto IL_01bf;
							case 6L:
								goto IL_01cf;
							}
						}
						long num3 = itemId - 512;
						if ((ulong)num3 <= 6uL)
						{
							switch (num3)
							{
							case 0L:
							{
								float dashCooldown = SaveDataHandler.ArchipelagoSaveData.DashCooldown;
								float num10 = (Data.InitialDashCooldown - Data.MinDashCooldown) / 5f;
								SaveDataHandler.ArchipelagoSaveData.DashCooldown = Math.Max(dashCooldown - num10, Data.MinDashCooldown);
								float dashForce = SaveDataHandler.ArchipelagoSaveData.DashForce;
								num10 = (Data.MaxDashForce - Data.InitialDashForce) / 5f;
								SaveDataHandler.ArchipelagoSaveData.DashForce = Math.Min(dashForce + num10, Data.MaxDashForce);
								GameHandler.onReceivedMovementUpgrade?.Invoke();
								break;
							}
							case 1L:
							{
								float walkSpeed = SaveDataHandler.ArchipelagoSaveData.WalkSpeed;
								float num5 = (Data.MaxWalkSpeed - Data.InitialWalkSpeed) / 5f;
								SaveDataHandler.ArchipelagoSaveData.WalkSpeed = Math.Min(walkSpeed + num5, Data.MaxWalkSpeed);
								GameHandler.onReceivedMovementUpgrade?.Invoke();
								break;
							}
							case 2L:
							{
								float swimSpeed = SaveDataHandler.ArchipelagoSaveData.SwimSpeed;
								float num7 = (Data.MaxSwimSpeed - Data.InitialSwimSpeed) / 5f;
								SaveDataHandler.ArchipelagoSaveData.SwimSpeed = Math.Min(swimSpeed + num7, Data.MaxSwimSpeed);
								GameHandler.onReceivedMovementUpgrade?.Invoke();
								break;
							}
							case 3L:
							{
								float jumpHeight = SaveDataHandler.ArchipelagoSaveData.JumpHeight;
								float num11 = (Data.MaxJumpHeight - Data.InitialJumpHeight) / 5f;
								SaveDataHandler.ArchipelagoSaveData.JumpHeight = Math.Min(jumpHeight + num11, Data.MaxJumpHeight);
								GameHandler.onReceivedMovementUpgrade?.Invoke();
								break;
							}
							case 4L:
							{
								float respawnFallSpeed = SaveDataHandler.ArchipelagoSaveData.RespawnFallSpeed;
								float num8 = (Data.MaxRespawnFallSpeed - Data.InitialRespawnFallSpeed) / 5f;
								SaveDataHandler.ArchipelagoSaveData.RespawnFallSpeed = Math.Min(respawnFallSpeed + num8, Data.MaxRespawnFallSpeed);
								float respawnFallMoveSpeed = SaveDataHandler.ArchipelagoSaveData.RespawnFallMoveSpeed;
								float num9 = (Data.MaxRespawnFallMoveSpeed - Data.InitialRespawnFallMoveSpeed) / 5f;
								SaveDataHandler.ArchipelagoSaveData.RespawnFallMoveSpeed = Math.Min(respawnFallMoveSpeed + num9, Data.MaxRespawnFallMoveSpeed);
								GameHandler.onReceivedMovementUpgrade?.Invoke();
								break;
							}
							case 5L:
							{
								float chirpCooldown = SaveDataHandler.ArchipelagoSaveData.ChirpCooldown;
								float num6 = (Data.InitialChirpCooldown - Data.MinChirpCooldown) / 5f;
								SaveDataHandler.ArchipelagoSaveData.ChirpCooldown = Math.Max(chirpCooldown - num6, Data.MinChirpCooldown);
								GameHandler.onReceivedMovementUpgrade?.Invoke();
								break;
							}
							case 6L:
							{
								float peckCooldown = SaveDataHandler.ArchipelagoSaveData.PeckCooldown;
								float num4 = (Data.InitialPeckCooldown - Data.MinPeckCooldown) / 5f;
								SaveDataHandler.ArchipelagoSaveData.PeckCooldown = Math.Max(peckCooldown - num4, Data.MinPeckCooldown);
								GameHandler.onReceivedMovementUpgrade?.Invoke();
								break;
							}
							}
						}
					}
					else
					{
						PluginMain.SaveDataHandler.UnlockWeek((int)item.ItemId - 1);
					}
				}
				goto IL_0486;
				IL_0135:
				if (SystemHandler.Get<DataKeeper>().Profile.CheckProgress((ProgressFlag)8192))
				{
					SaveDataHandler.ArchipelagoSaveData.TournamentUnlocked = true;
				}
				else
				{
					APConsole.Instance.Log("Warning: You do not own the Telepost Tournament DLC but have its checks enabled.");
				}
				goto IL_0486;
				IL_0105:
				SaveDataHandler.ArchipelagoSaveData.OvertimeSummerUnlocked = true;
				goto IL_0486;
				IL_0125:
				SaveDataHandler.ArchipelagoSaveData.OvertimeWinterUnlocked = true;
				goto IL_0486;
				IL_0115:
				SaveDataHandler.ArchipelagoSaveData.OvertimeFallUnlocked = true;
				goto IL_0486;
				IL_019f:
				PluginMain.GameHandler.EquipRandom((Categories)3);
				goto IL_0486;
				IL_018f:
				PluginMain.GameHandler.EquipRandom((Categories)1);
				goto IL_0486;
				IL_017f:
				PluginMain.GameHandler.EquipRandom((Categories)0);
				goto IL_0486;
				IL_016f:
				PluginMain.GameHandler.EquipRandom((Categories)2);
				goto IL_0486;
				IL_01bf:
				PluginMain.GameHandler.EquipRandom((Categories)5);
				goto IL_0486;
				IL_01af:
				PluginMain.GameHandler.EquipRandom((Categories)4);
				goto IL_0486;
				IL_01cf:
				PluginMain.GameHandler.EquipRandom((Categories)6);
				goto IL_0486;
				IL_0486:
				SystemHandler.Get<DataKeeper>().SaveProfile();
			}
			catch (Exception arg)
			{
				APConsole.Instance.Log($"[HandleItem ERROR] {arg}");
				throw;
			}
		}
	}
	public class LocationHandler
	{
		[HarmonyPatch(typeof(DataKeeper))]
		public class DataKeeper_Patch
		{
			[HarmonyPatch("CalenderLevelComplete")]
			[HarmonyPrefix]
			public static bool OnCalenderLevelComplete(DataKeeper __instance, LevelData levelData, LevelCompletionInfo info, ref Grade grade, ref ushort reward, ref ushort challengeReward, ref bool shouldSave)
			{
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Invalid comparison between I4 and Unknown
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
				//IL_0104: Unknown result type (might be due to invalid IL or missing references)
				//IL_013b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0141: Unknown result type (might be due to invalid IL or missing references)
				//IL_0147: Unknown result type (might be due to invalid IL or missing references)
				int value;
				bool flag = Data.LevelNameToId.TryGetValue(levelData.Name, out value);
				if (flag && value == 35)
				{
					PluginMain.ArchipelagoHandler.Release();
				}
				else if ((int)grade < (int)PluginMain.ArchipelagoHandler.SlotData.GradeCheckThreshold)
				{
					grade = (Grade)(-1);
				}
				else if (flag)
				{
					PluginMain.ArchipelagoHandler.CheckLocation(256 + 16 * value);
					ushort[] challengesCompleted = info.ChallengesCompleted;
					if (challengesCompleted != null && challengesCompleted.Length > 0)
					{
						PluginMain.ArchipelagoHandler.CheckLocation(256 + 16 * value + 11);
					}
					SaveDataHandler.ArchipelagoSaveData.LevelCompletions[value] = true;
				}
				reward = 0;
				challengeReward = 0;
				LevelResults val = SystemHandler.Get<LevelResults>();
				LevelRecord val2 = null;
				bool flag2 = false;
				if (KeyWeExtensions.IsValidIndex<LevelRecord>(__instance.ActiveLevelIndex, (IEnumerable<LevelRecord>)__instance.profile.LevelRecords, (short)0))
				{
					val2 = __instance.Profile.LevelRecords[__instance.ActiveLevelIndex];
					flag2 = __instance.Profile.CurrentLevelIndex == __instance.ActiveLevelIndex;
				}
				val.StoreMatchResults(levelData, val2, grade, flag2, __instance.activeLevelIndex, (int)info.GoalsCleared, info.Duration, reward, (short)(-1), info.CollectibleID, challengeReward);
				__instance.Profile.LevelAttempted(val.LastResults.NewRecord || val.LastResults.NewGrade, (int)__instance.ActiveLevelIndex, grade, info.GoalsCleared, info.Duration, info.TutorialDuration);
				shouldSave = true;
				return false;
			}

			[HarmonyPatch("OvertimeShiftComplete")]
			[HarmonyPrefix]
			public static bool OnOvertimeShiftComplete(DataKeeper __instance, ref bool __result, ref OvertimeShiftLevelData levelData, ref LevelCompletionInfo info, ref Grade grade, ref ushort reward, ref ushort challengeReward, ref bool shouldSave)
			{
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Invalid comparison between I4 and Unknown
				//IL_0114: Unknown result type (might be due to invalid IL or missing references)
				//IL_0170: Unknown result type (might be due to invalid IL or missing references)
				//IL_0181: Expected I4, but got Unknown
				File.AppendAllText(SaveSystem.DataRoot + "Levels.txt", ((LevelData)levelData).Name ?? "");
				int value;
				if ((int)grade < (int)PluginMain.ArchipelagoHandler.SlotData.GradeCheckThreshold)
				{
					grade = (Grade)(-1);
				}
				else if (Data.OvertimeLevelNameToId.TryGetValue(((LevelData)levelData).Name, out value))
				{
					PluginMain.ArchipelagoHandler.CheckLocation(1024 + 4 * value);
					ushort[] challengesCompleted = info.ChallengesCompleted;
					if (challengesCompleted != null && challengesCompleted.Length > 0)
					{
						PluginMain.ArchipelagoHandler.CheckLocation(1024 + 4 * value + 2);
					}
					SaveDataHandler.ArchipelagoSaveData.OvertimeLevelCompletions[value] = true;
				}
				reward = 0;
				challengeReward = 0;
				OvertimeShiftRecord overtimeShiftRecord = __instance.Profile.GetOvertimeShiftRecord((ushort)levelData.ID);
				float num = overtimeShiftRecord.WearableProgress;
				float num2 = 0f;
				if ((int)grade > -1)
				{
					num2 = __instance.OvertimeShifts.WearableUnlockThreshold / 3f * (float)((int)grade + 1);
					num = overtimeShiftRecord.WearableProgress + num2;
					shouldSave = true;
					if ((double)num >= (double)__instance.OvertimeShifts.WearableUnlockThreshold && !__instance.Profile.IsUnlocked(levelData.WearableCategory, 0, (int)(ushort)levelData.WearableID))
					{
						if (Data.OvertimeLevelNameToId.TryGetValue(((LevelData)levelData).Name, out var value2))
						{
							PluginMain.ArchipelagoHandler.CheckLocation(1024 + 4 * value2 + 1);
						}
						Utility.UnsignedClamp(ref num, __instance.OvertimeShifts.WearableUnlockThreshold);
						__instance.Profile.AddNotification((Type)2, (int)levelData.WearableCategory, (int)levelData.WearableID);
					}
				}
				float num3 = overtimeShiftRecord.WearableProgress / __instance.OvertimeShifts.WearableUnlockThreshold;
				float num4 = num / __instance.OvertimeShifts.WearableUnlockThreshold;
				SystemHandler.Get<LevelResults>().StoreOvertimeResults((LevelData)(object)levelData, grade, (ushort)__instance.ActiveLevelIndex, info.GoalsCleared, info.Duration, reward, num3, num4, challengeReward);
				__result = __instance.Profile.OvertimeAttempted(__instance.ActiveLevelIndex, grade, (int)info.GoalsCleared, info.Duration, num2, __instance.OvertimeShifts.WearableUnlockThreshold);
				return false;
			}

			[HarmonyPatch("TournamentCourseComplete")]
			[HarmonyPrefix]
			public static bool OnTournamentCourseComplete(LevelData levelData, LevelCompletionInfo info, ref Grade grade, ref ushort reward, ref bool shouldSave)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Invalid comparison between I4 and Unknown
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				if ((int)grade < (int)PluginMain.ArchipelagoHandler.SlotData.GradeCheckThreshold)
				{
					grade = (Grade)(-1);
					reward = 0;
					return true;
				}
				int value;
				bool flag = Data.TournamentLevelNameToId.TryGetValue(levelData.Name, out value);
				if (flag)
				{
					for (int i = 0; i < 3; i++)
					{
						if (flag && (int)info.TournyChallengeStates[i] == 1)
						{
							PluginMain.ArchipelagoHandler.CheckLocation(1280 + 4 * value + 1 + i);
						}
					}
					PluginMain.ArchipelagoHandler.CheckLocation(1280 + 4 * value);
					SaveDataHandler.ArchipelagoSaveData.TournamentCourseCompletions[value] = true;
				}
				reward = 0;
				return true;
			}
		}

		[HarmonyPatch(typeof(ProfileData))]
		public class Collectible_Patch
		{
			[HarmonyPatch("HasCollectibleBeenFound")]
			[HarmonyPrefix]
			public static void HasCollectibleBeenFound(ushort id)
			{
				string name = SystemHandler.Get<DataKeeper>().CurrentLevelData.Name;
				if (Data.LevelNameToId.TryGetValue(name, out var value))
				{
					PluginMain.ArchipelagoHandler.CheckLocation(256 + 16 * value + 10);
				}
				SaveDataHandler.ArchipelagoSaveData.CollectiblesChecked[value] = true;
			}
		}

		[HarmonyPatch(typeof(MatchGameMode))]
		public class MatchGameMode_Patch
		{
			[HarmonyPatch("GoalCompleted")]
			[HarmonyPrefix]
			protected static void OnGoalCompleted(MatchGameMode __instance)
			{
				if (Data.LevelNameToId.TryGetValue(((GameMode)__instance).LevelData.Name, out var value))
				{
					PluginMain.ArchipelagoHandler.CheckLocation(256 + 16 * value + 1 + ((GameMode)__instance).NumGoalsCleared);
				}
			}
		}

		[HarmonyPatch(typeof(DropoffWickertideGM))]
		public class ResetCartTracker
		{
			[HarmonyPatch("StartNextGoal")]
			[HarmonyPostfix]
			private static void Reset()
			{
				_wickertideCartCount = 0;
			}
		}

		[HarmonyPatch(typeof(PuzzlePackage))]
		public class PuzzlePackage_EndReached_Patch
		{
			[HarmonyPatch("EndReached")]
			[HarmonyPostfix]
			private static void EndReached_Postfix(PuzzlePackage __instance)
			{
				if (__instance is WickertideOctoCart)
				{
					LevelData currentLevelData = SystemHandler.Get<DataKeeper>().CurrentLevelData;
					if (Data.LevelNameToId.TryGetValue(currentLevelData.Name, out var value))
					{
						PluginMain.ArchipelagoHandler.CheckLocation(256 + 16 * value + 1 + _wickertideCartCount);
					}
					_wickertideCartCount++;
				}
			}
		}

		private static int _wickertideCartCount;
	}
	public class LoginMenuHandler : MonoBehaviour
	{
		[HarmonyPatch(typeof(Menu))]
		public class Menu_Patch
		{
			[HarmonyPatch("Focus")]
			[HarmonyPrefix]
			public static bool Focus(Menu __instance, bool isFocused, GameObject control = null)
			{
				return !IsTyping;
			}
		}

		[HarmonyPatch(typeof(MessageWindow))]
		public class MessageWindow_Patch
		{
			[HarmonyPatch("Opened")]
			[HarmonyPostfix]
			public static void Opened_Postfix(MessageWindow __instance)
			{
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_009a: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
				//IL_00da: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
				//IL_0162: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
				//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
				if (!ArchipelagoHandler.IsConnected && !ArchipelagoHandler.IsConnecting)
				{
					Transform transform = ((Component)__instance.textDisplay).gameObject.transform;
					__instance.textDisplay.text = "";
					((Component)((Menu)__instance).canvas).GetComponentInChildren<TMP_Text>().text = "Archipelago";
					((Component)((DialogBox)__instance).loneYupButton).GetComponentInChildren<TMP_Text>().text = "Connect";
					TextMeshProUGUI componentInChildren = ((Component)((Menu)__instance).canvas).GetComponentInChildren<TextMeshProUGUI>();
					AddLabel(transform, "Server", new Vector3(-2.15f, 1.5f, 0f), (TMP_Text)(object)componentInChildren);
					AddLabel(transform, "Port", new Vector3(-2.38f, 0.75f, 0f), (TMP_Text)(object)componentInChildren);
					AddLabel(transform, "Slot", new Vector3(-2.45f, 0f, 0f), (TMP_Text)(object)componentInChildren);
					AddLabel(transform, "Password", new Vector3(-2f, -0.75f, 0f), (TMP_Text)(object)componentInChildren);
					TMP_InputField val = AddInputField(transform, "ServerInput", new Vector3(1f, 1.5f, 0f), (TMP_Text)(object)componentInChildren, delegate(string text)
					{
						_server = text;
					});
					((Menu)__instance).FirstSelected = ((Component)val).gameObject;
					EventSystem.current.SetSelectedGameObject(((Component)val).gameObject);
					val.text = _server;
					AddInputField(transform, "PortInput", new Vector3(1f, 0.75f, 0f), (TMP_Text)(object)componentInChildren, delegate(string text)
					{
						ushort.TryParse(text, out _port);
					}).text = _port.ToString();
					AddInputField(transform, "SlotInput", new Vector3(1f, 0f, 0f), (TMP_Text)(object)componentInChildren, delegate(string text)
					{
						_slotName = text;
					}).text = _slotName;
					AddInputField(transform, "PasswordInput", new Vector3(1f, -0.75f, 0f), (TMP_Text)(object)componentInChildren, delegate(string text)
					{
						_password = text;
					}, isPassword: true).text = _password;
				}
			}

			private static void AddLabel(Transform reference, string label, Vector3 localPosition, TMP_Text template)
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				GameObject val = new GameObject("AP " + label + " Label");
				val.transform.SetParent(reference, false);
				TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
				((TMP_Text)val2).text = label;
				SetTextSettings(template, (TMP_Text)(object)val2);
				((Transform)((Component)val2).GetComponent<RectTransform>()).localPosition = localPosition;
			}

			private static TMP_InputField AddInputField(Transform parent, string name, Vector3 localPosition, TMP_Text template, Action<string> onValueChanged, bool isPassword = false)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Expected O, but got Unknown
				//IL_002c: 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_0058: 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_0087: Expected O, but got Unknown
				//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
				//IL_00db: Unknown result type (might be due to invalid IL or missing references)
				//IL_014d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0152: Unknown result type (might be due to invalid IL or missing references)
				//IL_0199: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
				GameObject val = new GameObject(name);
				val.transform.SetParent(parent, false);
				val.AddComponent<CanvasRenderer>();
				RectTransform obj = val.AddComponent<RectTransform>();
				obj.sizeDelta = new Vector2(4f, 0.5f);
				((Transform)obj).localPosition = localPosition;
				Image val2 = val.AddComponent<Image>();
				((Graphic)val2).color = new Color(0f, 0f, 0f, 0.4f);
				TMP_InputField val3 = val.AddComponent<TMP_InputField>();
				GameObject val4 = new GameObject("TextViewport", new Type[1] { typeof(RectTransform) });
				val4.transform.SetParent(val.transform, false);
				RectTransform component = val4.GetComponent<RectTransform>();
				component.anchorMin = new Vector2(0f, 0f);
				component.anchorMax = new Vector2(1f, 1f);
				component.offsetMin = Vector2.zero;
				component.offsetMax = Vector2.zero;
				val3.textViewport = component;
				((Selectable)val3).targetGraphic = (Graphic)(object)val2;
				((UnityEvent<string>)(object)val3.onSelect).AddListener((UnityAction<string>)delegate
				{
					IsTyping = true;
				});
				((UnityEvent<string>)(object)val3.onDeselect).AddListener((UnityAction<string>)delegate
				{
					IsTyping = false;
				});
				GameObject val5 = new GameObject("Text");
				val5.transform.SetParent(val4.transform, false);
				TextMeshProUGUI val6 = val5.AddComponent<TextMeshProUGUI>();
				SetTextSettings(template, (TMP_Text)(object)val6);
				((TMP_Text)val6).enableWordWrapping = false;
				((TMP_Text)val6).alignment = (TextAlignmentOptions)4097;
				RectTransform component2 = ((Component)val6).GetComponent<RectTransform>();
				component2.anchorMin = new Vector2(0.025f, 0f);
				component2.anchorMax = new Vector2(0.975f, 1f);
				component2.offsetMin = Vector2.zero;
				component2.offsetMax = Vector2.zero;
				val3.textComponent = (TMP_Text)(object)val6;
				if (isPassword)
				{
					val3.inputType = (InputType)2;
					val3.contentType = (ContentType)7;
				}
				else
				{
					val3.contentType = (ContentType)0;
				}
				((UnityEvent<string>)(object)val3.onValueChanged).AddListener((UnityAction<string>)onValueChanged.Invoke);
				return val3;
			}

			private static void SetTextSettings(TMP_Text template, TMP_Text text)
			{
				//IL_0019: 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)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Expected O, but got Unknown
				text.font = template.font;
				text.fontSize = 0.35f;
				((Graphic)text).color = ((Graphic)template).color;
				text.alignment = template.alignment;
				text.enableWordWrapping = template.enableWordWrapping;
				text.margin = template.margin;
				text.fontMaterial = new Material(template.fontMaterial);
			}

			[HarmonyPatch("OnYupSelected")]
			[HarmonyPrefix]
			public static bool Yup_Prefix(MessageWindow __instance)
			{
				if (ArchipelagoHandler.IsConnected)
				{
					return true;
				}
				ArchipelagoHandler.OnConnect = (Action)Delegate.Combine(ArchipelagoHandler.OnConnect, (Action)delegate
				{
					((Menu)__instance).CloseAnimationStart();
				});
				Connect();
				return false;
			}
		}

		[HarmonyPatch(typeof(StartScreen))]
		public class StartScreen_Patch
		{
			[HarmonyPatch(typeof(StartScreen), "Opened")]
			[HarmonyPostfix]
			private static void Postfix(StartScreen __instance)
			{
				if (!ArchipelagoHandler.IsConnected && !ArchipelagoHandler.IsConnecting)
				{
					MessageWindow val = Resources.FindObjectsOfTypeAll<MessageWindow>().FirstOrDefault();
					messageWindow = SystemHandler.Get<UIController>().OpenMenu<MessageWindow>(val, (Action<MessageWindow>)delegate
					{
					}, false, (Menu)null);
				}
			}

			[HarmonyPatch("GetInput")]
			[HarmonyPrefix]
			private static bool OnGetInput()
			{
				return false;
			}
		}

		private static MessageWindow messageWindow;

		private static string _password = "";

		private static ushort _port;

		private static string _server = "archipelago.gg";

		private static bool _showLogin;

		private static string _slotName = "";

		private static string _status = "";

		public static bool IsTyping;

		private GameObject _introClipboard;

		private Rect _windowRect = new Rect(100f, 100f, 600f, 500f);

		private void Start()
		{
			((MonoBehaviour)this).StartCoroutine(CheckProfileSelect());
			ConnectionInfoHandler.Load(ref _server, ref _port, ref _slotName, ref _password);
		}

		private IEnumerator CheckProfileSelect()
		{
			while (true)
			{
				yield return (object)new WaitForSeconds(0.5f);
				_introClipboard = GameObject.Find("/Director/Attract/Clipboard");
				if ((Object)(object)_introClipboard == (Object)null || _showLogin)
				{
					yield return null;
				}
				_showLogin = true;
				Object.Destroy((Object)(object)_introClipboard);
			}
		}

		private static void Connect()
		{
			ConnectionInfoHandler.Save(_server, _port, _slotName, _password);
			PluginMain.ArchipelagoHandler = new ArchipelagoHandler(_server, _port, _slotName, _password);
			PluginMain.ArchipelagoHandler.InitConnect();
			_status = "Connecting...";
		}
	}
	[BepInPlugin("KeyWeAPClient", "KeyWe AP Client", "1.0")]
	public class PluginMain : BaseUnityPlugin
	{
		public static LoginMenuHandler LoginHandler;

		public static SaveDataHandler SaveDataHandler;

		public static ArchipelagoHandler ArchipelagoHandler;

		public static ItemHandler ItemHandler;

		public static LocationHandler LocationHandler;

		public static GameHandler GameHandler;

		private readonly Harmony _harmony = new Harmony("KeyWeAPClient");

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_002a: 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)
			//IL_003f: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			_harmony.PatchAll();
			GameObject val = new GameObject("ArchipelagoLoginHandler");
			LoginHandler = val.AddComponent<LoginMenuHandler>();
			Object.DontDestroyOnLoad((Object)val);
			GameObject val2 = new GameObject("ArchipelagoSaveDataHandler");
			SaveDataHandler = val2.AddComponent<SaveDataHandler>();
			Object.DontDestroyOnLoad((Object)val2);
			GameObject val3 = new GameObject("ArchipelagoGameHandler");
			GameHandler = val3.AddComponent<GameHandler>();
			Object.DontDestroyOnLoad((Object)val3);
			ItemHandler = new ItemHandler();
			LocationHandler = new LocationHandler();
			APConsole.Create();
			APConsole.Instance.Log("Press F7 to toggle the archipelago log.");
		}

		private void Start()
		{
			Cursor.visible = true;
			((Behaviour)ControllerVibrationHandler.Instance).enabled = false;
		}
	}
	public class CustomSaveData
	{
		public int ItemIndex = 1;

		public float WalkSpeed = 10f;

		public float DashForce = 20f;

		public float SwimSpeed = 5f;

		public float JumpHeight = 22f;

		public float RespawnFallMoveSpeed = 5f;

		public float RespawnFallSpeed = 4f;

		public float ChirpCooldown = 0.6f;

		public float PeckCooldown = 0.6f;

		public float DashCooldown = 0.6f;

		public Dictionary<int, bool> WeeksUnlocked { get; set; } = new Dictionary<int, bool>
		{
			{ 0, false },
			{ 1, false },
			{ 2, false },
			{ 3, false },
			{ 4, false },
			{ 5, false },
			{ 6, false },
			{ 7, false },
			{ 8, false }
		};


		public bool OvertimeSummerUnlocked { get; set; }

		public bool OvertimeFallUnlocked { get; set; }

		public bool OvertimeWinterUnlocked { get; set; }

		public bool TournamentUnlocked { get; set; }

		public Dictionary<int, bool> Collectibles { get; set; } = new Dictionary<int, bool>
		{
			{ 0, false },
			{ 1, false },
			{ 2, false },
			{ 3, false },
			{ 4, false },
			{ 5, false },
			{ 6, false },
			{ 7, false },
			{ 8, false },
			{ 9, false },
			{ 10, false },
			{ 11, false },
			{ 12, false },
			{ 13, false },
			{ 14, false }
		};


		public Dictionary<int, bool> LevelCompletions { get; set; } = new Dictionary<int, bool>
		{
			{ 0, false },
			{ 1, false },
			{ 2, false },
			{ 3, false },
			{ 4, false },
			{ 5, false },
			{ 6, false },
			{ 7, false },
			{ 8, false },
			{ 9, false },
			{ 10, false },
			{ 11, false },
			{ 12, false },
			{ 13, false },
			{ 14, false },
			{ 15, false },
			{ 16, false },
			{ 17, false },
			{ 18, false },
			{ 19, false },
			{ 20, false },
			{ 21, false },
			{ 22, false },
			{ 23, false },
			{ 24, false },
			{ 25, false },
			{ 26, false },
			{ 27, false },
			{ 28, false },
			{ 29, false },
			{ 30, false },
			{ 31, false },
			{ 32, false },
			{ 33, false },
			{ 34, false },
			{ 35, false }
		};


		public Dictionary<int, bool> OvertimeLevelCompletions { get; set; } = new Dictionary<int, bool>
		{
			{ 0, false },
			{ 1, false },
			{ 2, false },
			{ 3, false },
			{ 4, false },
			{ 5, false },
			{ 6, false },
			{ 7, false },
			{ 8, false }
		};


		public Dictionary<int, bool> TournamentCourseCompletions { get; set; } = new Dictionary<int, bool>
		{
			{ 0, false },
			{ 1, false },
			{ 2, false }
		};


		public Dictionary<int, bool> CollectiblesChecked { get; set; } = new Dictionary<int, bool>
		{
			{ 0, false },
			{ 1, false },
			{ 2, false },
			{ 3, false },
			{ 4, false },
			{ 5, false },
			{ 6, false },
			{ 7, false },
			{ 8, false },
			{ 9, false },
			{ 10, false },
			{ 11, false },
			{ 12, false },
			{ 13, false },
			{ 14, false }
		};

	}
	public class SaveDataHandler : MonoBehaviour
	{
		[HarmonyPatch(typeof(SaveSystem))]
		private class DataRootPatch
		{
			[HarmonyPatch(/*Could not decode attribute arguments.*/)]
			[HarmonyPrefix]
			private static bool OnGetDataRoot(ref string __result)
			{
				string text = Path.Combine(Directory.GetParent(Application.dataPath).FullName, "ArchipelagoSaves/");
				if (!Directory.Exists(text))
				{
					Directory.CreateDirectory(text);
				}
				__result = text;
				return false;
			}

			[HarmonyPatch("LoadProfile")]
			[HarmonyPrefix]
			public static bool LoadProfile(ref ProfileData __result, int index)
			{
				ProfileData val = null;
				string path = SaveSystem.DataRoot + "APProfile" + _seed + _slot + ".kiwi";
				if (File.Exists(path))
				{
					ArchipelagoSaveData = JsonConvert.DeserializeObject<CustomSaveData>(File.ReadAllText(SaveSystem.DataRoot + "APSave" + _seed + _slot + ".json"));
					try
					{
						using BinaryReader binaryReader = new BinaryReader(File.Open(path, FileMode.Open));
						val = JsonUtility.FromJson<ProfileData>(StringEncryption.Decrypt(binaryReader.ReadString(), "TallKikiIsCursed_967f2d41-a0a0-42fa-a7ed-79b2c5977569"));
					}
					catch (Exception arg)
					{
						Debug.LogError((object)$"[KEYWE][SaveSystem] LoadData - Exception thrown while loading data:\n{arg}");
					}
				}
				__result = val;
				return false;
			}

			[HarmonyPatch("SaveProfile")]
			[HarmonyPrefix]
			public static bool SaveProfile(ProfileData profile, string profileName = "Profile")
			{
				string contents = JsonConvert.SerializeObject((object)ArchipelagoSaveData);
				File.WriteAllText(SaveSystem.DataRoot + "APSave" + _seed + _slot + ".json", contents);
				SaveSystem.TryCreateFolderDemo();
				string path = SaveSystem.DataRoot + "APProfile" + _seed + _slot + ".kiwi";
				if (profile == null)
				{
					return false;
				}
				try
				{
					using (BinaryWriter binaryWriter = new BinaryWriter(File.Open(path, FileMode.Create)))
					{
						string value = StringEncryption.Encrypt(JsonUtility.ToJson((object)profile), "TallKikiIsCursed_967f2d41-a0a0-42fa-a7ed-79b2c5977569");
						binaryWriter.Write(value);
					}
					SaveSystem.BackupSave(profile);
				}
				catch (Exception ex)
				{
					Debug.LogError((object)ex.Message);
				}
				return false;
			}
		}

		private static DataKeeper dataKeeper;

		private static string _seed;

		private static string _slot;

		public static CustomSaveData ArchipelagoSaveData;

		private void Start()
		{
			dataKeeper = SystemHandler.Get<DataKeeper>();
		}

		public void LoadProfile(string seed, string slot)
		{
			_seed = seed;
			_slot = slot;
			ushort num = (ushort)(ulong.Parse(seed.Substring(1, 15)) % 65535);
			((SystemBase)dataKeeper).Initialize();
			ProfileData val = dataKeeper.LoadProfile((int)num);
			if (val == null)
			{
				ArchipelagoSaveData = new CustomSaveData();
				val = dataKeeper.CreateProfile(num, SystemHandler.Get<StatTrackingSystem>().GetNewPlaythroughID());
				val.MarkProgress((ProgressFlag)1);
				val.MarkProgress((ProgressFlag)64);
				val.MarkProgress((ProgressFlag)512);
				val.MarkProgress((ProgressFlag)4);
				val.MarkProgress((ProgressFlag)2);
				val.MarkProgress((ProgressFlag)2048);
				val.MarkProgress((ProgressFlag)32);
				val.MarkProgress((ProgressFlag)4096);
				val.MarkProgress((ProgressFlag)1024);
				val.MarkProgress((ProgressFlag)16);
				val.MarkProgress((ProgressFlag)8);
				val.CurrentLevelIndex = 35;
			}
			dataKeeper.SaveProfile(val);
			dataKeeper.HasSelectedSaveProfile = true;
			dataKeeper.SelectProfile(val);
			((OvermapMenuOption)Object.FindObjectOfType<OvermapSwitchProfile>()).RefreshScene();
		}

		public void UnlockWeek(int weekIndex)
		{
			ArchipelagoSaveData.WeeksUnlocked[weekIndex] = true;
		}
	}
	public class ShopHandler
	{
		[HarmonyPatch(typeof(Wardrobe))]
		public class Wardrobe_Patch
		{
			[HarmonyPatch("ShowDisplayHalves")]
			[HarmonyPostfix]
			public static void OnShowDisplayHalves(Wardrobe __instance)
			{
				KeyWeExtensions.SetActive((MonoBehaviour)(object)__instance.itemDisplays[1], false);
			}
		}

		[HarmonyPatch(typeof(PlayerItemDisplay))]
		public class PlayerItemDisplay_Patch
		{
			public static void AddCategory(PlayerItemDisplay __instance, string categoryName, Categories category, int index)
			{
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				MethodInfo methodInfo = AccessTools.Method(typeof(CategoryDisplay), "add_OnSelected", (Type[])null, (Type[])null);
				MethodInfo methodInfo2 = AccessTools.Method(typeof(CategoryDisplay), "add_OnHighlighted", (Type[])null, (Type[])null);
				CategoryDisplay val = Object.Instantiate<CategoryDisplay>(__instance.categoryDisplayPrefab, __instance.categoryParent);
				__instance.categories[index] = val;
				val.Init(categoryName, category);
				Delegate @delegate = Delegate.CreateDelegate(methodInfo.GetParameters()[0].ParameterType, __instance, "Category_OnSelected");
				Delegate delegate2 = Delegate.CreateDelegate(methodInfo2.GetParameters()[0].ParameterType, __instance, "Category_OnHighlighted");
				methodInfo.Invoke(val, new object[1] { @delegate });
				methodInfo2.Invoke(val, new object[1] { delegate2 });
			}

			[HarmonyPatch("PopulateCategoryUI")]
			[HarmonyPrefix]
			public static bool OnPopulateCategoryUI(PlayerItemDisplay __instance)
			{
				__instance.categories = (CategoryDisplay[])(object)new CategoryDisplay[2];
				AddCategory(__instance, "Stamp Shop", (Categories)2, 0);
				AddCategory(__instance, "Coin Shop", (Categories)0, 1);
				return false;
			}
		}

		[HarmonyPatch(typeof(CategoryDisplay))]
		public class CategoryDisplay_Patch
		{
			[HarmonyPatch("Init")]
			[HarmonyPrefix]
			public static bool Init(CategoryDisplay __instance, string text, Categories category)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Invalid comparison between Unknown and I4
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0004: Unknown result type (might be due to invalid IL or missing references)
				if ((int)category != 2 && (int)category != 0)
				{
					KeyWeExtensions.SetActive((MonoBehaviour)(object)__instance, false);
					return false;
				}
				__instance.CategoryName = (((int)category == 0) ? "Coin Shop" : "Stamp Shop");
				__instance.Category = (Categories)(-1);
				((TMP_Text)__instance.textMesh).text = __instance.CategoryName;
				return false;
			}
		}
	}
	public class SlotData
	{
		public readonly int RequiredCollectibleChecks;

		public readonly int RequiredCollectibles;

		public readonly int RequiredLevelCompletions;

		public readonly int RequiredLevelCompletionsPerWeek;

		public readonly int RequiredOvertimeCompletions;

		public readonly int RequiredTournamentCompletions;

		public readonly bool TournamentIncluded;

		public readonly bool OvertimeIncluded;

		public bool DeathLink;

		public Grade GradeCheckThreshold;

		public SlotData(Dictionary<string, object> slotDict)
		{
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			foreach (KeyValuePair<string, object> item in slotDict)
			{
				Console.WriteLine($"{item.Key} {item.Value}");
			}
			TournamentIncluded = (long)slotDict["TournamentIncluded"] == 1;
			OvertimeIncluded = (long)slotDict["TournamentIncluded"] == 1;
			RequiredLevelCompletions = (int)(long)slotDict["RequiredLevelCompletions"];
			RequiredLevelCompletionsPerWeek = (int)(long)slotDict["RequiredLevelCompletionsPerWeek"];
			RequiredCollectibles = (int)(long)slotDict["RequiredCollectibles"];
			RequiredCollectibleChecks = (int)(long)slotDict["RequiredCollectibleChecks"];
			RequiredOvertimeCompletions = (int)(long)slotDict["RequiredOvertimeCompletions"];
			RequiredTournamentCompletions = (int)(long)slotDict["RequiredTournamentCompletions"];
			int num = (int)(long)slotDict["StartingWeek"];
			GradeCheckThreshold = (Grade)((int)(long)slotDict["LevelCompletionCheckThreshold"] switch
			{
				1 => 0, 
				2 => 1, 
				3 => 2, 
				_ => GradeCheckThreshold, 
			});
			DeathLink = (long)slotDict["DeathLink"] == 1;
			if (DeathLink)
			{
				PluginMain.ArchipelagoHandler.UpdateTags(new List<string>(1) { "DeathLink" });
			}
			SaveDataHandler.ArchipelagoSaveData.WeeksUnlocked[num - 1] = true;
			if (!SystemHandler.Get<DataKeeper>().Profile.CheckProgress((ProgressFlag)8192) && TournamentIncluded)
			{
				APConsole.Instance.Log("Warning: You do not own the Telepost Tournament DLC but have its checks enabled.");
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "KeyWe_AP_Client";

		public const string PLUGIN_NAME = "KeyWe Archipelago Client";

		public const string PLUGIN_VERSION = "0.1.0";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		internal IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}