Decompiled source of MonsterDB v0.0.1

MonsterDB.dll

Decompiled 3 hours ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using MonsterDB.Solution;
using MonsterDB.Solution.Behaviors;
using MonsterDB.Solution.Methods;
using ServerSync;
using TMPro;
using UnityEngine;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: AssemblyFileVersion("0.0.1")]
[assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")]
[assembly: ComVisible(false)]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyProduct("MonsterDB")]
[assembly: AssemblyCompany("RustyMods")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyTitle("MonsterDB")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<6e0dc3a0-64de-4aaf-b3b3-b90948b54a8e>Embedded]
	internal sealed class <6e0dc3a0-64de-4aaf-b3b3-b90948b54a8e>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[<6e0dc3a0-64de-4aaf-b3b3-b90948b54a8e>Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class <2f40b76b-2716-41a7-ab0b-f9a69626cdb6>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <2f40b76b-2716-41a7-ab0b-f9a69626cdb6>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <2f40b76b-2716-41a7-ab0b-f9a69626cdb6>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	[<6e0dc3a0-64de-4aaf-b3b3-b90948b54a8e>Embedded]
	[CompilerGenerated]
	internal sealed class <62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace MonsterDB
{
	[BepInPlugin("RustyMods.MonsterDB", "MonsterDB", "0.0.1")]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	public class MonsterDBPlugin : BaseUnityPlugin
	{
		[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(0)]
		public enum Toggle
		{
			On = 1,
			Off = 0
		}

		[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(0)]
		private class ConfigurationManagerAttributes
		{
			[UsedImplicitly]
			public int? Order;

			[UsedImplicitly]
			public bool? Browsable;

			[UsedImplicitly]
			[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(2)]
			public string Category;

			[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(new byte[] { 2, 1 })]
			[UsedImplicitly]
			public Action<ConfigEntryBase> CustomDrawer;
		}

		internal const string ModName = "MonsterDB";

		internal const string ModVersion = "0.0.1";

		internal const string Author = "RustyMods";

		private const string ModGUID = "RustyMods.MonsterDB";

		private static readonly string ConfigFileName = "RustyMods.MonsterDB.cfg";

		private static readonly string ConfigFileFullPath;

		internal static string ConnectionError;

		private readonly Harmony _harmony = new Harmony("RustyMods.MonsterDB");

		public static readonly ManualLogSource MonsterDBLogger;

		public static readonly ConfigSync ConfigSync;

		public static GameObject m_root;

		public static MonsterDBPlugin m_plugin;

		public void Awake()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			m_plugin = this;
			m_root = new GameObject("root");
			Object.DontDestroyOnLoad((Object)(object)m_root);
			m_root.SetActive(false);
			Tutorial.Write();
			SpawnMan.Setup();
			TextureManager.ReadLocalTextures();
			CreatureManager.Setup();
			Initialization.ReadLocalFiles();
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			_harmony.PatchAll(executingAssembly);
			SetupWatcher();
		}

		private void OnDestroy()
		{
			((BaseUnityPlugin)this).Config.Save();
		}

		private void SetupWatcher()
		{
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName);
			fileSystemWatcher.Changed += ReadConfigValues;
			fileSystemWatcher.Created += ReadConfigValues;
			fileSystemWatcher.Renamed += ReadConfigValues;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
		}

		private void ReadConfigValues(object sender, FileSystemEventArgs e)
		{
			if (!File.Exists(ConfigFileFullPath))
			{
				return;
			}
			try
			{
				MonsterDBLogger.LogDebug((object)"ReadConfigValues called");
				((BaseUnityPlugin)this).Config.Reload();
			}
			catch
			{
				MonsterDBLogger.LogError((object)("There was an issue loading your " + ConfigFileName));
				MonsterDBLogger.LogError((object)"Please check your config entries for spelling and format!");
			}
		}

		private ConfigEntry<T> config<[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(2)] T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags);
			ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val);
			SyncedConfigEntry<T> syncedConfigEntry = ConfigSync.AddConfigEntry<T>(val2);
			syncedConfigEntry.SynchronizedConfig = synchronizedSetting;
			return val2;
		}

		private ConfigEntry<T> config<[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(2)] T>(string group, string name, T value, string description, bool synchronizedSetting = true)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting);
		}

		static MonsterDBPlugin()
		{
			string configPath = Paths.ConfigPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName;
			ConnectionError = "";
			MonsterDBLogger = Logger.CreateLogSource("MonsterDB");
			ConfigSync = new ConfigSync("RustyMods.MonsterDB")
			{
				DisplayName = "MonsterDB",
				CurrentVersion = "0.0.1",
				MinimumRequiredVersion = "0.0.1"
			};
			m_root = null;
			m_plugin = null;
		}
	}
	[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
	public static class RegisterAndCheckVersion
	{
		[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
		private static void Prefix(ZNetPeer peer, ref ZNet __instance)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			MonsterDBPlugin.MonsterDBLogger.LogDebug((object)"Registering version RPC handler");
			peer.m_rpc.Register<ZPackage>("MonsterDB_VersionCheck", (Action<ZRpc, ZPackage>)RpcHandlers.RPC_MonsterDB_Version);
			MonsterDBPlugin.MonsterDBLogger.LogInfo((object)"Invoking version check");
			ZPackage val = new ZPackage();
			val.Write("0.0.1");
			peer.m_rpc.Invoke("MonsterDB_VersionCheck", new object[1] { val });
		}
	}
	[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	public static class VerifyClient
	{
		private static bool Prefix(ZRpc rpc, ZPackage pkg, ref ZNet __instance)
		{
			if (!__instance.IsServer() || RpcHandlers.ValidatedPeers.Contains(rpc))
			{
				return true;
			}
			MonsterDBPlugin.MonsterDBLogger.LogWarning((object)("Peer (" + rpc.m_socket.GetHostName() + ") never sent version or couldn't due to previous disconnect, disconnecting"));
			rpc.Invoke("Error", new object[1] { 3 });
			return false;
		}

		private static void Postfix(ZNet __instance)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "MonsterDBRequestAdminSync", new object[1] { (object)new ZPackage() });
		}
	}
	[HarmonyPatch(typeof(FejdStartup), "ShowConnectError")]
	public class ShowConnectionError
	{
		[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
		private static void Postfix(FejdStartup __instance)
		{
			if (__instance.m_connectionFailedPanel.activeSelf)
			{
				__instance.m_connectionFailedError.fontSizeMax = 25f;
				__instance.m_connectionFailedError.fontSizeMin = 15f;
				TMP_Text connectionFailedError = __instance.m_connectionFailedError;
				connectionFailedError.text = connectionFailedError.text + "\n" + MonsterDBPlugin.ConnectionError;
			}
		}
	}
	[HarmonyPatch(typeof(ZNet), "Disconnect")]
	public static class RemoveDisconnectedPeerFromVerified
	{
		[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
		private static void Prefix(ZNetPeer peer, ref ZNet __instance)
		{
			if (__instance.IsServer())
			{
				MonsterDBPlugin.MonsterDBLogger.LogInfo((object)("Peer (" + peer.m_rpc.m_socket.GetHostName() + ") disconnected, removing from validated list"));
				RpcHandlers.ValidatedPeers.Remove(peer.m_rpc);
			}
		}
	}
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	public static class RpcHandlers
	{
		public static readonly List<ZRpc> ValidatedPeers = new List<ZRpc>();

		public static void RPC_MonsterDB_Version(ZRpc rpc, ZPackage pkg)
		{
			string text = pkg.ReadString();
			MonsterDBPlugin.MonsterDBLogger.LogInfo((object)("Version check, local: 0.0.1,  remote: " + text));
			if (text != "0.0.1")
			{
				MonsterDBPlugin.ConnectionError = "MonsterDB Installed: 0.0.1\n Needed: " + text;
				if (ZNet.instance.IsServer())
				{
					MonsterDBPlugin.MonsterDBLogger.LogWarning((object)("Peer (" + rpc.m_socket.GetHostName() + ") has incompatible version, disconnecting..."));
					rpc.Invoke("Error", new object[1] { 3 });
				}
			}
			else if (!ZNet.instance.IsServer())
			{
				MonsterDBPlugin.MonsterDBLogger.LogInfo((object)"Received same version from server!");
			}
			else
			{
				MonsterDBPlugin.MonsterDBLogger.LogInfo((object)("Adding peer (" + rpc.m_socket.GetHostName() + ") to validated list"));
				ValidatedPeers.Add(rpc);
			}
		}

		public static string ComputeHashForMod()
		{
			using SHA256 sHA = SHA256.Create();
			byte[] array = sHA.ComputeHash(File.ReadAllBytes(Assembly.GetExecutingAssembly().Location));
			StringBuilder stringBuilder = new StringBuilder();
			byte[] array2 = array;
			foreach (byte b in array2)
			{
				stringBuilder.Append(b.ToString("X2"));
			}
			return stringBuilder.ToString();
		}
	}
}
namespace MonsterDB.Solution
{
	public static class Commands
	{
		[HarmonyPatch(typeof(Terminal), "Awake")]
		private static class Terminal_Awake_Patch
		{
			private static void Postfix()
			{
				LoadCommands();
			}
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEventFailable <>9__1_0;

			public static ConsoleOptionsFetcher <>9__1_1;

			internal object <LoadCommands>b__1_0(ConsoleEventArgs args)
			{
				if (args.Length < 2)
				{
					return false;
				}
				switch (args[1])
				{
				case "help":
					Help();
					break;
				case "clone":
				case "reset":
				case "write":
				case "update":
				case "export":
				case "clone_item":
				case "write_item":
				case "write_spawn":
				{
					if (args.Length < 3 || !Object.op_Implicit((Object)(object)ZNetScene.instance))
					{
						return false;
					}
					string text = args[2];
					GameObject val = DataBase.TryGetGameObject(text);
					if ((Object)(object)val == (Object)null)
					{
						MonsterDBPlugin.MonsterDBLogger.LogInfo((object)("Failed to find prefab: " + text));
						return false;
					}
					switch (args[1])
					{
					case "write":
						Write(val);
						break;
					case "update":
						Update(val);
						break;
					case "clone":
					{
						if (args.Length < 4)
						{
							return false;
						}
						string name2 = args[3];
						CreatureManager.Clone(val, name2);
						break;
					}
					case "reset":
						CreatureManager.Reset(val);
						break;
					case "write_item":
						if (!Object.op_Implicit((Object)(object)val.GetComponent<ItemDrop>()))
						{
							return false;
						}
						ItemDataMethods.Write(val);
						break;
					case "clone_item":
					{
						if (args.Length < 4)
						{
							return false;
						}
						string name = args[3];
						ItemDataMethods.Clone(val, name);
						break;
					}
					case "write_spawn":
						MonsterDBPlugin.MonsterDBLogger.LogInfo((object)(SpawnMan.Write(val) ? "Wrote spawn data to disk" : "Failed to find spawn data"));
						break;
					case "export":
						CreatureManager.Export(text);
						break;
					}
					break;
				}
				case "reload":
					Initialization.RemoveAll();
					Initialization.CloneAll();
					Initialization.UpdateAll();
					break;
				case "import":
					CreatureManager.Import();
					Initialization.RemoveAll();
					Initialization.CloneAll();
					Initialization.UpdateAll();
					break;
				}
				return true;
			}

			internal List<string> <LoadCommands>b__1_1()
			{
				return new List<string> { "help", "write", "update", "clone", "reset", "reload", "write_item", "clone_item", "import", "export" };
			}
		}

		private static void LoadCommands()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			object obj = <>c.<>9__1_0;
			if (obj == null)
			{
				ConsoleEventFailable val = delegate(ConsoleEventArgs args)
				{
					if (args.Length < 2)
					{
						return false;
					}
					switch (args[1])
					{
					case "help":
						Help();
						break;
					case "clone":
					case "reset":
					case "write":
					case "update":
					case "export":
					case "clone_item":
					case "write_item":
					case "write_spawn":
					{
						if (args.Length < 3 || !Object.op_Implicit((Object)(object)ZNetScene.instance))
						{
							return false;
						}
						string text = args[2];
						GameObject val4 = DataBase.TryGetGameObject(text);
						if ((Object)(object)val4 == (Object)null)
						{
							MonsterDBPlugin.MonsterDBLogger.LogInfo((object)("Failed to find prefab: " + text));
							return false;
						}
						switch (args[1])
						{
						case "write":
							Write(val4);
							break;
						case "update":
							Update(val4);
							break;
						case "clone":
						{
							if (args.Length < 4)
							{
								return false;
							}
							string name2 = args[3];
							CreatureManager.Clone(val4, name2);
							break;
						}
						case "reset":
							CreatureManager.Reset(val4);
							break;
						case "write_item":
							if (!Object.op_Implicit((Object)(object)val4.GetComponent<ItemDrop>()))
							{
								return false;
							}
							ItemDataMethods.Write(val4);
							break;
						case "clone_item":
						{
							if (args.Length < 4)
							{
								return false;
							}
							string name = args[3];
							ItemDataMethods.Clone(val4, name);
							break;
						}
						case "write_spawn":
							MonsterDBPlugin.MonsterDBLogger.LogInfo((object)(SpawnMan.Write(val4) ? "Wrote spawn data to disk" : "Failed to find spawn data"));
							break;
						case "export":
							CreatureManager.Export(text);
							break;
						}
						break;
					}
					case "reload":
						Initialization.RemoveAll();
						Initialization.CloneAll();
						Initialization.UpdateAll();
						break;
					case "import":
						CreatureManager.Import();
						Initialization.RemoveAll();
						Initialization.CloneAll();
						Initialization.UpdateAll();
						break;
					}
					return true;
				};
				<>c.<>9__1_0 = val;
				obj = (object)val;
			}
			object obj2 = <>c.<>9__1_1;
			if (obj2 == null)
			{
				ConsoleOptionsFetcher val2 = () => new List<string> { "help", "write", "update", "clone", "reset", "reload", "write_item", "clone_item", "import", "export" };
				<>c.<>9__1_1 = val2;
				obj2 = (object)val2;
			}
			ConsoleCommand val3 = new ConsoleCommand("monsterdb", "use help to list out commands", (ConsoleEventFailable)obj, false, false, false, false, false, (ConsoleOptionsFetcher)obj2, false, false, true);
		}

		private static void Help()
		{
			foreach (string item in new List<string> { "write [prefabName] - write creature data to disk", "update [prefabName] - reads files and updates creature", "clone [prefabName] [cloneName] - clones creature, and saves to disk", "reset [prefabName] - resets creature data to original state", "reload - reloads all MonsterDB files", "write_item [prefabName] - Saves ItemData to file for reference", "clone_item [prefabName] [cloneName] - clones item to use as a new attack for creatures", "write_spawn [prefabName] - Writes to disk spawn data, of current spawn system", "import - Imports all creature files from Import folder, and reload data", "export [prefabName] - Writes creature data to a single YML document to share" })
			{
				MonsterDBPlugin.MonsterDBLogger.LogInfo((object)item);
			}
		}

		[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
		private static void Write(GameObject prefab)
		{
			if (CreatureManager.IsClone(prefab))
			{
				MonsterDBPlugin.MonsterDBLogger.LogInfo((object)"Creature is a MonsterDB clone, will not write to disk");
				return;
			}
			CreatureManager.Write(prefab, out var folderPath);
			MonsterDBPlugin.MonsterDBLogger.LogInfo((object)("Saved " + ((Object)prefab).name + " at:"));
			MonsterDBPlugin.MonsterDBLogger.LogInfo((object)folderPath);
		}

		[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
		private static void Update(GameObject prefab)
		{
			CreatureManager.Read(((Object)prefab).name, CreatureManager.IsClone(prefab));
			CreatureManager.Update(prefab);
			MonsterDBPlugin.MonsterDBLogger.LogInfo((object)("Updated " + ((Object)prefab).name));
		}
	}
	[Serializable]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	public class CharacterData
	{
		public string ClonedFrom = "";

		public string PrefabName = "";

		public string Name = "";

		public string Group = "";

		public string Faction = "";

		public bool Boss;

		public bool DoNotHideBossHUD;

		public string BossEvent = "";

		public string DefeatSetGlobalKey = "";

		public bool AISkipTarget;

		public float CrouchSpeed;

		public float WalkSpeed;

		public float Speed;

		public float TurnSpeed;

		public float RunSpeed;

		public float RunTurnSpeed;

		public float FlySlowSpeed;

		public float FlyFastSpeed;

		public float FlyTurnSpeed;

		public float Acceleration;

		public float JumpForce;

		public float JumpForceForward;

		public float JumpForceTiredFactor;

		public float AirControl;

		public bool CanSwim;

		public float SwimDepth;

		public float SwimSpeed;

		public float SwimTurnSpeed;

		public float SwimAcceleration;

		public string GroundTilt = "";

		public float GroundTiltSpeed;

		public bool Flying;

		public float JumpStaminaUsage;

		public bool DisableWhileSleeping;

		public bool TolerateWater;

		public bool TolerateFire;

		public bool TolerateSmoke;

		public bool TolerateTar;

		public float Health;

		public string BluntResistance = "Normal";

		public string SlashResistance = "Normal";

		public string PierceResistance = "Normal";

		public string ChopResistance = "Normal";

		public string PickaxeResistance = "Normal";

		public string FireResistance = "Normal";

		public string FrostResistance = "Normal";

		public string LightningResistance = "Normal";

		public string PoisonResistance = "Normal";

		public string SpiritResistance = "Normal";

		public bool StaggerWhenBlocked;

		public float StaggerDamageFactor;
	}
	[Serializable]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	public class EffectInfo
	{
		public string PrefabName = "";

		public bool Enabled;

		public int Variant = -1;

		public bool Attach;

		public bool Follow;

		public bool InheritParentRotation;

		public bool InheritParentScale;

		public bool MultiplyParentVisualScale;

		public bool RandomRotation;

		public bool Scale;

		public string ChildTransform = "";
	}
	[Serializable]
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	public class AttackData
	{
		public string OriginalPrefab = "";

		public string Name = "";

		public string AnimationState = "";

		public int ToolTier;

		public float Damage;

		public float Blunt;

		public float Slash;

		public float Pierce;

		public float Chop;

		public float Pickaxe;

		public float Fire;

		public float Frost;

		public float Lightning;

		public float Poison;

		public float Spirit;

		public float AttackForce;

		public bool Dodgeable;

		public bool Blockable;

		public string SpawnOnHit = "";

		public string SpawnOnHitTerrain = "";

		public string AttackStatusEffect = "";

		public float AttackStatusEffectChance;

		public string AttackType = "";

		public string AttackAnimation = "";

		public bool HitTerrain;

		public bool HitFriendly;

		public float DamageMultiplier;

		public float DamageMultiplierPerMissingHP;

		public float DamageMultiplierByTotalHealthMissing;

		public float ForceMultiplier;

		public float StaggerMultiplier;

		public float RecoilPushback;

		public int SelfDamage;

		public string AttackOriginJoint = "";

		public float AttackRange;

		public float AttackHeight;

		public float AttackOffset;

		public string SpawnOnTrigger = "";

		public bool ToggleFlying;

		public bool Attach;

		public float AttackAngle;

		public float AttackRayWidth;

		public float MaxYAngle;

		public bool LowerDamagePerHit;

		public bool HitThroughWalls;

		public float AttackRangeMinimum;

		public float AttackInterval;

		public float AttackMaxAngle;

		public string Projectile = "";
	}
	[Serializable]
	public class RandomItemData
	{
		[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(1)]
		public string PrefabName = "";

		public float Chance;
	}
	[Serializable]
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	public class ProjectileData
	{
		public string Name = "";

		public float Damage;

		public float Blunt;

		public float Slash;

		public float Pierce;

		public float Chop;

		public float Pickaxe;

		public float Fire;

		public float Frost;

		public float Lightning;

		public float Poison;

		public float Spirit;

		public float AOE;

		public bool Dodgeable;

		public bool Blockable;

		public float AttackForce;

		public float BackstabBonus;

		public string StatusEffect = "";

		public float HealthReturn;

		public bool CanHitWater;

		public float Duration;

		public float Gravity;

		public float Drag;

		public float RayRadius;

		public bool StayAfterHitStatic;

		public bool StayAfterHitDynamic;

		public float StayDuration;

		public bool Bounce;

		public bool BounceOnWater;

		public float BouncePower;

		public float BounceRoughness;

		public int MaxBounces;

		public float MinBounceVelocity;

		public bool RespawnItemOnHit;

		public bool SpawnOnDuration;

		public string SpawnOnHit = "";

		public float SpawnOnHitChance;

		public int SpawnCount;

		public List<string> RandomSpawnOnHit = new List<string>();

		public int RandomSpawnOnHitCount;

		public bool RandomSpawnSkipLava;

		public bool StaticHitOnly;

		public bool GroundHitOnly;

		public bool SpawnRandomRotation;
	}
	[Serializable]
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	public class MonsterAIData
	{
		public float ViewRange;

		public float ViewAngle;

		public float HearRange;

		public bool MistVision;

		public float IdleSoundInterval;

		public float IdleSoundChance;

		public string PathAgentType = "";

		public float MoveMinAngle;

		public bool SmoothMovement;

		public bool SerpentMovement;

		public float SerpentTurnRadius;

		public float JumpInterval;

		public float RandomCircleInterval;

		public float RandomMoveInterval;

		public float RandomMoveRange;

		public bool RandomFly;

		public float ChanceToTakeOff;

		public float ChanceToLand;

		public float GroundDuration;

		public float AirDuration;

		public float MaxLandAltitude;

		public float TakeoffTime;

		public float FlyAltitudeMin;

		public float FlyAltitudeMax;

		public float FlyAbsMinAltitude;

		public bool AvoidFire;

		public bool AfraidOfFire;

		public bool AvoidWater;

		public bool AvoidLava;

		public bool SkipLavaTargets;

		public bool Aggravatable;

		public bool PassiveAggressive;

		public string SpawnMessage = "";

		public string DeathMessage = "";

		public string AlertedMessage = "";

		public float FleeRange;

		public float FleeAngle;

		public float FleeInterval;

		public float AlertRange;

		public bool FleeIfHurtWhenTargetCannotBeReached;

		public float FleeUnreachableSinceAttack;

		public float FleeUnreachableSinceHurt;

		public bool FleeIfNotAlerted;

		public float FleeIfLowHealth;

		public float FleeTimeSinceHurt;

		public bool FleeInLava;

		public bool CirculateWhileCharging;

		public bool CirculateWhileChargingFlying;

		public bool EnableHuntPlayer;

		public bool AttackPlayerObjects;

		public int PrivateAreaTriggerThreshold;

		public float InterceptTimeMax;

		public float InterceptTimeMin;

		public float MaxChaseDistance;

		public float MinAttackInterval;

		public float CircleTargetInterval;

		public float CircleTargetDuration;

		public float CircleTargetDistance;

		public bool Sleeping;

		public float WakeupRange;

		public bool NoiseWakeup;

		public float MaxNoiseWakeupRange;

		public float WakeupDelayMin;

		public float WakeupDelayMax;

		public bool AvoidLand;

		public List<string> ConsumeItems = new List<string>();

		public float ConsumeRange;

		public float ConsumeSearchRange;

		public float ConsumeSearchInterval;
	}
	[Serializable]
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	public class AnimalAIData
	{
		public float ViewRange;

		public float ViewAngle;

		public float HearRange;

		public bool MistVision;

		public float IdleSoundInterval;

		public float IdleSoundChance;

		public string PathAgentType = "";

		public float MoveMinAngle;

		public bool SmoothMovement;

		public bool SerpentMovement;

		public float SerpentTurnRadius;

		public float JumpInterval;

		public float RandomCircleInterval;

		public float RandomMoveInterval;

		public float RandomMoveRange;

		public bool RandomFly;

		public float ChanceToTakeOff;

		public float ChanceToLand;

		public float GroundDuration;

		public float AirDuration;

		public float MaxLandAltitude;

		public float TakeoffTime;

		public float FlyAltitudeMin;

		public float FlyAltitudeMax;

		public float FlyAbsMinAltitude;

		public bool AvoidFire;

		public bool AfraidOfFire;

		public bool AvoidWater;

		public bool AvoidLava;

		public bool SkipLavaTargets;

		public bool Aggravatable;

		public bool PassiveAggressive;

		public string SpawnMessage = "";

		public string DeathMessage = "";

		public string AlertedMessage = "";

		public float FleeRange;

		public float FleeAngle;

		public float FleeInterval;
	}
	[Serializable]
	public class CharacterDropData
	{
		[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(1)]
		public string PrefabName = "";

		public int AmountMin;

		public int AmountMax;

		public float Chance;

		public bool OnePerPlayer;

		public bool LevelMultiplier;

		public bool DoNotScale;
	}
	[Serializable]
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	public class TameableData
	{
		public float FedDuration;

		public float TamingTime;

		public bool StartTamed;

		public bool Commandable;

		public float UnsummonDistance;

		public float UnsummonOnOwnerLogoutSeconds;

		public string LevelUpOwnerSkill = "";

		public float LevelUpFactor;

		public bool DropSaddleOnDeath;

		public List<string> RandomStartingName = new List<string>();
	}
	[Serializable]
	public class ProcreationData
	{
		public float UpdateInterval;

		public float TotalCheckRange;

		public int MaxCreatures;

		public float PartnerCheckRange;

		public float PregnancyChance;

		public float PregnancyDuration;

		public int RequiredLovePoints;

		[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(1)]
		public string Offspring = "";

		public int MinOffspringLevel;

		public float SpawnOffset;
	}
	[Serializable]
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	public class NPCTalkData
	{
		public string Name = "";

		public float MaxRange;

		public float GreetRange;

		public float ByeRange;

		public float Offset;

		public float MinTalkInterval;

		public float HideDialogueDelay;

		public float RandomTalkInterval;

		public float RandomTalkChance;

		public List<string> RandomTalk = new List<string>();

		public List<string> RandomTalkInFactionBase = new List<string>();

		public List<string> RandomGreets = new List<string>();

		public List<string> RandomGoodbye = new List<string>();

		public List<string> PrivateAreaAlarm = new List<string>();

		public List<string> Aggravated = new List<string>();
	}
	[Serializable]
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	public class CreatureData
	{
		public VisualMethods.ScaleData m_scale = new VisualMethods.ScaleData();

		public VisualMethods.ScaleData m_ragdollScale = new VisualMethods.ScaleData();

		public Dictionary<string, VisualMethods.MaterialData> m_materials = new Dictionary<string, VisualMethods.MaterialData>();

		public CharacterData m_characterData = new CharacterData();

		public CharacterEffects m_effects = new CharacterEffects();

		public List<ItemAttackData> m_defaultItems = new List<ItemAttackData>();

		public List<ItemAttackData> m_randomWeapons = new List<ItemAttackData>();

		public List<ItemAttackData> m_randomArmors = new List<ItemAttackData>();

		public List<ItemAttackData> m_randomShields = new List<ItemAttackData>();

		public List<RandomItemData> m_randomItems = new List<RandomItemData>();

		public List<RandomItemSetsData> m_randomSets = new List<RandomItemSetsData>();

		public MonsterAIData m_monsterAIData = new MonsterAIData();

		public AnimalAIData m_animalAIData = new AnimalAIData();

		public List<CharacterDropData> m_characterDrops = new List<CharacterDropData>();

		public TameableData m_tameable = new TameableData();

		public ProcreationData m_procreation = new ProcreationData();

		public NPCTalkData m_npcTalk = new NPCTalkData();
	}
	[Serializable]
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	public class ItemAttackData
	{
		public AttackData m_attackData = new AttackData();

		public ItemEffects m_effects = new ItemEffects();
	}
	[Serializable]
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	public class RandomItemSetsData
	{
		public string m_name = "";

		public List<ItemAttackData> m_items = new List<ItemAttackData>();
	}
	[Serializable]
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	public class CharacterEffects
	{
		public List<EffectInfo> m_hitEffects = new List<EffectInfo>();

		public List<EffectInfo> m_critHitEffects = new List<EffectInfo>();

		public List<EffectInfo> m_backstabHitEffects = new List<EffectInfo>();

		public List<EffectInfo> m_deathEffects = new List<EffectInfo>();

		public List<EffectInfo> m_waterEffects = new List<EffectInfo>();

		public List<EffectInfo> m_tarEffects = new List<EffectInfo>();

		public List<EffectInfo> m_slideEffects = new List<EffectInfo>();

		public List<EffectInfo> m_jumpEffects = new List<EffectInfo>();

		public List<EffectInfo> m_flyingContinuousEffects = new List<EffectInfo>();

		public List<EffectInfo> m_pickupEffects = new List<EffectInfo>();

		public List<EffectInfo> m_dropEffects = new List<EffectInfo>();

		public List<EffectInfo> m_consumeItemEffects = new List<EffectInfo>();

		public List<EffectInfo> m_equipEffects = new List<EffectInfo>();

		public List<EffectInfo> m_perfectBlockEffects = new List<EffectInfo>();

		public List<EffectInfo> m_alertedEffects = new List<EffectInfo>();

		public List<EffectInfo> m_idleSounds = new List<EffectInfo>();

		public List<EffectInfo> m_wakeupEffects = new List<EffectInfo>();

		public List<EffectInfo> m_birthEffects = new List<EffectInfo>();

		public List<EffectInfo> m_loveEffects = new List<EffectInfo>();

		public List<EffectInfo> m_tamedEffects = new List<EffectInfo>();

		public List<EffectInfo> m_soothEffects = new List<EffectInfo>();

		public List<EffectInfo> m_petEffects = new List<EffectInfo>();

		public List<EffectInfo> m_unSummonEffects = new List<EffectInfo>();

		public List<EffectInfo> m_randomTalkFX = new List<EffectInfo>();

		public List<EffectInfo> m_randomGreetFX = new List<EffectInfo>();

		public List<EffectInfo> m_randomGoodbyeFX = new List<EffectInfo>();
	}
	[Serializable]
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	public class ItemEffects
	{
		public List<EffectInfo> m_hitEffects = new List<EffectInfo>();

		public List<EffectInfo> m_hitTerrainEffects = new List<EffectInfo>();

		public List<EffectInfo> m_blockEffects = new List<EffectInfo>();

		public List<EffectInfo> m_startEffects = new List<EffectInfo>();

		public List<EffectInfo> m_holdStartEffects = new List<EffectInfo>();

		public List<EffectInfo> m_equipEffects = new List<EffectInfo>();

		public List<EffectInfo> m_unEquipEffects = new List<EffectInfo>();

		public List<EffectInfo> m_triggerEffects = new List<EffectInfo>();

		public List<EffectInfo> m_trailStartEffects = new List<EffectInfo>();
	}
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	public static class CreatureManager
	{
		[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(0)]
		[HarmonyPatch(typeof(ZNet), "Awake")]
		private static class ZNet_Awake_Patch
		{
			private static void Postfix()
			{
				UpdateServer();
			}
		}

		public static readonly string m_folderPath;

		public static readonly string m_creatureFolderPath;

		public static readonly string m_cloneFolderPath;

		private static readonly string m_exportFolderPath;

		private static readonly string m_importFolderPath;

		private static readonly CustomSyncedValue<string> m_serverDataFiles;

		private static readonly Dictionary<string, CreatureData> m_originalData;

		public static Dictionary<string, CreatureData> m_data;

		public static readonly Dictionary<string, GameObject> m_clones;

		private static FileSystemWatcher m_creatureWatcher;

		private static FileSystemWatcher m_cloneWatcher;

		private static void UpdateServer()
		{
			if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer())
			{
				MonsterDBPlugin.MonsterDBLogger.LogDebug((object)"Server: Updating server sync creature & clones");
				ISerializer serializer = new SerializerBuilder().Build();
				m_serverDataFiles.Value = serializer.Serialize(m_data);
			}
		}

		public static bool IsClone(GameObject creature)
		{
			return m_clones.ContainsKey(((Object)creature).name);
		}

		public static void Setup()
		{
			m_serverDataFiles.ValueChanged += ReadServerFiles;
			SetupFileWatch();
		}

		private static void SetupFileWatch()
		{
			if (!Directory.Exists(m_folderPath))
			{
				Directory.CreateDirectory(m_folderPath);
			}
			if (!Directory.Exists(m_creatureFolderPath))
			{
				Directory.CreateDirectory(m_creatureFolderPath);
			}
			if (!Directory.Exists(m_cloneFolderPath))
			{
				Directory.CreateDirectory(m_cloneFolderPath);
			}
			if (!Directory.Exists(m_importFolderPath))
			{
				Directory.CreateDirectory(m_importFolderPath);
			}
			m_creatureWatcher = new FileSystemWatcher(m_creatureFolderPath, "*.yml")
			{
				EnableRaisingEvents = true,
				IncludeSubdirectories = true,
				SynchronizingObject = ThreadingHelper.SynchronizingObject,
				NotifyFilter = NotifyFilters.LastWrite
			};
			m_creatureWatcher.Changed += OnCreatureFileChange;
			m_cloneWatcher = new FileSystemWatcher(m_cloneFolderPath, "*.yml")
			{
				EnableRaisingEvents = true,
				IncludeSubdirectories = true,
				SynchronizingObject = ThreadingHelper.SynchronizingObject,
				NotifyFilter = NotifyFilters.LastWrite
			};
			m_cloneWatcher.Changed += OnCloneFileChange;
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(m_importFolderPath, "*.yml")
			{
				EnableRaisingEvents = true,
				IncludeSubdirectories = true,
				SynchronizingObject = ThreadingHelper.SynchronizingObject,
				NotifyFilter = NotifyFilters.LastWrite
			};
			fileSystemWatcher.Changed += OnImportFileChange;
		}

		private static void OnImportFileChange(object sender, FileSystemEventArgs e)
		{
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer())
			{
				return;
			}
			try
			{
				string fileName = Path.GetFileName(e.Name);
				IDeserializer deserializer = new DeserializerBuilder().Build();
				string input = File.ReadAllText(e.FullPath);
				CreatureData creatureData = deserializer.Deserialize<CreatureData>(input);
				GameObject val = DataBase.TryGetGameObject(creatureData.m_characterData.PrefabName);
				if (!((Object)(object)val == (Object)null))
				{
					m_data[creatureData.m_characterData.PrefabName] = creatureData;
					UpdateServer();
					Update(val);
					MonsterDBPlugin.MonsterDBLogger.LogDebug((object)(((Object)val).name + " data changed: " + fileName));
				}
			}
			catch
			{
				Helpers.LogParseFailure(e.FullPath);
			}
		}

		private static void OnCloneFileChange(object sender, FileSystemEventArgs e)
		{
			if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer())
			{
				string fileName = Path.GetFileName(e.Name);
				string cloneFolderName = GetCloneFolderName(e.FullPath);
				GameObject val = DataBase.TryGetGameObject(cloneFolderName);
				if (!((Object)(object)val == (Object)null))
				{
					Read(cloneFolderName, isClone: true);
					Update(val);
					MonsterDBPlugin.MonsterDBLogger.LogDebug((object)(cloneFolderName + " data changed: " + fileName));
				}
			}
		}

		private static void OnCreatureFileChange(object sender, FileSystemEventArgs e)
		{
			if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer())
			{
				string fileName = Path.GetFileName(e.Name);
				string creatureFolderName = GetCreatureFolderName(e.FullPath);
				GameObject val = DataBase.TryGetGameObject(creatureFolderName);
				if (!((Object)(object)val == (Object)null))
				{
					Read(creatureFolderName);
					Update(val);
					MonsterDBPlugin.MonsterDBLogger.LogDebug((object)(creatureFolderName + " data changed: " + fileName));
				}
			}
		}

		private static string GetCloneFolderName(string fullPath)
		{
			return fullPath.Replace(m_cloneFolderPath, string.Empty).Split(new char[1] { Path.DirectorySeparatorChar })[1];
		}

		private static string GetCreatureFolderName(string fullPath)
		{
			return fullPath.Replace(m_creatureFolderPath, string.Empty).Split(new char[1] { Path.DirectorySeparatorChar })[1];
		}

		private static void ReadServerFiles()
		{
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || ZNet.instance.IsServer())
			{
				return;
			}
			IDeserializer deserializer = new DeserializerBuilder().Build();
			try
			{
				Initialization.ResetAll();
				m_data = deserializer.Deserialize<Dictionary<string, CreatureData>>(m_serverDataFiles.Value);
				Initialization.RemoveAll();
				Initialization.CloneAll();
				Initialization.UpdateAll();
				MonsterDBPlugin.MonsterDBLogger.LogDebug((object)"Server updated MonsterDB Files");
			}
			catch
			{
				MonsterDBPlugin.MonsterDBLogger.LogDebug((object)"Failed to parse server synced data");
			}
		}

		public static void Delete(GameObject critter, bool loop = true)
		{
			string prefabName = ((Object)critter).name + "_ragdoll";
			GameObject val = DataBase.TryGetGameObject(prefabName);
			if ((Object)(object)val != (Object)null)
			{
				Delete(val, loop);
			}
			Helpers.RemoveFromZNetScene(critter);
			Helpers.RemoveFromObjectDB(critter);
			if (!loop)
			{
				m_clones.Remove(((Object)critter).name);
			}
			Transform val2 = MonsterDBPlugin.m_root.transform.Find(((Object)critter).name);
			if (Object.op_Implicit((Object)(object)val2))
			{
				Object.Destroy((Object)(object)((Component)val2).gameObject);
			}
		}

		private static void Save(GameObject critter, string cloneFrom)
		{
			if (!m_originalData.ContainsKey(((Object)critter).name))
			{
				CreatureData creatureData = new CreatureData();
				VisualMethods.Save(critter, ref creatureData);
				HumanoidMethods.Save(critter, cloneFrom, ref creatureData);
				CharacterMethods.Save(critter, cloneFrom, ref creatureData);
				MonsterAIMethods.Save(critter, ref creatureData);
				AnimalAIMethods.Save(critter, ref creatureData);
				CharacterDropMethods.Save(critter, ref creatureData);
				TameableMethods.Save(critter, ref creatureData);
				ProcreationMethods.Save(critter, ref creatureData);
				NPCTalkMethods.Save(critter, ref creatureData);
				m_originalData[((Object)critter).name] = creatureData;
			}
		}

		public static void Write(GameObject critter, out string folderPath, bool clone = false, string clonedFrom = "")
		{
			m_creatureWatcher.EnableRaisingEvents = false;
			m_cloneWatcher.EnableRaisingEvents = false;
			if (!Directory.Exists(m_folderPath))
			{
				Directory.CreateDirectory(m_folderPath);
			}
			if (!Directory.Exists(m_creatureFolderPath))
			{
				Directory.CreateDirectory(m_creatureFolderPath);
			}
			string obj = (clone ? m_cloneFolderPath : m_creatureFolderPath);
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			folderPath = obj + directorySeparatorChar + ((Object)critter).name;
			if (Directory.Exists(folderPath))
			{
				Directory.Delete(folderPath, recursive: true);
			}
			Directory.CreateDirectory(folderPath);
			VisualMethods.Write(critter, folderPath);
			HumanoidMethods.Write(critter, folderPath, clonedFrom);
			CharacterMethods.Write(critter, folderPath, clonedFrom);
			MonsterAIMethods.Write(critter, folderPath);
			AnimalAIMethods.Write(critter, folderPath);
			CharacterDropMethods.Write(critter, folderPath);
			TameableMethods.Write(critter, folderPath);
			ProcreationMethods.Write(critter, folderPath);
			NPCTalkMethods.Write(critter, folderPath);
			m_creatureWatcher.EnableRaisingEvents = true;
			m_cloneWatcher.EnableRaisingEvents = true;
		}

		public static void Read(string creatureName, bool isClone = false)
		{
			string obj = (isClone ? m_cloneFolderPath : m_creatureFolderPath);
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			string text = obj + directorySeparatorChar + creatureName;
			if (Directory.Exists(text))
			{
				CreatureData creatureData = new CreatureData();
				VisualMethods.Read(text, ref creatureData);
				HumanoidMethods.Read(text, ref creatureData);
				CharacterMethods.Read(text, ref creatureData);
				MonsterAIMethods.Read(text, ref creatureData);
				AnimalAIMethods.Read(text, ref creatureData);
				CharacterDropMethods.Read(text, ref creatureData);
				TameableMethods.Read(text, ref creatureData);
				ProcreationMethods.Read(text, ref creatureData);
				NPCTalkMethods.Read(text, ref creatureData);
				m_data[creatureName] = creatureData;
				UpdateServer();
			}
		}

		public static void Update(GameObject critter)
		{
			if (m_data.TryGetValue(((Object)critter).name, out var value))
			{
				Save(critter, value.m_characterData.ClonedFrom);
				VisualMethods.Update(critter, value);
				TameableMethods.Update(critter, value);
				HumanoidMethods.Update(critter, value);
				CharacterMethods.Update(critter, value);
				MonsterAIMethods.Update(critter, value);
				AnimalAIMethods.Update(critter, value);
				CharacterDropMethods.Update(critter, value);
				ProcreationMethods.Update(critter, value);
				NPCTalkMethods.Update(critter, value);
			}
		}

		public static void Reset(GameObject critter)
		{
			if (m_originalData.TryGetValue(((Object)critter).name, out var value))
			{
				VisualMethods.Update(critter, value);
				HumanoidMethods.Update(critter, value);
				CharacterMethods.Update(critter, value);
				MonsterAIMethods.Update(critter, value);
				AnimalAIMethods.Update(critter, value);
				CharacterDropMethods.Update(critter, value);
				TameableMethods.Update(critter, value);
				ProcreationMethods.Update(critter, value);
				NPCTalkMethods.Update(critter, value);
				MonsterDBPlugin.MonsterDBLogger.LogInfo((object)("Reset: " + ((Object)critter).name));
			}
		}

		public static void Clone(GameObject critter, string name, bool saveToDisk = true)
		{
			if (!Directory.Exists(m_folderPath))
			{
				Directory.CreateDirectory(m_folderPath);
			}
			if (!Directory.Exists(m_cloneFolderPath))
			{
				Directory.CreateDirectory(m_cloneFolderPath);
			}
			GameObject val = Object.Instantiate<GameObject>(critter, MonsterDBPlugin.m_root.transform, false);
			((Object)val).name = name;
			Dictionary<string, Material> ragDollMats = VisualMethods.CloneMaterials(val);
			CharacterMethods.CloneRagDoll(val, ragDollMats);
			HumanoidMethods.CloneRagDoll(val, ragDollMats);
			HumanoidMethods.CloneItems(val);
			Helpers.RegisterToZNetScene(val);
			m_clones[((Object)val).name] = val;
			if (saveToDisk)
			{
				Write(val, out var folderPath, clone: true, ((Object)critter).name);
				Read(((Object)val).name, isClone: true);
				MonsterDBPlugin.MonsterDBLogger.LogInfo((object)("Cloned " + ((Object)critter).name + " as " + ((Object)val).name));
				MonsterDBPlugin.MonsterDBLogger.LogInfo((object)folderPath);
			}
		}

		public static void Export(string creatureName)
		{
			if (!Directory.Exists(m_folderPath))
			{
				Directory.CreateDirectory(m_folderPath);
			}
			if (!Directory.Exists(m_exportFolderPath))
			{
				Directory.CreateDirectory(m_exportFolderPath);
			}
			if (!Directory.Exists(m_importFolderPath))
			{
				Directory.CreateDirectory(m_importFolderPath);
			}
			if (m_data.TryGetValue(creatureName, out var value))
			{
				ISerializer serializer = new SerializerBuilder().Build();
				string contents = serializer.Serialize(value);
				string exportFolderPath = m_exportFolderPath;
				char directorySeparatorChar = Path.DirectorySeparatorChar;
				string text = exportFolderPath + directorySeparatorChar + creatureName + ".yml";
				File.WriteAllText(text, contents);
				MonsterDBPlugin.MonsterDBLogger.LogDebug((object)"Exported creature data: ");
				MonsterDBPlugin.MonsterDBLogger.LogDebug((object)text);
			}
		}

		public static void Import()
		{
			if (!Directory.Exists(m_folderPath))
			{
				Directory.CreateDirectory(m_folderPath);
			}
			if (!Directory.Exists(m_importFolderPath))
			{
				Directory.CreateDirectory(m_importFolderPath);
			}
			string[] files = Directory.GetFiles(m_importFolderPath);
			if (files.Length == 0)
			{
				return;
			}
			IDeserializer deserializer = new DeserializerBuilder().Build();
			int num = 0;
			string[] array = files;
			foreach (string text in array)
			{
				try
				{
					string input = File.ReadAllText(text);
					CreatureData creatureData = deserializer.Deserialize<CreatureData>(input);
					string prefabName = creatureData.m_characterData.PrefabName;
					m_data[prefabName] = creatureData;
					num++;
				}
				catch
				{
					Helpers.LogParseFailure(text);
				}
			}
			MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Imported {num} creature data files");
		}

		static CreatureManager()
		{
			string configPath = Paths.ConfigPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			m_folderPath = configPath + directorySeparatorChar + "MonsterDB";
			string folderPath = m_folderPath;
			directorySeparatorChar = Path.DirectorySeparatorChar;
			m_creatureFolderPath = folderPath + directorySeparatorChar + "Creatures";
			string folderPath2 = m_folderPath;
			directorySeparatorChar = Path.DirectorySeparatorChar;
			m_cloneFolderPath = folderPath2 + directorySeparatorChar + "Clones";
			string folderPath3 = m_folderPath;
			directorySeparatorChar = Path.DirectorySeparatorChar;
			m_exportFolderPath = folderPath3 + directorySeparatorChar + "Export";
			string folderPath4 = m_folderPath;
			directorySeparatorChar = Path.DirectorySeparatorChar;
			m_importFolderPath = folderPath4 + directorySeparatorChar + "Import";
			m_serverDataFiles = new CustomSyncedValue<string>(MonsterDBPlugin.ConfigSync, "MonsterDB_ServerFiles", "");
			m_originalData = new Dictionary<string, CreatureData>();
			m_data = new Dictionary<string, CreatureData>();
			m_clones = new Dictionary<string, GameObject>();
			m_creatureWatcher = null;
			m_cloneWatcher = null;
		}
	}
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	public static class DataBase
	{
		[HarmonyPriority(800)]
		[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(0)]
		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private static class CacheResources_Patch
		{
			private static void Postfix()
			{
				CacheResources();
			}
		}

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

		public static readonly Dictionary<string, Texture2D> m_textures = new Dictionary<string, Texture2D>();

		private static void CacheResources()
		{
			List<GameObject> list = Resources.FindObjectsOfTypeAll<GameObject>().ToList();
			foreach (GameObject item in list)
			{
				m_items[((Object)item).name] = item;
			}
			List<Texture2D> source = Resources.FindObjectsOfTypeAll<Texture2D>().ToList();
			foreach (Texture2D item2 in source.Where([<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(0)] (Texture2D texture) => !Utility.IsNullOrWhiteSpace(((Object)texture).name)))
			{
				m_textures[((Object)item2).name] = item2;
			}
			string texturePath = TextureManager.m_texturePath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			string path = texturePath + directorySeparatorChar + "Resources.txt";
			if (!File.Exists(path))
			{
				List<string> contents = m_textures.Keys.ToList();
				File.WriteAllLines(path, contents);
			}
		}

		[return: <2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(2)]
		public static GameObject TryGetGameObject(string prefabName)
		{
			if (!Object.op_Implicit((Object)(object)ZNetScene.instance) || !Object.op_Implicit((Object)(object)ObjectDB.instance))
			{
				return null;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName);
			if ((Object)(object)itemPrefab != (Object)null)
			{
				return itemPrefab;
			}
			itemPrefab = ZNetScene.instance.GetPrefab(prefabName);
			if ((Object)(object)itemPrefab != (Object)null)
			{
				return itemPrefab;
			}
			if (ItemDataMethods.m_clonedItems.TryGetValue(prefabName, out var value))
			{
				return value;
			}
			GameObject value2;
			return (!m_items.TryGetValue(prefabName, out value2)) ? null : value2;
		}

		public static bool TryGetTexture(string textureName, out Texture2D texture)
		{
			if (TextureManager.m_customTextures.TryGetValue(textureName, out texture))
			{
				return true;
			}
			return m_textures.TryGetValue(textureName, out texture);
		}
	}
	public static class HumanMan
	{
		public static void Create()
		{
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Expected O, but got Unknown
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Expected O, but got Unknown
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Expected O, but got Unknown
			//IL_0356: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ba: Expected O, but got Unknown
			//IL_040e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0415: Expected O, but got Unknown
			//IL_0520: Unknown result type (might be due to invalid IL or missing references)
			//IL_0601: Unknown result type (might be due to invalid IL or missing references)
			//IL_0606: Unknown result type (might be due to invalid IL or missing references)
			//IL_061b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0622: Unknown result type (might be due to invalid IL or missing references)
			//IL_062a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0635: Unknown result type (might be due to invalid IL or missing references)
			//IL_0641: Expected O, but got Unknown
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Expected O, but got Unknown
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Expected O, but got Unknown
			GameObject prefab = ZNetScene.instance.GetPrefab("Player");
			Player val = default(Player);
			if (Object.op_Implicit((Object)(object)prefab) && prefab.TryGetComponent<Player>(ref val))
			{
				GameObject val2 = Object.Instantiate<GameObject>(prefab, MonsterDBPlugin.m_root.transform, false);
				((Object)val2).name = "Human";
				Object.Destroy((Object)(object)val2.GetComponent<PlayerController>());
				Object.Destroy((Object)(object)val2.GetComponent<Player>());
				Object.Destroy((Object)(object)val2.GetComponent<Talker>());
				Object.Destroy((Object)(object)val2.GetComponent<Skills>());
				ZNetView val3 = default(ZNetView);
				if (val2.TryGetComponent<ZNetView>(ref val3))
				{
					val3.m_persistent = true;
				}
				Human human = val2.AddComponent<Human>();
				((Object)human).name = ((Object)val2).name;
				((Character)human).m_name = "Human";
				((Character)human).m_group = "Humans";
				((Character)human).m_faction = (Faction)2;
				((Character)human).m_crouchSpeed = ((Character)val).m_crouchSpeed;
				((Character)human).m_walkSpeed = ((Character)val).m_walkSpeed;
				((Character)human).m_speed = ((Character)val).m_speed;
				((Character)human).m_runSpeed = ((Character)val).m_runSpeed;
				((Character)human).m_runTurnSpeed = ((Character)val).m_runTurnSpeed;
				((Character)human).m_acceleration = ((Character)val).m_acceleration;
				((Character)human).m_jumpForce = ((Character)val).m_jumpForce;
				((Character)human).m_jumpForceForward = ((Character)val).m_jumpForceForward;
				((Character)human).m_jumpForceTiredFactor = ((Character)val).m_jumpForceForward;
				((Character)human).m_airControl = ((Character)val).m_airControl;
				((Character)human).m_canSwim = true;
				((Character)human).m_swimDepth = ((Character)val).m_swimDepth;
				((Character)human).m_swimSpeed = ((Character)val).m_swimSpeed;
				((Character)human).m_swimTurnSpeed = ((Character)val).m_swimTurnSpeed;
				((Character)human).m_swimAcceleration = ((Character)val).m_swimAcceleration;
				((Character)human).m_groundTilt = ((Character)val).m_groundTilt;
				((Character)human).m_groundTiltSpeed = ((Character)val).m_groundTiltSpeed;
				((Character)human).m_jumpStaminaUsage = ((Character)val).m_jumpStaminaUsage;
				((Character)human).m_eye = Utils.FindChild(val2.transform, "EyePos", (IterativeSearchType)0);
				((Character)human).m_hitEffects = ((Character)val).m_hitEffects;
				((Character)human).m_critHitEffects = ((Character)val).m_critHitEffects;
				((Character)human).m_backstabHitEffects = ((Character)val).m_backstabHitEffects;
				GameObject val4 = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("Player_ragdoll"), MonsterDBPlugin.m_root.transform, false);
				Ragdoll val5 = default(Ragdoll);
				EffectList val6;
				if (val4.TryGetComponent<Ragdoll>(ref val5))
				{
					val5.m_ttl = 8f;
					Ragdoll obj = val5;
					val6 = new EffectList();
					val6.m_effectPrefabs = (EffectData[])(object)new EffectData[1]
					{
						new EffectData
						{
							m_prefab = ZNetScene.instance.GetPrefab("vfx_corpse_destruction_small"),
							m_enabled = true
						}
					};
					obj.m_removeEffect = val6;
					val5.m_float = true;
					val5.m_dropItems = true;
				}
				((Object)val4).name = "human_ragdoll";
				val4.AddComponent<Visuals>();
				Helpers.RegisterToZNetScene(val4);
				val6 = new EffectList();
				val6.m_effectPrefabs = (EffectData[])(object)new EffectData[2]
				{
					new EffectData
					{
						m_prefab = ZNetScene.instance.GetPrefab("vfx_player_death"),
						m_enabled = true
					},
					new EffectData
					{
						m_prefab = val4,
						m_enabled = true
					}
				};
				((Character)human).m_deathEffects = val6;
				((Character)human).m_waterEffects = ((Character)val).m_waterEffects;
				((Character)human).m_tarEffects = ((Character)val).m_tarEffects;
				((Character)human).m_slideEffects = ((Character)val).m_slideEffects;
				((Character)human).m_jumpEffects = ((Character)val).m_jumpEffects;
				((Character)human).m_flyingContinuousEffect = ((Character)val).m_flyingContinuousEffect;
				((Character)human).m_tolerateWater = true;
				((Character)human).m_health = 100f;
				((Character)human).m_damageModifiers = ((Character)val).m_damageModifiers;
				((Character)human).m_staggerWhenBlocked = true;
				((Character)human).m_staggerDamageFactor = ((Character)val).m_staggerDamageFactor;
				((Humanoid)human).m_defaultItems = ((Humanoid)val).m_defaultItems;
				((Humanoid)human).m_randomWeapon = ((Humanoid)val).m_randomWeapon;
				((Humanoid)human).m_randomArmor = ((Humanoid)val).m_randomArmor;
				((Humanoid)human).m_randomShield = ((Humanoid)val).m_randomShield;
				ItemSet[] array = new ItemSet[2];
				ItemSet val7 = new ItemSet();
				val7.m_name = "Leather";
				val7.m_items = (GameObject[])(object)new GameObject[3]
				{
					ZNetScene.instance.GetPrefab("ArmorLeatherChest"),
					ZNetScene.instance.GetPrefab("ArmorLeatherLegs"),
					ZNetScene.instance.GetPrefab("Torch")
				};
				array[0] = val7;
				val7 = new ItemSet();
				val7.m_name = "Bronze";
				val7.m_items = (GameObject[])(object)new GameObject[4]
				{
					ZNetScene.instance.GetPrefab("ArmorBronzeChest"),
					ZNetScene.instance.GetPrefab("ArmorBronzeLegs"),
					ZNetScene.instance.GetPrefab("ShieldBronzeBuckler"),
					ZNetScene.instance.GetPrefab("KnifeCopper")
				};
				array[1] = val7;
				((Humanoid)human).m_randomSets = (ItemSet[])(object)array;
				((Humanoid)human).m_randomItems = ((Humanoid)val).m_randomItems;
				((Humanoid)human).m_unarmedWeapon = ((Humanoid)val).m_unarmedWeapon;
				((Humanoid)human).m_pickupEffects = val.m_autopickupEffects;
				((Humanoid)human).m_dropEffects = ((Humanoid)val).m_dropEffects;
				((Humanoid)human).m_consumeItemEffects = ((Humanoid)val).m_consumeItemEffects;
				((Humanoid)human).m_equipEffects = val.m_equipStartEffects;
				((Humanoid)human).m_perfectBlockEffect = ((Humanoid)val).m_perfectBlockEffect;
				MonsterAI val8 = val2.AddComponent<MonsterAI>();
				((BaseAI)val8).m_viewRange = 30f;
				((BaseAI)val8).m_viewAngle = 90f;
				((BaseAI)val8).m_hearRange = 9999f;
				((BaseAI)val8).m_idleSoundInterval = 10f;
				((BaseAI)val8).m_idleSoundChance = 0f;
				((BaseAI)val8).m_pathAgentType = (AgentType)1;
				((BaseAI)val8).m_moveMinAngle = 90f;
				((BaseAI)val8).m_smoothMovement = true;
				((BaseAI)val8).m_jumpInterval = 10f;
				((BaseAI)val8).m_randomCircleInterval = 2f;
				((BaseAI)val8).m_randomMoveInterval = 30f;
				((BaseAI)val8).m_randomMoveRange = 3f;
				val8.m_alertRange = 20f;
				val8.m_circulateWhileCharging = true;
				val8.m_privateAreaTriggerTreshold = 4;
				val8.m_interceptTimeMax = 2f;
				val8.m_maxChaseDistance = 300f;
				val8.m_circleTargetInterval = 8f;
				val8.m_circleTargetDuration = 6f;
				val8.m_circleTargetDistance = 8f;
				val8.m_consumeRange = 2f;
				val8.m_consumeSearchRange = 5f;
				val8.m_consumeSearchInterval = 10f;
				val8.m_consumeItems = new List<ItemDrop>();
				CharacterDrop val9 = val2.AddComponent<CharacterDrop>();
				val9.m_drops = new List<Drop>
				{
					new Drop
					{
						m_prefab = ZNetScene.instance.GetPrefab("Coins"),
						m_amountMin = 1,
						m_amountMax = 10,
						m_chance = 0.25f,
						m_levelMultiplier = true
					}
				};
				GameObject prefab2 = ZNetScene.instance.GetPrefab("Boar");
				Tameable val10 = default(Tameable);
				if (prefab2.TryGetComponent<Tameable>(ref val10))
				{
					Tameable val11 = val2.AddComponent<Tameable>();
					val11.m_fedDuration = 600f;
					val11.m_tamingTime = 1800f;
					val11.m_commandable = true;
					val11.m_tamedEffect = val10.m_tamedEffect;
					val11.m_sootheEffect = val10.m_sootheEffect;
					val11.m_petEffect = val10.m_petEffect;
					val11.m_commandable = true;
					val11.m_unsummonDistance = 0f;
					val11.m_randomStartingName = new List<string>();
				}
				val2.AddComponent<Visuals>();
				Helpers.RegisterToZNetScene(val2);
			}
		}
	}
	public static class Initialization
	{
		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		[HarmonyPriority(0)]
		private static class ObjectDB_Awake_Patch
		{
			[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
			private static void Postfix(ObjectDB __instance)
			{
				if (Object.op_Implicit((Object)(object)__instance) && Object.op_Implicit((Object)(object)ZNetScene.instance))
				{
					HumanMan.Create();
					CloneAll();
					UpdateAll();
					SpawnMan.UpdateSpawnData();
				}
			}
		}

		public static void ReadLocalFiles()
		{
			if (!Directory.Exists(CreatureManager.m_folderPath))
			{
				Directory.CreateDirectory(CreatureManager.m_folderPath);
			}
			CreatureManager.Import();
			if (!Directory.Exists(CreatureManager.m_creatureFolderPath))
			{
				Directory.CreateDirectory(CreatureManager.m_creatureFolderPath);
			}
			string[] directories = Directory.GetDirectories(CreatureManager.m_creatureFolderPath);
			int num = 0;
			string[] array = directories;
			foreach (string text in array)
			{
				string text2 = text.Replace(CreatureManager.m_creatureFolderPath, string.Empty);
				char directorySeparatorChar = Path.DirectorySeparatorChar;
				string creatureName = text2.Replace(directorySeparatorChar.ToString(), string.Empty);
				CreatureManager.Read(creatureName);
				num++;
			}
			MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Registered {num} creature directories");
			num = 0;
			if (!Directory.Exists(CreatureManager.m_cloneFolderPath))
			{
				Directory.CreateDirectory(CreatureManager.m_cloneFolderPath);
			}
			string[] directories2 = Directory.GetDirectories(CreatureManager.m_cloneFolderPath);
			string[] array2 = directories2;
			foreach (string text3 in array2)
			{
				string text4 = text3.Replace(CreatureManager.m_cloneFolderPath, string.Empty);
				char directorySeparatorChar = Path.DirectorySeparatorChar;
				string creatureName2 = text4.Replace(directorySeparatorChar.ToString(), string.Empty);
				CreatureManager.Read(creatureName2, isClone: true);
				num++;
			}
			MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Registered {num} cloned creature directories");
		}

		public static void ResetAll()
		{
			int num = 0;
			foreach (KeyValuePair<string, CreatureData> datum in CreatureManager.m_data)
			{
				GameObject val = DataBase.TryGetGameObject(datum.Value.m_characterData.PrefabName);
				if (!((Object)(object)val == (Object)null))
				{
					CreatureManager.Reset(val);
					num++;
				}
			}
			MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Reset {num} creature data");
		}

		public static void RemoveAll()
		{
			int num = 0;
			foreach (KeyValuePair<string, GameObject> clone in CreatureManager.m_clones)
			{
				CreatureManager.Delete(clone.Value);
				num++;
			}
			CreatureManager.m_clones.Clear();
			MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Removed {num} clones");
		}

		public static void CloneAll()
		{
			int num = 0;
			foreach (KeyValuePair<string, CreatureData> datum in CreatureManager.m_data)
			{
				CloneAllItems(datum.Value);
				string clonedFrom = datum.Value.m_characterData.ClonedFrom;
				if (!Utility.IsNullOrWhiteSpace(clonedFrom))
				{
					GameObject val = DataBase.TryGetGameObject(clonedFrom);
					if (!((Object)(object)val == (Object)null))
					{
						string prefabName = datum.Value.m_characterData.PrefabName;
						CreatureManager.Clone(val, prefabName, saveToDisk: false);
						num++;
					}
				}
			}
			MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Cloned {num} creatures");
		}

		[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
		private static void CloneAllItems(CreatureData data)
		{
			CloneItems(data.m_defaultItems);
			CloneItems(data.m_randomWeapons);
			CloneItems(data.m_randomShields);
			CloneItems(data.m_randomArmors);
			foreach (RandomItemSetsData randomSet in data.m_randomSets)
			{
				CloneItems(randomSet.m_items);
			}
		}

		[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
		private static void CloneItems(List<ItemAttackData> data)
		{
			foreach (ItemAttackData datum in data)
			{
				if (!Utility.IsNullOrWhiteSpace(datum.m_attackData.OriginalPrefab))
				{
					GameObject val = DataBase.TryGetGameObject(datum.m_attackData.OriginalPrefab);
					if (!((Object)(object)val == (Object)null))
					{
						ItemDataMethods.Clone(val, datum.m_attackData.Name, write: false);
					}
				}
			}
		}

		public static void UpdateAll()
		{
			if (!Object.op_Implicit((Object)(object)ZNetScene.instance) || !Object.op_Implicit((Object)(object)ObjectDB.instance))
			{
				return;
			}
			int num = 0;
			foreach (KeyValuePair<string, CreatureData> datum in CreatureManager.m_data)
			{
				GameObject val = DataBase.TryGetGameObject(datum.Value.m_characterData.PrefabName);
				if (!((Object)(object)val == (Object)null))
				{
					CreatureManager.Update(val);
					num++;
				}
			}
			MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Updated {num} creatures");
		}
	}
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	public static class SpawnMan
	{
		[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(0)]
		[HarmonyPatch(typeof(SpawnSystem), "Awake")]
		private static class SpawnSystem_Awake_Patch
		{
			[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
			private static void Postfix(SpawnSystem __instance)
			{
				if (Object.op_Implicit((Object)(object)__instance) && !__instance.m_spawnLists.Contains(m_spawnSystemList))
				{
					__instance.m_spawnLists.Add(m_spawnSystemList);
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "Awake")]
		[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(0)]
		private static class ZNet_Awake_Patch
		{
			private static void Postfix()
			{
				UpdateServerFiles();
			}
		}

		[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
		private class CreatureSpawnData
		{
			public string m_name = "";

			public bool m_enabled = false;

			public bool m_devDisabled;

			public string m_prefab = null;

			public string m_biome = null;

			public string m_biomeArea = "Everything";

			public int m_maxSpawned = 1;

			public float m_spawnInterval = 4f;

			public float m_spawnChance = 100f;

			public float m_spawnDistance = 10f;

			public float m_spawnRadiusMin;

			public float m_spawnRadiusMax;

			public string m_requiredGlobalKey = "";

			public List<string> m_requiredEnvironments = new List<string>();

			public int m_groupSizeMin = 1;

			public int m_groupSizeMax = 1;

			public float m_groupRadius = 3f;

			public bool m_spawnAtNight = true;

			public bool m_spawnAtDay = true;

			public float m_minAltitude = -1000f;

			public float m_maxAltitude = 1000f;

			public float m_minTilt;

			public float m_maxTilt = 35f;

			public bool m_inForest = true;

			public bool m_outsideForest = true;

			public bool m_inLava;

			public bool m_outsideLava = true;

			public bool m_canSpawnCloseToPlayer;

			public bool m_insidePlayerBase;

			public float m_minOceanDepth;

			public float m_maxOceanDepth;

			public bool m_huntPlayer;

			public float m_groundOffset = 0.5f;

			public float m_groundOffsetRandom;

			public int m_maxLevel = 1;

			public int m_minLevel = 1;

			public float m_levelUpMinCenterDistance;

			public float m_overrideLevelupChance = -1f;

			public bool m_foldout;
		}

		private static readonly CustomSyncedValue<string> ServerSpawnSystem = new CustomSyncedValue<string>(MonsterDBPlugin.ConfigSync, "MonsterDB_SpawnSystemData", "");

		private static readonly string m_spawnFolderPath;

		private static readonly string m_referenceFolderPath;

		private static SpawnSystemList m_spawnSystemList;

		private static Dictionary<string, CreatureSpawnData> m_spawnData;

		public static void Setup()
		{
			m_spawnSystemList = MonsterDBPlugin.m_root.AddComponent<SpawnSystemList>();
			ReadSpawnFiles();
			string spawnFolderPath = m_spawnFolderPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			string path = spawnFolderPath + directorySeparatorChar + "Example.yml";
			if (!File.Exists(path))
			{
				CreatureSpawnData graph = new CreatureSpawnData();
				ISerializer serializer = new SerializerBuilder().Build();
				string contents = serializer.Serialize(graph);
				File.WriteAllText(path, contents);
			}
			ServerSpawnSystem.ValueChanged += delegate
			{
				if (Object.op_Implicit((Object)(object)ZNet.instance) && !ZNet.instance.IsServer())
				{
					UpdateSpawnData();
				}
			};
			SetupFileWatch();
		}

		private static void SetupFileWatch()
		{
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(m_spawnFolderPath, "*.yml")
			{
				EnableRaisingEvents = true,
				IncludeSubdirectories = false,
				SynchronizingObject = ThreadingHelper.SynchronizingObject,
				NotifyFilter = NotifyFilters.LastWrite
			};
			fileSystemWatcher.Created += OnSpawnChange;
			fileSystemWatcher.Deleted += OnSpawnChange;
			fileSystemWatcher.Changed += OnSpawnChange;
		}

		private static void OnSpawnChange(object sender, FileSystemEventArgs e)
		{
			if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer())
			{
				string fileName = Path.GetFileName(e.Name);
				if (!(fileName == "Example.yml"))
				{
					MonsterDBPlugin.MonsterDBLogger.LogDebug((object)"Spawn files changed");
					ClearSpawnData();
					ReadSpawnFiles();
				}
			}
		}

		private static void ReadFile(string filePath)
		{
			try
			{
				IDeserializer deserializer = new DeserializerBuilder().Build();
				string input = File.ReadAllText(filePath);
				CreatureSpawnData creatureSpawnData = deserializer.Deserialize<CreatureSpawnData>(input);
				m_spawnData[creatureSpawnData.m_name] = creatureSpawnData;
				UpdateSpawnList();
				UpdateServerFiles();
			}
			catch
			{
				Helpers.LogParseFailure(filePath);
			}
		}

		private static void ReadSpawnFiles()
		{
			if (!Directory.Exists(m_spawnFolderPath))
			{
				Directory.CreateDirectory(m_spawnFolderPath);
			}
			string[] files = Directory.GetFiles(m_spawnFolderPath, "*.yml");
			IDeserializer deserializer = new DeserializerBuilder().Build();
			int num = 0;
			string[] array = files;
			foreach (string text in array)
			{
				if (!text.EndsWith("Example.yml"))
				{
					string input = File.ReadAllText(text);
					try
					{
						CreatureSpawnData creatureSpawnData = deserializer.Deserialize<CreatureSpawnData>(input);
						m_spawnData[creatureSpawnData.m_name] = creatureSpawnData;
						num++;
					}
					catch
					{
						Helpers.LogParseFailure(text);
					}
				}
			}
			MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Registered {num} spawn files");
		}

		public static void UpdateSpawnData()
		{
			if (Utility.IsNullOrWhiteSpace(ServerSpawnSystem.Value))
			{
				return;
			}
			try
			{
				IDeserializer deserializer = new DeserializerBuilder().Build();
				Dictionary<string, CreatureSpawnData> dictionary = deserializer.Deserialize<Dictionary<string, CreatureSpawnData>>(ServerSpawnSystem.Value);
				ClearSpawnData();
				AddSpawnData(dictionary);
				UpdateSpawnList();
				MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Loaded {dictionary.Count} spawn files");
			}
			catch
			{
				MonsterDBPlugin.MonsterDBLogger.LogDebug((object)"Failed to parse server spawn files");
			}
		}

		private static void ClearSpawnData()
		{
			m_spawnData.Clear();
		}

		private static void AddSpawnData(Dictionary<string, CreatureSpawnData> data)
		{
			m_spawnData = data;
		}

		private static void UpdateSpawnList()
		{
			m_spawnSystemList.m_spawners = (from info in m_spawnData.Values.Select(FormatSpawnData)
				where info != null
				select info).ToList();
		}

		public static bool Write(GameObject critter)
		{
			if (!Directory.Exists(m_spawnFolderPath))
			{
				Directory.CreateDirectory(m_spawnFolderPath);
			}
			if (!Directory.Exists(m_referenceFolderPath))
			{
				Directory.CreateDirectory(m_referenceFolderPath);
			}
			CreatureSpawnData creatureSpawnData = new CreatureSpawnData();
			foreach (SpawnSystemList item in SpawnSystem.m_instances.SelectMany([<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(0)] (SpawnSystem instance) => instance.m_spawnLists))
			{
				using IEnumerator<SpawnData> enumerator2 = item.m_spawners.Where([<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(0)] (SpawnData stream) => (Object)(object)stream.m_prefab == (Object)(object)critter).GetEnumerator();
				if (enumerator2.MoveNext())
				{
					SpawnData current2 = enumerator2.Current;
					creatureSpawnData.m_name = current2.m_name;
					creatureSpawnData.m_enabled = current2.m_enabled;
					creatureSpawnData.m_prefab = ((Object)current2.m_prefab).name;
					creatureSpawnData.m_biome = ((object)(Biome)(ref current2.m_biome)).ToString();
					creatureSpawnData.m_biomeArea = ((object)(BiomeArea)(ref current2.m_biomeArea)).ToString();
					creatureSpawnData.m_maxSpawned = current2.m_maxSpawned;
					creatureSpawnData.m_spawnInterval = current2.m_spawnInterval;
					creatureSpawnData.m_spawnChance = current2.m_spawnChance;
					creatureSpawnData.m_spawnDistance = current2.m_spawnDistance;
					creatureSpawnData.m_spawnRadiusMin = current2.m_spawnRadiusMin;
					creatureSpawnData.m_spawnRadiusMax = current2.m_spawnRadiusMax;
					creatureSpawnData.m_requiredGlobalKey = current2.m_requiredGlobalKey;
					creatureSpawnData.m_requiredEnvironments = current2.m_requiredEnvironments;
					creatureSpawnData.m_groupSizeMin = current2.m_groupSizeMin;
					creatureSpawnData.m_groupSizeMax = current2.m_groupSizeMax;
					creatureSpawnData.m_groupRadius = current2.m_groupRadius;
					creatureSpawnData.m_spawnAtNight = current2.m_spawnAtNight;
					creatureSpawnData.m_spawnAtDay = current2.m_spawnAtDay;
					creatureSpawnData.m_minAltitude = current2.m_minAltitude;
					creatureSpawnData.m_maxAltitude = current2.m_maxAltitude;
					creatureSpawnData.m_minTilt = current2.m_minTilt;
					creatureSpawnData.m_maxTilt = current2.m_maxTilt;
					creatureSpawnData.m_inForest = current2.m_inForest;
					creatureSpawnData.m_outsideForest = current2.m_outsideForest;
					creatureSpawnData.m_inLava = current2.m_inLava;
					creatureSpawnData.m_outsideLava = current2.m_outsideLava;
					creatureSpawnData.m_canSpawnCloseToPlayer = current2.m_canSpawnCloseToPlayer;
					creatureSpawnData.m_insidePlayerBase = current2.m_insidePlayerBase;
					creatureSpawnData.m_minOceanDepth = current2.m_minOceanDepth;
					creatureSpawnData.m_maxOceanDepth = current2.m_maxOceanDepth;
					creatureSpawnData.m_huntPlayer = current2.m_huntPlayer;
					creatureSpawnData.m_groundOffset = current2.m_groundOffset;
					creatureSpawnData.m_groundOffsetRandom = current2.m_groundOffsetRandom;
					creatureSpawnData.m_maxLevel = current2.m_maxLevel;
					creatureSpawnData.m_minLevel = current2.m_minLevel;
					creatureSpawnData.m_levelUpMinCenterDistance = current2.m_levelUpMinCenterDistance;
					creatureSpawnData.m_overrideLevelupChance = current2.m_overrideLevelupChance;
					creatureSpawnData.m_foldout = current2.m_foldout;
				}
			}
			if (Utility.IsNullOrWhiteSpace(creatureSpawnData.m_prefab))
			{
				return false;
			}
			string text = creatureSpawnData.m_prefab + ".yml";
			string referenceFolderPath = m_referenceFolderPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			string path = referenceFolderPath + directorySeparatorChar + text;
			ISerializer serializer = new SerializerBuilder().Build();
			string contents = serializer.Serialize(creatureSpawnData);
			File.WriteAllText(path, contents);
			return true;
		}

		[return: <2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(2)]
		private static SpawnData FormatSpawnData(CreatureSpawnData input)
		{
			//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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Expected O, but got Unknown
			if (Utility.IsNullOrWhiteSpace(input.m_name))
			{
				return null;
			}
			GameObject val = DataBase.TryGetGameObject(input.m_prefab);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			if (!Enum.TryParse<Biome>(input.m_biome, out Biome result))
			{
				return null;
			}
			if (!Enum.TryParse<BiomeArea>(input.m_biomeArea, out BiomeArea result2))
			{
				return null;
			}
			return new SpawnData
			{
				m_name = input.m_name,
				m_enabled = input.m_enabled,
				m_devDisabled = input.m_devDisabled,
				m_prefab = val,
				m_biome = result,
				m_biomeArea = result2,
				m_maxSpawned = input.m_maxSpawned,
				m_spawnInterval = input.m_spawnInterval,
				m_spawnChance = input.m_spawnChance,
				m_spawnDistance = input.m_spawnDistance,
				m_spawnRadiusMin = input.m_spawnRadiusMin,
				m_spawnRadiusMax = input.m_spawnRadiusMax,
				m_requiredGlobalKey = input.m_requiredGlobalKey,
				m_requiredEnvironments = input.m_requiredEnvironments,
				m_groupSizeMin = input.m_groupSizeMin,
				m_groupSizeMax = input.m_groupSizeMax,
				m_groupRadius = input.m_groupRadius,
				m_spawnAtNight = input.m_spawnAtNight,
				m_spawnAtDay = input.m_spawnAtDay,
				m_minAltitude = input.m_minAltitude,
				m_maxAltitude = input.m_maxAltitude,
				m_minTilt = input.m_minTilt,
				m_maxTilt = input.m_maxTilt,
				m_inForest = input.m_inForest,
				m_outsideForest = input.m_outsideForest,
				m_inLava = input.m_inLava,
				m_outsideLava = input.m_outsideLava,
				m_canSpawnCloseToPlayer = input.m_canSpawnCloseToPlayer,
				m_insidePlayerBase = input.m_insidePlayerBase,
				m_minOceanDepth = input.m_minOceanDepth,
				m_maxOceanDepth = input.m_maxOceanDepth,
				m_huntPlayer = input.m_huntPlayer,
				m_groundOffset = input.m_groundOffset,
				m_groundOffsetRandom = input.m_groundOffsetRandom,
				m_maxLevel = input.m_maxLevel,
				m_minLevel = input.m_minLevel,
				m_levelUpMinCenterDistance = input.m_levelUpMinCenterDistance,
				m_overrideLevelupChance = input.m_overrideLevelupChance,
				m_foldout = input.m_foldout
			};
		}

		private static void UpdateServerFiles()
		{
			if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer())
			{
				ISerializer serializer = new SerializerBuilder().Build();
				string value = serializer.Serialize(m_spawnData);
				ServerSpawnSystem.Value = value;
			}
		}

		static SpawnMan()
		{
			string folderPath = CreatureManager.m_folderPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			m_spawnFolderPath = folderPath + directorySeparatorChar + "SpawnData";
			string spawnFolderPath = m_spawnFolderPath;
			directorySeparatorChar = Path.DirectorySeparatorChar;
			m_referenceFolderPath = spawnFolderPath + directorySeparatorChar + "References";
			m_spawnSystemList = null;
			m_spawnData = new Dictionary<string, CreatureSpawnData>();
		}
	}
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	public static class TextureManager
	{
		public static readonly string m_texturePath;

		public static readonly Dictionary<string, Texture2D> m_customTextures;

		private static readonly Dictionary<string, byte[]> m_textureBytes;

		public static void ReadLocalTextures()
		{
			if (!Directory.Exists(CreatureManager.m_folderPath))
			{
				Directory.CreateDirectory(CreatureManager.m_folderPath);
			}
			if (!Directory.Exists(m_texturePath))
			{
				Directory.CreateDirectory(m_texturePath);
			}
			string[] files = Directory.GetFiles(m_texturePath, "*.png");
			int num = 0;
			string[] array = files;
			foreach (string filePath in array)
			{
				RegisterTexture(filePath);
				num++;
			}
			MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Registered {num} textures");
		}

		private static Texture2D LoadTexture(string name, byte[] data)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Expected O, but got Unknown
			Texture2D val = new Texture2D(2, 2);
			ImageConversion.LoadImage(val, data);
			((Object)val).name = name;
			return val;
		}

		private static void RegisterTexture(string filePath)
		{
			byte[] data = File.ReadAllBytes(filePath);
			string name = Path.GetFileName(filePath).Replace(".png", string.Empty).Trim();
			Texture2D val = LoadTexture(name, data);
			m_customTextures[((Object)val).name] = val;
			MonsterDBPlugin.MonsterDBLogger.LogDebug((object)("Registered texture: " + ((Object)val).name));
		}

		private static Texture2D ReadBytes(string name, byte[] data)
		{
			Texture2D val = LoadTexture(name, data);
			m_customTextures[((Object)val).name] = val;
			m_textureBytes[((Object)val).name] = data;
			return val;
		}

		static TextureManager()
		{
			string folderPath = CreatureManager.m_folderPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			m_texturePath = folderPath + directorySeparatorChar + "CustomTextures";
			m_customTextures = new Dictionary<string, Texture2D>();
			m_textureBytes = new Dictionary<string, byte[]>();
		}
	}
	public static class Tutorial
	{
		public static void Write()
		{
			string folderPath = CreatureManager.m_folderPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			string path = folderPath + directorySeparatorChar + "README.md";
			if (!File.Exists(path))
			{
				TextAsset text = GetText("Tutorial.md");
				File.WriteAllText(path, text.text);
			}
		}

		[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
		private static TextAsset GetText(string fileName)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string name = executingAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(fileName));
			using Stream stream = executingAssembly.GetManifestResourceStream(name);
			if (stream == null)
			{
				return new TextAsset();
			}
			using StreamReader streamReader = new StreamReader(stream);
			string text = streamReader.ReadToEnd();
			return new TextAsset(text);
		}
	}
}
namespace MonsterDB.Solution.Methods
{
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	public static class AnimalAIMethods
	{
		public static void Save(GameObject critter, ref CreatureData creatureData)
		{
			AnimalAI val = default(AnimalAI);
			if (critter.TryGetComponent<AnimalAI>(ref val))
			{
				creatureData.m_animalAIData = RecordAIData(val);
				Helpers.SaveEffectList(((BaseAI)val).m_alertedEffects, ref creatureData.m_effects.m_alertedEffects);
				Helpers.SaveEffectList(((BaseAI)val).m_idleSound, ref creatureData.m_effects.m_idleSounds);
			}
		}

		public static void Write(GameObject critter, string folderPath)
		{
			AnimalAI val = default(AnimalAI);
			if (critter.TryGetComponent<AnimalAI>(ref val))
			{
				AnimalAIData graph = RecordAIData(val);
				char directorySeparatorChar = Path.DirectorySeparatorChar;
				string path = folderPath + directorySeparatorChar + "AnimalAI.yml";
				ISerializer serializer = new SerializerBuilder().Build();
				string contents = serializer.Serialize(graph);
				File.WriteAllText(path, contents);
				directorySeparatorChar = Path.DirectorySeparatorChar;
				string text = folderPath + directorySeparatorChar + "Effects";
				if (!Directory.Exists(text))
				{
					Directory.CreateDirectory(text);
				}
				directorySeparatorChar = Path.DirectorySeparatorChar;
				string filePath = text + directorySeparatorChar + "AlertedEffects.yml";
				directorySeparatorChar = Path.DirectorySeparatorChar;
				string filePath2 = text + directorySeparatorChar + "IdleSounds.yml";
				Helpers.WriteEffectList(((BaseAI)val).m_alertedEffects, filePath);
				Helpers.WriteEffectList(((BaseAI)val).m_idleSound, filePath2);
			}
		}

		private static AnimalAIData RecordAIData(AnimalAI component)
		{
			return new AnimalAIData
			{
				ViewRange = ((BaseAI)component).m_viewRange,
				ViewAngle = ((BaseAI)component).m_viewAngle,
				HearRange = ((BaseAI)component).m_hearRange,
				MistVision = ((BaseAI)component).m_mistVision,
				IdleSoundInterval = ((BaseAI)component).m_idleSoundInterval,
				IdleSoundChance = ((BaseAI)component).m_idleSoundChance,
				PathAgentType = ((object)(AgentType)(ref ((BaseAI)component).m_pathAgentType)).ToString(),
				MoveMinAngle = ((BaseAI)component).m_moveMinAngle,
				SmoothMovement = ((BaseAI)component).m_smoothMovement,
				SerpentMovement = ((BaseAI)component).m_serpentMovement,
				SerpentTurnRadius = ((BaseAI)component).m_serpentTurnRadius,
				JumpInterval = ((BaseAI)component).m_jumpInterval,
				RandomCircleInterval = ((BaseAI)component).m_randomCircleInterval,
				RandomMoveInterval = ((BaseAI)component).m_randomMoveInterval,
				RandomMoveRange = ((BaseAI)component).m_randomMoveRange,
				RandomFly = ((BaseAI)component).m_randomFly,
				ChanceToTakeOff = ((BaseAI)component).m_chanceToTakeoff,
				ChanceToLand = ((BaseAI)component).m_chanceToLand,
				GroundDuration = ((BaseAI)component).m_groundDuration,
				AirDuration = ((BaseAI)component).m_airDuration,
				MaxLandAltitude = ((BaseAI)component).m_maxLandAltitude,
				TakeoffTime = ((BaseAI)component).m_takeoffTime,
				FlyAltitudeMin = ((BaseAI)component).m_flyAltitudeMin,
				FlyAltitudeMax = ((BaseAI)component).m_flyAltitudeMax,
				FlyAbsMinAltitude = ((BaseAI)component).m_flyAbsMinAltitude,
				AvoidFire = ((BaseAI)component).m_avoidFire,
				AfraidOfFire = ((BaseAI)component).m_afraidOfFire,
				AvoidWater = ((BaseAI)component).m_avoidWater,
				AvoidLava = ((BaseAI)component).m_avoidLava,
				SkipLavaTargets = ((BaseAI)component).m_skipLavaTargets,
				Aggravatable = ((BaseAI)component).m_aggravatable,
				PassiveAggressive = ((BaseAI)component).m_passiveAggresive,
				SpawnMessage = ((BaseAI)component).m_spawnMessage,
				DeathMessage = ((BaseAI)component).m_deathMessage,
				AlertedMessage = ((BaseAI)component).m_alertedMessage,
				FleeRange = ((BaseAI)component).m_fleeRange,
				FleeAngle = ((BaseAI)component).m_fleeAngle,
				FleeInterval = ((BaseAI)component).m_fleeInterval
			};
		}

		public static void Read(string folderPath, ref CreatureData creatureData)
		{
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			string text = folderPath + directorySeparatorChar + "AnimalAI.yml";
			if (!File.Exists(text))
			{
				return;
			}
			string text2 = File.ReadAllText(text);
			if (Utility.IsNullOrWhiteSpace(text2))
			{
				return;
			}
			IDeserializer deserializer = new DeserializerBuilder().Build();
			try
			{
				AnimalAIData animalAIData = deserializer.Deserialize<AnimalAIData>(text2);
				creatureData.m_animalAIData = animalAIData;
				directorySeparatorChar = Path.DirectorySeparatorChar;
				string text3 = folderPath + directorySeparatorChar + "Effects";
				if (Directory.Exists(text3))
				{
					directorySeparatorChar = Path.DirectorySeparatorChar;
					string filePath = text3 + directorySeparatorChar + "AlertedEffects.yml";
					directorySeparatorChar = Path.DirectorySeparatorChar;
					string filePath2 = text3 + directorySeparatorChar + "IdleSounds.yml";
					Helpers.ReadEffectInfo(filePath, ref creatureData.m_effects.m_alertedEffects);
					Helpers.ReadEffectInfo(filePath2, ref creatureData.m_effects.m_idleSounds);
				}
			}
			catch
			{
				Helpers.LogParseFailure(text);
			}
		}

		public static void Update(GameObject critter, CreatureData creatureData)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			AnimalAIData animalAIData = creatureData.m_animalAIData;
			Vector3 scale = Helpers.GetScale(creatureData.m_scale);
			CharacterEffects effects = creatureData.m_effects;
			AnimalAI val = default(AnimalAI);
			if (critter.TryGetComponent<AnimalAI>(ref val))
			{
				((BaseAI)val).m_viewRange = animalAIData.ViewRange;
				((BaseAI)val).m_viewAngle = animalAIData.ViewAngle;
				((BaseAI)val).m_hearRange = animalAIData.HearRange;
				((BaseAI)val).m_mistVision = animalAIData.MistVision;
				((BaseAI)val).m_idleSoundInterval = animalAIData.IdleSoundInterval;
				((BaseAI)val).m_idleSoundChance = animalAIData.IdleSoundChance;
				if (!Enum.TryParse<AgentType>(animalAIData.PathAgentType, ignoreCase: true, out AgentType result))
				{
					((BaseAI)val).m_pathAgentType = result;
				}
				((BaseAI)val).m_moveMinAngle = animalAIData.MoveMinAngle;
				((BaseAI)val).m_smoothMovement = animalAIData.SmoothMovement;
				((BaseAI)val).m_serpentMovement = animalAIData.SerpentMovement;
				((BaseAI)val).m_serpentTurnRadius = animalAIData.SerpentTurnRadius;
				((BaseAI)val).m_jumpInterval = animalAIData.JumpInterval;
				((BaseAI)val).m_randomCircleInterval = animalAIData.RandomCircleInterval;
				((BaseAI)val).m_randomMoveInterval = animalAIData.RandomMoveInterval;
				((BaseAI)val).m_randomMoveRange = animalAIData.RandomMoveRange;
				((BaseAI)val).m_randomFly = animalAIData.RandomFly;
				((BaseAI)val).m_chanceToTakeoff = animalAIData.ChanceToTakeOff;
				((BaseAI)val).m_chanceToLand = animalAIData.ChanceToLand;
				((BaseAI)val).m_groundDuration = animalAIData.GroundDuration;
				((BaseAI)val).m_airDuration = animalAIData.AirDuration;
				((BaseAI)val).m_maxLandAltitude = animalAIData.MaxLandAltitude;
				((BaseAI)val).m_takeoffTime = animalAIData.TakeoffTime;
				((BaseAI)val).m_flyAltitudeMin = animalAIData.FlyAltitudeMin;
				((BaseAI)val).m_flyAltitudeMax = animalAIData.FlyAltitudeMax;
				((BaseAI)val).m_flyAbsMinAltitude = animalAIData.FlyAbsMinAltitude;
				((BaseAI)val).m_avoidFire = animalAIData.AvoidFire;
				((BaseAI)val).m_afraidOfFire = animalAIData.AfraidOfFire;
				((BaseAI)val).m_avoidWater = animalAIData.AvoidWater;
				((BaseAI)val).m_avoidLava = animalAIData.AvoidLava;
				((BaseAI)val).m_skipLavaTargets = animalAIData.SkipLavaTargets;
				((BaseAI)val).m_aggravatable = animalAIData.Aggravatable;
				((BaseAI)val).m_passiveAggresive = animalAIData.PassiveAggressive;
				((BaseAI)val).m_spawnMessage = animalAIData.SpawnMessage;
				((BaseAI)val).m_deathMessage = animalAIData.DeathMessage;
				((BaseAI)val).m_alertedMessage = animalAIData.AlertedMessage;
				((BaseAI)val).m_fleeRange = animalAIData.FleeRange;
				((BaseAI)val).m_fleeAngle = animalAIData.FleeAngle;
				((BaseAI)val).m_fleeInterval = animalAIData.FleeInterval;
				Helpers.UpdateEffectList(effects.m_alertedEffects, ref ((BaseAI)val).m_alertedEffects, scale);
				Helpers.UpdateEffectList(effects.m_idleSounds, ref ((BaseAI)val).m_alertedEffects, scale);
			}
		}
	}
	[<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)]
	[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)]
	public static class CharacterMethods
	{
		public static void Save(GameObject critter, string clonedFrom, ref CreatureData creatureData)
		{
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			Character val = default(Character);
			if (!critter.TryGetComponent<Character>(ref val))
			{
				return;
			}
			creatureData.m_characterData = RecordCharacterData(val, clonedFrom, critter);
			Helpers.SaveEffectList(val.m_hitEffects, ref creatureData.m_effects.m_hitEffects);
			Helpers.SaveEffectList(val.m_critHitEffects, ref creatureData.m_effects.m_critHitEffects);
			Helpers.SaveEffectList(val.m_backstabHitEffects, ref creatureData.m_effects.m_backstabHitEffects);
			Helpers.SaveEffectList(val.m_deathEffects, ref creatureData.m_effects.m_deathEffects);
			Helpers.SaveEffectList(val.m_waterEffects, ref creatureData.m_effects.m_waterEffects);
			Helpers.SaveEffectList(val.m_tarEffects, ref creatureData.m_effects.m_tarEffects);
			Helpers.SaveEffectList(val.m_slideEffects, ref creatureData.m_effects.m_slideEffects);
			Helpers.SaveEffectList(val.m_jumpEffects, ref creatureData.m_effects.m_jumpEffects);
			Helpers.SaveEffectList(val.m_flyingContinuousEffect, ref creatureData.m_effects.m_flyingContinuousEffects);
			if (val.m_deathEffects == null)
			{
				return;
			}
			EffectData[] effectPrefabs = val.m_deathEffects.m_effectPrefabs;
			foreach (EffectData val2 in effectPrefabs)
			{
				if (Object.op_Implicit((Object)(object)val2.m_prefab.GetComponent<Ragdoll>()))
				{
					Vector3 localScale = val2.m_prefab.transform.localScale;
					VisualMethods.ScaleData ragdollScale = new VisualMethods.ScaleData
					{
						x = localScale.x,
						y = localScale.y,
						z = localScale.z
					};
					creatureData.m_ragdollScale = ragdollScale;
				}
			}
		}

		public static void Write(GameObject critter, string folderPath, string clonedFrom = "")
		{
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid I