Decompiled source of Dimensional Storage v1.0.3

Com.JiceeDev.DimensionalStorage.dll

Decompiled 5 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using Com.JiceeDev.DimensionalStorage.Models;
using Com.JiceeDev.DimensionalStorage.Patches;
using Com.JiceeDev.DimensionalStorage.Tech;
using CommonAPI;
using CommonAPI.Systems;
using CommonAPI.Systems.ModLocalization;
using FullSerializer;
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;
using crecheng.DSPModSave;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("Com.JiceeDev.DimensionalStorage")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: AssemblyInformationalVersion("1.0.3+430d01760e2761da62a5ca4329b74d68ae5a8973")]
[assembly: AssemblyProduct("Com.JiceeDev.DimensionalStorage")]
[assembly: AssemblyTitle("Com.JiceeDev.DimensionalStorage")]
[assembly: AssemblyVersion("1.0.3.0")]
namespace Com.JiceeDev.DimensionalStorage
{
	[BepInPlugin("com.jiceedev.DimensionalStorage", "Dimensional Storage", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[CommonAPISubmoduleDependency(new string[] { "ProtoRegistry" })]
	public class DimensionalStorageMod : BaseUnityPlugin, IModCanSave
	{
		public static DimensionalStorageSystem DimensionalStorageSystem = new DimensionalStorageSystem();

		public static ITechManager TechManager = new TechManager();

		private void Awake()
		{
			Init();
			ApplyPatches();
		}

		private void ApplyPatches()
		{
			Harmony.CreateAndPatchAll(typeof(UIStorageWindowPatch), (string)null);
			Harmony.CreateAndPatchAll(typeof(StorageComponentGetItemCountPatch), (string)null);
			Harmony.CreateAndPatchAll(typeof(StorageComponentPatchAll), (string)null);
			Harmony.CreateAndPatchAll(typeof(BuildToolPatch), (string)null);
			Harmony.CreateAndPatchAll(typeof(StorageComponentTakeTailItemsPatch), (string)null);
			Harmony.CreateAndPatchAll(typeof(MechaForgePatch), (string)null);
			Harmony.CreateAndPatchAll(typeof(UIReplicatorWindowPatch), (string)null);
			Harmony.CreateAndPatchAll(typeof(StorageComponentReplicatorCheckItemsPatch), (string)null);
			Harmony.CreateAndPatchAll(typeof(GameHistoryDataPatch), (string)null);
		}

		public void Export(BinaryWriter writer)
		{
			DimensionalStorageSystem.Export(writer);
		}

		public void Import(BinaryReader reader)
		{
			TechManager?.Dispose();
			Init();
			DimensionalStorageSystem.Import(reader);
		}

		private void Init()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			Debug.Log((object)"Dimensional Storage Mod Init");
			DimensionalStorageSystem = new DimensionalStorageSystem();
			TechManager = new TechManager();
			GlobalConfiguration.Init(new ConfigFile(Path.Combine(Paths.ConfigPath, "global_configuration.cfg"), true));
			TechManager.RegisterTechs();
		}

		public void IntoOtherSave()
		{
		}
	}
	public interface ISaveComponent
	{
		void Export(BinaryWriter writer);

		void Import(BinaryReader reader);
	}
	public class DimensionalStorageSystem : ISaveComponent
	{
		public HashSet<StorageComponent> StorageContainers { get; private set; } = new HashSet<StorageComponent>();


		private bool CanAddMoreStorageContainers()
		{
			return StorageContainers.Count < DimensionalStorageMod.TechManager.GetCachedDimensionalBonus().NumberOfDimensionalStorage;
		}

		public int GetRemainingLinks()
		{
			return DimensionalStorageMod.TechManager.GetCachedDimensionalBonus().NumberOfDimensionalStorage - StorageContainers.Count;
		}

		public bool AddStorageContainer(StorageComponent storage)
		{
			if (CanAddMoreStorageContainers())
			{
				return StorageContainers.Add(storage);
			}
			return false;
		}

		public void RemoveStorageContainer(StorageComponent storage)
		{
			StorageContainers.Remove(storage);
		}

		public int GetItemCount(int itemId)
		{
			return StorageContainers.Select((StorageComponent c) => c.GetItemCount(itemId)).Sum();
		}

		public void TransferTo(StorageComponent other, int itemId, int count)
		{
			int val = StorageContainers.Select((StorageComponent c) => c.GetItemCount(itemId)).Sum();
			count = Math.Min(count, val);
			int num = default(int);
			int num2 = default(int);
			foreach (StorageComponent storageContainer in StorageContainers)
			{
				int itemCount = storageContainer.GetItemCount(itemId);
				if (itemCount > 0)
				{
					if (itemCount >= count)
					{
						storageContainer.TakeItem(itemId, count, ref num);
						other.AddItem(itemId, count, 0, 1, 0, ref num);
						break;
					}
					storageContainer.TakeItem(itemId, itemCount, ref num2);
					other.AddItem(itemId, itemCount, 0, 1, 0, ref num);
					count -= itemCount;
				}
			}
		}

		public void TransferToPlayer(int itemId, int count, int itemInc)
		{
			TransferToPlayer(GameMain.data.mainPlayer, itemId, count, itemInc);
		}

		public void TransferToPlayer(Player player, int itemId, int count, int itemInc)
		{
			int val = StorageContainers.Select((StorageComponent c) => c.GetItemCount(itemId)).Sum();
			count = Math.Min(count, val);
			itemInc = Math.Min(itemInc, count);
			player.TryAddItemToPackage(itemId, count, itemInc, true, 0, false);
			int num = default(int);
			int num2 = default(int);
			foreach (StorageComponent storageContainer in StorageContainers)
			{
				int itemCount = storageContainer.GetItemCount(itemId);
				if (itemCount > 0)
				{
					if (itemCount >= count)
					{
						storageContainer.TakeItem(itemId, count, ref num);
						break;
					}
					storageContainer.TakeItem(itemId, itemCount, ref num2);
					count -= itemCount;
				}
			}
		}

		public void Export(BinaryWriter writer)
		{
			writer.Write(StorageContainers.Count);
			foreach (StorageComponent storageContainer in StorageContainers)
			{
				writer.Write(storageContainer.id);
			}
		}

		public void Import(BinaryReader reader)
		{
			StorageContainers.Clear();
			int num = reader.ReadInt32();
			for (int i = 0; i < num; i++)
			{
				int id = reader.ReadInt32();
				StorageComponent val = GameMain.data.factories.First((PlanetFactory c) => c.factoryStorage.storagePool[id] != null).factoryStorage.storagePool[id];
				if (val != null)
				{
					StorageContainers.Add(val);
				}
			}
		}
	}
	public static class GlobalConfiguration
	{
		public static class Tech
		{
			public const string SectionName = "Tech";

			public static readonly string[] DefaultTechsPaths = new string[1] { "default.json" };

			public static string TechsPath { get; set; } = "default.json";


			public static int BaseNumberOfDimensionalStorage { get; set; } = 1;


			public static bool BaseCanBuildWithDimensionalStorage { get; set; } = false;


			public static bool BaseCanReplicateWithDimensionalStorage { get; set; } = false;

		}

		public static void Init(ConfigFile config)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			Tech.TechsPath = config.Bind<string>("Tech", "Filename where the tech tree is stored", "default.json", new ConfigDescription("Change The tech tree used, by default it uses the techs.json file in the config folder.\nSome mods may require a different tech tree, so you can change it here.\nAlready included tech trees: " + string.Join(", ", Tech.DefaultTechsPaths), (AcceptableValueBase)null, Array.Empty<object>())).Value;
			Tech.BaseNumberOfDimensionalStorage = config.Bind<int>("Tech", "Base number of Dimensional Storage", 1, new ConfigDescription("The number of Dimensional Storage that the player starts with.", (AcceptableValueBase)null, Array.Empty<object>())).Value;
			Tech.BaseCanBuildWithDimensionalStorage = config.Bind<bool>("Tech", "Can build with Dimensional Storage", false, new ConfigDescription("If true, the player can build with Dimensional Storage right from the start.", (AcceptableValueBase)null, Array.Empty<object>())).Value;
			Tech.BaseCanReplicateWithDimensionalStorage = config.Bind<bool>("Tech", "Can replicate with Dimensional Storage", false, new ConfigDescription("If true, the player can replicate with Dimensional Storage right from the start.", (AcceptableValueBase)null, Array.Empty<object>())).Value;
		}
	}
	public static class Utils
	{
		private static readonly string CurrentFolderAssemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

		private static readonly string AssetsPath = Path.Combine(CurrentFolderAssemblyPath, "assets");

		public static Texture2D GetTexture(string name, int width = 32, int height = 32)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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_001f: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			Texture2D val = new Texture2D(2, 2)
			{
				filterMode = (FilterMode)0
			};
			ImageConversion.LoadImage(val, File.ReadAllBytes(GetImagePath(name)));
			((Object)val).name = name;
			return val;
		}

		public static Sprite GetSprite(string name)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			Texture2D texture = GetTexture(name);
			Sprite obj = Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f));
			((Object)obj).name = name;
			return obj;
		}

		public static string GetImagePath(string name)
		{
			return Path.Combine(AssetsPath, name);
		}
	}
	public static class StringSerializationAPI
	{
		private static readonly fsSerializer _serializer = new fsSerializer();

		public static string Serialize(Type type, object value)
		{
			//IL_0009: 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_0011: Unknown result type (might be due to invalid IL or missing references)
			fsData val = default(fsData);
			fsResult val2 = _serializer.TrySerialize(type, value, ref val);
			((fsResult)(ref val2)).AssertSuccessWithoutWarnings();
			return fsJsonPrinter.CompressedJson(val);
		}

		public static object Deserialize(Type type, string serializedState)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			fsData val = fsJsonParser.Parse(serializedState);
			object result = null;
			fsResult val2 = _serializer.TryDeserialize(val, type, ref result);
			((fsResult)(ref val2)).AssertSuccessWithoutWarnings();
			return result;
		}
	}
}
namespace Com.JiceeDev.DimensionalStorage.Tech
{
	[Serializable]
	public class DimensionalBonus
	{
		public int NumberOfDimensionalStorage;

		public bool CanBuildWithDimensionalStorage;

		public bool CanReplicateWithDimensionalStorage;
	}
	public interface ITechManager : IDisposable
	{
		void RegisterTechs();

		DimensionalBonus GetCurrentDimensionalBonus(int techID);

		DimensionalBonus GetAllDimensionalBonus();

		DimensionalBonus GetCachedDimensionalBonus();

		void ReloadCache();
	}
	[Serializable]
	public class TechItem
	{
		public int ID;

		public string IDLong = "";

		public string Name = "";

		public string Description = "";

		public string Conclusion = "";

		public string IconPath = "";

		public int[] RequiredTechs = Array.Empty<int>();

		public int[] Jellos = Array.Empty<int>();

		public int[] JellosRates = Array.Empty<int>();

		public int HashNeeded;

		public int[] UnlockRecipes = Array.Empty<int>();

		public Vector2 Position = new Vector2(0f, 0f);

		public DimensionalBonus Bonuses = new DimensionalBonus();
	}
	public class GameHistoryDataPatch
	{
		[HarmonyPatch(typeof(GameHistoryData), "NotifyTechUnlock")]
		[HarmonyPostfix]
		public static void NotifyTechUnlockPostfix()
		{
			DimensionalStorageMod.TechManager.ReloadCache();
		}
	}
	public class TechManager : ITechManager, IDisposable
	{
		private static bool _isLoaded = false;

		private static readonly Dictionary<int, TechItem> _techItems = new Dictionary<int, TechItem>();

		private bool _isTechListening;

		private DimensionalBonus _currentBonus;

		public void RegisterTechs()
		{
			if (!_isLoaded)
			{
				LoadConfig();
				LoadTechs();
			}
		}

		public DimensionalBonus GetCurrentDimensionalBonus(int techID)
		{
			if (!GameMain.history.techStates.TryGetValue(techID, out var _))
			{
				return new DimensionalBonus();
			}
			if (!_techItems.TryGetValue(techID, out var value2))
			{
				return new DimensionalBonus();
			}
			return value2.Bonuses;
		}

		public void ReloadCache()
		{
			_currentBonus = GetAllDimensionalBonus();
		}

		public DimensionalBonus GetAllDimensionalBonus()
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			DimensionalBonus dimensionalBonus = new DimensionalBonus();
			dimensionalBonus.NumberOfDimensionalStorage += GlobalConfiguration.Tech.BaseNumberOfDimensionalStorage;
			dimensionalBonus.CanBuildWithDimensionalStorage |= GlobalConfiguration.Tech.BaseCanBuildWithDimensionalStorage;
			dimensionalBonus.CanReplicateWithDimensionalStorage |= GlobalConfiguration.Tech.BaseCanReplicateWithDimensionalStorage;
			foreach (TechItem value2 in _techItems.Values)
			{
				if (GameMain.history.techStates.TryGetValue(value2.ID, out var value) && value.unlocked)
				{
					dimensionalBonus.NumberOfDimensionalStorage += value2.Bonuses.NumberOfDimensionalStorage;
					dimensionalBonus.CanBuildWithDimensionalStorage |= value2.Bonuses.CanBuildWithDimensionalStorage;
					dimensionalBonus.CanReplicateWithDimensionalStorage |= value2.Bonuses.CanReplicateWithDimensionalStorage;
				}
			}
			return dimensionalBonus;
		}

		public DimensionalBonus GetCachedDimensionalBonus()
		{
			return _currentBonus ?? (_currentBonus = GetAllDimensionalBonus());
		}

		private static void LoadConfig()
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			string serializedState = File.ReadAllText(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? string.Empty, "config", "tech", GlobalConfiguration.Tech.TechsPath));
			TechTree techTree = StringSerializationAPI.Deserialize(typeof(TechTree), serializedState) as TechTree;
			Debug.Log((object)$"Loading tech tree from {GlobalConfiguration.Tech.TechsPath}, found {techTree.TechItems.Count} techs");
			foreach (TechItem techItem in techTree.TechItems)
			{
				Debug.Log((object)$"Registering tech {techItem.ID}: {techItem.IDLong} at position {techItem.Position}");
				Debug.Log((object)("desc:" + techItem.Description));
				Debug.Log((object)("conclusion:" + techItem.Conclusion));
				_techItems.Add(techItem.ID, techItem);
			}
			_isLoaded = true;
		}

		private static void CalculateJellosRates()
		{
			foreach (TechItem value in _techItems.Values)
			{
				for (int i = 0; i < value.Jellos.Length; i++)
				{
					value.JellosRates[i] = value.HashNeeded * value.JellosRates[i] / 3600;
				}
			}
		}

		private static void LoadTechs()
		{
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			foreach (TechItem value in _techItems.Values)
			{
				LocalizationModule.RegisterTranslation(value.IDLong + "_name", value.Name);
				LocalizationModule.RegisterTranslation(value.IDLong + "_desc", value.Description);
				LocalizationModule.RegisterTranslation(value.IDLong + "_conc", value.Conclusion);
				ProtoRegistry.RegisterTech(value.ID, value.IDLong + "_name", value.IDLong + "_desc", value.IDLong + "_conc", value.IconPath, value.RequiredTechs, value.Jellos, value.JellosRates, (long)value.HashNeeded, value.UnlockRecipes, value.Position);
			}
		}

		public void Dispose()
		{
		}
	}
	[Serializable]
	public class TechTree
	{
		public List<TechItem> TechItems;
	}
}
namespace Com.JiceeDev.DimensionalStorage.Patches
{
	public class BuildToolPatch
	{
		private static FieldInfo tmpPackageField = typeof(BuildTool).GetField("tmpPackage", BindingFlags.Instance | BindingFlags.NonPublic);

		[HarmonyPatch(typeof(BuildTool), "_GameTick")]
		[HarmonyPrefix]
		public static void _GameTickPrefix(BuildTool __instance, long time)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			StorageComponent val = (StorageComponent)tmpPackageField.GetValue(__instance);
			if (__instance.active && val == null)
			{
				TempBuildStorageComponent value = new TempBuildStorageComponent(__instance.player.package.size);
				tmpPackageField.SetValue(__instance, value);
			}
		}
	}
	public static class MechaForgePatch
	{
		private static FieldInfo _test_storage = typeof(MechaForge).GetField("_test_storage", BindingFlags.Instance | BindingFlags.NonPublic);

		[HarmonyPatch(typeof(MechaForge), "TryAddTask")]
		[HarmonyPrefix]
		public static bool TryAddTaskPrefix(MechaForge __instance)
		{
			InitStorage(__instance);
			return true;
		}

		[HarmonyPatch(typeof(MechaForge), "TryTaskWithTestPackage")]
		[HarmonyPrefix]
		public static bool TryTaskWithTestPackagePrefix(MechaForge __instance)
		{
			InitStorage(__instance);
			return true;
		}

		private static void InitStorage(MechaForge __instance)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			StorageComponent val = (StorageComponent)_test_storage.GetValue(__instance);
			if (val == null)
			{
				val = (StorageComponent)(object)new MechaForgeStorageTryAddTaskStorageComponent(0);
				_test_storage.SetValue(__instance, val);
			}
		}
	}
	[HarmonyPatch]
	public static class StorageComponentGetItemCountPatch
	{
		private static MethodBase TargetMethod()
		{
			return typeof(StorageComponent).GetMethod("GetItemCount", new Type[2]
			{
				typeof(int),
				typeof(int).MakeByRefType()
			});
		}

		[HarmonyPostfix]
		public static void GetItemCountPostfix(ref int __result, StorageComponent __instance, int itemId, ref int inc)
		{
			if (!__instance.isPlayerInventory && !(__instance is MechaForgeStorageTryAddTaskStorageComponent))
			{
				return;
			}
			DimensionalBonus cachedDimensionalBonus = DimensionalStorageMod.TechManager.GetCachedDimensionalBonus();
			if ((__instance.isPlayerInventory && !cachedDimensionalBonus.CanBuildWithDimensionalStorage) || (__instance is MechaForgeStorageTryAddTaskStorageComponent && !cachedDimensionalBonus.CanReplicateWithDimensionalStorage))
			{
				return;
			}
			try
			{
				int num = default(int);
				foreach (StorageComponent storageContainer in DimensionalStorageMod.DimensionalStorageSystem.StorageContainers)
				{
					__result += storageContainer.GetItemCount(itemId, ref num);
					inc += num;
				}
			}
			catch (Exception ex)
			{
				Debug.Log((object)("DS - GetItemCountPrefix error: " + ex.ToString()));
			}
		}
	}
	public class StorageComponentPatchAll
	{
		[HarmonyPatch(typeof(StorageComponent), "GetItemCount", new Type[] { typeof(int) })]
		[HarmonyPostfix]
		public static void GetItemCountPostfix(ref int __result, StorageComponent __instance, int itemId)
		{
			if (!__instance.isPlayerInventory && !(__instance is MechaForgeStorageTryAddTaskStorageComponent))
			{
				return;
			}
			DimensionalBonus cachedDimensionalBonus = DimensionalStorageMod.TechManager.GetCachedDimensionalBonus();
			if ((__instance.isPlayerInventory && !cachedDimensionalBonus.CanBuildWithDimensionalStorage) || (__instance is MechaForgeStorageTryAddTaskStorageComponent && !cachedDimensionalBonus.CanReplicateWithDimensionalStorage))
			{
				return;
			}
			try
			{
				__result += DimensionalStorageMod.DimensionalStorageSystem.GetItemCount(itemId);
			}
			catch (Exception ex)
			{
				Debug.Log((object)("DS - GetItemCountPrefix error: " + ex.ToString()));
			}
		}
	}
	public static class StorageComponentReplicatorCheckItemsPatch
	{
		private static MethodBase TargetMethod()
		{
			return typeof(StorageComponent).GetMethod("TakeItem", new Type[3]
			{
				typeof(int),
				typeof(int),
				typeof(int).MakeByRefType()
			});
		}

		[HarmonyPostfix]
		public static void TakeItemPostfix(StorageComponent __instance, ref int __result, int itemId, int count, ref int inc)
		{
			if (__instance is MechaForgeStorageTryAddTaskStorageComponent && DimensionalStorageMod.TechManager.GetCachedDimensionalBonus().CanReplicateWithDimensionalStorage)
			{
				int itemCount = __instance.GetItemCount(itemId);
				itemCount += DimensionalStorageMod.DimensionalStorageSystem.GetItemCount(itemId);
				__result = itemCount - count;
			}
		}
	}
	[HarmonyPatch]
	public static class StorageComponentTakeTailItemsPatch
	{
		private static MethodBase TargetMethod()
		{
			return typeof(StorageComponent).GetMethod("TakeTailItems", new Type[4]
			{
				typeof(int).MakeByRefType(),
				typeof(int).MakeByRefType(),
				typeof(int).MakeByRefType(),
				typeof(bool)
			});
		}

		[HarmonyPrefix]
		public static void TakeTailItemsPrefix(StorageComponent __instance, ref int itemId, ref int count, ref int inc, bool useBan)
		{
			if (__instance is TempBuildStorageComponent && DimensionalStorageMod.TechManager.GetCachedDimensionalBonus().CanBuildWithDimensionalStorage)
			{
				int itemCount = __instance.GetItemCount(itemId);
				if (count > itemCount)
				{
					DimensionalStorageMod.DimensionalStorageSystem.TransferToPlayer(itemId, count - itemCount, inc);
				}
			}
		}
	}
	public static class UIReplicatorWindowPatch
	{
		private static FieldInfo selectedRecipeField = typeof(UIReplicatorWindow).GetField("selectedRecipe", BindingFlags.Instance | BindingFlags.NonPublic);

		[HarmonyPatch(typeof(UIReplicatorWindow), "OnOkButtonClick")]
		[HarmonyPrefix]
		public static bool OnOkButtonClickPrefix(UIReplicatorWindow __instance)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			RecipeProto val = (RecipeProto)selectedRecipeField.GetValue(__instance);
			if (val == null || GameMain.isFullscreenPaused)
			{
				return true;
			}
			if (!DimensionalStorageMod.TechManager.GetCachedDimensionalBonus().CanReplicateWithDimensionalStorage)
			{
				return true;
			}
			for (int i = 0; i < val.Items.Length; i++)
			{
				int itemId = val.Items[i];
				int num = val.ItemCounts[i];
				DimensionalStorageMod.DimensionalStorageSystem.TransferToPlayer(itemId, num, num);
			}
			return true;
		}
	}
	public class UIStorageWindowPatch
	{
		public static UIButton DimensionalStorageButton;

		public static UIStorageWindow StorageWindow;

		[HarmonyPatch(typeof(UIStorageWindow), "_OnCreate")]
		[HarmonyPostfix]
		public static void _OnCreatePostfix(ref UIStorageWindow __instance)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			StorageWindow = __instance;
			if (!((Object)(object)DimensionalStorageButton != (Object)null))
			{
				UIButton val = Object.Instantiate<UIButton>(__instance.filterButton0, ((Component)__instance.filterButton0).transform.parent);
				((Component)val).transform.localPosition = new Vector3(((Component)val).transform.localPosition.x + 154f, ((Component)val).transform.localPosition.y, 0f);
				Transform child = ((Component)val).transform.GetChild(0);
				child.localScale = new Vector3(1.4f, 1.4f, 1.4f);
				((Component)child).GetComponent<Image>().sprite = Utils.GetSprite("dimensional_storage.png");
				val.tips.tipTitle = "Dimensional Storage (Inactive)";
				val.onClick += ButtonOnClick;
				DimensionalStorageButton = val;
			}
		}

		private static void ButtonOnClick(int obj)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			StorageComponent storageComponent = GetStorageComponent();
			if (storageComponent != null)
			{
				if (DimensionalStorageMod.DimensionalStorageSystem.StorageContainers.Contains(storageComponent))
				{
					DimensionalStorageMod.DimensionalStorageSystem.RemoveStorageContainer(storageComponent);
				}
				else if (!DimensionalStorageMod.DimensionalStorageSystem.AddStorageContainer(storageComponent))
				{
					VFAudio.Create("ui-error", (Transform)null, Vector3.zero, true, 5, -1, -1L);
					UIRealtimeTip.Popup("You have reached the maximum number of linked containers", false, 0);
				}
				UpdateUI(DimensionalStorageMod.DimensionalStorageSystem.StorageContainers.Contains(storageComponent));
			}
		}

		[HarmonyPatch(typeof(UIStorageWindow), "OnStorageIdChange")]
		[HarmonyPostfix]
		public static void OnStorageIdChangePostfix(ref UIStorageWindow __instance)
		{
			StorageComponent storageComponent = GetStorageComponent();
			if (storageComponent == null)
			{
				UpdateUI(isLinked: false);
			}
			else
			{
				UpdateUI(DimensionalStorageMod.DimensionalStorageSystem.StorageContainers.Contains(storageComponent));
			}
		}

		private static StorageComponent GetStorageComponent()
		{
			try
			{
				return StorageWindow.factoryStorage.storagePool[StorageWindow.storageId];
			}
			catch
			{
				return null;
			}
		}

		private static void UpdateUI(bool isLinked)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			((Graphic)((Selectable)DimensionalStorageButton.button).image).color = (isLinked ? Color.green : Color.red);
			DimensionalStorageButton.tips.tipTitle = (isLinked ? "Dimensional Storage (Active)" : "Dimensional Storage (Inactive)");
			DimensionalStorageButton.tips.tipText = "When active, the container will be linked to the Dimensional Storage\nRemaining links: " + DimensionalStorageMod.DimensionalStorageSystem.GetRemainingLinks();
		}
	}
}
namespace Com.JiceeDev.DimensionalStorage.Models
{
	public class MechaForgeStorageTryAddTaskStorageComponent : StorageComponent
	{
		public MechaForgeStorageTryAddTaskStorageComponent(int _size)
			: base(_size)
		{
		}
	}
	public class TempBuildStorageComponent : StorageComponent
	{
		public TempBuildStorageComponent(int _size)
			: base(_size)
		{
			Debug.Log((object)"DS - TempBuildStorageComponent constructor");
		}
	}
}

FullSerializer.dll

Decompiled 5 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Text;
using FullSerializer;
using FullSerializer.Internal;
using FullSerializer.Internal.Converters;
using FullSerializer.Internal.DirectConverters;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace FullSerializer
{
	public class fsConverterRegistrar
	{
		public static AnimationCurve_DirectConverter Register_AnimationCurve_DirectConverter;

		public static Bounds_DirectConverter Register_Bounds_DirectConverter;

		public static GUIStyleState_DirectConverter Register_GUIStyleState_DirectConverter;

		public static GUIStyle_DirectConverter Register_GUIStyle_DirectConverter;

		public static Gradient_DirectConverter Register_Gradient_DirectConverter;

		public static Keyframe_DirectConverter Register_Keyframe_DirectConverter;

		public static LayerMask_DirectConverter Register_LayerMask_DirectConverter;

		public static RectOffset_DirectConverter Register_RectOffset_DirectConverter;

		public static Rect_DirectConverter Register_Rect_DirectConverter;

		public static UnityEvent_Converter Register_UnityEvent_Converter;

		public static List<Type> Converters;

		static fsConverterRegistrar()
		{
			Converters = new List<Type>();
			FieldInfo[] declaredFields = typeof(fsConverterRegistrar).GetDeclaredFields();
			foreach (FieldInfo fieldInfo in declaredFields)
			{
				if (fieldInfo.Name.StartsWith("Register_"))
				{
					Converters.Add(fieldInfo.FieldType);
				}
			}
			MethodInfo[] declaredMethods = typeof(fsConverterRegistrar).GetDeclaredMethods();
			foreach (MethodInfo methodInfo in declaredMethods)
			{
				if (methodInfo.Name.StartsWith("Register_"))
				{
					methodInfo.Invoke(null, null);
				}
			}
		}
	}
}
namespace FullSerializer.Internal.DirectConverters
{
	public class AnimationCurve_DirectConverter : fsDirectConverter<AnimationCurve>
	{
		protected override fsResult DoSerialize(AnimationCurve model, Dictionary<string, fsData> serialized)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			fsResult success = fsResult.Success;
			success += SerializeMember(serialized, null, "keys", model.keys);
			success += SerializeMember<WrapMode>(serialized, null, "preWrapMode", model.preWrapMode);
			return success + SerializeMember<WrapMode>(serialized, null, "postWrapMode", model.postWrapMode);
		}

		protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref AnimationCurve model)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			fsResult success = fsResult.Success;
			Keyframe[] value = model.keys;
			success += DeserializeMember<Keyframe[]>(data, null, "keys", out value);
			model.keys = value;
			WrapMode value2 = model.preWrapMode;
			success += DeserializeMember<WrapMode>(data, null, "preWrapMode", out value2);
			model.preWrapMode = value2;
			WrapMode value3 = model.postWrapMode;
			success += DeserializeMember<WrapMode>(data, null, "postWrapMode", out value3);
			model.postWrapMode = value3;
			return success;
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			return (object)new AnimationCurve();
		}
	}
	public class Bounds_DirectConverter : fsDirectConverter<Bounds>
	{
		protected override fsResult DoSerialize(Bounds model, Dictionary<string, fsData> serialized)
		{
			//IL_0012: 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)
			fsResult success = fsResult.Success;
			success += SerializeMember<Vector3>(serialized, null, "center", ((Bounds)(ref model)).center);
			return success + SerializeMember<Vector3>(serialized, null, "size", ((Bounds)(ref model)).size);
		}

		protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref Bounds model)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			fsResult success = fsResult.Success;
			Vector3 value = ((Bounds)(ref model)).center;
			success += DeserializeMember<Vector3>(data, null, "center", out value);
			((Bounds)(ref model)).center = value;
			Vector3 value2 = ((Bounds)(ref model)).size;
			success += DeserializeMember<Vector3>(data, null, "size", out value2);
			((Bounds)(ref model)).size = value2;
			return success;
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			return (object)default(Bounds);
		}
	}
	public class GUIStyleState_DirectConverter : fsDirectConverter<GUIStyleState>
	{
		protected override fsResult DoSerialize(GUIStyleState model, Dictionary<string, fsData> serialized)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			fsResult success = fsResult.Success;
			success += SerializeMember<Texture2D>(serialized, null, "background", model.background);
			return success + SerializeMember<Color>(serialized, null, "textColor", model.textColor);
		}

		protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref GUIStyleState model)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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)
			fsResult success = fsResult.Success;
			Texture2D value = model.background;
			success += DeserializeMember<Texture2D>(data, null, "background", out value);
			model.background = value;
			Color value2 = model.textColor;
			success += DeserializeMember<Color>(data, null, "textColor", out value2);
			model.textColor = value2;
			return success;
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			return (object)new GUIStyleState();
		}
	}
	public class GUIStyle_DirectConverter : fsDirectConverter<GUIStyle>
	{
		protected override fsResult DoSerialize(GUIStyle model, Dictionary<string, fsData> serialized)
		{
			//IL_002b: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			fsResult success = fsResult.Success;
			success += SerializeMember<GUIStyleState>(serialized, null, "active", model.active);
			success += SerializeMember<TextAnchor>(serialized, null, "alignment", model.alignment);
			success += SerializeMember<RectOffset>(serialized, null, "border", model.border);
			success += SerializeMember<TextClipping>(serialized, null, "clipping", model.clipping);
			success += SerializeMember<Vector2>(serialized, null, "contentOffset", model.contentOffset);
			success += SerializeMember(serialized, null, "fixedHeight", model.fixedHeight);
			success += SerializeMember(serialized, null, "fixedWidth", model.fixedWidth);
			success += SerializeMember<GUIStyleState>(serialized, null, "focused", model.focused);
			success += SerializeMember<Font>(serialized, null, "font", model.font);
			success += SerializeMember(serialized, null, "fontSize", model.fontSize);
			success += SerializeMember<FontStyle>(serialized, null, "fontStyle", model.fontStyle);
			success += SerializeMember<GUIStyleState>(serialized, null, "hover", model.hover);
			success += SerializeMember<ImagePosition>(serialized, null, "imagePosition", model.imagePosition);
			success += SerializeMember<RectOffset>(serialized, null, "margin", model.margin);
			success += SerializeMember(serialized, null, "name", model.name);
			success += SerializeMember<GUIStyleState>(serialized, null, "normal", model.normal);
			success += SerializeMember<GUIStyleState>(serialized, null, "onActive", model.onActive);
			success += SerializeMember<GUIStyleState>(serialized, null, "onFocused", model.onFocused);
			success += SerializeMember<GUIStyleState>(serialized, null, "onHover", model.onHover);
			success += SerializeMember<GUIStyleState>(serialized, null, "onNormal", model.onNormal);
			success += SerializeMember<RectOffset>(serialized, null, "overflow", model.overflow);
			success += SerializeMember<RectOffset>(serialized, null, "padding", model.padding);
			success += SerializeMember(serialized, null, "richText", model.richText);
			success += SerializeMember(serialized, null, "stretchHeight", model.stretchHeight);
			success += SerializeMember(serialized, null, "stretchWidth", model.stretchWidth);
			return success + SerializeMember(serialized, null, "wordWrap", model.wordWrap);
		}

		protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref GUIStyle model)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			fsResult success = fsResult.Success;
			GUIStyleState value = model.active;
			success += DeserializeMember<GUIStyleState>(data, null, "active", out value);
			model.active = value;
			TextAnchor value2 = model.alignment;
			success += DeserializeMember<TextAnchor>(data, null, "alignment", out value2);
			model.alignment = value2;
			RectOffset value3 = model.border;
			success += DeserializeMember<RectOffset>(data, null, "border", out value3);
			model.border = value3;
			TextClipping value4 = model.clipping;
			success += DeserializeMember<TextClipping>(data, null, "clipping", out value4);
			model.clipping = value4;
			Vector2 value5 = model.contentOffset;
			success += DeserializeMember<Vector2>(data, null, "contentOffset", out value5);
			model.contentOffset = value5;
			float value6 = model.fixedHeight;
			success += DeserializeMember<float>(data, null, "fixedHeight", out value6);
			model.fixedHeight = value6;
			float value7 = model.fixedWidth;
			success += DeserializeMember<float>(data, null, "fixedWidth", out value7);
			model.fixedWidth = value7;
			GUIStyleState value8 = model.focused;
			success += DeserializeMember<GUIStyleState>(data, null, "focused", out value8);
			model.focused = value8;
			Font value9 = model.font;
			success += DeserializeMember<Font>(data, null, "font", out value9);
			model.font = value9;
			int value10 = model.fontSize;
			success += DeserializeMember<int>(data, null, "fontSize", out value10);
			model.fontSize = value10;
			FontStyle value11 = model.fontStyle;
			success += DeserializeMember<FontStyle>(data, null, "fontStyle", out value11);
			model.fontStyle = value11;
			GUIStyleState value12 = model.hover;
			success += DeserializeMember<GUIStyleState>(data, null, "hover", out value12);
			model.hover = value12;
			ImagePosition value13 = model.imagePosition;
			success += DeserializeMember<ImagePosition>(data, null, "imagePosition", out value13);
			model.imagePosition = value13;
			RectOffset value14 = model.margin;
			success += DeserializeMember<RectOffset>(data, null, "margin", out value14);
			model.margin = value14;
			string value15 = model.name;
			success += DeserializeMember<string>(data, null, "name", out value15);
			model.name = value15;
			GUIStyleState value16 = model.normal;
			success += DeserializeMember<GUIStyleState>(data, null, "normal", out value16);
			model.normal = value16;
			GUIStyleState value17 = model.onActive;
			success += DeserializeMember<GUIStyleState>(data, null, "onActive", out value17);
			model.onActive = value17;
			GUIStyleState value18 = model.onFocused;
			success += DeserializeMember<GUIStyleState>(data, null, "onFocused", out value18);
			model.onFocused = value18;
			GUIStyleState value19 = model.onHover;
			success += DeserializeMember<GUIStyleState>(data, null, "onHover", out value19);
			model.onHover = value19;
			GUIStyleState value20 = model.onNormal;
			success += DeserializeMember<GUIStyleState>(data, null, "onNormal", out value20);
			model.onNormal = value20;
			RectOffset value21 = model.overflow;
			success += DeserializeMember<RectOffset>(data, null, "overflow", out value21);
			model.overflow = value21;
			RectOffset value22 = model.padding;
			success += DeserializeMember<RectOffset>(data, null, "padding", out value22);
			model.padding = value22;
			bool value23 = model.richText;
			success += DeserializeMember<bool>(data, null, "richText", out value23);
			model.richText = value23;
			bool value24 = model.stretchHeight;
			success += DeserializeMember<bool>(data, null, "stretchHeight", out value24);
			model.stretchHeight = value24;
			bool value25 = model.stretchWidth;
			success += DeserializeMember<bool>(data, null, "stretchWidth", out value25);
			model.stretchWidth = value25;
			bool value26 = model.wordWrap;
			success += DeserializeMember<bool>(data, null, "wordWrap", out value26);
			model.wordWrap = value26;
			return success;
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			return (object)new GUIStyle();
		}
	}
	public class Gradient_DirectConverter : fsDirectConverter<Gradient>
	{
		protected override fsResult DoSerialize(Gradient model, Dictionary<string, fsData> serialized)
		{
			fsResult success = fsResult.Success;
			success += SerializeMember(serialized, null, "alphaKeys", model.alphaKeys);
			return success + SerializeMember(serialized, null, "colorKeys", model.colorKeys);
		}

		protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref Gradient model)
		{
			fsResult success = fsResult.Success;
			GradientAlphaKey[] value = model.alphaKeys;
			success += DeserializeMember<GradientAlphaKey[]>(data, null, "alphaKeys", out value);
			model.alphaKeys = value;
			GradientColorKey[] value2 = model.colorKeys;
			success += DeserializeMember<GradientColorKey[]>(data, null, "colorKeys", out value2);
			model.colorKeys = value2;
			return success;
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			return (object)new Gradient();
		}
	}
	public class Keyframe_DirectConverter : fsDirectConverter<Keyframe>
	{
		protected override fsResult DoSerialize(Keyframe model, Dictionary<string, fsData> serialized)
		{
			fsResult success = fsResult.Success;
			success += SerializeMember(serialized, null, "time", ((Keyframe)(ref model)).time);
			success += SerializeMember(serialized, null, "value", ((Keyframe)(ref model)).value);
			success += SerializeMember(serialized, null, "tangentMode", ((Keyframe)(ref model)).tangentMode);
			success += SerializeMember(serialized, null, "inTangent", ((Keyframe)(ref model)).inTangent);
			return success + SerializeMember(serialized, null, "outTangent", ((Keyframe)(ref model)).outTangent);
		}

		protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref Keyframe model)
		{
			fsResult success = fsResult.Success;
			float value = ((Keyframe)(ref model)).time;
			success += DeserializeMember<float>(data, null, "time", out value);
			((Keyframe)(ref model)).time = value;
			float value2 = ((Keyframe)(ref model)).value;
			success += DeserializeMember<float>(data, null, "value", out value2);
			((Keyframe)(ref model)).value = value2;
			int value3 = ((Keyframe)(ref model)).tangentMode;
			success += DeserializeMember<int>(data, null, "tangentMode", out value3);
			((Keyframe)(ref model)).tangentMode = value3;
			float value4 = ((Keyframe)(ref model)).inTangent;
			success += DeserializeMember<float>(data, null, "inTangent", out value4);
			((Keyframe)(ref model)).inTangent = value4;
			float value5 = ((Keyframe)(ref model)).outTangent;
			success += DeserializeMember<float>(data, null, "outTangent", out value5);
			((Keyframe)(ref model)).outTangent = value5;
			return success;
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			return (object)default(Keyframe);
		}
	}
	public class LayerMask_DirectConverter : fsDirectConverter<LayerMask>
	{
		protected override fsResult DoSerialize(LayerMask model, Dictionary<string, fsData> serialized)
		{
			fsResult success = fsResult.Success;
			return success + SerializeMember(serialized, null, "value", ((LayerMask)(ref model)).value);
		}

		protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref LayerMask model)
		{
			fsResult success = fsResult.Success;
			int value = ((LayerMask)(ref model)).value;
			success += DeserializeMember<int>(data, null, "value", out value);
			((LayerMask)(ref model)).value = value;
			return success;
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			return (object)default(LayerMask);
		}
	}
	public class RectOffset_DirectConverter : fsDirectConverter<RectOffset>
	{
		protected override fsResult DoSerialize(RectOffset model, Dictionary<string, fsData> serialized)
		{
			fsResult success = fsResult.Success;
			success += SerializeMember(serialized, null, "bottom", model.bottom);
			success += SerializeMember(serialized, null, "left", model.left);
			success += SerializeMember(serialized, null, "right", model.right);
			return success + SerializeMember(serialized, null, "top", model.top);
		}

		protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref RectOffset model)
		{
			fsResult success = fsResult.Success;
			int value = model.bottom;
			success += DeserializeMember<int>(data, null, "bottom", out value);
			model.bottom = value;
			int value2 = model.left;
			success += DeserializeMember<int>(data, null, "left", out value2);
			model.left = value2;
			int value3 = model.right;
			success += DeserializeMember<int>(data, null, "right", out value3);
			model.right = value3;
			int value4 = model.top;
			success += DeserializeMember<int>(data, null, "top", out value4);
			model.top = value4;
			return success;
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			return (object)new RectOffset();
		}
	}
	public class Rect_DirectConverter : fsDirectConverter<Rect>
	{
		protected override fsResult DoSerialize(Rect model, Dictionary<string, fsData> serialized)
		{
			fsResult success = fsResult.Success;
			success += SerializeMember(serialized, null, "xMin", ((Rect)(ref model)).xMin);
			success += SerializeMember(serialized, null, "yMin", ((Rect)(ref model)).yMin);
			success += SerializeMember(serialized, null, "xMax", ((Rect)(ref model)).xMax);
			return success + SerializeMember(serialized, null, "yMax", ((Rect)(ref model)).yMax);
		}

		protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref Rect model)
		{
			fsResult success = fsResult.Success;
			float value = ((Rect)(ref model)).xMin;
			success += DeserializeMember<float>(data, null, "xMin", out value);
			((Rect)(ref model)).xMin = value;
			float value2 = ((Rect)(ref model)).yMin;
			success += DeserializeMember<float>(data, null, "yMin", out value2);
			((Rect)(ref model)).yMin = value2;
			float value3 = ((Rect)(ref model)).xMax;
			success += DeserializeMember<float>(data, null, "xMax", out value3);
			((Rect)(ref model)).xMax = value3;
			float value4 = ((Rect)(ref model)).yMax;
			success += DeserializeMember<float>(data, null, "yMax", out value4);
			((Rect)(ref model)).yMax = value4;
			return success;
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			return (object)default(Rect);
		}
	}
}
namespace FullSerializer.Internal.Converters
{
	public class UnityEvent_Converter : fsConverter
	{
		public override bool CanProcess(Type type)
		{
			return typeof(UnityEvent).Resolve().IsAssignableFrom(type) && !type.IsGenericType;
		}

		public override bool RequestCycleSupport(Type storageType)
		{
			return false;
		}

		public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType)
		{
			Type type = (Type)instance;
			fsResult success = fsResult.Success;
			instance = JsonUtility.FromJson(fsJsonPrinter.CompressedJson(data), type);
			return success;
		}

		public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType)
		{
			fsResult success = fsResult.Success;
			serialized = fsJsonParser.Parse(JsonUtility.ToJson(instance));
			return success;
		}
	}
}
namespace FullSerializer.Internal
{
	public class fsArrayConverter : fsConverter
	{
		public override bool CanProcess(Type type)
		{
			return type.IsArray;
		}

		public override bool RequestCycleSupport(Type storageType)
		{
			return false;
		}

		public override bool RequestInheritanceSupport(Type storageType)
		{
			return false;
		}

		public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType)
		{
			IList list = (Array)instance;
			Type elementType = storageType.GetElementType();
			fsResult success = fsResult.Success;
			serialized = fsData.CreateList(list.Count);
			List<fsData> asList = serialized.AsList;
			for (int i = 0; i < list.Count; i++)
			{
				object instance2 = list[i];
				fsData data;
				fsResult result = Serializer.TrySerialize(elementType, instance2, out data);
				success.AddMessages(result);
				if (!result.Failed)
				{
					asList.Add(data);
				}
			}
			return success;
		}

		public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType)
		{
			fsResult success = fsResult.Success;
			fsResult fsResult = (success += CheckType(data, fsDataType.Array));
			if (fsResult.Failed)
			{
				return success;
			}
			Type elementType = storageType.GetElementType();
			List<fsData> asList = data.AsList;
			ArrayList arrayList = new ArrayList(asList.Count);
			int count = arrayList.Count;
			for (int i = 0; i < asList.Count; i++)
			{
				fsData data2 = asList[i];
				object result = null;
				if (i < count)
				{
					result = arrayList[i];
				}
				fsResult result2 = Serializer.TryDeserialize(data2, elementType, ref result);
				success.AddMessages(result2);
				if (!result2.Failed)
				{
					if (i < count)
					{
						arrayList[i] = result;
					}
					else
					{
						arrayList.Add(result);
					}
				}
			}
			instance = arrayList.ToArray(elementType);
			return success;
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			return fsMetaType.Get(Serializer.Config, storageType).CreateInstance();
		}
	}
	public class fsDateConverter : fsConverter
	{
		private const string DefaultDateTimeFormatString = "o";

		private const string DateTimeOffsetFormatString = "o";

		private string DateTimeFormatString => Serializer.Config.CustomDateTimeFormatString ?? "o";

		public override bool CanProcess(Type type)
		{
			return (object)type == typeof(DateTime) || (object)type == typeof(DateTimeOffset) || (object)type == typeof(TimeSpan);
		}

		public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType)
		{
			if (instance is DateTime dateTime)
			{
				serialized = new fsData(dateTime.ToString(DateTimeFormatString));
				return fsResult.Success;
			}
			if (instance is DateTimeOffset dateTimeOffset)
			{
				serialized = new fsData(dateTimeOffset.ToString("o"));
				return fsResult.Success;
			}
			if (instance is TimeSpan timeSpan)
			{
				serialized = new fsData(timeSpan.ToString());
				return fsResult.Success;
			}
			throw new InvalidOperationException("FullSerializer Internal Error -- Unexpected serialization type");
		}

		public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType)
		{
			if (!data.IsString)
			{
				return fsResult.Fail("Date deserialization requires a string, not " + data.Type);
			}
			if ((object)storageType == typeof(DateTime))
			{
				if (DateTime.TryParse(data.AsString, null, DateTimeStyles.RoundtripKind, out var result))
				{
					instance = result;
					return fsResult.Success;
				}
				if (fsGlobalConfig.AllowInternalExceptions)
				{
					try
					{
						instance = Convert.ToDateTime(data.AsString);
						return fsResult.Success;
					}
					catch (Exception ex)
					{
						return fsResult.Fail("Unable to parse " + data.AsString + " into a DateTime; got exception " + ex);
					}
				}
				return fsResult.Fail("Unable to parse " + data.AsString + " into a DateTime");
			}
			if ((object)storageType == typeof(DateTimeOffset))
			{
				if (DateTimeOffset.TryParse(data.AsString, null, DateTimeStyles.RoundtripKind, out var result2))
				{
					instance = result2;
					return fsResult.Success;
				}
				return fsResult.Fail("Unable to parse " + data.AsString + " into a DateTimeOffset");
			}
			if ((object)storageType == typeof(TimeSpan))
			{
				if (TimeSpan.TryParse(data.AsString, out var result3))
				{
					instance = result3;
					return fsResult.Success;
				}
				return fsResult.Fail("Unable to parse " + data.AsString + " into a TimeSpan");
			}
			throw new InvalidOperationException("FullSerializer Internal Error -- Unexpected deserialization type");
		}
	}
	public class fsDictionaryConverter : fsConverter
	{
		public override bool CanProcess(Type type)
		{
			return typeof(IDictionary).IsAssignableFrom(type);
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			return fsMetaType.Get(Serializer.Config, storageType).CreateInstance();
		}

		public override fsResult TryDeserialize(fsData data, ref object instance_, Type storageType)
		{
			IDictionary dictionary = (IDictionary)instance_;
			fsResult success = fsResult.Success;
			GetKeyValueTypes(dictionary.GetType(), out var keyStorageType, out var valueStorageType);
			if (data.IsList)
			{
				List<fsData> asList = data.AsList;
				for (int i = 0; i < asList.Count; i++)
				{
					fsData data2 = asList[i];
					if ((success += CheckType(data2, fsDataType.Object)).Failed)
					{
						return success;
					}
					if ((success += CheckKey(data2, "Key", out var subitem)).Failed)
					{
						return success;
					}
					if ((success += CheckKey(data2, "Value", out var subitem2)).Failed)
					{
						return success;
					}
					object result = null;
					object result2 = null;
					if ((success += Serializer.TryDeserialize(subitem, keyStorageType, ref result)).Failed)
					{
						return success;
					}
					if ((success += Serializer.TryDeserialize(subitem2, valueStorageType, ref result2)).Failed)
					{
						return success;
					}
					AddItemToDictionary(dictionary, result, result2);
				}
			}
			else
			{
				if (!data.IsDictionary)
				{
					return FailExpectedType(data, fsDataType.Array, fsDataType.Object);
				}
				foreach (KeyValuePair<string, fsData> item in data.AsDictionary)
				{
					if (!fsSerializer.IsReservedKeyword(item.Key))
					{
						fsData data3 = new fsData(item.Key);
						fsData value = item.Value;
						object result3 = null;
						object result4 = null;
						fsResult fsResult = (success += Serializer.TryDeserialize(data3, keyStorageType, ref result3));
						if (fsResult.Failed)
						{
							return success;
						}
						if ((success += Serializer.TryDeserialize(value, valueStorageType, ref result4)).Failed)
						{
							return success;
						}
						AddItemToDictionary(dictionary, result3, result4);
					}
				}
			}
			return success;
		}

		public override fsResult TrySerialize(object instance_, out fsData serialized, Type storageType)
		{
			serialized = fsData.Null;
			fsResult success = fsResult.Success;
			IDictionary dictionary = (IDictionary)instance_;
			GetKeyValueTypes(dictionary.GetType(), out var keyStorageType, out var valueStorageType);
			IDictionaryEnumerator enumerator = dictionary.GetEnumerator();
			bool flag = true;
			List<fsData> list = new List<fsData>(dictionary.Count);
			List<fsData> list2 = new List<fsData>(dictionary.Count);
			while (enumerator.MoveNext())
			{
				if ((success += Serializer.TrySerialize(keyStorageType, enumerator.Key, out var data)).Failed)
				{
					return success;
				}
				if ((success += Serializer.TrySerialize(valueStorageType, enumerator.Value, out var data2)).Failed)
				{
					return success;
				}
				list.Add(data);
				list2.Add(data2);
				flag &= data.IsString;
			}
			if (flag)
			{
				serialized = fsData.CreateDictionary();
				Dictionary<string, fsData> asDictionary = serialized.AsDictionary;
				for (int i = 0; i < list.Count; i++)
				{
					fsData fsData = list[i];
					fsData value = list2[i];
					asDictionary[fsData.AsString] = value;
				}
			}
			else
			{
				serialized = fsData.CreateList(list.Count);
				List<fsData> asList = serialized.AsList;
				for (int j = 0; j < list.Count; j++)
				{
					fsData value2 = list[j];
					fsData value3 = list2[j];
					Dictionary<string, fsData> dictionary2 = new Dictionary<string, fsData>();
					dictionary2["Key"] = value2;
					dictionary2["Value"] = value3;
					asList.Add(new fsData(dictionary2));
				}
			}
			return success;
		}

		private fsResult AddItemToDictionary(IDictionary dictionary, object key, object value)
		{
			if (key == null || value == null)
			{
				Type @interface = fsReflectionUtility.GetInterface(dictionary.GetType(), typeof(ICollection<>));
				if ((object)@interface == null)
				{
					return fsResult.Warn(string.Concat(dictionary.GetType(), " does not extend ICollection"));
				}
				Type type = @interface.GetGenericArguments()[0];
				object obj = Activator.CreateInstance(type, key, value);
				MethodInfo flattenedMethod = @interface.GetFlattenedMethod("Add");
				flattenedMethod.Invoke(dictionary, new object[1] { obj });
				return fsResult.Success;
			}
			dictionary[key] = value;
			return fsResult.Success;
		}

		private static void GetKeyValueTypes(Type dictionaryType, out Type keyStorageType, out Type valueStorageType)
		{
			Type @interface = fsReflectionUtility.GetInterface(dictionaryType, typeof(IDictionary<, >));
			if ((object)@interface != null)
			{
				Type[] genericArguments = @interface.GetGenericArguments();
				keyStorageType = genericArguments[0];
				valueStorageType = genericArguments[1];
			}
			else
			{
				keyStorageType = typeof(object);
				valueStorageType = typeof(object);
			}
		}
	}
	public class fsEnumConverter : fsConverter
	{
		public override bool CanProcess(Type type)
		{
			return type.Resolve().IsEnum;
		}

		public override bool RequestCycleSupport(Type storageType)
		{
			return false;
		}

		public override bool RequestInheritanceSupport(Type storageType)
		{
			return false;
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			return Enum.ToObject(storageType, (object)0);
		}

		public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType)
		{
			if (Serializer.Config.SerializeEnumsAsInteger)
			{
				serialized = new fsData(Convert.ToInt64(instance));
			}
			else if (fsPortableReflection.GetAttribute<FlagsAttribute>(storageType) != null)
			{
				long num = Convert.ToInt64(instance);
				StringBuilder stringBuilder = new StringBuilder();
				bool flag = true;
				foreach (object value in Enum.GetValues(storageType))
				{
					long num2 = Convert.ToInt64(value);
					if ((num & num2) != 0)
					{
						if (!flag)
						{
							stringBuilder.Append(",");
						}
						flag = false;
						stringBuilder.Append(value.ToString());
					}
				}
				serialized = new fsData(stringBuilder.ToString());
			}
			else
			{
				serialized = new fsData(Enum.GetName(storageType, instance));
			}
			return fsResult.Success;
		}

		public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType)
		{
			if (data.IsString)
			{
				string[] array = data.AsString.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				long num = 0L;
				foreach (string text in array)
				{
					if (!ArrayContains<string>(Enum.GetNames(storageType), text))
					{
						return fsResult.Fail("Cannot find enum name " + text + " on type " + storageType);
					}
					long num2 = (long)Convert.ChangeType(Enum.Parse(storageType, text), typeof(long));
					num |= num2;
				}
				instance = Enum.ToObject(storageType, (object)num);
				return fsResult.Success;
			}
			if (data.IsInt64)
			{
				int num3 = (int)data.AsInt64;
				instance = Enum.ToObject(storageType, (object)num3);
				return fsResult.Success;
			}
			return fsResult.Fail("EnumConverter encountered an unknown JSON data type");
		}

		private static bool ArrayContains<T>(T[] values, T value)
		{
			for (int i = 0; i < values.Length; i++)
			{
				if (EqualityComparer<T>.Default.Equals(values[i], value))
				{
					return true;
				}
			}
			return false;
		}
	}
}
namespace FullSerializer
{
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface)]
	public sealed class fsForwardAttribute : Attribute
	{
		public string MemberName;

		public fsForwardAttribute(string memberName)
		{
			MemberName = memberName;
		}
	}
}
namespace FullSerializer.Internal
{
	public class fsForwardConverter : fsConverter
	{
		private string _memberName;

		public fsForwardConverter(fsForwardAttribute attribute)
		{
			_memberName = attribute.MemberName;
		}

		public override bool CanProcess(Type type)
		{
			throw new NotSupportedException("Please use the [fsForward(...)] attribute.");
		}

		private fsResult GetProperty(object instance, out fsMetaProperty property)
		{
			fsMetaProperty[] properties = fsMetaType.Get(Serializer.Config, instance.GetType()).Properties;
			for (int i = 0; i < properties.Length; i++)
			{
				if (properties[i].MemberName == _memberName)
				{
					property = properties[i];
					return fsResult.Success;
				}
			}
			property = null;
			return fsResult.Fail("No property named \"" + _memberName + "\" on " + instance.GetType().CSharpName());
		}

		public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType)
		{
			serialized = fsData.Null;
			fsResult success = fsResult.Success;
			fsMetaProperty property;
			fsResult fsResult = (success += GetProperty(instance, out property));
			if (fsResult.Failed)
			{
				return success;
			}
			object instance2 = property.Read(instance);
			return Serializer.TrySerialize(property.StorageType, instance2, out serialized);
		}

		public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType)
		{
			fsResult success = fsResult.Success;
			fsMetaProperty property;
			fsResult fsResult = (success += GetProperty(instance, out property));
			if (fsResult.Failed)
			{
				return success;
			}
			object result = null;
			if ((success += Serializer.TryDeserialize(data, property.StorageType, ref result)).Failed)
			{
				return success;
			}
			property.Write(instance, result);
			return success;
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			return fsMetaType.Get(Serializer.Config, storageType).CreateInstance();
		}
	}
	public class fsGuidConverter : fsConverter
	{
		public override bool CanProcess(Type type)
		{
			return (object)type == typeof(Guid);
		}

		public override bool RequestCycleSupport(Type storageType)
		{
			return false;
		}

		public override bool RequestInheritanceSupport(Type storageType)
		{
			return false;
		}

		public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType)
		{
			serialized = new fsData(((Guid)instance).ToString());
			return fsResult.Success;
		}

		public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType)
		{
			if (data.IsString)
			{
				instance = new Guid(data.AsString);
				return fsResult.Success;
			}
			return fsResult.Fail("fsGuidConverter encountered an unknown JSON data type");
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			return default(Guid);
		}
	}
	public class fsIEnumerableConverter : fsConverter
	{
		public override bool CanProcess(Type type)
		{
			if (!typeof(IEnumerable).IsAssignableFrom(type))
			{
				return false;
			}
			return (object)GetAddMethod(type) != null;
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			return fsMetaType.Get(Serializer.Config, storageType).CreateInstance();
		}

		public override fsResult TrySerialize(object instance_, out fsData serialized, Type storageType)
		{
			IEnumerable enumerable = (IEnumerable)instance_;
			fsResult success = fsResult.Success;
			Type elementType = GetElementType(storageType);
			serialized = fsData.CreateList(HintSize(enumerable));
			List<fsData> asList = serialized.AsList;
			foreach (object item in enumerable)
			{
				fsData data;
				fsResult result = Serializer.TrySerialize(elementType, item, out data);
				success.AddMessages(result);
				if (!result.Failed)
				{
					asList.Add(data);
				}
			}
			if (IsStack(enumerable.GetType()))
			{
				asList.Reverse();
			}
			return success;
		}

		private bool IsStack(Type type)
		{
			return type.Resolve().IsGenericType && (object)type.Resolve().GetGenericTypeDefinition() == typeof(Stack<>);
		}

		public override fsResult TryDeserialize(fsData data, ref object instance_, Type storageType)
		{
			IEnumerable enumerable = (IEnumerable)instance_;
			fsResult success = fsResult.Success;
			fsResult fsResult = (success += CheckType(data, fsDataType.Array));
			if (fsResult.Failed)
			{
				return success;
			}
			Type elementType = GetElementType(storageType);
			MethodInfo addMethod = GetAddMethod(storageType);
			MethodInfo flattenedMethod = storageType.GetFlattenedMethod("get_Item");
			MethodInfo flattenedMethod2 = storageType.GetFlattenedMethod("set_Item");
			if ((object)flattenedMethod2 == null)
			{
				TryClear(storageType, enumerable);
			}
			int num = TryGetExistingSize(storageType, enumerable);
			List<fsData> asList = data.AsList;
			for (int i = 0; i < asList.Count; i++)
			{
				fsData data2 = asList[i];
				object result = null;
				if ((object)flattenedMethod != null && i < num)
				{
					result = flattenedMethod.Invoke(enumerable, new object[1] { i });
				}
				fsResult result2 = Serializer.TryDeserialize(data2, elementType, ref result);
				success.AddMessages(result2);
				if (!result2.Failed)
				{
					if ((object)flattenedMethod2 != null && i < num)
					{
						flattenedMethod2.Invoke(enumerable, new object[2] { i, result });
					}
					else
					{
						addMethod.Invoke(enumerable, new object[1] { result });
					}
				}
			}
			return success;
		}

		private static int HintSize(IEnumerable collection)
		{
			if (collection is ICollection)
			{
				return ((ICollection)collection).Count;
			}
			return 0;
		}

		private static Type GetElementType(Type objectType)
		{
			if (objectType.HasElementType)
			{
				return objectType.GetElementType();
			}
			Type @interface = fsReflectionUtility.GetInterface(objectType, typeof(IEnumerable<>));
			if ((object)@interface != null)
			{
				return @interface.GetGenericArguments()[0];
			}
			return typeof(object);
		}

		private static void TryClear(Type type, object instance)
		{
			type.GetFlattenedMethod("Clear")?.Invoke(instance, null);
		}

		private static int TryGetExistingSize(Type type, object instance)
		{
			PropertyInfo flattenedProperty = type.GetFlattenedProperty("Count");
			if ((object)flattenedProperty != null)
			{
				return (int)flattenedProperty.GetGetMethod().Invoke(instance, null);
			}
			return 0;
		}

		private static MethodInfo GetAddMethod(Type type)
		{
			Type @interface = fsReflectionUtility.GetInterface(type, typeof(ICollection<>));
			if ((object)@interface != null)
			{
				MethodInfo declaredMethod = @interface.GetDeclaredMethod("Add");
				if ((object)declaredMethod != null)
				{
					return declaredMethod;
				}
			}
			return type.GetFlattenedMethod("Add") ?? type.GetFlattenedMethod("Push") ?? type.GetFlattenedMethod("Enqueue");
		}
	}
	public class fsKeyValuePairConverter : fsConverter
	{
		public override bool CanProcess(Type type)
		{
			return type.Resolve().IsGenericType && (object)type.GetGenericTypeDefinition() == typeof(KeyValuePair<, >);
		}

		public override bool RequestCycleSupport(Type storageType)
		{
			return false;
		}

		public override bool RequestInheritanceSupport(Type storageType)
		{
			return false;
		}

		public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType)
		{
			fsResult success = fsResult.Success;
			fsData subitem;
			fsResult fsResult = (success += CheckKey(data, "Key", out subitem));
			if (fsResult.Failed)
			{
				return success;
			}
			if ((success += CheckKey(data, "Value", out var subitem2)).Failed)
			{
				return success;
			}
			Type[] genericArguments = storageType.GetGenericArguments();
			Type storageType2 = genericArguments[0];
			Type storageType3 = genericArguments[1];
			object result = null;
			object result2 = null;
			success.AddMessages(Serializer.TryDeserialize(subitem, storageType2, ref result));
			success.AddMessages(Serializer.TryDeserialize(subitem2, storageType3, ref result2));
			instance = Activator.CreateInstance(storageType, result, result2);
			return success;
		}

		public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType)
		{
			PropertyInfo declaredProperty = storageType.GetDeclaredProperty("Key");
			PropertyInfo declaredProperty2 = storageType.GetDeclaredProperty("Value");
			object value = declaredProperty.GetValue(instance, null);
			object value2 = declaredProperty2.GetValue(instance, null);
			Type[] genericArguments = storageType.GetGenericArguments();
			Type storageType2 = genericArguments[0];
			Type storageType3 = genericArguments[1];
			fsResult success = fsResult.Success;
			success.AddMessages(Serializer.TrySerialize(storageType2, value, out var data));
			success.AddMessages(Serializer.TrySerialize(storageType3, value2, out var data2));
			serialized = fsData.CreateDictionary();
			if (data != null)
			{
				serialized.AsDictionary["Key"] = data;
			}
			if (data2 != null)
			{
				serialized.AsDictionary["Value"] = data2;
			}
			return success;
		}
	}
	public class fsNullableConverter : fsConverter
	{
		public override bool CanProcess(Type type)
		{
			return type.Resolve().IsGenericType && (object)type.GetGenericTypeDefinition() == typeof(Nullable<>);
		}

		public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType)
		{
			return Serializer.TrySerialize(Nullable.GetUnderlyingType(storageType), instance, out serialized);
		}

		public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType)
		{
			return Serializer.TryDeserialize(data, Nullable.GetUnderlyingType(storageType), ref instance);
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			return storageType;
		}
	}
	public class fsPrimitiveConverter : fsConverter
	{
		public override bool CanProcess(Type type)
		{
			return type.Resolve().IsPrimitive || (object)type == typeof(string) || (object)type == typeof(decimal);
		}

		public override bool RequestCycleSupport(Type storageType)
		{
			return false;
		}

		public override bool RequestInheritanceSupport(Type storageType)
		{
			return false;
		}

		private static bool UseBool(Type type)
		{
			return (object)type == typeof(bool);
		}

		private static bool UseInt64(Type type)
		{
			return (object)type == typeof(sbyte) || (object)type == typeof(byte) || (object)type == typeof(short) || (object)type == typeof(ushort) || (object)type == typeof(int) || (object)type == typeof(uint) || (object)type == typeof(long) || (object)type == typeof(ulong);
		}

		private static bool UseDouble(Type type)
		{
			return (object)type == typeof(float) || (object)type == typeof(double) || (object)type == typeof(decimal);
		}

		private static bool UseString(Type type)
		{
			return (object)type == typeof(string) || (object)type == typeof(char);
		}

		public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType)
		{
			Type type = instance.GetType();
			if (Serializer.Config.Serialize64BitIntegerAsString && ((object)type == typeof(long) || (object)type == typeof(ulong)))
			{
				serialized = new fsData((string)Convert.ChangeType(instance, typeof(string)));
				return fsResult.Success;
			}
			if (UseBool(type))
			{
				serialized = new fsData((bool)instance);
				return fsResult.Success;
			}
			if (UseInt64(type))
			{
				serialized = new fsData((long)Convert.ChangeType(instance, typeof(long)));
				return fsResult.Success;
			}
			if (UseDouble(type))
			{
				if ((object)instance.GetType() == typeof(float) && (float)instance != float.MinValue && (float)instance != float.MaxValue && !float.IsInfinity((float)instance) && !float.IsNaN((float)instance))
				{
					serialized = new fsData((double)(decimal)(float)instance);
					return fsResult.Success;
				}
				serialized = new fsData((double)Convert.ChangeType(instance, typeof(double)));
				return fsResult.Success;
			}
			if (UseString(type))
			{
				serialized = new fsData((string)Convert.ChangeType(instance, typeof(string)));
				return fsResult.Success;
			}
			serialized = null;
			return fsResult.Fail("Unhandled primitive type " + instance.GetType());
		}

		public override fsResult TryDeserialize(fsData storage, ref object instance, Type storageType)
		{
			fsResult success = fsResult.Success;
			if (UseBool(storageType))
			{
				fsResult fsResult = (success += CheckType(storage, fsDataType.Boolean));
				if (fsResult.Succeeded)
				{
					instance = storage.AsBool;
				}
				return success;
			}
			if (UseDouble(storageType) || UseInt64(storageType))
			{
				if (storage.IsDouble)
				{
					instance = Convert.ChangeType(storage.AsDouble, storageType);
				}
				else if (storage.IsInt64)
				{
					instance = Convert.ChangeType(storage.AsInt64, storageType);
				}
				else
				{
					if (!Serializer.Config.Serialize64BitIntegerAsString || !storage.IsString || ((object)storageType != typeof(long) && (object)storageType != typeof(ulong)))
					{
						return fsResult.Fail(string.Concat(GetType().Name, " expected number but got ", storage.Type, " in ", storage));
					}
					instance = Convert.ChangeType(storage.AsString, storageType);
				}
				return fsResult.Success;
			}
			if (UseString(storageType))
			{
				fsResult fsResult2 = (success += CheckType(storage, fsDataType.String));
				if (fsResult2.Succeeded)
				{
					instance = storage.AsString;
				}
				return success;
			}
			return fsResult.Fail(GetType().Name + ": Bad data; expected bool, number, string, but got " + storage);
		}
	}
	public class fsReflectedConverter : fsConverter
	{
		public override bool CanProcess(Type type)
		{
			if (type.Resolve().IsArray || typeof(ICollection).IsAssignableFrom(type))
			{
				return false;
			}
			return true;
		}

		public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType)
		{
			serialized = fsData.CreateDictionary();
			fsResult success = fsResult.Success;
			fsMetaType fsMetaType = fsMetaType.Get(Serializer.Config, instance.GetType());
			fsMetaType.EmitAotData();
			for (int i = 0; i < fsMetaType.Properties.Length; i++)
			{
				fsMetaProperty fsMetaProperty2 = fsMetaType.Properties[i];
				if (fsMetaProperty2.CanRead)
				{
					fsData data;
					fsResult result = Serializer.TrySerialize(fsMetaProperty2.StorageType, fsMetaProperty2.OverrideConverterType, fsMetaProperty2.Read(instance), out data);
					success.AddMessages(result);
					if (!result.Failed)
					{
						serialized.AsDictionary[fsMetaProperty2.JsonName] = data;
					}
				}
			}
			return success;
		}

		public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType)
		{
			fsResult success = fsResult.Success;
			fsResult fsResult = (success += CheckType(data, fsDataType.Object));
			if (fsResult.Failed)
			{
				return success;
			}
			fsMetaType fsMetaType = fsMetaType.Get(Serializer.Config, storageType);
			fsMetaType.EmitAotData();
			for (int i = 0; i < fsMetaType.Properties.Length; i++)
			{
				fsMetaProperty fsMetaProperty2 = fsMetaType.Properties[i];
				if (fsMetaProperty2.CanWrite && data.AsDictionary.TryGetValue(fsMetaProperty2.JsonName, out var value))
				{
					object result = null;
					if (fsMetaProperty2.CanRead)
					{
						result = fsMetaProperty2.Read(instance);
					}
					fsResult result2 = Serializer.TryDeserialize(value, fsMetaProperty2.StorageType, fsMetaProperty2.OverrideConverterType, ref result);
					success.AddMessages(result2);
					if (!result2.Failed)
					{
						fsMetaProperty2.Write(instance, result);
					}
				}
			}
			return success;
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			fsMetaType fsMetaType = fsMetaType.Get(Serializer.Config, storageType);
			return fsMetaType.CreateInstance();
		}
	}
	public class fsTypeConverter : fsConverter
	{
		public override bool CanProcess(Type type)
		{
			return typeof(Type).IsAssignableFrom(type);
		}

		public override bool RequestCycleSupport(Type type)
		{
			return false;
		}

		public override bool RequestInheritanceSupport(Type type)
		{
			return false;
		}

		public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType)
		{
			Type type = (Type)instance;
			serialized = new fsData(type.FullName);
			return fsResult.Success;
		}

		public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType)
		{
			if (!data.IsString)
			{
				return fsResult.Fail("Type converter requires a string");
			}
			instance = fsTypeCache.GetType(data.AsString);
			if (instance == null)
			{
				return fsResult.Fail("Unable to find type " + data.AsString);
			}
			return fsResult.Success;
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			return storageType;
		}
	}
	public class fsWeakReferenceConverter : fsConverter
	{
		public override bool CanProcess(Type type)
		{
			return (object)type == typeof(WeakReference);
		}

		public override bool RequestCycleSupport(Type storageType)
		{
			return false;
		}

		public override bool RequestInheritanceSupport(Type storageType)
		{
			return false;
		}

		public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType)
		{
			WeakReference weakReference = (WeakReference)instance;
			fsResult success = fsResult.Success;
			serialized = fsData.CreateDictionary();
			if (weakReference.IsAlive)
			{
				fsData data;
				fsResult fsResult = (success += Serializer.TrySerialize(weakReference.Target, out data));
				if (fsResult.Failed)
				{
					return success;
				}
				serialized.AsDictionary["Target"] = data;
				serialized.AsDictionary["TrackResurrection"] = new fsData(weakReference.TrackResurrection);
			}
			return success;
		}

		public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType)
		{
			fsResult success = fsResult.Success;
			fsResult fsResult = (success += CheckType(data, fsDataType.Object));
			if (fsResult.Failed)
			{
				return success;
			}
			if (data.AsDictionary.ContainsKey("Target"))
			{
				fsData data2 = data.AsDictionary["Target"];
				object result = null;
				fsResult fsResult2 = (success += Serializer.TryDeserialize(data2, typeof(object), ref result));
				if (fsResult2.Failed)
				{
					return success;
				}
				bool trackResurrection = false;
				if (data.AsDictionary.ContainsKey("TrackResurrection") && data.AsDictionary["TrackResurrection"].IsBool)
				{
					trackResurrection = data.AsDictionary["TrackResurrection"].AsBool;
				}
				instance = new WeakReference(result, trackResurrection);
			}
			return success;
		}

		public override object CreateInstance(fsData data, Type storageType)
		{
			return new WeakReference(null);
		}
	}
	public class fsCyclicReferenceManager
	{
		private class ObjectReferenceEqualityComparator : IEqualityComparer<object>
		{
			public static readonly IEqualityComparer<object> Instance = new ObjectReferenceEqualityComparator();

			bool IEqualityComparer<object>.Equals(object x, object y)
			{
				return object.ReferenceEquals(x, y);
			}

			int IEqualityComparer<object>.GetHashCode(object obj)
			{
				return RuntimeHelpers.GetHashCode(obj);
			}
		}

		private Dictionary<object, int> _objectIds = new Dictionary<object, int>(ObjectReferenceEqualityComparator.Instance);

		private int _nextId;

		private Dictionary<int, object> _marked = new Dictionary<int, object>();

		private int _depth;

		public void Enter()
		{
			_depth++;
		}

		public bool Exit()
		{
			_depth--;
			if (_depth == 0)
			{
				_objectIds = new Dictionary<object, int>(ObjectReferenceEqualityComparator.Instance);
				_nextId = 0;
				_marked = new Dictionary<int, object>();
			}
			if (_depth < 0)
			{
				_depth = 0;
				throw new InvalidOperationException("Internal Error - Mismatched Enter/Exit");
			}
			return _depth == 0;
		}

		public object GetReferenceObject(int id)
		{
			if (!_marked.ContainsKey(id))
			{
				throw new InvalidOperationException("Internal Deserialization Error - Object definition has not been encountered for object with id=" + id + "; have you reordered or modified the serialized data? If this is an issue with an unmodified Full Serializer implementation and unmodified serialization data, please report an issue with an included test case.");
			}
			return _marked[id];
		}

		public void AddReferenceWithId(int id, object reference)
		{
			_marked[id] = reference;
		}

		public int GetReferenceId(object item)
		{
			if (!_objectIds.TryGetValue(item, out var value))
			{
				value = _nextId++;
				_objectIds[item] = value;
			}
			return value;
		}

		public bool IsReference(object item)
		{
			return _marked.ContainsKey(GetReferenceId(item));
		}

		public void MarkSerialized(object item)
		{
			int referenceId = GetReferenceId(item);
			if (_marked.ContainsKey(referenceId))
			{
				throw new InvalidOperationException(string.Concat("Internal Error - ", item, " has already been marked as serialized"));
			}
			_marked[referenceId] = item;
		}
	}
	public struct fsOption<T>
	{
		private bool _hasValue;

		private T _value;

		public static fsOption<T> Empty;

		public bool HasValue => _hasValue;

		public bool IsEmpty => !_hasValue;

		public T Value
		{
			get
			{
				if (IsEmpty)
				{
					throw new InvalidOperationException("fsOption is empty");
				}
				return _value;
			}
		}

		public fsOption(T value)
		{
			_hasValue = true;
			_value = value;
		}
	}
	public static class fsOption
	{
		public static fsOption<T> Just<T>(T value)
		{
			return new fsOption<T>(value);
		}
	}
	public static class fsPortableReflection
	{
		private struct AttributeQuery
		{
			public MemberInfo MemberInfo;

			public Type AttributeType;
		}

		private class AttributeQueryComparator : IEqualityComparer<AttributeQuery>
		{
			public bool Equals(AttributeQuery x, AttributeQuery y)
			{
				return (object)x.MemberInfo == y.MemberInfo && (object)x.AttributeType == y.AttributeType;
			}

			public int GetHashCode(AttributeQuery obj)
			{
				return obj.MemberInfo.GetHashCode() + 17 * obj.AttributeType.GetHashCode();
			}
		}

		public static Type[] EmptyTypes = new Type[0];

		private static IDictionary<AttributeQuery, Attribute> _cachedAttributeQueries = new Dictionary<AttributeQuery, Attribute>(new AttributeQueryComparator());

		private static BindingFlags DeclaredFlags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		public static bool HasAttribute<TAttribute>(MemberInfo element)
		{
			return HasAttribute(element, typeof(TAttribute));
		}

		public static bool HasAttribute<TAttribute>(MemberInfo element, bool shouldCache)
		{
			return HasAttribute(element, typeof(TAttribute), shouldCache);
		}

		public static bool HasAttribute(MemberInfo element, Type attributeType)
		{
			return HasAttribute(element, attributeType, shouldCache: true);
		}

		public static bool HasAttribute(MemberInfo element, Type attributeType, bool shouldCache)
		{
			return element.IsDefined(attributeType, inherit: true);
		}

		public static Attribute GetAttribute(MemberInfo element, Type attributeType, bool shouldCache)
		{
			AttributeQuery attributeQuery = default(AttributeQuery);
			attributeQuery.MemberInfo = element;
			attributeQuery.AttributeType = attributeType;
			AttributeQuery key = attributeQuery;
			if (!_cachedAttributeQueries.TryGetValue(key, out var value))
			{
				object[] customAttributes = element.GetCustomAttributes(attributeType, inherit: true);
				if (customAttributes.Length > 0)
				{
					value = (Attribute)customAttributes[0];
				}
				if (shouldCache)
				{
					_cachedAttributeQueries[key] = value;
				}
			}
			return value;
		}

		public static TAttribute GetAttribute<TAttribute>(MemberInfo element, bool shouldCache) where TAttribute : Attribute
		{
			return (TAttribute)GetAttribute(element, typeof(TAttribute), shouldCache);
		}

		public static TAttribute GetAttribute<TAttribute>(MemberInfo element) where TAttribute : Attribute
		{
			return GetAttribute<TAttribute>(element, shouldCache: true);
		}

		public static PropertyInfo GetDeclaredProperty(this Type type, string propertyName)
		{
			PropertyInfo[] declaredProperties = type.GetDeclaredProperties();
			for (int i = 0; i < declaredProperties.Length; i++)
			{
				if (declaredProperties[i].Name == propertyName)
				{
					return declaredProperties[i];
				}
			}
			return null;
		}

		public static MethodInfo GetDeclaredMethod(this Type type, string methodName)
		{
			MethodInfo[] declaredMethods = type.GetDeclaredMethods();
			for (int i = 0; i < declaredMethods.Length; i++)
			{
				if (declaredMethods[i].Name == methodName)
				{
					return declaredMethods[i];
				}
			}
			return null;
		}

		public static ConstructorInfo GetDeclaredConstructor(this Type type, Type[] parameters)
		{
			ConstructorInfo[] declaredConstructors = type.GetDeclaredConstructors();
			foreach (ConstructorInfo constructorInfo in declaredConstructors)
			{
				ParameterInfo[] parameters2 = constructorInfo.GetParameters();
				if (parameters.Length != parameters2.Length)
				{
					continue;
				}
				for (int j = 0; j < parameters2.Length; j++)
				{
					if ((object)parameters2[j].ParameterType != parameters[j])
					{
					}
				}
				return constructorInfo;
			}
			return null;
		}

		public static ConstructorInfo[] GetDeclaredConstructors(this Type type)
		{
			return type.GetConstructors(DeclaredFlags);
		}

		public static MemberInfo[] GetFlattenedMember(this Type type, string memberName)
		{
			List<MemberInfo> list = new List<MemberInfo>();
			while ((object)type != null)
			{
				MemberInfo[] declaredMembers = type.GetDeclaredMembers();
				for (int i = 0; i < declaredMembers.Length; i++)
				{
					if (declaredMembers[i].Name == memberName)
					{
						list.Add(declaredMembers[i]);
					}
				}
				type = type.Resolve().BaseType;
			}
			return list.ToArray();
		}

		public static MethodInfo GetFlattenedMethod(this Type type, string methodName)
		{
			while ((object)type != null)
			{
				MethodInfo[] declaredMethods = type.GetDeclaredMethods();
				for (int i = 0; i < declaredMethods.Length; i++)
				{
					if (declaredMethods[i].Name == methodName)
					{
						return declaredMethods[i];
					}
				}
				type = type.Resolve().BaseType;
			}
			return null;
		}

		public static IEnumerable<MethodInfo> GetFlattenedMethods(this Type type, string methodName)
		{
			while ((object)type != null)
			{
				MethodInfo[] methods = type.GetDeclaredMethods();
				for (int i = 0; i < methods.Length; i++)
				{
					if (methods[i].Name == methodName)
					{
						yield return methods[i];
					}
				}
				type = type.Resolve().BaseType;
			}
		}

		public static PropertyInfo GetFlattenedProperty(this Type type, string propertyName)
		{
			while ((object)type != null)
			{
				PropertyInfo[] declaredProperties = type.GetDeclaredProperties();
				for (int i = 0; i < declaredProperties.Length; i++)
				{
					if (declaredProperties[i].Name == propertyName)
					{
						return declaredProperties[i];
					}
				}
				type = type.Resolve().BaseType;
			}
			return null;
		}

		public static MemberInfo GetDeclaredMember(this Type type, string memberName)
		{
			MemberInfo[] declaredMembers = type.GetDeclaredMembers();
			for (int i = 0; i < declaredMembers.Length; i++)
			{
				if (declaredMembers[i].Name == memberName)
				{
					return declaredMembers[i];
				}
			}
			return null;
		}

		public static MethodInfo[] GetDeclaredMethods(this Type type)
		{
			return type.GetMethods(DeclaredFlags);
		}

		public static PropertyInfo[] GetDeclaredProperties(this Type type)
		{
			return type.GetProperties(DeclaredFlags);
		}

		public static FieldInfo[] GetDeclaredFields(this Type type)
		{
			return type.GetFields(DeclaredFlags);
		}

		public static MemberInfo[] GetDeclaredMembers(this Type type)
		{
			return type.GetMembers(DeclaredFlags);
		}

		public static MemberInfo AsMemberInfo(Type type)
		{
			return type;
		}

		public static bool IsType(MemberInfo member)
		{
			return member is Type;
		}

		public static Type AsType(MemberInfo member)
		{
			return (Type)member;
		}

		public static Type Resolve(this Type type)
		{
			return type;
		}
	}
}
namespace FullSerializer
{
	public static class fsTypeExtensions
	{
		public static string CSharpName(this Type type)
		{
			return type.CSharpName(includeNamespace: false);
		}

		public static string CSharpName(this Type type, bool includeNamespace, bool ensureSafeDeclarationName)
		{
			string text = type.CSharpName(includeNamespace);
			if (ensureSafeDeclarationName)
			{
				text = text.Replace('>', '_').Replace('<', '_').Replace('.', '_');
			}
			return text;
		}

		public static string CSharpName(this Type type, bool includeNamespace)
		{
			if ((object)type == typeof(void))
			{
				return "void";
			}
			if ((object)type == typeof(int))
			{
				return "int";
			}
			if ((object)type == typeof(float))
			{
				return "float";
			}
			if ((object)type == typeof(bool))
			{
				return "bool";
			}
			if ((object)type == typeof(double))
			{
				return "double";
			}
			if ((object)type == typeof(string))
			{
				return "string";
			}
			if (type.IsGenericParameter)
			{
				return type.ToString();
			}
			string text = "";
			IEnumerable<Type> source = type.GetGenericArguments();
			if (type.IsNested)
			{
				text = text + type.DeclaringType.CSharpName() + ".";
				if (type.DeclaringType.GetGenericArguments().Length > 0)
				{
					source = source.Skip(type.DeclaringType.GetGenericArguments().Length);
				}
			}
			if (!source.Any())
			{
				text += type.Name;
			}
			else
			{
				text += type.Name.Substring(0, type.Name.IndexOf('`'));
				text = text + "<" + string.Join(",", source.Select((Type t) => t.CSharpName(includeNamespace)).ToArray()) + ">";
			}
			if (includeNamespace && type.Namespace != null)
			{
				text = type.Namespace + "." + text;
			}
			return text;
		}
	}
}
namespace FullSerializer.Internal
{
	public static class fsVersionManager
	{
		private static readonly Dictionary<Type, fsOption<fsVersionedType>> _cache = new Dictionary<Type, fsOption<fsVersionedType>>();

		public static fsResult GetVersionImportPath(string currentVersion, fsVersionedType targetVersion, out List<fsVersionedType> path)
		{
			path = new List<fsVersionedType>();
			if (!GetVersionImportPathRecursive(path, currentVersion, targetVersion))
			{
				return fsResult.Fail("There is no migration path from \"" + currentVersion + "\" to \"" + targetVersion.VersionString + "\"");
			}
			path.Add(targetVersion);
			return fsResult.Success;
		}

		private static bool GetVersionImportPathRecursive(List<fsVersionedType> path, string currentVersion, fsVersionedType current)
		{
			for (int i = 0; i < current.Ancestors.Length; i++)
			{
				fsVersionedType fsVersionedType2 = current.Ancestors[i];
				if (fsVersionedType2.VersionString == currentVersion || GetVersionImportPathRecursive(path, currentVersion, fsVersionedType2))
				{
					path.Add(fsVersionedType2);
					return true;
				}
			}
			return false;
		}

		public static fsOption<fsVersionedType> GetVersionedType(Type type)
		{
			if (!_cache.TryGetValue(type, out var value))
			{
				fsObjectAttribute attribute = fsPortableReflection.GetAttribute<fsObjectAttribute>(type);
				if (attribute != null && (!string.IsNullOrEmpty(attribute.VersionString) || attribute.PreviousModels != null))
				{
					if (attribute.PreviousModels != null && string.IsNullOrEmpty(attribute.VersionString))
					{
						throw new Exception(string.Concat("fsObject attribute on ", type, " contains a PreviousModels specifier - it must also include a VersionString modifier"));
					}
					fsVersionedType[] array = new fsVersionedType[(attribute.PreviousModels != null) ? attribute.PreviousModels.Length : 0];
					for (int i = 0; i < array.Length; i++)
					{
						fsOption<fsVersionedType> versionedType = GetVersionedType(attribute.PreviousModels[i]);
						if (versionedType.IsEmpty)
						{
							throw new Exception(string.Concat("Unable to create versioned type for ancestor ", versionedType, "; please add an [fsObject(VersionString=\"...\")] attribute"));
						}
						ref fsVersionedType reference = ref array[i];
						reference = versionedType.Value;
					}
					fsVersionedType fsVersionedType2 = default(fsVersionedType);
					fsVersionedType2.Ancestors = array;
					fsVersionedType2.VersionString = attribute.VersionString;
					fsVersionedType2.ModelType = type;
					fsVersionedType fsVersionedType3 = fsVersionedType2;
					VerifyUniqueVersionStrings(fsVersionedType3);
					VerifyConstructors(fsVersionedType3);
					value = fsOption.Just(fsVersionedType3);
				}
				_cache[type] = value;
			}
			return value;
		}

		private static void VerifyConstructors(fsVersionedType type)
		{
			ConstructorInfo[] declaredConstructors = type.ModelType.GetDeclaredConstructors();
			for (int i = 0; i < type.Ancestors.Length; i++)
			{
				Type modelType = type.Ancestors[i].ModelType;
				bool flag = false;
				for (int j = 0; j < declaredConstructors.Length; j++)
				{
					ParameterInfo[] parameters = declaredConstructors[j].GetParameters();
					if (parameters.Length == 1 && (object)parameters[0].ParameterType == modelType)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					throw new fsMissingVersionConstructorException(type.ModelType, modelType);
				}
			}
		}

		private static void VerifyUniqueVersionStrings(fsVersionedType type)
		{
			Dictionary<string, Type> dictionary = new Dictionary<string, Type>();
			Queue<fsVersionedType> queue = new Queue<fsVersionedType>();
			queue.Enqueue(type);
			while (queue.Count > 0)
			{
				fsVersionedType fsVersionedType2 = queue.Dequeue();
				if (dictionary.ContainsKey(fsVersionedType2.VersionString) && (object)dictionary[fsVersionedType2.VersionString] != fsVersionedType2.ModelType)
				{
					throw new fsDuplicateVersionNameException(dictionary[fsVersionedType2.VersionString], fsVersionedType2.ModelType, fsVersionedType2.VersionString);
				}
				dictionary[fsVersionedType2.VersionString] = fsVersionedType2.ModelType;
				fsVersionedType[] ancestors = fsVersionedType2.Ancestors;
				foreach (fsVersionedType item in ancestors)
				{
					queue.Enqueue(item);
				}
			}
		}
	}
	public struct fsVersionedType
	{
		public fsVersionedType[] Ancestors;

		public string VersionString;

		public Type ModelType;

		public object Migrate(object ancestorInstance)
		{
			return Activator.CreateInstance(ModelType, ancestorInstance);
		}

		public override string ToString()
		{
			return string.Concat("fsVersionedType [ModelType=", ModelType, ", VersionString=", VersionString, ", Ancestors.Length=", Ancestors.Length, "]");
		}

		public static bool operator ==(fsVersionedType a, fsVersionedType b)
		{
			return (object)a.ModelType == b.ModelType;
		}

		public static bool operator !=(fsVersionedType a, fsVersionedType b)
		{
			return (object)a.ModelType != b.ModelType;
		}

		public override bool Equals(object obj)
		{
			return obj is fsVersionedType && (object)ModelType == ((fsVersionedType)obj).ModelType;
		}

		public override int GetHashCode()
		{
			return ModelType.GetHashCode();
		}
	}
	public class fsMetaProperty
	{
		private MemberInfo _memberInfo;

		public Type StorageType { get; private set; }

		public Type OverrideConverterType { get; private set; }

		public bool CanRead { get; private set; }

		public bool CanWrite { get; private set; }

		public string JsonName { get; private set; }

		public string MemberName { get; private set; }

		public bool IsPublic { get; private set; }

		public bool IsReadOnly { get; private set; }

		internal fsMetaProperty(fsConfig config, FieldInfo field)
		{
			_memberInfo = field;
			StorageType = field.FieldType;
			MemberName = field.Name;
			IsPublic = field.IsPublic;
			IsReadOnly = field.IsInitOnly;
			CanRead = true;
			CanWrite = true;
			CommonInitialize(config);
		}

		internal fsMetaProperty(fsConfig config, PropertyInfo property)
		{
			_memberInfo = property;
			StorageType = property.PropertyType;
			MemberName = property.Name;
			IsPublic = (object)property.GetGetMethod() != null && property.GetGetMethod().IsPublic && (object)property.GetSetMethod() != null && property.GetSetMethod().IsPublic;
			IsReadOnly = false;
			CanRead = property.CanRead;
			CanWrite = property.CanWrite;
			CommonInitialize(config);
		}

		private void CommonInitialize(fsConfig config)
		{
			fsPropertyAttribute attribute = fsPortableReflection.GetAttribute<fsPropertyAttribute>(_memberInfo);
			if (attribute != null)
			{
				JsonName = attribute.Name;
				OverrideConverterType = attribute.Converter;
			}
			if (string.IsNullOrEmpty(JsonName))
			{
				JsonName = config.GetJsonNameFromMemberName(MemberName, _memberInfo);
			}
		}

		public void Write(object context, object value)
		{
			FieldInfo fieldInfo = _memberInfo as FieldInfo;
			PropertyInfo propertyInfo = _memberInfo as PropertyInfo;
			if ((object)fieldInfo != null)
			{
				fieldInfo.SetValue(context, value);
				return;
			}
			propertyInfo?.GetSetMethod(nonPublic: true)?.Invoke(context, new object[1] { value });
		}

		public object Read(object context)
		{
			if (_memberInfo is PropertyInfo)
			{
				return ((PropertyInfo)_memberInfo).GetValue(context, new object[0]);
			}
			return ((FieldInfo)_memberInfo).GetValue(context);
		}
	}
}
namespace FullSerializer
{
	public class fsMetaType
	{
		private static Dictionary<fsConfig, Dictionary<Type, fsMetaType>> _configMetaTypes = new Dictionary<fsConfig, Dictionary<Type, fsMetaType>>();

		public Type ReflectedType;

		private bool _hasEmittedAotData;

		private bool? _hasDefaultConstructorCache;

		private bool _isDefaultConstructorPublic;

		public fsMetaProperty[] Properties { get; private set; }

		public bool HasDefaultConstructor
		{
			get
			{
				if (!_hasDefaultConstructorCache.HasValue)
				{
					if (ReflectedType.Resolve().IsArray)
					{
						_hasDefaultConstructorCache = true;
						_isDefaultConstructorPublic = true;
					}
					else if (ReflectedType.Resolve().IsValueType)
					{
						_hasDefaultConstructorCache = true;
						_isDefaultConstructorPublic = true;
					}
					else
					{
						ConstructorInfo declaredConstructor = ReflectedType.GetDeclaredConstructor(fsPortableReflection.EmptyTypes);
						_hasDefaultConstructorCache = (object)declaredConstructor != null;
						if ((object)declaredConstructor != null)
						{
							_isDefaultConstructorPublic = declaredConstructor.IsPublic;
						}
					}
				}
				return _hasDefaultConstructorCache.Value;
			}
		}

		private fsMetaType(fsConfig config, Type reflectedType)
		{
			ReflectedType = reflectedType;
			List<fsMetaProperty> list = new List<fsMetaProperty>();
			CollectProperties(config, list, reflectedType);
			Properties = list.ToArray();
		}

		public static fsMetaType Get(fsConfig config, Type type)
		{
			if (!_configMetaTypes.TryGetValue(config, out var value))
			{
				Dictionary<Type, fsMetaType> dictionary = new Dictionary<Type, fsMetaType>();
				_configMetaTypes[config] = dictionary;
				value = dictionary;
			}
			if (!value.TryGetValue(type, out var value2))
			{
				value2 = (value[type] = new fsMetaType(config, type));
			}
			return value2;
		}

		public static void ClearCache()
		{
			_configMetaTypes = new Dictionary<fsConfig, Dictionary<Type, fsMetaType>>();
		}

		private static void CollectProperties(fsConfig config, List<fsMetaProperty> properties, Type reflectedType)
		{
			bool flag = config.DefaultMemberSerialization == fsMemberSerialization.OptIn;
			bool flag2 = config.DefaultMemberSerialization == fsMemberSerialization.OptOut;
			fsObjectAttribute attribute = fsPortableReflection.GetAttribute<fsObjectAttribute>(reflectedType);
			if (attribute != null)
			{
				flag = attribute.MemberSerialization == fsMemberSerialization.OptIn;
				flag2 = attribute.MemberSerialization == fsMemberSerialization.OptOut;
			}
			MemberInfo[] declaredMembers = reflectedType.GetDeclaredMembers();
			MemberInfo[] array = declaredMembers;
			foreach (MemberInfo member in array)
			{
				if (config.IgnoreSerializeAttributes.Any((Type t) => fsPortableReflection.HasAttribute(member, t)))
				{
					continue;
				}
				PropertyInfo propertyInfo = member as PropertyInfo;
				FieldInfo fieldInfo = member as FieldInfo;
				if (((object)propertyInfo == null && (object)fieldInfo == null) || ((object)propertyInfo != null && !config.EnablePropertySerialization) || (flag && !config.SerializeAttributes.Any((Type t) => fsPortableReflection.HasAttribute(member, t))) || (flag2 && config.IgnoreSerializeAttributes.Any((Type t) => fsPortableReflection.HasAttribute(member, t))))
				{
					continue;
				}
				if ((object)propertyInfo != null)
				{
					if (CanSerializeProperty(config, propertyInfo, declaredMembers, flag2))
					{
						properties.Add(new fsMetaProperty(config, propertyInfo));
					}
				}
				else if ((object)fieldInfo != null && CanSerializeField(config, fieldInfo, flag2))
				{
					properties.Add(new fsMetaProperty(config, fieldInfo));
				}
			}
			if ((object)reflectedType.Resolve().BaseType != null)
			{
				CollectProperties(config, properties, reflectedType.Resolve().BaseType);
			}
		}

		private static bool IsAutoProperty(PropertyInfo property, MemberInfo[] members)
		{
			return property.CanWrite && property.CanRead && fsPortableReflection.HasAttribute(property.GetGetMethod(), typeof(CompilerGeneratedAttribute), shouldCache: false);
		}

		private static bool CanSerializeProperty(fsConfig config, PropertyInfo property, MemberInfo[] members, bool annotationFreeValue)
		{
			if (typeof(Delegate).IsAssignableFrom(property.PropertyType))
			{
				return false;
			}
			MethodInfo getMethod = property.GetGetMethod(nonPublic: false);
			MethodInfo setMethod = property.GetSetMethod(nonPublic: false);
			if (((object)getMethod != null && getMethod.IsStatic) || ((object)setMethod != null && setMethod.IsStatic))
			{
				return false;
			}
			if (property.GetIndexParameters().Length > 0)
			{
				return false;
			}
			if (config.SerializeAttributes.Any((Type t) => fsPortableReflection.HasAttribute(property, t)))
			{
				return true;
			}
			if (!property.CanRead || !property.CanWrite)
			{
				return false;
			}
			if ((object)getMethod != null && (config.SerializeNonPublicSetProperties || (object)setMethod != null) && (config.SerializeNonAutoProperties || IsAutoProperty(property, members)))
			{
				return true;
			}
			return annotationFreeValue;
		}

		private static bool CanSerializeField(fsConfig config, FieldInfo field, bool annotationFreeValue)
		{
			if (typeof(Delegate).IsAssignableFrom(field.FieldType))
			{
				return false;
			}
			if (field.IsDefined(typeof(CompilerGeneratedAttribute), inherit: false))
			{
				return false;
			}
			if (field.IsStatic)
			{
				return false;
			}
			if (config.SerializeAttributes.Any((Type t) => fsPortableReflection.HasAttribute(field, t)))
			{
				return true;
			}
			if (!annotationFreeValue && !field.IsPublic)
			{
				return false;
			}
			return true;
		}

		public bool EmitAotData()
		{
			if (!_hasEmittedAotData)
			{
				_hasEmittedAotData = true;
				for (int i = 0; i < Properties.Length; i++)
				{
					if (!Properties[i].IsPublic)
					{
						return false;
					}
					if (Properties[i].IsReadOnly)
					{
						return false;
					}
				}
				if (!HasDefaultConstructor)
				{
					return false;
				}
				fsAotCompilationManager.AddAotCompilation(ReflectedType, Properties, _isDefaultConstructorPublic);
				return true;
			}
			return false;
		}

		public object CreateInstance()
		{
			if (ReflectedType.Resolve().IsInterface || ReflectedType.Resolve().IsAbstract)
			{
				throw new Exception("Cannot create an instance of an interface or abstract type for " + ReflectedType);
			}
			if (typeof(ScriptableObject).IsAssignableFrom(ReflectedType))
			{
				return ScriptableObject.CreateInstance(ReflectedType);
			}
			if ((object)typeof(string) == ReflectedType)
			{
				return string.Empty;
			}
			if (!HasDefaultConstructor)
			{
				return FormatterServices.GetSafeUninitializedObject(ReflectedType);
			}
			if (ReflectedType.Resolve().IsArray)
			{
				return Array.CreateInstance(ReflectedType.GetElementType(), 0);
			}
			try
			{
				return Activator.CreateInstance(ReflectedType, nonPublic: true);
			}
			catch (MissingMethodException innerException)
			{
				throw new InvalidOperationException(string.Concat("Unable to create instance of ", ReflectedType, "; there is no default constructor"), innerException);
			}
			catch (TargetInvocationException innerException2)
			{
				throw new InvalidOperationException(string.Concat("Constructor of ", ReflectedType, " threw an exception when creating an instance"), innerException2);
			}
			catch (MemberAccessException innerException3)
			{
				throw new InvalidOperationException("Unable to access constructor of " + ReflectedType, innerException3);
			}
		}
	}
}
namespace FullSerializer.Internal
{
	public static class fsReflectionUtility
	{
		public static Type GetInterface(Type type, Type interfaceType)
		{
			if (interfaceType.Resolve().IsGenericType && !interfaceType.Resolve().IsGenericTypeDefinition)
			{
				throw new ArgumentException("GetInterface requires that if the interface type is generic, then it must be the generic type definition, not a specific generic type instantiation");
			}
			while ((object)type != null)
			{
				Type[] interfaces = type.GetInterfaces();
				foreach (Type type2 in interfaces)
				{
					if (type2.Resolve().IsGenericType)
					{
						if ((object)interfaceType == type2.GetGenericTypeDefinition())
						{
							return type2;
						}
					}
					else if ((object)interfaceType == type2)
					{
						return type2;
					}
				}
				type = type.Resolve().BaseType;
			}
			return null;
		}
	}
	public static class fsTypeCache
	{
		private static Dictionary<string, Type> _cachedTypes;

		private static Dictionary<string, Assembly> _assembliesByName;

		private static List<Assembly> _assembliesByIndex;

		static fsTypeCache()
		{
			_cachedTypes = new Dictionary<string, Type>();
			_assembliesByName = new Dictionary<string, Assembly>();
			_assembliesByIndex = new List<Assembly>();
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				_assembliesByName[assembly.FullName] = assembly;
				_assembliesByIndex.Add(assembly);
			}
			_cachedTypes = new Dictionary<string, Type>();
			AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoaded;
		}

		private static void OnAssemblyLoaded(object sender, AssemblyLoadEventArgs args)
		{
			_assembliesByName[args.LoadedAssembly.FullName] = args.LoadedAssembly;
			_assembliesByIndex.Add(args.LoadedAssembly);
			_cachedTypes = new Dictionary<string, Type>();
		}

		private static bool TryDirectTypeLookup(string assemblyName, string typeName, out Type type)
		{
			if (assemblyName != null && _assembliesByName.TryGetValue(assemblyName, out var value))
			{
				type = value.GetType(typeName, throwOnError: false);
				return (object)type != null;
			}
			type = null;
			return false;
		}

		private static bool TryIndirectTypeLookup(string typeName, out Type type)
		{
			for (int i = 0; i < _assembliesByIndex.Count; i++)
			{
				Assembly assembly = _assembliesByIndex[i];
				type = assembly.GetType(typeName);
				if ((object)type != null)
				{
					return true;
				}
			}
			for (int i = 0; i < _assembliesByIndex.Count; i++)
			{
				Assembly assembly2 = _assembliesByIndex[i];
				Type[] types = assembly2.GetTypes();
				foreach (Type type2 in types)
				{
					if (type2.FullName == typeName)
					{
						type = type2;
						return true;
					}
				}
			}
			type = null;
			return false;
		}

		public static void Reset()
		{
			_cachedTypes = new Dictionary<string, Type>();
		}

		public static Type GetType(string name)
		{
			return GetType(name, null);
		}

		public static Type GetType(string name, string assemblyHint)
		{
			if (string.IsNullOrEmpty(name))
			{
				return null;
			}
			if (!_cachedTypes.TryGetValue(name, out var value))
			{
				if (TryDirectTypeLookup(assemblyHint, name, out value) || !TryIndirectTypeLookup(name, out value))
				{
				}
				_cachedTypes[name] = value;
			}
			return value;
		}
	}
}
namespace FullSerializer
{
	public class fsAotCompilationManager
	{
		private struct AotCompilation
		{
			public Type Type;

			public fsMetaProperty[] Members;

			public bool IsConstructorPublic;
		}

		private static Dictionary<Type, string> _computedAotCompilations = new Dictionary<Type, string>();

		private static List<AotCompilation> _uncomputedAotCompilations = new List<AotCompilation>();

		public static Dictionary<Type, string> AvailableAotCompilations
		{
			get
			{
				for (int i = 0; i < _uncomputedAotCompilations.Count; i++)
				{
					AotCompilation aotCompilation = _uncomputedAotCompilations[i];
					_computedAotCompilations[aotCompilation.Type] = GenerateDirectConverterForTypeInCSharp(aotCompilation.Type, aotCompilation.Members, aotCompilation.IsConstructorPublic);
				}
				_uncomputedAotCompilations.Clear();
				return _computedAotCompilations;
			}
		}

		public static bool TryToPerformAotCompilation(fsConfig config, Type type, out string aotCompiledClassInCSharp)
		{
			if (fsMetaType.Get(config, type).EmitAotData())
			{
				aotCompiledClassInCSharp = AvailableAotCompilations[type];
				return true;
			}
			aotCompiledClassInCSharp = null;
			return false;
		}

		public static void AddAotCompilation(Type type, fsMetaProperty[] members, bool isConstructorPublic)
		{
			_uncomputedAotCompilations.Add(new AotCompilation
			{
				Type = type,
				Members = members,
				IsConstructorPublic = isConstructorPublic
			});
		}

		private static string GetConverterString(fsMetaProperty member)
		{
			if ((object)member.OverrideConverterType == null)
			{
				return "null";
			}
			return $"typeof({member.OverrideConverterType.CSharpName(includeNamespace: true)})";
		}

		private static string GenerateDirectConverterForTypeInCSharp(Type type, fsMetaProperty[] members, bool isConstructorPublic)
		{
			StringBuilder stringBuilder = new StringBuilder();
			string text = type.CSharpName(includeNamespace: true);
			string text2 = type.CSharpName(includeNamespace: true, ensureSafeDeclarationName: true);
			stringBuilder.AppendLine("using System;");
			stringBuilder.AppendLine("using System.Collections.Generic;");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("namespace FullSerializer {");
			stringBuilder.AppendLine("    partial class fsConverterRegistrar {");
			stringBuilder.AppendLine("        public static Speedup." + text2 + "_DirectConverter Register_" + text2 + ";");
			stringBuilder.AppendLine("    }");
			stringBuilder.AppendLine("}");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("namespace FullSerializer.Speedup {");
			stringBuilder.AppendLine("    public class " + text2 + "_DirectConverter : fsDirectConverter<" + text + "> {");
			stringBuilder.AppendLine("        protected override fsResult DoSerialize(" + text + " model, Dictionary<string, fsData> serialized) {");
			stringBuilder.AppendLine("            var result = fsResult.Success;");
			stringBuilder.AppendLine();
			foreach (fsMetaProperty fsMetaProperty in members)
			{
				stringBuilder.AppendLine("            result += SerializeMember(serialized, " + GetConverterString(fsMetaProperty) + ", \"" + fsMetaProperty.JsonName + "\", model." + fsMetaProperty.MemberName + ");");
			}
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("            return result;");
			stringBuilder.AppendLine("        }");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("        protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref " + text + " model) {");
			stringBuilder.AppendLine("            var result = fsResult.Success;");
			stringBuilder.AppendLine();
			for (int j = 0; j < members.Length; j++)
			{
				fsMetaProperty fsMetaProperty2 = members[j];
				stringBuilder.AppendLine("            var t" + j + " = model." + fsMetaProperty2.MemberName + ";");
				stringBuilder.AppendLine("            result += DeserializeMember(data, " + GetConverterString(fsMetaProperty2) + ", \"" + fsMetaProperty2.JsonName + "\", out t" + j + ");");
				stringBuilder.AppendLine("            model." + fsMetaProperty2.MemberName + " = t" + j + ";");
				stringBuilder.AppendLine();
			}
			stringBuilder.AppendLine("            return result;");
			stringBuilder.AppendLine("        }");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("        public override object CreateInstance(fsData data, Type storageType) {");
			if (isConstructorPublic)
			{
				stringBuilder.AppendLine("            return new " + text + "();");
			}
			else
			{
				stringBuilder.AppendLine("            return Activator.CreateInstance(typeof(" + text + "), /*nonPublic:*/true);");
			}
			stringBuilder.AppendLine("        }");
			stringBuilder.AppendLine("    }");
			stringBuilder.AppendLine("}");
			return stringBuilder.ToString();
		}
	}
	public abstract class fsBaseConverter
	{
		public fsSerializer Serializer;

		public virtual object CreateInstance(fsData data, Type storageType)
		{
			if (RequestCycleSupport(storageType))
			{
				throw new InvalidOperationException(string.Concat("Please override CreateInstance for ", GetType().FullName, "; the object graph for ", storageType, " can contain potentially contain cycles, so separated instance creation is needed"));
			}
			return storageType;
		}

		public virtual bool RequestCycleSupport(Type storageType)
		{
			if ((object)storageType == typeof(string))
			{
				return false;
			}
			return storageType.Resolve().IsClass || storageType.Resolve().IsInterface;
		}

		public virtual bool RequestInheritanceSupport(Type storageType)
		{
			return !storageType.Resolve().IsSealed;
		}

		public abstract fsResult TrySerialize(object instance, out fsData serialized, Type storageType);

		public abstract fsResult TryDeserialize(fsData data, ref object instance, Type storageType);

		protected fsResult FailExpectedType(fsData data, params fsDataType[] types)
		{
			return fsResult.Fail(string.Concat(GetType().Name, " expected one of ", string.Join(", ", types.Select((fsDataType t) => t.ToString()).ToArray()), " but got ", data.Type, " in ", data));
		}

		protected fsResult CheckType(fsData data, fsDataType type)
		{
			if (data.Type != type)
			{
				return fsResult.Fail(string.Concat(GetType().Name, " expected ", type, " but got ", data.Type, " in ", data));
			}
			return fsResult.Success;
		}

		protected fsResult CheckKey(fsData data, string key, out fsData subitem)
		{
			return CheckKey(data.AsDictionary, key, out subitem);
		}

		protected fsResult CheckKey(Dictionary<string, fsData> data, string key, out fsData subitem)
		{
			if (!data.TryGetValue(key, out subitem))
			{
				return fsResult.Fail(GetType().Name + " requires a <" + key + "> key in the data " + data);
			}
			return fsResult.Success;
		}

		protected fsResult SerializeMember<T>(Dictionary<string, fsData> data, Type overrideConverterType, string name, T value)
		{
			fsData data2;
			fsResult result = Serializer.TrySerialize(typeof(T), overrideConverterType, value, out data2);
			if (result.Succeeded)
			{
				data[name] = data2;
			}
			return result;
		}

		protected fsResult DeserializeMember<T>(Dictionary<string, fsData> data, Type overrideConverterType, string name, out T value)
		{
			if (!data.TryGetValue(name, out var value2))
			{
				value = default(T);
				return fsResult.Fail("Unable to find member \"" + name + "\"");
			}
			object result = null;
			fsResult result2 = Serializer.TryDeserialize(value2, typeof(T), overrideConverterType, ref result);
			value = (T)result;
			return result2;
		}
	}
	public static class fsGlobalConfig
	{
		public static bool IsCaseSensitive = true;

		public static bool AllowInternalExceptions = true;

		public static string InternalFieldPrefix = "$";
	}
	public class fsConfig
	{
		public Type[] SerializeAttributes = new Type[2]
		{
			typeof(SerializeField),
			typeof(fsPropertyAttribute)
		};

		public Type[] IgnoreSerializeAttributes = new Type[2]
		{
			typeof(NonSerializedAttribute),
			typeof(fsIgnoreAttribute)
		};

		public fsMemberSerialization DefaultMemberSerialization = fsMemberSerialization.Default;

		public Func<string, MemberInfo, string> GetJsonNameFromMemberName = (string name, MemberInfo info) => name;

		public bool EnablePropertySerialization = true;

		public bool SerializeNonAutoProperties = false;

		public bool SerializeNonPublicSetProperties = true;

		public string CustomDateTimeFormatString = null;

		public bool Serialize64BitIntegerAsString = false;

		public bool SerializeEnumsAsInteger = false;
	}
	public sealed class fsContext
	{
		private readonly Dictionary<Type, object> _contextObjects = new Dictionary<Type, object>();

		public void Reset()
		{
			_contextObjects.Clear();
		}

		public void Set<T>(T obj)
		{
			_contextObjects[typeof(T)] = obj;
		}

		public bool Has<T>()
		{
			return _contextObjects.ContainsKey(typeof(T));
		}

		public T Get<T>()
		{
			if (_contextObjects.TryGetValue(typeof(T), out var value))
			{
				return (T)value;
			}
			throw new InvalidOperationException("There is no context object of type " + typeof(T));
		}
	}
	public abstract class fsConverter : fsBaseConverter
	{
		public abstract bool CanProcess(Type type);
	}
	public enum fsDataType
	{
		Array,
		Object,
		Double,
		Int64,
		Boolean,
		String,
		Null
	}
	public sealed class fsData
	{
		private object _value;

		public static readonly fsData True = new fsData(boolean: true);

		public static readonly fsData False = new fsData(boolean: false);

		public static readonly fsData Null = new fsData();

		public fsDataType Type
		{
			get
			{
				if (_value == null)
				{
					return fsDataType.Null;
				}
				if (_value is double)
				{
					return fsDataType.Double;
				}
				if (_value is long)
				{
					return fsDataType.Int64;
				}
				if (_value is bool)
				{
					return fsDataType.Boolean;
				}
				if (_value is string)
				{
					return fsDataType.String;
				}
				if (_value is Dictionary<string, fsData>)
				{
					return fsDataType.Object;
				}
				if (_value is List<fsData>)
				{
					return fsDataType.Array;
				}
				throw new InvalidOperationException("unknown JSON data type");
			}
		}

		public bool IsNull => _value == null;

		public bool IsDouble => _value is double;

		public bool IsInt64 => _value is long;

		public bool IsBool => _value is bool;

		public bool IsString => _value is string;

		public bool IsDictionary => _value is Dictionary<string, fsData>;

		public bool IsList => _value is List<fsData>;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public double AsDouble => Cast<double>();

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public long AsInt64 => Cast<long>();

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public bool AsBool => Cast<bool>();

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public string AsString => Cast<string>();

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public Dictionary<string, fsData> AsDictionary => Cast<Dictionary<string, fsData>>();

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public List<fsData> AsList => Cast<List<fsData>>();

		public fsData()
		{
			_value = null;
		}

		public fsData(bool boolean)
		{
			_value = boolean;
		}

		public fsData(double f)
		{
			_value = f;
		}

		public fsData(long i)
		{
			_value = i;
		}

		public fsData(string str)
		{
			_value = str;
		}

		public fsData(Dictionary<string, fsData> dict)
		{
			_value = dict;
		}

		public fsData(List<fsData> list)
		{
			_value = list;
		}

		public static fsData CreateDictionary()
		{
			return new fsData(new Dictionary<string, fsData>((!fsGlobalConfig.IsCaseSensitive) ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal));
		}

		public static fsData CreateList()
		{
			return new fsData(new List<fsData>());
		}

		public static fsData CreateList(int capacity)
		{
			return new fsData(new List<fsData>(capacity));
		}

		internal void BecomeDictionary()
		{
			_value = new Dictionary<string, fsData>();
		}

		internal fsData Clone()
		{
			fsData fsData2 = new fsData();
			fsData2._value = _value;
			return fsData2;
		}

		private T Cast<T>()
		{
			if (_value is T)
			{
				return (T)_value;
			}
			throw new InvalidCastException(string.Concat("Unable to cast <", this, "> (with type = ", _value.GetType(), ") to type ", typeof(T)));
		}

		public override string ToString()
		{
			return fsJsonPrinter.CompressedJson(this);
		}

		public override bool Equals(object obj)
		{
			return Equals(obj as fsData);
		}

		public bool Equals(fsData other)
		{
			if (other == null || Type != other.Type)
			{
				return false;
			}
			switch (Type)
			{
			case fsDataType.Null:
				return true;
			case fsDataType.Double:
				return AsDouble == other.AsDouble || Math.Abs(AsDouble - other.AsDouble) < double.Epsilon;
			case fsDataType.Int64:
				return AsInt64 == other.AsInt64;
			case fsDataType.Boolean:
				return AsBool == other.AsBool;
			case fsDataType.String:
				return AsString == other.AsString;
			case fsDataType.Array:
			{
				List<fsData> asList = AsList;
				List<fsData> asList2 = other.AsList;
				if (asList.Count != asList2.Count)
				{
					return false;
				}
				for (int i = 0; i < asList.Count; i++)
				{
					if (!asList[i].Equals(asList2[i]))
					{
						return false;
					}
				}
				return true;
			}
			case fsDataType.Object:
			{
				Dictionary<string, fsData> asDictionary = AsDictionary;
				Dictionary<string, fsData> asDictionary2 = other.AsDictionary;
				if (asDictionary.Count != asDictionary2.Count)
				{
					return false;
				}
				foreach (string key in asDictionary.Keys)
				{
					if (!asDictionary2.ContainsKey(key))
					{
						return false;
					}
					if (!asDictionary[key].Equals(asDictionary2[key]))
					{
						return false;
					}
				}
				return true;
			}
			default:
				throw new Exception("Unknown data type");
			}
		}

		public static bool operator ==(fsData a, fsData b)
		{
			if (object.ReferenceEquals(a, b))
			{
				return true;
			}
			if ((object)a == null || (object)b == null)
			{
				return false;
			}
			if (a.IsDouble && b.IsDouble)
			{
				return Math.Abs(a.AsDouble - b.AsDouble) < double.Epsilon;
			}
			return a.Equals(b);
		}

		public static bool operator !=(fsData a, fsData b)
		{
			return !(a == b);
		}

		public override int GetHashCode()
		{
			return _value.GetHashCode();
		}
	}
	public abstract class fsDirectConverter : fsBaseConverter
	{
		public abstract Type ModelType { get; }
	}
	public abstract class fsDirectConverter<TModel> : fsDirectConverter
	{
		public override Type ModelType => typeof(TModel);

		public sealed override fsResult TrySerialize(object instance, out fsData serialized, Type storageType)
		{
			Dictionary<string, fsData> dictionary = new Dictionary<string, fsData>();
			fsResult result = DoSerialize((TModel)instance, dictionary);
			serialized = new fsData(dictionary);
			return result;
		}

		public sealed override fsResult TryDeserialize(fsData data, ref object instance, Type storageType)
		{
			fsResult success = fsResult.Success;
			fsResult fsResult2 = (success += CheckType(data, fsDataType.Object));
			if (fsResult2.Failed)
			{
				return success;
			}
			TModel model = (TModel)instance;
			success += DoDeserialize(data.AsDictionary, ref model);
			instance = model;
			return success;
		}

		protected abstract fsResult DoSerialize(TModel model, Dictionary<string, fsData> serialized);

		protected abstract fsResult DoDeserialize(Dictionary<string, fsData> data, ref TModel model);
	}
	public sealed class fsMissingVersionConstructorException : Exception
	{
		public fsMissingVersionConstructorException(Type versionedType, Type constructorType)
			: base(string.Concat(versionedType, " is missing a constructor for previous model type ", constructorType))
		{
		}
	}
	public sealed class fsDuplicateVersionNameException : Exception
	{
		public fsDuplicateVersionNameException(Type typeA, Type typeB, string version)
			: base(string.Concat(typeA, " and ", typeB, " have the same version string (", version, "); please change one of them."))
		{
		}
	}
	public interface fsISerializationCallbacks
	{
		void OnBeforeSerialize(Type storageType);

		void OnAfterSerialize(Type storageType, ref fsData data);

		void OnBeforeDeserialize(Type storageType, ref fsData data);

		void OnAfterDeserialize(Type storageType);
	}
}
namespace FullSerializer.Internal
{
	public class fsSerializationCallbackProcessor : fsObjectProcessor
	{
		public override bool CanProcess(Type type)
		{
			return typeof(fsISerializationCallbacks).IsAssignableFrom(type);
		}

		public override void OnBeforeSerialize(Type storageType, object instance)
		{
			if (instance != null)
			{
				((fsISerializationCallbacks)instance).OnBeforeSerialize(storageType);
			}
		}

		public override void OnAfterSerialize(Type storageType, object instance, ref fsData data)
		{
			if (instance != null)
			{
				((fsISerializationCallbacks)instance).OnAfterSerialize(storageType, ref data);
			}
		}

		public override void OnBeforeDeserializeAfterInstanceCreation(Type storageType, object instance, ref fsData data)
		{
			if (!(instance is fsISerializationCallbacks))
			{
				throw new InvalidCastException(string.Concat("Please ensure the converter for ", storageType, " actually returns an instance of it, not an instance of ", instance.GetType()));