Decompiled source of AtlyssTools v1.0.5

bin/AtlyssTools.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
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 System.Security;
using System.Security.Permissions;
using AtlyssTools.Commands;
using AtlyssTools.Registries;
using AtlyssTools.Utility;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("AtlyssTools")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.4.0")]
[assembly: AssemblyInformationalVersion("1.0.4+40c9d29d52ba3d0440edac5d8309b79458eb2017")]
[assembly: AssemblyProduct("AtlyssTools")]
[assembly: AssemblyTitle("AtlyssTools")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.4.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace AtlyssTools
{
	public class AtlyssToolsLoader
	{
		public class AtlyssLoaderStateManager : LoaderStateManager
		{
			public void PreLibraryInit()
			{
				foreach (AtlyssToolsLoaderModInfo value in Instance.ModInfos.Values)
				{
					foreach (Action item in value.OnPreLibraryInit)
					{
						item?.Invoke();
					}
				}
			}

			public void PostLibraryInit()
			{
				foreach (AtlyssToolsLoaderModInfo value in Instance.ModInfos.Values)
				{
					foreach (Action item in value.OnPostLibraryInit)
					{
						item?.Invoke();
					}
				}
			}

			public void PreCacheInit()
			{
				Instance.LoadAllJsonAssets();
				foreach (AtlyssToolsLoaderModInfo value in Instance.ModInfos.Values)
				{
					foreach (Action item in value.OnPreCacheInit)
					{
						item?.Invoke();
					}
				}
			}

			public void PostCacheInit()
			{
				foreach (AtlyssToolsLoaderModInfo value in Instance.ModInfos.Values)
				{
					foreach (Action item in value.OnPostCacheInit)
					{
						item?.Invoke();
					}
				}
			}
		}

		private static AtlyssToolsLoader _instance;

		private readonly List<IAttributeRegisterableManager> _attributeManagers = new List<IAttributeRegisterableManager>();

		private readonly Dictionary<Type, BaseScriptablesManager> _managers;

		private readonly LoaderStateMachine _stateMachine = new LoaderStateMachine();

		public readonly Dictionary<string, AtlyssToolsLoaderModInfo> ModInfos = new Dictionary<string, AtlyssToolsLoaderModInfo>();

		public LoaderStateMachine.LoadState State
		{
			get
			{
				return _stateMachine.State;
			}
			set
			{
				_stateMachine.SetState(value);
			}
		}

		public static AtlyssToolsLoader Instance => _instance ?? (_instance = new AtlyssToolsLoader());

		private AtlyssToolsLoader()
		{
			_managers = new Dictionary<Type, BaseScriptablesManager>();
			RegisterManagers();
			_stateMachine.RegisterManager(new AtlyssLoaderStateManager());
		}

		public void RegisterManagers()
		{
			List<BaseScriptablesManager> list = new List<BaseScriptablesManager>(25)
			{
				StatusConditionManager.Instance,
				SceneTransferConditionManager.Instance,
				PolymorphConditionManager.Instance,
				ChestpieceManager.Instance,
				ArmorDyeManager.Instance,
				CapeManager.Instance,
				ClassTomeManager.Instance,
				HelmManager.Instance,
				LeggingsManager.Instance,
				RingManager.Instance,
				ShieldManager.Instance,
				SkillScrollManager.Instance,
				StatusConsumableManager.Instance,
				TradeItemManager.Instance,
				WeaponManager.Instance,
				CreepManager.Instance,
				QuestManager.Instance,
				PlayerRaceManager.Instance,
				CombatElementManager.Instance,
				StatModifierManager.Instance,
				PlayerBaseClassManager.Instance,
				SkillManager.Instance,
				ArmorRenderManager.Instance,
				ShopkeepManager.Instance,
				CastEffectCollectionManager.Instance
			};
			foreach (BaseScriptablesManager item in list)
			{
				_managers.Add(item.GetObjectType(), item);
				_stateMachine.RegisterManager(item.GetStateManager());
			}
			_attributeManagers.Add(new CommandManager());
			_attributeManagers.Add(new ChatProcessorManager());
		}

		public BaseScriptablesManager GetManager(Type type)
		{
			if (_managers.TryGetValue(type, out var value))
			{
				return value;
			}
			return null;
		}

		private void FindAttributeLoaded(Assembly assembly)
		{
			Type[] types = assembly.GetTypes();
			foreach (Type type in types)
			{
				if (type.IsAbstract || type.IsInterface)
				{
					continue;
				}
				foreach (IAttributeRegisterableManager attributeManager in _attributeManagers)
				{
					if (attributeManager.CanRegister(type))
					{
						attributeManager.Register(type, assembly.GetName().Name);
					}
				}
			}
		}

		public static void LoadPlugin(string modName, string modPath, Assembly assembly)
		{
			modName = modName.ToLower();
			if (assembly != null)
			{
				Instance.FindAttributeLoaded(assembly);
			}
			AtlyssToolsLoaderModInfo atlyssToolsLoaderModInfo;
			if (Instance.ModInfos.ContainsKey(modName))
			{
				atlyssToolsLoaderModInfo = Instance.ModInfos[modName];
			}
			else
			{
				atlyssToolsLoaderModInfo = new AtlyssToolsLoaderModInfo
				{
					ModId = modName,
					ModPath = modPath
				};
				Instance.ModInfos.Add(modName, atlyssToolsLoaderModInfo);
			}
			atlyssToolsLoaderModInfo.Initialize();
			if (!Directory.Exists(modPath + "/Assets"))
			{
				Plugin.Logger.LogError((object)("Mod " + modName + " does not have an Assets folder"));
			}
			atlyssToolsLoaderModInfo.LoadAssetBundles();
			Plugin.Logger.LogInfo((object)("Loaded AtlyssTools mod assets for " + modName));
		}

		public static void LoadPlugin(string modName, string modPath)
		{
			LoadPlugin(modName, modPath, Assembly.GetCallingAssembly());
		}

		public static void UnloadMod(string modName)
		{
			if (Instance.ModInfos.ContainsKey(modName))
			{
				Instance.ModInfos[modName].Dispose();
				Instance.ModInfos.Remove(modName);
			}
		}

		public static List<T> GetScriptableObjects<T>() where T : ScriptableObject
		{
			List<T> list = new List<T>();
			foreach (AtlyssToolsLoaderModInfo value in Instance.ModInfos.Values)
			{
				list.AddRange(value.GetModScriptableObjects<T>());
			}
			return list;
		}

		public static List<T> GetScriptableObjects<T>(string modName) where T : ScriptableObject
		{
			if (!Instance.ModInfos.ContainsKey(modName))
			{
				return null;
			}
			return Instance.ModInfos[modName].GetModScriptableObjects<T>();
		}

		public static Object LoadAsset(string assetName, Type type)
		{
			if (string.IsNullOrEmpty(assetName))
			{
				return null;
			}
			assetName = assetName.Replace("\\", "/");
			if (assetName.Contains(":"))
			{
				string[] array = assetName.Split(new char[1] { ':' });
				if (array.Length != 2)
				{
					Plugin.Logger.LogError((object)("Failed to load " + assetName + " of type " + type.Name + " Invalid format"));
					return null;
				}
				Object val = Instance.ModInfos[array[0].ToLower()].LoadModAsset(array[1], type);
				if (val != (Object)null)
				{
					return val;
				}
				Plugin.Logger.LogError((object)("Failed to load " + assetName + " from " + array[0] + " of type " + type.Name + ". File not found or invalid"));
				return null;
			}
			foreach (AtlyssToolsLoaderModInfo value in Instance.ModInfos.Values)
			{
				Object val2 = value.LoadModAsset(assetName, type);
				if (val2 != (Object)null)
				{
					return val2;
				}
			}
			Object val3 = Resources.Load(assetName, type);
			if (val3 != (Object)null)
			{
				return val3;
			}
			Plugin.Logger.LogError((object)("Failed to load " + assetName + " of type " + type.Name + ". File not found or invalid"));
			return null;
		}

		public static T LoadAsset<T>(string assetName) where T : Object
		{
			Object obj = LoadAsset(assetName, typeof(T));
			return (T)(object)((obj is T) ? obj : null);
		}

		public void LoadAllJsonAssets()
		{
			foreach (AtlyssToolsLoaderModInfo value in ModInfos.Values)
			{
				Plugin.Logger.LogInfo((object)("Loading JSON assets for " + value.ModId));
				foreach (KeyValuePair<Type, BaseScriptablesManager> manager in Instance._managers)
				{
					manager.Value.OnModLoad(value);
				}
			}
		}

		public static void RegisterPreLibraryInit(string modName, Action action)
		{
			GetModInfo(modName)?.OnPreLibraryInit.Add(action);
		}

		public static void RegisterPostLibraryInit(string modName, Action action)
		{
			GetModInfo(modName)?.OnPostLibraryInit.Add(action);
		}

		public static void RegisterPreCacheInit(string modName, Action action)
		{
			GetModInfo(modName)?.OnPreCacheInit.Add(action);
		}

		public static void RegisterPostCacheInit(string modName, Action action)
		{
			GetModInfo(modName)?.OnPostCacheInit.Add(action);
		}

		public static AtlyssToolsLoaderModInfo GetModInfo(string modName)
		{
			modName = modName.ToLower();
			if (!Instance.ModInfos.ContainsKey(modName))
			{
				Plugin.Logger.LogError((object)("Mod " + modName + " not found"));
				return null;
			}
			return Instance.ModInfos[modName];
		}

		public static void FindAssetOnly()
		{
			string pluginPath = Paths.PluginPath;
			string[] directories = Directory.GetDirectories(pluginPath);
			string[] array = directories;
			foreach (string text in array)
			{
				string[] files = Directory.GetFiles(text, "AtlyssTools.json", SearchOption.TopDirectoryOnly);
				if (files.Length == 0)
				{
					continue;
				}
				string text2 = File.ReadAllText(files[0]);
				AtlyssToolsModDef atlyssToolsModDef = JsonConvert.DeserializeObject<AtlyssToolsModDef>(text2);
				if (atlyssToolsModDef == null)
				{
					Plugin.Logger.LogError((object)("Failed to load AtlyssTools.json for " + text));
					continue;
				}
				Plugin.Logger.LogInfo((object)("Found AtlyssTools mod " + atlyssToolsModDef.ModName));
				string[] files2 = Directory.GetFiles(text, "*.dll", SearchOption.TopDirectoryOnly);
				if (files2.Length == 0)
				{
					LoadPlugin(atlyssToolsModDef.ModId, text, null);
				}
			}
		}

		public void GenerateDump()
		{
			string text = Paths.PluginPath + "/AtlyssToolsDump.json";
			using (StreamWriter streamWriter = new StreamWriter(text))
			{
				foreach (AtlyssToolsLoaderModInfo value2 in ModInfos.Values)
				{
					streamWriter.WriteLine("Mod: " + value2.ModId);
					foreach (KeyValuePair<Type, BaseScriptablesManager> manager in _managers)
					{
						streamWriter.WriteLine("Manager: " + manager.Key.Name);
						foreach (object modScriptableObject in value2.GetModScriptableObjects(manager.Key))
						{
							streamWriter.WriteLine(manager.Value.GetName((ScriptableObject)((modScriptableObject is ScriptableObject) ? modScriptableObject : null)));
						}
					}
					streamWriter.WriteLine();
					streamWriter.WriteLine();
				}
			}
			Plugin.Logger.LogInfo((object)("Dumped all scriptable objects to " + text));
			string path = Paths.PluginPath + "/AtlyssToolsAssetsDump.json";
			using StreamWriter streamWriter2 = new StreamWriter(path);
			foreach (AtlyssToolsLoaderModInfo value3 in ModInfos.Values)
			{
				streamWriter2.WriteLine("Mod: " + value3.ModId);
				foreach (AssetBundle bundle in value3.Bundles)
				{
					streamWriter2.WriteLine("Bundle: " + ((Object)bundle).name);
					string[] allAssetNames = bundle.GetAllAssetNames();
					foreach (string value in allAssetNames)
					{
						streamWriter2.WriteLine(value);
					}
				}
				streamWriter2.WriteLine();
				streamWriter2.WriteLine();
			}
		}
	}
	public class AtlyssToolsLoaderModInfo
	{
		private static readonly Type[] NonConcreteType = new Type[2]
		{
			typeof(ScriptableCondition),
			typeof(ScriptableItem)
		};

		private static readonly List<Type> ConcreteType = new List<Type>(15)
		{
			typeof(ScriptableStatusCondition),
			typeof(ScriptableSceneTransferCondition),
			typeof(ScriptablePolymorphCondition),
			typeof(ScriptableChestpiece),
			typeof(ScriptableArmorDye),
			typeof(ScriptableCape),
			typeof(ScriptableClassTome),
			typeof(ScriptableHelm),
			typeof(ScriptableLeggings),
			typeof(ScriptableRing),
			typeof(ScriptableShield),
			typeof(ScriptableSkillScroll),
			typeof(ScriptableStatusConsumable),
			typeof(ScriptableTradeItem),
			typeof(ScriptableWeapon)
		};

		private readonly Dictionary<Type, IList> _scriptableObjects = new Dictionary<Type, IList>();

		public readonly List<AssetBundle> Bundles = new List<AssetBundle>();

		public readonly List<Action> OnPostCacheInit = new List<Action>();

		public readonly List<Action> OnPostLibraryInit = new List<Action>();

		public readonly List<Action> OnPreCacheInit = new List<Action>();

		public readonly List<Action> OnPreLibraryInit = new List<Action>();

		public readonly Dictionary<string, Object> PathToAsset = new Dictionary<string, Object>();

		public string ModId;

		public string ModPath;

		public void Dispose()
		{
			foreach (AssetBundle bundle in Bundles)
			{
				bundle.Unload(true);
			}
		}

		public void Initialize()
		{
		}

		public void LoadScriptableType<T>() where T : ScriptableObject
		{
			if (!_scriptableObjects.ContainsKey(typeof(T)))
			{
				_scriptableObjects.Add(typeof(T), new List<T>());
			}
			LoadJsonObjects<T>();
			LoadAssetObjects<T>();
		}

		public void LoadAssetBundles()
		{
			if (!Directory.Exists(ModPath + "/Assets"))
			{
				return;
			}
			string[] files = Directory.GetFiles(ModPath + "/Assets", "*", SearchOption.AllDirectories);
			string[] array = files;
			foreach (string text in array)
			{
				if (text.EndsWith(".manifest"))
				{
					continue;
				}
				string path = text + ".manifest";
				if (File.Exists(path))
				{
					AssetBundle val = AssetBundle.LoadFromFile(text);
					if ((Object)(object)val != (Object)null)
					{
						Bundles.Add(val);
					}
				}
			}
		}

		public List<T> GetModScriptableObjects<T>() where T : ScriptableObject
		{
			return _scriptableObjects.ContainsKey(typeof(T)) ? (_scriptableObjects[typeof(T)] as List<T>) : new List<T>();
		}

		public IList GetModScriptableObjects(Type type)
		{
			IList result;
			if (!_scriptableObjects.TryGetValue(type, out var value))
			{
				IList list = new List<Object>();
				result = list;
			}
			else
			{
				result = value;
			}
			return result;
		}

		public void LoadAssetObjects<T>() where T : ScriptableObject
		{
			foreach (AssetBundle bundle in Bundles)
			{
				T[] array = bundle.LoadAllAssets<T>();
				T[] array2 = array;
				foreach (T item in array2)
				{
					((List<T>)_scriptableObjects[typeof(T)]).Add(item);
				}
			}
		}

		private void LoadJsonObjects<T>() where T : ScriptableObject
		{
			string path = ModPath + "/Assets/" + typeof(T).Name;
			if (!Directory.Exists(path))
			{
				return;
			}
			string[] files = Directory.GetFiles(path, "*.json", SearchOption.AllDirectories);
			foreach (string text in files)
			{
				string path2 = text.Replace(ModPath + "/Assets/", "").Replace(".json", "").Replace("\\", "/");
				Object val = LoadJsonObject(path2, typeof(T));
				if (val == (Object)null)
				{
					Plugin.Logger.LogError((object)("Failed to load json object " + text + " for type " + typeof(T).Name + ", mod " + ModId));
				}
			}
		}

		private Object LoadJsonObject(string path, Type type)
		{
			if (string.IsNullOrEmpty(path))
			{
				return null;
			}
			if (NonConcreteType.Contains(type))
			{
				string typeName = path.Split(new char[1] { '/' })[0].ToLower();
				type = ConcreteType.FirstOrDefault((Type t) => t.Name.ToLower() == typeName);
				if (type == null)
				{
					return null;
				}
			}
			if (!_scriptableObjects.ContainsKey(type))
			{
				_scriptableObjects.Add(type, (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(type)));
			}
			path = path.Replace(".json", "");
			if (PathToAsset.TryGetValue(path, out var value))
			{
				return value;
			}
			if (!File.Exists(ModPath + "/Assets/" + path + ".json"))
			{
				return null;
			}
			string text = File.ReadAllText(ModPath + "/Assets/" + path + ".json");
			if (string.IsNullOrEmpty(text))
			{
				return null;
			}
			if (!type.IsSubclassOf(typeof(ScriptableObject)) && type != typeof(ScriptableObject))
			{
				Plugin.Logger.LogError((object)("Type " + type.Name + " is not a ScriptableObject"));
				return null;
			}
			object obj = JsonUtility.LoadFromJson(text, type);
			if (obj == null)
			{
				Plugin.Logger.LogError((object)("Failed to load json asset " + path));
				return null;
			}
			_scriptableObjects[type].Add(obj);
			PathToAsset.Add(path, (Object)((obj is Object) ? obj : null));
			Plugin.Logger.LogDebug((object)("Loaded json object " + path + " for type " + type.Name));
			return (Object)((obj is Object) ? obj : null);
		}

		public Object LoadModAsset(string assetName, Type type)
		{
			foreach (AssetBundle bundle in Bundles)
			{
				Object val = bundle.LoadAsset(assetName, type);
				if (val != (Object)null)
				{
					return val;
				}
			}
			if (type.IsSubclassOf(typeof(ScriptableObject)) || type == typeof(ScriptableObject))
			{
				Object val2 = LoadJsonObject(assetName, type);
				if (val2 != (Object)null)
				{
					return val2;
				}
			}
			return null;
		}
	}
	[BepInPlugin("com.ladyfey22.atlysstools", "AtlyssTools", "1.0.4")]
	[BepInProcess("Atlyss.exe")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Version = "1.0.4";

		internal static ManualLogSource Logger;

		private string _pluginPath;

		private void Awake()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			_pluginPath = Paths.PluginPath + "/AtlyssTools";
			Logger = ((BaseUnityPlugin)this).Logger;
			Logger.LogInfo((object)"Plugin 1.0.4 is loaded!");
			AtlyssToolsLoader.LoadPlugin("AtlyssTools", _pluginPath);
			AtlyssToolsLoader.FindAssetOnly();
			new Harmony("AtlyssTools").PatchAll(Assembly.GetExecutingAssembly());
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "AtlyssTools";

		public const string PLUGIN_NAME = "AtlyssTools";

		public const string PLUGIN_VERSION = "1.0.4";
	}
}
namespace AtlyssTools.Utility
{
	public class AtlyssToolsModDef
	{
		public string AtlasVersion;

		public string Author;

		public string Description;

		public string ModId;

		public string ModName;

		public string Version;
	}
	public interface IAttributeRegisterableManager
	{
		string Name { get; }

		Type AttributeType { get; }

		IDictionary GetRegistered();

		void Register(Type type, string modId);

		bool CanRegister(Type obj);
	}
	public class AttributeRegisterableManager<TBase, TAttributeType> : IAttributeRegisterableManager where TBase : class where TAttributeType : Attribute
	{
		private readonly Dictionary<string, List<TBase>> _registered = new Dictionary<string, List<TBase>>();

		public string Name => typeof(TBase).Name;

		public Type AttributeType => typeof(TAttributeType);

		public IDictionary GetRegistered()
		{
			return _registered;
		}

		public void Register(Type objType, string modId)
		{
			if (!CanRegister(objType))
			{
				return;
			}
			if (!objType.IsSubclassOf(typeof(TBase)))
			{
				Plugin.Logger.LogError((object)("Object " + objType.Name + " is not of type " + typeof(TBase).Name));
				return;
			}
			if (!_registered.ContainsKey(modId))
			{
				_registered.Add(modId, new List<TBase>());
			}
			TBase item = Activator.CreateInstance(objType) as TBase;
			_registered[modId].Add(item);
		}

		public bool CanRegister(Type obj)
		{
			return obj.GetCustomAttributes(AttributeType, inherit: true).Length != 0;
		}

		public List<TBase> GetRegisteredList()
		{
			return _registered.Values.SelectMany((List<TBase> x) => x).ToList();
		}

		public Dictionary<string, List<TBase>> GetRegisteredDict()
		{
			return _registered;
		}

		public List<TBase> GetRegistered(string modId)
		{
			if (_registered.TryGetValue(modId, out var value))
			{
				return value;
			}
			return new List<TBase>();
		}
	}
	public class CopyTools
	{
		private static List<Type> ExternalTypes = new List<Type>(7)
		{
			typeof(ScriptableObject),
			typeof(Texture2D),
			typeof(Sprite),
			typeof(Material),
			typeof(Shader),
			typeof(AudioClip),
			typeof(AnimationClip)
		};

		public static void DeepCopy(object source, object dest)
		{
			Type type = source.GetType();
			Type type2 = dest.GetType();
			if (type != type2)
			{
				throw new Exception("Source and destination types must be the same");
			}
			if (source is IList list && dest is IList list2)
			{
				list2.Clear();
				{
					foreach (object item in list)
					{
						object obj = Activator.CreateInstance(item.GetType());
						DeepCopy(item, obj);
						list2.Add(obj);
					}
					return;
				}
			}
			if (source is IDictionary dictionary && dest is IDictionary dictionary2)
			{
				dictionary2.Clear();
				{
					foreach (DictionaryEntry item2 in dictionary)
					{
						object obj2 = Activator.CreateInstance(item2.Key.GetType());
						object obj3 = Activator.CreateInstance(item2.Value.GetType());
						DeepCopy(item2.Key, obj2);
						DeepCopy(item2.Value, obj3);
						dictionary2.Add(obj2, obj3);
					}
					return;
				}
			}
			FieldInfo[] fields = type.GetFields();
			FieldInfo[] array = fields;
			foreach (FieldInfo field in array)
			{
				if (ExternalTypes.Contains(field.FieldType) || ExternalTypes.Exists((Type t) => field.FieldType.IsSubclassOf(t)) || field.FieldType.IsPrimitive)
				{
					field.SetValue(dest, field.GetValue(source));
					continue;
				}
				object value = field.GetValue(source);
				object obj4 = Activator.CreateInstance(field.FieldType);
				DeepCopy(value, obj4);
				field.SetValue(dest, obj4);
			}
		}
	}
	public class AssetConverter<T> : JsonConverter<T> where T : Object
	{
		public override void WriteJson(JsonWriter writer, T value, JsonSerializer serializer)
		{
			writer.WriteValue(((Object)value).name);
		}

		public override T ReadJson(JsonReader reader, Type objectType, T existingValue, bool hasExistingValue, JsonSerializer serializer)
		{
			string assetName = reader.Value?.ToString();
			return AtlyssToolsLoader.LoadAsset<T>(assetName);
		}
	}
	public class Vector3Converter : JsonConverter<Vector3>
	{
		public override void WriteJson(JsonWriter writer, Vector3 value, JsonSerializer serializer)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			writer.WriteStartArray();
			writer.WriteValue(value.x);
			writer.WriteValue(value.y);
			writer.WriteValue(value.z);
			writer.WriteEndArray();
		}

		public override Vector3 ReadJson(JsonReader reader, Type objectType, Vector3 existingValue, bool hasExistingValue, JsonSerializer serializer)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			reader.Read();
			if (reader.Value != null)
			{
				float num = Convert.ToSingle(reader.Value);
				reader.Read();
				float num2 = Convert.ToSingle(reader.Value);
				reader.Read();
				float num3 = Convert.ToSingle(reader.Value);
				reader.Read();
				return new Vector3(num, num2, num3);
			}
			return Vector3.zero;
		}
	}
	public class ColorConverter : JsonConverter<Color>
	{
		public override void WriteJson(JsonWriter writer, Color value, JsonSerializer serializer)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			writer.WriteStartArray();
			writer.WriteValue(value.r);
			writer.WriteValue(value.g);
			writer.WriteValue(value.b);
			writer.WriteValue(value.a);
			writer.WriteEndArray();
		}

		public override Color ReadJson(JsonReader reader, Type objectType, Color existingValue, bool hasExistingValue, JsonSerializer serializer)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			reader.Read();
			if (reader.Value != null)
			{
				float num = (float)(double)reader.Value;
				reader.Read();
				float num2 = (float)(double)reader.Value;
				reader.Read();
				float num3 = (float)(double)reader.Value;
				reader.Read();
				float num4 = (float)(double)reader.Value;
				reader.Read();
				return new Color(num, num2, num3, num4);
			}
			return Color.white;
		}
	}
	public class BaseConverter<T> : JsonConverter<T> where T : ScriptableObject
	{
		public override bool CanWrite => false;

		public override void WriteJson(JsonWriter writer, T value, JsonSerializer serializer)
		{
			throw new NotImplementedException();
		}

		public override T ReadJson(JsonReader reader, Type objectType, T existingValue, bool hasExistingValue, JsonSerializer serializer)
		{
			if (reader.Depth == 0)
			{
				if (!(AtlyssToolsLoader.Instance.GetManager(typeof(T)) is ScriptablesManager<T> scriptablesManager))
				{
					throw new Exception("Manager not found");
				}
				JObject val = JObject.Load(reader);
				string jsonName = scriptablesManager.GetJsonName(val);
				T val2 = scriptablesManager.GetFromCache(jsonName);
				if ((Object)(object)val2 == (Object)null)
				{
					Plugin.Logger.LogDebug((object)$"Failed to load {jsonName} from cache for type {typeof(T)}");
					Plugin.Logger.LogDebug((object)$"Creating new object of type {typeof(T)}");
					val2 = ScriptableObject.CreateInstance<T>();
				}
				serializer.Populate(((JToken)val).CreateReader(), (object)val2);
				return val2;
			}
			string text = reader.Value?.ToString();
			if (string.IsNullOrEmpty(text))
			{
				return default(T);
			}
			T val3 = AtlyssToolsLoader.LoadAsset<T>(text);
			if ((Object)(object)val3 == (Object)null)
			{
				Plugin.Logger.LogError((object)("Failed to load asset " + text + " in " + JsonUtility.currentFilePath));
			}
			return val3;
		}
	}
	public class Vector2Converter : JsonConverter<Vector2>
	{
		public override void WriteJson(JsonWriter writer, Vector2 value, JsonSerializer serializer)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			writer.WriteStartArray();
			writer.WriteValue(value.x);
			writer.WriteValue(value.y);
			writer.WriteEndArray();
		}

		public override Vector2 ReadJson(JsonReader reader, Type objectType, Vector2 existingValue, bool hasExistingValue, JsonSerializer serializer)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			reader.Read();
			float num = Convert.ToSingle(reader.Value);
			reader.Read();
			float num2 = Convert.ToSingle(reader.Value);
			reader.Read();
			return new Vector2(num, num2);
		}
	}
	public class Vector4Converter : JsonConverter<Vector4>
	{
		public override void WriteJson(JsonWriter writer, Vector4 value, JsonSerializer serializer)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			writer.WriteStartArray();
			writer.WriteValue(value.x);
			writer.WriteValue(value.y);
			writer.WriteValue(value.z);
			writer.WriteValue(value.w);
			writer.WriteEndArray();
		}

		public override Vector4 ReadJson(JsonReader reader, Type objectType, Vector4 existingValue, bool hasExistingValue, JsonSerializer serializer)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			reader.Read();
			float num = Convert.ToSingle(reader.Value);
			reader.Read();
			float num2 = Convert.ToSingle(reader.Value);
			reader.Read();
			float num3 = Convert.ToSingle(reader.Value);
			reader.Read();
			float num4 = Convert.ToSingle(reader.Value);
			reader.Read();
			return new Vector4(num, num2, num3, num4);
		}
	}
	public class ArrayConverter : JsonConverter
	{
		public override bool CanWrite => false;

		public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
		{
		}

		private int FindItemIndex(IList list, JObject criteria)
		{
			if (criteria.ContainsKey("index"))
			{
				int num = Extensions.Value<int>((IEnumerable<JToken>)criteria["index"]);
				return (num >= 0 && num < list.Count) ? num : (-1);
			}
			foreach (object item in list)
			{
				bool flag = true;
				foreach (JProperty item2 in criteria.Properties())
				{
					if (!(item2.Name == "value"))
					{
						FieldInfo field = item.GetType().GetField(item2.Name);
						if (field == null)
						{
							Plugin.Logger.LogError((object)$"JSON Load Error: Array modification field {item2.Name} does not exist for type {item.GetType()}");
							flag = false;
							break;
						}
						string text = field.GetValue(item)?.ToString();
						if (text == null || text != ((object)item2.Value).ToString())
						{
							flag = false;
							break;
						}
					}
				}
				if (flag)
				{
					return list.IndexOf(item);
				}
			}
			return -1;
		}

		public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Invalid comparison between Unknown and I4
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Invalid comparison between Unknown and I4
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			if ((int)reader.TokenType == 2)
			{
				Type elementType = objectType.GetElementType();
				if (elementType == null)
				{
					return existingValue;
				}
				List<object> list = new List<object>();
				while (reader.Read() && (int)reader.TokenType != 14)
				{
					object item = serializer.Deserialize(reader, elementType);
					list.Add(item);
				}
				Array array = Array.CreateInstance(elementType, list.Count);
				for (int i = 0; i < list.Count; i++)
				{
					array.SetValue(list[i], i);
				}
				return array;
			}
			if ((int)reader.TokenType == 1)
			{
				JObject val = JObject.Load(reader);
				Type elementType2 = objectType.GetElementType();
				if (elementType2 == null)
				{
					return existingValue;
				}
				List<object> list2 = new List<object>();
				if (existingValue != null)
				{
					foreach (object item3 in (Array)existingValue)
					{
						list2.Add(item3);
					}
				}
				if (val.ContainsKey("add"))
				{
					JToken obj = val["add"];
					JArray val2 = (JArray)(object)((obj is JArray) ? obj : null);
					if (val2 != null)
					{
						foreach (JObject item4 in ((JToken)val2).Children<JObject>())
						{
							object item2 = serializer.Deserialize(((JToken)item4).CreateReader(), elementType2);
							list2.Add(item2);
						}
					}
				}
				if (val.ContainsKey("remove"))
				{
					JToken obj2 = val["remove"];
					JArray val3 = (JArray)(object)((obj2 is JArray) ? obj2 : null);
					if (val3 != null)
					{
						HashSet<int> hashSet = new HashSet<int>();
						foreach (JObject item5 in ((JToken)val3).Children<JObject>())
						{
							int num = FindItemIndex(list2, item5);
							if (num >= 0)
							{
								hashSet.Add(num);
							}
						}
						foreach (int item6 in hashSet.OrderByDescending((int x) => x))
						{
							list2.RemoveAt(item6);
						}
					}
				}
				if (val.ContainsKey("modify"))
				{
					JToken obj3 = val["modify"];
					JArray val4 = (JArray)(object)((obj3 is JArray) ? obj3 : null);
					if (val4 != null)
					{
						foreach (JObject item7 in ((JToken)val4).Children<JObject>())
						{
							int num2 = FindItemIndex(list2, item7);
							if (num2 >= 0 && item7.ContainsKey("value") && item7["value"] is JObject)
							{
								serializer.Populate(item7["value"].CreateReader(), list2[num2]);
							}
							else
							{
								Plugin.Logger.LogError((object)("JSON Load Error: Failed to modify item in array of " + elementType2));
							}
						}
					}
				}
				Array array2 = Array.CreateInstance(elementType2, list2.Count);
				for (int j = 0; j < list2.Count; j++)
				{
					array2.SetValue(list2[j], j);
				}
				return array2;
			}
			return existingValue;
		}

		public override bool CanConvert(Type objectType)
		{
			return objectType.IsArray;
		}
	}
	public class JsonUtility
	{
		public static string currentFilePath;

		private static List<JsonConverter> _converters;

		private static readonly List<Type> ScriptableTypes = new List<Type>(37)
		{
			typeof(ScriptableArmorRender),
			typeof(ScriptableCombatElement),
			typeof(ScriptableCreep),
			typeof(ScriptableDialogData),
			typeof(ScriptableEmoteList),
			typeof(ScriptableLootTable),
			typeof(ScriptableMapData),
			typeof(ScriptablePlayerBaseClass),
			typeof(ScriptablePlayerRace),
			typeof(ScriptablePolymorphCondition),
			typeof(ScriptableQuest),
			typeof(ScriptableSceneTransferCondition),
			typeof(ScriptableShopkeep),
			typeof(ScriptableSkill),
			typeof(ScriptableStatAttribute),
			typeof(ScriptableStatModifier),
			typeof(ScriptableStatModifierTable),
			typeof(ScriptableStatusCondition),
			typeof(ScriptableWeaponProjectileSet),
			typeof(ScriptableWeaponType),
			typeof(CastEffectCollection),
			typeof(ScriptableChestpiece),
			typeof(ScriptableArmor),
			typeof(ScriptableArmorDye),
			typeof(ScriptableCape),
			typeof(ScriptableClassTome),
			typeof(ScriptableHelm),
			typeof(ScriptableLeggings),
			typeof(ScriptableRing),
			typeof(ScriptableShield),
			typeof(ScriptableSkillScroll),
			typeof(ScriptableStatusConsumable),
			typeof(ScriptableTradeItem),
			typeof(ScriptableWeapon),
			typeof(ScriptableItem),
			typeof(ScriptableCondition),
			typeof(CastEffectCollection)
		};

		private static readonly List<Type> AssetTypes = new List<Type>(5)
		{
			typeof(Texture),
			typeof(AudioClip),
			typeof(Sprite),
			typeof(GameObject),
			typeof(Mesh)
		};

		private static JsonConverter CreateGenericBase(Type type)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			Type typeFromHandle = typeof(BaseConverter<>);
			Type[] typeArguments = new Type[1] { type };
			Type type2 = typeFromHandle.MakeGenericType(typeArguments);
			return (JsonConverter)Activator.CreateInstance(type2);
		}

		private static JsonConverter CreateAssetConverter(Type type)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			Type typeFromHandle = typeof(AssetConverter<>);
			Type[] typeArguments = new Type[1] { type };
			Type type2 = typeFromHandle.MakeGenericType(typeArguments);
			return (JsonConverter)Activator.CreateInstance(type2);
		}

		public static JsonSerializerSettings GetSettings(Type type)
		{
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Expected O, but got Unknown
			if (!ScriptableTypes.Contains(type) && !AssetTypes.Contains(type))
			{
				throw new Exception("Type must be a ScriptableObject or Asset");
			}
			if (_converters == null)
			{
				_converters = new List<JsonConverter>(5)
				{
					(JsonConverter)(object)new Vector3Converter(),
					(JsonConverter)(object)new ColorConverter(),
					(JsonConverter)(object)new Vector2Converter(),
					(JsonConverter)(object)new Vector4Converter(),
					(JsonConverter)(object)new ArrayConverter()
				};
				foreach (Type scriptableType in ScriptableTypes)
				{
					_converters.Add(CreateGenericBase(scriptableType));
				}
				foreach (Type assetType in AssetTypes)
				{
					_converters.Add(CreateAssetConverter(assetType));
				}
			}
			return new JsonSerializerSettings
			{
				PreserveReferencesHandling = (PreserveReferencesHandling)1,
				TypeNameHandling = (TypeNameHandling)4,
				Converters = _converters
			};
		}

		public static object LoadFromJson(string json, Type type)
		{
			if (string.IsNullOrEmpty(json))
			{
				return null;
			}
			JsonSerializerSettings settings = GetSettings(type);
			return JsonConvert.DeserializeObject(json, type, settings);
		}

		public static T LoadFromJson<T>(string json)
		{
			if (string.IsNullOrEmpty(json))
			{
				return default(T);
			}
			JsonSerializerSettings settings = GetSettings(typeof(T));
			return JsonConvert.DeserializeObject<T>(json, settings);
		}

		public static T ReadFromFile<T>(string path) where T : ScriptableObject
		{
			if (string.IsNullOrEmpty(path))
			{
				Plugin.Logger.LogError((object)"Path is null or empty");
				return default(T);
			}
			if (!File.Exists(path))
			{
				Plugin.Logger.LogError((object)("File " + path + " does not exist"));
				return default(T);
			}
			currentFilePath = path;
			string json = File.ReadAllText(path);
			return LoadFromJson<T>(json);
		}
	}
	public interface LoaderStateManager
	{
		void PreLibraryInit();

		void PostLibraryInit();

		void PreCacheInit();

		void PostCacheInit();
	}
	public class LoaderStateMachine
	{
		public enum LoadState
		{
			PreCacheInit,
			PostCacheInit,
			PreLibraryInit,
			PostLibraryInit
		}

		private readonly List<LoaderStateManager> _managers = new List<LoaderStateManager>();

		public LoadState State { get; private set; }

		internal void SetState(LoadState state)
		{
			State = state;
			foreach (LoaderStateManager manager in _managers)
			{
				switch (state)
				{
				case LoadState.PreCacheInit:
					manager.PreCacheInit();
					break;
				case LoadState.PostCacheInit:
					manager.PostCacheInit();
					break;
				case LoadState.PreLibraryInit:
					manager.PreLibraryInit();
					break;
				case LoadState.PostLibraryInit:
					manager.PostLibraryInit();
					break;
				}
			}
		}

		public void RegisterManager(LoaderStateManager manager)
		{
			_managers.Add(manager);
		}

		public void RegisterManagers(IEnumerable<LoaderStateManager> managers)
		{
			_managers.AddRange(managers);
		}
	}
}
namespace AtlyssTools.Registries
{
	public abstract class CachelessManager<T> : ScriptablesManager<T> where T : ScriptableObject
	{
		private readonly Dictionary<string, T> _cached = new Dictionary<string, T>();

		public override void PreCacheInit()
		{
			_cached.Clear();
			T[] array = Resources.LoadAll<T>("");
			T[] array2 = array;
			foreach (T val in array2)
			{
				string name = GetName((ScriptableObject)(object)val);
				if (_cached.ContainsKey(name))
				{
					Plugin.Logger.LogError((object)$"Duplicate asset name {name} for type {typeof(T)}");
				}
				else
				{
					_cached[name] = val;
				}
			}
		}

		public override string GetName(ScriptableObject obj)
		{
			return ((Object)obj).name;
		}

		public override string GetJsonName(JObject obj)
		{
			JToken obj2 = obj["name"];
			return (obj2 != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj2) : null;
		}

		protected override IDictionary InternalGetCached()
		{
			return _cached;
		}
	}
	[Manager]
	public class ArmorRenderManager : CachelessManager<ScriptableArmorRender>
	{
		private static ArmorRenderManager _instance;

		public static ArmorRenderManager Instance => _instance ?? (_instance = new ArmorRenderManager());

		protected ArmorRenderManager()
		{
		}
	}
	[Manager]
	public class ShopkeepManager : CachelessManager<ScriptableShopkeep>
	{
		private static ShopkeepManager _instance;

		public static ShopkeepManager Instance => _instance ?? (_instance = new ShopkeepManager());

		protected ShopkeepManager()
		{
		}

		public override string GetName(ScriptableObject obj)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return ((ScriptableShopkeep)obj)._shopName;
		}

		public override string GetJsonName(JObject obj)
		{
			JToken obj2 = obj["_shopName"];
			return (obj2 != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj2) : null;
		}
	}
	[Manager]
	public class CastEffectCollectionManager : CachelessManager<CastEffectCollection>
	{
		private static CastEffectCollectionManager _instance;

		public static CastEffectCollectionManager Instance => _instance ?? (_instance = new CastEffectCollectionManager());

		protected CastEffectCollectionManager()
		{
		}
	}
	public class ConditionManager<T> : ScriptablesManager<T> where T : ScriptableObject
	{
		protected ConditionManager()
		{
		}

		protected override IDictionary InternalGetCached()
		{
			return GameManager._current._cachedScriptableConditions;
		}

		public override string GetName(ScriptableObject obj)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			ScriptableCondition val = (ScriptableCondition)obj;
			return $"{val._conditionName}_{val._conditionRank}";
		}

		public override string GetJsonName(JObject obj)
		{
			JToken obj2 = obj["_conditionName"];
			return (obj2 != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj2) : null;
		}
	}
	[Manager]
	public class StatusConditionManager : ConditionManager<ScriptableStatusCondition>
	{
		private static StatusConditionManager _instance;

		public static StatusConditionManager Instance => _instance ?? (_instance = new StatusConditionManager());

		protected StatusConditionManager()
		{
		}
	}
	[Manager]
	public class SceneTransferConditionManager : ConditionManager<ScriptableSceneTransferCondition>
	{
		private static SceneTransferConditionManager _instance;

		public static SceneTransferConditionManager Instance => _instance ?? (_instance = new SceneTransferConditionManager());

		protected SceneTransferConditionManager()
		{
		}
	}
	[Manager]
	public class PolymorphConditionManager : ConditionManager<ScriptablePolymorphCondition>
	{
		private static PolymorphConditionManager _instance;

		public static PolymorphConditionManager Instance => _instance ?? (_instance = new PolymorphConditionManager());

		protected PolymorphConditionManager()
		{
		}
	}
	public abstract class ItemManager<T> : ScriptablesManager<T> where T : ScriptableObject
	{
		protected override IDictionary InternalGetCached()
		{
			return GameManager._current._cachedScriptableItems;
		}

		public override string GetName(ScriptableObject obj)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return ((ScriptableItem)obj)._itemName;
		}

		public override string GetJsonName(JObject obj)
		{
			JToken obj2 = obj["_itemName"];
			return (obj2 != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj2) : null;
		}
	}
	[Manager]
	public class ChestpieceManager : ItemManager<ScriptableChestpiece>
	{
		private static ChestpieceManager _instance;

		public static ChestpieceManager Instance => _instance ?? (_instance = new ChestpieceManager());

		protected ChestpieceManager()
		{
		}
	}
	[Manager]
	public class ArmorDyeManager : ItemManager<ScriptableArmorDye>
	{
		private static ArmorDyeManager _instance;

		public static ArmorDyeManager Instance => _instance ?? (_instance = new ArmorDyeManager());

		protected ArmorDyeManager()
		{
		}
	}
	[Manager]
	public class CapeManager : ItemManager<ScriptableCape>
	{
		private static CapeManager _instance;

		public static CapeManager Instance => _instance ?? (_instance = new CapeManager());

		protected CapeManager()
		{
		}
	}
	[Manager]
	public class ClassTomeManager : ItemManager<ScriptableClassTome>
	{
		private static ClassTomeManager _instance;

		public static ClassTomeManager Instance => _instance ?? (_instance = new ClassTomeManager());

		protected ClassTomeManager()
		{
		}
	}
	[Manager]
	public class HelmManager : ItemManager<ScriptableHelm>
	{
		private static HelmManager _instance;

		public static HelmManager Instance => _instance ?? (_instance = new HelmManager());

		protected HelmManager()
		{
		}
	}
	[Manager]
	public class LeggingsManager : ItemManager<ScriptableLeggings>
	{
		private static LeggingsManager _instance;

		public static LeggingsManager Instance => _instance ?? (_instance = new LeggingsManager());

		protected LeggingsManager()
		{
		}
	}
	[Manager]
	public class RingManager : ItemManager<ScriptableRing>
	{
		private static RingManager _instance;

		public static RingManager Instance => _instance ?? (_instance = new RingManager());

		protected RingManager()
		{
		}
	}
	[Manager]
	public class ShieldManager : ItemManager<ScriptableShield>
	{
		private static ShieldManager _instance;

		public static ShieldManager Instance => _instance ?? (_instance = new ShieldManager());

		protected ShieldManager()
		{
		}
	}
	[Manager]
	public class SkillScrollManager : ItemManager<ScriptableSkillScroll>
	{
		private static SkillScrollManager _instance;

		public static SkillScrollManager Instance => _instance ?? (_instance = new SkillScrollManager());

		protected SkillScrollManager()
		{
		}
	}
	[Manager]
	public class StatusConsumableManager : ItemManager<ScriptableStatusConsumable>
	{
		private static StatusConsumableManager _instance;

		public static StatusConsumableManager Instance => _instance ?? (_instance = new StatusConsumableManager());

		protected StatusConsumableManager()
		{
		}
	}
	[Manager]
	public class TradeItemManager : ItemManager<ScriptableTradeItem>
	{
		private static TradeItemManager _instance;

		public static TradeItemManager Instance => _instance ?? (_instance = new TradeItemManager());

		protected TradeItemManager()
		{
		}
	}
	[Manager]
	public class WeaponManager : ItemManager<ScriptableWeapon>
	{
		private static WeaponManager _instance;

		public static WeaponManager Instance => _instance ?? (_instance = new WeaponManager());

		protected WeaponManager()
		{
		}
	}
	[AttributeUsage(AttributeTargets.Class)]
	public class ManagerAttribute : Attribute
	{
	}
	public class CreepManager : ScriptablesManager<ScriptableCreep>
	{
		private static CreepManager _instance;

		public static CreepManager Instance => _instance ?? (_instance = new CreepManager());

		protected CreepManager()
		{
		}

		protected override IDictionary InternalGetCached()
		{
			return GameManager._current._cachedScriptableCreeps;
		}

		public override string GetName(ScriptableObject obj)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return ((ScriptableCreep)obj)._creepName;
		}

		public override string GetJsonName(JObject obj)
		{
			JToken obj2 = obj["_creepName"];
			return (obj2 != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj2) : null;
		}
	}
	public class QuestManager : ScriptablesManager<ScriptableQuest>
	{
		private static QuestManager _instance;

		public static QuestManager Instance => _instance ?? (_instance = new QuestManager());

		protected QuestManager()
		{
		}

		protected override IDictionary InternalGetCached()
		{
			return GameManager._current._cachedScriptableQuests;
		}

		public override string GetName(ScriptableObject obj)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return ((ScriptableQuest)obj)._questName;
		}

		public override string GetJsonName(JObject obj)
		{
			JToken obj2 = obj["_questName"];
			return (obj2 != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj2) : null;
		}
	}
	public class PlayerRaceManager : ScriptablesManager<ScriptablePlayerRace>
	{
		private static PlayerRaceManager _instance;

		public static PlayerRaceManager Instance => _instance ?? (_instance = new PlayerRaceManager());

		protected PlayerRaceManager()
		{
		}

		protected override IDictionary InternalGetCached()
		{
			return GameManager._current._cachedScriptableRaces;
		}

		public override string GetName(ScriptableObject obj)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return ((ScriptablePlayerRace)obj)._raceName;
		}

		public override string GetJsonName(JObject obj)
		{
			JToken obj2 = obj["_raceName"];
			return (obj2 != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj2) : null;
		}
	}
	public class CombatElementManager : ScriptablesManager<ScriptableCombatElement>
	{
		private static CombatElementManager _instance;

		public static CombatElementManager Instance => _instance ?? (_instance = new CombatElementManager());

		protected CombatElementManager()
		{
		}

		protected override IDictionary InternalGetCached()
		{
			return GameManager._current._cachedScriptableCombatElements;
		}

		public override string GetName(ScriptableObject obj)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return ((ScriptableCombatElement)obj)._elementName;
		}

		public override string GetJsonName(JObject obj)
		{
			JToken obj2 = obj["_elementName"];
			return (obj2 != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj2) : null;
		}
	}
	public class StatModifierManager : ScriptablesManager<ScriptableStatModifier>
	{
		private static StatModifierManager _instance;

		public static StatModifierManager Instance => _instance ?? (_instance = new StatModifierManager());

		protected StatModifierManager()
		{
		}

		protected override IDictionary InternalGetCached()
		{
			return GameManager._current._cachedScriptableStatModifiers;
		}

		public override string GetName(ScriptableObject obj)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return ((ScriptableStatModifier)obj)._modifierTag;
		}

		public override string GetJsonName(JObject obj)
		{
			JToken obj2 = obj["_modifierTag"];
			return (obj2 != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj2) : null;
		}
	}
	[Manager]
	public class PlayerBaseClassManager : ScriptablesManager<ScriptablePlayerBaseClass>
	{
		private static PlayerBaseClassManager _instance;

		public static PlayerBaseClassManager Instance => _instance ?? (_instance = new PlayerBaseClassManager());

		protected PlayerBaseClassManager()
		{
		}

		protected override IDictionary InternalGetCached()
		{
			return GameManager._current._cachedScriptablePlayerClasses;
		}

		public override string GetName(ScriptableObject obj)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return ((ScriptablePlayerBaseClass)obj)._className;
		}

		public override string GetJsonName(JObject obj)
		{
			JToken obj2 = obj["_className"];
			return (obj2 != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj2) : null;
		}
	}
	public abstract class BaseScriptablesManager
	{
		public abstract Type GetObjectType();

		protected abstract IDictionary InternalGetCached();

		public abstract LoaderStateManager GetStateManager();

		public abstract void OnModLoad(AtlyssToolsLoaderModInfo modInfo);

		public abstract ScriptableObject Instantiate();

		public abstract string GetName(ScriptableObject obj);

		public abstract string GetJsonName(JObject obj);
	}
	public abstract class ScriptablesManager<T> : BaseScriptablesManager where T : ScriptableObject
	{
		private class ScriptablesStateManager : LoaderStateManager
		{
			[CompilerGenerated]
			[DebuggerBrowsable(DebuggerBrowsableState.Never)]
			private ScriptablesManager<T> <manager>P;

			public ScriptablesStateManager(ScriptablesManager<T> manager)
			{
				<manager>P = manager;
				base..ctor();
			}

			public void PreCacheInit()
			{
				<manager>P.PreCacheInit();
			}

			public void PostCacheInit()
			{
				<manager>P.PostCacheInit();
			}

			public void PreLibraryInit()
			{
				<manager>P.PreLibraryInit();
			}

			public void PostLibraryInit()
			{
				<manager>P.PostLibraryInit();
			}
		}

		public readonly LoaderStateManager StateManager;

		protected ScriptablesManager()
		{
			StateManager = new ScriptablesStateManager(this);
		}

		private void Register(T obj)
		{
			if ((Object)(object)obj == (Object)null)
			{
				Plugin.Logger.LogError((object)("Attempted to register a null object for type " + typeof(T)));
				return;
			}
			IDictionary dictionary = InternalGetCached();
			string name = GetName((ScriptableObject)(object)obj);
			if (dictionary.Contains(name))
			{
				object? obj2 = dictionary[name];
				Replace((T)((obj2 is T) ? obj2 : null), obj);
			}
			else
			{
				dictionary.Add(name, obj);
			}
		}

		public override Type GetObjectType()
		{
			return typeof(T);
		}

		public virtual IList GetModdedObjects()
		{
			return AtlyssToolsLoader.GetScriptableObjects<T>();
		}

		public List<T> GetModded()
		{
			return GetModdedObjects().Cast<T>().ToList();
		}

		public Dictionary<string, T> GetCached()
		{
			return InternalGetCached() as Dictionary<string, T>;
		}

		public void LoadToCache()
		{
			List<T> scriptableObjects = AtlyssToolsLoader.GetScriptableObjects<T>();
			foreach (T item in scriptableObjects)
			{
				Register(item);
			}
		}

		public override void OnModLoad(AtlyssToolsLoaderModInfo modInfo)
		{
			modInfo.LoadScriptableType<T>();
		}

		public override LoaderStateManager GetStateManager()
		{
			return StateManager;
		}

		public T GetFromCache(string objName)
		{
			IDictionary dictionary = InternalGetCached();
			if (dictionary.Contains(objName))
			{
				object? obj = dictionary[objName];
				return (T)((obj is T) ? obj : null);
			}
			return default(T);
		}

		public void Replace(T to, T from)
		{
			Type type = ((object)from).GetType();
			Type type2 = ((object)to).GetType();
			if (type != type2)
			{
				Plugin.Logger.LogError((object)$"Source type {type} does not match destination type {type2}");
				return;
			}
			FieldInfo[] fields = type.GetFields();
			FieldInfo[] array = fields;
			foreach (FieldInfo fieldInfo in array)
			{
				fieldInfo.SetValue(to, fieldInfo.GetValue(from));
			}
			PropertyInfo[] properties = type.GetProperties();
			PropertyInfo[] array2 = properties;
			foreach (PropertyInfo propertyInfo in array2)
			{
				propertyInfo.SetValue(to, propertyInfo.GetValue(from));
			}
		}

		public void ReplaceCachedAll(string destCache, string sourceCache)
		{
			T fromCache = GetFromCache(sourceCache);
			T fromCache2 = GetFromCache(destCache);
			if ((Object)(object)fromCache == (Object)null)
			{
				Plugin.Logger.LogError((object)("Source cache " + sourceCache + " is null"));
			}
			else if ((Object)(object)fromCache2 == (Object)null)
			{
				Plugin.Logger.LogError((object)("Destination cache " + destCache + " is null"));
			}
			else
			{
				Replace(fromCache2, fromCache);
			}
		}

		public virtual void PreCacheInit()
		{
		}

		public virtual void PostCacheInit()
		{
			LoadToCache();
		}

		public virtual void PreLibraryInit()
		{
		}

		public virtual void PostLibraryInit()
		{
		}

		public override ScriptableObject Instantiate()
		{
			return (ScriptableObject)(object)ScriptableObject.CreateInstance<T>();
		}
	}
	[Manager]
	public class SkillManager : ScriptablesManager<ScriptableSkill>
	{
		private static SkillManager _instance;

		public readonly List<string> GeneralSkills = new List<string>();

		internal static SkillManager Instance => _instance ?? (_instance = new SkillManager());

		protected SkillManager()
		{
		}

		public void RegisterGeneralSkill(string skillName)
		{
			if (GeneralSkills.Contains(skillName))
			{
				Plugin.Logger.LogWarning((object)("General skill " + skillName + " already registered"));
			}
			else if (AtlyssToolsLoader.Instance.State > LoaderStateMachine.LoadState.PreLibraryInit)
			{
				Plugin.Logger.LogWarning((object)("General skill " + skillName + " registered after skill library load"));
			}
			else
			{
				GeneralSkills.Add(skillName);
			}
		}

		protected override IDictionary InternalGetCached()
		{
			return GameManager._current._cachedScriptableSkills;
		}

		public override string GetName(ScriptableObject obj)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return ((ScriptableSkill)obj)._skillName;
		}

		public override string GetJsonName(JObject obj)
		{
			JToken obj2 = obj["_skillName"];
			return (obj2 != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj2) : null;
		}

		public override void PreLibraryInit()
		{
			base.PreLibraryInit();
			foreach (string generalSkill in Instance.GeneralSkills)
			{
				if (!GameManager._current._cachedScriptableSkills.TryGetValue(generalSkill, out var value))
				{
					Plugin.Logger.LogError((object)("General skill " + generalSkill + " not found in cache"));
					continue;
				}
				List<ScriptableSkill> list = GameManager._current._statLogics._generalSkills.ToList();
				list.Add(value);
				GameManager._current._statLogics._generalSkills = list.ToArray();
			}
		}
	}
}
namespace AtlyssTools.Patches
{
	[HarmonyPatch(typeof(ChatBehaviour), "Awake")]
	public class ChatPatch
	{
		[HarmonyPostfix]
		public static void Postfix(ChatBehaviour __instance)
		{
			ChatManager.Instance.BaseGameChatManager = __instance;
		}
	}
	[HarmonyPatch(typeof(ChatBehaviour), "Send_ChatMessage")]
	public class ChatSendMessagePatch
	{
		[HarmonyPrefix]
		public static bool Prefix(ChatBehaviour __instance, string _message)
		{
			Plugin.Logger.LogInfo((object)("ChatBehaviour.Send_ChatMessage prefix patch: " + _message));
			if (string.IsNullOrEmpty(_message) || !ChatManager.Instance.ProcessMessage(_message))
			{
				return true;
			}
			__instance._lastMessage = _message;
			__instance._chatInput.text = "";
			return false;
		}
	}
	[HarmonyPatch(typeof(GameManager), "Cache_ScriptableAssets")]
	public class GameManagerPatches
	{
		[HarmonyPrefix]
		private static void Prefix(GameManager __instance)
		{
			Plugin.Logger.LogInfo((object)"GameManager.Cache_ScriptableAssets prefix patch");
			AtlyssToolsLoader.Instance.State = LoaderStateMachine.LoadState.PreCacheInit;
		}

		[HarmonyPostfix]
		private static void Postfix(GameManager __instance)
		{
			Plugin.Logger.LogInfo((object)"GameManager.Cache_ScriptableAssets postfix patch");
			AtlyssToolsLoader.Instance.State = LoaderStateMachine.LoadState.PostCacheInit;
		}
	}
	[HarmonyPatch(typeof(PlayerCasting), "Init_SkillLibrary")]
	public class CastingPatches
	{
		[HarmonyPrefix]
		private static void Prefix(PlayerCasting __instance)
		{
			AtlyssToolsLoader.Instance.State = LoaderStateMachine.LoadState.PreLibraryInit;
		}

		[HarmonyPostfix]
		private static void Postfix(PlayerCasting __instance)
		{
			AtlyssToolsLoader.Instance.State = LoaderStateMachine.LoadState.PostLibraryInit;
		}
	}
}
namespace AtlyssTools.Commands
{
	public abstract class ChatProcessor
	{
		public virtual bool ProcessMessage(string message)
		{
			return false;
		}
	}
	public class ChatProcessorAttribute : Attribute
	{
	}
	public class ChatProcessorManager : AttributeRegisterableManager<ChatProcessor, ChatProcessorAttribute>
	{
		public static ChatProcessorManager Instance { get; private set; }

		public ChatProcessorManager()
		{
			if (Instance != null)
			{
				Plugin.Logger.LogWarning((object)"ChatProcessorManager already exists");
			}
			Instance = this;
		}
	}
	public class ChatManager
	{
		private static ChatManager _instance;

		public static ChatManager Instance => _instance ?? (_instance = new ChatManager());

		public ChatBehaviour BaseGameChatManager { get; set; }

		public void SendMessage(string message)
		{
			BaseGameChatManager.New_ChatMessage(message);
		}

		public bool ProcessMessage(string message)
		{
			foreach (ChatProcessor registered in ChatProcessorManager.Instance.GetRegisteredList())
			{
				if (registered.ProcessMessage(message))
				{
					return true;
				}
			}
			return false;
		}
	}
	public class CommandAttribute : Attribute
	{
	}
	public abstract class Command
	{
		public string Name { get; protected set; }

		public string Description { get; protected set; }

		public string[] Aliases { get; protected set; }

		public abstract bool Execute(ChatManager chatManager, string[] args);

		public abstract bool DisplayUsage(ChatManager chatManager);
	}
	public class CommandManager : AttributeRegisterableManager<Command, CommandAttribute>
	{
		public static CommandManager Instance { get; private set; }

		public CommandManager()
		{
			if (Instance != null)
			{
				Plugin.Logger.LogWarning((object)"CommandManager already exists");
			}
			Instance = this;
		}

		public bool ExecuteCommand(string commandName, string[] args)
		{
			foreach (Command registered in GetRegisteredList())
			{
				if (!(registered.Name == commandName) && !registered.Aliases.Contains(commandName))
				{
					continue;
				}
				try
				{
					if (registered.Execute(ChatManager.Instance, args))
					{
						return true;
					}
				}
				catch (Exception arg)
				{
					Plugin.Logger.LogError((object)$"Error executing command '{commandName}': {arg}");
					return false;
				}
				registered.DisplayUsage(ChatManager.Instance);
				return true;
			}
			ChatManager.Instance.SendMessage("Command '" + commandName + "' not found");
			return true;
		}
	}
	[ChatProcessor]
	public class CommandProcessor : ChatProcessor
	{
		public override bool ProcessMessage(string message)
		{
			if (!string.IsNullOrEmpty(message) && message.StartsWith("/"))
			{
				List<string> list = message.Substring(1).Split(new char[1] { ' ' }).ToList();
				string commandName = list[0];
				list.RemoveAt(0);
				return CommandManager.Instance.ExecuteCommand(commandName, list.ToArray());
			}
			return false;
		}
	}
	[Command]
	public class HelpCommand : Command
	{
		public HelpCommand()
		{
			base.Name = "help";
			base.Description = "Displays a list of available commands";
			base.Aliases = new string[1] { "?" };
		}

		public override bool Execute(ChatManager chatManager, string[] args)
		{
			if (args.Length != 0)
			{
				foreach (Command registered in CommandManager.Instance.GetRegisteredList())
				{
					if (registered.Name == args[0] || registered.Aliases.Contains(args[0]))
					{
						registered.DisplayUsage(chatManager);
						return true;
					}
				}
				chatManager.SendMessage("Command '" + args[0] + "' not found");
				return true;
			}
			foreach (Command registered2 in CommandManager.Instance.GetRegisteredList())
			{
				chatManager.SendMessage(registered2.Name + " - " + registered2.Description);
			}
			return true;
		}

		public override bool DisplayUsage(ChatManager chatManager)
		{
			chatManager.SendMessage("Usage: /help [command]");
			return true;
		}
	}
	[Command]
	public class AtlyssToolsCommand : Command
	{
		public AtlyssToolsCommand()
		{
			base.Name = "atlysstools";
			base.Description = "Gets the AtlyssTools version";
			base.Aliases = new string[1] { "at" };
		}

		public override bool Execute(ChatManager chatManager, string[] args)
		{
			if (args.Length != 0)
			{
				if (args[0].Equals("dump"))
				{
					AtlyssToolsLoader.Instance.GenerateDump();
				}
				else if (args[0].Equals("version"))
				{
					chatManager.SendMessage("AtlyssTools version: 1.0.4");
				}
				else
				{
					chatManager.SendMessage("Unknown subcommand '" + args[0] + "'");
					DisplayUsage(chatManager);
				}
			}
			return true;
		}

		public override bool DisplayUsage(ChatManager chatManager)
		{
			chatManager.SendMessage("Usage: /atlysstools [dump|version]");
			return true;
		}
	}
}