Decompiled source of ArchipelagoMod v0.2.2

plugins/Archipelago.MultiClient.Net.dll

Decompiled 4 months ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.WebSockets;
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.Cache;
using Archipelago.MultiClient.Net.ConcurrentCollection;
using Archipelago.MultiClient.Net.Converters;
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 = "")]
[assembly: AssemblyCompany("Jarno Westhof, Hussein Farran, Zach Parks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyDescription("A client library for use with .NET based prog-langs for interfacing with Archipelago hosts.")]
[assembly: AssemblyFileVersion("5.0.4.0")]
[assembly: AssemblyInformationalVersion("5.0.4")]
[assembly: AssemblyProduct("Archipelago.MultiClient.Net")]
[assembly: AssemblyTitle("Archipelago.MultiClient.Net")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/ArchipelagoMW/Archipelago.MultiClient.Net")]
[assembly: AssemblyVersion("5.0.4.0")]
internal interface IConcurrentHashSet<T>
{
	bool TryAdd(T item);

	bool Contains(T item);

	void UnionWith(T[] otherSet);

	T[] ToArray();

	ReadOnlyCollection<T> AsToReadOnlyCollection();

	ReadOnlyCollection<T> AsToReadOnlyCollectionExcept(IConcurrentHashSet<T> otherSet);
}
namespace Archipelago.MultiClient.Net
{
	[Serializable]
	public abstract class ArchipelagoPacketBase
	{
		[JsonIgnore]
		internal JObject jobject;

		[JsonProperty("cmd")]
		[JsonConverter(typeof(StringEnumConverter))]
		public abstract ArchipelagoPacketType PacketType { get; }

		public JObject ToJObject()
		{
			return jobject;
		}
	}
	public class ArchipelagoSession
	{
		private const int ArchipelagoConnectionTimeoutInSeconds = 4;

		private TaskCompletionSource<LoginResult> loginResultTask = new TaskCompletionSource<LoginResult>();

		private TaskCompletionSource<RoomInfoPacket> roomInfoPacketTask = new TaskCompletionSource<RoomInfoPacket>();

		public IArchipelagoSocketHelper Socket { get; }

		public ReceivedItemsHelper Items { get; }

		public LocationCheckHelper Locations { get; }

		public PlayerHelper Players { get; }

		public DataStorageHelper DataStorage { get; }

		public ConnectionInfoHelper ConnectionInfo { get; }

		public RoomStateHelper RoomState { get; }

		public MessageLogHelper MessageLog { get; }

		internal ArchipelagoSession(IArchipelagoSocketHelper socket, ReceivedItemsHelper items, LocationCheckHelper locations, PlayerHelper players, RoomStateHelper roomState, ConnectionInfoHelper connectionInfo, DataStorageHelper dataStorage, MessageLogHelper messageLog)
		{
			Socket = socket;
			Items = items;
			Locations = locations;
			Players = players;
			RoomState = roomState;
			ConnectionInfo = connectionInfo;
			DataStorage = dataStorage;
			MessageLog = messageLog;
			socket.PacketReceived += Socket_PacketReceived;
		}

		private void Socket_PacketReceived(ArchipelagoPacketBase packet)
		{
			if (!(packet is ConnectedPacket) && !(packet is ConnectionRefusedPacket))
			{
				if (packet is RoomInfoPacket result)
				{
					roomInfoPacketTask.TrySetResult(result);
				}
				return;
			}
			if (packet is ConnectedPacket && RoomState.Version != null && RoomState.Version >= new Version(0, 3, 8))
			{
				LogUsedVersion();
			}
			loginResultTask.TrySetResult(LoginResult.FromPacket(packet));
		}

		private void LogUsedVersion()
		{
			try
			{
				string fileVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion;
				Socket.SendPacketAsync(new SetPacket
				{
					Key = ".NetUsedVersions",
					DefaultValue = (JToken)(object)JObject.FromObject((object)new Dictionary<string, bool>()),
					Operations = new OperationSpecification[1] { Operation.Update(new Dictionary<string, bool> { 
					{
						ConnectionInfo.Game + ":" + fileVersion + ":NETSTANDARD2_0",
						true
					} }) }
				});
			}
			catch
			{
			}
		}

		public Task<RoomInfoPacket> ConnectAsync()
		{
			roomInfoPacketTask = new TaskCompletionSource<RoomInfoPacket>();
			Task.Factory.StartNew(delegate
			{
				try
				{
					Task task = Socket.ConnectAsync();
					task.Wait(TimeSpan.FromSeconds(4.0));
					if (!task.IsCompleted)
					{
						roomInfoPacketTask.TrySetCanceled();
					}
				}
				catch (AggregateException)
				{
					roomInfoPacketTask.TrySetCanceled();
				}
			});
			return roomInfoPacketTask.Task;
		}

		public Task<LoginResult> LoginAsync(string game, string name, ItemsHandlingFlags itemsHandlingFlags, Version version = null, string[] tags = null, string uuid = null, string password = null, bool requestSlotData = true)
		{
			loginResultTask = new TaskCompletionSource<LoginResult>();
			if (!roomInfoPacketTask.Task.IsCompleted)
			{
				loginResultTask = new TaskCompletionSource<LoginResult>();
				loginResultTask.SetResult(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.SetResult(new LoginFailure("You are not connected, run ConnectAsync() first"));
				return loginResultTask.Task;
			}
			SetResultAfterTimeout(loginResultTask, 4, new LoginFailure("Connection timed out."));
			return loginResultTask.Task;
		}

		private static void SetResultAfterTimeout<T>(TaskCompletionSource<T> task, int timeoutInSeconds, T result)
		{
			new CancellationTokenSource(TimeSpan.FromSeconds(timeoutInSeconds)).Token.Register(delegate
			{
				task.TrySetResult(result);
			});
		}

		public LoginResult TryConnectAndLogin(string game, string name, ItemsHandlingFlags itemsHandlingFlags, Version version = null, string[] tags = null, string uuid = null, string password = null, bool requestSlotData = true)
		{
			Task<RoomInfoPacket> task = ConnectAsync();
			try
			{
				task.Wait(TimeSpan.FromSeconds(4.0));
			}
			catch (AggregateException ex)
			{
				if (ex.GetBaseException() is OperationCanceledException)
				{
					return new LoginFailure("Connection timed out.");
				}
				return new LoginFailure(ex.GetBaseException().Message);
			}
			if (!task.IsCompleted)
			{
				return new LoginFailure("Connection timed out.");
			}
			return LoginAsync(game, name, itemsHandlingFlags, version, tags, uuid, password, requestSlotData).Result;
		}

		private ConnectPacket BuildConnectPacket(string name, string password, Version version, bool requestSlotData)
		{
			return new ConnectPacket
			{
				Game = ConnectionInfo.Game,
				Name = name,
				Password = password,
				Tags = ConnectionInfo.Tags,
				Uuid = ConnectionInfo.Uuid,
				Version = ((version != null) ? new NetworkVersion(version) : new NetworkVersion(0, 4, 0)),
				ItemsHandling = ConnectionInfo.ItemsHandlingFlags,
				RequestSlotData = requestSlotData
			};
		}
	}
	public static class ArchipelagoSessionFactory
	{
		public static ArchipelagoSession CreateSession(Uri uri)
		{
			ArchipelagoSocketHelper socket = new ArchipelagoSocketHelper(uri);
			DataPackageCache dataPackageCache = new DataPackageCache(socket);
			LocationCheckHelper locationCheckHelper = new LocationCheckHelper(socket, dataPackageCache);
			ReceivedItemsHelper items = new ReceivedItemsHelper(socket, locationCheckHelper, dataPackageCache);
			ConnectionInfoHelper connectionInfoHelper = new ConnectionInfoHelper(socket);
			PlayerHelper players = new PlayerHelper(socket, connectionInfoHelper);
			RoomStateHelper roomState = new RoomStateHelper(socket, locationCheckHelper);
			DataStorageHelper dataStorage = new DataStorageHelper(socket, connectionInfoHelper);
			MessageLogHelper messageLog = new MessageLogHelper(socket, items, locationCheckHelper, players, connectionInfoHelper);
			return new ArchipelagoSession(socket, items, locationCheckHelper, players, roomState, connectionInfoHelper, dataStorage, messageLog);
		}

		public static ArchipelagoSession CreateSession(string hostname, int port = 38281)
		{
			return CreateSession(ParseUri(hostname, port));
		}

		internal static Uri ParseUri(string hostname, int port)
		{
			string text = hostname;
			if (!text.StartsWith("ws://") && !text.StartsWith("wss://"))
			{
				text = "unspecified://" + text;
			}
			if (!text.Substring(text.IndexOf("://", StringComparison.Ordinal) + 3).Contains(":"))
			{
				text += $":{port}";
			}
			if (text.EndsWith(":"))
			{
				text += port;
			}
			return new Uri(text);
		}
	}
	public abstract class LoginResult
	{
		public abstract bool Successful { get; }

		public static LoginResult FromPacket(ArchipelagoPacketBase packet)
		{
			if (!(packet is ConnectedPacket connectedPacket))
			{
				if (packet is ConnectionRefusedPacket connectionRefusedPacket)
				{
					return new LoginFailure(connectionRefusedPacket);
				}
				throw new ArgumentOutOfRangeException("packet", "packet is not a connection result packet");
			}
			return new LoginSuccessful(connectedPacket);
		}
	}
	public class LoginSuccessful : LoginResult
	{
		public override bool Successful => true;

		public int Team { get; }

		public int Slot { get; }

		public Dictionary<string, object> SlotData { get; }

		public LoginSuccessful(ConnectedPacket connectedPacket)
		{
			Team = connectedPacket.Team;
			Slot = connectedPacket.Slot;
			SlotData = connectedPacket.SlotData;
		}
	}
	public class LoginFailure : LoginResult
	{
		public override bool Successful => false;

		public ConnectionRefusedError[] ErrorCodes { get; }

		public string[] Errors { get; }

		public LoginFailure(ConnectionRefusedPacket connectionRefusedPacket)
		{
			if (connectionRefusedPacket.Errors != null)
			{
				ErrorCodes = connectionRefusedPacket.Errors.ToArray();
				Errors = ErrorCodes.Select(GetErrorMessage).ToArray();
			}
			else
			{
				ErrorCodes = new ConnectionRefusedError[0];
				Errors = new string[0];
			}
		}

		public LoginFailure(string message)
		{
			ErrorCodes = new ConnectionRefusedError[0];
			Errors = new string[1] { message };
		}

		private static string GetErrorMessage(ConnectionRefusedError errorCode)
		{
			return errorCode switch
			{
				ConnectionRefusedError.InvalidSlot => "The slot name did not match any slot on the server.", 
				ConnectionRefusedError.InvalidGame => "The slot is set to a different game on the server.", 
				ConnectionRefusedError.SlotAlreadyTaken => "The slot already has a connection with a different uuid established.", 
				ConnectionRefusedError.IncompatibleVersion => "The client and server version mismatch.", 
				ConnectionRefusedError.InvalidPassword => "The password is invalid.", 
				ConnectionRefusedError.InvalidItemsHandling => "The item handling flags provided are invalid.", 
				_ => $"Unknown error: {errorCode}.", 
			};
		}
	}
}
namespace Archipelago.MultiClient.Net.Packets
{
	public class BouncedPacket : BouncePacket
	{
		public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Bounced;
	}
	public class BouncePacket : ArchipelagoPacketBase
	{
		public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Bounce;

		[JsonProperty("games")]
		public List<string> Games { get; set; } = new List<string>();


		[JsonProperty("slots")]
		public List<int> Slots { get; set; } = new List<int>();


		[JsonProperty("tags")]
		public List<string> Tags { get; set; } = new List<string>();


		[JsonProperty("data")]
		public Dictionary<string, JToken> Data { get; set; }
	}
	public class ConnectedPacket : ArchipelagoPacketBase
	{
		public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Connected;

		[JsonProperty("team")]
		public int Team { get; set; }

		[JsonProperty("slot")]
		public int Slot { get; set; }

		[JsonProperty("players")]
		public NetworkPlayer[] Players { get; set; }

		[JsonProperty("missing_locations")]
		public long[] MissingChecks { get; set; }

		[JsonProperty("checked_locations")]
		public long[] LocationsChecked { get; set; }

		[JsonProperty("slot_data")]
		public Dictionary<string, object> SlotData { get; set; }

		[JsonProperty("slot_info")]
		public Dictionary<int, NetworkSlot> SlotInfo { get; set; }

		[JsonProperty("hint_points")]
		public int? HintPoints { get; set; }
	}
	public class ConnectionRefusedPacket : ArchipelagoPacketBase
	{
		public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.ConnectionRefused;

		[JsonProperty("errors", ItemConverterType = typeof(StringEnumConverter))]
		public ConnectionRefusedError[] Errors { get; set; }
	}
	public class ConnectPacket : ArchipelagoPacketBase
	{
		public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Connect;

		[JsonProperty("password")]
		public string Password { get; set; }

		[JsonProperty("game")]
		public string Game { get; set; }

		[JsonProperty("name")]
		public string Name { get; set; }

		[JsonProperty("uuid")]
		public string Uuid { get; set; }

		[JsonProperty("version")]
		public NetworkVersion Version { get; set; }

		[JsonProperty("tags")]
		public string[] Tags { get; set; }

		[JsonProperty("items_handling")]
		public ItemsHandlingFlags ItemsHandling { get; set; }

		[JsonProperty("slot_data")]
		public bool RequestSlotData { get; set; }
	}
	public class ConnectUpdatePacket : ArchipelagoPacketBase
	{
		public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.ConnectUpdate;

		[JsonProperty("tags")]
		public string[] Tags { get; set; }

		[JsonProperty("items_handling")]
		public ItemsHandlingFlags? ItemsHandling { get; set; }
	}
	public class DataPackagePacket : ArchipelagoPacketBase
	{
		public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.DataPackage;

		[JsonProperty("data")]
		public 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 bool CreateAsHint { get; set; }
	}
	public class PrintJsonPacket : ArchipelagoPacketBase
	{
		public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.PrintJSON;

		[JsonProperty("data")]
		public JsonMessagePart[] Data { get; set; }

		[JsonProperty("type")]
		[JsonConverter(typeof(StringEnumConverter))]
		public JsonMessageType? MessageType { get; set; }
	}
	public class ItemPrintJsonPacket : PrintJsonPacket
	{
		[JsonProperty("receiving")]
		public int ReceivingPlayer { get; set; }

		[JsonProperty("item")]
		public NetworkItem Item { get; set; }
	}
	public class ItemCheatPrintJsonPacket : PrintJsonPacket
	{
		[JsonProperty("receiving")]
		public int ReceivingPlayer { get; set; }

		[JsonProperty("item")]
		public NetworkItem Item { get; set; }

		[JsonProperty("team")]
		public int Team { get; set; }
	}
	public class HintPrintJsonPacket : PrintJsonPacket
	{
		[JsonProperty("receiving")]
		public int ReceivingPlayer { get; set; }

		[JsonProperty("item")]
		public NetworkItem Item { get; set; }

		[JsonProperty("found")]
		public bool? Found { get; set; }
	}
	public class JoinPrintJsonPacket : PrintJsonPacket
	{
		[JsonProperty("team")]
		public int Team { get; set; }

		[JsonProperty("slot")]
		public int Slot { get; set; }

		[JsonProperty("tags")]
		public string[] Tags { get; set; }
	}
	public class LeavePrintJsonPacket : PrintJsonPacket
	{
		[JsonProperty("team")]
		public int Team { get; set; }

		[JsonProperty("slot")]
		public int Slot { get; set; }
	}
	public class ChatPrintJsonPacket : PrintJsonPacket
	{
		[JsonProperty("team")]
		public int Team { get; set; }

		[JsonProperty("slot")]
		public int Slot { get; set; }

		[JsonProperty("message")]
		public string Message { get; set; }
	}
	public class ServerChatPrintJsonPacket : PrintJsonPacket
	{
		[JsonProperty("message")]
		public string Message { get; set; }
	}
	public class TutorialPrintJsonPacket : PrintJsonPacket
	{
	}
	public class TagsChangedPrintJsonPacket : PrintJsonPacket
	{
		[JsonProperty("team")]
		public int Team { get; set; }

		[JsonProperty("slot")]
		public int Slot { get; set; }

		[JsonProperty("tags")]
		public string[] Tags { get; set; }
	}
	public class CommandResultPrintJsonPacket : PrintJsonPacket
	{
	}
	public class AdminCommandResultPrintJsonPacket : PrintJsonPacket
	{
	}
	public class GoalPrintJsonPacket : PrintJsonPacket
	{
		[JsonProperty("team")]
		public int Team { get; set; }

		[JsonProperty("slot")]
		public int Slot { get; set; }
	}
	public class ReleasePrintJsonPacket : PrintJsonPacket
	{
		[JsonProperty("team")]
		public int Team { get; set; }

		[JsonProperty("slot")]
		public int Slot { get; set; }
	}
	public class CollectPrintJsonPacket : PrintJsonPacket
	{
		[JsonProperty("team")]
		public int Team { get; set; }

		[JsonProperty("slot")]
		public int Slot { get; set; }
	}
	public class CountdownPrintJsonPacket : PrintJsonPacket
	{
		[JsonProperty("countdown")]
		public int RemainingSeconds { get; set; }
	}
	public class ReceivedItemsPacket : ArchipelagoPacketBase
	{
		public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.ReceivedItems;

		[JsonProperty("index")]
		public int Index { get; set; }

		[JsonProperty("items")]
		public NetworkItem[] Items { get; set; }
	}
	public class RetrievedPacket : ArchipelagoPacketBase
	{
		public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Retrieved;

		[JsonProperty("keys")]
		public Dictionary<string, JToken> Data { get; set; }
	}
	public class RoomInfoPacket : ArchipelagoPacketBase
	{
		public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.RoomInfo;

		[JsonProperty("version")]
		public NetworkVersion Version { get; set; }

		[JsonProperty("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; }

		[Obsolete("use DataPackageChecksums instead")]
		[JsonProperty("datapackage_versions")]
		public Dictionary<string, int> DataPackageVersions { 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; }

		public Guid? Reference { get; set; }
	}
	public class SetReplyPacket : ArchipelagoPacketBase
	{
		public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.SetReply;

		[JsonProperty("key")]
		public string Key { get; set; }

		[JsonProperty("value")]
		public JToken Value { get; set; }

		[JsonProperty("default")]
		public JToken DefaultValue { get; set; }

		[JsonProperty("original_value")]
		public JToken OriginalValue { get; set; }

		[JsonProperty("operation")]
		public string Operation { get; set; }

		[JsonProperty("want_reply")]
		public bool WantReply { get; set; }

		public Guid? Reference { get; set; }
	}
	public class StatusUpdatePacket : ArchipelagoPacketBase
	{
		public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.StatusUpdate;

		[JsonProperty("status")]
		public ArchipelagoClientState Status { get; set; }
	}
	public class SyncPacket : ArchipelagoPacketBase
	{
		public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Sync;
	}
	internal class UnknownPacket : ArchipelagoPacketBase
	{
		public override ArchipelagoPacketType PacketType => ArchipelagoPacketType.Unknown;
	}
}
namespace Archipelago.MultiClient.Net.Models
{
	public struct Color : IEquatable<Color>
	{
		public static Color Red = new Color(byte.MaxValue, 0, 0);

		public static Color Green = new Color(0, 128, 0);

		public static Color Yellow = new Color(byte.MaxValue, byte.MaxValue, 0);

		public static Color Blue = new Color(0, 0, byte.MaxValue);

		public static Color Magenta = new Color(byte.MaxValue, 0, byte.MaxValue);

		public static Color Cyan = new Color(0, byte.MaxValue, byte.MaxValue);

		public static Color Black = new Color(0, 0, 0);

		public static Color White = new Color(byte.MaxValue, byte.MaxValue, byte.MaxValue);

		public static Color SlateBlue = new Color(106, 90, 205);

		public static Color Salmon = new Color(250, 128, 114);

		public static Color Plum = new Color(221, 160, 221);

		public byte R { get; set; }

		public byte G { get; set; }

		public byte B { get; set; }

		public Color(byte r, byte g, byte b)
		{
			R = r;
			G = g;
			B = b;
		}

		public override bool Equals(object obj)
		{
			if (obj is Color color && R == color.R && G == color.G)
			{
				return B == color.B;
			}
			return false;
		}

		public bool Equals(Color other)
		{
			if (R == other.R && G == other.G)
			{
				return B == other.B;
			}
			return false;
		}

		public override int GetHashCode()
		{
			return ((-1520100960 * -1521134295 + R.GetHashCode()) * -1521134295 + G.GetHashCode()) * -1521134295 + B.GetHashCode();
		}

		public static bool operator ==(Color left, Color right)
		{
			return left.Equals(right);
		}

		public static bool operator !=(Color left, Color right)
		{
			return !(left == right);
		}
	}
	public class DataPackage
	{
		[JsonProperty("games")]
		public Dictionary<string, GameData> Games { get; set; } = new Dictionary<string, GameData>();

	}
	public class DataStorageElement
	{
		internal DataStorageElementContext Context;

		internal List<OperationSpecification> Operations = new List<OperationSpecification>(0);

		internal DataStorageHelper.DataStorageUpdatedHandler Callbacks;

		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();
			Operations.Add(new OperationSpecification
			{
				OperationType = operationType,
				Value = value
			});
			Callbacks = source.Callbacks;
		}

		internal DataStorageElement(DataStorageElement source, Callback callback)
			: this(source.Context)
		{
			Operations = source.Operations.ToList();
			Callbacks = source.Callbacks;
			Callbacks = (DataStorageHelper.DataStorageUpdatedHandler)Delegate.Combine(Callbacks, callback.Method);
		}

		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, 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, JToken b)
		{
			return new DataStorageElement(a, OperationType.Mul, b);
		}

		public static DataStorageElement operator %(DataStorageElement a, JToken b)
		{
			return new DataStorageElement(a, OperationType.Mod, b);
		}

		public static DataStorageElement operator ^(DataStorageElement a, JToken b)
		{
			return new DataStorageElement(a, OperationType.Pow, 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, decimal b)
		{
			return new DataStorageElement(a, OperationType.Add, JToken.FromObject((object)(-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, float b)
		{
			return new DataStorageElement(a, OperationType.Add, JToken.FromObject((object)(0f - 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, decimal b)
		{
			return new DataStorageElement(a, OperationType.Mul, JToken.FromObject((object)(1m / 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, float b)
		{
			return new DataStorageElement(a, OperationType.Mul, JToken.FromObject((object)(1.0 / (double)b)));
		}

		[Obsolete("Use + Operation.Min() instead")]
		public static DataStorageElement operator >>(DataStorageElement a, int b)
		{
			return new DataStorageElement(a, OperationType.Min, JToken.op_Implicit(b));
		}

		[Obsolete("Use + Operation.Max() instead")]
		public static DataStorageElement operator <<(DataStorageElement a, int b)
		{
			return new DataStorageElement(a, OperationType.Max, JToken.op_Implicit(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 decimal(DataStorageElement e)
		{
			return RetrieveAndReturnDecimalValue<decimal>(e);
		}

		public static implicit operator decimal?(DataStorageElement e)
		{
			return RetrieveAndReturnDecimalValue<decimal?>(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 float(DataStorageElement e)
		{
			return RetrieveAndReturnDecimalValue<float>(e);
		}

		public static implicit operator float?(DataStorageElement e)
		{
			return RetrieveAndReturnDecimalValue<float?>(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 void Initialize(JToken value)
		{
			Context.Initialize(Context.Key, value);
		}

		public void Initialize(IEnumerable value)
		{
			Context.Initialize(Context.Key, (JToken)(object)JArray.FromObject((object)value));
		}

		public Task<T> GetAsync<T>()
		{
			return GetAsync().ContinueWith((Task<JToken> r) => r.Result.ToObject<T>());
		}

		public Task<JToken> GetAsync()
		{
			return Context.GetAsync(Context.Key);
		}

		private static T RetrieveAndReturnArrayValue<T>(DataStorageElement e)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Invalid comparison between Unknown and I4
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Invalid comparison between Unknown and I4
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			if (e.cachedValue != null)
			{
				return ((JToken)(JArray)e.cachedValue).ToObject<T>();
			}
			JArray val = (JArray)(((object)e.Context.GetData(e.Context.Key).ToObject<JArray>()) ?? ((object)new JArray()));
			foreach (OperationSpecification operation in e.Operations)
			{
				switch (operation.OperationType)
				{
				case OperationType.Add:
					if ((int)operation.Value.Type != 2)
					{
						throw new InvalidOperationException($"Cannot perform operation {OperationType.Add} on Array value, with a non Array value: {operation.Value}");
					}
					((JContainer)val).Merge((object)operation.Value);
					break;
				case OperationType.Replace:
					if ((int)operation.Value.Type != 2)
					{
						throw new InvalidOperationException($"Cannot replace Array value, with a non Array value: {operation.Value}");
					}
					val = (JArray)(((object)operation.Value.ToObject<JArray>()) ?? ((object)new JArray()));
					break;
				default:
					throw new InvalidOperationException($"Cannot perform operation {operation.OperationType} on Array value");
				}
			}
			e.cachedValue = (JToken)(object)val;
			return ((JToken)val).ToObject<T>();
		}

		private static string RetrieveAndReturnStringValue(DataStorageElement e)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Invalid comparison between Unknown and I4
			if (e.cachedValue != null)
			{
				return (string)e.cachedValue;
			}
			JToken val = e.Context.GetData(e.Context.Key);
			string text = (((int)val.Type == 10) ? null : ((object)val).ToString());
			foreach (OperationSpecification operation in e.Operations)
			{
				switch (operation.OperationType)
				{
				case OperationType.Add:
					text += (string)operation.Value;
					break;
				case OperationType.Mul:
					if ((int)operation.Value.Type != 6)
					{
						throw new InvalidOperationException($"Cannot perform operation {OperationType.Mul} on string value, with a non interger value: {operation.Value}");
					}
					text = string.Concat(Enumerable.Repeat(text, (int)operation.Value));
					break;
				case OperationType.Replace:
					text = (string)operation.Value;
					break;
				default:
					throw new InvalidOperationException($"Cannot perform operation {operation.OperationType} on string value");
				}
			}
			if (text == null)
			{
				e.cachedValue = (JToken)(object)JValue.CreateNull();
			}
			else
			{
				e.cachedValue = JToken.op_Implicit(text);
			}
			return (string)e.cachedValue;
		}

		private static T RetrieveAndReturnBoolValue<T>(DataStorageElement e)
		{
			if (e.cachedValue != null)
			{
				return e.cachedValue.ToObject<T>();
			}
			bool? flag = e.Context.GetData(e.Context.Key).ToObject<bool?>() ?? ((bool?)Activator.CreateInstance(typeof(T)));
			foreach (OperationSpecification operation in e.Operations)
			{
				if (operation.OperationType == OperationType.Replace)
				{
					flag = (bool?)operation.Value;
					continue;
				}
				throw new InvalidOperationException($"Cannot perform operation {operation.OperationType} on boolean value");
			}
			e.cachedValue = JToken.op_Implicit(flag);
			if (!flag.HasValue)
			{
				return default(T);
			}
			return (T)Convert.ChangeType(flag.Value, IsNullable<T>() ? Nullable.GetUnderlyingType(typeof(T)) : typeof(T));
		}

		private static T RetrieveAndReturnDecimalValue<T>(DataStorageElement e)
		{
			if (e.cachedValue != null)
			{
				return e.cachedValue.ToObject<T>();
			}
			decimal? num = e.Context.GetData(e.Context.Key).ToObject<decimal?>();
			if (!num.HasValue && !IsNullable<T>())
			{
				num = Activator.CreateInstance<decimal>();
			}
			foreach (OperationSpecification operation in e.Operations)
			{
				switch (operation.OperationType)
				{
				case OperationType.Replace:
					num = (decimal)operation.Value;
					break;
				case OperationType.Add:
					num += (decimal?)(decimal)operation.Value;
					break;
				case OperationType.Mul:
					num *= (decimal?)(decimal)operation.Value;
					break;
				case OperationType.Mod:
					num %= (decimal?)(decimal)operation.Value;
					break;
				case OperationType.Pow:
					num = (decimal)Math.Pow((double)num.Value, (double)operation.Value);
					break;
				case OperationType.Max:
					num = Math.Max(num.Value, (decimal)operation.Value);
					break;
				case OperationType.Min:
					num = Math.Min(num.Value, (decimal)operation.Value);
					break;
				case OperationType.Xor:
					num = (long)num.Value ^ (long)operation.Value;
					break;
				case OperationType.Or:
					num = (long)num.Value | (long)operation.Value;
					break;
				case OperationType.And:
					num = (long)num.Value & (long)operation.Value;
					break;
				case OperationType.LeftShift:
					num = (long)num.Value << (int)operation.Value;
					break;
				case OperationType.RightShift:
					num = (long)num.Value >> (int)operation.Value;
					break;
				}
			}
			e.cachedValue = JToken.op_Implicit(num);
			if (!num.HasValue)
			{
				return default(T);
			}
			return (T)Convert.ChangeType(num.Value, IsNullable<T>() ? Nullable.GetUnderlyingType(typeof(T)) : typeof(T));
		}

		private static bool IsNullable<T>()
		{
			if (typeof(T).IsGenericType)
			{
				return typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>).GetGenericTypeDefinition();
			}
			return false;
		}

		public T To<T>()
		{
			if (Operations.Count != 0)
			{
				throw new InvalidOperationException("DataStorageElement.To<T>() cannot be used together with other operations on the DataStorageElement");
			}
			return Context.GetData(Context.Key).ToObject<T>();
		}

		public override string ToString()
		{
			return (Context?.ToString() ?? "(null)") + ", (" + ListOperations() + ")";
		}

		private string ListOperations()
		{
			if (Operations != null)
			{
				return string.Join(", ", Operations.Select((OperationSpecification o) => o.ToString()).ToArray());
			}
			return "none";
		}
	}
	internal class DataStorageElementContext
	{
		internal string Key { get; set; }

		internal Action<string, DataStorageHelper.DataStorageUpdatedHandler> AddHandler { get; set; }

		internal Action<string, DataStorageHelper.DataStorageUpdatedHandler> RemoveHandler { get; set; }

		internal Func<string, JToken> GetData { get; set; }

		internal Action<string, JToken> Initialize { get; set; }

		internal Func<string, Task<JToken>> GetAsync { get; set; }

		public override string ToString()
		{
			return "Key: " + Key;
		}
	}
	public class GameData
	{
		[JsonProperty("location_name_to_id")]
		public Dictionary<string, long> LocationLookup { get; set; } = new Dictionary<string, long>();


		[JsonProperty("item_name_to_id")]
		public Dictionary<string, long> ItemLookup { get; set; } = new Dictionary<string, long>();


		[Obsolete("use Checksum instead")]
		[JsonProperty("version")]
		public int Version { get; set; }

		[JsonProperty("checksum")]
		public string Checksum { get; set; }
	}
	public class Hint
	{
		[JsonProperty("receiving_player")]
		public int ReceivingPlayer { get; set; }

		[JsonProperty("finding_player")]
		public int FindingPlayer { get; set; }

		[JsonProperty("item")]
		public long ItemId { get; set; }

		[JsonProperty("location")]
		public long LocationId { get; set; }

		[JsonProperty("item_flags")]
		public ItemFlags ItemFlags { get; set; }

		[JsonProperty("found")]
		public bool Found { get; set; }

		[JsonProperty("entrance")]
		public string Entrance { get; set; }
	}
	public class JsonMessagePart
	{
		[JsonProperty("type")]
		[JsonConverter(typeof(StringEnumConverter), new object[] { typeof(SnakeCaseNamingStrategy) })]
		public JsonMessagePartType? Type { get; set; }

		[JsonProperty("color")]
		[JsonConverter(typeof(StringEnumConverter), new object[] { typeof(SnakeCaseNamingStrategy) })]
		public JsonMessagePartColor? Color { get; set; }

		[JsonProperty("text")]
		public string Text { get; set; }

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

		[JsonProperty("flags")]
		public ItemFlags? Flags { get; set; }
	}
	public struct NetworkItem
	{
		[JsonProperty("item")]
		public long Item { get; set; }

		[JsonProperty("location")]
		public long Location { get; set; }

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

		[JsonProperty("flags")]
		public ItemFlags Flags { get; set; }
	}
	public struct NetworkPlayer
	{
		[JsonProperty("team")]
		public int Team { get; set; }

		[JsonProperty("slot")]
		public int Slot { get; set; }

		[JsonProperty("alias")]
		public string Alias { get; set; }

		[JsonProperty("name")]
		public string Name { get; set; }
	}
	public struct NetworkSlot
	{
		[JsonProperty("name")]
		public string Name { get; set; }

		[JsonProperty("game")]
		public string Game { get; set; }

		[JsonProperty("type")]
		public SlotType Type { get; set; }

		[JsonProperty("group_members")]
		public int[] GroupMembers { get; set; }
	}
	public class NetworkVersion
	{
		[JsonProperty("major")]
		public int Major { get; set; }

		[JsonProperty("minor")]
		public int Minor { get; set; }

		[JsonProperty("build")]
		public int Build { get; set; }

		[JsonProperty("class")]
		public string Class => "Version";

		public NetworkVersion()
		{
		}

		public NetworkVersion(int major, int minor, int build)
		{
			Major = major;
			Minor = minor;
			Build = build;
		}

		public NetworkVersion(Version version)
		{
			Major = version.Major;
			Minor = version.Minor;
			Build = version.Build;
		}

		public Version ToVersion()
		{
			return new Version(Major, Minor, Build);
		}
	}
	public class OperationSpecification
	{
		[JsonProperty("operation")]
		[JsonConverter(typeof(StringEnumConverter), new object[] { typeof(SnakeCaseNamingStrategy) })]
		public OperationType OperationType;

		[JsonProperty("value")]
		public JToken Value { get; set; }

		public override string ToString()
		{
			return $"{OperationType}: {Value}";
		}
	}
	public static class Operation
	{
		public static OperationSpecification Min(JToken i)
		{
			return new OperationSpecification
			{
				OperationType = OperationType.Min,
				Value = i
			};
		}

		public static OperationSpecification Max(JToken i)
		{
			return new OperationSpecification
			{
				OperationType = OperationType.Max,
				Value = i
			};
		}

		public static OperationSpecification Remove(JToken value)
		{
			return new OperationSpecification
			{
				OperationType = OperationType.Remove,
				Value = 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 class Bitwise
	{
		public static OperationSpecification Xor(long i)
		{
			return new OperationSpecification
			{
				OperationType = OperationType.Xor,
				Value = JToken.op_Implicit(i)
			};
		}

		public static OperationSpecification Or(long i)
		{
			return new OperationSpecification
			{
				OperationType = OperationType.Or,
				Value = JToken.op_Implicit(i)
			};
		}

		public static OperationSpecification And(long i)
		{
			return new OperationSpecification
			{
				OperationType = OperationType.And,
				Value = JToken.op_Implicit(i)
			};
		}

		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
			};
		}
	}
}
namespace Archipelago.MultiClient.Net.MessageLog.Parts
{
	public class EntranceMessagePart : MessagePart
	{
		internal EntranceMessagePart(JsonMessagePart messagePart)
			: base(MessagePartType.Entrance, messagePart, Color.Blue)
		{
			base.Text = messagePart.Text;
		}
	}
	public class ItemMessagePart : MessagePart
	{
		public ItemFlags Flags { get; }

		public long ItemId { get; }

		internal ItemMessagePart(IReceivedItemsHelper items, JsonMessagePart part)
			: base(MessagePartType.Item, part)
		{
			Flags = part.Flags.GetValueOrDefault();
			base.Color = GetColor(Flags);
			JsonMessagePartType? type = part.Type;
			if (type.HasValue)
			{
				switch (type.GetValueOrDefault())
				{
				case JsonMessagePartType.ItemId:
					ItemId = long.Parse(part.Text);
					base.Text = items.GetItemName(ItemId) ?? $"Item: {ItemId}";
					break;
				case JsonMessagePartType.ItemName:
					ItemId = 0L;
					base.Text = part.Text;
					break;
				}
			}
		}

		private static Color GetColor(ItemFlags flags)
		{
			if (HasFlag(flags, ItemFlags.Advancement))
			{
				return Color.Plum;
			}
			if (HasFlag(flags, ItemFlags.NeverExclude))
			{
				return Color.SlateBlue;
			}
			if (HasFlag(flags, ItemFlags.Trap))
			{
				return Color.Salmon;
			}
			return Color.Cyan;
		}

		private static bool HasFlag(ItemFlags flags, ItemFlags flag)
		{
			return flags.HasFlag(flag);
		}
	}
	public class LocationMessagePart : MessagePart
	{
		public long LocationId { get; }

		internal LocationMessagePart(ILocationCheckHelper locations, JsonMessagePart part)
			: base(MessagePartType.Location, part, Color.Green)
		{
			JsonMessagePartType? type = part.Type;
			if (type.HasValue)
			{
				switch (type.GetValueOrDefault())
				{
				case JsonMessagePartType.LocationId:
					LocationId = long.Parse(part.Text);
					base.Text = locations.GetLocationNameFromId(LocationId) ?? $"Location: {LocationId}";
					break;
				case JsonMessagePartType.PlayerName:
					LocationId = 0L;
					base.Text = part.Text;
					break;
				}
			}
		}
	}
	public class MessagePart
	{
		public string Text { get; internal set; }

		public MessagePartType Type { get; internal set; }

		public Color Color { get; internal set; }

		public bool IsBackgroundColor { get; internal set; }

		internal MessagePart(MessagePartType type, JsonMessagePart messagePart, Color? color = null)
		{
			Type = type;
			Text = messagePart.Text;
			if (color.HasValue)
			{
				Color = color.Value;
			}
			else if (messagePart.Color.HasValue)
			{
				Color = GetColor(messagePart.Color.Value);
				IsBackgroundColor = messagePart.Color.Value >= JsonMessagePartColor.BlackBg;
			}
			else
			{
				Color = Color.White;
			}
		}

		private static Color GetColor(JsonMessagePartColor color)
		{
			switch (color)
			{
			case JsonMessagePartColor.Red:
			case JsonMessagePartColor.RedBg:
				return Color.Red;
			case JsonMessagePartColor.Green:
			case JsonMessagePartColor.GreenBg:
				return Color.Green;
			case JsonMessagePartColor.Yellow:
			case JsonMessagePartColor.YellowBg:
				return Color.Yellow;
			case JsonMessagePartColor.Blue:
			case JsonMessagePartColor.BlueBg:
				return Color.Blue;
			case JsonMessagePartColor.Magenta:
			case JsonMessagePartColor.MagentaBg:
				return Color.Magenta;
			case JsonMessagePartColor.Cyan:
			case JsonMessagePartColor.CyanBg:
				return Color.Cyan;
			case JsonMessagePartColor.Black:
			case JsonMessagePartColor.BlackBg:
				return Color.Black;
			case JsonMessagePartColor.White:
			case JsonMessagePartColor.WhiteBg:
				return Color.White;
			default:
				return Color.White;
			}
		}

		public override string ToString()
		{
			return Text;
		}
	}
	public enum MessagePartType
	{
		Text,
		Player,
		Item,
		Location,
		Entrance
	}
	public class PlayerMessagePart : MessagePart
	{
		public bool IsActivePlayer { get; }

		public int SlotId { get; }

		internal PlayerMessagePart(IPlayerHelper players, IConnectionInfoProvider connectionInfo, JsonMessagePart part)
			: base(MessagePartType.Player, part)
		{
			switch (part.Type)
			{
			case JsonMessagePartType.PlayerId:
				SlotId = int.Parse(part.Text);
				IsActivePlayer = SlotId == connectionInfo.Slot;
				base.Text = players.GetPlayerAlias(SlotId) ?? $"Player {SlotId}";
				break;
			case JsonMessagePartType.PlayerName:
				SlotId = 0;
				IsActivePlayer = false;
				base.Text = part.Text;
				break;
			}
			base.Color = GetColor(IsActivePlayer);
		}

		private static Color GetColor(bool isActivePlayer)
		{
			if (isActivePlayer)
			{
				return Color.Magenta;
			}
			return Color.Yellow;
		}
	}
}
namespace Archipelago.MultiClient.Net.MessageLog.Messages
{
	public class AdminCommandResultLogMessage : LogMessage
	{
		internal AdminCommandResultLogMessage(MessagePart[] parts)
			: base(parts)
		{
		}
	}
	public class ChatLogMessage : PlayerSpecificLogMessage
	{
		public string Message { get; }

		internal ChatLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot, string message)
			: base(parts, players, connectionInfo, team, slot)
		{
			Message = message;
		}
	}
	public class CollectLogMessage : PlayerSpecificLogMessage
	{
		internal CollectLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot)
			: base(parts, players, connectionInfo, team, slot)
		{
		}
	}
	public class CommandResultLogMessage : LogMessage
	{
		internal CommandResultLogMessage(MessagePart[] parts)
			: base(parts)
		{
		}
	}
	public class CountdownLogMessage : LogMessage
	{
		public int RemainingSeconds { get; }

		internal CountdownLogMessage(MessagePart[] parts, int remainingSeconds)
			: base(parts)
		{
			RemainingSeconds = remainingSeconds;
		}
	}
	public class GoalLogMessage : PlayerSpecificLogMessage
	{
		internal GoalLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot)
			: base(parts, players, connectionInfo, team, slot)
		{
		}
	}
	public class HintItemSendLogMessage : ItemSendLogMessage
	{
		public bool IsFound { get; }

		internal HintItemSendLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int receiver, int sender, NetworkItem item, bool found)
			: base(parts, players, connectionInfo, receiver, sender, item)
		{
			IsFound = found;
		}
	}
	public class ItemCheatLogMessage : ItemSendLogMessage
	{
		internal ItemCheatLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot, NetworkItem item)
			: base(parts, players, connectionInfo, slot, 0, item, team)
		{
		}
	}
	public class ItemSendLogMessage : LogMessage
	{
		[Obsolete("Use Receiver.Slot instead")]
		public int ReceivingPlayerSlot { get; }

		[Obsolete("Use Sender.Slot instead")]
		public int SendingPlayerSlot { get; }

		public PlayerInfo Receiver { get; }

		public PlayerInfo Sender { get; }

		public bool IsReceiverTheActivePlayer { get; }

		public bool IsSenderTheActivePlayer { get; }

		public bool IsRelatedToActivePlayer { get; }

		public NetworkItem Item { get; }

		internal ItemSendLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int receiver, int sender, NetworkItem item)
			: this(parts, players, connectionInfo, receiver, sender, item, connectionInfo.Team)
		{
		}

		internal ItemSendLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int receiver, int sender, NetworkItem item, int team)
			: base(parts)
		{
			ReadOnlyDictionary<int, ReadOnlyCollection<PlayerInfo>> players2 = players.Players;
			ReceivingPlayerSlot = receiver;
			SendingPlayerSlot = sender;
			IsReceiverTheActivePlayer = connectionInfo.Team == team && connectionInfo.Slot == receiver;
			IsSenderTheActivePlayer = connectionInfo.Team == team && connectionInfo.Slot == sender;
			Receiver = ((players2.Count > team && players2[team].Count > receiver) ? players2[team][receiver] : new PlayerInfo());
			Sender = ((players2.Count > team && players2[team].Count > sender) ? players2[team][sender] : new PlayerInfo());
			IsRelatedToActivePlayer = IsReceiverTheActivePlayer || IsSenderTheActivePlayer || Receiver.IsSharingGroupWith(connectionInfo.Team, connectionInfo.Slot) || Sender.IsSharingGroupWith(connectionInfo.Team, connectionInfo.Slot);
			Item = item;
		}
	}
	public class JoinLogMessage : PlayerSpecificLogMessage
	{
		public string[] Tags { get; }

		internal JoinLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot, string[] tags)
			: base(parts, players, connectionInfo, team, slot)
		{
			Tags = tags;
		}
	}
	public class LeaveLogMessage : PlayerSpecificLogMessage
	{
		internal LeaveLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot)
			: base(parts, players, connectionInfo, team, slot)
		{
		}
	}
	public class LogMessage
	{
		public MessagePart[] Parts { get; }

		internal LogMessage(MessagePart[] parts)
		{
			Parts = parts;
		}

		public override string ToString()
		{
			if (Parts.Length == 1)
			{
				return Parts[0].Text;
			}
			StringBuilder stringBuilder = new StringBuilder();
			MessagePart[] parts = Parts;
			foreach (MessagePart messagePart in parts)
			{
				stringBuilder.Append(messagePart.Text);
			}
			return stringBuilder.ToString();
		}
	}
	public abstract class PlayerSpecificLogMessage : LogMessage
	{
		public PlayerInfo Player { get; }

		public bool IsActivePlayer { get; }

		public bool IsRelatedToActivePlayer { get; }

		internal PlayerSpecificLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot)
			: base(parts)
		{
			ReadOnlyDictionary<int, ReadOnlyCollection<PlayerInfo>> players2 = players.Players;
			IsActivePlayer = connectionInfo.Team == team && connectionInfo.Slot == slot;
			Player = ((players2.Count > team && players2[team].Count > slot) ? players2[team][slot] : new PlayerInfo());
			IsRelatedToActivePlayer = IsActivePlayer || Player.IsSharingGroupWith(connectionInfo.Team, connectionInfo.Slot);
		}
	}
	public class ReleaseLogMessage : PlayerSpecificLogMessage
	{
		internal ReleaseLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot)
			: base(parts, players, connectionInfo, team, slot)
		{
		}
	}
	public class ServerChatLogMessage : LogMessage
	{
		public string Message { get; }

		internal ServerChatLogMessage(MessagePart[] parts, string message)
			: base(parts)
		{
			Message = message;
		}
	}
	public class TagsChangedLogMessage : PlayerSpecificLogMessage
	{
		public string[] Tags { get; }

		internal TagsChangedLogMessage(MessagePart[] parts, IPlayerHelper players, IConnectionInfoProvider connectionInfo, int team, int slot, string[] tags)
			: base(parts, players, connectionInfo, team, slot)
		{
			Tags = tags;
		}
	}
	public class TutorialLogMessage : LogMessage
	{
		internal TutorialLogMessage(MessagePart[] parts)
			: base(parts)
		{
		}
	}
}
namespace Archipelago.MultiClient.Net.Helpers
{
	public class ArchipelagoSocketHelper : IArchipelagoSocketHelper
	{
		private static readonly ArchipelagoPacketConverter Converter = new ArchipelagoPacketConverter();

		private const int ReceiveChunkSize = 1024;

		private const int SendChunkSize = 1024;

		private readonly ConcurrentQueue<Tuple<ArchipelagoPacketBase, TaskCompletionSource<bool>>> sendQueue = new ConcurrentQueue<Tuple<ArchipelagoPacketBase, TaskCompletionSource<bool>>>();

		internal ClientWebSocket webSocket;

		public Uri Uri { get; }

		public bool Connected
		{
			get
			{
				if (webSocket.State != WebSocketState.Open)
				{
					return webSocket.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 ArchipelagoSocketHelper(Uri hostUri)
		{
			Uri = hostUri;
			webSocket = new ClientWebSocket();
		}

		public async Task ConnectAsync()
		{
			await ConnectToProvidedUri(Uri);
			if (this.SocketOpened != null)
			{
				this.SocketOpened();
			}
			Task.Run((Func<Task?>)PollingLoop);
			Task.Run((Func<Task?>)SendLoop);
		}

		private async Task ConnectToProvidedUri(Uri uri)
		{
			if (uri.Scheme != "unspecified")
			{
				await webSocket.ConnectAsync(uri, CancellationToken.None);
				return;
			}
			try
			{
				await ConnectToProvidedUri(uri.AsWss());
				if (webSocket.State == WebSocketState.Open)
				{
					return;
				}
			}
			catch
			{
				webSocket = new ClientWebSocket();
			}
			await ConnectToProvidedUri(uri.AsWs());
		}

		private async Task PollingLoop()
		{
			byte[] buffer = new byte[1024];
			while (webSocket.State == WebSocketState.Open)
			{
				string message = null;
				try
				{
					message = await ReadMessageAsync(buffer);
				}
				catch (Exception e)
				{
					OnError(e);
				}
				OnMessageReceived(message);
			}
		}

		private async Task SendLoop()
		{
			while (webSocket.State == WebSocketState.Open)
			{
				try
				{
					await HandleSendBuffer();
				}
				catch (Exception e)
				{
					OnError(e);
				}
			}
		}

		private async Task<string> ReadMessageAsync(byte[] buffer)
		{
			StringBuilder stringResult = new StringBuilder();
			WebSocketReceiveResult result;
			do
			{
				result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
				if (result.MessageType == WebSocketMessageType.Close)
				{
					await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
					OnSocketClosed();
				}
				else
				{
					stringResult.Append(Encoding.UTF8.GetString(buffer, 0, result.Count));
				}
			}
			while (!result.EndOfMessage);
			return stringResult.ToString();
		}

		public async Task DisconnectAsync()
		{
			await webSocket.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.Enqueue(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>> result;
			while (sendQueue.TryDequeue(out result))
			{
				list.Add(result.Item1);
				tasks.Add(result.Item2);
			}
			if (!list.Any())
			{
				return;
			}
			if (webSocket.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 / 1024.0);
			for (int i = 0; i < messagesCount; i++)
			{
				int num = 1024 * i;
				int num2 = 1024;
				bool endOfMessage = i + 1 == messagesCount;
				if (num2 * (i + 1) > messageBuffer.Length)
				{
					num2 = messageBuffer.Length - num;
				}
				await webSocket.SendAsync(new ArraySegment<byte>(messageBuffer, num, num2), WebSocketMessageType.Text, endOfMessage, CancellationToken.None);
			}
			foreach (TaskCompletionSource<bool> item in tasks)
			{
				item.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 = JsonConvert.DeserializeObject<List<ArchipelagoPacketBase>>(message, (JsonConverter[])(object)new JsonConverter[1] { Converter });
				if (list == null)
				{
					return;
				}
				foreach (ArchipelagoPacketBase item in list)
				{
					this.PacketReceived(item);
				}
			}
			catch (Exception e)
			{
				OnError(e);
			}
		}

		private 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);
			}
		}
	}
	internal 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();
				}
			}
			else
			{
				Team = connectedPacket.Team;
				Slot = connectedPacket.Slot;
			}
		}

		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 class DataStorageHelper
	{
		public delegate void DataStorageUpdatedHandler(JToken originalValue, JToken newValue);

		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)
		{
			if (!(packet is RetrievedPacket retrievedPacket))
			{
				if (packet is SetReplyPacket setReplyPacket)
				{
					if (setReplyPacket.Reference.HasValue && operationSpecificCallbacks.TryGetValue(setReplyPacket.Reference.Value, out var value))
					{
						value(setReplyPacket.OriginalValue, setReplyPacket.Value);
						operationSpecificCallbacks.Remove(setReplyPacket.Reference.Value);
					}
					if (onValueChangedEventHandlers.TryGetValue(setReplyPacket.Key, out var value2))
					{
						value2(setReplyPacket.OriginalValue, setReplyPacket.Value);
					}
				}
				return;
			}
			foreach (KeyValuePair<string, JToken> datum in retrievedPacket.Data)
			{
				if (asyncRetrievalTasks.TryGetValue(datum.Key, out var value3))
				{
					value3.SetResult(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)
				});
			}
			if (e.Callbacks != null)
			{
				Guid guid = Guid.NewGuid();
				operationSpecificCallbacks[guid] = e.Callbacks;
				socket.SendPacketAsync(new SetPacket
				{
					Key = key,
					Operations = e.Operations.ToArray(),
					WantReply = true,
					Reference = guid
				});
			}
			else
			{
				socket.SendPacketAsync(new SetPacket
				{
					Key = key,
					Operations = e.Operations.ToArray()
				});
			}
		}

		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)];
		}

		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)
			{
				onHintsUpdated(newValue.ToObject<Hint[]>());
			};
			if (retrieveCurrentlyUnlockedHints)
			{
				GetHintsAsync(slot, team).ContinueWith(delegate(Task<Hint[]> t)
				{
					onHintsUpdated(t.Result);
				});
			}
		}

		public Dictionary<string, object> GetSlotData(int? slot = null)
		{
			return GetSlotDataElement(slot).To<Dictionary<string, object>>();
		}

		public Task<Dictionary<string, object>> GetSlotDataAsync(int? slot = null)
		{
			return GetSlotDataElement(slot).GetAsync<Dictionary<string, object>>();
		}

		public Dictionary<string, string[]> GetItemNameGroups(string game = null)
		{
			return GetItemNameGroupsElement(game).To<Dictionary<string, string[]>>();
		}

		public Task<Dictionary<string, string[]>> GetItemNameGroupsAsync(string game = null)
		{
			return GetItemNameGroupsElement(game).GetAsync<Dictionary<string, string[]>>();
		}
	}
	public class ArchipelagoSocketHelperDelagates
	{
		public delegate void PacketReceivedHandler(ArchipelagoPacketBase packet);

		public delegate void PacketsSentHandler(ArchipelagoPacketBase[] packets);

		public delegate void ErrorReceivedHandler(Exception e, string message);

		public delegate void SocketClosedHandler(string reason);

		public delegate void SocketOpenedHandler();
	}
	public interface IArchipelagoSocketHelper
	{
		Uri Uri { get; }

		bool Connected { get; }

		event ArchipelagoSocketHelperDelagates.PacketReceivedHandler PacketReceived;

		event ArchipelagoSocketHelperDelagates.PacketsSentHandler PacketsSent;

		event ArchipelagoSocketHelperDelagates.ErrorReceivedHandler ErrorReceived;

		event ArchipelagoSocketHelperDelagates.SocketClosedHandler SocketClosed;

		event ArchipelagoSocketHelperDelagates.SocketOpenedHandler SocketOpened;

		void SendPacket(ArchipelagoPacketBase packet);

		void SendMultiplePackets(List<ArchipelagoPacketBase> packets);

		void SendMultiplePackets(params ArchipelagoPacketBase[] packets);

		Task ConnectAsync();

		Task DisconnectAsync();

		Task SendPacketAsync(ArchipelagoPacketBase packet);

		Task SendMultiplePacketsAsync(List<ArchipelagoPacketBase> packets);

		Task SendMultiplePacketsAsync(params ArchipelagoPacketBase[] packets);
	}
	public interface ILocationCheckHelper
	{
		ReadOnlyCollection<long> AllLocations { get; }

		ReadOnlyCollection<long> AllLocationsChecked { get; }

		ReadOnlyCollection<long> AllMissingLocations { get; }

		void CompleteLocationChecks(params long[] ids);

		Task CompleteLocationChecksAsync(params long[] ids);

		long GetLocationIdFromName(string game, string locationName);

		string GetLocationNameFromId(long locationId);
	}
	public class LocationCheckHelper : ILocationCheckHelper
	{
		public delegate void CheckedLocationsUpdatedHandler(ReadOnlyCollection<long> newCheckedLocations);

		private readonly IConcurrentHashSet<long> allLocations = new ConcurrentHashSet<long>();

		private readonly IConcurrentHashSet<long> locationsChecked = new ConcurrentHashSet<long>();

		private readonly IConcurrentHashSet<long> serverConfirmedChecks = new ConcurrentHashSet<long>();

		private ReadOnlyCollection<long> missingLocations = new ReadOnlyCollection<long>(new long[0]);

		private readonly IArchipelagoSocketHelper socket;

		private readonly IDataPackageCache cache;

		private bool awaitingLocationInfoPacket;

		private TaskCompletionSource<LocationInfoPacket> locationInfoPacketCallbackTask;

		private Dictionary<string, Dictionary<string, long>> gameLocationNameToIdMapping;

		private Dictionary<long, string> locationIdToNameMapping;

		public ReadOnlyCollection<long> AllLocations => allLocations.AsToReadOnlyCollection();

		public ReadOnlyCollection<long> AllLocationsChecked => locationsChecked.AsToReadOnlyCollection();

		public ReadOnlyCollection<long> AllMissingLocations => missingLocations;

		public event CheckedLocationsUpdatedHandler CheckedLocationsUpdated;

		internal LocationCheckHelper(IArchipelagoSocketHelper socket, IDataPackageCache cache)
		{
			this.socket = socket;
			this.cache = cache;
			socket.PacketReceived += Socket_PacketReceived;
		}

		private void Socket_PacketReceived(ArchipelagoPacketBase packet)
		{
			if (!(packet is ConnectedPacket connectedPacket))
			{
				if (!(packet is RoomUpdatePacket roomUpdatePacket))
				{
					if (!(packet is LocationInfoPacket result))
					{
						if (packet is InvalidPacketPacket invalidPacketPacket && awaitingLocationInfoPacket && invalidPacketPacket.OriginalCmd == ArchipelagoPacketType.LocationScouts)
						{
							locationInfoPacketCallbackTask.TrySetException(new ArchipelagoServerRejectedPacketException(invalidPacketPacket.OriginalCmd, invalidPacketPacket.ErrorType, "location scout rejected by the server: " + invalidPacketPacket.ErrorText));
							awaitingLocationInfoPacket = false;
							locationInfoPacketCallbackTask = null;
						}
					}
					else if (awaitingLocationInfoPacket)
					{
						if (locationInfoPacketCallbackTask != null)
						{
							locationInfoPacketCallbackTask.SetResult(result);
						}
						awaitingLocationInfoPacket = false;
						locationInfoPacketCallbackTask = null;
					}
				}
				else
				{
					CheckLocations(roomUpdatePacket.CheckedLocations);
					if (roomUpdatePacket.CheckedLocations != null)
					{
						serverConfirmedChecks.UnionWith(roomUpdatePacket.CheckedLocations);
					}
				}
			}
			else
			{
				allLocations.UnionWith(connectedPacket.LocationsChecked);
				allLocations.UnionWith(connectedPacket.MissingChecks);
				serverConfirmedChecks.UnionWith(connectedPacket.LocationsChecked);
				missingLocations = new ReadOnlyCollection<long>(connectedPacket.MissingChecks);
				CheckLocations(connectedPacket.LocationsChecked);
			}
		}

		public void CompleteLocationChecks(params long[] ids)
		{
			CheckLocations(ids);
			LocationChecksPacket locationChecksPacket = GetLocationChecksPacket();
			if (locationChecksPacket.Locations.Any())
			{
				socket.SendPacket(locationChecksPacket);
			}
		}

		public Task CompleteLocationChecksAsync(params long[] ids)
		{
			return Task.Factory.StartNew(delegate
			{
				CheckLocations(ids);
			}).ContinueWith(delegate
			{
				if (GetLocationChecksPacket().Locations.Any())
				{
					socket.SendPacketAsync(GetLocationChecksPacket());
				}
			});
		}

		private LocationChecksPacket GetLocationChecksPacket()
		{
			return new LocationChecksPacket
			{
				Locations = locationsChecked.AsToReadOnlyCollectionExcept(serverConfirmedChecks).ToArray()
			};
		}

		public Task<LocationInfoPacket> ScoutLocationsAsync(bool createAsHint, params long[] ids)
		{
			locationInfoPacketCallbackTask = new TaskCompletionSource<LocationInfoPacket>();
			awaitingLocationInfoPacket = true;
			socket.SendPacket(new LocationScoutsPacket
			{
				Locations = ids,
				CreateAsHint = createAsHint
			});
			return locationInfoPacketCallbackTask.Task;
		}

		public Task<LocationInfoPacket> ScoutLocationsAsync(params long[] ids)
		{
			return ScoutLocationsAsync(createAsHint: false, ids);
		}

		public long GetLocationIdFromName(string game, string locationName)
		{
			if (!cache.TryGetDataPackageFromCache(out var package))
			{
				return -1L;
			}
			if (gameLocationNameToIdMapping == null)
			{
				gameLocationNameToIdMapping = package.Games.ToDictionary((KeyValuePair<string, GameData> x) => x.Key, (KeyValuePair<string, GameData> x) => x.Value.LocationLookup.ToDictionary((KeyValuePair<string, long> y) => y.Key, (KeyValuePair<string, long> y) => y.Value));
			}
			if (!gameLocationNameToIdMapping.TryGetValue(game, out var value))
			{
				return -1L;
			}
			if (!value.TryGetValue(locationName, out var value2))
			{
				return -1L;
			}
			return value2;
		}

		public string GetLocationNameFromId(long locationId)
		{
			if (!cache.TryGetDataPackageFromCache(out var package))
			{
				return null;
			}
			if (locationIdToNameMapping == null)
			{
				locationIdToNameMapping = package.Games.Select((KeyValuePair<string, GameData> x) => x.Value).SelectMany((GameData x) => x.LocationLookup).ToDictionary((KeyValuePair<string, long> x) => x.Value, (KeyValuePair<string, long> x) => x.Key);
			}
			if (!locationIdToNameMapping.TryGetValue(locationId, out var value))
			{
				return null;
			}
			return value;
		}

		private void CheckLocations(ICollection<long> locationIds)
		{
			if (locationIds == null || !locationIds.Any())
			{
				return;
			}
			List<long> list = new List<long>();
			foreach (long locationId in locationIds)
			{
				allLocations.TryAdd(locationId);
				if (locationsChecked.TryAdd(locationId))
				{
					list.Add(locationId);
				}
			}
			missingLocations = allLocations.AsToReadOnlyCollectionExcept(locationsChecked);
			if (list.Any())
			{
				this.CheckedLocationsUpdated?.Invoke(new ReadOnlyCollection<long>(list));
			}
		}
	}
	public class MessageLogHelper
	{
		public delegate void MessageReceivedHandler(LogMessage message);

		private readonly IReceivedItemsHelper items;

		private readonly ILocationCheckHelper locations;

		private readonly IPlayerHelper players;

		private readonly IConnectionInfoProvider connectionInfo;

		public event MessageReceivedHandler OnMessageReceived;

		internal MessageLogHelper(IArchipelagoSocketHelper socket, IReceivedItemsHelper items, ILocationCheckHelper locations, IPlayerHelper players, IConnectionInfoProvider connectionInfo)
		{
			this.items = items;
			this.locations = locations;
			this.players = players;
			this.connectionInfo = connectionInfo;
			socket.PacketReceived += Socket_PacketReceived;
		}

		private void Socket_PacketReceived(ArchipelagoPacketBase packet)
		{
			if (this.OnMessageReceived != null && packet is PrintJsonPacket printJsonPacket)
			{
				TriggerOnMessageReceived(printJsonPacket);
			}
		}

		private void TriggerOnMessageReceived(PrintJsonPacket printJsonPacket)
		{
			foreach (PrintJsonPacket item in SplitPacketsPerLine(printJsonPacket))
			{
				MessagePart[] parsedData = GetParsedData(item);
				LogMessage message = ((item is ItemPrintJsonPacket itemPrintJsonPacket) ? new ItemSendLogMessage(parsedData, players, connectionInfo, itemPrintJsonPacket.ReceivingPlayer, itemPrintJsonPacket.Item.Player, itemPrintJsonPacket.Item) : ((item is ItemCheatPrintJsonPacket itemCheatPrintJsonPacket) ? new ItemCheatLogMessage(parsedData, players, connectionInfo, itemCheatPrintJsonPacket.Team, itemCheatPrintJsonPacket.ReceivingPlayer, itemCheatPrintJsonPacket.Item) : ((item is HintPrintJsonPacket hintPrintJsonPacket) ? new HintItemSendLogMessage(parsedData, players, connectionInfo, hintPrintJsonPacket.ReceivingPlayer, hintPrintJsonPacket.Item.Player, hintPrintJsonPacket.Item, hintPrintJsonPacket.Found.HasValue && hintPrintJsonPacket.Found.Value) : ((item is JoinPrintJsonPacket joinPrintJsonPacket) ? new JoinLogMessage(parsedData, players, connectionInfo, joinPrintJsonPacket.Team, joinPrintJsonPacket.Slot, joinPrintJsonPacket.Tags) : ((item is LeavePrintJsonPacket leavePrintJsonPacket) ? new LeaveLogMessage(parsedData, players, connectionInfo, leavePrintJsonPacket.Team, leavePrintJsonPacket.Slot) : ((item is ChatPrintJsonPacket chatPrintJsonPacket) ? new ChatLogMessage(parsedData, players, connectionInfo, chatPrintJsonPacket.Team, chatPrintJsonPacket.Slot, chatPrintJsonPacket.Message) : ((item is ServerChatPrintJsonPacket serverChatPrintJsonPacket) ? new ServerChatLogMessage(parsedData, serverChatPrintJsonPacket.Message) : ((item is TutorialPrintJsonPacket) ? new TutorialLogMessage(parsedData) : ((item is TagsChangedPrintJsonPacket tagsChangedPrintJsonPacket) ? new TagsChangedLogMessage(parsedData, players, connectionInfo, tagsChangedPrintJsonPacket.Team, tagsChangedPrintJsonPacket.Slot, tagsChangedPrintJsonPacket.Tags) : ((item is CommandResultPrintJsonPacket) ? new CommandResultLogMessage(parsedData) : ((item is AdminCommandResultPrintJsonPacket) ? new AdminCommandResultLogMessage(parsedData) : ((item is GoalPrintJsonPacket goalPrintJsonPacket) ? new GoalLogMessage(parsedData, players, connectionInfo, goalPrintJsonPacket.Team, goalPrintJsonPacket.Slot) : ((item is ReleasePrintJsonPacket releasePrintJsonPacket) ? new ReleaseLogMessage(parsedData, players, connectionInfo, releasePrintJsonPacket.Team, releasePrintJsonPacket.Slot) : ((item is CollectPrintJsonPacket collectPrintJsonPacket) ? new CollectLogMessage(parsedData, players, connectionInfo, collectPrintJsonPacket.Team, collectPrintJsonPacket.Slot) : ((!(item is CountdownPrintJsonPacket countdownPrintJsonPacket)) ? new LogMessage(parsedData) : new CountdownLogMessage(parsedData, countdownPrintJsonPacket.RemainingSeconds))))))))))))))));
				this.OnMessageReceived?.Invoke(message);
			}
		}

		private static IEnumerable<PrintJsonPacket> SplitPacketsPerLine(PrintJsonPacket printJsonPacket)
		{
			List<PrintJsonPacket> list = new List<PrintJsonPacket>();
			List<JsonMessagePart> list2 = new List<JsonMessagePart>();
			JsonMessagePart[] data = printJsonPacket.Data;
			foreach (JsonMessagePart jsonMessagePart in data)
			{
				string[] array = jsonMessagePart.Text.Split(new char[1] { '\n' });
				for (int j = 0; j < array.Length; j++)
				{
					string text = array[j];
					list2.Add(new JsonMessagePart
					{
						Text = text,
						Type = jsonMessagePart.Type,
						Color = jsonMessagePart.Color,
						Flags = jsonMessagePart.Flags,
						Player = jsonMessagePart.Player
					});
					if (j < array.Length - 1)
					{
						PrintJsonPacket printJsonPacket2 = CloneWithoutData(printJsonPacket);
						printJsonPacket2.Data = list2.ToArray();
						list.Add(printJsonPacket2);
						list2 = new List<JsonMessagePart>();
					}
				}
			}
			PrintJsonPacket printJsonPacket3 = CloneWithoutData(printJsonPacket);
			printJsonPacket3.Data = list2.ToArray();
			list.Add(printJsonPacket3);
			return list;
		}

		private static PrintJsonPacket CloneWithoutData(PrintJsonPacket source)
		{
			if (!(source is ItemPrintJsonPacket itemPrintJsonPacket))
			{
				if (!(source is ItemCheatPrintJsonPacket itemCheatPrintJsonPacket))
				{
					if (!(source is HintPrintJsonPacket hintPrintJsonPacket))
					{
						if (!(source is JoinPrintJsonPacket joinPrintJsonPacket))
						{
							if (!(source is LeavePrintJsonPacket leavePrintJsonPacket))
							{
								if (!(source is ChatPrintJsonPacket chatPrintJsonPacket))
								{
									if (!(source is ServerChatPrintJsonPacket serverChatPrintJsonPacket))
									{
										if (!(source is TutorialPrintJsonPacket tutorialPrintJsonPacket))
										{
											if (!(source is TagsChangedPrintJsonPacket tagsChangedPrintJsonPacket))
											{
												if (!(source is CommandResultPrintJsonPacket commandResultPrintJsonPacket))
												{
													if (!(source is AdminCommandResultPrintJsonPacket adminCommandResultPrintJsonPacket))
													{
														if (!(source is GoalPrintJsonPacket goalPrintJsonPacket))
														{
															if (!(source is ReleasePrintJsonPacket releasePrintJsonPacket))
															{
																if (!(source is CollectPrintJsonPacket collectPrintJsonPacket))
																{
																	if (source is CountdownPrintJsonPacket countdownPrintJsonPacket)
																	{
																		return new CountdownPrintJsonPacket
																		{
																			RemainingSeconds = countdownPrintJsonPacket.RemainingSeconds
																		};
																	}
																	return new PrintJsonPacket
																	{
																		MessageType = source.MessageType
																	};
																}
																return new CollectPrintJsonPacket
																{
																	MessageType = collectPrintJsonPacket.MessageType,
																	Team = collectPrintJsonPacket.Team,
																	Slot = collectPrintJsonPacket.Slot
																};
															}
															return new ReleasePrintJsonPacket
															{
																MessageType = releasePrintJsonPacket.MessageType,
																Team = releasePrintJsonPacket.Team,
																Slot = releasePrintJsonPacket.Slot
															};
														}
														return new GoalPrintJsonPacket
														{
															MessageType = goalPrintJsonPacket.MessageType,
															Team = goalPrintJsonPacket.Team,
															Slot = goalPrintJsonPacket.Slot
														};
													}
													return new AdminCommandResultPrintJsonPacket
													{
														MessageType = adminCommandResultPrintJsonPacket.MessageType
													};
												}
												return new CommandResultPrintJsonPacket
												{
													MessageType = commandResultPrintJsonPacket.MessageType
												};
											}
											return new TagsChangedPrintJsonPacket
											{
												MessageType = tagsChangedPrintJsonPacket.MessageType,
												Team = tagsChangedPrintJsonPacket.Team,
												Slot = tagsChangedPrintJsonPacket.Slot,
												Tags = tagsChangedPrintJsonPacket.Tags
											};
										}
										return new TutorialPrintJsonPacket
										{
											MessageType = tutorialPrintJsonPacket.MessageType
										};
									}
									return new ServerChatPrintJsonPacket
									{
										MessageType = serverChatPrintJsonPacket.MessageType,
										Message = serverChatPrintJsonPacket.Message
									};
								}
								return new ChatPrintJsonPacket
								{
									MessageType = chatPrintJsonPacket.MessageType,
									Team = chatPrintJsonPacket.Team,
									Slot = chatPrintJsonPacket.Slot,
									Message = chatPrintJsonPacket.Message
								};
							}
							return new LeavePrintJsonPacket
							{
								MessageType = leavePrintJsonPacket.MessageType,
								Team = leavePrintJsonPacket.Team,
								Slot = leavePrintJsonPacket.Slot
							};
						}
						return new JoinPrintJsonPacket
						{
							MessageType = joinPrintJsonPacket.MessageType,
							Team = joinPrintJsonPacket.Team,
							Slot = joinPrintJsonPacket.Slot,
							Tags = joinPrintJsonPacket.Tags
						};
					}
					return new HintPrintJsonPacket
					{
						MessageType = hintPrintJsonPacket.MessageType,
						ReceivingPlayer = hintPrintJsonPacket.ReceivingPlayer,
						Item = hintPrintJsonPacket.Item,
						Found = hintPrintJsonPacket.Found
					};
				}
				return new ItemCheatPrintJsonPacket
				{
					MessageType = itemCheatPrintJsonPacket.MessageType,
					ReceivingPlayer = itemCheatPrintJsonPacket.ReceivingPlayer,
					Item = itemCheatPrintJsonPacket.Item,
					Team = itemCheatPrintJsonPacket.Team
				};
			}
			return new ItemPrintJsonPacket
			{
				MessageType = itemPrintJsonPacket.MessageType,
				ReceivingPlayer = itemPrintJsonPacket.ReceivingPlayer,
				Item = itemPrintJsonPacket.Item
			};
		}

		internal MessagePart[] GetParsedData(PrintJsonPacket packet)
		{
			return packet.Data.Select(GetMessagePart).ToArray();
		}

		private MessagePart GetMessagePart(JsonMessagePart part)
		{
			switch (part.Type)
			{
			case JsonMessagePartType.ItemId:
			case JsonMessagePartType.ItemName:
				return new ItemMessagePart(items, part);
			case JsonMessagePartType.PlayerId:
			case JsonMessagePartType.PlayerName:
				return new PlayerMessagePart(players, connectionInfo, part);
			case JsonMessagePartType.LocationId:
			case JsonMessagePartType.LocationName:
				return new LocationMessagePart(locations, part);
			case JsonMessagePartType.EntranceName:
				return new EntranceMessagePart(part);
			default:
				return new MessagePart(MessagePartType.Text, part);
			}
		}
	}
	public interface IPlayerHelper
	{
		ReadOnlyDictionary<int, ReadOnlyCollection<PlayerInfo>> Players { get; }

		IEnumerable<PlayerInfo> AllPlayers { get; }

		string GetPlayerAlias(int slot);

		string GetPlayerName(int slot);

		string GetPlayerAliasAndName(int slot);
	}
	public class PlayerHelper : IPlayerHelper
	{
		private readonly IConnectionInfoProvider connectionInfo;

		private ReadOnlyDictionary<int, ReadOnlyCollection<PlayerInfo>> players = new ReadOnlyDictionary<int, ReadOnlyCollection<PlayerInfo>>(new Dictionary<int, ReadOnlyCollection<PlayerInfo>>(0));

		public ReadOnlyDictionary<int, ReadOnlyCollection<PlayerInfo>> Players => players;

		public IEnumerable<PlayerInfo> AllPlayers => players.SelectMany((KeyValuePair<int, ReadOnlyCollection<PlayerInfo>> kvp) => kvp.Value);

		internal PlayerHelper(IArchipelagoSocketHelper socket, IConnectionInfoProvider connectionInfo)
		{
			this.connectionInfo = connectionInfo;
			socket.PacketReceived += PacketReceived;
		}

		public string GetPlayerAlias(int slot)
		{
			if (players == null)
			{
				return null;
			}
			return players[connectionInfo.Team].FirstOrDefault((PlayerInfo p) => p.Slot == slot)?.Alias;
		}

		public string GetPlayerName(int slot)
		{
			if (players == null)
			{
				return null;
			}
			return players[connectionInfo.Team].FirstOrDefault((PlayerInfo p) => p.Slot == slot)?.Name;
		}

		public string GetPlayerAliasAndName(int slot)
		{
			if (players == null)
			{
				return null;
			}
			PlayerInfo playerInfo = players[connectionInfo.Team].FirstOrDefault((PlayerInfo p) => p.Slot == slot);
			if (playerInfo == null)
			{
				return null;
			}
			return playerInfo.Alias + " (" + playerInfo.Name + ")";
		}

		private void PacketReceived(ArchipelagoPacketBase packet)
		{
			if (!(packet is ConnectedPacket connectedPacket))
			{
				if (packet is RoomUpdatePacket roomUpdatePacket)
				{
					UpdatePlayerInfo(roomUpdatePacket.Players);
				}
			}
			else
			{
				CreatePlayerInfo(connectedPacket.Players, connectedPacket.SlotInfo);
			}
		}

		private void CreatePlayerInfo(NetworkPlayer[] networkPlayers, Dictionary<int, NetworkSlot> slotInfos)
		{
			NetworkSlot[] source = ((slotInfos == null) ? new NetworkSlot[0] : slotInfos.Values.Where((NetworkSlot s) => s.Type == SlotType.Group).ToArray());
			int num = 0;
			int num2 = 0;
			NetworkPlayer[] array = networkPlayers;
			for (int i = 0; i < array.Length; i++)
			{
				NetworkPlayer networkPlayer = array[i];
				if (networkPlayer.Team > num)
				{
					num = networkPlayer.Team;
				}
				if (networkPlayer.Slot > num2)
				{
					num2 = networkPlayer.Slot;
				}
			}
			Dictionary<int, PlayerInfo[]> dictionary = new Dictionary<int, PlayerInfo[]>(num);
			for (int j = 0; j <= num; j++)
			{
				dictionary[j] = new PlayerInfo[num2 + 1];
				dictionary[j][0] = new PlayerInfo
				{
					Team = j,
					Slot = 0,
					Name = "Server",
					Alias = "Server",
					Game = "Archipelago",
					Groups = new NetworkSlot[0]
				};
			}
			array = networkPlayers;
			for (int i = 0; i < array.Length; i++)
			{
				NetworkPlayer p = array[i];
				dictionary[p.Team][p.Slot] = new PlayerInfo
				{
					Team = p.Team,
					Slot = p.Slot,
					Name = p.Name,
					Alias = p.Alias,
					Game = slotInfos?[p.Slot].Game,
					Groups = source.Where((NetworkSlot g) => g.GroupMembers.Contains(p.Slot)).ToArray()
				};
			}
			Dictionary<int, ReadOnlyCollection<PlayerInfo>> dictionary2 = new Dictionary<int, ReadOnlyCollection<PlayerInfo>>(dictionary.Count);
			foreach (KeyValuePair<int, PlayerInfo[]> item in dictionary)
			{
				dictionary2[item.Key] = new ReadOnlyCollection<PlayerInfo>(item.Value);
			}
			players = new ReadOnlyDictionary<int, ReadOnlyCollection<PlayerInfo>>(dictionary2);
		}

		private void UpdatePlayerInfo(NetworkPlayer[] networkPlayers)
		{
			if (networkPlayers != null && networkPlayers.Length != 0)
			{
				for (int i = 0; i < networkPlayers.Length; i++)
				{
					NetworkPlayer networkPlayer = networkPlayers[i];
					players[networkPlayer.Team][networkPlayer.Slot].Name = networkPlayer.Name;
					players[networkPlayer.Team][networkPlayer.Slot].Alias = networkPlayer.Alias;
				}
			}
		}
	}
	public class PlayerInfo
	{
		public int Team { get; internal set; }

		public int Slot { get; internal set; }

		public string Alias { get; internal set; }

		public string Name { get; internal se

plugins/Archipelago_Inscryption.dll

Decompiled 4 months ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using System.Threading.Tasks;
using Archipelago.MultiClient.Net;
using Archipelago.MultiClient.Net.BounceFeatures.DeathLink;
using Archipelago.MultiClient.Net.Enums;
using Archipelago.MultiClient.Net.Helpers;
using Archipelago.MultiClient.Net.MessageLog.Messages;
using Archipelago.MultiClient.Net.Models;
using Archipelago.MultiClient.Net.Packets;
using Archipelago_Inscryption.Archipelago;
using Archipelago_Inscryption.Assets;
using Archipelago_Inscryption.Components;
using Archipelago_Inscryption.Helpers;
using Archipelago_Inscryption.Properties;
using Archipelago_Inscryption.Utils;
using BepInEx;
using BepInEx.Logging;
using DiskCardGame;
using GBC;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Pixelplacement;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("Archipelago_Inscryption")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+263f076fb77e722b6c5ff39971dc5ae0650d0198")]
[assembly: AssemblyProduct("Archipelago_Inscryption")]
[assembly: AssemblyTitle("Archipelago_Inscryption")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.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]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Archipelago_Inscryption
{
	[BepInPlugin("ballininc.inscryption.archipelagomod", "ArchipelagoMod", "0.2.2")]
	public class ArchipelagoModPlugin : BaseUnityPlugin
	{
		internal const string PluginGuid = "ballininc.inscryption.archipelagomod";

		internal const string PluginName = "ArchipelagoMod";

		internal const string PluginVersion = "0.2.2";

		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Harmony val = new Harmony("ballininc.inscryption.archipelagomod");
			val.PatchAll(Assembly.GetExecutingAssembly());
			AssetsManager.LoadAssets();
			ArchipelagoManager.Init();
			ScriptableObjectLoader<CardInfo>.LoadData("");
		}
	}
}
namespace Archipelago_Inscryption.Utils
{
	internal static class Extensions
	{
		internal static void ResetTransform(this Transform transform)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			transform.localPosition = Vector3.zero;
			transform.localRotation = Quaternion.identity;
			transform.localScale = Vector3.one;
		}

		internal static void SetLayerRecursive(this GameObject gameObject, int layer)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			gameObject.layer = layer;
			foreach (Transform item in gameObject.transform)
			{
				Transform val = item;
				((Component)val).gameObject.SetLayerRecursive(layer);
			}
		}

		internal static string GetPath(this Transform transform)
		{
			return (Object.op_Implicit((Object)(object)transform.parent) ? (transform.parent.GetPath() + "/") : "") + ((Object)transform).name;
		}
	}
}
namespace Archipelago_Inscryption.Properties
{
	[GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
	[DebuggerNonUserCode]
	[CompilerGenerated]
	internal class Resources
	{
		private static ResourceManager resourceMan;

		private static CultureInfo resourceCulture;

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static ResourceManager ResourceManager
		{
			get
			{
				if (resourceMan == null)
				{
					ResourceManager resourceManager = new ResourceManager("Archipelago_Inscryption.Properties.Resources", typeof(Resources).Assembly);
					resourceMan = resourceManager;
				}
				return resourceMan;
			}
		}

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static CultureInfo Culture
		{
			get
			{
				return resourceCulture;
			}
			set
			{
				resourceCulture = value;
			}
		}

		internal static byte[] archiassets
		{
			get
			{
				object @object = ResourceManager.GetObject("archiassets", resourceCulture);
				return (byte[])@object;
			}
		}

		internal Resources()
		{
		}
	}
}
namespace Archipelago_Inscryption.Patches
{
	[HarmonyPatch]
	internal class CheckPatches
	{
		[HarmonyPatch(typeof(StoryEventsData), "SetEventCompleted")]
		[HarmonyPrefix]
		private static bool SendCheckOnStoryEvent(StoryEvent storyEvent)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Invalid comparison between Unknown and I4
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Invalid comparison between Unknown and I4
			if ((int)storyEvent == 173)
			{
				return false;
			}
			ArchipelagoManager.SendStoryCheckIfApplicable(storyEvent);
			if ((int)storyEvent == 24)
			{
				ArchipelagoData.Data.act1Completed = true;
			}
			else if ((int)storyEvent == 48)
			{
				ArchipelagoData.Data.act2Completed = true;
			}
			else if ((int)storyEvent == 105)
			{
				ArchipelagoData.Data.act3Completed = true;
			}
			ArchipelagoManager.VerifyGoalCompletion();
			return true;
		}

		[HarmonyPatch(typeof(CardSingleChoicesSequencer), "AddChosenCardToDeck")]
		[HarmonyPrefix]
		private static bool DontAddIfCheckCard(CardSingleChoicesSequencer __instance)
		{
			if (((Object)((Card)__instance.chosenReward).Info).name.Contains("Archipelago"))
			{
				if (((Object)((Card)__instance.chosenReward).Info).name.Contains("ArchipelagoCheck"))
				{
					string name = ((Object)((Card)__instance.chosenReward).Info).name;
					string checkName = name.Substring(name.IndexOf('_') + 1);
					APCheck check = Enum.GetValues(typeof(APCheck)).Cast<APCheck>().FirstOrDefault((APCheck c) => c.ToString() == checkName);
					ArchipelagoManager.SendCheck(check);
				}
				((CardChoicesSequencer)__instance).deckPile.AddToPile(((Component)__instance.chosenReward).transform);
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(SaveFile), "CollectGBCCard")]
		[HarmonyPrefix]
		private static bool SendCheckInsteadOfAddingCard(CardInfo card)
		{
			if (((Object)card).name.Contains("Archipelago"))
			{
				string checkName = ((Object)card).name.Substring(((Object)card).name.IndexOf('_') + 1);
				APCheck check = Enum.GetValues(typeof(APCheck)).Cast<APCheck>().FirstOrDefault((APCheck c) => c.ToString() == checkName);
				ArchipelagoManager.SendCheck(check);
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(SafeInteractable), "Start")]
		[HarmonyPrefix]
		private static bool ReplaceStinkbugCardWithCheck(SafeInteractable __instance)
		{
			GameObject gameObject = ((Component)__instance.regularContents.GetComponentInChildren<DiscoverableTalkingCardInteractable>(true)).gameObject;
			DiscoverableCheckInteractable discoverableCheckInteractable = RandomizerHelper.CreateDiscoverableCardCheck(gameObject, APCheck.CabinSafe, destroyOriginal: true, (StoryEvent)6);
			MainInputInteractable val = __instance.interiorObjects[1];
			if (!ArchipelagoManager.HasItem(APItem.WardrobeKey))
			{
				((Component)((Component)val).transform.parent).gameObject.SetActive(false);
				((Component)__instance).gameObject.AddComponent<ActivateOnItemReceived>().Init(((Component)((Component)val).transform.parent).gameObject, APItem.WardrobeKey);
			}
			else
			{
				((Component)((Component)val).transform.parent).gameObject.SetActive(true);
			}
			__instance.interiorObjects.Clear();
			__instance.interiorObjects.Add(val);
			if (Object.op_Implicit((Object)(object)discoverableCheckInteractable))
			{
				__instance.interiorObjects.Add((MainInputInteractable)(object)discoverableCheckInteractable);
				((InteractableBase)discoverableCheckInteractable).SetEnabled(false);
			}
			if (ArchipelagoOptions.randomizeCodes)
			{
				__instance.correctLockPositions = ArchipelagoData.Data.cabinSafeCode.Select((int digit) => (10 - digit) % 10).ToList();
			}
			return true;
		}

		[HarmonyPatch(typeof(WardrobeDrawerInteractable), "Start")]
		[HarmonyPrefix]
		private static bool ReplaceWardrobeCardWithCheck(WardrobeDrawerInteractable __instance)
		{
			//IL_0019: 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_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			APCheck check;
			StoryEvent activeStoryFlag;
			if (((Object)__instance).name.Contains("1"))
			{
				check = APCheck.CabinDrawer1;
				activeStoryFlag = (StoryEvent)8;
			}
			else if (((Object)__instance).name.Contains("2"))
			{
				check = APCheck.CabinDrawer2;
				activeStoryFlag = (StoryEvent)9;
			}
			else if (((Object)__instance).name.Contains("3"))
			{
				check = APCheck.CabinDrawer3;
				activeStoryFlag = (StoryEvent)10;
			}
			else if (((Object)__instance).name.Contains("4"))
			{
				check = APCheck.CabinDrawer4;
				activeStoryFlag = (StoryEvent)11;
				Transform transform = ((Component)__instance.drawerContents[0]).transform;
				transform.eulerAngles = new Vector3(90f, 114f, 0f);
				transform.localScale = Vector3.one * 0.7114f;
			}
			else if (((Object)__instance.drawerContents[0]).name.Contains("Card"))
			{
				check = APCheck.FactoryDrawer2;
				activeStoryFlag = (StoryEvent)57;
			}
			else
			{
				check = APCheck.FactoryDrawer1;
				activeStoryFlag = (StoryEvent)56;
			}
			DiscoverableCheckInteractable discoverableCheckInteractable = RandomizerHelper.CreateDiscoverableCardCheck(((Component)__instance.drawerContents[0]).gameObject, check, destroyOriginal: true, activeStoryFlag);
			__instance.drawerContents.Clear();
			if (Object.op_Implicit((Object)(object)discoverableCheckInteractable))
			{
				__instance.drawerContents.Add((MainInputInteractable)(object)discoverableCheckInteractable);
			}
			return true;
		}

		[HarmonyPatch(typeof(CuckooClock), "Start")]
		[HarmonyPrefix]
		private static bool ReplaceClockContentsWithChecks(CuckooClock __instance)
		{
			//IL_0108: 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_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Expected O, but got Unknown
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0428: Unknown result type (might be due to invalid IL or missing references)
			//IL_0459: Unknown result type (might be due to invalid IL or missing references)
			//IL_048a: Unknown result type (might be due to invalid IL or missing references)
			if (SaveManager.SaveFile.IsPart3)
			{
				GameObject gameObject = ((Component)__instance.largeCompartmentContents[0]).gameObject;
				__instance.largeCompartmentContents.Clear();
				DiscoverableCheckInteractable discoverableCheckInteractable = RandomizerHelper.CreateDiscoverableCardCheck(gameObject, APCheck.FactoryClock, destroyOriginal: true, (StoryEvent)142);
				int layer = LayerMask.NameToLayer("FirstPersonLighting");
				if (Object.op_Implicit((Object)(object)discoverableCheckInteractable))
				{
					__instance.largeCompartmentContents.Add((MainInputInteractable)(object)discoverableCheckInteractable);
					((Component)discoverableCheckInteractable).gameObject.SetLayerRecursive(layer);
					if (!StoryEventsData.EventCompleted((StoryEvent)142))
					{
						((InteractableBase)discoverableCheckInteractable).SetEnabled(false);
					}
				}
				if (ArchipelagoOptions.randomizeCodes)
				{
					__instance.solutionPositionsLarge = ArchipelagoData.Data.factoryClockCode.ToArray();
					__instance.solutionPositionsSmall = ArchipelagoData.Data.cabinSmallClockCode.ToArray();
				}
			}
			else
			{
				GameObject gameObject2 = ((Component)__instance.largeCompartmentContents[0]).gameObject;
				GameObject gameObject3 = ((Component)__instance.smallCompartmentContents[0]).gameObject;
				gameObject3.transform.eulerAngles = new Vector3(0f, 180f, 0f);
				gameObject3.transform.localScale = Vector3.one * 0.7114f;
				DiscoverableCheckInteractable discoverableCheckInteractable2 = RandomizerHelper.CreateDiscoverableCardCheck(gameObject2, APCheck.CabinClock1, destroyOriginal: true, (StoryEvent)30);
				DiscoverableCheckInteractable discoverableCheckInteractable3 = RandomizerHelper.CreateDiscoverableCardCheck(gameObject3, APCheck.CabinClock2, destroyOriginal: true, (StoryEvent)131);
				Object.Destroy((Object)(object)((Component)__instance.largeCompartmentContents[1]).gameObject);
				__instance.largeCompartmentContents.Clear();
				__instance.smallCompartmentContents.Clear();
				int layer2 = LayerMask.NameToLayer("FirstPersonLighting");
				if (Object.op_Implicit((Object)(object)discoverableCheckInteractable2))
				{
					__instance.largeCompartmentContents.Add((MainInputInteractable)(object)discoverableCheckInteractable2);
					((Component)discoverableCheckInteractable2).gameObject.SetLayerRecursive(layer2);
					if (!StoryEventsData.EventCompleted((StoryEvent)30))
					{
						((InteractableBase)discoverableCheckInteractable2).SetEnabled(false);
					}
				}
				if (Object.op_Implicit((Object)(object)discoverableCheckInteractable3))
				{
					((DiscoverableObjectInteractable)discoverableCheckInteractable3).closeUpEulers = Vector3.zero;
					((DiscoverableObjectInteractable)discoverableCheckInteractable3).closeUpDistance = 2.2f;
					((Component)discoverableCheckInteractable3).GetComponent<BoxCollider>().size = new Vector3(1.2f, 1.8f, 0.4f);
					__instance.smallCompartmentContents.Add((MainInputInteractable)(object)discoverableCheckInteractable3);
					((Component)discoverableCheckInteractable3).gameObject.SetLayerRecursive(layer2);
					if (!StoryEventsData.EventCompleted((StoryEvent)30))
					{
						((InteractableBase)discoverableCheckInteractable3).SetEnabled(false);
					}
				}
				if (ArchipelagoOptions.randomizeCodes)
				{
					__instance.solutionPositionsLarge = ArchipelagoData.Data.cabinClockCode.ToArray();
					__instance.solutionPositionsSmall = ArchipelagoData.Data.cabinSmallClockCode.ToArray();
					Transform val = ((Component)__instance).transform.Find("CuckooClock");
					List<Transform> list = new List<Transform>();
					foreach (Transform item2 in val)
					{
						Transform item = item2;
						list.Add(item);
					}
					((Component)list.First((Transform x) => ((Object)((Component)x).gameObject).name == "WizardMark_Tall" && x.eulerAngles.z > 270f)).gameObject.SetActive(false);
					((Component)list.First((Transform x) => ((Object)((Component)x).gameObject).name == "WizardMark_Tall" && x.eulerAngles.z < 270f)).gameObject.SetActive(false);
					((Component)list.First((Transform x) => ((Object)((Component)x).gameObject).name == "WizardMark_Short")).gameObject.SetActive(false);
					GameObject val2 = Object.Instantiate<GameObject>(AssetsManager.clockCluesPrefab, val);
					val2.transform.localPosition = new Vector3(0f, 1.9459f, 0.6f);
					val2.transform.eulerAngles = new Vector3(0f, 180f, 0f);
					Transform val3 = val2.transform.Find("SecondCluePivot");
					Transform val4 = val2.transform.Find("MinuteCluePivot");
					Transform val5 = val2.transform.Find("HourCluePivot");
					val3.localEulerAngles = new Vector3(0f, 0f, (float)(360 - 30 * ArchipelagoData.Data.cabinClockCode[0]));
					val4.localEulerAngles = new Vector3(0f, 0f, (float)(360 - 30 * ArchipelagoData.Data.cabinClockCode[1]));
					val5.localEulerAngles = new Vector3(0f, 0f, (float)(360 - 30 * ArchipelagoData.Data.cabinClockCode[2]));
					val2.SetLayerRecursive(LayerMask.NameToLayer("WizardEyeVisible"));
				}
			}
			return true;
		}

		[HarmonyPatch(typeof(WolfStatueSlotInteractable), "Start")]
		[HarmonyPrefix]
		private static bool ReplaceDaggerWithCheck(WolfStatueSlotInteractable __instance)
		{
			//IL_0037: 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_004d: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
			DiscoverableCheckInteractable discoverableCheckInteractable = RandomizerHelper.CreateDiscoverableCardCheck(((Component)__instance.dagger).gameObject, APCheck.CabinDagger, destroyOriginal: true, (StoryEvent)173);
			if (!Object.op_Implicit((Object)(object)discoverableCheckInteractable))
			{
				return true;
			}
			((DiscoverableCardInteractable)discoverableCheckInteractable).requireStoryEventToAddToDeck = true;
			((DiscoverableCardInteractable)discoverableCheckInteractable).requiredStoryEvent = (StoryEvent)16;
			((DiscoverableObjectInteractable)discoverableCheckInteractable).closeUpDistance = 2.2f;
			((DiscoverableObjectInteractable)discoverableCheckInteractable).closeUpEulers = Vector3.zero;
			((Component)discoverableCheckInteractable).GetComponent<BoxCollider>().size = new Vector3(1.2f, 1.8f, 0.4f);
			((Component)discoverableCheckInteractable).transform.position = new Vector3(28.1565f, 8.5275f, 11.2946f);
			((Component)discoverableCheckInteractable).transform.eulerAngles = new Vector3(46.6807f, 140f, 0f);
			((Component)discoverableCheckInteractable).transform.localScale = Vector3.one * 0.7114f;
			return true;
		}

		[HarmonyPatch(typeof(WolfStatueSlotInteractable), "UnlockDagger")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> IgnoreDagger(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.Calls(x, AccessTools.Method(typeof(Animator), "Play", new Type[3]
			{
				typeof(string),
				typeof(int),
				typeof(float)
			}, (Type[])null)));
			num++;
			list.RemoveRange(num, 10);
			return list.AsEnumerable();
		}

		[HarmonyPatch(typeof(OilPaintingPuzzle), "OnRewardTaken")]
		[HarmonyPrefix]
		private static bool TakeCardInstead(OilPaintingPuzzle __instance)
		{
			__instance.state.rewardTaken = true;
			RandomizerHelper.ClaimPaintingCheck(__instance.state.rewardIndex);
			__instance.DisplaySaveState(__instance.state);
			return false;
		}

		[HarmonyPatch(typeof(SaveState), "get_RewardRedeemed")]
		[HarmonyPrefix]
		private static bool SkipStoryEventVerification(SaveState __instance, ref bool __result)
		{
			__result = __instance.rewardTaken;
			return false;
		}

		[HarmonyPatch(typeof(OilPaintingPuzzle), "Start")]
		[HarmonyPrefix]
		private static bool ReplacePaintingRewardsWithChecks(OilPaintingPuzzle __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_001c: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Expected O, but got Unknown
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Expected O, but got Unknown
			//IL_0280: 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_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject();
			val.transform.position = new Vector3(19.22f, 9.5f, -15.9f);
			val.transform.eulerAngles = new Vector3(0f, 180f, 0f);
			val.transform.localScale = Vector3.one * 0.7114f;
			val.AddComponent<BoxCollider>().size = new Vector3(0f, 0f, 0f);
			Transform parent = __instance.rewardDisplayedItems[0].transform.parent;
			foreach (GameObject rewardDisplayedItem in __instance.rewardDisplayedItems)
			{
				Object.Destroy((Object)(object)rewardDisplayedItem);
			}
			__instance.rewardDisplayedItems.Clear();
			DiscoverableCheckInteractable discoverableCheckInteractable = RandomizerHelper.CreateDiscoverableCardCheck(val, APCheck.CabinPainting1, destroyOriginal: false, (StoryEvent)173);
			DiscoverableCheckInteractable discoverableCheckInteractable2 = RandomizerHelper.CreateDiscoverableCardCheck(val, APCheck.CabinPainting2, destroyOriginal: false, (StoryEvent)173);
			DiscoverableCheckInteractable discoverableCheckInteractable3 = RandomizerHelper.CreateDiscoverableCardCheck(val, APCheck.CabinPainting3, destroyOriginal: true, (StoryEvent)173);
			int layer = LayerMask.NameToLayer("CardOffscreen");
			if (Object.op_Implicit((Object)(object)discoverableCheckInteractable))
			{
				((Card)discoverableCheckInteractable.card).RenderCard();
				Object.Destroy((Object)(object)((Component)discoverableCheckInteractable.card).GetComponent<BoxCollider>());
				__instance.rewardDisplayedItems.Add(Object.Instantiate<GameObject>(((Component)discoverableCheckInteractable.card).gameObject, parent));
				((InteractableBase)discoverableCheckInteractable).SetEnabled(false);
			}
			else
			{
				__instance.rewardDisplayedItems.Add(new GameObject());
			}
			if (Object.op_Implicit((Object)(object)discoverableCheckInteractable2))
			{
				((Card)discoverableCheckInteractable2.card).RenderCard();
				Object.Destroy((Object)(object)((Component)discoverableCheckInteractable2.card).GetComponent<BoxCollider>());
				__instance.rewardDisplayedItems.Add(Object.Instantiate<GameObject>(((Component)discoverableCheckInteractable2.card).gameObject, parent));
				((InteractableBase)discoverableCheckInteractable2).SetEnabled(false);
			}
			else
			{
				__instance.rewardDisplayedItems.Add(new GameObject());
			}
			if (Object.op_Implicit((Object)(object)discoverableCheckInteractable3))
			{
				((Card)discoverableCheckInteractable3.card).RenderCard();
				Object.Destroy((Object)(object)((Component)discoverableCheckInteractable3.card).GetComponent<BoxCollider>());
				__instance.rewardDisplayedItems.Add(Object.Instantiate<GameObject>(((Component)discoverableCheckInteractable3.card).gameObject, parent));
				((InteractableBase)discoverableCheckInteractable3).SetEnabled(false);
			}
			else
			{
				__instance.rewardDisplayedItems.Add(new GameObject());
			}
			foreach (GameObject rewardDisplayedItem2 in __instance.rewardDisplayedItems)
			{
				rewardDisplayedItem2.transform.localPosition = new Vector3(0f, 0.8618f, 0.9273f);
				rewardDisplayedItem2.transform.localEulerAngles = new Vector3(0f, 0f, 0f);
				rewardDisplayedItem2.transform.localScale = Vector3.one * 0.7114f;
				rewardDisplayedItem2.SetLayerRecursive(layer);
			}
			RandomizerHelper.SetPaintingRewards(discoverableCheckInteractable, discoverableCheckInteractable2, discoverableCheckInteractable3);
			return true;
		}

		[HarmonyPatch(typeof(WallCandlesPuzzle), "Start")]
		[HarmonyPrefix]
		private static bool ReplaceGreaterSmokeWithCheck(WallCandlesPuzzle __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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)
			GameObject val = new GameObject();
			val.transform.position = new Vector3(13.4709f, 11.3545f, 19.8158f);
			val.transform.eulerAngles = Vector3.zero;
			val.transform.localScale = Vector3.one * 0.7114f;
			val.AddComponent<BoxCollider>().size = new Vector3(0f, 0f, 0f);
			((Component)__instance.card).gameObject.SetActive(false);
			DiscoverableCheckInteractable discoverableCheckInteractable = RandomizerHelper.CreateDiscoverableCardCheck(val, APCheck.CabinSmoke, destroyOriginal: true, (StoryEvent)173);
			if (!Object.op_Implicit((Object)(object)discoverableCheckInteractable))
			{
				return true;
			}
			((InteractableBase)discoverableCheckInteractable).SetEnabled(false);
			__instance.card = (DiscoverableCardInteractable)(object)discoverableCheckInteractable;
			Object.Destroy((Object)(object)((Component)discoverableCheckInteractable.card).GetComponent<BoxCollider>());
			return true;
		}

		[HarmonyPatch(typeof(WallCandlesPuzzle), "OnCandleClicked")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> UnlockSmokeCheckInstead(IEnumerable<CodeInstruction> instructions)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.Calls(x, AccessTools.Method(typeof(WallCandlesPuzzle), "UnlockCardSequence", (Type[])null, (Type[])null)));
			num--;
			list.RemoveRange(num, 4);
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(WallCandlesPuzzle), "card")));
			list2.Add(new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.Method(typeof(DiscoverableObjectInteractable), "Discover", (Type[])null, (Type[])null)));
			List<CodeInstruction> collection = list2;
			list.InsertRange(num, collection);
			return list.AsEnumerable();
		}

		[HarmonyPatch(typeof(ContainerVolume), "Start")]
		[HarmonyPostfix]
		private static void ReplaceContainterContentWithCheck(ContainerVolume __instance)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			if (((Component)__instance).transform.GetPath() == "Temple/BasementRoom/Casket/ContainerVolume")
			{
				return;
			}
			if (((UnityEventBase)__instance.pickupEvent).GetPersistentEventCount() > 0)
			{
				__instance.pickupEvent = new TriggerEvent();
				((UnityEvent<BaseEventData>)(object)__instance.pickupEvent).AddListener((UnityAction<BaseEventData>)delegate
				{
					RandomizerHelper.GiveObjectRelatedCheck(((Component)__instance).gameObject);
				});
			}
			else
			{
				if (((UnityEventBase)((DisplayTextVolume)__instance).postTextEvent).GetPersistentEventCount() <= 0)
				{
					return;
				}
				((DisplayTextVolume)__instance).postTextEvent = new TriggerEvent();
				((UnityEvent<BaseEventData>)(object)((DisplayTextVolume)__instance).postTextEvent).AddListener((UnityAction<BaseEventData>)delegate
				{
					RandomizerHelper.GiveObjectRelatedCheck(((Component)__instance).gameObject);
				});
			}
			if (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<GainEpitaphPiece>()))
			{
				((DisplayTextVolume)__instance).textLines.Clear();
				((DisplayTextVolume)__instance).textLines.Add("You found a strange card inside.");
			}
		}

		[HarmonyPatch(typeof(GainEpitaphPiece), "GetTextBoxPickupLine")]
		[HarmonyPrefix]
		private static bool ReplaceEpitaphText(ref string __result)
		{
			__result = "...Upon closer inspection, it's actually a strange looking card.";
			return false;
		}

		[HarmonyPatch(typeof(GainEpitaphPiece), "Start")]
		[HarmonyPrefix]
		private static bool AddEpitaphCheck(GainEpitaphPiece __instance)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			PickupObjectVolume component = ((Component)__instance).GetComponent<PickupObjectVolume>();
			if ((Object)(object)component != (Object)null)
			{
				component.pickupEvent = new TriggerEvent();
				((UnityEvent<BaseEventData>)(object)((DisplayTextVolume)component).postTextEvent).AddListener((UnityAction<BaseEventData>)delegate
				{
					RandomizerHelper.GiveObjectRelatedCheck(((Component)__instance).gameObject);
				});
			}
			return true;
		}

		[HarmonyPatch(typeof(WellVolume), "OnPostMessage")]
		[HarmonyPrefix]
		private static bool ReplaceWellItemsWithChecks(WellVolume __instance)
		{
			if (__instance.saveState.State.intVal == 0)
			{
				RandomizerHelper.GiveGBCCheck(APCheck.GBCEpitaphPiece9);
			}
			else if (__instance.saveState.State.intVal == 1)
			{
				RandomizerHelper.GiveGBCCheck(APCheck.GBCCryptWell);
			}
			ObjectStateData state = __instance.saveState.State;
			state.intVal++;
			return false;
		}

		[HarmonyPatch(typeof(PickupObjectVolume), "Start")]
		[HarmonyPrefix]
		private static bool ReplacePickupWithCheck(PickupObjectVolume __instance)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Invalid comparison between Unknown and I4
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Invalid comparison between Unknown and I4
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Expected O, but got Unknown
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Invalid comparison between Unknown and I4
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Expected O, but got Unknown
			if (__instance.unlockStoryEvent)
			{
				if ((int)__instance.storyEventToUnlock == 111)
				{
					__instance.unlockStoryEvent = false;
					((UnityEvent<BaseEventData>)(object)((DisplayTextVolume)__instance).postTextEvent).AddListener((UnityAction<BaseEventData>)delegate
					{
						RandomizerHelper.GiveGBCCheck(APCheck.GBCClover);
					});
					((DisplayTextVolume)__instance).textLines.Clear();
					((DisplayTextVolume)__instance).textLines.Add("You picked the clover leaf from the stem...");
					((DisplayTextVolume)__instance).textLines.Add("...but it suddenly turned itself into a strange card.");
				}
				else if ((int)__instance.storyEventToUnlock == 114)
				{
					__instance.unlockStoryEvent = false;
					((UnityEvent<BaseEventData>)(object)((DisplayTextVolume)__instance).postTextEvent).AddListener((UnityAction<BaseEventData>)delegate
					{
						RandomizerHelper.GiveGBCCheck(APCheck.GBCBoneLordFemur);
					});
					((DisplayTextVolume)__instance).textLines.Clear();
					((DisplayTextVolume)__instance).textLines.Add("You took the Bone Lord's femur from the pedestal...");
					((DisplayTextVolume)__instance).textLines.Add("...but it suddenly turned itself into a strange card.");
				}
				else if ((int)__instance.storyEventToUnlock == 115)
				{
					__instance.unlockStoryEvent = false;
					((UnityEvent<BaseEventData>)(object)((DisplayTextVolume)__instance).postTextEvent).AddListener((UnityAction<BaseEventData>)delegate
					{
						RandomizerHelper.GiveGBCCheck(APCheck.GBCBoneLordHoloKey);
					});
					((DisplayTextVolume)__instance).textLines.Clear();
					((DisplayTextVolume)__instance).textLines.Add("You found a strange flickering key...");
					((DisplayTextVolume)__instance).textLines.Add("...but as you touched it, the key turned itself into a card.");
				}
				else if ((int)__instance.storyEventToUnlock == 126)
				{
					__instance.unlockStoryEvent = false;
					((UnityEvent<BaseEventData>)(object)((DisplayTextVolume)__instance).postTextEvent).AddListener((UnityAction<BaseEventData>)delegate
					{
						RandomizerHelper.GiveGBCCheck(APCheck.GBCMycologistsHoloKey);
					});
					((DisplayTextVolume)__instance).textLines.Clear();
					((DisplayTextVolume)__instance).textLines.Add("You found a strange flickering key...");
					((DisplayTextVolume)__instance).textLines.Add("...but as you touched it, the key turned itself into a card.");
				}
			}
			else if (SceneLoader.ActiveSceneName == "GBC_Temple_Tech" && ((Object)((Component)__instance).gameObject).name == "RecyclingBinVolume")
			{
				__instance.pickupEvent = new TriggerEvent();
				((UnityEvent<BaseEventData>)(object)((DisplayTextVolume)__instance).postTextEvent).AddListener((UnityAction<BaseEventData>)delegate
				{
					RandomizerHelper.GiveGBCCheck(APCheck.GBCFactoryTrashCan);
				});
				((DisplayTextVolume)__instance).textLines.Clear();
				((DisplayTextVolume)__instance).textLines.Add("You rummage through the junk cards... And find a strange card that didn't seem to belong with the others.");
			}
			else if (SceneLoader.ActiveSceneName == "GBC_Temple_Undead" && ((Object)((Component)__instance).gameObject).name == "Card")
			{
				__instance.pickupEvent = new TriggerEvent();
				((UnityEvent<BaseEventData>)(object)((DisplayTextVolume)__instance).postTextEvent).AddListener((UnityAction<BaseEventData>)delegate
				{
					RandomizerHelper.GiveGBCCheck(APCheck.GBCBoneLordHorn);
				});
			}
			return true;
		}

		[HarmonyPatch(typeof(BrokenCoin), "RespondsToOtherCardAssignedToSlot")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> AllowObolRepairIfCheckAvailable(IEnumerable<CodeInstruction> instructions)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.Calls(x, AccessTools.Method(typeof(StoryEventsData), "EventCompleted", (Type[])null, (Type[])null)));
			num--;
			list.RemoveRange(num, 2);
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Ldc_I4, (object)52));
			list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ArchipelagoManager), "HasCompletedCheck", (Type[])null, (Type[])null)));
			List<CodeInstruction> collection = list2;
			list.InsertRange(num, collection);
			return list.AsEnumerable();
		}

		[HarmonyPatch(typeof(InspectorNPC), "Suicide")]
		[HarmonyPostfix]
		private static void GiveInspectorCheck()
		{
			RandomizerHelper.GiveGBCCheck(APCheck.GBCBattleInspector);
		}

		[HarmonyPatch(typeof(SmelterNPC), "Suicide")]
		[HarmonyPostfix]
		private static void GiveMelterCheck()
		{
			RandomizerHelper.GiveGBCCheck(APCheck.GBCBattleMelter);
		}

		[HarmonyPatch(typeof(GainMonocleVolume), "Start")]
		[HarmonyPostfix]
		private static void ChangeMonocleMessage(GainMonocleVolume __instance)
		{
			((DisplayTextVolume)__instance).textLines.Add("Your vision was suddenly obstructed. You take off the monocle...");
			((DisplayTextVolume)__instance).textLines.Add("...or so you thought. It was a strange card instead.");
		}

		[HarmonyPatch(typeof(GainMonocleVolume), "OnPostMessage")]
		[HarmonyPrefix]
		private static bool GiveMonocleCheck(GainMonocleVolume __instance)
		{
			__instance.SaveState.boolVal = true;
			__instance.Hide();
			RandomizerHelper.GiveGBCCheck(APCheck.GBCMonocle);
			return false;
		}

		[HarmonyPatch(typeof(CubeChestInteractable), "Start")]
		[HarmonyPostfix]
		private static void ReplaceAnglerCardWithCheck(CubeChestInteractable __instance)
		{
			GameObject gameObject = ((Component)((Component)__instance).GetComponentInChildren<DiscoverableTalkingCardInteractable>(true)).gameObject;
			RandomizerHelper.CreateDiscoverableCardCheck(gameObject, APCheck.FactoryChest, destroyOriginal: true, (StoryEvent)173);
		}

		[HarmonyPatch(typeof(HoloMapArea), "Start")]
		[HarmonyPrefix]
		private static void ReplaceMapNodesWithChecks(HoloMapArea __instance)
		{
			switch (((Object)__instance).name)
			{
			case "HoloMapArea_StartingIslandBattery(Clone)":
				RandomizerHelper.CreateHoloMapNodeCheck(((Component)((Component)__instance).transform.Find("Nodes/UnlockItemNode3D_Battery")).gameObject, APCheck.FactoryExtraBattery);
				break;
			case "HoloMapArea_Shop(Clone)":
				RandomizerHelper.CreateHoloMapNodeCheck(((Component)((Component)__instance).transform.Find("Nodes/ShopNode3D_ShieldGenItem/UnlockItemNode3D_ShieldGenerator")).gameObject, APCheck.FactoryNanoArmorGenerator);
				RandomizerHelper.CreateHoloMapNodeCheck(((Component)((Component)__instance).transform.Find("Nodes/ShopNode3D_PickupPelt/PickupPeltNode3D")).gameObject, APCheck.FactoryHoloPelt1);
				break;
			case "HoloMapArea_TempleWizardSide(Clone)":
			{
				Transform val = ((Component)__instance).transform.Find("Splatter/clue");
				((Renderer)((Component)val).GetComponent<MeshRenderer>()).material.mainTexture = (Texture)(object)AssetsManager.factoryClockClueTexs[ArchipelagoData.Data.factoryClockCode[2]];
				break;
			}
			}
		}

		[HarmonyPatch(typeof(InspectionMachineInteractable), "Start")]
		[HarmonyPrefix]
		private static void CreateBatteryCheck(InspectionMachineInteractable __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_001c: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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();
			val.transform.position = new Vector3(90.3f, 5f, 5f);
			val.transform.eulerAngles = new Vector3(0f, 90f, 0f);
			val.transform.localScale = Vector3.one * 0.7114f;
			val.AddComponent<BoxCollider>().size = new Vector3(1.2f, 1.8f, 0.2f);
			RandomizerHelper.CreateDiscoverableCardCheck(val, APCheck.FactoryInspectometerBattery, destroyOriginal: true, (StoryEvent)173);
			HoldableBattery componentInChildren = ((Component)__instance).GetComponentInChildren<HoldableBattery>();
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				if (!ArchipelagoManager.HasItem(APItem.InspectometerBattery))
				{
					((Component)((Component)componentInChildren).transform.parent).gameObject.SetActive(false);
					((Component)__instance).gameObject.AddComponent<ActivateOnItemReceived>().Init(((Component)((Component)componentInChildren).transform.parent).gameObject, APItem.InspectometerBattery);
				}
				else
				{
					((Component)((Component)componentInChildren).transform.parent).gameObject.SetActive(true);
				}
			}
		}

		[HarmonyPatch(typeof(HoloMapPeltMinigame), "Start")]
		[HarmonyPrefix]
		private static bool ReplacePeltWithCheck(HoloMapPeltMinigame __instance)
		{
			APCheck check = APCheck.FactoryHoloPelt1;
			switch (((Object)((Component)((Component)__instance).GetComponentInParent<HoloMapArea>()).gameObject).name)
			{
			case "HoloMapArea_NeutralWest_Secret(Clone)":
				check = APCheck.FactoryHoloPelt2;
				break;
			case "HoloMapArea_NatureSecret(Clone)":
				check = APCheck.FactoryHoloPelt3;
				break;
			case "HoloMapArea_TempleUndeadShop(Clone)":
				check = APCheck.FactoryHoloPelt4;
				break;
			case "HoloMapArea_WizardSecret(Clone)":
				check = APCheck.FactoryHoloPelt5;
				break;
			}
			HoloMapNode val = RandomizerHelper.CreateHoloMapNodeCheck(((Component)__instance.rewardNode).gameObject, check);
			if (Object.op_Implicit((Object)(object)val))
			{
				__instance.rewardNode = val;
				return true;
			}
			if (((HoloMapNode)__instance.trapInteractable).Completed)
			{
				((Component)__instance.rabbitAnim).gameObject.SetActive(false);
				__instance.trapAnim.Play("shut", 0, 1f);
			}
			return false;
		}

		[HarmonyPatch(typeof(HoloMapLukeFile), "OnFolderHitMapKeyframe")]
		[HarmonyPostfix]
		private static void GiveLukeFileCheck(HoloMapLukeFile __instance)
		{
			APCheck check = ((((Object)((Component)((Component)__instance).transform.parent.parent).gameObject).name == "HoloMapArea_NatureSidePath(Clone)") ? APCheck.FactoryLukeFileEntry1 : ((((Object)((Component)((Component)__instance).transform.parent.parent).gameObject).name == "HoloMapArea_NeutralWestSide_2(Clone)") ? APCheck.FactoryLukeFileEntry2 : ((!(((Object)((Component)((Component)__instance).transform.parent.parent).gameObject).name == "HoloMapArea_NeutralWest_LukeFile(Clone)")) ? APCheck.FactoryLukeFileEntry4 : APCheck.FactoryLukeFileEntry3)));
			ArchipelagoManager.SendCheck(check);
		}

		[HarmonyPatch(typeof(HoloMapWell), "Start")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> ChangeDredgedCondition(IEnumerable<CodeInstruction> instructions)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.LoadsField(x, AccessTools.Field(typeof(Part3SaveData), "foundUndeadTempleQuill"), false));
			num--;
			list.RemoveRange(num, 2);
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Ldc_I4, (object)99));
			list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ArchipelagoManager), "HasCompletedCheck", (Type[])null, (Type[])null)));
			List<CodeInstruction> collection = list2;
			list.InsertRange(num, collection);
			return list.AsEnumerable();
		}

		[HarmonyPatch(typeof(HoloMapWell), "Start")]
		[HarmonyPostfix]
		private static void ReplaceQuillWithCheck(HoloMapWell __instance)
		{
			HoloMapNode val = RandomizerHelper.CreateHoloMapNodeCheck(((Component)__instance.itemNodes[0]).gameObject, APCheck.FactoryWell);
			if (Object.op_Implicit((Object)(object)val))
			{
				__instance.itemNodes[0] = (MapNode)(object)val;
			}
		}

		[HarmonyPatch(typeof(FactoryGemsDrone), "Start")]
		[HarmonyPostfix]
		private static void CreateGemsDroneCheck(FactoryGemsDrone __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject();
			val.transform.SetParent(((Component)__instance).transform.Find("Anim"));
			val.transform.localPosition = new Vector3(0.0109f, 0.2764f, 1.6309f);
			val.transform.localEulerAngles = new Vector3(90f, 0f, 0f);
			val.transform.localScale = Vector3.one * 0.7114f;
			val.AddComponent<BoxCollider>().size = new Vector3(1.2f, 1.8f, 0.2f);
			RandomizerHelper.CreateDiscoverableCardCheck(val, APCheck.FactoryGemsDrone, destroyOriginal: true, (StoryEvent)173);
			if (Object.op_Implicit((Object)(object)__instance.shelf.CurrentHoldable) && !ArchipelagoManager.HasItem(APItem.GemsModule))
			{
				((Component)__instance.shelf).gameObject.SetActive(false);
				((Component)__instance).gameObject.AddComponent<ActivateOnItemReceived>().Init(((Component)__instance.shelf).gameObject, APItem.GemsModule);
			}
		}

		[HarmonyPatch(typeof(FirstPersonItemHolder), "PickUpHoldable")]
		[HarmonyPrefix]
		private static bool SendDroneCheckIfNotCompleted(HoldableInteractable holdable)
		{
			if (holdable is HoldableGemsModule && !ArchipelagoManager.HasCompletedCheck(APCheck.FactoryGemsDrone))
			{
				DiscoverableCheckInteractable discoverableCheckInteractable = Object.FindObjectsOfType<DiscoverableCheckInteractable>().FirstOrDefault((DiscoverableCheckInteractable go) => ((Object)go).name.Contains("FactoryGemsDrone"));
				if (Object.op_Implicit((Object)(object)discoverableCheckInteractable))
				{
					((DiscoverableObjectInteractable)discoverableCheckInteractable).Discover();
				}
				else
				{
					ArchipelagoManager.SendCheck(APCheck.FactoryGemsDrone);
				}
			}
			return true;
		}

		[HarmonyPatch(typeof(FactoryGemsDrone), "OnGemsTaken")]
		[HarmonyPrefix]
		private static bool PreventDroneFlyOff(FactoryGemsDrone __instance)
		{
			((InteractableBase)__instance.shelf).SetEnabled(false);
			return false;
		}

		[HarmonyPatch(typeof(BonelordNPC), "SetRewardsGiven")]
		[HarmonyPostfix]
		private static void MoveFemurPedestal(BonelordNPC __instance)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			__instance.bonelordRewardsParent.transform.Find("Pedestal/Femur").parent.position = new Vector3(9.22f, 15.07f, 0f);
		}

		[HarmonyPatch(typeof(LeshyDialogueNPC), "ManagedLateUpdate")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> PreventLeshyBattleIfCameraCheckNotCompleted(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.LoadsField(x, AccessTools.Field(typeof(LeshyDialogueNPC), "npcVolumes"), false));
			num++;
			list.RemoveRange(num, 10);
			list.Insert(num, new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(RandomizerHelper), "IsLeshyNotReadyForBattle", (Type[])null, (Type[])null)));
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch]
	internal class WizardEyePatch
	{
		private static MethodBase TargetMethod()
		{
			return typeof(ChooseEyeballSequencer).GetNestedType("<ChooseEyeball>d__5", BindingFlags.Instance | BindingFlags.NonPublic).GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> ReplaceWizardEyeWithCheck(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.Calls(x, AccessTools.Method(typeof(StoryEventsData), "EventCompleted", (Type[])null, (Type[])null)));
			num--;
			list.RemoveRange(num, 3);
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Ldloc_1, (object)null));
			list2.Add(new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(ChooseEyeballSequencer), "wizardEyeball")));
			list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(RandomizerHelper), "CreateWizardEyeCheck", (Type[])null, (Type[])null)));
			List<CodeInstruction> collection = list2;
			list.InsertRange(num, collection);
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch]
	internal class Act2BattlePatch
	{
		private static MethodBase TargetMethod()
		{
			return typeof(CardBattleNPC).GetNestedType("<PostCombatEncounterSequence>d__64", BindingFlags.Instance | BindingFlags.NonPublic).GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> ReplaceCardPackRewardWithCheck(IEnumerable<CodeInstruction> instructions)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.Calls(x, AccessTools.Method(typeof(GainCardPacks), "OpenPacksSequence", (Type[])null, (Type[])null)));
			num--;
			list.RemoveRange(num, 2);
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(RandomizerHelper), "CombatRewardCheckSequence", (Type[])null, (Type[])null)));
			List<CodeInstruction> collection = list2;
			list.InsertRange(num, collection);
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch]
	internal class Act2CardGainMessagePatch
	{
		private static MethodBase TargetMethod()
		{
			return typeof(SingleCardGainUI).GetNestedType("<HideEndingSequence>d__10", BindingFlags.Instance | BindingFlags.NonPublic).GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> ReplaceMessageIfCheckCard(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int index = list.FindIndex((CodeInstruction x) => x.opcode == OpCodes.Ldstr && (string)x.operand == "The card was added to your collection.");
			list.RemoveAt(index);
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Ldloc_1, (object)null));
			list2.Add(new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(SingleCardGainUI), "currentCard")));
			list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(RandomizerHelper), "GetCardGainedMessage", (Type[])null, (Type[])null)));
			List<CodeInstruction> collection = list2;
			list.InsertRange(index, collection);
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch]
	internal class Act2GhoulEpitaphCheckPatch
	{
		private static MethodBase TargetMethod()
		{
			return typeof(GhoulNPC).GetNestedType("<OnDefeatedSequence>d__11", BindingFlags.Instance | BindingFlags.NonPublic).GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> ReplaceEpitaphWithCheck(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.Calls(x, AccessTools.Method(typeof(GainEpitaphPiece), "GainPiece", (Type[])null, (Type[])null)));
			num -= 2;
			list.RemoveRange(num, 3);
			num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.Calls(x, AccessTools.Method(typeof(Tween), "Shake", (Type[])null, (Type[])null)));
			num += 2;
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Ldloc_1, (object)null));
			list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.PropertyGetter(typeof(Component), "gameObject")));
			list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(RandomizerHelper), "GiveObjectRelatedCheck", (Type[])null, (Type[])null)));
			List<CodeInstruction> collection = list2;
			list.InsertRange(num, collection);
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch]
	internal class Act2MagnificusCheckPatch
	{
		private static MethodBase TargetMethod()
		{
			return typeof(MagnificusNPC).GetNestedType("<GlitchOutSequence>d__8", BindingFlags.Instance | BindingFlags.NonPublic).GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> ReplacePackWithCheck(IEnumerable<CodeInstruction> instructions)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.Calls(x, AccessTools.Method(typeof(GainCardPacks), "OpenPacksSequence", (Type[])null, (Type[])null)));
			num -= 2;
			list.RemoveRange(num, 3);
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Ldc_I4, (object)18));
			list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(RandomizerHelper), "GiveGBCCheckSequence", (Type[])null, (Type[])null)));
			List<CodeInstruction> collection = list2;
			list.InsertRange(num, collection);
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch]
	internal class Act2TentacleCheckPatch
	{
		private static MethodBase TargetMethod()
		{
			return typeof(TentacleInteractable).GetNestedType("<>c__DisplayClass14_0", BindingFlags.Instance | BindingFlags.NonPublic).GetMethod("<GiveCardSequence>b__1", BindingFlags.Instance | BindingFlags.NonPublic);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> ReplacePackWithCheck(IEnumerable<CodeInstruction> instructions)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.Calls(x, AccessTools.Method(typeof(GainSingleCards), "TriggerCardsSequence", (Type[])null, (Type[])null)));
			num -= 3;
			list.RemoveRange(num, 4);
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Ldc_I4, (object)44));
			list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(RandomizerHelper), "GiveGBCCheck", (Type[])null, (Type[])null)));
			List<CodeInstruction> collection = list2;
			list.InsertRange(num, collection);
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch]
	internal class Act2SafeCheckPatch
	{
		private static MethodBase TargetMethod()
		{
			return typeof(SafeVolume).GetNestedType("<GainDogFoodSequence>d__6", BindingFlags.Instance | BindingFlags.NonPublic).GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> ReplaceMeatWithCheck(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.Calls(x, AccessTools.Method(typeof(TextBox), "ShowUntilInput", (Type[])null, (Type[])null)));
			num -= 11;
			list.RemoveRange(num, 12);
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Ldc_I4, (object)37));
			list2.Add(new CodeInstruction(OpCodes.Ldstr, (object)"You found a strange card inside."));
			list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(RandomizerHelper), "GiveGBCCheckWithMessageSequence", (Type[])null, (Type[])null)));
			List<CodeInstruction> collection = list2;
			list.InsertRange(num, collection);
			num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.Calls(x, AccessTools.Method(typeof(StoryEventsData), "SetEventCompleted", (Type[])null, (Type[])null)));
			num -= 3;
			list.RemoveRange(num, 4);
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch]
	internal class Act2ObolCheckPatch
	{
		private static MethodBase TargetMethod()
		{
			return typeof(BrokenCoin).GetNestedType("<OnOtherCardAssignedToSlot>d__3", BindingFlags.Instance | BindingFlags.NonPublic).GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> ReplaceObolWithCheck(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			CodeInstruction val = list.Find((CodeInstruction x) => x.opcode == OpCodes.Ldstr && (string)x.operand == "You received an Ancient Obol.");
			val.operand = "You received an Ancient Obol...but it turned itself into a strange card.";
			int num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.Calls(x, AccessTools.Method(typeof(StoryEventsData), "SetEventCompleted", (Type[])null, (Type[])null)));
			num -= 3;
			list.RemoveRange(num, 4);
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Ldc_I4, (object)52));
			list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ArchipelagoManager), "SendCheck", (Type[])null, (Type[])null)));
			List<CodeInstruction> collection = list2;
			list.InsertRange(num, collection);
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch]
	internal class Act2CameraCheckPatch
	{
		private static MethodBase TargetMethod()
		{
			return typeof(LeshyDialogueNPC).GetNestedType("<PostDialogueSequence>d__5", BindingFlags.Instance | BindingFlags.NonPublic).GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> ReplaceCameraWithCheck(IEnumerable<CodeInstruction> instructions)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.LoadsField(x, AccessTools.Field(typeof(NatureTempleSaveData), "hasCamera"), false));
			num -= 2;
			list.RemoveRange(num, 3);
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Ldc_I4, (object)57));
			list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ArchipelagoManager), "HasCompletedCheck", (Type[])null, (Type[])null)));
			List<CodeInstruction> collection = list2;
			list.InsertRange(num, collection);
			num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.StoresField(x, AccessTools.Field(typeof(NatureTempleSaveData), "hasCamera")));
			num -= 3;
			list.RemoveRange(num, 4);
			list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Ldc_I4, (object)57));
			list2.Add(new CodeInstruction(OpCodes.Ldstr, (object)"The camera suddenly turned into a strange card."));
			list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(RandomizerHelper), "GiveGBCCheckWithMessage", (Type[])null, (Type[])null)));
			collection = list2;
			list.InsertRange(num, collection);
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch]
	internal class TarotCardsPatch
	{
		private static MethodBase TargetMethod()
		{
			return typeof(TraderMaskInteractable).GetNestedType("<DialogueSequence>d__11", BindingFlags.Instance | BindingFlags.NonPublic).GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> ReplaceTarotCardsWithCheck(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int index = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.Calls(x, AccessTools.Method(typeof(TraderMaskInteractable), "ChooseTarotSequence", (Type[])null, (Type[])null)));
			list.RemoveAt(index);
			list.Insert(index, new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(RandomizerHelper), "TraderPeltRewardCheckSequence", (Type[])null, (Type[])null)));
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch]
	internal class ItemPatches
	{
		[HarmonyPatch(typeof(RunState), "Initialize")]
		[HarmonyPostfix]
		private static void SetEyeStateIfEyeReceived(RunState __instance)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (ArchipelagoManager.HasItem(APItem.MagnificusEye))
			{
				__instance.eyeState = (EyeballState)2;
			}
		}

		[HarmonyPatch(typeof(SaveData), "Initialize")]
		[HarmonyPostfix]
		private static void InitializeItemNewGame(SaveData __instance)
		{
			if (ArchipelagoData.Data == null)
			{
				return;
			}
			List<NetworkItem> receivedItems = ArchipelagoData.Data.receivedItems;
			int currency = receivedItems.Count((NetworkItem item) => ((NetworkItem)(ref item)).Item == 147040);
			__instance.currency = currency;
			int num = 0;
			num = ((ArchipelagoOptions.epitaphPiecesRandomization == EpitaphPiecesRandomization.AllPieces) ? ArchipelagoData.Data.receivedItems.Count((NetworkItem item) => ((NetworkItem)(ref item)).Item == 147018) : ((ArchipelagoOptions.epitaphPiecesRandomization != EpitaphPiecesRandomization.Groups) ? 9 : (ArchipelagoData.Data.receivedItems.Count((NetworkItem item) => ((NetworkItem)(ref item)).Item == 147019) * 3)));
			for (int i = 0; i < num && i < 9; i++)
			{
				SaveData.Data.undeadTemple.epitaphPieces[i].found = true;
			}
			if (ArchipelagoManager.HasItem(APItem.CameraReplica))
			{
				__instance.natureTemple.hasCamera = true;
			}
			if (SaveManager.SaveFile.gbcCardsCollected != null)
			{
				if (ArchipelagoManager.HasItem(APItem.DrownedSoulCard))
				{
					ArchipelagoManager.ApplyItemReceived(APItem.DrownedSoulCard);
				}
				if (ArchipelagoManager.HasItem(APItem.SalmonCard))
				{
					ArchipelagoManager.ApplyItemReceived(APItem.SalmonCard);
				}
				if (ArchipelagoManager.HasItem(APItem.GreatKrakenCard))
				{
					ArchipelagoManager.ApplyItemReceived(APItem.GreatKrakenCard);
				}
				if (ArchipelagoManager.HasItem(APItem.BoneLordHorn))
				{
					ArchipelagoManager.ApplyItemReceived(APItem.BoneLordHorn);
				}
			}
		}

		[HarmonyPatch(typeof(SaveFile), "ResetGBCSaveData")]
		[HarmonyPostfix]
		private static void InitializeStoryEventsNewGame(SaveFile __instance)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			KeyValuePair<APItem, StoryEvent>[] array = new KeyValuePair<APItem, StoryEvent>[5]
			{
				new KeyValuePair<APItem, StoryEvent>(APItem.PileOfMeat, (StoryEvent)98),
				new KeyValuePair<APItem, StoryEvent>(APItem.Monocle, (StoryEvent)65),
				new KeyValuePair<APItem, StoryEvent>(APItem.AncientObol, (StoryEvent)112),
				new KeyValuePair<APItem, StoryEvent>(APItem.BoneLordFemur, (StoryEvent)114),
				new KeyValuePair<APItem, StoryEvent>(APItem.GBCCloverPlant, (StoryEvent)111)
			};
			for (int i = 0; i < array.Length; i++)
			{
				if (ArchipelagoManager.HasItem(array[i].Key))
				{
					StoryEventsData.SetEventCompleted(array[i].Value, false, false);
				}
			}
		}

		[HarmonyPatch(typeof(RunState), "InitializeStarterDeckAndItems")]
		[HarmonyPostfix]
		private static void AddInsectTotemHeadIfNeeded(RunState __instance)
		{
			if (StoryEventsData.EventCompleted((StoryEvent)103) && !__instance.totemTops.Contains((Tribe)6))
			{
				__instance.totemTops.Add((Tribe)6);
			}
		}

		[HarmonyPatch(typeof(WolfTalkingCard), "get_OnDrawnDialogueId")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> IDontNeedYourReminderJustShutUp(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			int index = list.FindIndex((CodeInstruction x) => x.opcode == OpCodes.Ldstr && (string)x.operand == "WolfFilmRollReminder");
			list.RemoveAt(index);
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null));
			list2.Add(new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.PropertyGetter(typeof(WolfTalkingCard), "OnDrawnFallbackDialogueId")));
			List<CodeInstruction> collection = list2;
			list.InsertRange(index, collection);
			return list.AsEnumerable();
		}

		[HarmonyPatch(typeof(DeckReviewSequencer), "OnEnterDeckView")]
		[HarmonyPostfix]
		private static void SpawnCardPackPile(DeckReviewSequencer __instance)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			if (ArchipelagoData.Data.availableCardPacks > 0 && (int)Singleton<GameFlowManager>.Instance.CurrentGameState == 1 && Singleton<GameMap>.Instance.FullyUnrolled)
			{
				RandomizerHelper.SpawnPackPile(__instance);
			}
		}

		[HarmonyPatch(typeof(Part3DeckReviewSequencer), "OnEnterDeckView")]
		[HarmonyPostfix]
		private static void SpawnCardPackPile(Part3DeckReviewSequencer __instance)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			if (StoryEventsData.EventCompleted((StoryEvent)54) && ArchipelagoData.Data.availableCardPacks > 0 && (int)Singleton<GameFlowManager>.Instance.CurrentGameState == 1)
			{
				RandomizerHelper.SpawnPackPile((DeckReviewSequencer)(object)__instance);
			}
		}

		[HarmonyPatch(typeof(DeckReviewSequencer), "OnExitDeckView")]
		[HarmonyPostfix]
		private static void DestroyCardPackPile(DeckReviewSequencer __instance)
		{
			RandomizerHelper.DestroyPackPile();
		}

		[HarmonyPatch(typeof(Part3DeckReviewSequencer), "OnExitDeckView")]
		[HarmonyPostfix]
		private static void DestroyPart3CardPackPile(Part3DeckReviewSequencer __instance)
		{
			RandomizerHelper.DestroyPackPile();
		}
	}
	[HarmonyPatch]
	internal class AnglerHookRemovalPatch
	{
		private static MethodBase TargetMethod()
		{
			return typeof(RunIntroSequencer).GetNestedType("<RunIntroSequence>d__1", BindingFlags.Instance | BindingFlags.NonPublic).GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> PreventFishHook(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.LoadsConstant(x, 122L));
			num -= 2;
			list.RemoveRange(num, 4);
			List<CodeInstruction> collection = new List<CodeInstruction>
			{
				new CodeInstruction(OpCodes.Pop, (object)null),
				new CodeInstruction(OpCodes.Ldc_I4_1, (object)null)
			};
			list.InsertRange(num, collection);
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch]
	internal class OtherPatches
	{
		[HarmonyPatch(typeof(AchievementManager), "Unlock")]
		[HarmonyPrefix]
		private static bool PreventAchievementUnlock()
		{
			return false;
		}

		[HarmonyPatch(typeof(SaveManager), "get_SaveFolderPath")]
		[HarmonyPrefix]
		private static bool ReplaceSaveFilePath(ref string __result)
		{
			if (ArchipelagoData.saveName == "")
			{
				return true;
			}
			__result = Path.Combine(Paths.GameRootPath, "ArchipelagoSaveFiles", ArchipelagoData.saveName) + "/";
			return false;
		}

		[HarmonyPatch(typeof(SaveManager), "get_SaveFilePath")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> ReplaceSaveFileName(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			CodeInstruction val = list.Find((CodeInstruction x) => x.opcode == OpCodes.Ldstr && (string)x.operand == "SaveFile.gwsave");
			val.operand = "SaveFile-Archipelago.gwsave";
			return list.AsEnumerable();
		}

		[HarmonyPatch(typeof(SaveManager), "SaveToFile")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> ReplaceBackUpSaveFileName(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			CodeInstruction val = list.Find((CodeInstruction x) => x.opcode == OpCodes.Ldstr && (string)x.operand == "SaveFile-Backup.gwsave");
			val.operand = "SaveFile-Archipelago-Backup.gwsave";
			return list.AsEnumerable();
		}

		[HarmonyPatch(typeof(SaveManager), "SaveToFile")]
		[HarmonyPostfix]
		private static void SaveArchipelagoDataToFile()
		{
			ArchipelagoData.SaveToFile();
		}

		[HarmonyPatch(typeof(SaveFile), "GetCurrentRandomSeed")]
		[HarmonyPostfix]
		private static void AddOpenedPacksToSeed(SaveFile __instance, ref int __result)
		{
			if (__instance.IsPart1 || __instance.IsPart3)
			{
				__result += __instance.gbcData.packsOpened * 2;
			}
			if (__instance.IsPart1)
			{
				__result += RunState.Run.currentNodeId * 100 * SaveManager.saveFile.pastRuns.Count + 1;
			}
			if (__instance.IsPart2)
			{
				__result += (SaveManager.saveFile.gbcData.npcAttempts + 1) * 50;
			}
			if (__instance.IsPart3)
			{
				__result += (Part3SaveData.Data.bounty + 1) * 50;
			}
		}

		[HarmonyPatch(typeof(PageContentLoader), "LoadPage")]
		[HarmonyPostfix]
		private static void ChangeRulebookPassword(PageContentLoader __instance)
		{
			if (!ArchipelagoOptions.randomizeCodes || __instance.currentAdditiveObjects.Count <= 0 || !((Object)__instance.currentAdditiveObjects.First()).name.Contains("SafePassword"))
			{
				return;
			}
			GameObject val = __instance.currentAdditiveObjects.First();
			TextMeshPro[] componentsInChildren = val.GetComponentsInChildren<TextMeshPro>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (((Object)((Component)componentsInChildren[i]).gameObject).name.Contains("(1)"))
				{
					((TMP_Text)componentsInChildren[i]).text = ArchipelagoData.Data.cabinSafeCode[1].ToString();
				}
				else if (((Object)((Component)componentsInChildren[i]).gameObject).name.Contains("(2)"))
				{
					((TMP_Text)componentsInChildren[i]).text = ArchipelagoData.Data.cabinSafeCode[2].ToString();
				}
				else
				{
					((TMP_Text)componentsInChildren[i]).text = ArchipelagoData.Data.cabinSafeCode[0].ToString();
				}
			}
		}

		[HarmonyPatch(typeof(Part1FinaleSceneSequencer), "ShowArm")]
		[HarmonyPostfix]
		private static void ChangeSmallClockPassword(Part1FinaleSceneSequencer __instance)
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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)
			if (ArchipelagoOptions.randomizeCodes && !((Object)(object)((Component)__instance.deckTrialSequencer).transform.parent.Find("SmallClockClue(Clone)") != (Object)null))
			{
				GameObject gameObject = ((Component)((Component)__instance.deckTrialSequencer).transform.parent.Find("Cube")).gameObject;
				((Renderer)gameObject.GetComponent<MeshRenderer>()).material.mainTexture = (Texture)(object)AssetsManager.boonTableTex;
				GameObject val = Object.Instantiate<GameObject>(AssetsManager.smallClockCluePrefab, gameObject.transform.parent);
				((Renderer)val.GetComponent<MeshRenderer>()).material.mainTexture = (Texture)(object)AssetsManager.smallClockClueTexs[ArchipelagoData.Data.cabinSmallClockCode[2]];
				val.transform.localPosition = new Vector3(-1.6744f, 1.6f, -0.9f);
				val.transform.localEulerAngles = new Vector3(90f, 90f, 0f);
				val.transform.localScale = new Vector3(0.7f, 0.5f, 0.7f);
			}
		}

		[HarmonyPatch(typeof(DogFoodBowlVolume), "Start")]
		[HarmonyPostfix]
		private static void ReplaceGBCSafeCodeClue(DogFoodBowlVolume __instance)
		{
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			if (!ArchipelagoOptions.randomizeCodes)
			{
				return;
			}
			SpriteRenderer component = ((Component)((Component)__instance).transform.root.Find("OutdoorsCentral/Floor")).GetComponent<SpriteRenderer>();
			component.sprite = AssetsManager.editedNatureFloorSprite;
			GameObject val = Object.Instantiate<GameObject>(AssetsManager.gbcSafeCluePrefab, ((Component)component).transform);
			val.layer = LayerMask.NameToLayer("GBCPixel");
			string text = "";
			foreach (int item in ArchipelagoData.Data.cabinSafeCode)
			{
				text += item;
			}
			val.GetComponent<TextMesh>().text = text;
			((Renderer)val.GetComponent<MeshRenderer>()).sortingOrder = -9;
			val.transform.localPosition = new Vector3(-0.56f, 0.1f, 0f);
		}

		[HarmonyPatch(typeof(SafeVolume), "IsSolved")]
		[HarmonyPrefix]
		private static bool ReplaceGBCSafeCode(SafeVolume __instance, ref bool __result)
		{
			if (ArchipelagoOptions.randomizeCodes)
			{
				__result = SaveData.Data.natureTemple.safeState.sliderPositions[0] == ArchipelagoData.Data.cabinSafeCode[0] && SaveData.Data.natureTemple.safeState.sliderPositions[1] == ArchipelagoData.Data.cabinSafeCode[1] && SaveData.Data.natureTemple.safeState.sliderPositions[2] == ArchipelagoData.Data.cabinSafeCode[2];
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(TurnManager), "PlayerIsWinner")]
		[HarmonyPrefix]
		private static bool PlayerLostIfDeathLink(ref bool __result)
		{
			if (DeathLinkManager.receivedDeath)
			{
				__result = false;
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(Part1BossOpponent), "HasGrizzlyGlitchPhase")]
		[HarmonyPrefix]
		private static bool RemoveGrizzlyScriptedDeath(ref bool __result)
		{
			if (!ArchipelagoOptions.skipTutorial && !ArchipelagoOptions.deathlink)
			{
				return true;
			}
			__result = false;
			return false;
		}

		[HarmonyPatch(typeof(Part3GameFlowManager), "SceneSpecificInitialization")]
		[HarmonyPostfix]
		private static void FixPart3TransitionAfterPart2()
		{
			if (StoryEventsData.EventCompleted((StoryEvent)81))
			{
				PauseMenu.pausingDisabled = false;
				GameObject val = GameObject.Find("GlitchTransitionSound");
				if ((Object)(object)val != (Object)null)
				{
					AudioController.Instance.FadeSourceVolume(val.GetComponent<AudioSource>(), 0f, 4f, true);
				}
			}
		}

		[HarmonyPatch(typeof(PedestalVolume), "Start")]
		[HarmonyPostfix]
		private static void ChangePedestalCode(PedestalVolume __instance)
		{
			if (ArchipelagoOptions.randomizeCodes)
			{
				if (__instance.Index == 0)
				{
					__instance.solution = ArchipelagoData.Data.wizardCode1.ToArray();
				}
				else if (__instance.Index == 1)
				{
					__instance.solution = ArchipelagoData.Data.wizardCode2.ToArray();
				}
				else if (__instance.Index == 2)
				{
					__instance.solution = ArchipelagoData.Data.wizardCode3.ToArray();
					GameObject val = GameObject.Find("/Temple/BackRoom_3/WizardMarking_F3_2/icon");
					ArchipelagoOptions.SetClueSprite(val.GetComponent<SpriteRenderer>(), 2, 1);
					GameObject val2 = GameObject.Find("/GBCCameras/UI/PauseMenu/MenuParent/Menu/OptionsUI/MainPanel/TabGroup_Audio/WizardMarking_F3_3/icon");
					ArchipelagoOptions.SetClueSprite(val2.GetComponent<SpriteRenderer>(), 2, 2);
				}
			}
		}

		[HarmonyPatch(typeof(OilPaintingPuzzle), "GenerateSolution")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> ChangePaintingAnimal(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int index = list.FindIndex((CodeInstruction x) => x.opcode == OpCodes.Ldstr && (string)x.operand == "Squirrel");
			list.RemoveAt(index);
			list.Insert(index, new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(RandomizerHelper), "GetPaintingAnimal", (Type[])null, (Type[])null)));
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch]
	internal class DeathPatch
	{
		private static MethodBase TargetMethod()
		{
			return typeof(Part1GameFlowManager).GetNestedType("<PlayerLostBattleSequence>d__9", BindingFlags.Instance | BindingFlags.NonPublic).GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> CallPreDeathInstead(IEnumerable<CodeInstruction> instructions)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.Calls(x, AccessTools.Method(typeof(ViewManager), "SwitchToView", (Type[])null, (Type[])null)));
			num += 3;
			list.RemoveAt(num);
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(RandomizerHelper), "PrePlayerDeathSequence", (Type[])null, (Type[])null)));
			List<CodeInstruction> collection = list2;
			list.InsertRange(num, collection);
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch]
	internal class AfterDeathPatch
	{
		private static MethodBase TargetMethod()
		{
			return typeof(Part1GameFlowManager).GetNestedType("<KillPlayerSequence>d__13", BindingFlags.Instance | BindingFlags.NonPublic).GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> CallPreDeathInstead(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = list.FindIndex((CodeInstruction x) => x.opcode == OpCodes.Ldstr && (string)x.operand == "Demo_End");
			num -= 3;
			list.RemoveRange(num, 5);
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Pop, (object)null));
			list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(RandomizerHelper), "AfterPlayerDeathSequence", (Type[])null, (Type[])null)));
			List<CodeInstruction> collection = list2;
			list.InsertRange(num, collection);
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch]
	internal class DeathLinkPatch
	{
		[HarmonyPatch(typeof(CardBattleNPC), "PostCombatEncounterSequence")]
		[HarmonyPrefix]
		private static bool SendDeathLinkOnPart2(bool playerDefeated)
		{
			if (DeathLinkManager.receivedDeath)
			{
				return true;
			}
			if (playerDefeated)
			{
				DeathLinkManager.SendDeathLink();
			}
			return true;
		}

		[HarmonyPatch(typeof(Part3GameFlowManager), "PlayerRespawnSequence")]
		[HarmonyPrefix]
		private static bool SendDeathLinkOnPart3()
		{
			if (DeathLinkManager.receivedDeath)
			{
				return true;
			}
			DeathLinkManager.SendDeathLink();
			return true;
		}
	}
	[HarmonyPatch]
	internal class BlowOutCandlePatch
	{
		private static MethodBase TargetMethod()
		{
			return typeof(Part1GameFlowManager).GetNestedType("<PlayerLostBattleSequence>d__9", BindingFlags.Instance | BindingFlags.NonPublic).GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> BlowOutAllCandlesIfDeathLink(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = list.FindIndex((CodeInstruction x) => CodeInstructionExtensions.Calls(x, AccessTools.Method(typeof(CandleHolder), "BlowOutCandleSequence", (Type[])null, (Type[])null)));
			num -= 2;
			list.RemoveRange(num, 3);
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Ldc_I4_0, (object)null));
			list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(RandomizerHelper), "BlowOutOneOrAllCandles", (Type[])null, (Type[])null)));
			List<CodeInstruction> collection = list2;
			list.InsertRange(num, collection);
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch]
	internal class RandomizeDeckPatch
	{
		[HarmonyPatch(typeof(MapNode), "OnArriveAtNode")]
		[HarmonyPrefix]
		private static bool RandomizeDeckAct1(MapNode __instance)
		{
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Expected O, but got Unknown
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Expected O, but got Unknown
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_034c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: 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_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_0378: Unknown result type (might be due to invalid IL or missing references)
			if (ArchipelagoOptions.randomizeDeck != 0)
			{
				List<CardInfo> list = new List<CardInfo>();
				List<CardInfo> list2 = new List<CardInfo>();
				List<CardInfo> cardsInfoRandomPool = new List<CardInfo>();
				List<string> list3 = new List<string>();
				int currentRandomSeed = SaveManager.SaveFile.GetCurrentRandomSeed();
				if (ArchipelagoManager.HasItem(APItem.StinkbugCard))
				{
					list2.Add(CardLoader.GetCardByName("Stinkbug_Talking"));
				}
				if (ArchipelagoManager.HasItem(APItem.StuntedWolfCard))
				{
					list2.Add(CardLoader.GetCardByName("Wolf_Talking"));
				}
				list2.AddRange(RandomizerHelper.GetAllDeathCards());
				if (!StoryEventsData.EventCompleted((StoryEvent)17) && ArchipelagoManager.HasItem(APItem.CagedWolfCard))
				{
					CardInfo cardByName = CardLoader.GetCardByName("CagedWolf");
					list3.Add(((Object)cardByName).name);
					list.Add(cardByName);
				}
				if (ArchipelagoOptions.randomizeDeck == RandomizeDeck.RandomizeType)
				{
					cardsInfoRandomPool = ScriptableObjectLoader<CardInfo>.AllData.FindAll((CardInfo x) => (int)x.temple == 0 && x.metaCategories.Contains((CardMetaCategory)0) && !x.metaCategories.Contains((CardMetaCategory)6) && !x.metaCategories.Contains((CardMetaCategory)3) && ConceptProgressionTree.Tree.CardUnlocked(x, false) && (ArchipelagoManager.HasItem(APItem.GreatKrakenCard) || ((Object)x).name != "Kraken"));
				}
				else
				{
					cardsInfoRandomPool.AddRange(ScriptableObjectLoader<CardInfo>.AllData.FindAll((CardInfo x) => ((x.metaCategories.Contains((CardMetaCategory)3) || x.metaCategories.Contains((CardMetaCategory)0)) && (int)x.temple == 0 && (Object)(object)x.portraitTex != (Object)null && !x.metaCategories.Contains((CardMetaCategory)6) && ConceptProgressionTree.Tree.CardUnlocked(x, false) && (ArchipelagoManager.HasItem(APItem.GreatKrakenCard) || ((Object)x).name != "Kraken")) || ((Object)x).name == "Ouroboros"));
				}
				list2.Add(CardLoader.GetCardByName("Stoat_Talking"));
				cardsInfoRandomPool.AddRange(list2);
				foreach (CardInfo card in ((CardCollectionInfo)RunState.Run.playerDeck).Cards)
				{
					CardInfo val = ScriptableObject.CreateInstance<CardInfo>();
					if (((Object)card).name == "CagedWolf")
					{
						continue;
					}
					if (ArchipelagoOptions.randomizeDeck == RandomizeDeck.RandomizeType)
					{
						if (card.HasTrait((Trait)13))
						{
							val = card;
							list3.Add(((Object)val).name);
							list.Add(val);
							continue;
						}
						if (card.metaCategories.Contains((CardMetaCategory)3))
						{
							val = RandomizerHelper.RandomRareCardInAct1(currentRandomSeed++);
						}
						else
						{
							val = cardsInfoRandomPool[SeededRandom.Range(0, cardsInfoRandomPool.Count, currentRandomSeed++)];
							RandomizerHelper.OnlyPutOneTalkingCardInDeckAct1(ref cardsInfoRandomPool, ref val);
							if (!val.mods.Any((CardModificationInfo x) => x.deathCardInfo != null))
							{
								val = (CardInfo)val.Clone();
							}
						}
					}
					else
					{
						val = cardsInfoRandomPool[SeededRandom.Range(0, cardsInfoRandomPool.Count, currentRandomSeed++)];
						RandomizerHelper.OnlyPutOneTalkingCardInDeckAct1(ref cardsInfoRandomPool, ref val);
						if (!val.mods.Any((CardModificationInfo x) => x.deathCardInfo != null))
						{
							val = (CardInfo)val.Clone();
						}
					}
					foreach (CardModificationInfo mod in card.Mods)
					{
						if (mod.deathCardInfo != null)
						{
							continue;
						}
						if (ArchipelagoOptions.randomizeAbilities != 0 && mod.fromCardMerge)
						{
							List<Ability> list4 = new List<Ability>();
							if (mod.abilities.Count > 0)
							{
								for (int i = 0; i < mod.abilities.Count; i++)
								{
									Ability randomLearnedAbility = AbilitiesUtil.GetRandomLearnedAbility(currentRandomSeed++, false, 0, 5, (AbilityMetaCategory)1);
									while (val.HasAbility(randomLearnedAbility))
									{
										randomLearnedAbility = AbilitiesUtil.GetRandomLearnedAbility(currentRandomSeed++, false, 0, 5, (AbilityMetaCategory)1);
									}
									list4.Add(randomLearnedAbility);
								}
								mod.abilities = list4;
							}
						}
						val.mods.Add(mod);
					}
					if (ArchipelagoOptions.randomizeAbilities == RandomizeAbilities.RandomizeAll)
					{
						int count = val.abilities.Count;
						val.abilities.Clear();
						for (int j = 0; j < count; j++)
						{
							val.abilities.Add(AbilitiesUtil.GetRandomLearnedAbility(currentRandomSeed++, false, 0, 5, (AbilityMetaCategory)1));
						}
					}
					val.decals = card.decals;
					list3.Add(((Object)val).name);
					list.Add(val);
				}
				((CardCollectionInfo)RunState.Run.playerDeck).CardInfos = list;
				((CardCollectionInfo)RunState.Run.playerDeck).cardIds = list3;
				RunState.Run.playerDeck.UpdateModDictionary();
			}
			return true;
		}

		[HarmonyPatch(typeof(GBCEncounterManager), "StartEncounter")]
		[HarmonyPrefix]
		private static bool RandomizeDeckAct2()
		{
			//IL_0558: Unknown result type (might be due to invalid IL or missing references)
			//IL_055f: Expected O, but got Unknown
			//IL_049c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04be: Expected I4, but got Unknown
			//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0400: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_0404: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: Expected I4, but got Unknown
			//IL_05c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cc: Expected O, but got Unknown
			//IL_0629: Unknown result type (might be due to invalid IL or missing references)
			//IL_0651: Unknown result type (might be due to invalid IL or missing references)
			//IL_0696: Unknown result type (might be due to invalid IL or missing references)
			//IL_0679: Unknown result type (might be due to invalid IL or missing references)
			if (ArchipelagoOptions.randomizeDeck != 0)
			{
				int currentRandomSeed = SaveManager.SaveFile.GetCurrentRandomSeed();
				List<CardInfo> list = new List<CardInfo>();
				List<string> list2 = new List<string>();
				List<CardInfo> list3 = new List<CardInfo>();
				List<CardInfo> list4 = new List<CardInfo>();
				List<CardInfo> list5 = new List<CardInfo>();
				List<CardInfo> list6 = new List<CardInfo>();
				List<CardInfo> list7 = new List<CardInfo>();
				List<CardInfo> list8 = new List<CardInfo>();
				List<CardInfo> list9 = new List<CardInfo>();
				List<CardInfo> list10 = new List<CardInfo>();
				List<CardInfo> list11 = new List<CardInfo>();
				int num = 0;
				list3 = ScriptableObjectLoader<CardInfo>.AllData.FindAll((CardInfo x) => x.metaCategories.Contains((CardMetaCategory)5) && ConceptProgressionTree.Tree.CardUnlocked(x, false) && (Object)(object)x.pixelPortrait != (Object)null && (ArchipelagoManager.HasItem(APItem.GreatKrakenCard) || ((Object)x).name != "Kraken"));
				if (!ArchipelagoManager.HasCompletedCheck(APCheck.GBCAncientObol))
				{
					CardInfo cardByName = CardLoader.GetCardByName("CoinLeft");
					list.Add(cardByName);
					list2.Add(((Object)cardByName).name);
					CardInfo cardByName2 = CardLoader.GetCardByName("CoinRight");
					list.Add(cardByName2);
					list2.Add(((Object)cardByName2).name);
					num += 2;
				}
				if (ArchipelagoOptions.randomizeDeck == RandomizeDeck.RandomizeType)
				{
					list4 = list3.FindAll((CardInfo x) => (int)x.temple == 0);
					list5 = list4.FindAll((CardInfo x) => x.metaCategories.Contains((CardMetaCategory)3));
					list4 = list4.FindAll((CardInfo x) => !x.metaCategories.Contains((CardMetaCategory)3));
					list6 = list3.FindAll((CardInfo x) => (int)x.temple == 1);
					list7 = list6.FindAll((CardInfo x) => x.metaCategories.Contains((CardMetaCategory)3));
					list6 = list6.FindAll((CardInfo x) => !x.metaCategories.Contains((CardMetaCategory)3));
					list8 = list3.FindAll((CardInfo x) => (int)x.temple == 2);
					list9 = list8.FindAll((CardInfo x) => x.metaCategories.Contains((CardMetaCategory)3));
					list8 = list8.FindAll((CardInfo x) => !x.metaCategories.Contains((CardMetaCategory)3));
					list10 = list3.FindAll((CardInfo x) => (int)x.temple == 3);
					list11 = list10.FindAll((CardInfo x) => x.metaCategories.Contains((CardMetaCategory)3));
					list10 = list10.FindAll((CardInfo x) => !x.metaCategories.Contains((CardMetaCategory)3));
				}
				if (ArchipelagoManager.HasItem(APItem.DrownedSoulCard))
				{
					list3.Add(CardLoader.GetCardByName("DrownedSoul"));
					if (ArchipelagoOptions.randomizeDeck == RandomizeDeck.RandomizeType)
					{
						list4.Add(CardLoader.GetCardByName("DrownedSoul"));
						list6.Add(CardLoader.GetCardByName("DrownedSoul"));
						list8.Add(CardLoader.GetCardByName("DrownedSoul"));
						list10.Add(CardLoader.GetCardByName("DrownedSoul"));
					}
				}
				List<AbilityInfo> list12 = ScriptableObjectLoader<AbilityInfo>.allData.FindAll((AbilityInfo x) => x.metaCategories.Contains((AbilityMetaCategory)5) || x.metaCategories.Contains((AbilityMetaCategory)6) || x.metaCategories.Contains((AbilityMetaCategory)1) || x.metaCategories.Contains((AbilityMetaCategory)3));
				foreach (CardInfo card in ((CardCollectionInfo)SaveData.Data.deck).Cards)
				{
					if (num > 0)
					{
						num--;
						continue;
					}
					CardInfo val = ScriptableObject.CreateInstance<CardInfo>();
					if (ArchipelagoOptions.randomizeDeck == RandomizeDeck.RandomizeType)
					{
						if (card.metaCategories.Contains((CardMetaCategory)3))
						{
							CardTemple temple = card.temple;
							CardTemple val2 = temple;
							switch ((int)val2)
							{
							case 0:
								val = list5[SeededRandom.Range(0, list5.Count, currentRandomSeed++)];
								break;
							case 1:
								val = list7[SeededRandom.Range(0, list7.Count, currentRandomSeed++)];
								break;
							case 2:
								val = list9[SeededRandom.Range(0, list9.Count, currentRandomSeed++)];
								break;
							case 3:
								val = list11[SeededRandom.Range(0, list11.Count, currentRandomSeed++)];
								break;
							}
						}
						else
						{
							CardTemple temple2 = card.temple;
							CardTemple val3 = temple2;
							switch ((int)val3)
							{
							case 0:
								val = list4[SeededRandom.Range(0, list4.Count, currentRandomSeed++)];
								break;
							case 1:
								val = list6[SeededRandom.Range(0, list6.Count, currentRandomSeed++)];
								break;
							case 2:
								val = list8[SeededRandom.Range(0, list8.Count, currentRandomSeed++)];
								break;
							case 3:
								val = list10[SeededRandom.Range(0, list10.Count, currentRandomSeed++)];
								break;
							}
						}
					}
					else
					{
						val = (CardInfo)list3[SeededRandom.Range(0, list3.Count, currentRandomSeed++)].Clone();
					}
					if (((Object)val).name == "DrownedSoul")
					{
						if (ArchipelagoOptions.randomizeDeck == RandomizeDeck.RandomizeType)
						{
							list4.Remove(val);
							list8.Remove(val);
							list6.Remove(val);
							list10.Remove(val);
						}
						else
						{
							list3.Remove(val);
						}
					}
					val = (CardInfo)val.Clone();
					if (ArchipelagoOptions.randomizeAbilities == RandomizeAbilities.RandomizeAll)
					{
						int num2 = 0;
						int count = val.abilities.Count;
						val.abilities.Clear();
						for (int i = 0; i < count; i++)
						{
							switch (Random.Range(0, 4))
							{
							case 0:
								val.abilities.Add(AbilitiesUtil.GetRandomLearnedAbility(currentRandomSeed++, false, 0, 5, (AbilityMetaCategory)6));
								break;
							case 1:
								val.abilities.Add(AbilitiesUtil.GetRandomLearnedAbility(currentRandomSeed++, false, 0, 5, (AbilityMetaCategory)5));
								break;
							case 2:
								val.abilities.Add(AbilitiesUtil.GetRandomLearnedAbility(currentRandomSeed++, false, 0, 5, (AbilityMetaCategory)3));
								break;
							default:
								val.abilities.Add(AbilitiesUtil.GetRandomLearnedAbility(currentRandomSeed++, false, 0, 5, (AbilityMetaCategory)1));
								break;
							}
						}
					}
					list2.Add(((Object)val).name);
					list.Add(val);
				}
				((CardCollectionInfo)SaveData.Data.deck).CardInfos = list;
				((CardCollectionInfo)SaveData.Data.deck).cardIds = list2;
				SaveData.Data.deck.UpdateModDictionary();
			}
			return true;
		}

		[HarmonyPatch(typeof(HoloMapNode), "OnSelected")]
		[HarmonyPrefix]
		private static bool RandomizeDeckAct3()
		{
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0372: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			if (ArchipelagoOptions.randomizeDeck != 0)
			{
				int seed = SaveManager.SaveFile.GetCurrentRandomSeed();
				List<CardInfo> list = new List<CardInfo>();
				List<string> list2 = new List<string>();
				List<CardInfo> cardsInfoRandomPool = ScriptableObjectLoader<CardInfo>.AllData.FindAll((CardInfo x) => (int)x.temple == 2 && (Object)(object)x.portraitTex != (Object)null && ((Object)x).name != "!BOUNTYHUNTER_BASE" && ((Object)x).name != "Librarian" && !((Object)x).name.Contains("EmptyVessel") && ((Object)x).name != "!MYCOCARD_BASE" && ((Object)x).name != "CaptiveFile" && ((Object)x).name != "!BUILDACARD_BASE");
				cardsInfoRandomPool.AddRange(RandomizerHelper.GetAllCustomCards());
				List<CardInfo> cardsInfoRandomGemPool = cardsInfoRandomPool;
				List<CardInfo> cardsInfoRandomConduitPool = cardsInfoRandomPool;
				if (ArchipelagoOptions.randomizeDeck == RandomizeDeck.RandomizeType)
				{
					cardsInfoRandomConduitPool = ScriptableObjectLoader<CardInfo>.AllData.FindAll((CardInfo x) => ((Object)x).name.Contains("Conduit") || ((Object)x).name.Contains("Cell"));
					cardsInfoRandomGemPool = ScriptableObjectLoader<CardInfo>.AllData.FindAll((CardInfo x) => ((Object)x).name.Contains("Sentinel") || ((Object)x).name.Contains("Gem"));
					cardsInfoRandomPool.RemoveAll((CardInfo x) => ((Object)x).name.Contains("Conduit") || ((Object)x).name.Contains("Cell") || ((Object)x).name.Contains("Sentinel") || ((Object)x).name.Contains("Gem"));
				}
				else
	

plugins/Newtonsoft.Json.dll

Decompiled 4 months ago
#define DEBUG
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Numerics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Versioning;
using System.Security;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json.Bson;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Linq.JsonPath;
using Newtonsoft.Json.Schema;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Utilities;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AllowPartiallyTrustedCallers]
[assembly: InternalsVisibleTo("Newtonsoft.Json.Schema")]
[assembly: InternalsVisibleTo("Newtonsoft.Json.Tests")]
[assembly: InternalsVisibleTo("Newtonsoft.Json.Dynamic, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cbd8d53b9d7de30f1f1278f636ec462cf9c254991291e66ebb157a885638a517887633b898ccbcf0d5c5ff7be85a6abe9e765d0ac7cd33c68dac67e7e64530e8222101109f154ab14a941c490ac155cd1d4fcba0fabb49016b4ef28593b015cab5937da31172f03f67d09edda404b88a60023f062ae71d0b2e4438b74cc11dc9")]
[assembly: AssemblyTrademark("")]
[assembly: CLSCompliant(true)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("Newtonsoft")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyCopyright("Copyright © James Newton-King 2008")]
[assembly: AssemblyDescription("Json.NET is a popular high-performance JSON framework for .NET")]
[assembly: AssemblyFileVersion("11.0.1")]
[assembly: AssemblyInformationalVersion("11.0.1-beta2+8931bf49300e016eeb846932030e0445944db3bf")]
[assembly: AssemblyProduct("Json.NET")]
[assembly: AssemblyTitle("Json.NET .NET Standard 2.0")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/ArchipelagoMW/Archipelago.MultiClient.Net.git")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("11.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true)]
	internal sealed class NotNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
	internal sealed class NotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public NotNullWhenAttribute(bool returnValue)
		{
			ReturnValue = returnValue;
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)]
	internal sealed class MaybeNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)]
	internal sealed class AllowNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	internal class DoesNotReturnIfAttribute : Attribute
	{
		public bool ParameterValue { get; }

		public DoesNotReturnIfAttribute(bool parameterValue)
		{
			ParameterValue = parameterValue;
		}
	}
}
namespace Newtonsoft.Json
{
	public enum ConstructorHandling
	{
		Default,
		AllowNonPublicDefaultConstructor
	}
	public enum DateFormatHandling
	{
		IsoDateFormat,
		MicrosoftDateFormat
	}
	public enum DateParseHandling
	{
		None,
		DateTime,
		DateTimeOffset
	}
	public enum DateTimeZoneHandling
	{
		Local,
		Utc,
		Unspecified,
		RoundtripKind
	}
	public class DefaultJsonNameTable : JsonNameTable
	{
		private class Entry
		{
			internal readonly string Value;

			internal readonly int HashCode;

			internal Entry Next;

			internal Entry(string value, int hashCode, Entry next)
			{
				Value = value;
				HashCode = hashCode;
				Next = next;
			}
		}

		private static readonly int HashCodeRandomizer;

		private int _count;

		private Entry[] _entries;

		private int _mask = 31;

		static DefaultJsonNameTable()
		{
			HashCodeRandomizer = Environment.TickCount;
		}

		public DefaultJsonNameTable()
		{
			_entries = new Entry[_mask + 1];
		}

		public override string? Get(char[] key, int start, int length)
		{
			if (length == 0)
			{
				return string.Empty;
			}
			int num = length + HashCodeRandomizer;
			num += (num << 7) ^ key[start];
			int num2 = start + length;
			for (int i = start + 1; i < num2; i++)
			{
				num += (num << 7) ^ key[i];
			}
			num -= num >> 17;
			num -= num >> 11;
			num -= num >> 5;
			int num3 = num & _mask;
			Entry[] entries = _entries;
			for (Entry entry = entries[num3]; entry != null; entry = entry.Next)
			{
				if (entry.HashCode == num && TextEquals(entry.Value, key, start, length))
				{
					return entry.Value;
				}
			}
			return null;
		}

		public string Add(string key)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			int length = key.Length;
			if (length == 0)
			{
				return string.Empty;
			}
			int num = length + HashCodeRandomizer;
			for (int i = 0; i < key.Length; i++)
			{
				num += (num << 7) ^ key[i];
			}
			num -= num >> 17;
			num -= num >> 11;
			num -= num >> 5;
			for (Entry entry = _entries[num & _mask]; entry != null; entry = entry.Next)
			{
				if (entry.HashCode == num && entry.Value.Equals(key, StringComparison.Ordinal))
				{
					return entry.Value;
				}
			}
			return AddEntry(key, num);
		}

		private string AddEntry(string str, int hashCode)
		{
			int num = hashCode & _mask;
			Entry entry = new Entry(str, hashCode, _entries[num]);
			_entries[num] = entry;
			if (_count++ == _mask)
			{
				Grow();
			}
			return entry.Value;
		}

		private void Grow()
		{
			Entry[] entries = _entries;
			int num = _mask * 2 + 1;
			Entry[] array = new Entry[num + 1];
			for (int i = 0; i < entries.Length; i++)
			{
				Entry entry = entries[i];
				while (entry != null)
				{
					int num2 = entry.HashCode & num;
					Entry next = entry.Next;
					entry.Next = array[num2];
					array[num2] = entry;
					entry = next;
				}
			}
			_entries = array;
			_mask = num;
		}

		private static bool TextEquals(string str1, char[] str2, int str2Start, int str2Length)
		{
			if (str1.Length != str2Length)
			{
				return false;
			}
			for (int i = 0; i < str1.Length; i++)
			{
				if (str1[i] != str2[str2Start + i])
				{
					return false;
				}
			}
			return true;
		}
	}
	[Flags]
	public enum DefaultValueHandling
	{
		Include = 0,
		Ignore = 1,
		Populate = 2,
		IgnoreAndPopulate = 3
	}
	public enum FloatFormatHandling
	{
		String,
		Symbol,
		DefaultValue
	}
	public enum FloatParseHandling
	{
		Double,
		Decimal
	}
	public enum Formatting
	{
		None,
		Indented
	}
	public interface IArrayPool<T>
	{
		T[] Rent(int minimumLength);

		void Return(T[]? array);
	}
	public interface IJsonLineInfo
	{
		int LineNumber { get; }

		int LinePosition { get; }

		bool HasLineInfo();
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
	public sealed class JsonArrayAttribute : JsonContainerAttribute
	{
		private bool _allowNullItems;

		public bool AllowNullItems
		{
			get
			{
				return _allowNullItems;
			}
			set
			{
				_allowNullItems = value;
			}
		}

		public JsonArrayAttribute()
		{
		}

		public JsonArrayAttribute(bool allowNullItems)
		{
			_allowNullItems = allowNullItems;
		}

		public JsonArrayAttribute(string id)
			: base(id)
		{
		}
	}
	[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false)]
	public sealed class JsonConstructorAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
	public abstract class JsonContainerAttribute : Attribute
	{
		internal bool? _isReference;

		internal bool? _itemIsReference;

		internal ReferenceLoopHandling? _itemReferenceLoopHandling;

		internal TypeNameHandling? _itemTypeNameHandling;

		private Type? _namingStrategyType;

		private object[]? _namingStrategyParameters;

		public string? Id { get; set; }

		public string? Title { get; set; }

		public string? Description { get; set; }

		public Type? ItemConverterType { get; set; }

		public object[]? ItemConverterParameters { get; set; }

		public Type? NamingStrategyType
		{
			get
			{
				return _namingStrategyType;
			}
			set
			{
				_namingStrategyType = value;
				NamingStrategyInstance = null;
			}
		}

		public object[]? NamingStrategyParameters
		{
			get
			{
				return _namingStrategyParameters;
			}
			set
			{
				_namingStrategyParameters = value;
				NamingStrategyInstance = null;
			}
		}

		internal NamingStrategy? NamingStrategyInstance { get; set; }

		public bool IsReference
		{
			get
			{
				return _isReference.GetValueOrDefault();
			}
			set
			{
				_isReference = value;
			}
		}

		public bool ItemIsReference
		{
			get
			{
				return _itemIsReference.GetValueOrDefault();
			}
			set
			{
				_itemIsReference = value;
			}
		}

		public ReferenceLoopHandling ItemReferenceLoopHandling
		{
			get
			{
				return _itemReferenceLoopHandling.GetValueOrDefault();
			}
			set
			{
				_itemReferenceLoopHandling = value;
			}
		}

		public TypeNameHandling ItemTypeNameHandling
		{
			get
			{
				return _itemTypeNameHandling.GetValueOrDefault();
			}
			set
			{
				_itemTypeNameHandling = value;
			}
		}

		protected JsonContainerAttribute()
		{
		}

		protected JsonContainerAttribute(string id)
		{
			Id = id;
		}
	}
	public static class JsonConvert
	{
		public static readonly string True = "true";

		public static readonly string False = "false";

		public static readonly string Null = "null";

		public static readonly string Undefined = "undefined";

		public static readonly string PositiveInfinity = "Infinity";

		public static readonly string NegativeInfinity = "-Infinity";

		public static readonly string NaN = "NaN";

		public static Func<JsonSerializerSettings>? DefaultSettings { get; set; }

		public static string ToString(DateTime value)
		{
			return ToString(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.RoundtripKind);
		}

		public static string ToString(DateTime value, DateFormatHandling format, DateTimeZoneHandling timeZoneHandling)
		{
			DateTime value2 = DateTimeUtils.EnsureDateTime(value, timeZoneHandling);
			using StringWriter stringWriter = StringUtils.CreateStringWriter(64);
			stringWriter.Write('"');
			DateTimeUtils.WriteDateTimeString(stringWriter, value2, format, null, CultureInfo.InvariantCulture);
			stringWriter.Write('"');
			return stringWriter.ToString();
		}

		public static string ToString(DateTimeOffset value)
		{
			return ToString(value, DateFormatHandling.IsoDateFormat);
		}

		public static string ToString(DateTimeOffset value, DateFormatHandling format)
		{
			using StringWriter stringWriter = StringUtils.CreateStringWriter(64);
			stringWriter.Write('"');
			DateTimeUtils.WriteDateTimeOffsetString(stringWriter, value, format, null, CultureInfo.InvariantCulture);
			stringWriter.Write('"');
			return stringWriter.ToString();
		}

		public static string ToString(bool value)
		{
			return value ? True : False;
		}

		public static string ToString(char value)
		{
			return ToString(char.ToString(value));
		}

		public static string ToString(Enum value)
		{
			return value.ToString("D");
		}

		public static string ToString(int value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		public static string ToString(short value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		[CLSCompliant(false)]
		public static string ToString(ushort value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		[CLSCompliant(false)]
		public static string ToString(uint value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		public static string ToString(long value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		private static string ToStringInternal(BigInteger value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		[CLSCompliant(false)]
		public static string ToString(ulong value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		public static string ToString(float value)
		{
			return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture));
		}

		internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
		{
			return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable);
		}

		private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
		{
			if (floatFormatHandling == FloatFormatHandling.Symbol || (!double.IsInfinity(value) && !double.IsNaN(value)))
			{
				return text;
			}
			if (floatFormatHandling == FloatFormatHandling.DefaultValue)
			{
				return (!nullable) ? "0.0" : Null;
			}
			return quoteChar + text + quoteChar;
		}

		public static string ToString(double value)
		{
			return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture));
		}

		internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
		{
			return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable);
		}

		private static string EnsureDecimalPlace(double value, string text)
		{
			if (double.IsNaN(value) || double.IsInfinity(value) || text.IndexOf('.') != -1 || text.IndexOf('E') != -1 || text.IndexOf('e') != -1)
			{
				return text;
			}
			return text + ".0";
		}

		private static string EnsureDecimalPlace(string text)
		{
			if (text.IndexOf('.') != -1)
			{
				return text;
			}
			return text + ".0";
		}

		public static string ToString(byte value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		[CLSCompliant(false)]
		public static string ToString(sbyte value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		public static string ToString(decimal value)
		{
			return EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture));
		}

		public static string ToString(Guid value)
		{
			return ToString(value, '"');
		}

		internal static string ToString(Guid value, char quoteChar)
		{
			string text = value.ToString("D", CultureInfo.InvariantCulture);
			string text2 = quoteChar.ToString(CultureInfo.InvariantCulture);
			return text2 + text + text2;
		}

		public static string ToString(TimeSpan value)
		{
			return ToString(value, '"');
		}

		internal static string ToString(TimeSpan value, char quoteChar)
		{
			return ToString(value.ToString(), quoteChar);
		}

		public static string ToString(Uri? value)
		{
			if (value == null)
			{
				return Null;
			}
			return ToString(value, '"');
		}

		internal static string ToString(Uri value, char quoteChar)
		{
			return ToString(value.OriginalString, quoteChar);
		}

		public static string ToString(string? value)
		{
			return ToString(value, '"');
		}

		public static string ToString(string? value, char delimiter)
		{
			return ToString(value, delimiter, StringEscapeHandling.Default);
		}

		public static string ToString(string? value, char delimiter, StringEscapeHandling stringEscapeHandling)
		{
			if (delimiter != '"' && delimiter != '\'')
			{
				throw new ArgumentException("Delimiter must be a single or double quote.", "delimiter");
			}
			return JavaScriptUtils.ToEscapedJavaScriptString(value, delimiter, appendDelimiters: true, stringEscapeHandling);
		}

		public static string ToString(object? value)
		{
			if (value == null)
			{
				return Null;
			}
			return ConvertUtils.GetTypeCode(value.GetType()) switch
			{
				PrimitiveTypeCode.String => ToString((string)value), 
				PrimitiveTypeCode.Char => ToString((char)value), 
				PrimitiveTypeCode.Boolean => ToString((bool)value), 
				PrimitiveTypeCode.SByte => ToString((sbyte)value), 
				PrimitiveTypeCode.Int16 => ToString((short)value), 
				PrimitiveTypeCode.UInt16 => ToString((ushort)value), 
				PrimitiveTypeCode.Int32 => ToString((int)value), 
				PrimitiveTypeCode.Byte => ToString((byte)value), 
				PrimitiveTypeCode.UInt32 => ToString((uint)value), 
				PrimitiveTypeCode.Int64 => ToString((long)value), 
				PrimitiveTypeCode.UInt64 => ToString((ulong)value), 
				PrimitiveTypeCode.Single => ToString((float)value), 
				PrimitiveTypeCode.Double => ToString((double)value), 
				PrimitiveTypeCode.DateTime => ToString((DateTime)value), 
				PrimitiveTypeCode.Decimal => ToString((decimal)value), 
				PrimitiveTypeCode.DateTimeOffset => ToString((DateTimeOffset)value), 
				PrimitiveTypeCode.Guid => ToString((Guid)value), 
				PrimitiveTypeCode.Uri => ToString((Uri)value), 
				PrimitiveTypeCode.TimeSpan => ToString((TimeSpan)value), 
				PrimitiveTypeCode.BigInteger => ToStringInternal((BigInteger)value), 
				_ => throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType())), 
			};
		}

		[DebuggerStepThrough]
		public static string SerializeObject(object? value)
		{
			return SerializeObject(value, (Type?)null, (JsonSerializerSettings?)null);
		}

		[DebuggerStepThrough]
		public static string SerializeObject(object? value, Formatting formatting)
		{
			return SerializeObject(value, formatting, (JsonSerializerSettings?)null);
		}

		[DebuggerStepThrough]
		public static string SerializeObject(object? value, params JsonConverter[] converters)
		{
			JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings
			{
				Converters = converters
			} : null);
			return SerializeObject(value, null, settings);
		}

		[DebuggerStepThrough]
		public static string SerializeObject(object? value, Formatting formatting, params JsonConverter[] converters)
		{
			JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings
			{
				Converters = converters
			} : null);
			return SerializeObject(value, null, formatting, settings);
		}

		[DebuggerStepThrough]
		public static string SerializeObject(object? value, JsonSerializerSettings? settings)
		{
			return SerializeObject(value, null, settings);
		}

		[DebuggerStepThrough]
		public static string SerializeObject(object? value, Type? type, JsonSerializerSettings? settings)
		{
			JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
			return SerializeObjectInternal(value, type, jsonSerializer);
		}

		[DebuggerStepThrough]
		public static string SerializeObject(object? value, Formatting formatting, JsonSerializerSettings? settings)
		{
			return SerializeObject(value, null, formatting, settings);
		}

		[DebuggerStepThrough]
		public static string SerializeObject(object? value, Type? type, Formatting formatting, JsonSerializerSettings? settings)
		{
			JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
			jsonSerializer.Formatting = formatting;
			return SerializeObjectInternal(value, type, jsonSerializer);
		}

		private static string SerializeObjectInternal(object? value, Type? type, JsonSerializer jsonSerializer)
		{
			StringBuilder sb = new StringBuilder(256);
			StringWriter stringWriter = new StringWriter(sb, CultureInfo.InvariantCulture);
			using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter))
			{
				jsonTextWriter.Formatting = jsonSerializer.Formatting;
				jsonSerializer.Serialize(jsonTextWriter, value, type);
			}
			return stringWriter.ToString();
		}

		[DebuggerStepThrough]
		public static object? DeserializeObject(string value)
		{
			return DeserializeObject(value, (Type?)null, (JsonSerializerSettings?)null);
		}

		[DebuggerStepThrough]
		public static object? DeserializeObject(string value, JsonSerializerSettings settings)
		{
			return DeserializeObject(value, null, settings);
		}

		[DebuggerStepThrough]
		public static object? DeserializeObject(string value, Type type)
		{
			return DeserializeObject(value, type, (JsonSerializerSettings?)null);
		}

		[DebuggerStepThrough]
		public static T? DeserializeObject<T>(string value)
		{
			return JsonConvert.DeserializeObject<T>(value, (JsonSerializerSettings?)null);
		}

		[DebuggerStepThrough]
		public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject)
		{
			return DeserializeObject<T>(value);
		}

		[DebuggerStepThrough]
		public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject, JsonSerializerSettings settings)
		{
			return DeserializeObject<T>(value, settings);
		}

		[DebuggerStepThrough]
		public static T? DeserializeObject<T>(string value, params JsonConverter[] converters)
		{
			return (T)DeserializeObject(value, typeof(T), converters);
		}

		[DebuggerStepThrough]
		public static T? DeserializeObject<T>(string value, JsonSerializerSettings? settings)
		{
			return (T)DeserializeObject(value, typeof(T), settings);
		}

		[DebuggerStepThrough]
		public static object? DeserializeObject(string value, Type type, params JsonConverter[] converters)
		{
			JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings
			{
				Converters = converters
			} : null);
			return DeserializeObject(value, type, settings);
		}

		public static object? DeserializeObject(string value, Type? type, JsonSerializerSettings? settings)
		{
			ValidationUtils.ArgumentNotNull(value, "value");
			JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
			if (!jsonSerializer.IsCheckAdditionalContentSet())
			{
				jsonSerializer.CheckAdditionalContent = true;
			}
			using JsonTextReader reader = new JsonTextReader(new StringReader(value));
			return jsonSerializer.Deserialize(reader, type);
		}

		[DebuggerStepThrough]
		public static void PopulateObject(string value, object target)
		{
			PopulateObject(value, target, null);
		}

		public static void PopulateObject(string value, object target, JsonSerializerSettings? settings)
		{
			JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
			using JsonReader jsonReader = new JsonTextReader(new StringReader(value));
			jsonSerializer.Populate(jsonReader, target);
			if (settings == null || !settings.CheckAdditionalContent)
			{
				return;
			}
			while (jsonReader.Read())
			{
				if (jsonReader.TokenType != JsonToken.Comment)
				{
					throw JsonSerializationException.Create(jsonReader, "Additional text found in JSON string after finishing deserializing object.");
				}
			}
		}
	}
	public abstract class JsonConverter
	{
		public virtual bool CanRead => true;

		public virtual bool CanWrite => true;

		public abstract void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer);

		public abstract object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer);

		public abstract bool CanConvert(Type objectType);
	}
	public abstract class JsonConverter<T> : JsonConverter
	{
		public sealed override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
		{
			if (!((value != null) ? (value is T) : ReflectionUtils.IsNullable(typeof(T))))
			{
				throw new JsonSerializationException("Converter cannot write specified value to JSON. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T)));
			}
			WriteJson(writer, (T)value, serializer);
		}

		public abstract void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer);

		public sealed override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
		{
			bool flag = existingValue == null;
			if (!flag && !(existingValue is T))
			{
				throw new JsonSerializationException("Converter cannot read JSON with the specified existing value. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T)));
			}
			return ReadJson(reader, objectType, flag ? default(T) : ((T)existingValue), !flag, serializer);
		}

		public abstract T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer);

		public sealed override bool CanConvert(Type objectType)
		{
			return typeof(T).IsAssignableFrom(objectType);
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter, AllowMultiple = false)]
	public sealed class JsonConverterAttribute : Attribute
	{
		private readonly Type _converterType;

		public Type ConverterType => _converterType;

		public object[]? ConverterParameters { get; }

		public JsonConverterAttribute(Type converterType)
		{
			if (converterType == null)
			{
				throw new ArgumentNullException("converterType");
			}
			_converterType = converterType;
		}

		public JsonConverterAttribute(Type converterType, params object[] converterParameters)
			: this(converterType)
		{
			ConverterParameters = converterParameters;
		}
	}
	public class JsonConverterCollection : Collection<JsonConverter>
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
	public sealed class JsonDictionaryAttribute : JsonContainerAttribute
	{
		public JsonDictionaryAttribute()
		{
		}

		public JsonDictionaryAttribute(string id)
			: base(id)
		{
		}
	}
	[Serializable]
	public class JsonException : Exception
	{
		public JsonException()
		{
		}

		public JsonException(string message)
			: base(message)
		{
		}

		public JsonException(string message, Exception? innerException)
			: base(message, innerException)
		{
		}

		public JsonException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}

		internal static JsonException Create(IJsonLineInfo lineInfo, string path, string message)
		{
			message = JsonPosition.FormatMessage(lineInfo, path, message);
			return new JsonException(message);
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
	public class JsonExtensionDataAttribute : Attribute
	{
		public bool WriteData { get; set; }

		public bool ReadData { get; set; }

		public JsonExtensionDataAttribute()
		{
			WriteData = true;
			ReadData = true;
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
	public sealed class JsonIgnoreAttribute : Attribute
	{
	}
	public abstract class JsonNameTable
	{
		public abstract string? Get(char[] key, int start, int length);
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false)]
	public sealed class JsonObjectAttribute : JsonContainerAttribute
	{
		private MemberSerialization _memberSerialization = MemberSerialization.OptOut;

		internal MissingMemberHandling? _missingMemberHandling;

		internal Required? _itemRequired;

		internal NullValueHandling? _itemNullValueHandling;

		public MemberSerialization MemberSerialization
		{
			get
			{
				return _memberSerialization;
			}
			set
			{
				_memberSerialization = value;
			}
		}

		public MissingMemberHandling MissingMemberHandling
		{
			get
			{
				return _missingMemberHandling.GetValueOrDefault();
			}
			set
			{
				_missingMemberHandling = value;
			}
		}

		public NullValueHandling ItemNullValueHandling
		{
			get
			{
				return _itemNullValueHandling.GetValueOrDefault();
			}
			set
			{
				_itemNullValueHandling = value;
			}
		}

		public Required ItemRequired
		{
			get
			{
				return _itemRequired.GetValueOrDefault();
			}
			set
			{
				_itemRequired = value;
			}
		}

		public JsonObjectAttribute()
		{
		}

		public JsonObjectAttribute(MemberSerialization memberSerialization)
		{
			MemberSerialization = memberSerialization;
		}

		public JsonObjectAttribute(string id)
			: base(id)
		{
		}
	}
	internal enum JsonContainerType
	{
		None,
		Object,
		Array,
		Constructor
	}
	internal struct JsonPosition
	{
		private static readonly char[] SpecialCharacters = new char[18]
		{
			'.', ' ', '\'', '/', '"', '[', ']', '(', ')', '\t',
			'\n', '\r', '\f', '\b', '\\', '\u0085', '\u2028', '\u2029'
		};

		internal JsonContainerType Type;

		internal int Position;

		internal string? PropertyName;

		internal bool HasIndex;

		public JsonPosition(JsonContainerType type)
		{
			Type = type;
			HasIndex = TypeHasIndex(type);
			Position = -1;
			PropertyName = null;
		}

		internal int CalculateLength()
		{
			switch (Type)
			{
			case JsonContainerType.Object:
				return PropertyName.Length + 5;
			case JsonContainerType.Array:
			case JsonContainerType.Constructor:
				return MathUtils.IntLength((ulong)Position) + 2;
			default:
				throw new ArgumentOutOfRangeException("Type");
			}
		}

		internal void WriteTo(StringBuilder sb, ref StringWriter? writer, ref char[]? buffer)
		{
			switch (Type)
			{
			case JsonContainerType.Object:
			{
				string propertyName = PropertyName;
				if (propertyName.IndexOfAny(SpecialCharacters) != -1)
				{
					sb.Append("['");
					if (writer == null)
					{
						writer = new StringWriter(sb);
					}
					JavaScriptUtils.WriteEscapedJavaScriptString(writer, propertyName, '\'', appendDelimiters: false, JavaScriptUtils.SingleQuoteCharEscapeFlags, StringEscapeHandling.Default, null, ref buffer);
					sb.Append("']");
				}
				else
				{
					if (sb.Length > 0)
					{
						sb.Append('.');
					}
					sb.Append(propertyName);
				}
				break;
			}
			case JsonContainerType.Array:
			case JsonContainerType.Constructor:
				sb.Append('[');
				sb.Append(Position);
				sb.Append(']');
				break;
			}
		}

		internal static bool TypeHasIndex(JsonContainerType type)
		{
			return type == JsonContainerType.Array || type == JsonContainerType.Constructor;
		}

		internal static string BuildPath(List<JsonPosition> positions, JsonPosition? currentPosition)
		{
			int num = 0;
			if (positions != null)
			{
				for (int i = 0; i < positions.Count; i++)
				{
					num += positions[i].CalculateLength();
				}
			}
			if (currentPosition.HasValue)
			{
				num += currentPosition.GetValueOrDefault().CalculateLength();
			}
			StringBuilder stringBuilder = new StringBuilder(num);
			StringWriter writer = null;
			char[] buffer = null;
			if (positions != null)
			{
				foreach (JsonPosition position in positions)
				{
					position.WriteTo(stringBuilder, ref writer, ref buffer);
				}
			}
			currentPosition?.WriteTo(stringBuilder, ref writer, ref buffer);
			return stringBuilder.ToString();
		}

		internal static string FormatMessage(IJsonLineInfo? lineInfo, string path, string message)
		{
			if (!message.EndsWith(Environment.NewLine, StringComparison.Ordinal))
			{
				message = message.Trim();
				if (!StringUtils.EndsWith(message, '.'))
				{
					message += ".";
				}
				message += " ";
			}
			message += "Path '{0}'".FormatWith(CultureInfo.InvariantCulture, path);
			if (lineInfo != null && lineInfo.HasLineInfo())
			{
				message += ", line {0}, position {1}".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition);
			}
			message += ".";
			return message;
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
	public sealed class JsonPropertyAttribute : Attribute
	{
		internal NullValueHandling? _nullValueHandling;

		internal DefaultValueHandling? _defaultValueHandling;

		internal ReferenceLoopHandling? _referenceLoopHandling;

		internal ObjectCreationHandling? _objectCreationHandling;

		internal TypeNameHandling? _typeNameHandling;

		internal bool? _isReference;

		internal int? _order;

		internal Required? _required;

		internal bool? _itemIsReference;

		internal ReferenceLoopHandling? _itemReferenceLoopHandling;

		internal TypeNameHandling? _itemTypeNameHandling;

		public Type? ItemConverterType { get; set; }

		public object[]? ItemConverterParameters { get; set; }

		public Type? NamingStrategyType { get; set; }

		public object[]? NamingStrategyParameters { get; set; }

		public NullValueHandling NullValueHandling
		{
			get
			{
				return _nullValueHandling.GetValueOrDefault();
			}
			set
			{
				_nullValueHandling = value;
			}
		}

		public DefaultValueHandling DefaultValueHandling
		{
			get
			{
				return _defaultValueHandling.GetValueOrDefault();
			}
			set
			{
				_defaultValueHandling = value;
			}
		}

		public ReferenceLoopHandling ReferenceLoopHandling
		{
			get
			{
				return _referenceLoopHandling.GetValueOrDefault();
			}
			set
			{
				_referenceLoopHandling = value;
			}
		}

		public ObjectCreationHandling ObjectCreationHandling
		{
			get
			{
				return _objectCreationHandling.GetValueOrDefault();
			}
			set
			{
				_objectCreationHandling = value;
			}
		}

		public TypeNameHandling TypeNameHandling
		{
			get
			{
				return _typeNameHandling.GetValueOrDefault();
			}
			set
			{
				_typeNameHandling = value;
			}
		}

		public bool IsReference
		{
			get
			{
				return _isReference.GetValueOrDefault();
			}
			set
			{
				_isReference = value;
			}
		}

		public int Order
		{
			get
			{
				return _order.GetValueOrDefault();
			}
			set
			{
				_order = value;
			}
		}

		public Required Required
		{
			get
			{
				return _required.GetValueOrDefault();
			}
			set
			{
				_required = value;
			}
		}

		public string? PropertyName { get; set; }

		public ReferenceLoopHandling ItemReferenceLoopHandling
		{
			get
			{
				return _itemReferenceLoopHandling.GetValueOrDefault();
			}
			set
			{
				_itemReferenceLoopHandling = value;
			}
		}

		public TypeNameHandling ItemTypeNameHandling
		{
			get
			{
				return _itemTypeNameHandling.GetValueOrDefault();
			}
			set
			{
				_itemTypeNameHandling = value;
			}
		}

		public bool ItemIsReference
		{
			get
			{
				return _itemIsReference.GetValueOrDefault();
			}
			set
			{
				_itemIsReference = value;
			}
		}

		public JsonPropertyAttribute()
		{
		}

		public JsonPropertyAttribute(string propertyName)
		{
			PropertyName = propertyName;
		}
	}
	public abstract class JsonReader : IDisposable
	{
		protected internal enum State
		{
			Start,
			Complete,
			Property,
			ObjectStart,
			Object,
			ArrayStart,
			Array,
			Closed,
			PostValue,
			ConstructorStart,
			Constructor,
			Error,
			Finished
		}

		private JsonToken _tokenType;

		private object? _value;

		internal char _quoteChar;

		internal State _currentState;

		private JsonPosition _currentPosition;

		private CultureInfo? _culture;

		private DateTimeZoneHandling _dateTimeZoneHandling;

		private int? _maxDepth;

		private bool _hasExceededMaxDepth;

		internal DateParseHandling _dateParseHandling;

		internal FloatParseHandling _floatParseHandling;

		private string? _dateFormatString;

		private List<JsonPosition>? _stack;

		protected State CurrentState => _currentState;

		public bool CloseInput { get; set; }

		public bool SupportMultipleContent { get; set; }

		public virtual char QuoteChar
		{
			get
			{
				return _quoteChar;
			}
			protected internal set
			{
				_quoteChar = value;
			}
		}

		public DateTimeZoneHandling DateTimeZoneHandling
		{
			get
			{
				return _dateTimeZoneHandling;
			}
			set
			{
				if (value < DateTimeZoneHandling.Local || value > DateTimeZoneHandling.RoundtripKind)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_dateTimeZoneHandling = value;
			}
		}

		public DateParseHandling DateParseHandling
		{
			get
			{
				return _dateParseHandling;
			}
			set
			{
				if (value < DateParseHandling.None || value > DateParseHandling.DateTimeOffset)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_dateParseHandling = value;
			}
		}

		public FloatParseHandling FloatParseHandling
		{
			get
			{
				return _floatParseHandling;
			}
			set
			{
				if (value < FloatParseHandling.Double || value > FloatParseHandling.Decimal)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_floatParseHandling = value;
			}
		}

		public string? DateFormatString
		{
			get
			{
				return _dateFormatString;
			}
			set
			{
				_dateFormatString = value;
			}
		}

		public int? MaxDepth
		{
			get
			{
				return _maxDepth;
			}
			set
			{
				if (value <= 0)
				{
					throw new ArgumentException("Value must be positive.", "value");
				}
				_maxDepth = value;
			}
		}

		public virtual JsonToken TokenType => _tokenType;

		public virtual object? Value => _value;

		public virtual Type? ValueType => _value?.GetType();

		public virtual int Depth
		{
			get
			{
				int num = _stack?.Count ?? 0;
				if (JsonTokenUtils.IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None)
				{
					return num;
				}
				return num + 1;
			}
		}

		public virtual string Path
		{
			get
			{
				if (_currentPosition.Type == JsonContainerType.None)
				{
					return string.Empty;
				}
				JsonPosition? currentPosition = ((_currentState != State.ArrayStart && _currentState != State.ConstructorStart && _currentState != State.ObjectStart) ? new JsonPosition?(_currentPosition) : null);
				return JsonPosition.BuildPath(_stack, currentPosition);
			}
		}

		public CultureInfo Culture
		{
			get
			{
				return _culture ?? CultureInfo.InvariantCulture;
			}
			set
			{
				_culture = value;
			}
		}

		public virtual Task<bool> ReadAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			return cancellationToken.CancelIfRequestedAsync<bool>() ?? Read().ToAsync();
		}

		public async Task SkipAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			if (TokenType == JsonToken.PropertyName)
			{
				await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
			}
			if (JsonTokenUtils.IsStartToken(TokenType))
			{
				int depth = Depth;
				while (await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && depth < Depth)
				{
				}
			}
		}

		internal async Task ReaderReadAndAssertAsync(CancellationToken cancellationToken)
		{
			if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)))
			{
				throw CreateUnexpectedEndException();
			}
		}

		public virtual Task<bool?> ReadAsBooleanAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			return cancellationToken.CancelIfRequestedAsync<bool?>() ?? Task.FromResult(ReadAsBoolean());
		}

		public virtual Task<byte[]?> ReadAsBytesAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			return cancellationToken.CancelIfRequestedAsync<byte[]>() ?? Task.FromResult(ReadAsBytes());
		}

		internal async Task<byte[]?> ReadArrayIntoByteArrayAsync(CancellationToken cancellationToken)
		{
			List<byte> buffer = new List<byte>();
			do
			{
				if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)))
				{
					SetToken(JsonToken.None);
				}
			}
			while (!ReadArrayElementIntoByteArrayReportDone(buffer));
			byte[] d = buffer.ToArray();
			SetToken(JsonToken.Bytes, d, updateIndex: false);
			return d;
		}

		public virtual Task<DateTime?> ReadAsDateTimeAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			return cancellationToken.CancelIfRequestedAsync<DateTime?>() ?? Task.FromResult(ReadAsDateTime());
		}

		public virtual Task<DateTimeOffset?> ReadAsDateTimeOffsetAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			return cancellationToken.CancelIfRequestedAsync<DateTimeOffset?>() ?? Task.FromResult(ReadAsDateTimeOffset());
		}

		public virtual Task<decimal?> ReadAsDecimalAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			return cancellationToken.CancelIfRequestedAsync<decimal?>() ?? Task.FromResult(ReadAsDecimal());
		}

		public virtual Task<double?> ReadAsDoubleAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			return Task.FromResult(ReadAsDouble());
		}

		public virtual Task<int?> ReadAsInt32Async(CancellationToken cancellationToken = default(CancellationToken))
		{
			return cancellationToken.CancelIfRequestedAsync<int?>() ?? Task.FromResult(ReadAsInt32());
		}

		public virtual Task<string?> ReadAsStringAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			return cancellationToken.CancelIfRequestedAsync<string>() ?? Task.FromResult(ReadAsString());
		}

		internal async Task<bool> ReadAndMoveToContentAsync(CancellationToken cancellationToken)
		{
			bool flag = await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
			if (flag)
			{
				flag = await MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
			}
			return flag;
		}

		internal Task<bool> MoveToContentAsync(CancellationToken cancellationToken)
		{
			JsonToken tokenType = TokenType;
			JsonToken jsonToken = tokenType;
			if (jsonToken == JsonToken.None || jsonToken == JsonToken.Comment)
			{
				return MoveToContentFromNonContentAsync(cancellationToken);
			}
			return AsyncUtils.True;
		}

		private async Task<bool> MoveToContentFromNonContentAsync(CancellationToken cancellationToken)
		{
			JsonToken jsonToken2;
			do
			{
				if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)))
				{
					return false;
				}
				JsonToken tokenType = TokenType;
				JsonToken jsonToken = tokenType;
				jsonToken2 = jsonToken;
			}
			while (jsonToken2 == JsonToken.None || jsonToken2 == JsonToken.Comment);
			return true;
		}

		internal JsonPosition GetPosition(int depth)
		{
			if (_stack != null && depth < _stack.Count)
			{
				return _stack[depth];
			}
			return _currentPosition;
		}

		protected JsonReader()
		{
			_currentState = State.Start;
			_dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
			_dateParseHandling = DateParseHandling.DateTime;
			_floatParseHandling = FloatParseHandling.Double;
			_maxDepth = 64;
			CloseInput = true;
		}

		private void Push(JsonContainerType value)
		{
			UpdateScopeWithFinishedValue();
			if (_currentPosition.Type == JsonContainerType.None)
			{
				_currentPosition = new JsonPosition(value);
				return;
			}
			if (_stack == null)
			{
				_stack = new List<JsonPosition>();
			}
			_stack.Add(_currentPosition);
			_currentPosition = new JsonPosition(value);
			if (!_maxDepth.HasValue || !(Depth + 1 > _maxDepth) || _hasExceededMaxDepth)
			{
				return;
			}
			_hasExceededMaxDepth = true;
			throw JsonReaderException.Create(this, "The reader's MaxDepth of {0} has been exceeded.".FormatWith(CultureInfo.InvariantCulture, _maxDepth));
		}

		private JsonContainerType Pop()
		{
			JsonPosition currentPosition;
			if (_stack != null && _stack.Count > 0)
			{
				currentPosition = _currentPosition;
				_currentPosition = _stack[_stack.Count - 1];
				_stack.RemoveAt(_stack.Count - 1);
			}
			else
			{
				currentPosition = _currentPosition;
				_currentPosition = default(JsonPosition);
			}
			if (_maxDepth.HasValue && Depth <= _maxDepth)
			{
				_hasExceededMaxDepth = false;
			}
			return currentPosition.Type;
		}

		private JsonContainerType Peek()
		{
			return _currentPosition.Type;
		}

		public abstract bool Read();

		public virtual int? ReadAsInt32()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Integer:
			case JsonToken.Float:
			{
				object value = Value;
				if (value is int value2)
				{
					return value2;
				}
				int num;
				if (value is BigInteger bigInteger)
				{
					num = (int)bigInteger;
				}
				else
				{
					try
					{
						num = Convert.ToInt32(value, CultureInfo.InvariantCulture);
					}
					catch (Exception ex)
					{
						throw JsonReaderException.Create(this, "Could not convert to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex);
					}
				}
				SetToken(JsonToken.Integer, num, updateIndex: false);
				return num;
			}
			case JsonToken.String:
			{
				string s = (string)Value;
				return ReadInt32String(s);
			}
			default:
				throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		internal int? ReadInt32String(string? s)
		{
			if (StringUtils.IsNullOrEmpty(s))
			{
				SetToken(JsonToken.Null, null, updateIndex: false);
				return null;
			}
			if (int.TryParse(s, NumberStyles.Integer, Culture, out var result))
			{
				SetToken(JsonToken.Integer, result, updateIndex: false);
				return result;
			}
			SetToken(JsonToken.String, s, updateIndex: false);
			throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
		}

		public virtual string? ReadAsString()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.String:
				return (string)Value;
			default:
				if (JsonTokenUtils.IsPrimitiveToken(contentToken))
				{
					object value = Value;
					if (value != null)
					{
						string text = ((!(value is IFormattable formattable)) ? ((value is Uri uri) ? uri.OriginalString : value.ToString()) : formattable.ToString(null, Culture));
						SetToken(JsonToken.String, text, updateIndex: false);
						return text;
					}
				}
				throw JsonReaderException.Create(this, "Error reading string. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		public virtual byte[]? ReadAsBytes()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.StartObject:
			{
				ReadIntoWrappedTypeObject();
				byte[] array3 = ReadAsBytes();
				ReaderReadAndAssert();
				if (TokenType != JsonToken.EndObject)
				{
					throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
				}
				SetToken(JsonToken.Bytes, array3, updateIndex: false);
				return array3;
			}
			case JsonToken.String:
			{
				string text = (string)Value;
				Guid g;
				byte[] array2 = ((text.Length == 0) ? CollectionUtils.ArrayEmpty<byte>() : ((!ConvertUtils.TryConvertGuid(text, out g)) ? Convert.FromBase64String(text) : g.ToByteArray()));
				SetToken(JsonToken.Bytes, array2, updateIndex: false);
				return array2;
			}
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Bytes:
				if (Value is Guid guid)
				{
					byte[] array = guid.ToByteArray();
					SetToken(JsonToken.Bytes, array, updateIndex: false);
					return array;
				}
				return (byte[])Value;
			case JsonToken.StartArray:
				return ReadArrayIntoByteArray();
			default:
				throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		internal byte[] ReadArrayIntoByteArray()
		{
			List<byte> list = new List<byte>();
			do
			{
				if (!Read())
				{
					SetToken(JsonToken.None);
				}
			}
			while (!ReadArrayElementIntoByteArrayReportDone(list));
			byte[] array = list.ToArray();
			SetToken(JsonToken.Bytes, array, updateIndex: false);
			return array;
		}

		private bool ReadArrayElementIntoByteArrayReportDone(List<byte> buffer)
		{
			switch (TokenType)
			{
			case JsonToken.None:
				throw JsonReaderException.Create(this, "Unexpected end when reading bytes.");
			case JsonToken.Integer:
				buffer.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture));
				return false;
			case JsonToken.EndArray:
				return true;
			case JsonToken.Comment:
				return false;
			default:
				throw JsonReaderException.Create(this, "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
			}
		}

		public virtual double? ReadAsDouble()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Integer:
			case JsonToken.Float:
			{
				object value = Value;
				if (value is double value2)
				{
					return value2;
				}
				double num = ((!(value is BigInteger bigInteger) || 1 == 0) ? Convert.ToDouble(value, CultureInfo.InvariantCulture) : ((double)bigInteger));
				SetToken(JsonToken.Float, num, updateIndex: false);
				return num;
			}
			case JsonToken.String:
				return ReadDoubleString((string)Value);
			default:
				throw JsonReaderException.Create(this, "Error reading double. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		internal double? ReadDoubleString(string? s)
		{
			if (StringUtils.IsNullOrEmpty(s))
			{
				SetToken(JsonToken.Null, null, updateIndex: false);
				return null;
			}
			if (double.TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, Culture, out var result))
			{
				SetToken(JsonToken.Float, result, updateIndex: false);
				return result;
			}
			SetToken(JsonToken.String, s, updateIndex: false);
			throw JsonReaderException.Create(this, "Could not convert string to double: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
		}

		public virtual bool? ReadAsBoolean()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Integer:
			case JsonToken.Float:
			{
				bool flag = ((!(Value is BigInteger bigInteger) || 1 == 0) ? Convert.ToBoolean(Value, CultureInfo.InvariantCulture) : (bigInteger != 0L));
				SetToken(JsonToken.Boolean, flag, updateIndex: false);
				return flag;
			}
			case JsonToken.String:
				return ReadBooleanString((string)Value);
			case JsonToken.Boolean:
				return (bool)Value;
			default:
				throw JsonReaderException.Create(this, "Error reading boolean. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		internal bool? ReadBooleanString(string? s)
		{
			if (StringUtils.IsNullOrEmpty(s))
			{
				SetToken(JsonToken.Null, null, updateIndex: false);
				return null;
			}
			if (bool.TryParse(s, out var result))
			{
				SetToken(JsonToken.Boolean, result, updateIndex: false);
				return result;
			}
			SetToken(JsonToken.String, s, updateIndex: false);
			throw JsonReaderException.Create(this, "Could not convert string to boolean: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
		}

		public virtual decimal? ReadAsDecimal()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Integer:
			case JsonToken.Float:
			{
				object value = Value;
				if (value is decimal value2)
				{
					return value2;
				}
				decimal num;
				if (value is BigInteger bigInteger)
				{
					num = (decimal)bigInteger;
				}
				else
				{
					try
					{
						num = Convert.ToDecimal(value, CultureInfo.InvariantCulture);
					}
					catch (Exception ex)
					{
						throw JsonReaderException.Create(this, "Could not convert to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex);
					}
				}
				SetToken(JsonToken.Float, num, updateIndex: false);
				return num;
			}
			case JsonToken.String:
				return ReadDecimalString((string)Value);
			default:
				throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		internal decimal? ReadDecimalString(string? s)
		{
			if (StringUtils.IsNullOrEmpty(s))
			{
				SetToken(JsonToken.Null, null, updateIndex: false);
				return null;
			}
			if (decimal.TryParse(s, NumberStyles.Number, Culture, out var result))
			{
				SetToken(JsonToken.Float, result, updateIndex: false);
				return result;
			}
			if (ConvertUtils.DecimalTryParse(s.ToCharArray(), 0, s.Length, out result) == ParseResult.Success)
			{
				SetToken(JsonToken.Float, result, updateIndex: false);
				return result;
			}
			SetToken(JsonToken.String, s, updateIndex: false);
			throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
		}

		public virtual DateTime? ReadAsDateTime()
		{
			switch (GetContentToken())
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Date:
				if (Value is DateTimeOffset dateTimeOffset)
				{
					SetToken(JsonToken.Date, dateTimeOffset.DateTime, updateIndex: false);
				}
				return (DateTime)Value;
			case JsonToken.String:
				return ReadDateTimeString((string)Value);
			default:
				throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
			}
		}

		internal DateTime? ReadDateTimeString(string? s)
		{
			if (StringUtils.IsNullOrEmpty(s))
			{
				SetToken(JsonToken.Null, null, updateIndex: false);
				return null;
			}
			if (DateTimeUtils.TryParseDateTime(s, DateTimeZoneHandling, _dateFormatString, Culture, out var dt))
			{
				dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
				SetToken(JsonToken.Date, dt, updateIndex: false);
				return dt;
			}
			if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
			{
				dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
				SetToken(JsonToken.Date, dt, updateIndex: false);
				return dt;
			}
			throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
		}

		public virtual DateTimeOffset? ReadAsDateTimeOffset()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Date:
				if (Value is DateTime dateTime)
				{
					SetToken(JsonToken.Date, new DateTimeOffset(dateTime), updateIndex: false);
				}
				return (DateTimeOffset)Value;
			case JsonToken.String:
			{
				string s = (string)Value;
				return ReadDateTimeOffsetString(s);
			}
			default:
				throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		internal DateTimeOffset? ReadDateTimeOffsetString(string? s)
		{
			if (StringUtils.IsNullOrEmpty(s))
			{
				SetToken(JsonToken.Null, null, updateIndex: false);
				return null;
			}
			if (DateTimeUtils.TryParseDateTimeOffset(s, _dateFormatString, Culture, out var dt))
			{
				SetToken(JsonToken.Date, dt, updateIndex: false);
				return dt;
			}
			if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
			{
				SetToken(JsonToken.Date, dt, updateIndex: false);
				return dt;
			}
			SetToken(JsonToken.String, s, updateIndex: false);
			throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
		}

		internal void ReaderReadAndAssert()
		{
			if (!Read())
			{
				throw CreateUnexpectedEndException();
			}
		}

		internal JsonReaderException CreateUnexpectedEndException()
		{
			return JsonReaderException.Create(this, "Unexpected end when reading JSON.");
		}

		internal void ReadIntoWrappedTypeObject()
		{
			ReaderReadAndAssert();
			if (Value != null && Value.ToString() == "$type")
			{
				ReaderReadAndAssert();
				if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal))
				{
					ReaderReadAndAssert();
					if (Value.ToString() == "$value")
					{
						return;
					}
				}
			}
			throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject));
		}

		public void Skip()
		{
			if (TokenType == JsonToken.PropertyName)
			{
				Read();
			}
			if (JsonTokenUtils.IsStartToken(TokenType))
			{
				int depth = Depth;
				while (Read() && depth < Depth)
				{
				}
			}
		}

		protected void SetToken(JsonToken newToken)
		{
			SetToken(newToken, null, updateIndex: true);
		}

		protected void SetToken(JsonToken newToken, object? value)
		{
			SetToken(newToken, value, updateIndex: true);
		}

		protected void SetToken(JsonToken newToken, object? value, bool updateIndex)
		{
			_tokenType = newToken;
			_value = value;
			switch (newToken)
			{
			case JsonToken.StartObject:
				_currentState = State.ObjectStart;
				Push(JsonContainerType.Object);
				break;
			case JsonToken.StartArray:
				_currentState = State.ArrayStart;
				Push(JsonContainerType.Array);
				break;
			case JsonToken.StartConstructor:
				_currentState = State.ConstructorStart;
				Push(JsonContainerType.Constructor);
				break;
			case JsonToken.EndObject:
				ValidateEnd(JsonToken.EndObject);
				break;
			case JsonToken.EndArray:
				ValidateEnd(JsonToken.EndArray);
				break;
			case JsonToken.EndConstructor:
				ValidateEnd(JsonToken.EndConstructor);
				break;
			case JsonToken.PropertyName:
				_currentState = State.Property;
				_currentPosition.PropertyName = (string)value;
				break;
			case JsonToken.Raw:
			case JsonToken.Integer:
			case JsonToken.Float:
			case JsonToken.String:
			case JsonToken.Boolean:
			case JsonToken.Null:
			case JsonToken.Undefined:
			case JsonToken.Date:
			case JsonToken.Bytes:
				SetPostValueState(updateIndex);
				break;
			case JsonToken.Comment:
				break;
			}
		}

		internal void SetPostValueState(bool updateIndex)
		{
			if (Peek() != 0 || SupportMultipleContent)
			{
				_currentState = State.PostValue;
			}
			else
			{
				SetFinished();
			}
			if (updateIndex)
			{
				UpdateScopeWithFinishedValue();
			}
		}

		private void UpdateScopeWithFinishedValue()
		{
			if (_currentPosition.HasIndex)
			{
				_currentPosition.Position++;
			}
		}

		private void ValidateEnd(JsonToken endToken)
		{
			JsonContainerType jsonContainerType = Pop();
			if (GetTypeForCloseToken(endToken) != jsonContainerType)
			{
				throw JsonReaderException.Create(this, "JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, jsonContainerType));
			}
			if (Peek() != 0 || SupportMultipleContent)
			{
				_currentState = State.PostValue;
			}
			else
			{
				SetFinished();
			}
		}

		protected void SetStateBasedOnCurrent()
		{
			JsonContainerType jsonContainerType = Peek();
			switch (jsonContainerType)
			{
			case JsonContainerType.Object:
				_currentState = State.Object;
				break;
			case JsonContainerType.Array:
				_currentState = State.Array;
				break;
			case JsonContainerType.Constructor:
				_currentState = State.Constructor;
				break;
			case JsonContainerType.None:
				SetFinished();
				break;
			default:
				throw JsonReaderException.Create(this, "While setting the reader state back to current object an unexpected JsonType was encountered: {0}".FormatWith(CultureInfo.InvariantCulture, jsonContainerType));
			}
		}

		private void SetFinished()
		{
			_currentState = ((!SupportMultipleContent) ? State.Finished : State.Start);
		}

		private JsonContainerType GetTypeForCloseToken(JsonToken token)
		{
			return token switch
			{
				JsonToken.EndObject => JsonContainerType.Object, 
				JsonToken.EndArray => JsonContainerType.Array, 
				JsonToken.EndConstructor => JsonContainerType.Constructor, 
				_ => throw JsonReaderException.Create(this, "Not a valid close JsonToken: {0}".FormatWith(CultureInfo.InvariantCulture, token)), 
			};
		}

		void IDisposable.Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (_currentState != State.Closed && disposing)
			{
				Close();
			}
		}

		public virtual void Close()
		{
			_currentState = State.Closed;
			_tokenType = JsonToken.None;
			_value = null;
		}

		internal void ReadAndAssert()
		{
			if (!Read())
			{
				throw JsonSerializationException.Create(this, "Unexpected end when reading JSON.");
			}
		}

		internal void ReadForTypeAndAssert(JsonContract? contract, bool hasConverter)
		{
			if (!ReadForType(contract, hasConverter))
			{
				throw JsonSerializationException.Create(this, "Unexpected end when reading JSON.");
			}
		}

		internal bool ReadForType(JsonContract? contract, bool hasConverter)
		{
			if (hasConverter)
			{
				return Read();
			}
			switch (contract?.InternalReadType ?? ReadType.Read)
			{
			case ReadType.Read:
				return ReadAndMoveToContent();
			case ReadType.ReadAsInt32:
				ReadAsInt32();
				break;
			case ReadType.ReadAsInt64:
			{
				bool result = ReadAndMoveToContent();
				if (TokenType == JsonToken.Undefined)
				{
					throw JsonReaderException.Create(this, "An undefined token is not a valid {0}.".FormatWith(CultureInfo.InvariantCulture, contract?.UnderlyingType ?? typeof(long)));
				}
				return result;
			}
			case ReadType.ReadAsDecimal:
				ReadAsDecimal();
				break;
			case ReadType.ReadAsDouble:
				ReadAsDouble();
				break;
			case ReadType.ReadAsBytes:
				ReadAsBytes();
				break;
			case ReadType.ReadAsBoolean:
				ReadAsBoolean();
				break;
			case ReadType.ReadAsString:
				ReadAsString();
				break;
			case ReadType.ReadAsDateTime:
				ReadAsDateTime();
				break;
			case ReadType.ReadAsDateTimeOffset:
				ReadAsDateTimeOffset();
				break;
			default:
				throw new ArgumentOutOfRangeException();
			}
			return TokenType != JsonToken.None;
		}

		internal bool ReadAndMoveToContent()
		{
			return Read() && MoveToContent();
		}

		internal bool MoveToContent()
		{
			JsonToken tokenType = TokenType;
			while (tokenType == JsonToken.None || tokenType == JsonToken.Comment)
			{
				if (!Read())
				{
					return false;
				}
				tokenType = TokenType;
			}
			return true;
		}

		private JsonToken GetContentToken()
		{
			JsonToken tokenType;
			do
			{
				if (!Read())
				{
					SetToken(JsonToken.None);
					return JsonToken.None;
				}
				tokenType = TokenType;
			}
			while (tokenType == JsonToken.Comment);
			return tokenType;
		}
	}
	[Serializable]
	public class JsonReaderException : JsonException
	{
		public int LineNumber { get; }

		public int LinePosition { get; }

		public string? Path { get; }

		public JsonReaderException()
		{
		}

		public JsonReaderException(string message)
			: base(message)
		{
		}

		public JsonReaderException(string message, Exception innerException)
			: base(message, innerException)
		{
		}

		public JsonReaderException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}

		public JsonReaderException(string message, string path, int lineNumber, int linePosition, Exception? innerException)
			: base(message, innerException)
		{
			Path = path;
			LineNumber = lineNumber;
			LinePosition = linePosition;
		}

		internal static JsonReaderException Create(JsonReader reader, string message)
		{
			return Create(reader, message, null);
		}

		internal static JsonReaderException Create(JsonReader reader, string message, Exception? ex)
		{
			return Create(reader as IJsonLineInfo, reader.Path, message, ex);
		}

		internal static JsonReaderException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex)
		{
			message = JsonPosition.FormatMessage(lineInfo, path, message);
			int lineNumber;
			int linePosition;
			if (lineInfo != null && lineInfo.HasLineInfo())
			{
				lineNumber = lineInfo.LineNumber;
				linePosition = lineInfo.LinePosition;
			}
			else
			{
				lineNumber = 0;
				linePosition = 0;
			}
			return new JsonReaderException(message, path, lineNumber, linePosition, ex);
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
	public sealed class JsonRequiredAttribute : Attribute
	{
	}
	[Serializable]
	public class JsonSerializationException : JsonException
	{
		public int LineNumber { get; }

		public int LinePosition { get; }

		public string? Path { get; }

		public JsonSerializationException()
		{
		}

		public JsonSerializationException(string message)
			: base(message)
		{
		}

		public JsonSerializationException(string message, Exception innerException)
			: base(message, innerException)
		{
		}

		public JsonSerializationException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}

		public JsonSerializationException(string message, string path, int lineNumber, int linePosition, Exception? innerException)
			: base(message, innerException)
		{
			Path = path;
			LineNumber = lineNumber;
			LinePosition = linePosition;
		}

		internal static JsonSerializationException Create(JsonReader reader, string message)
		{
			return Create(reader, message, null);
		}

		internal static JsonSerializationException Create(JsonReader reader, string message, Exception? ex)
		{
			return Create(reader as IJsonLineInfo, reader.Path, message, ex);
		}

		internal static JsonSerializationException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex)
		{
			message = JsonPosition.FormatMessage(lineInfo, path, message);
			int lineNumber;
			int linePosition;
			if (lineInfo != null && lineInfo.HasLineInfo())
			{
				lineNumber = lineInfo.LineNumber;
				linePosition = lineInfo.LinePosition;
			}
			else
			{
				lineNumber = 0;
				linePosition = 0;
			}
			return new JsonSerializationException(message, path, lineNumber, linePosition, ex);
		}
	}
	public class JsonSerializer
	{
		internal TypeNameHandling _typeNameHandling;

		internal TypeNameAssemblyFormatHandling _typeNameAssemblyFormatHandling;

		internal PreserveReferencesHandling _preserveReferencesHandling;

		internal ReferenceLoopHandling _referenceLoopHandling;

		internal MissingMemberHandling _missingMemberHandling;

		internal ObjectCreationHandling _objectCreationHandling;

		internal NullValueHandling _nullValueHandling;

		internal DefaultValueHandling _defaultValueHandling;

		internal ConstructorHandling _constructorHandling;

		internal MetadataPropertyHandling _metadataPropertyHandling;

		internal JsonConverterCollection? _converters;

		internal IContractResolver _contractResolver;

		internal ITraceWriter? _traceWriter;

		internal IEqualityComparer? _equalityComparer;

		internal ISerializationBinder _serializationBinder;

		internal StreamingContext _context;

		private IReferenceResolver? _referenceResolver;

		private Formatting? _formatting;

		private DateFormatHandling? _dateFormatHandling;

		private DateTimeZoneHandling? _dateTimeZoneHandling;

		private DateParseHandling? _dateParseHandling;

		private FloatFormatHandling? _floatFormatHandling;

		private FloatParseHandling? _floatParseHandling;

		private StringEscapeHandling? _stringEscapeHandling;

		private CultureInfo _culture;

		private int? _maxDepth;

		private bool _maxDepthSet;

		private bool? _checkAdditionalContent;

		private string? _dateFormatString;

		private bool _dateFormatStringSet;

		public virtual IReferenceResolver? ReferenceResolver
		{
			get
			{
				return GetReferenceResolver();
			}
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException("value", "Reference resolver cannot be null.");
				}
				_referenceResolver = value;
			}
		}

		[Obsolete("Binder is obsolete. Use SerializationBinder instead.")]
		public virtual SerializationBinder Binder
		{
			get
			{
				if (_serializationBinder is SerializationBinder result)
				{
					return result;
				}
				if (_serializationBinder is SerializationBinderAdapter serializationBinderAdapter)
				{
					return serializationBinderAdapter.SerializationBinder;
				}
				throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set.");
			}
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException("value", "Serialization binder cannot be null.");
				}
				_serializationBinder = (value as ISerializationBinder) ?? new SerializationBinderAdapter(value);
			}
		}

		public virtual ISerializationBinder SerializationBinder
		{
			get
			{
				return _serializationBinder;
			}
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException("value", "Serialization binder cannot be null.");
				}
				_serializationBinder = value;
			}
		}

		public virtual ITraceWriter? TraceWriter
		{
			get
			{
				return _traceWriter;
			}
			set
			{
				_traceWriter = value;
			}
		}

		public virtual IEqualityComparer? EqualityComparer
		{
			get
			{
				return _equalityComparer;
			}
			set
			{
				_equalityComparer = value;
			}
		}

		public virtual TypeNameHandling TypeNameHandling
		{
			get
			{
				return _typeNameHandling;
			}
			set
			{
				if (value < TypeNameHandling.None || value > TypeNameHandling.Auto)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_typeNameHandling = value;
			}
		}

		[Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")]
		public virtual FormatterAssemblyStyle TypeNameAssemblyFormat
		{
			get
			{
				return (FormatterAssemblyStyle)_typeNameAssemblyFormatHandling;
			}
			set
			{
				if (value < FormatterAssemblyStyle.Simple || value > FormatterAssemblyStyle.Full)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_typeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value;
			}
		}

		public virtual TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling
		{
			get
			{
				return _typeNameAssemblyFormatHandling;
			}
			set
			{
				if (value < TypeNameAssemblyFormatHandling.Simple || value > TypeNameAssemblyFormatHandling.Full)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_typeNameAssemblyFormatHandling = value;
			}
		}

		public virtual PreserveReferencesHandling PreserveReferencesHandling
		{
			get
			{
				return _preserveReferencesHandling;
			}
			set
			{
				if (value < PreserveReferencesHandling.None || value > PreserveReferencesHandling.All)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_preserveReferencesHandling = value;
			}
		}

		public virtual ReferenceLoopHandling ReferenceLoopHandling
		{
			get
			{
				return _referenceLoopHandling;
			}
			set
			{
				if (value < ReferenceLoopHandling.Error || value > ReferenceLoopHandling.Serialize)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_referenceLoopHandling = value;
			}
		}

		public virtual MissingMemberHandling MissingMemberHandling
		{
			get
			{
				return _missingMemberHandling;
			}
			set
			{
				if (value < MissingMemberHandling.Ignore || value > MissingMemberHandling.Error)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_missingMemberHandling = value;
			}
		}

		public virtual NullValueHandling NullValueHandling
		{
			get
			{
				return _nullValueHandling;
			}
			set
			{
				if (value < NullValueHandling.Include || value > NullValueHandling.Ignore)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_nullValueHandling = value;
			}
		}

		public virtual DefaultValueHandling DefaultValueHandling
		{
			get
			{
				return _defaultValueHandling;
			}
			set
			{
				if (value < DefaultValueHandling.Include || value > DefaultValueHandling.IgnoreAndPopulate)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_defaultValueHandling = value;
			}
		}

		public virtual ObjectCreationHandling ObjectCreationHandling
		{
			get
			{
				return _objectCreationHandling;
			}
			set
			{
				if (value < ObjectCreationHandling.Auto || value > ObjectCreationHandling.Replace)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_objectCreationHandling = value;
			}
		}

		public virtual ConstructorHandling ConstructorHandling
		{
			get
			{
				return _constructorHandling;
			}
			set
			{
				if (value < ConstructorHandling.Default || value > ConstructorHandling.AllowNonPublicDefaultConstructor)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_constructorHandling = value;
			}
		}

		public virtual MetadataPropertyHandling MetadataPropertyHandling
		{
			get
			{
				return _metadataPropertyHandling;
			}
			set
			{
				if (value < MetadataPropertyHandling.Default || value > MetadataPropertyHandling.Ignore)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_metadataPropertyHandling = value;
			}
		}

		public virtual JsonConverterCollection Converters
		{
			get
			{
				if (_converters == null)
				{
					_converters = new JsonConverterCollection();
				}
				return _converters;
			}
		}

		public virtual IContractResolver ContractResolver
		{
			get
			{
				return _contractResolver;
			}
			set
			{
				_contractResolver = value ?? DefaultContractResolver.Instance;
			}
		}

		public virtual StreamingContext Context
		{
			get
			{
				return _context;
			}
			set
			{
				_context = value;
			}
		}

		public virtual Formatting Formatting
		{
			get
			{
				return _formatting.GetValueOrDefault();
			}
			set
			{
				_formatting = value;
			}
		}

		public virtual DateFormatHandling DateFormatHandling
		{
			get
			{
				return _dateFormatHandling.GetValueOrDefault();
			}
			set
			{
				_dateFormatHandling = value;
			}
		}

		public virtual DateTimeZoneHandling DateTimeZoneHandling
		{
			get
			{
				return _dateTimeZoneHandling ?? DateTimeZoneHandling.RoundtripKind;
			}
			set
			{
				_dateTimeZoneHandling = value;
			}
		}

		public virtual DateParseHandling DateParseHandling
		{
			get
			{
				return _dateParseHandling ?? DateParseHandling.DateTime;
			}
			set
			{
				_dateParseHandling = value;
			}
		}

		public virtual FloatParseHandling FloatParseHandling
		{
			get
			{
				return _floatParseHandling.GetValueOrDefault();
			}
			set
			{
				_floatParseHandling = value;
			}
		}

		public virtual FloatFormatHandling FloatFormatHandling
		{
			get
			{
				return _floatFormatHandling.GetValueOrDefault();
			}
			set
			{
				_floatFormatHandling = value;
			}
		}

		public virtual StringEscapeHandling StringEscapeHandling
		{
			get
			{
				return _stringEscapeHandling.GetValueOrDefault();
			}
			set
			{
				_stringEscapeHandling = value;
			}
		}

		public virtual string DateFormatString
		{
			get
			{
				return _dateFormatString ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
			}
			set
			{
				_dateFormatString = value;
				_dateFormatStringSet = true;
			}
		}

		public virtual CultureInfo Culture
		{
			get
			{
				return _culture ?? JsonSerializerSettings.DefaultCulture;
			}
			set
			{
				_culture = value;
			}
		}

		public virtual int? MaxDepth
		{
			get
			{
				return _maxDepth;
			}
			set
			{
				if (value <= 0)
				{
					throw new ArgumentException("Value must be positive.", "value");
				}
				_maxDepth = value;
				_maxDepthSet = true;
			}
		}

		public virtual bool CheckAdditionalContent
		{
			get
			{
				return _checkAdditionalContent.GetValueOrDefault();
			}
			set
			{
				_checkAdditionalContent = value;
			}
		}

		public virtual event EventHandler<Newtonsoft.Json.Serialization.ErrorEventArgs>? Error;

		internal bool IsCheckAdditionalContentSet()
		{
			return _checkAdditionalContent.HasValue;
		}

		public JsonSerializer()
		{
			_referenceLoopHandling = ReferenceLoopHandling.Error;
			_missingMemberHandling = MissingMemberHandling.Ignore;
			_nullValueHandling = NullValueHandling.Include;
			_defaultValueHandling = DefaultValueHandling.Include;
			_objectCreationHandling = ObjectCreationHandling.Auto;
			_preserveReferencesHandling = PreserveReferencesHandling.None;
			_constructorHandling = ConstructorHandling.Default;
			_typeNameHandling = TypeNameHandling.None;
			_metadataPropertyHandling = MetadataPropertyHandling.Default;
			_context = JsonSerializerSettings.DefaultContext;
			_serializationBinder = DefaultSerializationBinder.Instance;
			_culture = JsonSerializerSettings.DefaultCulture;
			_contractResolver = DefaultContractResolver.Instance;
		}

		public static JsonSerializer Create()
		{
			return new JsonSerializer();
		}

		public static JsonSerializer Create(JsonSerializerSettings? settings)
		{
			JsonSerializer jsonSerializer = Create();
			if (settings != null)
			{
				ApplySerializerSettings(jsonSerializer, settings);
			}
			return jsonSerializer;
		}

		public static JsonSerializer CreateDefault()
		{
			JsonSerializerSettings settings = JsonConvert.DefaultSettings?.Invoke();
			return Create(settings);
		}

		public static JsonSerializer CreateDefault(JsonSerializerSettings? settings)
		{
			JsonSerializer jsonSerializer = CreateDefault();
			if (settings != null)
			{
				ApplySerializerSettings(jsonSerializer, settings);
			}
			return jsonSerializer;
		}

		private static void ApplySerializerSettings(JsonSerializer serializer, JsonSerializerSettings settings)
		{
			if (!CollectionUtils.IsNullOrEmpty(settings.Converters))
			{
				for (int i = 0; i < settings.Converters.Count; i++)
				{
					serializer.Converters.Insert(i, settings.Converters[i]);
				}
			}
			if (settings._typeNameHandling.HasValue)
			{
				serializer.TypeNameHandling = settings.TypeNameHandling;
			}
			if (settings._metadataPropertyHandling.HasValue)
			{
				serializer.MetadataPropertyHandling = settings.MetadataPropertyHandling;
			}
			if (settings._typeNameAssemblyFormatHandling.HasValue)
			{
				serializer.TypeNameAssemblyFormatHandling = settings.TypeNameAssemblyFormatHandling;
			}
			if (settings._preserveReferencesHandling.HasValue)
			{
				serializer.PreserveReferencesHandling = settings.PreserveReferencesHandling;
			}
			if (settings._referenceLoopHandling.HasValue)
			{
				serializer.ReferenceLoopHandling = settings.ReferenceLoopHandling;
			}
			if (settings._missingMemberHandling.HasValue)
			{
				serializer.MissingMemberHandling = settings.MissingMemberHandling;
			}
			if (settings._objectCreationHandling.HasValue)
			{
				serializer.ObjectCreationHandling = settings.ObjectCreationHandling;
			}
			if (settings._nullValueHandling.HasValue)
			{
				serializer.NullValueHandling = settings.NullValueHandling;
			}
			if (settings._defaultValueHandling.HasValue)
			{
				serializer.DefaultValueHandling = settings.DefaultValueHandling;
			}
			if (settings._constructorHandling.HasValue)
			{
				serializer.ConstructorHandling = settings.ConstructorHandling;
			}
			if (settings._context.HasValue)
			{
				serializer.Context = settings.Context;
			}
			if (settings._checkAdditionalContent.HasValue)
			{
				serializer._checkAdditionalContent = settings._checkAdditionalContent;
			}
			if (settings.Error != null)
			{
				serializer.Error += settings.Error;
			}
			if (settings.ContractResolver != null)
			{
				serializer.ContractResolver = settings.ContractResolver;
			}
			if (settings.ReferenceResolverProvider != null)
			{
				serializer.ReferenceResolver = settings.ReferenceResolverProvider();
			}
			if (settings.TraceWriter != null)
			{
				serializer.TraceWriter = settings.TraceWriter;
			}
			if (settings.EqualityComparer != null)
			{
				serializer.EqualityComparer = settings.EqualityComparer;
			}
			if (settings.SerializationBinder != null)
			{
				serializer.SerializationBinder = settings.SerializationBinder;
			}
			if (settings._formatting.HasValue)
			{
				serializer._formatting = settings._formatting;
			}
			if (settings._dateFormatHandling.HasValue)
			{
				serializer._dateFormatHandling = settings._dateFormatHandling;
			}
			if (settings._dateTimeZoneHandling.HasValue)
			{
				serializer._dateTimeZoneHandling = settings._dateTimeZoneHandling;
			}
			if (settings._dateParseHandling.HasValue)
			{
				serializer._dateParseHandling = settings._dateParseHandling;
			}
			if (settings._dateFormatStringSet)
			{
				serializer._dateFormatString = settings._dateFormatString;
				serializer._dateFormatStringSet = settings._dateFormatStringSet;
			}
			if (settings._floatFormatHandling.HasValue)
			{
				serializer._floatFormatHandling = settings._floatFormatHandling;
			}
			if (settings._floatParseHandling.HasValue)
			{
				serializer._floatParseHandling = settings._floatParseHandling;
			}
			if (settings._stringEscapeHandling.HasValue)
			{
				serializer._stringEscapeHandling = settings._stringEscapeHandling;
			}
			if (settings._culture != null)
			{
				serializer._culture = settings._culture;
			}
			if (settings._maxDepthSet)
			{
				serializer._maxDepth = settings._maxDepth;
				serializer._maxDepthSet = settings._maxDepthSet;
			}
		}

		[DebuggerStepThrough]
		public void Populate(TextReader reader, object target)
		{
			Populate(new JsonTextReader(reader), target);
		}

		[DebuggerStepThrough]
		public void Populate(JsonReader reader, object target)
		{
			PopulateInternal(reader, target);
		}

		internal virtual void PopulateInternal(JsonReader reader, object target)
		{
			ValidationUtils.ArgumentNotNull(reader, "reader");
			ValidationUtils.ArgumentNotNull(target, "target");
			SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString);
			TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null);
			JsonSerializerInternalReader jsonSerializerInternalReader = new JsonSerializerInternalReader(this);
			jsonSerializerInternalReader.Populate(traceJsonReader ?? reader, target);
			if (traceJsonReader != null)
			{
				TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null);
			}
			ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString);
		}

		[DebuggerStepThrough]
		public object? Deserialize(JsonReader reader)
		{
			return Deserialize(reader, null);
		}

		[DebuggerStepThrough]
		public object? Deserialize(TextReader reader, Type objectType)
		{
			return Deserialize(new JsonTextReader(reader), objectType);
		}

		[DebuggerStepThrough]
		public T? Deserialize<T>(JsonReader reader)
		{
			return (T)Deserialize(reader, typeof(T));
		}

		[DebuggerStepThrough]
		public object? Deserialize(JsonReader reader, Type? objectType)
		{
			return DeserializeInternal(reader, objectType);
		}

		internal virtual object? DeserializeInternal(JsonReader reader, Type? objectType)
		{
			ValidationUtils.ArgumentNotNull(reader, "reader");
			SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString);
			TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null);
			JsonSerializerInternalReader jsonSerializerInternalReader = new JsonSerializerInternalReader(this);
			object result = jsonSerializerInternalReader.Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent);
			if (traceJsonReader != null)
			{
				TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null);
			}
			ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString);
			return result;
		}

		internal void SetupReader(JsonReader reader, out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string? previousDateFormatString)
		{
			if (_culture != null && !_culture.Equals(reader.Culture))
			{
				previousCulture = reader.Culture;
				reader.Culture = _culture;
			}
			else
			{
				previousCulture = null;
			}
			if (_dateTimeZoneHandling.HasValue && reader.DateTimeZoneHandling != _dateTimeZoneHandling)
			{
				previousDateTimeZoneHandling = reader.DateTimeZoneHandling;
				reader.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault();
			}
			else
			{
				previousDateTimeZoneHandling = null;
			}
			if (_dateParseHandling.HasValue && reader.DateParseHandling != _dateParseHandling)
			{
				previousDateParseHandling = reader.DateParseHandling;
				reader.DateParseHandling = _dateParseHandling.GetValueOrDefault();
			}
			else
			{
				previousDateParseHandling = null;
			}
			if (_floatParseHandling.HasValue && reader.FloatParseHandling != _floatParseHandling)
			{
				previousFloatParseHandling = reader.FloatParseHandling;
				reader.FloatParseHandling = _floatParseHandling.GetValueOrDefault();
			}
			else
			{
				previousFloatParseHandling = null;
			}
			if (_maxDepthSet && reader.MaxDepth != _maxDepth)
			{
				previousMaxDepth = reader.MaxDepth;
				reader.MaxDepth = _maxDepth;
			}
			else
			{
				previousMaxDepth = null;
			}
			if (_dateFormatStringSet && reader.DateFormatString != _dateFormatString)
			{
				previousDateFormatString = reader.DateFormatString;
				reader.DateFormatString = _dateFormatString;
			}
			else
			{
				previousDateFormatString = null;
			}
			if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable == null && _contractResolver is DefaultContractResolver defaultContractResolver)
			{
				jsonTextReader.PropertyNameTable = defaultContractResolver.GetNameTable();
			}
		}

		private void ResetReader(JsonReader reader, CultureInfo? previousCulture, DateTimeZoneHandling? previousDateTimeZoneHandling, DateParseHandling? previousDateParseHandling, FloatParseHandling? previousFloatParseHandling, int? previousMaxDepth, string? previousDateFormatString)
		{
			if (previousCulture != null)
			{
				reader.Culture = previousCulture;
			}
			if (previousDateTimeZoneHandling.HasValue)
			{
				reader.DateTimeZoneHandling = previousDateTimeZoneHandling.GetValueOrDefault();
			}
			if (previousDateParseHandling.HasValue)
			{
				reader.DateParseHandling = previousDateParseHandling.GetValueOrDefault();
			}
			if (previousFloatParseHandling.HasValue)
			{
				reader.FloatParseHandling = previousFloatParseHandling.GetValueOrDefault();
			}
			if (_maxDepthSet)
			{
				reader.MaxDepth = previousMaxDepth;
			}
			if (_dateFormatStringSet)
			{
				reader.DateFormatString = previousDateFormatString;
			}
			if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable != null && _contractResolver is DefaultContractResolver defaultContractResolver && jsonTextReader.PropertyNameTable == defaultContractResolver.GetNameTable())
			{
				jsonTextReader.PropertyNameTable = null;
			}
		}

		public void Serialize(TextWriter textWriter, object? value)
		{
			Serialize(new JsonTextWriter(textWriter), value);
		}

		public void Serialize(JsonWriter jsonWriter, object? value, Type? objectType)
		{
			SerializeInternal(jsonWriter, value, objectType);
		}

		public void Serialize(TextWriter textWriter, object? value, Type objectType)
		{
			Serialize(new JsonTextWriter(textWriter), value, objectType);
		}

		public void Serialize(JsonWriter jsonWriter, object? value)
		{
			SerializeInternal(jsonWriter, value, null);
		}

		private TraceJsonReader CreateTraceJsonReader(JsonReader reader)
		{
			TraceJsonReader traceJsonReader = new TraceJsonReader(reader);
			if (reader.TokenType != 0)
			{
				traceJsonReader.WriteCurrentToken();
			}
			return traceJsonReader;
		}

		internal virtual void SerializeInternal(JsonWriter jsonWriter, object? value, Type? objectType)
		{
			ValidationUtils.ArgumentNotNull(jsonWriter, "jsonWriter");
			Formatting? formatting = null;
			if (_formatting.HasValue && jsonWriter.Formatting != _formatting)
			{
				formatting = jsonWriter.Formatting;
				jsonWriter.Formatting = _formatting.GetValueOrDefault();
			}
			DateFormatHandling? dateFormatHandling = null;
			if (_dateFormatHandling.HasValue && jsonWriter.DateFormatHandling != _dateFormatHandling)
			{
				dateFormatHandling = jsonWriter.DateFormatHandling;
				jsonWriter.DateFormatHandling = _dateFormatHandling.GetValueOrDefault();
			}
			DateTimeZoneHandling? dateTimeZoneHandling = null;
			if (_dateTimeZoneHandling.HasValue && jsonWriter.DateTimeZoneHandling != _dateTimeZoneHandling)
			{
				dateTimeZoneHandling = jsonWriter.DateTimeZoneHandling;
				jsonWriter.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault();
			}
			FloatFormatHandling? floatFormatHandling = null;
			if (_floatFormatHandling.HasValue && jsonWriter.FloatFormatHandling != _floatFormatHandling)
			{
				floatFormatHandling = jsonWriter.FloatFormatHandling;
				jsonWriter.FloatFormatHandling = _floatFormatHandling.GetValueOrDefault();
			}
			StringEscapeHandling? stringEscapeHandling = null;
			if (_stringEscapeHandling.HasValue && jsonWriter.StringEscapeHandling != _stringEscapeHandling)
			{
				stringEscapeHandling = jsonWriter.StringEscapeHandling;
				jsonWriter.StringEscapeHandling = _stringEscapeHandling.GetValueOrDefault();
			}
			CultureInfo cultureInfo = null;
			if (_culture != null && !_culture.Equals(jsonWriter.Culture))
			{
				cultureInfo = jsonWriter.Culture;
				jsonWriter.Culture = _culture;
			}
			string dateFormatString = null;
			if (_dateFormatStringSet && jsonWriter.DateFormatString != _dateFormatString)
			{
				dateFormatString = jsonWriter.DateFormatString;
				jsonWriter.DateFormatString = _dateFormatString;
			}
			TraceJsonWriter traceJsonWriter = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? new TraceJsonWriter(jsonWriter) : null);
			JsonSerializerInternalWriter jsonSerializerInternalWriter = new JsonSerializerInternalWriter(this);
			jsonSerializerInternalWriter.Serialize(traceJsonWriter ?? jsonWriter, value, objectType);
			if (traceJsonWriter != null)
			{
				TraceWriter.Trace(TraceLevel.Verbose, traceJsonWriter.GetSerializedJsonMessage(), null);
			}
			if (formatting.HasValue)
			{
				jsonWriter.Formatting = formatting.GetValueOrDefault();
			}
			if (dateFormatHandling.HasValue)
			{
				jsonWriter.DateFormatHandling = dateFormatHandling.GetValueOrDefault();
			}
			if (dateTimeZoneHandling.HasValue)
			{
				jsonWriter.DateTimeZoneHandling = dateTimeZoneHandling.GetValueOrDefault();
			}
			if (floatFormatHandling.HasValue)
			{
				jsonWriter.FloatFormatHandling = floatFormatHandling.GetValueOrDefault();
			}
			if (stringEscapeHandling.HasValue)
			{
				jsonWriter.StringEscapeHandling = stringEscapeHandling.GetValueOrDefault();
			}
			if (_dateFormatStringSet)
			{
				jsonWriter.DateFormatString = dateFormatString;
			}
			if (cultureInfo != null)
			{
				jsonWriter.Culture = cultureInfo;
			}
		}

		internal IReferenceResolver GetReferenceResolver()
		{
			if (_referenceResolver == null)
			{
				_referenceResolver = new DefaultReferenceResolver();
			}
			return _referenceResolver;
		}

		internal JsonConverter? GetMatchingConverter(Type type)
		{
			return GetMatchingConverter(_converters, type);
		}

		internal static JsonConverter? GetMatchingConverter(IList<JsonConverter>? converters, Type objectType)
		{
			ValidationUtils.ArgumentNotNull(objectType, "objectType");
			if (converters != null)
			{
				for (int i = 0; i < converters.Count; i++)
				{
					JsonConverter jsonConverter = converters[i];
					if (jsonConverter.CanConvert(objectType))
					{
						return jsonConverter;
					}
				}
			}
			return null;
		}

		internal void OnError(Newtonsoft.Json.Serialization.ErrorEventArgs e)
		{
			this.Error?.Invoke(this, e);
		}
	}
	public class JsonSerializerSettings
	{
		internal const ReferenceLoopHandling DefaultReferenceLoopHandling = ReferenceLoopHandling.Error;

		internal const MissingMemberHandling DefaultMissingMemberHandling = MissingMemberHandling.Ignore;

		internal const NullValueHandling DefaultNullValueHandling = NullValueHandling.Include;

		internal const DefaultValueHandling DefaultDefaultValueHandling = DefaultValueHandling.Include;

		internal const ObjectCreationHandling DefaultObjectCreationHandling = ObjectCreationHandling.Auto;

		internal const PreserveReferencesHandling DefaultPreserveReferencesHandling = PreserveReferencesHandling.None;

		internal const ConstructorHandling DefaultConstructorHandling = ConstructorHandling.Default;

		internal const TypeNameHandling DefaultTypeNameHandling = TypeNameHandling.None;

		internal const MetadataPropertyHandling DefaultMetadataPropertyHandling = MetadataPropertyHandling.Default;

		internal static readonly StreamingContext DefaultContext;

		internal const Formatting DefaultFormatting = Formatting.None;

		internal const DateFormatHandling DefaultDateFormatHandling = DateFormatHandling.IsoDateFormat;

		internal const DateTimeZoneHandling DefaultDateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;

		internal const DateParseHandling DefaultDateParseHandling = DateParseHandling.DateTime;

		internal const FloatParseHandling DefaultFloatParseHandling = FloatParseHandling.Double;

		internal const FloatFormatHandling DefaultFloatFormatHandling = FloatFormatHandling.String;

		internal const StringEscapeHandling DefaultStringEscapeHandling = StringEscapeHandling.Default;

		internal const TypeNameAssemblyFormatHandling DefaultTypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple;

		internal static readonly CultureInfo DefaultCulture;

		internal const bool DefaultCheckAdditionalContent = false;

		internal const string DefaultDateFormatString = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";

		internal const int DefaultMaxDepth = 64;

		internal Formatting? _formatting;

		internal DateFormatHandling? _dateFormatHandling;

		internal DateTimeZoneHandling? _dateTimeZoneHandling;

		internal DateParseHandling? _dateParseHandling;

		internal FloatFormatHandling? _floatFormatHandling;

		internal FloatParseHandling? _floatParseHandling;

		internal StringEscapeHandling? _stringEscapeHandling;

		internal CultureInfo? _culture;

		internal bool? _checkAdditionalContent;

		internal int? _maxDepth;

		internal bool _maxDepthSet;

		internal string? _dateFormatString;

		internal bool _dateFormatStringSet;

		internal TypeNameAssemblyFormatHandling? _typeNameAssemblyFormatHandling;

		internal DefaultValueHandling? _defaultValueHandling;

		internal PreserveReferencesHandling? _preserveReferencesHandling;

		internal NullValueHandling? _nullValueHandling;

		internal ObjectCreationHandling? _objectCreationHandling;

		internal MissingMemberHandling? _missingMemberHandling;

		internal ReferenceLoopHandling? _referenceLoopHandling;

		internal StreamingContext? _context;

		internal ConstructorHandling? _constructorHandling;

		internal TypeNameHandling? _typeNameHandling;

		internal MetadataPropertyHandling? _metadataPropertyHandling;

		public ReferenceLoopHandling ReferenceLoopHandling
		{
			get
			{
				return _referenceLoopHandling.GetValueOrDefault();
			}
			set
			{
				_referenceLoopHandling = value;
			}
		}

		public MissingMemberHandling MissingMemberHandling
		{
			get
			{
				return _missingMemberHandling.GetValueOrDefault();
			}
			set
			{
				_missingMemberHandling = value;
			}
		}

		public ObjectCreationHandling ObjectCreationHandling
		{
			get
			{
				return _objectCreationHandling.GetValueOrDefault();
			}
			set
			{
				_objectCreationHandling = value;
			}
		}

		public NullValueHandling NullValueHandling
		{
			get
			{
				return _nullValueHandling.GetValueOrDefault();
			}
			set
			{
				_nullValueHandling = value;
			}
		}

		public DefaultValueHandling DefaultValueHandling
		{
			get
			{
				return _defaultValueHandling.GetValueOrDefault();
			}
			set
			{
				_defaultValueHandling = value;
			}
		}

		public IList<JsonConverter> Converters { get; set; }

		public PreserveReferencesHandling PreserveReferencesHandling
		{
			get
			{
				return _preserveReferencesHandling.GetValueOrDefault();
			}
			set
			{
				_preserveReferencesHandling = value;
			}
		}

		public TypeNameHandling TypeNameHandling
		{
			get
			{
				return _typeNameHandling.GetValueOrDefault();
			}
			set
			{
				_typeNameHandling = value;
			}
		}

		public MetadataPropertyHandling MetadataPropertyHandling
		{
			get
			{
				return _metadataPropertyHandling.GetValueOrDefault();
			}
			set
			{
				_metadataPropertyHandling = value;
			}
		}

		[Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")]
		public FormatterAssemblyStyle TypeNameAssemblyFormat
		{
			get
			{
				return (FormatterAssemblyStyle)TypeNameAssemblyFormatHandling;
			}
			set
			{
				TypeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value;
			}
		}

		public TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling
		{
			get
			{
				return _typeNameAssemblyFormatHandling.GetValueOrDefault();
			}
			set
			{
				_typeNameAssemblyFormatHandling = value;
			}
		}

		public ConstructorHandling ConstructorHandling
		{
			get
			{
				return _constructorHandling.GetValueOrDefault();
			}
			set
			{
				_constructorHandling = value;
			}
		}

		public IContractResolver? ContractResolver { get; set; }

		public IEqualityComparer? EqualityComparer { get; set; }

		[Obsolete("ReferenceResolver property is obsolete. Use the ReferenceResolverProvider property to set the IReferenceResolver: settings.ReferenceResolverProvider = () => resolver")]
		public IReferenceResolver? ReferenceResolver
		{
			get
			{
				return ReferenceResolverProvider?.Invoke();
			}
			set
			{
				IReferenceResolver value2 = value;
				ReferenceResolverProvider = ((value2 != null) ? ((Func<IReferenceResolver>)(() => value2)) : null);
			}
		}

		public Func<IReferenceResolver?>? ReferenceResolverProvider { get; set; }

		public ITraceWriter? TraceWriter { get; set; }

		[Obsolete("Binder is obsolete. Use SerializationBinder instead.")]
		public SerializationBinder? Binder
		{
			get
			{
				if (SerializationBinder == null)
				{
					return null;
				}
				if (SerializationBinder is SerializationBinderAdapter serializationBinderAdapter)
				{
					return serializationBinderAdapter.SerializationBinder;
				}
				throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set.");
			}
			set
			{
				SerializationBinder = ((value == null) ? null : new SerializationBinderAdapter(value));
			}
		}

		public ISerializationBinder? SerializationBinder { get; set; }

		public EventHandler<Newtonsoft.Json.Serialization.ErrorEventArgs>? Error { get; set; }

		public StreamingContext Context
		{
			get
			{
				return _context ?? DefaultContext;
			}
			set
			{
				_context = value;
			}
		}

		public string DateFormatString
		{
			get
			{
				return _dateFormatString ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
			}
			set
			{
				_dateFormatString = value;
				_dateFormatStringSet = true;
			}
		}

		public int? MaxDepth
		{
			get
			{
				return _maxDepthSet ? _maxDepth : new int?(64);
			}
			set
			{
				if (value <= 0)
				{
					throw new ArgumentException("Value must be positive.", "value");
				}
				_maxDepth = value;
				_maxDepthSet = true;
			}
		}

		public Formatting Formatting
		{
			get
			{
				return _formatting.GetValueOrDefault();
			}
			set
			{
				_formatting = value;
			}
		}

		public DateFormatHandling DateFormatHandling
		{
			get
			{
				return _dateFormatHandling.GetValueOrDefault();
			}
			set
			{
				_dateFormatHandling = value;
			}
		}

		public DateTimeZoneHandling DateTimeZoneHandling
		{
			get
			{
				return _dateTimeZoneHandling ?? DateTimeZoneHandling.RoundtripKind;
			}
			set
			{
				_dateTimeZoneHandling = value;
			}
		}

		public DateParseHandling DateParseHandling
		{
			get
			{
				return _dateParseHandling ?? DateParseHandling.DateT