Decompiled source of TCG AP Client v1.1.1

plugins/Archipelago.MultiClient.Net.dll

Decompiled 2 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 © 2026")]
[assembly: AssemblyDescription("A client library for use with .NET based prog-langs for interfacing with Archipelago hosts.")]
[assembly: AssemblyFileVersion("6.7.1.0")]
[assembly: AssemblyInformationalVersion("6.7.1+0c57591db30f2497b0b4fef87164aa2bbe2e51b2")]
[assembly: AssemblyProduct("Archipelago.MultiClient.Net")]
[assembly: AssemblyTitle("Archipelago.MultiClient.Net")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/ArchipelagoMW/Archipelago.MultiClient.Net")]
[assembly: AssemblyVersion("6.7.1.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>());
	

plugins/TCG_AP_Client.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using ApClient;
using ApClient.Archipelago;
using ApClient.Archipelago.Mapping;
using ApClient.Patches.Functionality;
using ApClient.UI;
using ApClient.assets;
using ApClient.data;
using ApClient.mapping;
using ApClient.ui;
using Archipelago.MultiClient.Net;
using Archipelago.MultiClient.Net.BounceFeatures.DeathLink;
using Archipelago.MultiClient.Net.Enums;
using Archipelago.MultiClient.Net.Helpers;
using Archipelago.MultiClient.Net.MessageLog.Messages;
using Archipelago.MultiClient.Net.MessageLog.Parts;
using Archipelago.MultiClient.Net.Models;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using I2.Loc;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("TCG_AP_Client")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+5087665129d1ecb89bd91118021f44a2322c01ac")]
[assembly: AssemblyProduct("TCG AP Client")]
[assembly: AssemblyTitle("TCG_AP_Client")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.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 UIInfoPanel : MonoBehaviour
{
	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static UnityAction <>9__1_0;

		public static UnityAction <>9__1_1;

		public static UnityAction <>9__1_2;

		public static Func<Transform, bool> <>9__1_3;

		public static Func<Transform, bool> <>9__1_4;

		public static Func<Transform, bool> <>9__1_5;

		public static Func<Transform, bool> <>9__1_6;

		public static Func<Transform, bool> <>9__1_7;

		public static Func<Transform, bool> <>9__1_8;

		public static Func<Transform, bool> <>9__1_9;

		public static Func<Transform, bool> <>9__1_10;

		public static Func<Transform, bool> <>9__1_11;

		public static Func<CompiledAchievement, bool> <>9__100_0;

		public static Func<CompiledAchievement, int> <>9__100_1;

		internal void <setInstance>b__1_0()
		{
			Instance.UpdateAchievementList(Instance.cardOpenItems);
			Instance.currentCardItems = Instance.cardOpenItems;
		}

		internal void <setInstance>b__1_1()
		{
			Instance.UpdateAchievementList(Instance.cardSellItems);
			Instance.currentCardItems = Instance.cardSellItems;
		}

		internal void <setInstance>b__1_2()
		{
			Instance.UpdateAchievementList(Instance.cardGradeItems);
			Instance.currentCardItems = Instance.cardGradeItems;
		}

		internal bool <setInstance>b__1_3(Transform t)
		{
			return ((Object)t).name == "AchievementContent";
		}

		internal bool <setInstance>b__1_4(Transform t)
		{
			return ((Object)t).name == "ProductContent";
		}

		internal bool <setInstance>b__1_5(Transform t)
		{
			return ((Object)t).name == "CollectionGoal";
		}

		internal bool <setInstance>b__1_6(Transform t)
		{
			return ((Object)t).name == "LevelGoal";
		}

		internal bool <setInstance>b__1_7(Transform t)
		{
			return ((Object)t).name == "GhostGoal";
		}

		internal bool <setInstance>b__1_8(Transform t)
		{
			return ((Object)t).name == "Generic Group";
		}

		internal bool <setInstance>b__1_9(Transform t)
		{
			return ((Object)t).name == "Formats1";
		}

		internal bool <setInstance>b__1_10(Transform t)
		{
			return ((Object)t).name == "Formats2";
		}

		internal bool <setInstance>b__1_11(Transform t)
		{
			return ((Object)t).name == "Formats3";
		}

		internal bool <UpdateAchievementList>b__100_0(CompiledAchievement a)
		{
			return a.IsHinted;
		}

		internal int <UpdateAchievementList>b__100_1(CompiledAchievement a)
		{
			if (a.completed)
			{
				return 2;
			}
			if (a.Available)
			{
				return 0;
			}
			return 1;
		}
	}

	[CompilerGenerated]
	private sealed class <DelayedHide>d__89 : IEnumerator<object>, IEnumerator, IDisposable
	{
		private int <>1__state;

		private object <>2__current;

		public float delay;

		public bool visable;

		public UIInfoPanel <>4__this;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <DelayedHide>d__89(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(delay);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				if (!<>4__this.showGUI)
				{
					<>4__this.window.SetActive(false);
				}
				return false;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	private static UIInfoPanel Instance;

	public GameObject window;

	private bool showGUI = true;

	public TextMeshProUGUI levelMaxText;

	public TextMeshProUGUI storedXPText;

	public TextMeshProUGUI licensesText;

	public Transform achievementContent;

	public Transform productContent;

	public Transform CollectionGoalUI;

	public Transform LevelGoalUI;

	public Transform GhostGoalUI;

	public TextMeshProUGUI percentCollected;

	public TextMeshProUGUI percentGoal;

	public TextMeshProUGUI levelGoalText;

	public TextMeshProUGUI currentGhostsSold;

	public TextMeshProUGUI ghostGoalText;

	public GameObject achievementPrefab;

	public GameObject productPrefab;

	private Button cardOpenButton;

	private Button cardSellButton;

	private Button cardGradeButton;

	public TextMeshProUGUI basicCount;

	public TextMeshProUGUI rareCount;

	public TextMeshProUGUI epicCount;

	public TextMeshProUGUI legendaryCount;

	public TextMeshProUGUI destinyBasicCount;

	public TextMeshProUGUI destinyRareCount;

	public TextMeshProUGUI destinyEpicCount;

	public TextMeshProUGUI destinyLegendaryCount;

	public Transform GenericEventGroup;

	public Transform Formats1;

	public Transform Formats2;

	public Transform Formats3;

	public Image GenericImage;

	public Image StandardImage;

	public Image PauperImage;

	public Image FireImage;

	public Image EarthImage;

	public Image WaterImage;

	public Image WindImage;

	public Image FirstEdImage;

	public Image SilverImage;

	public Image GoldImage;

	public Image EXImage;

	public Image FullArtImage;

	public Image FoilImage;

	public TextMeshProUGUI GenericCount;

	public TextMeshProUGUI StandardCount;

	public TextMeshProUGUI PauperCount;

	public TextMeshProUGUI FireCount;

	public TextMeshProUGUI EarthCount;

	public TextMeshProUGUI WaterCount;

	public TextMeshProUGUI WindCount;

	public TextMeshProUGUI FirstEdCount;

	public TextMeshProUGUI SilverCount;

	public TextMeshProUGUI GoldCount;

	public TextMeshProUGUI EXCount;

	public TextMeshProUGUI FullArtCount;

	public TextMeshProUGUI FoilCount;

	public TextMeshProUGUI GenericTotal;

	public TextMeshProUGUI StandardTotal;

	public TextMeshProUGUI PauperTotal;

	public TextMeshProUGUI FireTotal;

	public TextMeshProUGUI EarthTotal;

	public TextMeshProUGUI WaterTotal;

	public TextMeshProUGUI WindTotal;

	public TextMeshProUGUI FirstEdTotal;

	public TextMeshProUGUI SilverTotal;

	public TextMeshProUGUI GoldTotal;

	public TextMeshProUGUI EXTotal;

	public TextMeshProUGUI FullArtTotal;

	public TextMeshProUGUI FoilTotal;

	public TextMeshProUGUI basicCountTotal;

	public TextMeshProUGUI rareCountTotal;

	public TextMeshProUGUI epicCountTotal;

	public TextMeshProUGUI legendaryCountTotal;

	public TextMeshProUGUI destinyBasicCountTotal;

	public TextMeshProUGUI destinyRareCountTotal;

	public TextMeshProUGUI destinyEpicCountTotal;

	public TextMeshProUGUI destinyLegendaryCountTotal;

	public List<CompiledAchievement> cardOpenItems;

	public List<CompiledAchievement> cardSellItems;

	public List<CompiledAchievement> cardGradeItems;

	public List<CompiledAchievement> currentCardItems;

	private Color formatAvailableColor = new Color(0.164f, 0.164f, 0.55f, 0.4f);

	public static void setInstance(UIInfoPanel instance, GameObject apinfoobject, GameObject achievementPrefab, GameObject productPrefab, Dictionary<string, List<CompiledAchievement>> achievements)
	{
		//IL_1142: Unknown result type (might be due to invalid IL or missing references)
		//IL_1147: Unknown result type (might be due to invalid IL or missing references)
		//IL_114d: Expected O, but got Unknown
		//IL_1176: Unknown result type (might be due to invalid IL or missing references)
		//IL_117b: Unknown result type (might be due to invalid IL or missing references)
		//IL_1181: Expected O, but got Unknown
		//IL_11aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_11af: Unknown result type (might be due to invalid IL or missing references)
		//IL_11b5: Expected O, but got Unknown
		Instance = instance;
		Instance.window = apinfoobject;
		Instance.achievementPrefab = achievementPrefab;
		Instance.productPrefab = productPrefab;
		int num = 0;
		if (Plugin.ArchipelagoHandler.slotData.CardSanity > 0)
		{
			switch (Plugin.ArchipelagoHandler.slotData.CardOpeningCheckDifficulty)
			{
			case 0:
				num = 12;
				break;
			case 1:
				num = 1;
				break;
			case 2:
				num = 3;
				break;
			case 3:
				num = 4;
				break;
			case 4:
				num = 6;
				break;
			}
			if (num != 12 && Plugin.ArchipelagoHandler.slotData.CardSanity == 2)
			{
				num *= 2;
			}
		}
		else
		{
			num = 12;
		}
		TextMeshProUGUI[] componentsInChildren = apinfoobject.GetComponentsInChildren<TextMeshProUGUI>(true);
		foreach (TextMeshProUGUI val in componentsInChildren)
		{
			switch (((Object)val).name)
			{
			case "MaxLevel":
				Instance.levelMaxText = val;
				break;
			case "StoredXp":
				Instance.storedXPText = val;
				break;
			case "LicensesRequired":
				Instance.licensesText = val;
				break;
			case "PercentCollected":
				Instance.percentCollected = val;
				break;
			case "PercentGoal":
				Instance.percentGoal = val;
				break;
			case "LevelGoalText":
				Instance.levelGoalText = val;
				break;
			case "CurrentGhostsSold":
				Instance.currentGhostsSold = val;
				break;
			case "GhostGoalText":
				Instance.ghostGoalText = val;
				break;
			case "Basic Count":
				Instance.basicCount = val;
				Instance.setCardCollectionCount((ECollectionPackType)0);
				break;
			case "Rare Count":
				Instance.rareCount = val;
				Instance.setCardCollectionCount((ECollectionPackType)1);
				break;
			case "Epic Count":
				Instance.epicCount = val;
				Instance.setCardCollectionCount((ECollectionPackType)2);
				break;
			case "Legendary Count":
				Instance.legendaryCount = val;
				Instance.setCardCollectionCount((ECollectionPackType)3);
				break;
			case "Destiny Basic Count":
				Instance.destinyBasicCount = val;
				Instance.setCardCollectionCount((ECollectionPackType)4);
				break;
			case "Destiny Rare Count":
				Instance.destinyRareCount = val;
				Instance.setCardCollectionCount((ECollectionPackType)5);
				break;
			case "Destiny Epic Count":
				Instance.destinyEpicCount = val;
				Instance.setCardCollectionCount((ECollectionPackType)6);
				break;
			case "Destiny Legendary Count":
				Instance.destinyLegendaryCount = val;
				Instance.setCardCollectionCount((ECollectionPackType)7);
				break;
			case "Generic Count":
				Instance.GenericCount = val;
				break;
			case "Standard Count":
				Instance.StandardCount = val;
				break;
			case "Pauper Count":
				Instance.PauperCount = val;
				break;
			case "Fire Count":
				Instance.FireCount = val;
				break;
			case "Earth Count":
				Instance.EarthCount = val;
				break;
			case "Water Count":
				Instance.WaterCount = val;
				break;
			case "Wind Count":
				Instance.WindCount = val;
				break;
			case "1st Ed Count":
				Instance.FirstEdCount = val;
				break;
			case "Silver Count":
				Instance.SilverCount = val;
				break;
			case "Gold Count":
				Instance.GoldCount = val;
				break;
			case "EX Count":
				Instance.EXCount = val;
				break;
			case "Full Art Count":
				Instance.FullArtCount = val;
				break;
			case "Foil Count":
				Instance.FoilCount = val;
				break;
			case "Generic Total":
				Instance.GenericTotal = val;
				break;
			case "Standard Total":
				Instance.StandardTotal = val;
				break;
			case "Pauper Total":
				Instance.PauperTotal = val;
				break;
			case "Fire Total":
				Instance.FireTotal = val;
				break;
			case "Earth Total":
				Instance.EarthTotal = val;
				break;
			case "Water Total":
				Instance.WaterTotal = val;
				break;
			case "Wind Total":
				Instance.WindTotal = val;
				break;
			case "1st Ed Total":
				Instance.FirstEdTotal = val;
				break;
			case "Silver Total":
				Instance.SilverTotal = val;
				break;
			case "Gold Total":
				Instance.GoldTotal = val;
				break;
			case "EX Total":
				Instance.EXTotal = val;
				break;
			case "Full Art Total":
				Instance.FullArtTotal = val;
				break;
			case "Foil Total":
				Instance.FoilTotal = val;
				break;
			case "Basic Total":
				Instance.basicCountTotal = val;
				((TMP_Text)Instance.basicCountTotal).text = $"{27 * num}";
				break;
			case "Rare Total":
				Instance.rareCountTotal = val;
				((TMP_Text)Instance.rareCountTotal).text = $"{34 * num}";
				break;
			case "Epic Total":
				Instance.epicCountTotal = val;
				((TMP_Text)Instance.epicCountTotal).text = $"{34 * num}";
				break;
			case "Legendary Total":
				Instance.legendaryCountTotal = val;
				((TMP_Text)Instance.legendaryCountTotal).text = $"{26 * num}";
				break;
			case "Destiny Basic Total":
				Instance.destinyBasicCountTotal = val;
				((TMP_Text)Instance.destinyBasicCountTotal).text = $"{27 * num}";
				break;
			case "Destiny Rare Total":
				Instance.destinyRareCountTotal = val;
				((TMP_Text)Instance.destinyRareCountTotal).text = $"{34 * num}";
				break;
			case "Destiny Epic Total":
				Instance.destinyEpicCountTotal = val;
				((TMP_Text)Instance.destinyEpicCountTotal).text = $"{34 * num}";
				break;
			case "Destiny Legendary Total":
				Instance.destinyLegendaryCountTotal = val;
				((TMP_Text)Instance.destinyLegendaryCountTotal).text = $"{26 * num}";
				break;
			}
		}
		Button[] componentsInChildren2 = apinfoobject.GetComponentsInChildren<Button>(true);
		foreach (Button val2 in componentsInChildren2)
		{
			switch (((Object)val2).name)
			{
			case "CardGradeButton":
				Instance.cardGradeButton = val2;
				break;
			case "CardSellButton":
				Instance.cardSellButton = val2;
				break;
			case "CardOpenButton":
				Instance.cardOpenButton = val2;
				break;
			}
		}
		Image[] componentsInChildren3 = apinfoobject.GetComponentsInChildren<Image>(true);
		foreach (Image val3 in componentsInChildren3)
		{
			switch (((Object)val3).name)
			{
			case "Generic Panel":
				Instance.GenericImage = val3;
				break;
			case "Standard Panel":
				Instance.StandardImage = val3;
				break;
			case "Pauper Panel":
				Instance.PauperImage = val3;
				break;
			case "Fire Panel":
				Instance.FireImage = val3;
				break;
			case "Earth Panel":
				Instance.EarthImage = val3;
				break;
			case "Water Panel":
				Instance.WaterImage = val3;
				break;
			case "Wind Panel":
				Instance.WindImage = val3;
				break;
			case "1st Ed Panel":
				Instance.FirstEdImage = val3;
				break;
			case "Silver Panel":
				Instance.SilverImage = val3;
				break;
			case "Gold Panel":
				Instance.GoldImage = val3;
				break;
			case "EX Panel":
				Instance.EXImage = val3;
				break;
			case "Full Art Panel":
				Instance.FullArtImage = val3;
				break;
			case "Foil Panel":
				Instance.FoilImage = val3;
				break;
			}
		}
		ButtonClickedEvent onClick = Instance.cardOpenButton.onClick;
		object obj = <>c.<>9__1_0;
		if (obj == null)
		{
			UnityAction val4 = delegate
			{
				Instance.UpdateAchievementList(Instance.cardOpenItems);
				Instance.currentCardItems = Instance.cardOpenItems;
			};
			<>c.<>9__1_0 = val4;
			obj = (object)val4;
		}
		((UnityEvent)onClick).AddListener((UnityAction)obj);
		ButtonClickedEvent onClick2 = Instance.cardSellButton.onClick;
		object obj2 = <>c.<>9__1_1;
		if (obj2 == null)
		{
			UnityAction val5 = delegate
			{
				Instance.UpdateAchievementList(Instance.cardSellItems);
				Instance.currentCardItems = Instance.cardSellItems;
			};
			<>c.<>9__1_1 = val5;
			obj2 = (object)val5;
		}
		((UnityEvent)onClick2).AddListener((UnityAction)obj2);
		ButtonClickedEvent onClick3 = Instance.cardGradeButton.onClick;
		object obj3 = <>c.<>9__1_2;
		if (obj3 == null)
		{
			UnityAction val6 = delegate
			{
				Instance.UpdateAchievementList(Instance.cardGradeItems);
				Instance.currentCardItems = Instance.cardGradeItems;
			};
			<>c.<>9__1_2 = val6;
			obj3 = (object)val6;
		}
		((UnityEvent)onClick3).AddListener((UnityAction)obj3);
		Instance.achievementContent = ((IEnumerable<Transform>)apinfoobject.GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "AchievementContent"));
		Instance.productContent = ((IEnumerable<Transform>)apinfoobject.GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "ProductContent"));
		Instance.CollectionGoalUI = ((IEnumerable<Transform>)apinfoobject.GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "CollectionGoal"));
		Instance.LevelGoalUI = ((IEnumerable<Transform>)apinfoobject.GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "LevelGoal"));
		Instance.GhostGoalUI = ((IEnumerable<Transform>)apinfoobject.GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "GhostGoal"));
		Instance.GenericEventGroup = ((IEnumerable<Transform>)apinfoobject.GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "Generic Group"));
		Instance.Formats1 = ((IEnumerable<Transform>)apinfoobject.GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "Formats1"));
		Instance.Formats2 = ((IEnumerable<Transform>)apinfoobject.GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "Formats2"));
		Instance.Formats3 = ((IEnumerable<Transform>)apinfoobject.GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "Formats3"));
		switch (Plugin.ArchipelagoHandler.slotData.Goal)
		{
		case 0:
			((Component)Instance.LevelGoalUI).gameObject.SetActive(true);
			((Component)Instance.GhostGoalUI).gameObject.SetActive(false);
			((Component)Instance.CollectionGoalUI).gameObject.SetActive(false);
			((TMP_Text)Instance.levelGoalText).text = $"{Plugin.ArchipelagoHandler.slotData.MaxLevel}";
			break;
		case 1:
			((Component)Instance.CollectionGoalUI).gameObject.SetActive(true);
			((Component)Instance.GhostGoalUI).gameObject.SetActive(false);
			((Component)Instance.LevelGoalUI).gameObject.SetActive(false);
			((TMP_Text)Instance.percentGoal).text = $"{Plugin.ArchipelagoHandler.slotData.CollectionGoalPercent}%";
			break;
		case 2:
			((Component)Instance.GhostGoalUI).gameObject.SetActive(true);
			((Component)Instance.CollectionGoalUI).gameObject.SetActive(false);
			((Component)Instance.LevelGoalUI).gameObject.SetActive(false);
			((TMP_Text)Instance.ghostGoalText).text = $"{Plugin.ArchipelagoHandler.slotData.GhostGoalAmount}";
			break;
		}
		Instance.cardOpenItems = achievements[Constants.OPEN_ACHIEVEMENT_TYPE];
		Instance.cardSellItems = achievements[Constants.SELL_ACHIEVEMENT_TYPE];
		Instance.cardGradeItems = achievements[Constants.GRADE_ACHIEVEMENT_TYPE];
		if (Instance.cardGradeItems.Count > 0)
		{
			((Selectable)Instance.cardGradeButton).interactable = true;
			Instance.UpdateAchievementList(Instance.cardGradeItems);
			Instance.currentCardItems = Instance.cardGradeItems;
		}
		if (Instance.cardSellItems.Count > 0)
		{
			((Selectable)Instance.cardSellButton).interactable = true;
			Instance.UpdateAchievementList(Instance.cardSellItems);
			Instance.currentCardItems = Instance.cardSellItems;
		}
		if (Instance.cardOpenItems.Count > 0)
		{
			((Selectable)Instance.cardOpenButton).interactable = true;
			Instance.UpdateAchievementList(Instance.cardOpenItems);
			Instance.currentCardItems = Instance.cardOpenItems;
		}
		Instance.UpdateProductList(new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
		ScrollRect componentInChildren = apinfoobject.GetComponentInChildren<ScrollRect>(true);
		for (int l = 0; l < 15; l++)
		{
			Instance.UpdateCardCollection((ECollectionPackType)l, 0);
		}
		if (Plugin.ArchipelagoHandler.slotData.Goal != 1)
		{
			return;
		}
		decimal num2 = default(decimal);
		foreach (KeyValuePair<ECollectionPackType, List<int>> item in Plugin.SaveHandler.GetSaveData().foundCards.foundByPackType)
		{
			num2 += (decimal)item.Value.Count;
		}
		decimal num3 = num2 / (num2 + (decimal)Plugin.SaveHandler.GetSaveData().foundCards.notfound.Count);
		Instance.setPercentGoalCollected(num3 * 100m);
	}

	public static UIInfoPanel getInstance()
	{
		return Instance;
	}

	public void setVisable(bool visable)
	{
		showGUI = visable;
		if ((Object)(object)window != (Object)null)
		{
			window.SetActive(visable);
			UpdateAchievementList(cardOpenItems);
			int maxLevel = APLogicUtil.GetMaxLevel(CPlayerData.m_ShopLevel);
			SetLevelMax(maxLevel);
			SetStoredXP(Plugin.SaveHandler.GetSaveData().StoredXP);
			SetLicensesToLevel(APLogicUtil.GetRemainingLicenses(maxLevel));
		}
	}

	public void toggleVisability()
	{
		setVisable(!showGUI);
	}

	public void DelaySetVisable(bool visible)
	{
		if (showGUI)
		{
			showGUI = visible;
			if (!((Object)(object)window == (Object)null))
			{
				((MonoBehaviour)this).StopAllCoroutines();
				((MonoBehaviour)this).StartCoroutine(DelayedHide(0.15f, visible));
			}
		}
	}

	[IteratorStateMachine(typeof(<DelayedHide>d__89))]
	private IEnumerator DelayedHide(float delay, bool visable)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <DelayedHide>d__89(0)
		{
			<>4__this = this,
			delay = delay,
			visable = visable
		};
	}

	public void setCardCollectionCount(ECollectionPackType type)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		Instance.UpdateCardCollection(type, Plugin.SaveHandler.GetSaveData().foundCards.sanityCount[type]);
	}

	public void SetLevelMax(int value)
	{
		((TMP_Text)levelMaxText).text = $"{value}";
	}

	public void SetStoredXP(int value)
	{
		((TMP_Text)storedXPText).text = $"{value}";
	}

	public void SetLicensesToLevel(int value)
	{
		((TMP_Text)licensesText).text = $"{value}";
	}

	public void InitializeEventGames(bool allevents, int total)
	{
		//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_0014: 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_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: 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_00fc: 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_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: Unknown result type (might be due to invalid IL or missing references)
		Image genericImage = GenericImage;
		Color red = Color.red;
		((Graphic)genericImage).color = ((Color)(ref red)).AlphaMultiplied(0.4f);
		Image standardImage = StandardImage;
		red = Color.red;
		((Graphic)standardImage).color = ((Color)(ref red)).AlphaMultiplied(0.4f);
		Image pauperImage = PauperImage;
		red = Color.red;
		((Graphic)pauperImage).color = ((Color)(ref red)).AlphaMultiplied(0.4f);
		Image fireImage = FireImage;
		red = Color.red;
		((Graphic)fireImage).color = ((Color)(ref red)).AlphaMultiplied(0.4f);
		Image earthImage = EarthImage;
		red = Color.red;
		((Graphic)earthImage).color = ((Color)(ref red)).AlphaMultiplied(0.4f);
		Image waterImage = WaterImage;
		red = Color.red;
		((Graphic)waterImage).color = ((Color)(ref red)).AlphaMultiplied(0.4f);
		Image windImage = WindImage;
		red = Color.red;
		((Graphic)windImage).color = ((Color)(ref red)).AlphaMultiplied(0.4f);
		Image firstEdImage = FirstEdImage;
		red = Color.red;
		((Graphic)firstEdImage).color = ((Color)(ref red)).AlphaMultiplied(0.4f);
		Image silverImage = SilverImage;
		red = Color.red;
		((Graphic)silverImage).color = ((Color)(ref red)).AlphaMultiplied(0.4f);
		Image goldImage = GoldImage;
		red = Color.red;
		((Graphic)goldImage).color = ((Color)(ref red)).AlphaMultiplied(0.4f);
		Image eXImage = EXImage;
		red = Color.red;
		((Graphic)eXImage).color = ((Color)(ref red)).AlphaMultiplied(0.4f);
		Image fullArtImage = FullArtImage;
		red = Color.red;
		((Graphic)fullArtImage).color = ((Color)(ref red)).AlphaMultiplied(0.4f);
		Image foilImage = FoilImage;
		red = Color.red;
		((Graphic)foilImage).color = ((Color)(ref red)).AlphaMultiplied(0.4f);
		if (allevents)
		{
			((Component)GenericEventGroup).gameObject.SetActive(false);
			((TMP_Text)StandardTotal).text = $"{total}";
			((TMP_Text)PauperTotal).text = $"{total}";
			((TMP_Text)FireTotal).text = $"{total}";
			((TMP_Text)EarthTotal).text = $"{total}";
			((TMP_Text)WaterTotal).text = $"{total}";
			((TMP_Text)WindTotal).text = $"{total}";
			((TMP_Text)FirstEdTotal).text = $"{total}";
			((TMP_Text)SilverTotal).text = $"{total}";
			((TMP_Text)GoldTotal).text = $"{total}";
			((TMP_Text)EXTotal).text = $"{total}";
			((TMP_Text)FullArtTotal).text = $"{total}";
			((TMP_Text)FoilTotal).text = $"{total}";
		}
		else
		{
			((Component)Formats1).gameObject.SetActive(false);
			((Component)Formats2).gameObject.SetActive(false);
			((Component)Formats3).gameObject.SetActive(false);
			((TMP_Text)GenericTotal).text = $"{total}";
		}
		CheckAllFormatsAvailability();
	}

	public void CheckAllFormatsAvailability()
	{
		if (Plugin.ArchipelagoHandler.slotData.NoFormat)
		{
			UpdateFormatAvailability((EGameEventFormat)12);
		}
		for (int i = 0; i < 12; i++)
		{
			if (Plugin.ArchipelagoHandler.GetItemCount(PlayTableMapping.FormatStartingId + i) > 0)
			{
				UpdateFormatAvailability((EGameEventFormat)i);
			}
		}
	}

	public void UpdateFormatAvailability(EGameEventFormat eventType)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: 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_0022: 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_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Expected I4, but got Unknown
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: 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_0171: 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)
		if (Plugin.ArchipelagoHandler.GetItemCount(FurnatureMapping.getIdFromType((EObjectType)11)) != 0)
		{
			switch (eventType - -1)
			{
			case 13:
				((Graphic)GenericImage).color = formatAvailableColor;
				break;
			case 1:
				((Graphic)StandardImage).color = formatAvailableColor;
				break;
			case 2:
				((Graphic)PauperImage).color = formatAvailableColor;
				break;
			case 3:
				((Graphic)FireImage).color = formatAvailableColor;
				break;
			case 4:
				((Graphic)EarthImage).color = formatAvailableColor;
				break;
			case 5:
				((Graphic)WaterImage).color = formatAvailableColor;
				break;
			case 6:
				((Graphic)WindImage).color = formatAvailableColor;
				break;
			case 7:
				((Graphic)FirstEdImage).color = formatAvailableColor;
				break;
			case 8:
				((Graphic)SilverImage).color = formatAvailableColor;
				break;
			case 9:
				((Graphic)GoldImage).color = formatAvailableColor;
				break;
			case 10:
				((Graphic)EXImage).color = formatAvailableColor;
				break;
			case 11:
				((Graphic)FullArtImage).color = formatAvailableColor;
				break;
			case 12:
				((Graphic)FoilImage).color = formatAvailableColor;
				break;
			case 0:
				break;
			}
		}
	}

	public void UpdateFormatCount(EGameEventFormat packType, int count)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Expected I4, but got Unknown
		switch ((int)packType)
		{
		case 12:
			if ((Object)(object)GenericCount != (Object)null)
			{
				((TMP_Text)GenericCount).text = $"{count}";
			}
			break;
		case 0:
			if ((Object)(object)StandardCount != (Object)null)
			{
				((TMP_Text)StandardCount).text = $"{count}";
			}
			break;
		case 1:
			if ((Object)(object)PauperCount != (Object)null)
			{
				((TMP_Text)PauperCount).text = $"{count}";
			}
			break;
		case 2:
			if ((Object)(object)FireCount != (Object)null)
			{
				((TMP_Text)FireCount).text = $"{count}";
			}
			break;
		case 3:
			if ((Object)(object)EarthCount != (Object)null)
			{
				((TMP_Text)EarthCount).text = $"{count}";
			}
			break;
		case 4:
			if ((Object)(object)WaterCount != (Object)null)
			{
				((TMP_Text)WaterCount).text = $"{count}";
			}
			break;
		case 5:
			if ((Object)(object)WindCount != (Object)null)
			{
				((TMP_Text)WindCount).text = $"{count}";
			}
			break;
		case 6:
			if ((Object)(object)FirstEdCount != (Object)null)
			{
				((TMP_Text)FirstEdCount).text = $"{count}";
			}
			break;
		case 7:
			if ((Object)(object)SilverCount != (Object)null)
			{
				((TMP_Text)SilverCount).text = $"{count}";
			}
			break;
		case 8:
			if ((Object)(object)GoldCount != (Object)null)
			{
				((TMP_Text)GoldCount).text = $"{count}";
			}
			break;
		case 9:
			if ((Object)(object)EXCount != (Object)null)
			{
				((TMP_Text)EXCount).text = $"{count}";
			}
			break;
		case 10:
			if ((Object)(object)FullArtCount != (Object)null)
			{
				((TMP_Text)FullArtCount).text = $"{count}";
			}
			break;
		case 11:
			if ((Object)(object)FoilCount != (Object)null)
			{
				((TMP_Text)FoilCount).text = $"{count}";
			}
			break;
		}
	}

	public void UpdateCardCollection(ECollectionPackType packType, int count)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Expected I4, but got Unknown
		switch ((int)packType)
		{
		case 0:
			((TMP_Text)basicCount).text = $"{count}";
			break;
		case 1:
			((TMP_Text)rareCount).text = $"{count}";
			break;
		case 2:
			((TMP_Text)epicCount).text = $"{count}";
			break;
		case 3:
			((TMP_Text)legendaryCount).text = $"{count}";
			break;
		case 4:
			((TMP_Text)destinyBasicCount).text = $"{count}";
			break;
		case 5:
			((TMP_Text)destinyRareCount).text = $"{count}";
			break;
		case 6:
			((TMP_Text)destinyEpicCount).text = $"{count}";
			break;
		case 7:
			((TMP_Text)destinyLegendaryCount).text = $"{count}";
			break;
		}
	}

	public void UpdateAchievementList(List<CompiledAchievement> items)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		foreach (Transform item in achievementContent)
		{
			Transform val = item;
			Object.Destroy((Object)(object)((Component)val).gameObject);
		}
		List<CompiledAchievement> list = items.OrderByDescending((CompiledAchievement a) => a.IsHinted).ThenBy(delegate(CompiledAchievement a)
		{
			if (a.completed)
			{
				return 2;
			}
			return (!a.Available) ? 1 : 0;
		}).ToList();
		foreach (CompiledAchievement item2 in list)
		{
			GameObject val2 = Object.Instantiate<GameObject>(achievementPrefab, achievementContent);
			((TMP_Text)((Component)val2.transform.Find("Text")).GetComponent<TextMeshProUGUI>()).text = item2.data.name;
			((TMP_Text)((Component)val2.transform.Find("ProgressText")).GetComponent<TextMeshProUGUI>()).text = $"{item2.progress}/{item2.data.threshold}";
			Transform val3 = val2.transform.Find("Hint");
			((Behaviour)((Component)val3.Find("HintText")).GetComponent<TextMeshProUGUI>()).enabled = item2.IsHinted;
			((Behaviour)((Component)val3).GetComponent<Image>()).enabled = item2.IsHinted;
			((Graphic)((Component)val2.transform).GetComponent<Image>()).color = (item2.completed ? new Color(0.6f, 0.6f, 0.6f) : (item2.Available ? new Color(0f, 0.5f, 55f) : new Color(0.86f, 0f, 0f)));
		}
	}

	public void UpdateProductList(List<int> products)
	{
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Expected O, but got Unknown
		foreach (int item in products)
		{
			GameObject val = Object.Instantiate<GameObject>(productPrefab);
			val.transform.SetParent(productContent, false);
			((TMP_Text)((Component)val.transform.Find("Text")).GetComponent<TextMeshProUGUI>()).text = "test name";
			Transform val2 = val.transform.Find("Button");
			((TMP_Text)((Component)val2.Find("ButtonText")).GetComponent<TextMeshProUGUI>()).text = "Hinted";
			((Behaviour)((Component)val2).GetComponent<Button>()).enabled = true;
			((UnityEvent)((Component)val2).GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				Plugin.Logger.LogInfo((object)$"Hint {item}");
			});
		}
	}

	private void Update()
	{
	}

	public void setPercentGoalCollected(decimal percent)
	{
		((TMP_Text)percentCollected).text = $"{Math.Round(percent, 1)}%";
	}

	public void setGhostGoalSold(int totalNum)
	{
		((TMP_Text)currentGhostsSold).text = $"{totalNum}";
	}

	internal void UpdateImportantLicenses(List<RestockData> restockDatas)
	{
		throw new NotImplementedException();
	}

	public void Refresh()
	{
		if (Instance.currentCardItems != null)
		{
			Instance.UpdateAchievementList(Instance.currentCardItems);
		}
	}
}
namespace ApClient
{
	public class Constants
	{
		public static readonly int SAVE_SLOT = 3;

		public static readonly string OPEN_ACHIEVEMENT_TYPE = "open";

		public static readonly string SELL_ACHIEVEMENT_TYPE = "sell";

		public static readonly string GRADE_ACHIEVEMENT_TYPE = "grade";

		public static readonly float SHOPLIFT_CHANCE = 0.1f;
	}
	[BepInPlugin("TCG_AP_Client", "TCG AP Client", "1.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public static ManualLogSource Logger;

		public static ArchipelagoHandler ArchipelagoHandler;

		public static ItemHandler ItemHandler;

		private static ConfigFile ConfigRef;

		public static ConfigEntry<float> MessageInTime;

		public static ConfigEntry<bool> FilterLog;

		public static ConfigEntry<float> MessageHoldTime;

		public static ConfigEntry<float> MessageOutTime;

		public static ConfigEntry<bool> EnableDebugLogging;

		public static ConfigEntry<KeyCode> ConnectionHotKey;

		public static ConfigEntry<KeyCode> LogToggleKey;

		public static ConfigEntry<KeyCode> HistoryToggleKey;

		public static ConfigEntry<bool> doDeathlink;

		public static ConfigEntry<string> LastUsedIP;

		public static ConfigEntry<string> LastUsedPassword;

		public static ConfigEntry<string> LastUsedSlot;

		private readonly Harmony Harmony = new Harmony("TCG_AP_Client");

		private static AssetBundle myAssetBundle;

		public static SaveHandler SaveHandler { get; private set; }

		public static bool SceneLoaded { get; private set; }

		private void Awake()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			Application.logMessageReceived += new LogCallback(HandleUnityLog);
			Harmony.PatchAll();
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			Logger.LogInfo((object)"Plugin TCG_AP_Client is loaded!");
			SceneManager.sceneLoaded += OnSceneLoad;
			bindConfig();
			ArchipelagoHandler = ((Component)this).gameObject.AddComponent<ArchipelagoHandler>();
			ItemHandler = ((Component)this).gameObject.AddComponent<ItemHandler>();
		}

		private void Start()
		{
			string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Assets");
			string text = Path.Combine(path, "apinfoui");
			myAssetBundle = AssetBundle.LoadFromFile(text);
			TextAsset val = myAssetBundle.LoadAsset<TextAsset>("metadata");
			BundleMetadata bundleMetadata = JsonConvert.DeserializeObject<BundleMetadata>(val.text);
			string[] array = bundleMetadata.bundleVersion.Split(".");
			string[] array2 = "1.0.0".Split(".");
			if (array[0] != array2[0] || array[1] != array2[1])
			{
				ConnectionMenu.SetState("Wrong asset version. Needs " + array[0] + "." + array[1] + ".X", buttonActive: false);
				Logger.LogError((object)("Loaded asset bundle version " + bundleMetadata.bundleVersion + " does not match plugin major and minor version 1.1.0"));
			}
			else
			{
				Logger.LogInfo((object)("Loaded asset bundle version " + bundleMetadata.bundleVersion));
			}
			_ = ConnectionMenu.Instance;
		}

		private void OnSceneLoad(Scene scene, LoadSceneMode mode)
		{
			if (((Scene)(ref scene)).name == "Title")
			{
				Util.SetTitleInteractable(interactable: false);
				SceneLoaded = false;
			}
			if (!(((Scene)(ref scene)).name == "Start"))
			{
			}
		}

		public static void SetSceneLoaded()
		{
			GameObject val = myAssetBundle.LoadAsset<GameObject>("APInfo");
			GameObject val2 = Object.Instantiate<GameObject>(val);
			UIInfoPanel instance = val2.AddComponent<UIInfoPanel>();
			SceneLoaded = true;
			UIInfoPanel.setInstance(instance, val2, myAssetBundle.LoadAsset<GameObject>("Achievement"), myAssetBundle.LoadAsset<GameObject>("Product"), SaveHandler.GetAchievementHandler().achievementsByType);
			UIInfoPanel.getInstance().setVisable(visable: false);
			UIInfoPanel.getInstance().InitializeEventGames(!ArchipelagoHandler.slotData.NoFormat, ArchipelagoHandler.slotData.PlayTableChecks);
			SaveHandler.GetAchievementHandler().UpdateAvailability(APLogicUtil.GetAllAvailablePacks());
			ConnectionMenu.setVisable(visable: false);
			ItemHandler.FlushQueue();
			if (ArchipelagoHandler.slotData.StartingEmployeeIndex == -1 || CPlayerData.GetIsWorkerHired(ArchipelagoHandler.slotData.StartingEmployeeIndex))
			{
				return;
			}
			CPlayerData.SetIsWorkerHired(ArchipelagoHandler.slotData.StartingEmployeeIndex, true);
			CSingleton<WorkerManager>.Instance.ActivateWorker(ArchipelagoHandler.slotData.StartingEmployeeIndex, true);
			int num = 0;
			for (int i = 0; i < CPlayerData.m_IsWorkerHired.Count; i++)
			{
				if (CPlayerData.m_IsWorkerHired[i])
				{
					num++;
				}
			}
			AchievementManager.OnStaffHired(num);
		}

		public static bool IsGameReady()
		{
			return ArchipelagoHandler.IsConnected && SceneLoaded;
		}

		public static bool EnabledDeathLink()
		{
			return ArchipelagoHandler.IsConnected && IsGameReady() && ArchipelagoHandler.slotData.Deathlink && doDeathlink.Value;
		}

		private void Update()
		{
			if ((Input.GetKeyDown((KeyCode)9) || Input.GetKeyDown((KeyCode)27)) && IsGameReady())
			{
				UIInfoPanel.getInstance().DelaySetVisable(visible: false);
			}
		}

		private void bindConfig()
		{
			ConfigRef = ((BaseUnityPlugin)this).Config;
			EnableDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "EnableDebugLogging", false, "Enables or disables debug logging in the Archipelago Console.");
			FilterLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "FilterLog", false, "Filter the archipelago log to only show messages relevant to you.");
			MessageInTime = ((BaseUnityPlugin)this).Config.Bind<float>("Logging", "MessageInTime", 0.25f, "How long messages take to animate in.");
			MessageHoldTime = ((BaseUnityPlugin)this).Config.Bind<float>("Logging", "MessageHoldTime", 3f, "How long messages stay in the log before animating out.");
			MessageOutTime = ((BaseUnityPlugin)this).Config.Bind<float>("Logging", "MessageOutTime", 0.5f, "How long messages stay in the log before animating out.");
			doDeathlink = ((BaseUnityPlugin)this).Config.Bind<bool>("GamePlay", "Enable Deathlink", true, "Enable sending and receiving deathlinks. Overrides YAML.");
			ConnectionHotKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Hotkeys", "Toggle Connection Window", (KeyCode)289, "Press this key to toggle AP Connection GUI");
			LogToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Hotkeys", "Toggle AP Console", (KeyCode)288, "Press this key to toggle AP Console Output");
			HistoryToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Hotkeys", "Toggle AP Console History", (KeyCode)287, "Press this key to toggle AP Console History");
			LastUsedIP = ((BaseUnityPlugin)this).Config.Bind<string>("Connection", "LastUsedIP", "", "The last server IP entered.");
			LastUsedPassword = ((BaseUnityPlugin)this).Config.Bind<string>("Connection", "LastUsedPassword", "", "The last server password entered.");
			LastUsedSlot = ((BaseUnityPlugin)this).Config.Bind<string>("Connection", "LastUsedSlot", "", "The last player slot name entered.");
		}

		public static async Task<bool> ConnectAsync(string ip, string password, string slot)
		{
			LastUsedIP.Value = ip;
			LastUsedPassword.Value = password;
			LastUsedSlot.Value = slot;
			SaveHandler = await ArchipelagoHandler.ConnectAsync(ip, password, slot);
			if (SaveHandler != null)
			{
				Util.RunTitleInteractableSaveLogic();
				ConfigRef.Save();
				return true;
			}
			ConfigRef.Save();
			return false;
		}

		public static async Task Disconnect()
		{
			Cleanup();
			if ((Object)(object)ArchipelagoHandler != (Object)null)
			{
				try
				{
					await ArchipelagoHandler.DisconnectAsync();
				}
				catch (Exception ex)
				{
					Logger.LogWarning((object)$"Disconnect error: {ex}");
				}
			}
		}

		public static void Cleanup()
		{
			ConnectionMenu.setVisable(visable: true);
			ConnectionMenu.SetState("Not Connected", buttonActive: true);
			ClearSave();
		}

		public static void ClearSave()
		{
			if (SaveHandler != null && IsGameReady())
			{
				CSingleton<ShelfManager>.Instance.SaveInteractableObjectData(false);
				CSingleton<CGameManager>.Instance.SaveGameData(0);
			}
			SaveHandler = null;
		}

		private void HandleUnityLog(string condition, string stackTrace, LogType type)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if ((int)type != 2 || !condition.Contains("Parent of RectTransform is being set with parent property"))
			{
				Debug.unityLogger.Log(type, (object)condition);
			}
		}

		private void OnDestroy()
		{
			Logger.LogInfo((object)"Unloading AP Mod");
			Harmony.UnpatchSelf();
		}
	}
	public class Util : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <FakeKnockout>d__11 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Customer c;

			public Util <>4__this;

			private Animator <anim>5__1;

			private NavMeshAgent <agent>5__2;

			private float <fallAngle>5__3;

			private Vector3 <fallAxis>5__4;

			private Quaternion <startRot>5__5;

			private Quaternion <endRot>5__6;

			private Vector3 <startPos>5__7;

			private Vector3 <endPos>5__8;

			private float <duration>5__9;

			private float <t>5__10;

			private float <lerp>5__11;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <FakeKnockout>d__11(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<anim>5__1 = null;
				<agent>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0127: Unknown result type (might be due to invalid IL or missing references)
				//IL_012c: Unknown result type (might be due to invalid IL or missing references)
				//IL_013d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0142: Unknown result type (might be due to invalid IL or missing references)
				//IL_0149: 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)
				//IL_015f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0164: Unknown result type (might be due to invalid IL or missing references)
				//IL_0175: Unknown result type (might be due to invalid IL or missing references)
				//IL_017a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0181: Unknown result type (might be due to invalid IL or missing references)
				//IL_0186: Unknown result type (might be due to invalid IL or missing references)
				//IL_0190: Unknown result type (might be due to invalid IL or missing references)
				//IL_0195: Unknown result type (might be due to invalid IL or missing references)
				//IL_019a: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
				//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
				//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
				//IL_030c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0316: Expected O, but got Unknown
				//IL_006b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Expected O, but got Unknown
				//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f0: Expected O, but got Unknown
				//IL_027d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0282: Unknown result type (might be due to invalid IL or missing references)
				//IL_028c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0291: Unknown result type (might be due to invalid IL or missing references)
				//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
				//IL_02ac: Expected O, but got Unknown
				//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
				//IL_0204: Unknown result type (might be due to invalid IL or missing references)
				//IL_020f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0226: Unknown result type (might be due to invalid IL or missing references)
				//IL_022c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0237: Unknown result type (might be due to invalid IL or missing references)
				Transform transform2;
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if ((Object)(object)c == (Object)null)
					{
						return false;
					}
					<>2__current = (object)new WaitForSeconds(Random.Range(0f, 0.3f));
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<anim>5__1 = c.m_Anim;
					<anim>5__1.SetBool("IsBeingSprayed", true);
					<agent>5__2 = ((Component)c).GetComponent<NavMeshAgent>();
					if ((Object)(object)<agent>5__2 != (Object)null)
					{
						((Behaviour)<agent>5__2).enabled = false;
					}
					<>2__current = (object)new WaitForSeconds(Random.Range(0.5f, 1.2f));
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<anim>5__1.speed = 0f;
					<fallAngle>5__3 = Random.Range(-110f, 110f);
					<fallAxis>5__4 = Vector3.forward;
					<startRot>5__5 = ((Component)c).transform.rotation;
					<endRot>5__6 = <startRot>5__5 * Quaternion.AngleAxis(<fallAngle>5__3, <fallAxis>5__4);
					<startPos>5__7 = ((Component)c).transform.position;
					<endPos>5__8 = <startPos>5__7 + Vector3.down * 0.6f;
					<duration>5__9 = 0.35f;
					<t>5__10 = 0f;
					goto IL_025a;
				case 3:
					<>1__state = -1;
					goto IL_025a;
				case 4:
				{
					<>1__state = -1;
					Transform transform = ((Component)c).transform;
					transform.position -= Vector3.up * 0.08f;
					<anim>5__1.SetBool("IsBeingSprayed", false);
					((Behaviour)<anim>5__1).enabled = false;
					<>2__current = (object)new WaitForSeconds(10f);
					<>1__state = 5;
					return true;
				}
				case 5:
					{
						<>1__state = -1;
						if ((Object)(object)c != (Object)null)
						{
							c.DeactivateCustomer();
						}
						return false;
					}
					IL_025a:
					if (<t>5__10 < <duration>5__9)
					{
						if ((Object)(object)c == (Object)null)
						{
							return false;
						}
						<t>5__10 += Time.deltaTime;
						<lerp>5__11 = <t>5__10 / <duration>5__9;
						((Component)c).transform.rotation = Quaternion.Slerp(<startRot>5__5, <endRot>5__6, <lerp>5__11);
						((Component)c).transform.position = Vector3.Lerp(<startPos>5__7, <endPos>5__8, <lerp>5__11);
						<>2__current = null;
						<>1__state = 3;
						return true;
					}
					transform2 = ((Component)c).transform;
					transform2.position += Vector3.up * 0.08f;
					<>2__current = (object)new WaitForSeconds(0.05f);
					<>1__state = 4;
					return true;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static readonly Queue<Action> _mainThreadQueue = new Queue<Action>();

		private static Util _instance;

		public static Util Instance
		{
			get
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Expected O, but got Unknown
				if ((Object)(object)_instance == (Object)null)
				{
					GameObject val = new GameObject("CoroutineRunner");
					Object.DontDestroyOnLoad((Object)(object)val);
					_instance = val.AddComponent<Util>();
				}
				return _instance;
			}
		}

		public static void RunOnMainThread(Action action)
		{
			Util instance = Instance;
			lock (_mainThreadQueue)
			{
				_mainThreadQueue.Enqueue(action);
			}
		}

		private void Update()
		{
			lock (_mainThreadQueue)
			{
				while (_mainThreadQueue.Count > 0)
				{
					_mainThreadQueue.Dequeue()();
				}
			}
		}

		public static CardData CardRoller(ECollectionPackType collectionPackType)
		{
			//IL_0020: 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_0026: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Invalid comparison between Unknown and I4
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			ECardExpansionType val = (ECardExpansionType)(!((double)Random.Range(0f, 1f) > 0.5));
			return new CardData
			{
				isFoil = ((double)Random.Range(0f, 1f) > 0.5),
				isDestiny = ((int)val == 1),
				borderType = (ECardBorderType)Random.Range(0, 6),
				monsterType = (EMonsterType)Random.Range(0, 122),
				expansionType = val,
				isChampionCard = false,
				isNew = true
			};
		}

		public static Texture2D LoadTexture(string resourceName)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			using Stream stream = executingAssembly.GetManifestResourceStream(resourceName);
			if (stream == null)
			{
				Debug.LogError((object)("Embedded resource not found: " + resourceName));
				return null;
			}
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			Texture2D val = new Texture2D(2, 2);
			ImageConversion.LoadImage(val, array);
			return val;
		}

		public static void SetTitleInteractable(bool interactable)
		{
			TitleScreen val = Object.FindFirstObjectByType<TitleScreen>();
			((Selectable)val.m_LoadGameButton).interactable = interactable;
			GameObject val2 = GameObject.Find("NewGameBtn");
			if ((Object)(object)val2 != (Object)null)
			{
				Button componentInChildren = val2.GetComponentInChildren<Button>();
				((Selectable)componentInChildren).interactable = interactable;
			}
		}

		public static void RunTitleInteractableSaveLogic()
		{
			TitleScreen val = Object.FindFirstObjectByType<TitleScreen>();
			GameObject val2 = GameObject.Find("NewGameBtn");
			Button val3 = null;
			if ((Object)(object)val2 != (Object)null)
			{
				val3 = val2.GetComponentInChildren<Button>();
			}
			if (Plugin.SaveHandler.doesSaveExist())
			{
				((Selectable)val.m_LoadGameButton).interactable = true;
				((Selectable)val3).interactable = false;
			}
			else
			{
				((Selectable)val.m_LoadGameButton).interactable = false;
				((Selectable)val3).interactable = true;
			}
		}

		public void KnockoutCustomer(Customer c)
		{
			((MonoBehaviour)this).StartCoroutine(FakeKnockout(c));
		}

		[IteratorStateMachine(typeof(<FakeKnockout>d__11))]
		private IEnumerator FakeKnockout(Customer c)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <FakeKnockout>d__11(0)
			{
				<>4__this = this,
				c = c
			};
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "TCG_AP_Client";

		public const string PLUGIN_NAME = "TCG AP Client";

		public const string PLUGIN_VERSION = "1.1.0";
	}
}
namespace ApClient.UI
{
	public class ConnectionMenu : MonoBehaviour
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__OnConnectPressed;
		}

		private static ConnectionMenu _instance;

		private static Canvas canvas;

		private static RectTransform window;

		private static TMP_InputField ipField;

		private static TMP_InputField passField;

		private static TMP_InputField slotField;

		private static TMP_Text stateLabel;

		private static Button connectButton;

		private static GameObject buttonObj;

		private static TMP_Text btnText;

		public static bool showGUI = true;

		private static string state = "Not Connected";

		public static ConnectionMenu Instance
		{
			get
			{
				if ((Object)(object)_instance == (Object)null)
				{
					Create();
				}
				return _instance;
			}
		}

		public static bool ButtonInteractable()
		{
			return ((Selectable)connectButton).interactable;
		}

		public static void SetState(string newState, bool buttonActive)
		{
			state = newState;
			((Selectable)connectButton).interactable = buttonActive;
			buttonObj.SetActive(buttonActive);
		}

		public static void setVisable(bool visable)
		{
			showGUI = visable;
			if ((Object)(object)window != (Object)null)
			{
				((Component)window).gameObject.SetActive(showGUI);
			}
		}

		public void toggleVisability()
		{
			setVisable(!showGUI);
		}

		private static void Create()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: 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)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			//IL_038e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d2: Expected O, but got Unknown
			//IL_0414: Unknown result type (might be due to invalid IL or missing references)
			//IL_0437: Unknown result type (might be due to invalid IL or missing references)
			//IL_044e: Unknown result type (might be due to invalid IL or missing references)
			//IL_045e: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Expected O, but got Unknown
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bd: Expected O, but got Unknown
			if (!((Object)(object)_instance != (Object)null))
			{
				GameObject val = new GameObject("ConnectionMenu");
				Object.DontDestroyOnLoad((Object)(object)val);
				_instance = val.AddComponent<ConnectionMenu>();
				GameObject val2 = new GameObject("ConnectionCanvas");
				canvas = val2.AddComponent<Canvas>();
				val2.transform.SetParent(val.transform, false);
				canvas.renderMode = (RenderMode)0;
				canvas.sortingOrder = 2000;
				CanvasScaler val3 = val2.AddComponent<CanvasScaler>();
				val3.uiScaleMode = (ScaleMode)1;
				val3.referenceResolution = new Vector2(1920f, 1080f);
				val2.AddComponent<GraphicRaycaster>();
				GameObject val4 = new GameObject("MenuBackground", new Type[1] { typeof(Image) });
				val4.transform.SetParent(((Component)canvas).transform, false);
				Image component = val4.GetComponent<Image>();
				((Graphic)component).color = new Color(0.1f, 0.1f, 0.1f, 0.92f);
				component.type = (Type)1;
				Outline val5 = val4.AddComponent<Outline>();
				((Shadow)val5).effectColor = Color.black;
				((Shadow)val5).effectDistance = new Vector2(2f, -2f);
				window = val4.GetComponent<RectTransform>();
				window.sizeDelta = new Vector2(320f, 350f);
				window.anchorMin = new Vector2(0f, 1f);
				window.anchorMax = new Vector2(0f, 1f);
				window.pivot = new Vector2(0f, 1f);
				window.anchoredPosition = new Vector2(20f, -20f);
				TMP_Text val6 = CreateText("AP Client", new Vector2(0f, 150f), 20, val4.transform);
				val6.alignment = (TextAlignmentOptions)514;
				Texture2D val7 = Util.LoadTexture("ApClient.assets.color-icon.png");
				if ((Object)(object)val7 != (Object)null)
				{
					GameObject val8 = new GameObject("Logo", new Type[1] { typeof(Image) });
					val8.transform.SetParent(val4.transform, false);
					Image component2 = val8.GetComponent<Image>();
					Sprite sprite = Sprite.Create(val7, new Rect(0f, 0f, (float)((Texture)val7).width, (float)((Texture)val7).height), new Vector2(0.5f, 0.5f));
					component2.sprite = sprite;
					RectTransform component3 = val8.GetComponent<RectTransform>();
					component3.sizeDelta = new Vector2(50f, 50f);
					component3.anchoredPosition = new Vector2(0f, 110f);
				}
				CreateLabel("Address:Port", new Vector2(0f, 80f), val4.transform);
				ipField = CreateInput(Plugin.LastUsedIP.Value, new Vector2(0f, 55f), val4.transform);
				CreateLabel("Password", new Vector2(0f, 20f), val4.transform);
				passField = CreateInput(Plugin.LastUsedPassword.Value, new Vector2(0f, -5f), val4.transform);
				CreateLabel("Slot", new Vector2(0f, -40f), val4.transform);
				slotField = CreateInput(Plugin.LastUsedSlot.Value, new Vector2(0f, -65f), val4.transform);
				buttonObj = new GameObject("ConnectButton", new Type[2]
				{
					typeof(Image),
					typeof(Button)
				});
				buttonObj.transform.SetParent(val4.transform, false);
				Image component4 = buttonObj.GetComponent<Image>();
				component4.type = (Type)1;
				((Graphic)component4).color = new Color(0.2f, 0.4f, 0.8f, 0.9f);
				RectTransform component5 = buttonObj.GetComponent<RectTransform>();
				component5.sizeDelta = new Vector2(160f, 35f);
				component5.anchoredPosition = new Vector2(0f, -100f);
				btnText = CreateText("Connect", Vector2.zero, 18, buttonObj.transform);
				btnText.alignment = (TextAlignmentOptions)514;
				connectButton = buttonObj.GetComponent<Button>();
				ButtonClickedEvent onClick = connectButton.onClick;
				object obj = <>O.<0>__OnConnectPressed;
				if (obj == null)
				{
					UnityAction val9 = OnConnectPressed;
					<>O.<0>__OnConnectPressed = val9;
					obj = (object)val9;
				}
				((UnityEvent)onClick).AddListener((UnityAction)obj);
				stateLabel = CreateText("Not Connected", new Vector2(0f, -140f), 14, val4.transform);
				stateLabel.alignment = (TextAlignmentOptions)514;
			}
		}

		private void Update()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(Plugin.ConnectionHotKey.Value))
			{
				toggleVisability();
			}
			if ((Object)(object)stateLabel != (Object)null)
			{
				stateLabel.text = state;
			}
		}

		private static async void OnConnectPressed()
		{
			Debug.Log((object)"Connect pressed!");
			if (await Plugin.ConnectAsync(ipField.text, passField.text, slotField.text))
			{
				SetState("Connected", buttonActive: false);
			}
			else if (!state.Contains("AP Requires Mod"))
			{
				SetState("Connection Failed", buttonActive: true);
			}
		}

		private static TMP_Text CreateText(string text, Vector2 pos, int size, Transform parent)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(text, new Type[1] { typeof(TextMeshProUGUI) });
			val.transform.SetParent(parent, false);
			TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).text = text;
			((TMP_Text)component).fontSize = size;
			((Graphic)component).color = Color.white;
			((TMP_Text)component).alignment = (TextAlignmentOptions)513;
			RectTransform component2 = ((Component)component).GetComponent<RectTransform>();
			component2.sizeDelta = new Vector2(280f, 30f);
			component2.anchoredPosition = pos;
			return (TMP_Text)(object)component;
		}

		private static TMP_Text CreateLabel(string text, Vector2 pos, Transform parent)
		{
			//IL_0002: 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)
			TMP_Text val = CreateText(text, pos, 14, parent);
			((Graphic)val).color = new Color(0.8f, 0.8f, 0.8f, 1f);
			val.alignment = (TextAlignmentOptions)4097;
			return val;
		}

		private static TMP_InputField CreateInput(string initial, Vector2 pos, Transform parent)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			//IL_00c9: 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_00ed: 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_0127: 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_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("InputField", new Type[2]
			{
				typeof(Image),
				typeof(TMP_InputField)
			});
			val.transform.SetParent(parent, false);
			Image component = val.GetComponent<Image>();
			component.type = (Type)1;
			((Graphic)component).color = new Color(0.2f, 0.2f, 0.2f, 1f);
			RectTransform component2 = val.GetComponent<RectTransform>();
			component2.sizeDelta = new Vector2(200f, 35f);
			component2.anchoredPosition = pos;
			GameObject val2 = new GameObject("TextArea", new Type[1] { typeof(RectMask2D) });
			val2.transform.SetParent(val.transform, false);
			RectTransform component3 = val2.GetComponent<RectTransform>();
			component3.anchorMin = Vector2.zero;
			component3.anchorMax = Vector2.one;
			component3.offsetMin = new Vector2(5f, 5f);
			component3.offsetMax = new Vector2(-5f, -5f);
			TMP_Text component4 = (TMP_Text)(object)new GameObject("Text", new Type[1] { typeof(TextMeshProUGUI) }).GetComponent<TextMeshProUGUI>();
			component4.transform.SetParent(val2.transform, false);
			component4.text = initial;
			component4.fontSize = 14f;
			((Graphic)component4).color = Color.white;
			component4.alignment = (TextAlignmentOptions)513;
			RectTransform component5 = ((Component)component4).GetComponent<RectTransform>();
			component5.anchorMin = Vector2.zero;
			component5.anchorMax = Vector2.one;
			component5.offsetMin = Vector2.zero;
			component5.offsetMax = Vector2.zero;
			TMP_InputField component6 = val.GetComponent<TMP_InputField>();
			component6.textViewport = component3;
			component6.textComponent = component4;
			component6.text = initial;
			component6.caretColor = Color.white;
			((Behaviour)component6).enabled = false;
			((Behaviour)component6).enabled = true;
			return component6;
		}
	}
}
namespace ApClient.ui
{
	public class APConsole : MonoBehaviour
	{
		private enum ConsoleAnchorCorner
		{
			BottomLeft,
			BottomRight,
			TopLeft,
			TopRight
		}

		[Serializable]
		public class LogEntry
		{
			public enum State
			{
				SlideIn,
				Hold,
				FadeOut
			}

			public State state = State.SlideIn;

			public float stateTimer;

			public float offsetY;

			public float baseY;

			public float animatedY;

			public TextMeshProUGUI text;

			public Image background;

			public string message;

			public string colorizedMessage;

			public float height;

			public LogEntry(string msg)
			{
				message = msg;
				colorizedMessage = msg;
				height = 28f;
			}
		}

		private static readonly Dictionary<string, string> KeywordColors = new Dictionary<string, string>();

		private const string FontName = "";

		private Color TextColor = Color.white;

		private Color BackColor = new Color(0f, 0f, 0f, 0.8f);

		private const int MaxHistoryEntries = 1000;

		private GraphicRaycaster _raycaster;

		private const CursorLockMode DefaultCursorMode = 1;

		private const bool DefaultCursorVisible = false;

		private const float DefaultMessageHeight = 28f;

		private const float DefaultConsoleHeight = 200f;

		private const float DefaultConsoleWidth = 600f;

		private float _slideInTime = 0.25f;

		private float _holdTime = 3f;

		private float _fadeOutTime = 0.5f;

		private const float SlideInOffset = -50f;

		private const float FadeUpOffset = 20f;

		private float _paddingX = 25f;

		private float _paddingY = 25f;

		private float _messageSpacing = 2.5f;

		private ConsoleAnchorCorner _anchorCorner = ConsoleAnchorCorner.BottomLeft;

		private float _consoleWidth = 600f;

		private float _consoleHeight = 200f;

		private float _messageHeight = 28f;

		private bool _rebuildHistoryDirty;

		private int _historyBuiltCount;

		private static TMP_FontAsset _font;

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

		private ConcurrentQueue<LogEntry> _cachedEntries = new ConcurrentQueue<LogEntry>();

		private readonly ConcurrentQueue<TextMeshProUGUI> _textPool = new ConcurrentQueue<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 static APConsole _instance;

		public static APConsole Instance
		{
			get
			{
				if ((Object)(object)_instance == (Object)null)
				{
					Create();
				}
				return _instance;
			}
		}

		private static void Create()
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_011e: 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)
			if ((Object)(object)_instance != (Object)null)
			{
				return;
			}
			TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
			TMP_FontAsset[] array2 = array;
			foreach (TMP_FontAsset val in array2)
			{
				Console.WriteLine(((Object)val).name);
			}
			_font = ((IEnumerable<TMP_FontAsset>)Resources.FindObjectsOfTypeAll<TMP_FontAsset>()).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset x) => ((Object)x).name == ""));
			GameObject val2 = new GameObject("ArchipelagoConsoleUI");
			Object.DontDestroyOnLoad((Object)(object)val2);
			_instance = val2.AddComponent<APConsole>();
			_instance.BuildUI();
			if (Plugin.MessageInTime != null)
			{
				_instance._slideInTime = Plugin.MessageInTime.Value;
			}
			if (Plugin.MessageHoldTime != null)
			{
				_instance._holdTime = Plugin.MessageHoldTime.Value;
			}
			if (Plugin.MessageOutTime != null)
			{
				_instance._fadeOutTime = Plugin.MessageOutTime.Value;
			}
			_instance.Log("by FyreDay");
			_instance.Log($"Press {Plugin.LogToggleKey.Value} to Toggle log & {Plugin.HistoryToggleKey.Value} to toggle history");
			foreach (string key in KeywordColors.Keys)
			{
				_instance.DebugLog(key);
			}
		}

		private void Update()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			UpdateMessages(Time.deltaTime);
			TryAddNewMessages();
			if (Input.GetKeyDown(Plugin.LogToggleKey.Value))
			{
				ToggleConsole();
			}
			if (Input.GetKeyDown(Plugin.HistoryToggleKey.Value))
			{
				ToggleHistory();
			}
			if (_showHistory)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
			if (_showHistory && _rebuildHistoryDirty)
			{
				_rebuildHistoryDirty = false;
				RebuildHistory();
			}
		}

		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 + _messageSpacing;
			}
		}

		private bool AnimateEntry(LogEntry entry, float delta)
		{
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: 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 / _slideInTime);
				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 >= _holdTime)
				{
					entry.state = LogEntry.State.FadeOut;
					entry.stateTimer = 0f;
				}
				break;
			case LogEntry.State.FadeOut:
			{
				float num = Mathf.Clamp01(entry.stateTimer / _fadeOutTime);
				entry.offsetY = Mathf.Lerp(0f, 20f, num);
				float num2 = 1f - num;
				if ((Object)(object)entry.text != (Object)null)
				{
					((Graphic)entry.text).color = new Color(TextColor.r, TextColor.g, TextColor.b, num2);
				}
				if ((Object)(object)entry.background != (Object)null)
				{
					((Graphic)entry.background).color = new Color(BackColor.r, BackColor.g, BackColor.b, 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())
			{
				return;
			}
			int num = Mathf.FloorToInt(_consoleHeight / _messageHeight);
			if (_visibleEntries.Count < num)
			{
				_cachedEntries.TryDequeue(out var result);
				if (result != null)
				{
					result.state = LogEntry.State.SlideIn;
					result.stateTimer = 0f;
					result.offsetY = -50f;
					result.animatedY = result.baseY + result.offsetY;
					CreateEntryVisual(result);
					_visibleEntries.Add(result);
					RecalculateBaseY();
					result.animatedY = result.baseY + result.offsetY;
				}
			}
		}

		private void ApplyRectSettings(RectTransform rt, Vector2 min, Vector2 max, Vector2 pivot, Vector2 pos, Vector2 size)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			rt.anchorMin = min;
			rt.anchorMax = max;
			rt.pivot = pivot;
			rt.anchoredPosition = pos;
			rt.sizeDelta = size;
		}

		private void PositionMessageContainer(RectTransform rect)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_0067: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: 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)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			Vector2 min;
			Vector2 val2 = default(Vector2);
			Vector2 pos = default(Vector2);
			switch (_anchorCorner)
			{
			case ConsoleAnchorCorner.BottomLeft:
				((Vector2)(ref val))..ctor(0f, 0f);
				min = (val2 = val);
				((Vector2)(ref pos))..ctor(_paddingX, _paddingY);
				break;
			case ConsoleAnchorCorner.BottomRight:
				((Vector2)(ref val2))..ctor(1f, 0f);
				min = val2;
				((Vector2)(ref val))..ctor(1f, 0f);
				((Vector2)(ref pos))..ctor(0f - _paddingX, _paddingY);
				break;
			case ConsoleAnchorCorner.TopLeft:
				((Vector2)(ref val2))..ctor(0f, 1f);
				min = val2;
				((Vector2)(ref val))..ctor(0f, 1f);
				((Vector2)(ref pos))..ctor(_paddingX, 0f - _paddingY);
				break;
			case ConsoleAnchorCorner.TopRight:
				((Vector2)(ref val2))..ctor(1f, 1f);
				min = val2;
				((Vector2)(ref val))..ctor(1f, 1f);
				((Vector2)(ref pos))..ctor(0f - _paddingX, 0f - _paddingY);
				break;
			default:
				((Vector2)(ref val))..ctor(0f, 0f);
				min = (val2 = val);
				((Vector2)(ref pos))..ctor(_paddingX, _paddingY);
				break;
			}
			ApplyRectSettings(rect, min, val2, val, pos, new Vector2(_consoleWidth, _consoleHeight));
		}

		private void PositionHistoryPanel(RectTransform rect)
		{
			PositionMessageContainer(rect);
		}

		private void AddHistoryEntryVisual(LogEntry entry)
		{
			//IL_002e: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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;
			ApplyRectSettings(rectTransform, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0.5f, 1f), Vector2.zero, new Vector2(_consoleWidth, _messageHeight));
			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 = TextColor;
			((Graphic)background).color = BackColor;
			((TMP_Text)text).text = entry.colorizedMessage;
			Canvas.ForceUpdateCanvases();
			LayoutRebuilder.ForceRebuildLayoutImmediate(rectTransform2);
			float preferredHeight = Mathf.Max(_messageHeight, ((TMP_Text)text).preferredHeight + 8f);
			LayoutElement val = ((Component)background).GetComponent<LayoutElement>() ?? ((Component)background).gameObject.AddComponent<LayoutElement>();
			val.preferredHeight = preferredHeight;
		}

		private void CreateEntryVisual(LogEntry entry)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: 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;
			ApplyRectSettings(rectTransform, Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero, new Vector2(_consoleWidth, _messageHeight));
			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 = TextColor;
			((Graphic)background).color = BackColor;
			UpdateEntryVisual(entry);
		}

		private void UpdateEntryVisual(LogEntry entry)
		{
			//IL_00ce: 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)
			if ((Object)(object)entry.text != (Object)null)
			{
				((TMP_Text)entry.text).text = entry.colorizedMessage;
				float preferredHeight = ((TMP_Text)entry.text).preferredHeight;
				entry.height = Mathf.Max(_messageHeight, preferredHeight + 8f);
				if ((Object)(object)entry.background != (Object)null)
				{
					((Graphic)entry.background).rectTransform.sizeDelta = new Vector2(_consoleWidth, entry.height);
				}
			}
			float num = entry.baseY + entry.offsetY;
			entry.animatedY = Mathf.Lerp(entry.animatedY, num, Time.deltaTime * 12f);
			if ((Object)(object)entry.background != (Object)null)
			{
				((Graphic)entry.background).rectTransform.anchoredPosition = new Vector2(0f, entry.animatedY);
			}
		}

		private TextMeshProUGUI GetText()
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			if (_textPool.TryDequeue(out var result) && (Object)(object)result != (Object)null)
			{
				((Component)result).gameObject.SetActive(true);
				return result;
			}
			GameObject val = new GameObject("LogText", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(TextMeshProUGUI)
			});
			TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).fontSize = 19f;
			((Graphic)component).color = TextColor;
			((TMP_Text)component).font = _font;
			((TMP_Text)component).wordSpacing = 20f;
			((TMP_Text)component).alignment = (TextAlignmentOptions)4097;
			((Graphic)component).raycastTarget = false;
			return component;
		}

		private Image GetBackground()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (_backgroundPool.TryDequeue(out var result) && (Object)(object)result != (Object)null)
			{
				((Component)result).gameObject.SetActive(true);
				return result;
			}
			GameObject val = new GameObject("LogBG");
			Image val2 = val.AddComponent<Image>();
			((Graphic)val2).color = BackColor;
			val2.type = (Type)1;
			((Graphic)val2).raycastTarget = false;
			return val2;
		}

		private void RecycleEntry(LogEntry entry)
		{
			if ((Object)(object)entry.text != (Object)null)
			{
				((Component)entry.text).gameObject.SetActive(false);
				_textPool.Enqueue(entry.text);
				entry.text = null;
			}
			if ((Object)(object)entry.background != (Object)null)
			{
				((Component)entry.background).gameObject.SetActive(false);
				_backgroundPool.Enqueue(entry.background);
				entry.background = null;
			}
		}

		private string Colorize(string input)
		{
			if (string.IsNullOrEmpty(input))
			{
				return input;
			}
			List<string> list = Tokenize(input);
			ApplyMultiWordColoring(list);
			ApplySingleWordColoring(list);
			return string.Concat(list);
		}

		private List<string> Tokenize(string input)
		{
			return string.IsNullOrEmpty(input) ? new List<string>() : Regex.Split(input, "(\\s+)").ToList();
		}

		private void ApplySingleWordColoring(List<string> tokens)
		{
			Dictionary<string, string> dictionary = KeywordColors.Where((KeyValuePair<string, string> kvp) => !kvp.Key.Contains(" ")).ToDictionary((KeyValuePair<string, string> k) => k.Key.ToLowerInvariant(), (KeyValuePair<string, string> v) => v.Value);
			for (int i = 0; i < tokens.Count; i++)
			{
				string text = tokens[i];
				if (IsWord(text))
				{
					string key = Regex.Replace(text.ToLowerInvariant(), "[^a-z0-9]", "");
					if (dictionary.TryGetValue(key, out var value))
					{
						tokens[i] = "<color=" + value + ">" + text + "</color>";
					}
				}
			}
		}

		private void ApplyMultiWordColoring(List<string> tokens)
		{
			List<KeyValuePair<string, string>> list = (from kvp in KeywordColors
				where kvp.Key.Contains(" ")
				select kvp into k
				orderby k.Key.Length descending
				select k).ToList();
			if (list.Count == 0)
			{
				return;
			}
			for (int i = 0; i < tokens.Count; i++)
			{
				if (!IsWord(tokens[i]))
				{
					continue;
				}
				string text = string.Concat(tokens.Skip(i));
				string text2 = text.ToLowerInvariant();
				foreach (KeyValuePair<string, string> item in list)
				{
					if (!text2.StartsWith(item.Key.ToLowerInvariant()))
					{
						continue;
					}
					int num = 0;
					string text3 = "";
					for (int j = i; j < tokens.Count; j++)
					{
						if (text3.Length >= item.Key.Length)
						{
							break;
						}
						text3 += tokens[j];
						num++;
					}
					tokens[i] = "<color=" + item.Value + ">" + text3 + "</color>";
					for (int l = 1; l < num; l++)
					{
						tokens[i + l] = "";
					}
					i += num - 1;
					break;
				}
			}
		}

		private bool IsWord(string token)
		{
			return !string.IsNullOrWhiteSpace(token);
		}

		public void Log(string text)
		{
			Plugin.Logger.LogInfo((object)text);
			string colorizedMessage = Colorize(text);
			LogEntry item = new LogEntry(text)
			{
				colorizedMessage = colorizedMessage
			};
			_historyEntries.Add(item);
			if (_historyEntries.Count > 1000)
			{
				_historyEntries.RemoveAt(0);
				_historyBuiltCount = Mathf.Max(0, _historyBuiltCount - 1);
			}
			if (_showHistory)
			{
				_rebuildHistoryDirty = true;
			}
			else
			{
				_cachedEntries.Enqueue(item);
			}
		}

		public void DebugLog(string text)
		{
			if (Plugin.EnableDebugLogging != null && Plugin.EnableDebugLogging.Value)
			{
				Log(text);
			}
		}

		private void ToggleHistory()
		{
			_showHistory = !_showHistory;
			if ((Object)(object)_messageParent == (Object)null || (Object)(object)_historyPanel == (Object)null)
			{
				return;
			}
			((Component)_messageParent).gameObject.SetActive(!_showHistory);
			_historyPanel.SetActive(_showHistory);
			if (_showHistory)
			{
				((Behaviour)_raycaster).enabled = true;
				foreach (LogEntry visibleEntry in _visibleEntries)
				{
					if ((Object)(object)visibleEntry.text != (Object)null)
					{
						((Component)visibleEntry.text).gameObject.SetActive(false);
						_textPool.Enqueue(visibleEntry.text);
					}
					if ((Object)(object)visibleEntry.background != (Object)null)
					{
						((Component)visibleEntry.background).gameObject.SetActive(false);
						_backgroundPool.Enqueue(visibleEntry.background);
					}
				}
				_visibleEntries.Clear();
				_cachedEntries = new ConcurrentQueue<LogEntry>();
				RebuildHistory();
			}
			else
			{
				((Behaviour)_raycaster).enabled = false;
				Cursor.lockState = (CursorLockMode)1;
				Cursor.visible = false;
				((Component)_messageParent).gameObject.SetActive(_showConsole);
			}
		}

		private void ToggleConsole()
		{
			_showConsole = !_showConsole;
			if ((Object)(object)_messageParent == (Object)null || (Object)(object)_historyPanel == (Object)null)
			{
				return;
			}
			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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Expected O, but got Unknown
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Expected O, but got Unknown
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Expected O, but got Unknown
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: 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);
			_raycaster = val.GetComponent<GraphicRaycaster>();
			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);
			_messageParent = val2.transform;
			PositionMessageContainer(component3);
			_historyPanel = new GameObject("HistoryPanel", new Type[1] { typeof(RectTransform) });
			RectTransform component4 = _historyPanel.GetComponent<RectTransform>();
			((Transform)component4).SetParent(val.transform, false);
			PositionHistoryPanel(component4);
			_historyPanel.SetActive(false);
			_historyScrollRect = _historyPanel.AddComponent<ScrollRect>();
			_historyScrollRect.horizontal = false;
			_historyScrollRect.vertical = true;
			_historyScrollRect.scrollSensitivity = 5f;
			_historyScrollRect.movementType = (MovementType)2;
			GameObject val3 = new GameObject("Viewport", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Mask)
			});
			_historyViewport = val3.GetComponent<RectTransform>();
			val3.transform.SetParent(_historyPanel.transform, false);
			_historyViewport.anchorMin = Vector2.zero;
			_historyViewport.anchorMax = Vector2.one;
			RectTransform historyViewport = _historyViewport;
			Vector2 offsetMin = (_historyViewport.offsetMax = Vector2.zero);
			historyViewport.offsetMin = offsetMin;
			Image component5 = val3.GetComponent<Image>();
			((Graphic)component5).color = BackColor;
			component5.type = (Type)0;
			((Graphic)component5).raycastTarget = true;
			Mask component6 = val3.GetComponent<Mask>();
			component6.showMaskGraphic = false;
			_historyScrollRect.viewport = _historyViewport;
			GameObject val4 = new GameObject("Content", new Type[3]
			{
				typeof(RectTransform),
				typeof(VerticalLayoutGroup),
				typeof(ContentSizeFitter)
			});
			RectTransform component7 = val4.GetComponent<RectTransform>();
			((Transform)component7).SetParent(val3.transform, false);