Decompiled source of CreatureManager v1.0.7

CreatureManager.dll

Decompiled 2 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.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CreatureManager;
using GUIFramework;
using HarmonyLib;
using JetBrains.Annotations;
using LocalizationManager;
using Microsoft.CodeAnalysis;
using ServerSync;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.ObjectPool;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.RepresentationModel;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Callbacks;
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: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("CreatureManager")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("sighsorry")]
[assembly: AssemblyProduct("CreatureManager")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")]
[assembly: AssemblyFileVersion("1.0.7")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.7.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace LocalizationManager
{
	internal static class Localizer
	{
		private static BaseUnityPlugin? _plugin;

		private static readonly List<string> fileExtensions = new List<string>(2) { ".json", ".yml" };

		private static BaseUnityPlugin plugin
		{
			get
			{
				//IL_009b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a5: Expected O, but got Unknown
				if (_plugin == null)
				{
					IEnumerable<TypeInfo> source;
					try
					{
						source = Assembly.GetExecutingAssembly().DefinedTypes.ToList();
					}
					catch (ReflectionTypeLoadException ex)
					{
						source = from t in ex.Types
							where t != null
							select t.GetTypeInfo();
					}
					_plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
				}
				return _plugin;
			}
		}

		internal static void Load(Harmony harmony)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			//IL_0089: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			_ = plugin;
			harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", new Type[1] { typeof(string) }, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "BeforeLanguageSetup", (Type[])null, (Type[])null), 800, (string[])null, (string[])null, (bool?)null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "SafeLoadLocalization", (Type[])null, (Type[])null), 0, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", Type.EmptyTypes, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalizationLater", (Type[])null, (Type[])null), 0, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		internal static void Unload()
		{
			_plugin = null;
		}

		private static void LoadLocalizationLater()
		{
			Localization instance = Localization.instance;
			if (instance != null)
			{
				SafeLoadLocalization(instance, instance.GetSelectedLanguage());
			}
		}

		[HarmonyPriority(800)]
		private static void BeforeLanguageSetup(Localization __instance)
		{
			try
			{
				CreatureServerLocalization.BeforeLanguageSetup(__instance);
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Failed to prepare CreatureManager server localization before a language change. " + ex.Message));
			}
		}

		[HarmonyPriority(0)]
		private static void SafeLoadLocalization(Localization __instance, string language)
		{
			try
			{
				LoadLocalization(__instance, language);
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Failed to load " + plugin.Info.Metadata.Name + " localization for '" + language + "'. Vanilla localization will remain active. " + ex.Message));
			}
			try
			{
				CreatureServerLocalization.ApplyCurrentLocalization(__instance, language);
			}
			catch (Exception ex2)
			{
				Debug.LogError((object)("Failed to apply CreatureManager server localization for '" + language + "'. " + ex2.Message));
			}
		}

		private static void LoadLocalization(Localization __instance, string language)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories)
				where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0
				select f)
			{
				string[] array = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' });
				if (array.Length >= 2)
				{
					string text = array[1];
					if (dictionary.ContainsKey(text))
					{
						Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped."));
					}
					else
					{
						dictionary[text] = item;
					}
				}
			}
			byte[] array2 = LoadTranslationFromAssembly("English");
			if (array2 == null)
			{
				throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml.");
			}
			Dictionary<string, string> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array2));
			if (dictionary2 == null)
			{
				throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty.");
			}
			string text2 = null;
			if (language != "English")
			{
				if (dictionary.TryGetValue(language, out var value))
				{
					text2 = File.ReadAllText(value);
				}
				else
				{
					byte[] array3 = LoadTranslationFromAssembly(language);
					if (array3 != null)
					{
						text2 = Encoding.UTF8.GetString(array3);
					}
				}
			}
			if (text2 == null && dictionary.TryGetValue("English", out var value2))
			{
				text2 = File.ReadAllText(value2);
			}
			if (text2 != null)
			{
				foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>())
				{
					dictionary2[item2.Key] = item2.Value;
				}
			}
			foreach (KeyValuePair<string, string> item3 in dictionary2)
			{
				__instance.AddWord(item3.Key, item3.Value);
			}
		}

		private static byte[]? LoadTranslationFromAssembly(string language)
		{
			foreach (string fileExtension in fileExtensions)
			{
				byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension);
				if (array != null)
				{
					return array;
				}
			}
			return null;
		}

		public static byte[]? ReadEmbeddedFileBytes(string resourceFileName, Assembly? containingAssembly = null)
		{
			using MemoryStream memoryStream = new MemoryStream();
			if ((object)containingAssembly == null)
			{
				containingAssembly = Assembly.GetCallingAssembly();
			}
			string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal));
			if (text != null)
			{
				containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream);
			}
			return (memoryStream.Length == 0L) ? null : memoryStream.ToArray();
		}
	}
}
namespace CreatureManager
{
	internal static class CreatureConsoleCommands
	{
		private enum SpawnAutocompleteField
		{
			None,
			Prefab,
			Modifier
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static ConsoleEvent <0>__WriteReference;

			public static ConsoleOptionsFetcher <1>__GetReferenceDomainOptions;

			public static ConsoleEvent <2>__WriteFull;

			public static ConsoleOptionsFetcher <3>__GetFullDomainOptions;

			public static ConsoleEvent <4>__Spawn;

			public static ConsoleOptionsFetcher <5>__GetSpawnPrefabOptions;

			public static ConsoleEvent <6>__Karma;
		}

		private const string SpawnCommandName = "cm:spawn";

		private const int MaximumCommandSpawnLevel = 100;

		private static readonly List<string> ReferenceDomainOptions = new List<string> { "creature", "ai", "attack", "loadout", "projectile", "texture", "levelvisual" };

		private static readonly List<string> FullDomainOptions = new List<string> { "creature" };

		private static readonly List<string> EmptyAutocompleteOptions = new List<string>();

		private static readonly char[] ArgumentSeparators = new char[2] { ' ', '\t' };

		private static ConsoleCommand? SpawnCommand;

		private static bool Registered;

		internal static void Register()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Expected O, but got Unknown
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Expected O, but got Unknown
			if (!Registered)
			{
				Registered = true;
				object obj = <>O.<0>__WriteReference;
				if (obj == null)
				{
					ConsoleEvent val = WriteReference;
					<>O.<0>__WriteReference = val;
					obj = (object)val;
				}
				object obj2 = <>O.<1>__GetReferenceDomainOptions;
				if (obj2 == null)
				{
					ConsoleOptionsFetcher val2 = GetReferenceDomainOptions;
					<>O.<1>__GetReferenceDomainOptions = val2;
					obj2 = (object)val2;
				}
				new ConsoleCommand("cm:reference", "Write generated CreatureManager reference files. Usage: cm:reference creature|ai|attack|loadout|projectile|texture|levelvisual", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)obj2, false, false, false);
				object obj3 = <>O.<2>__WriteFull;
				if (obj3 == null)
				{
					ConsoleEvent val3 = WriteFull;
					<>O.<2>__WriteFull = val3;
					obj3 = (object)val3;
				}
				object obj4 = <>O.<3>__GetFullDomainOptions;
				if (obj4 == null)
				{
					ConsoleOptionsFetcher val4 = GetFullDomainOptions;
					<>O.<3>__GetFullDomainOptions = val4;
					obj4 = (object)val4;
				}
				new ConsoleCommand("cm:full", "Write generated CreatureManager full scaffold YAML. Usage: cm:full creature", (ConsoleEvent)obj3, false, false, false, false, false, (ConsoleOptionsFetcher)obj4, false, false, false);
				string text = $"Spawn a creature with optional modifiers and an exact trailing level from 1 to {100}. Usage: cm:spawn <prefab> [modifier1,modifier2,modifier3,modifier4] [level]";
				object obj5 = <>O.<4>__Spawn;
				if (obj5 == null)
				{
					ConsoleEvent val5 = Spawn;
					<>O.<4>__Spawn = val5;
					obj5 = (object)val5;
				}
				object obj6 = <>O.<5>__GetSpawnPrefabOptions;
				if (obj6 == null)
				{
					ConsoleOptionsFetcher val6 = GetSpawnPrefabOptions;
					<>O.<5>__GetSpawnPrefabOptions = val6;
					obj6 = (object)val6;
				}
				SpawnCommand = new ConsoleCommand("cm:spawn", text, (ConsoleEvent)obj5, true, true, true, false, false, (ConsoleOptionsFetcher)obj6, false, true, true);
				object obj7 = <>O.<6>__Karma;
				if (obj7 == null)
				{
					ConsoleEvent val7 = Karma;
					<>O.<6>__Karma = val7;
					obj7 = (object)val7;
				}
				new ConsoleCommand("cm:karma", "Show or set current 3x3 zone-neighborhood Karma. Usage: cm:karma [value]", (ConsoleEvent)obj7, true, true, true, false, false, (ConsoleOptionsFetcher)null, false, true, true);
			}
		}

		private static List<string> GetReferenceDomainOptions()
		{
			return ReferenceDomainOptions;
		}

		private static List<string> GetFullDomainOptions()
		{
			return FullDomainOptions;
		}

		private static List<string> GetSpawnPrefabOptions()
		{
			List<GameObject> creaturePrefabs = CreaturePrefabRegistry.GetCreaturePrefabs();
			List<string> list = new List<string>(creaturePrefabs.Count);
			foreach (GameObject item in creaturePrefabs)
			{
				list.Add(((Object)item).name);
			}
			return list;
		}

		internal static void InvalidateSpawnAutocompleteOptions()
		{
			if (SpawnCommand != null)
			{
				SpawnCommand.m_tabOptions = null;
			}
		}

		internal static void AdjustSpawnAutocomplete(Terminal terminal, ref string word, ref List<string> options)
		{
			if (!TryGetSpawnAutocompleteContext(terminal, out SpawnAutocompleteField field, out string currentToken))
			{
				return;
			}
			switch (field)
			{
			case SpawnAutocompleteField.Prefab:
				word = currentToken;
				if (options == null || options.Count == 0)
				{
					options = GetSpawnPrefabOptions();
				}
				break;
			case SpawnAutocompleteField.Modifier:
				options = GetModifierAutocompleteOptions(currentToken, out word);
				break;
			default:
				word = currentToken;
				options = EmptyAutocompleteOptions;
				break;
			}
		}

		private static bool TryGetSpawnAutocompleteContext(Terminal terminal, out SpawnAutocompleteField field, out string currentToken)
		{
			field = SpawnAutocompleteField.None;
			currentToken = "";
			if ((Object)(object)terminal.m_input == (Object)null)
			{
				return false;
			}
			GuiInputField input = terminal.m_input;
			string text = ((TMP_InputField)input).text ?? "";
			string text2 = text[..Mathf.Clamp(((TMP_InputField)input).caretPosition, 0, text.Length)].TrimStart(Array.Empty<char>());
			if (terminal.m_tabPrefix != 0 && text2.Length > 0 && text2[0] == terminal.m_tabPrefix)
			{
				text2 = text2.Substring(1);
			}
			if (!text2.StartsWith("cm:spawn", StringComparison.OrdinalIgnoreCase) || text2.Length <= "cm:spawn".Length || !char.IsWhiteSpace(text2["cm:spawn".Length]))
			{
				return false;
			}
			string text3 = text2.Substring("cm:spawn".Length).TrimStart(ArgumentSeparators);
			if (text3.Length == 0)
			{
				field = SpawnAutocompleteField.Prefab;
				return true;
			}
			int num = IndexOfWhitespace(text3);
			if (num < 0)
			{
				field = SpawnAutocompleteField.Prefab;
				currentToken = text3;
				return true;
			}
			string text4 = text3.Substring(num).TrimStart(ArgumentSeparators);
			if (text4.Length == 0)
			{
				field = SpawnAutocompleteField.Modifier;
				return true;
			}
			int num2 = LastNonWhitespaceIndex(text4);
			if (num2 < text4.Length - 1)
			{
				if (text4[num2] == ',')
				{
					field = SpawnAutocompleteField.Modifier;
					currentToken = text4;
				}
				return true;
			}
			int num3 = num2;
			while (num3 >= 0 && !char.IsWhiteSpace(text4[num3]))
			{
				num3--;
			}
			string s = text4.Substring(num3 + 1);
			int result;
			if (num3 >= 0)
			{
				int num4 = LastNonWhitespaceIndex(text4, num3);
				if (num4 < 0 || text4[num4] != ',')
				{
					return true;
				}
			}
			else if (int.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out result))
			{
				return true;
			}
			field = SpawnAutocompleteField.Modifier;
			currentToken = text4;
			return true;
		}

		private static int IndexOfWhitespace(string value)
		{
			for (int i = 0; i < value.Length; i++)
			{
				if (char.IsWhiteSpace(value[i]))
				{
					return i;
				}
			}
			return -1;
		}

		private static int LastNonWhitespaceIndex(string value, int exclusiveEnd = -1)
		{
			int num = ((exclusiveEnd < 0) ? (value.Length - 1) : Mathf.Min(exclusiveEnd - 1, value.Length - 1));
			while (num >= 0 && char.IsWhiteSpace(value[num]))
			{
				num--;
			}
			return num;
		}

		private static List<string> GetModifierAutocompleteOptions(string modifierToken, out string currentModifier)
		{
			string[] array = modifierToken.Split(new char[1] { ',' }, StringSplitOptions.None);
			currentModifier = array[^1].Trim();
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			for (int i = 0; i < array.Length - 1; i++)
			{
				string text = array[i].Trim();
				if (text.Length > 0)
				{
					hashSet.Add(text);
				}
			}
			if (hashSet.Count >= 4)
			{
				return EmptyAutocompleteOptions;
			}
			IReadOnlyList<string> knownModifierKeys = CreatureModifierManager.GetKnownModifierKeys();
			List<string> list = new List<string>(knownModifierKeys.Count - hashSet.Count);
			foreach (string item in knownModifierKeys)
			{
				if (!hashSet.Contains(item))
				{
					list.Add(item);
				}
			}
			return list;
		}

		private static void WriteReference(ConsoleEventArgs args)
		{
			CreatureAssetOwnerCatalog.RefreshMappings();
			string scope = GetScope(args);
			if (!IsKnownScope(scope, args, "cm:reference", includeTexture: true))
			{
				return;
			}
			if (scope switch
			{
				"ai" => CreatureDomainManager.TryWriteAiReferenceConfigurationFile(out string path, out string error), 
				"attack" => CreatureDomainManager.TryWriteAttackReferenceConfigurationFile(out path, out error), 
				"loadout" => CreatureDomainManager.TryWriteCreatureLoadoutReferenceConfigurationFile(out path, out error), 
				"projectile" => CreatureDomainManager.TryWriteProjectileReferenceConfigurationFile(out path, out error), 
				"texture" => CreatureDomainManager.TryWriteTextureReferenceConfigurationFile(out path, out error), 
				"levelvisual" => CreatureDomainManager.TryWriteLevelVisualReferenceConfigurationFile(out path, out error), 
				_ => CreatureDomainManager.TryWriteReferenceConfigurationFile(out path, out error), 
			})
			{
				Terminal context = args.Context;
				if (context != null)
				{
					context.AddString("Wrote " + NormalizeScope(scope) + " reference to " + path);
				}
			}
			else
			{
				Terminal context2 = args.Context;
				if (context2 != null)
				{
					context2.AddString(error);
				}
			}
		}

		private static void WriteFull(ConsoleEventArgs args)
		{
			CreatureAssetOwnerCatalog.RefreshMappings();
			string scope = GetScope(args);
			string path;
			string error;
			if (scope != "creature")
			{
				Terminal context = args.Context;
				if (context != null)
				{
					context.AddString("Syntax: cm:full creature");
				}
			}
			else if (CreatureDomainManager.TryWriteFullScaffoldConfigurationFile(out path, out error))
			{
				Terminal context2 = args.Context;
				if (context2 != null)
				{
					context2.AddString("Wrote " + NormalizeScope(scope) + " full scaffold to " + path);
				}
			}
			else
			{
				Terminal context3 = args.Context;
				if (context3 != null)
				{
					context3.AddString(error);
				}
			}
		}

		private static void Karma(ConsoleEventArgs args)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			if (!RequireAuthoritativeAdmin(args))
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				Terminal context = args.Context;
				if (context != null)
				{
					context.AddString("No local player.");
				}
				return;
			}
			ExecuteKarma(args, ((Component)localPlayer).transform.position, delegate(string message)
			{
				Terminal context2 = args.Context;
				if (context2 != null)
				{
					context2.AddString(message);
				}
			});
		}

		private static void ExecuteKarma(ConsoleEventArgs args, Vector3 playerPosition, Action<string> reply)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			if (args.Length == 1)
			{
				reply(CreatureKarmaManager.GetDebugLine(playerPosition));
				return;
			}
			if (args.Length != 2 || !float.TryParse(args[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || float.IsNaN(result) || float.IsInfinity(result) || result < 0f)
			{
				reply("Syntax: cm:karma [non-negative value]");
				return;
			}
			CreatureKarmaManager.SetDebugKarma(playerPosition, result);
			reply(CreatureKarmaManager.GetDebugLine(playerPosition));
		}

		private static void Spawn(ConsoleEventArgs args)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			if (!RequireAuthoritativeAdmin(args))
			{
				return;
			}
			if (!CreatureLevelManager.IsLevelSystemEnabled())
			{
				Terminal context = args.Context;
				if (context != null)
				{
					context.AddString("CreatureManager level system is disabled.");
				}
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				Terminal context2 = args.Context;
				if (context2 != null)
				{
					context2.AddString("No local player.");
				}
				return;
			}
			ExecuteSpawn(args, ((Component)localPlayer).transform.position, ((Component)localPlayer).transform.rotation, delegate(string message)
			{
				Terminal context3 = args.Context;
				if (context3 != null)
				{
					context3.AddString(message);
				}
			});
		}

		private static void ExecuteSpawn(ConsoleEventArgs args, Vector3 playerPosition, Quaternion playerRotation, Action<string> reply)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_00ab: 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)
			if (!TryParseSpawnArguments(args, out string prefabName, out int level, out List<string> modifiers, out string error))
			{
				reply(error);
				return;
			}
			GameObject prefab = CreaturePrefabRegistry.GetPrefab(prefabName);
			if ((Object)(object)prefab == (Object)null)
			{
				reply("Creature prefab '" + prefabName + "' was not found.");
				return;
			}
			if ((Object)(object)prefab.GetComponent<Character>() == (Object)null || CreaturePrefabRegistry.IsPlayerPrefab(prefab))
			{
				reply("Prefab '" + prefabName + "' is not a supported non-player creature.");
				return;
			}
			Vector3 commandSpawnPosition = GetCommandSpawnPosition(playerPosition, playerRotation * Vector3.forward);
			Quaternion val = Quaternion.Euler(0f, ((Quaternion)(ref playerRotation)).eulerAngles.y, 0f);
			GameObject val2 = null;
			CreatureManagerSpawnLifecycle.BeginSourceContext(CreatureSpawnSourceKind.Managed);
			try
			{
				val2 = Object.Instantiate<GameObject>(prefab, commandSpawnPosition, val);
			}
			catch (Exception ex)
			{
				error = "Failed to spawn '" + prefabName + "': " + ex.Message;
			}
			finally
			{
				CreatureManagerSpawnLifecycle.EndSourceContext();
			}
			if ((Object)(object)val2 == (Object)null)
			{
				reply((error.Length > 0) ? error : ("Failed to spawn '" + prefabName + "'."));
				return;
			}
			Character component = val2.GetComponent<Character>();
			if ((Object)(object)component == (Object)null || !CreatureModifierManager.TryApplyForcedModifiers(component, modifiers, out error) || !CreatureLevelManager.TryApplyForcedLevel(component, level, out error))
			{
				CleanupFailedSpawn(val2);
				reply((error.Length > 0) ? error : ("Failed to initialize '" + prefabName + "'."));
			}
			else
			{
				CreatureManagerCharacterLifecycle.ApplyLevelAndModifiers(component);
				string arg = ((modifiers.Count > 0) ? string.Join(", ", modifiers) : "none");
				reply($"Spawned {((Object)prefab).name} at level {level} with modifiers: {arg}.");
			}
		}

		private static void CleanupFailedSpawn(GameObject spawned)
		{
			try
			{
				ZNetView component = spawned.GetComponent<ZNetView>();
				if ((Object)(object)ZNetScene.instance != (Object)null && (Object)(object)component != (Object)null && component.IsValid() && component.GetZDO() != null)
				{
					ZNetScene.instance.Destroy(spawned);
					return;
				}
			}
			catch
			{
			}
			Object.Destroy((Object)(object)spawned);
		}

		internal static bool TryHandleAuthenticatedRemoteAdminCommand(ZNet znet, ZRpc rpc, string command)
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: 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_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Expected O, but got Unknown
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			string remoteCommandName = GetRemoteCommandName(command);
			if (!string.Equals(remoteCommandName, "cm:spawn", StringComparison.OrdinalIgnoreCase) && !string.Equals(remoteCommandName, "cm:karma", StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			if (!znet.IsServer() || rpc == null)
			{
				return false;
			}
			Action<string> action = delegate(string message)
			{
				try
				{
					znet.RemotePrint(rpc, message);
				}
				catch
				{
				}
			};
			try
			{
				ZNetPeer peer = znet.GetPeer(rpc);
				if (peer == null || !peer.IsReady() || ((ZDOID)(ref peer.m_characterID)).IsNone() || ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null)
				{
					action("Could not resolve the remote admin's active player.");
					return true;
				}
				ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID);
				GameObject val = ((zDO != null) ? ZNetScene.instance.GetPrefab(zDO.GetPrefab()) : null);
				if (zDO == null || zDO.GetOwner() != peer.m_uid || (Object)(object)val == (Object)null || (Object)(object)val.GetComponent<Player>() == (Object)null)
				{
					action("Could not validate the remote admin's active player.");
					return true;
				}
				Vector3 position = zDO.GetPosition();
				Quaternion val2 = zDO.GetRotation();
				if (!IsFinite(position))
				{
					action("Could not validate the remote admin's player position.");
					return true;
				}
				if (!IsFinite(val2))
				{
					val2 = Quaternion.identity;
				}
				ConsoleEventArgs args = new ConsoleEventArgs(command, (Terminal)(object)Console.instance);
				if (string.Equals(remoteCommandName, "cm:spawn", StringComparison.OrdinalIgnoreCase))
				{
					if (!CreatureLevelManager.IsLevelSystemEnabled())
					{
						action("CreatureManager level system is disabled.");
						return true;
					}
					ExecuteSpawn(args, position, val2, action);
				}
				else
				{
					ExecuteKarma(args, position, action);
				}
				ISocket socket = rpc.GetSocket();
				string text = ((socket != null) ? socket.GetHostName() : null) ?? "";
				CreatureManagerPlugin.Log.LogInfo((object)("Remote admin '" + text + "' executed CreatureManager command '" + remoteCommandName + "'."));
			}
			catch (Exception ex)
			{
				CreatureManagerPlugin.Log.LogWarning((object)("Failed to execute remote CreatureManager command '" + remoteCommandName + "': " + ex.Message));
				action("CreatureManager could not execute the remote command. Check the server log.");
			}
			return true;
		}

		private static string GetRemoteCommandName(string command)
		{
			if (string.IsNullOrWhiteSpace(command))
			{
				return "";
			}
			int num = command.IndexOfAny(ArgumentSeparators);
			return ((num >= 0) ? command.Substring(0, num) : command).Trim();
		}

		private static bool RequireAuthoritativeAdmin(ConsoleEventArgs args)
		{
			if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && ZNet.instance.LocalPlayerIsAdminOrHost())
			{
				return true;
			}
			Terminal context = args.Context;
			if (context != null)
			{
				context.AddString("This command must be run locally by the server host.");
			}
			return false;
		}

		private static bool TryParseSpawnArguments(ConsoleEventArgs args, out string prefabName, out int level, out List<string> modifiers, out string error)
		{
			prefabName = ((args.Length >= 2) ? (args[1] ?? "").Trim() : "");
			level = 1;
			modifiers = new List<string>();
			error = "";
			if (prefabName.Length == 0)
			{
				error = "Syntax: cm:spawn <prefab> [modifier1,modifier2,modifier3,modifier4] [level]";
				return false;
			}
			int num = args.Length;
			if (args.Length >= 3 && int.TryParse(args[args.Length - 1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
			{
				if (result < 1 || result > 100)
				{
					error = $"level must be an integer from 1 to {100}.";
					return false;
				}
				level = result;
				num--;
			}
			if (num > 2)
			{
				List<string> list = new List<string>(num - 2);
				for (int i = 2; i < num; i++)
				{
					list.Add(args[i] ?? "");
				}
				string text = string.Join(" ", list).Trim();
				string[] array = text.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				if (text.Length == 0 || array.Length == 0 || !CreatureModifierManager.TryNormalizeForcedModifierKeys(array, out modifiers, out error))
				{
					error = ((error.Length > 0) ? error : "At least one modifier must be specified.");
					return false;
				}
			}
			return true;
		}

		private static Vector3 GetCommandSpawnPosition(Vector3 playerPosition, Vector3 playerForward)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = playerForward;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				val = Vector3.forward;
			}
			((Vector3)(ref val)).Normalize();
			Vector3 val2 = playerPosition + val * 3f;
			if (val2.y >= 4000f)
			{
				return val2 + Vector3.up * 0.5f;
			}
			float num = default(float);
			if ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGroundHeight(val2 + Vector3.up * 100f, ref num))
			{
				val2.y = num + 0.5f;
			}
			else if (WorldGenerator.instance != null)
			{
				val2.y = WorldGenerator.instance.GetHeight(val2.x, val2.z) + 0.5f;
			}
			else
			{
				val2.y += 0.5f;
			}
			return val2;
		}

		private static bool IsFinite(Vector3 value)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (IsFinite(value.x) && IsFinite(value.y))
			{
				return IsFinite(value.z);
			}
			return false;
		}

		private static bool IsFinite(Quaternion value)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (IsFinite(value.x) && IsFinite(value.y) && IsFinite(value.z))
			{
				return IsFinite(value.w);
			}
			return false;
		}

		private static bool IsFinite(float value)
		{
			if (!float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}

		private static string GetScope(ConsoleEventArgs args)
		{
			if (args.Length < 2)
			{
				return "";
			}
			return (args[1] ?? "").Trim().ToLowerInvariant();
		}

		private static bool IsKnownScope(string scope, ConsoleEventArgs args, string command, bool includeTexture)
		{
			bool flag;
			switch (scope)
			{
			case "creature":
			case "ai":
			case "attack":
				flag = true;
				break;
			default:
				flag = false;
				break;
			}
			if (flag)
			{
				return true;
			}
			flag = includeTexture;
			if (flag)
			{
				bool flag2;
				switch (scope)
				{
				case "loadout":
				case "projectile":
				case "texture":
				case "levelvisual":
					flag2 = true;
					break;
				default:
					flag2 = false;
					break;
				}
				flag = flag2;
			}
			if (flag)
			{
				return true;
			}
			Terminal context = args.Context;
			if (context != null)
			{
				context.AddString(includeTexture ? ("Syntax: " + command + " creature|ai|attack|loadout|projectile|texture|levelvisual") : ("Syntax: " + command + " creature|ai|attack"));
			}
			return false;
		}

		private static string NormalizeScope(string scope)
		{
			return scope switch
			{
				"ai" => "ai", 
				"attack" => "attack", 
				"loadout" => "loadout", 
				"projectile" => "projectile", 
				"texture" => "texture", 
				"levelvisual" => "levelvisual", 
				_ => "creature", 
			};
		}
	}
	internal static class CreatureCompendiumManager
	{
		private readonly struct CompendiumModifierEntry
		{
			internal readonly string ModifierKey;

			internal readonly string GroupHeading;

			internal readonly string Name;

			internal readonly string Description;

			internal readonly Sprite Sprite;

			internal CompendiumModifierEntry(string modifierKey, string groupHeading, string name, string description, Sprite sprite)
			{
				ModifierKey = modifierKey;
				GroupHeading = groupHeading;
				Name = name;
				Description = description;
				Sprite = sprite;
			}
		}

		private const string PageTopic = "CreatureManager";

		private const string BodyIconPrefix = "CreatureManager_CompendiumModifierIcon_";

		private const string IconLinkPrefix = "cm-modifier-icon-";

		private const char IconPlaceholder = '';

		private const float IconSize = 18f;

		private const float IconTextGap = 5f;

		internal static void AddModifierEntries(TextsDialog dialog)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			if ((Object)(object)dialog == (Object)null || dialog.m_texts == null)
			{
				return;
			}
			dialog.m_texts.RemoveAll((TextInfo text) => IsCreatureManagerPage(text?.m_topic));
			ConfigEntry<CreatureManagerPlugin.Toggle> enableLevelSystem = CreatureManagerPlugin.EnableLevelSystem;
			if (enableLevelSystem != null && enableLevelSystem.Value == CreatureManagerPlugin.Toggle.Off)
			{
				return;
			}
			List<CompendiumModifierEntry> list = BuildEntries();
			if (list.Count != 0)
			{
				TextInfo item = new TextInfo("CreatureManager", BuildPageText(list));
				dialog.m_texts.Add(item);
				dialog.m_texts.Sort((TextInfo a, TextInfo b) => a.m_topic.CompareTo(b.m_topic));
			}
		}

		internal static void RefreshPageContentIcons(TextsDialog dialog, TextInfo info)
		{
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: 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_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)dialog == (Object)null || info == null || (Object)(object)dialog.m_textArea == (Object)null)
			{
				return;
			}
			ClearPageContentIcons(dialog);
			if (!IsCreatureManagerPage(info.m_topic))
			{
				return;
			}
			List<CompendiumModifierEntry> list = BuildEntries();
			if (list.Count == 0)
			{
				return;
			}
			Dictionary<string, CompendiumModifierEntry> dictionary = new Dictionary<string, CompendiumModifierEntry>(StringComparer.OrdinalIgnoreCase);
			foreach (CompendiumModifierEntry item in list)
			{
				dictionary[item.ModifierKey] = item;
			}
			TMP_Text textArea = dialog.m_textArea;
			Transform parent = textArea.transform.parent;
			RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			textArea.ForceMeshUpdate(false, false);
			LayoutRebuilder.ForceRebuildLayoutImmediate(val);
			textArea.ForceMeshUpdate(false, false);
			TMP_TextInfo textInfo = textArea.textInfo;
			for (int i = 0; i < textInfo.linkCount; i++)
			{
				TMP_LinkInfo val2 = textInfo.linkInfo[i];
				string linkID = ((TMP_LinkInfo)(ref val2)).GetLinkID();
				if (linkID.StartsWith("cm-modifier-icon-", StringComparison.Ordinal) && dictionary.TryGetValue(linkID.Substring("cm-modifier-icon-".Length), out var value) && val2.linkTextfirstCharacterIndex >= 0 && val2.linkTextfirstCharacterIndex < textInfo.characterCount)
				{
					TMP_CharacterInfo marker = textInfo.characterInfo[val2.linkTextfirstCharacterIndex];
					AttachBodyIcon(val, textArea.rectTransform, marker, value.Sprite, value.ModifierKey);
				}
			}
		}

		private static List<CompendiumModifierEntry> BuildEntries()
		{
			List<CompendiumModifierEntry> list = new List<CompendiumModifierEntry>();
			Dictionary<string, ModifierDefinition> globalModifierDefinitions = CreatureLevelManager.GetGlobalModifierDefinitions();
			if (globalModifierDefinitions.Count == 0)
			{
				return list;
			}
			foreach (string knownModifierKey in CreatureModifierManager.GetKnownModifierKeys())
			{
				if (globalModifierDefinitions.TryGetValue(knownModifierKey, out var value) && CreatureModifierManager.TryGetModifierSprite(knownModifierKey, out Sprite sprite))
				{
					list.Add(new CompendiumModifierEntry(knownModifierKey, CreatureModifierManager.GetModifierGroupHeading(knownModifierKey), CreatureModifierManager.GetModifierDisplayName(knownModifierKey), CreatureModifierManager.GetModifierCompendiumText(knownModifierKey, value), sprite));
				}
			}
			return list;
		}

		private static string BuildPageText(List<CompendiumModifierEntry> entries)
		{
			StringBuilder stringBuilder = new StringBuilder();
			string a = string.Empty;
			foreach (CompendiumModifierEntry entry in entries)
			{
				if (!string.Equals(a, entry.GroupHeading, StringComparison.Ordinal))
				{
					if (stringBuilder.Length > 0)
					{
						stringBuilder.Append('\n');
					}
					stringBuilder.Append("<color=#FFD27A><b>").Append(entry.GroupHeading).Append("</b></color>\n\n");
					a = entry.GroupHeading;
				}
				stringBuilder.Append("<link=\"").Append("cm-modifier-icon-").Append(entry.ModifierKey)
					.Append("\"><color=#00000000>")
					.Append('')
					.Append("</color></link> ")
					.Append("   ")
					.Append("<color=orange><b>")
					.Append(entry.Name)
					.Append("</b></color>")
					.Append('\n')
					.Append("     ")
					.Append(entry.Description)
					.Append("\n\n");
			}
			return stringBuilder.ToString().TrimEnd(Array.Empty<char>());
		}

		private static void AttachBodyIcon(RectTransform content, RectTransform textArea, TMP_CharacterInfo marker, Sprite sprite, string modifierKey)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)content == (Object)null) && !((Object)(object)textArea == (Object)null) && !((Object)(object)sprite == (Object)null))
			{
				GameObject val = new GameObject("CreatureManager_CompendiumModifierIcon_" + modifierKey, new Type[3]
				{
					typeof(RectTransform),
					typeof(Image),
					typeof(LayoutElement)
				})
				{
					layer = ((Component)textArea).gameObject.layer
				};
				RectTransform val2 = (RectTransform)val.transform;
				((Transform)val2).SetParent((Transform)(object)content, false);
				val2.anchorMin = content.pivot;
				val2.anchorMax = content.pivot;
				val2.pivot = new Vector2(0.5f, 0.5f);
				val2.sizeDelta = new Vector2(18f, 18f);
				Vector3 val3 = (marker.bottomLeft + marker.topLeft) * 0.5f;
				val3.x += 14f;
				Vector3 val4 = ((Transform)textArea).TransformPoint(val3);
				Vector3 val5 = ((Transform)content).InverseTransformPoint(val4);
				val2.anchoredPosition = new Vector2(val5.x, val5.y);
				Image component = val.GetComponent<Image>();
				component.sprite = sprite;
				component.preserveAspect = true;
				((Graphic)component).raycastTarget = false;
				val.GetComponent<LayoutElement>().ignoreLayout = true;
			}
		}

		private static void ClearPageContentIcons(TextsDialog dialog)
		{
			if (!((Object)(object)dialog?.m_textArea == (Object)null))
			{
				ClearIconChildren(dialog.m_textArea.transform);
				if ((Object)(object)dialog.m_textArea.transform.parent != (Object)null)
				{
					ClearIconChildren(dialog.m_textArea.transform.parent);
				}
			}
		}

		private static void ClearIconChildren(Transform parent)
		{
			for (int num = parent.childCount - 1; num >= 0; num--)
			{
				Transform child = parent.GetChild(num);
				if (((Object)child).name.StartsWith("CreatureManager_CompendiumModifierIcon_", StringComparison.Ordinal))
				{
					Object.Destroy((Object)(object)((Component)child).gameObject);
				}
			}
		}

		private static bool IsCreatureManagerPage(string? topic)
		{
			return string.Equals(topic, "CreatureManager", StringComparison.Ordinal);
		}
	}
	internal sealed class CreatureDefinition
	{
		public string? Prefab { get; set; }

		public bool? Enabled { get; set; }

		public string? ClonedFrom { get; set; }

		public string? Ai { get; set; }

		public CharacterDefinition? Character { get; set; }

		public HumanoidDefinition? Humanoid { get; set; }

		public float? Scale { get; set; }

		public List<string>? Textures { get; set; }

		public AppearanceDefinition? Appearance { get; set; }

		public List<string>? AvailableAttackAnimations { get; set; }

		internal bool IsEnabled => Enabled != false;
	}
	internal sealed class AiDefinition
	{
		public string? Ai { get; set; }

		public bool? Enabled { get; set; }

		public string? CopyFrom { get; set; }

		public string? ClonedFrom { get; set; }

		public BaseAiDefinition? BaseAI { get; set; }

		public MonsterAiDefinition? MonsterAI { get; set; }

		internal bool IsEnabled => Enabled != false;
	}
	internal sealed class BaseAiDefinition
	{
		public List<string>? Senses { get; set; }

		public List<float>? IdleSound { get; set; }

		public List<string>? Movement { get; set; }

		public List<string>? Serpent { get; set; }

		public List<float>? RandomMove { get; set; }

		public List<string>? Flight { get; set; }

		public List<string>? Avoid { get; set; }

		public List<float>? Flee { get; set; }

		public List<string>? Aggressive { get; set; }

		public List<string>? Messages { get; set; }
	}
	internal sealed class MonsterAiDefinition
	{
		public float? AlertRange { get; set; }

		public List<string>? Hunt { get; set; }

		public List<float>? Chase { get; set; }

		public List<float>? Circle { get; set; }

		public List<string>? HurtFlee { get; set; }

		public List<string>? Charge { get; set; }

		public List<string>? Sleep { get; set; }

		public bool? AvoidLand { get; set; }
	}
	internal sealed class AttackDefinition
	{
		public string? Prefab { get; set; }

		public bool? Enabled { get; set; }

		public string? ClonedFrom { get; set; }

		public AttackDamageDefinition? Damage { get; set; }

		public List<string>? Attack { get; set; }

		public List<string>? StatusEffect { get; set; }

		public List<string>? Projectile { get; set; }

		public List<float>? Ai { get; set; }

		internal bool IsEnabled => Enabled != false;
	}
	internal sealed class ProjectileDefinition
	{
		public string? Prefab { get; set; }

		public bool? Enabled { get; set; }

		public string? ClonedFrom { get; set; }

		public List<string>? UsedByAttacks { get; set; }

		public ProjectileComponentDefinition? Projectile { get; set; }

		public SpawnAbilityDefinition? SpawnAbility { get; set; }

		internal bool IsEnabled => Enabled != false;
	}
	internal sealed class ProjectileComponentDefinition
	{
		private string? _spawnOnHit;

		[YamlIgnore]
		public string? SpawnOnHit
		{
			get
			{
				return _spawnOnHit;
			}
			set
			{
				_spawnOnHit = value;
				SpawnOnHitSpecified = true;
			}
		}

		[YamlIgnore]
		public bool SpawnOnHitSpecified { get; private set; }

		[YamlMember(Alias = "spawnOnHit")]
		public ExplicitNullableYamlString? SerializedSpawnOnHit
		{
			get
			{
				if (!SpawnOnHitSpecified)
				{
					return null;
				}
				return new ExplicitNullableYamlString(_spawnOnHit);
			}
			set
			{
				_spawnOnHit = value?.Value;
				SpawnOnHitSpecified = true;
			}
		}

		internal bool HasSpecifiedFields => SpawnOnHitSpecified;
	}
	internal sealed class SpawnAbilityDefinition
	{
		private List<string>? _spawnPrefabs;

		public List<string>? SpawnPrefabs
		{
			get
			{
				return _spawnPrefabs;
			}
			set
			{
				_spawnPrefabs = value;
				SpawnPrefabsSpecified = true;
			}
		}

		[YamlIgnore]
		public bool SpawnPrefabsSpecified { get; private set; }
	}
	internal sealed class ExplicitNullableYamlString : IYamlConvertible
	{
		internal string? Value { get; private set; }

		public ExplicitNullableYamlString()
		{
		}

		internal ExplicitNullableYamlString(string? value)
		{
			Value = value;
		}

		public void Read(IParser parser, Type expectedType, ObjectDeserializer nestedObjectDeserializer)
		{
			Value = (string)nestedObjectDeserializer(typeof(string));
		}

		public void Write(IEmitter emitter, ObjectSerializer nestedObjectSerializer)
		{
			nestedObjectSerializer(Value, typeof(string));
		}
	}
	internal sealed class FactionDefinition
	{
		public string? Faction { get; set; }

		public int? Id { get; set; }

		public List<string>? Friendly { get; set; }

		public List<string>? AggravatedFriendly { get; set; }

		public List<string>? AlertedFriendly { get; set; }
	}
	internal static class CreatureModifierCatalog
	{
		internal static readonly IReadOnlyList<string> Keys = Array.AsReadOnly(new string[32]
		{
			"enraged", "fire", "frost", "lightning", "spirit", "armorPiercing", "staggering", "undodgeable", "armored", "deathward",
			"regenerating", "reflection", "vortex", "adaptive", "unflinching", "chameleon", "exposed", "weakened", "withered", "crippling",
			"disruptive", "adrenalineDrain", "corrosive", "toxicDeath", "swift", "attackSpeed", "vampiric", "reaping", "blink", "omen",
			"juggernaut", "blamer"
		});

		private static readonly HashSet<string> KeySet = new HashSet<string>(Keys, StringComparer.OrdinalIgnoreCase);

		internal static bool IsKnown(string modifier)
		{
			if (!string.IsNullOrWhiteSpace(modifier))
			{
				return KeySet.Contains(modifier.Trim());
			}
			return false;
		}
	}
	internal sealed class LevelDefinition
	{
		private Dictionary<string, ModifierDefinition>? _modifiers;

		public string? Target { get; set; }

		public string? Biome { get; set; }

		public List<string>? Prefabs { get; set; }

		public List<float>? Level { get; set; }

		public float? Damage { get; set; }

		public float? DamagePerLevel { get; set; }

		public float? Health { get; set; }

		public float? HealthPerLevel { get; set; }

		public float? ScalePerLevel { get; set; }

		public List<float>? DistanceScaling { get; set; }

		public List<float>? ModifierDistanceScaling { get; set; }

		public Dictionary<string, ModifierDefinition>? Modifiers
		{
			get
			{
				return _modifiers;
			}
			set
			{
				_modifiers = ((value == null) ? null : new Dictionary<string, ModifierDefinition>(value, StringComparer.OrdinalIgnoreCase));
			}
		}

		public bool ModifiersCleared { get; set; }

		public bool IsPreset { get; set; }
	}
	internal sealed class ModifierDefinition
	{
		public float? Chance { get; set; }

		public float? Power { get; set; }

		public float? Cooldown { get; set; }

		public int? MaxActivations { get; set; }

		public float? MaxRange { get; set; }

		public string? StartEffect { get; set; }

		public float? ProcChance { get; set; }

		public float? Duration { get; set; }

		public float? SecondaryPower { get; set; }

		public float? Radius { get; set; }

		public string? TriggerEffect { get; set; }

		public float? MaxKarmaGain { get; set; }

		public float? FleeHealthRatio { get; set; }

		public int? ReapingHealMaxActivations { get; set; }

		public float? ReapingMaxHealthPerKill { get; set; }

		public float? ReapingMaxHealthCap { get; set; }

		public float? ReapingDamagePerKill { get; set; }

		public float? ReapingDamageCap { get; set; }

		public float? ReapingScalePerKill { get; set; }

		public float? ReapingScaleCap { get; set; }

		internal ModifierDefinition Clone()
		{
			ModifierDefinition modifierDefinition = new ModifierDefinition();
			modifierDefinition.OverlayFrom(this);
			return modifierDefinition;
		}

		internal void OverlayFrom(ModifierDefinition source)
		{
			if (source.Chance.HasValue)
			{
				Chance = source.Chance;
			}
			if (source.Power.HasValue)
			{
				Power = source.Power;
			}
			if (source.Cooldown.HasValue)
			{
				Cooldown = source.Cooldown;
			}
			if (source.MaxActivations.HasValue)
			{
				MaxActivations = source.MaxActivations;
			}
			if (source.MaxRange.HasValue)
			{
				MaxRange = source.MaxRange;
			}
			if (source.StartEffect != null)
			{
				StartEffect = source.StartEffect;
			}
			if (source.ProcChance.HasValue)
			{
				ProcChance = source.ProcChance;
			}
			if (source.Duration.HasValue)
			{
				Duration = source.Duration;
			}
			if (source.SecondaryPower.HasValue)
			{
				SecondaryPower = source.SecondaryPower;
			}
			if (source.Radius.HasValue)
			{
				Radius = source.Radius;
			}
			if (source.TriggerEffect != null)
			{
				TriggerEffect = source.TriggerEffect;
			}
			if (source.MaxKarmaGain.HasValue)
			{
				MaxKarmaGain = source.MaxKarmaGain;
			}
			if (source.FleeHealthRatio.HasValue)
			{
				FleeHealthRatio = source.FleeHealthRatio;
			}
			if (source.ReapingHealMaxActivations.HasValue)
			{
				ReapingHealMaxActivations = source.ReapingHealMaxActivations;
			}
			if (source.ReapingMaxHealthPerKill.HasValue)
			{
				ReapingMaxHealthPerKill = source.ReapingMaxHealthPerKill;
			}
			if (source.ReapingMaxHealthCap.HasValue)
			{
				ReapingMaxHealthCap = source.ReapingMaxHealthCap;
			}
			if (source.ReapingDamagePerKill.HasValue)
			{
				ReapingDamagePerKill = source.ReapingDamagePerKill;
			}
			if (source.ReapingDamageCap.HasValue)
			{
				ReapingDamageCap = source.ReapingDamageCap;
			}
			if (source.ReapingScalePerKill.HasValue)
			{
				ReapingScalePerKill = source.ReapingScalePerKill;
			}
			if (source.ReapingScaleCap.HasValue)
			{
				ReapingScaleCap = source.ReapingScaleCap;
			}
		}
	}
	internal sealed class ModifierChanceDefinition
	{
		private readonly Dictionary<string, float> _values = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase);

		internal float? Get(string modifier)
		{
			if (!_values.TryGetValue(modifier, out var value))
			{
				return null;
			}
			return value;
		}

		internal void Set(string modifier, float chance)
		{
			_values[modifier] = chance;
		}
	}
	internal sealed class ModifierPowerDefinition
	{
		private readonly Dictionary<string, float> _values = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase);

		public float? DeathwardCooldown { get; set; }

		public int? DeathwardMaxActivations { get; set; }

		public float? ReflectionProcChance { get; set; }

		public float? ExposedProcChance { get; set; }

		public float? ExposedDuration { get; set; }

		public float? WeakenedProcChance { get; set; }

		public float? WeakenedDuration { get; set; }

		public float? WitheredProcChance { get; set; }

		public float? WitheredDuration { get; set; }

		public float? CripplingJump { get; set; }

		public float? CripplingProcChance { get; set; }

		public float? CripplingDuration { get; set; }

		public float? DisruptiveEitr { get; set; }

		public float? DisruptiveProcChance { get; set; }

		public float? DisruptiveDuration { get; set; }

		public float? AdrenalineDrainGainReduction { get; set; }

		public float? AdrenalineDrainProcChance { get; set; }

		public float? AdrenalineDrainDuration { get; set; }

		public float? CorrosiveProcChance { get; set; }

		public float? CorrosiveDuration { get; set; }

		public float? ToxicDeathRadius { get; set; }

		public string? ToxicDeathTriggerEffect { get; set; }

		public int? ReapingHealMaxActivations { get; set; }

		public float? ReapingMaxHealthPerKill { get; set; }

		public float? ReapingMaxHealthCap { get; set; }

		public float? ReapingDamagePerKill { get; set; }

		public float? ReapingDamageCap { get; set; }

		public float? ReapingScalePerKill { get; set; }

		public float? ReapingScaleCap { get; set; }

		public float? BlinkCooldown { get; set; }

		public float? BlinkMaxRange { get; set; }

		public string? BlinkStartEffect { get; set; }

		public float? KnockbackCooldown { get; set; }

		public float? BlamerMaxKarmaGain { get; set; }

		public float? BlamerFleeHealthRatio { get; set; }

		internal float? Get(string modifier)
		{
			if (!_values.TryGetValue(modifier, out var value))
			{
				return null;
			}
			return value;
		}

		internal void Set(string modifier, float power)
		{
			_values[modifier] = power;
		}
	}
	internal sealed class AttackDamageDefinition
	{
		public float? Damage { get; set; }

		public float? Blunt { get; set; }

		public float? Slash { get; set; }

		public float? Pierce { get; set; }

		public float? Chop { get; set; }

		public float? Pickaxe { get; set; }

		public float? Fire { get; set; }

		public float? Frost { get; set; }

		public float? Lightning { get; set; }

		public float? Poison { get; set; }

		public float? Spirit { get; set; }

		public float? AttackForce { get; set; }

		public int? ToolTier { get; set; }
	}
	internal sealed class CharacterDefinition
	{
		public string? Name { get; set; }

		public string? Faction { get; set; }

		public string? Boss { get; set; }

		public string? DefeatSetGlobalKey { get; set; }

		public string? Health { get; set; }

		public DamageModifiersDefinition? DamageModifiers { get; set; }

		public string? Speed { get; set; }

		public string? Jump { get; set; }

		public string? Swim { get; set; }

		public string? Flight { get; set; }
	}
	internal sealed class DamageModifiersDefinition
	{
		public string? Blunt { get; set; }

		public string? Slash { get; set; }

		public string? Pierce { get; set; }

		public string? Chop { get; set; }

		public string? Pickaxe { get; set; }

		public string? Fire { get; set; }

		public string? Frost { get; set; }

		public string? Lightning { get; set; }

		public string? Poison { get; set; }

		public string? Spirit { get; set; }
	}
	internal sealed class HumanoidDefinition
	{
		public List<string>? DefaultItems { get; set; }

		public List<string>? RandomWeapon { get; set; }

		public List<string>? RandomArmor { get; set; }

		public List<string>? RandomHair { get; set; }

		public List<string>? RandomShield { get; set; }

		public List<string>? RandomItems { get; set; }

		public List<string>? RandomSets { get; set; }
	}
	internal sealed class AppearanceDefinition
	{
		private string? _hair;

		private string? _beard;

		public string? Hair
		{
			get
			{
				return _hair;
			}
			set
			{
				_hair = ((value != null && string.IsNullOrWhiteSpace(value)) ? "" : value);
			}
		}

		public string? Beard
		{
			get
			{
				return _beard;
			}
			set
			{
				_beard = ((value != null && string.IsNullOrWhiteSpace(value)) ? "" : value);
			}
		}

		public string? HairColor { get; set; }

		public string? SkinColor { get; set; }

		public int? ModelIndex { get; set; }

		internal bool HasSpecifiedFields
		{
			get
			{
				if (Hair == null && Beard == null && HairColor == null && SkinColor == null)
				{
					return ModelIndex.HasValue;
				}
				return true;
			}
		}
	}
	internal static class CreatureDomainManager
	{
		private sealed class TextureMaterialOverride
		{
			internal Renderer Renderer;

			internal int MaterialIndex;

			internal Material Original;

			internal Material Generated;

			internal bool Active;
		}

		private sealed class RagdollScaleRuntimeState
		{
			internal readonly Vector3 FinalScale;

			internal readonly Vector3 EquipmentScale;

			internal RagdollScaleRuntimeState(Vector3 finalScale, Vector3 equipmentScale)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				FinalScale = finalScale;
				EquipmentScale = equipmentScale;
			}
		}

		private sealed class RagdollTextureRuntimeState
		{
			internal readonly string RendererName;

			internal readonly int MaterialIndex;

			internal readonly Texture Texture;

			internal RagdollTextureRuntimeState(string rendererName, int materialIndex, Texture texture)
			{
				RendererName = rendererName;
				MaterialIndex = materialIndex;
				Texture = texture;
			}
		}

		internal sealed class CreatureAppearanceRuntimeState
		{
			internal readonly string? Hair;

			internal readonly string? Beard;

			internal readonly Vector3? HairColor;

			internal readonly Vector3? SkinColor;

			internal readonly int? ModelIndex;

			internal bool HasSpecifiedFields
			{
				get
				{
					if (Hair == null && Beard == null && !HairColor.HasValue && !SkinColor.HasValue)
					{
						return ModelIndex.HasValue;
					}
					return true;
				}
			}

			internal CreatureAppearanceRuntimeState(string? hair, string? beard, Vector3? hairColor, Vector3? skinColor, int? modelIndex)
			{
				Hair = hair;
				Beard = beard;
				HairColor = hairColor;
				SkinColor = skinColor;
				ModelIndex = modelIndex;
			}
		}

		private sealed class DefinitionSnapshot
		{
			internal List<FactionDefinition> Factions = new List<FactionDefinition>();

			internal List<LevelDefinition> Levels = new List<LevelDefinition>();

			internal List<AiDefinition> Ai = new List<AiDefinition>();

			internal List<AttackDefinition> Attacks = new List<AttackDefinition>();

			internal List<ProjectileDefinition> Projectiles = new List<ProjectileDefinition>();

			internal List<CreatureDefinition> Creatures = new List<CreatureDefinition>();

			internal string KarmaYaml = "";
		}

		private sealed class SyncedYamlBundleData
		{
			public int Version { get; set; }

			public List<FactionDefinition>? Factions { get; set; }

			public List<LevelDefinition>? Levels { get; set; }

			public List<AiDefinition>? Ai { get; set; }

			public List<AttackDefinition>? Attacks { get; set; }

			public List<ProjectileDefinition>? Projectiles { get; set; }

			public List<CreatureDefinition>? Creatures { get; set; }

			public string? Karma { get; set; }
		}

		private sealed class DefinitionApplyCheckpoint
		{
			internal readonly Dictionary<string, CreatureAppearanceRuntimeState> InheritedAppearances = new Dictionary<string, CreatureAppearanceRuntimeState>(InheritedAppearanceByClone, StringComparer.OrdinalIgnoreCase);

			internal readonly Dictionary<string, GameObject> RagdollSources = new Dictionary<string, GameObject>(RagdollCloneSources, StringComparer.OrdinalIgnoreCase);

			internal readonly Dictionary<string, Vector3> OriginalRagdollScaleValues = new Dictionary<string, Vector3>(OriginalRagdollScales, StringComparer.OrdinalIgnoreCase);

			internal readonly Dictionary<string, RagdollScaleRuntimeState> InheritedRagdollScaleValues = new Dictionary<string, RagdollScaleRuntimeState>(InheritedRagdollScales, StringComparer.OrdinalIgnoreCase);

			internal readonly Dictionary<string, RagdollTextureRuntimeState[]> InheritedRagdollTextureValues = new Dictionary<string, RagdollTextureRuntimeState[]>(InheritedRagdollTextures, StringComparer.OrdinalIgnoreCase);

			internal readonly Dictionary<(int RendererId, int MaterialIndex), TextureMaterialOverride> TextureOverrides = new Dictionary<(int, int), TextureMaterialOverride>(TextureMaterialOverrides);
		}

		private sealed class ReferenceFileSnapshot
		{
			internal readonly string CreatureYaml;

			internal readonly string AiYaml;

			internal readonly string AttackYaml;

			internal readonly string CreatureLoadout;

			internal readonly string ProjectileYaml;

			internal readonly string TextureReference;

			internal readonly string Signature;

			internal ReferenceFileSnapshot(string creatureYaml, string aiYaml, string attackYaml, string creatureLoadout, string projectileYaml, string textureReference, string signature)
			{
				CreatureYaml = creatureYaml;
				AiYaml = aiYaml;
				AttackYaml = attackYaml;
				CreatureLoadout = creatureLoadout;
				ProjectileYaml = projectileYaml;
				TextureReference = textureReference;
				Signature = signature;
			}
		}

		private sealed class CloneMaterializationRequest
		{
			internal readonly string Target;

			internal readonly string Source;

			internal readonly string Domain;

			internal CloneMaterializationRequest(string target, string source, string domain)
			{
				Target = target;
				Source = source;
				Domain = domain;
			}
		}

		private delegate bool TryReadYaml<T>(string yaml, string source, out List<T> definitions);

		private const long ReloadDebounceTicks = 2500000L;

		private const long SyncedApplyDebounceTicks = 1000000L;

		private const int SyncedYamlBundleVersion = 4;

		private const string ReferenceLogicVersion = "2026-07-21-ragdoll-visual-v2";

		private const string MainTextureProperty = "_MainTex";

		private const string RagdollCloneSuffix = "_CreatureManagerRagdoll";

		private const string DefaultTextureResourcePrefix = "CreatureManager.defaults.textures.";

		private static readonly string[] DefaultTextureFileNames = new string[11]
		{
			"boar2.png", "DarkBrood.png", "DarkSpider.png", "DarkSpiderSmall.png", "goblin2.png", "PolarFenring.png", "PolarLox.png", "PolarWolf.png", "StormFenring.png", "SvartalfarMage.png",
			"troll2.png"
		};

		private static readonly object Sync = new object();

		private static readonly ISerializer Serializer = new SerializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitNull).Build();

		private static readonly IDeserializer Deserializer = new DeserializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).Build();

		private static ConfigSync? ConfigSync;

		private static CustomSyncedValue<string>? SyncedYamlBundle;

		private static FileSystemWatcher? Watcher;

		private static DateTime PendingDiskReloadTime = DateTime.MaxValue;

		private static DateTime PendingSyncedApplyTime = DateTime.MaxValue;

		private static DateTime PendingTextureRefreshTime = DateTime.MaxValue;

		private static bool DiskReloadPending;

		private static bool SyncedApplyPending;

		private static bool TextureRefreshPending;

		private static bool GameDataRefreshPending;

		private static bool SuppressSyncedApply;

		private static bool RemoteBundleReady;

		private static bool WatcherResetPending;

		private static DefinitionSnapshot ActiveSnapshot = new DefinitionSnapshot();

		private static readonly Dictionary<string, Vector3> EquipmentVisualScales = new Dictionary<string, Vector3>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, GameObject[]> RandomHairPrefabsByCreature = new Dictionary<string, GameObject[]>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, CreatureAppearanceRuntimeState> AppearanceByCreature = new Dictionary<string, CreatureAppearanceRuntimeState>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, CreatureAppearanceRuntimeState> InheritedAppearanceByClone = new Dictionary<string, CreatureAppearanceRuntimeState>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, CreatureAppearanceRuntimeState> AppearanceByRagdollPrefab = new Dictionary<string, CreatureAppearanceRuntimeState>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, GameObject> ManagedRagdollPrefabs = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, GameObject> RagdollCloneSources = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, Vector3> OriginalRagdollScales = new Dictionary<string, Vector3>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, RagdollScaleRuntimeState> RagdollScalesByPrefab = new Dictionary<string, RagdollScaleRuntimeState>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, RagdollScaleRuntimeState> InheritedRagdollScales = new Dictionary<string, RagdollScaleRuntimeState>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, RagdollTextureRuntimeState[]> RagdollTexturesByPrefab = new Dictionary<string, RagdollTextureRuntimeState[]>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, RagdollTextureRuntimeState[]> InheritedRagdollTextures = new Dictionary<string, RagdollTextureRuntimeState[]>(StringComparer.OrdinalIgnoreCase);

		private static readonly HashSet<int> AppliedRagdollTextureVisuals = new HashSet<int>();

		private static readonly HashSet<string> SuccessfullyAppliedDefinitionTargets = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<(int RendererId, int MaterialIndex), TextureMaterialOverride> TextureMaterialOverrides = new Dictionary<(int, int), TextureMaterialOverride>();

		private static readonly MaterialPropertyBlock RagdollTexturePropertyBlock = new MaterialPropertyBlock();

		private static bool GameDataReady;

		private static bool ActiveDefinitionsApplied;

		private static bool LoadedHumanoidsRefreshedForCurrentGameData;

		private static bool ReferenceCaptureAttemptedForCurrentGameData;

		private static ReferenceFileSnapshot? CapturedReferenceFiles;

		private static int PendingGameDataRefreshFrame = int.MaxValue;

		internal static string ConfigDirectoryPath => Path.Combine(Paths.ConfigPath, "CreatureManager");

		internal static string CacheDirectoryPath => Path.Combine(ConfigDirectoryPath, "cache");

		internal static string TextureDirectoryPath => Path.Combine(ConfigDirectoryPath, "textures");

		internal static string FactionConfigurationPath => Path.Combine(ConfigDirectoryPath, "factions.yml");

		internal static string LevelConfigurationPath => Path.Combine(ConfigDirectoryPath, "levels.yml");

		internal static string KarmaConfigurationPath => Path.Combine(ConfigDirectoryPath, "karma.yml");

		internal static string AiConfigurationPath => Path.Combine(ConfigDirectoryPath, "ai.yml");

		internal static string AiReferenceConfigurationPath => Path.Combine(ConfigDirectoryPath, "ai.reference.yml");

		internal static string AttackConfigurationPath => Path.Combine(ConfigDirectoryPath, "attacks.yml");

		internal static string AttackSampleConfigurationPath => Path.Combine(ConfigDirectoryPath, "attacks.sample.yml");

		internal static string AttackReferenceConfigurationPath => Path.Combine(ConfigDirectoryPath, "attacks.reference.yml");

		internal static string ProjectileConfigurationPath => Path.Combine(ConfigDirectoryPath, "projectile.yml");

		internal static string ProjectileReferenceConfigurationPath => Path.Combine(ConfigDirectoryPath, "projectile.reference.yml");

		internal static string CreatureLoadoutReferenceConfigurationPath => Path.Combine(ConfigDirectoryPath, "creatureLoadout.reference.txt");

		internal static string TextureReferenceConfigurationPath => Path.Combine(ConfigDirectoryPath, "textures.reference.txt");

		internal static string LevelVisualReferenceConfigurationPath => Path.Combine(ConfigDirectoryPath, "levelVisual.reference.yml");

		internal static string CreatureConfigurationPath => Path.Combine(ConfigDirectoryPath, "creatures.yml");

		internal static string CreatureSampleConfigurationPath => Path.Combine(ConfigDirectoryPath, "creatures.sample.yml");

		internal static string ReferenceConfigurationPath => Path.Combine(ConfigDirectoryPath, "creatures.reference.yml");

		internal static string FullScaffoldConfigurationPath => Path.Combine(ConfigDirectoryPath, "creatures.full.yml");

		private static string ReferenceStatePath => Path.Combine(CacheDirectoryPath, ".reference-state.txt");

		internal static void Initialize(ConfigSync configSync)
		{
			ConfigSync = configSync;
			ActiveDefinitionsApplied = false;
			RemoteBundleReady = false;
			LoadedHumanoidsRefreshedForCurrentGameData = false;
			SyncedYamlBundle = new CustomSyncedValue<string>(configSync, "YamlBundle", "", 100);
			SyncedYamlBundle.ValueChanged += RequestSyncedYamlApply;
			configSync.SourceOfTruthChanged += OnSourceOfTruthChanged;
			EnsureDirectoriesAndDefaultFiles();
			if (configSync.IsSourceOfTruth)
			{
				LoadDefinitionsFromDisk(assignSyncedValue: true);
			}
			else
			{
				RequestSyncedYamlApply();
			}
			SetupWatcher();
			CreatureConsoleCommands.Register();
		}

		internal static void Dispose()
		{
			NotifyGameDataUnavailable();
			if (SyncedYamlBundle != null)
			{
				SyncedYamlBundle.ValueChanged -= RequestSyncedYamlApply;
				SyncedYamlBundle = null;
			}
			if (ConfigSync != null)
			{
				ConfigSync.SourceOfTruthChanged -= OnSourceOfTruthChanged;
				ConfigSync = null;
			}
			DiskReloadPending = false;
			SyncedApplyPending = false;
			TextureRefreshPending = false;
			GameDataRefreshPending = false;
			PendingDiskReloadTime = DateTime.MaxValue;
			PendingSyncedApplyTime = DateTime.MaxValue;
			PendingTextureRefreshTime = DateTime.MaxValue;
			PendingGameDataRefreshFrame = int.MaxValue;
			SuppressSyncedApply = false;
			RemoteBundleReady = false;
			WatcherResetPending = false;
			ReferenceCaptureAttemptedForCurrentGameData = false;
			CapturedReferenceFiles = null;
			Watcher?.Dispose();
			Watcher = null;
			lock (Sync)
			{
				ActiveSnapshot = new DefinitionSnapshot();
			}
			CreatureTextureRegistry.Dispose();
		}

		internal static void RequestConfigurationReload()
		{
			ConfigSync? configSync = ConfigSync;
			if (configSync == null || configSync.IsSourceOfTruth)
			{
				DiskReloadPending = true;
				PendingDiskReloadTime = DateTime.UtcNow.AddTicks(2500000L);
			}
		}

		internal static void Update()
		{
			if (!DiskReloadPending && !SyncedApplyPending && !TextureRefreshPending && !GameDataRefreshPending)
			{
				return;
			}
			if (GameDataRefreshPending && Time.frameCount >= PendingGameDataRefreshFrame)
			{
				CompletePendingGameDataRefresh();
			}
			DateTime utcNow = DateTime.UtcNow;
			if (DiskReloadPending && utcNow >= PendingDiskReloadTime)
			{
				DiskReloadPending = false;
				PendingDiskReloadTime = DateTime.MaxValue;
				TextureRefreshPending = false;
				PendingTextureRefreshTime = DateTime.MaxValue;
				ConfigSync? configSync = ConfigSync;
				if (configSync == null || configSync.IsSourceOfTruth)
				{
					LoadDefinitionsFromDisk(assignSyncedValue: true);
					if (WatcherResetPending)
					{
						WatcherResetPending = false;
						SetupWatcher();
					}
				}
			}
			if (SyncedApplyPending && utcNow >= PendingSyncedApplyTime)
			{
				SyncedApplyPending = false;
				PendingSyncedApplyTime = DateTime.MaxValue;
				TextureRefreshPending = false;
				PendingTextureRefreshTime = DateTime.MaxValue;
				ApplySyncedYaml();
				if (WatcherResetPending)
				{
					WatcherResetPending = false;
					SetupWatcher();
				}
			}
			if (TextureRefreshPending && !DiskReloadPending && !SyncedApplyPending && utcNow >= PendingTextureRefreshTime)
			{
				TextureRefreshPending = false;
				PendingTextureRefreshTime = DateTime.MaxValue;
				ApplyDefinitionsToGameData();
				if (WatcherResetPending)
				{
					WatcherResetPending = false;
					SetupWatcher();
				}
			}
		}

		internal static void NotifyGameDataAvailable(bool objectDbFinalized = false)
		{
			if (HasGameDataInstances())
			{
				GameDataReady = true;
				CreatureConsoleCommands.InvalidateSpawnAutocompleteOptions();
				CreatureAssetOwnerCatalog.InvalidateMappings();
				GameDataRefreshPending = true;
				PendingGameDataRefreshFrame = (objectDbFinalized ? Time.frameCount : Math.Min(PendingGameDataRefreshFrame, Time.frameCount + 1));
				if (objectDbFinalized)
				{
					CompletePendingGameDataRefresh();
				}
			}
		}

		private static void CompletePendingGameDataRefresh()
		{
			if (GameDataRefreshPending && HasGameDataInstances())
			{
				GameDataRefreshPending = false;
				PendingGameDataRefreshFrame = int.MaxValue;
				CaptureReferenceConfigurationFilesIfNeeded();
				WriteCapturedReferenceConfigurationFilesIfNeeded();
				ConfigSync? configSync = ConfigSync;
				if (configSync != null && !configSync.IsSourceOfTruth && !RemoteBundleReady)
				{
					RequestSyncedYamlApply();
				}
				ApplyDefinitionsToGameData();
			}
		}

		internal static void NotifyGameDataUnavailable()
		{
			CreaturePrefabBaseline.RestoreAllAndClear();
			DisposeTextureOverrides();
			EquipmentVisualScales.Clear();
			RandomHairPrefabsByCreature.Clear();
			AppearanceByCreature.Clear();
			InheritedAppearanceByClone.Clear();
			AppearanceByRagdollPrefab.Clear();
			ManagedRagdollPrefabs.Clear();
			RagdollCloneSources.Clear();
			OriginalRagdollScales.Clear();
			RagdollScalesByPrefab.Clear();
			InheritedRagdollScales.Clear();
			RagdollTexturesByPrefab.Clear();
			InheritedRagdollTextures.Clear();
			AppliedRagdollTextureVisuals.Clear();
			SuccessfullyAppliedDefinitionTargets.Clear();
			ActiveDefinitionsApplied = false;
			CreaturePrefabRegistry.ResetOwnedClones();
			CreatureConsoleCommands.InvalidateSpawnAutocompleteOptions();
			CreatureAssetOwnerCatalog.InvalidateMappings();
			GameDataReady = false;
			LoadedHumanoidsRefreshedForCurrentGameData = false;
			ReferenceCaptureAttemptedForCurrentGameData = false;
			CapturedReferenceFiles = null;
			RemoteBundleReady = false;
			SyncedApplyPending = false;
			GameDataRefreshPending = false;
			PendingSyncedApplyTime = DateTime.MaxValue;
			PendingGameDataRefreshFrame = int.MaxValue;
			TextureRefreshPending = false;
			PendingTextureRefreshTime = DateTime.MaxValue;
		}

		internal static void LoadDefinitionsFromDisk(bool assignSyncedValue)
		{
			if (GameDataRefreshPending)
			{
				RequestConfigurationReload();
				return;
			}
			EnsureDirectoriesAndDefaultFiles();
			if (!TryBuildDiskSnapshot(out DefinitionSnapshot snapshot) || !CreatureKarmaManager.TryParseYaml(snapshot.KarmaYaml, KarmaConfigurationPath, out CreatureKarmaManager.ParsedConfiguration parsed))
			{
				CreatureManagerPlugin.Log.LogWarning((object)"Keeping the complete last-known-good CreatureManager configuration because at least one local YAML domain is invalid.");
				return;
			}
			string serialized = null;
			if (assignSyncedValue)
			{
				if (!TrySerializeAndVerifyBundle(snapshot, out serialized, out DefinitionSnapshot verified))
				{
					CreatureManagerPlugin.Log.LogWarning((object)"Keeping the complete last-known-good CreatureManager configuration because the synchronized YAML bundle did not round-trip.");
					return;
				}
				snapshot = verified;
				if (!CreatureKarmaManager.TryParseYaml(snapshot.KarmaYaml, "local synchronized YAML bundle", out parsed))
				{
					CreatureManagerPlugin.Log.LogWarning((object)"Keeping the complete last-known-good CreatureManager configuration because Karma did not survive the synchronized YAML bundle round-trip.");
					return;
				}
			}
			if (!TryBeginDefinitionClonePreparation(snapshot, "local YAML bundle", out var preparationStarted))
			{
				CreatureManagerPlugin.Log.LogWarning((object)"Keeping the complete last-known-good CreatureManager configuration because its clones could not be prepared.");
				return;
			}
			bool keepPreparedClones = false;
			string text = null;
			bool flag = false;
			try
			{
				if (serialized != null)
				{
					SuppressSyncedApply = true;
					try
					{
						if (SyncedYamlBundle == null)
						{
							CreatureManagerPlugin.Log.LogError((object)"Cannot publish the synchronized YAML bundle because ServerSync is not initialized.");
							return;
						}
						text = SyncedYamlBundle.Value;
						SyncedYamlBundle.AssignLocalValue(serialized);
						flag = true;
					}
					catch (Exception ex)
					{
						CreatureManagerPlugin.Log.LogError((object)("Failed to publish the synchronized YAML bundle; keeping the complete last-known-good configuration: " + ex.Message));
						return;
					}
					finally
					{
						SuppressSyncedApply = false;
					}
					SyncedApplyPending = false;
					PendingSyncedApplyTime = DateTime.MaxValue;
				}
				if (!TrySetActiveDefinitions(snapshot, "local YAML bundle", preparationStarted))
				{
					if (!flag || SyncedYamlBundle == null || text == null)
					{
						return;
					}
					SuppressSyncedApply = true;
					try
					{
						SyncedYamlBundle.AssignLocalValue(text);
						return;
					}
					catch (Exception ex2)
					{
						CreatureManagerPlugin.Log.LogError((object)("Failed to restore the previous synchronized YAML bundle after the local definition transaction was rejected: " + ex2.Message));
						return;
					}
					finally
					{
						SuppressSyncedApply = false;
					}
				}
				CreatureKarmaManager.CommitParsedConfiguration(parsed);
				keepPreparedClones = true;
			}
			finally
			{
				EndDefinitionClonePreparation(preparationStarted, keepPreparedClones);
			}
		}

		internal static bool TryWriteReferenceConfigurationFile(out string path, out string error)
		{
			path = ReferenceConfigurationPath;
			return TryWriteGeneratedFile(path, CreatureReferenceWriter.BuildReferenceYaml, "creature reference YAML", out error);
		}

		internal static bool TryWriteFullScaffoldConfigurationFile(out string path, out string error)
		{
			path = FullScaffoldConfigurationPath;
			return TryWriteGeneratedFile(path, CreatureReferenceWriter.BuildFullScaffoldYaml, "creature full scaffold YAML", out error);
		}

		internal static bool TryWriteAttackReferenceConfigurationFile(out string path, out string error)
		{
			path = AttackReferenceConfigurationPath;
			return TryWriteGeneratedFile(path, CreatureReferenceWriter.BuildAttackReferenceYaml, "attack reference YAML", out error);
		}

		internal static bool TryWriteAiReferenceConfigurationFile(out string path, out string error)
		{
			path = AiReferenceConfigurationPath;
			return TryWriteGeneratedFile(path, CreatureReferenceWriter.BuildAiReferenceYaml, "AI reference YAML", out error);
		}

		internal static bool TryWriteTextureReferenceConfigurationFile(out string path, out string error)
		{
			path = TextureReferenceConfigurationPath;
			return TryWriteGeneratedFile(path, CreatureTextureRegistry.BuildTextureReferenceText, "texture reference", out error);
		}

		internal static bool TryWriteLevelVisualReferenceConfigurationFile(out string path, out string error)
		{
			path = LevelVisualReferenceConfigurationPath;
			return TryWriteGeneratedFile(path, CreatureReferenceWriter.BuildLevelVisualReferenceYaml, "level visual reference YAML", out error);
		}

		internal static bool TryWriteCreatureLoadoutReferenceConfigurationFile(out string path, out string error)
		{
			path = CreatureLoadoutReferenceConfigurationPath;
			return TryWriteGeneratedFile(path, CreatureReferenceWriter.BuildCreatureLoadoutReferenceText, "creature loadout reference", out error);
		}

		internal static bool TryWriteProjectileReferenceConfigurationFile(out string path, out string error)
		{
			path = ProjectileReferenceConfigurationPath;
			return TryWriteGeneratedFile(path, CreatureReferenceWriter.BuildProjectileReferenceYaml, "projectile reference YAML", out error);
		}

		private static bool TryWriteGeneratedFile(string path, Func<string> buildContent, string label, out string error)
		{
			error = "";
			if (!IsGameDataReady())
			{
				error = "Creature game data is not ready yet.";
				return false;
			}
			try
			{
				File.WriteAllText(path, buildContent());
				CreatureManagerPlugin.Log.LogInfo((object)("Wrote " + label + " to " + path + "."));
				return true;
			}
			catch (Exception ex)
			{
				error = "Failed to write " + label + ": " + ex.Message;
				CreatureManagerPlugin.Log.LogError((object)(error + " Path: " + path));
				return false;
			}
		}

		private static void CaptureReferenceConfigurationFilesIfNeeded()
		{
			if (ReferenceCaptureAttemptedForCurrentGameData || !IsGameDataReady())
			{
				return;
			}
			ReferenceCaptureAttemptedForCurrentGameData = true;
			ConfigSync? configSync = ConfigSync;
			if (configSync != null && !configSync.IsSourceOfTruth)
			{
				return;
			}
			try
			{
				CreatureAssetOwnerCatalog.RefreshMappings();
				string text = CreatureReferenceWriter.BuildReferenceYaml();
				string text2 = CreatureReferenceWriter.BuildAiReferenceYaml();
				string text3 = CreatureReferenceWriter.BuildAttackReferenceYaml();
				string text4 = CreatureReferenceWriter.BuildCreatureLoadoutReferenceText();
				string text5 = CreatureReferenceWriter.BuildProjectileReferenceYaml();
				string text6 = CreatureTextureRegistry.BuildTextureReferenceText();
				if (!(text == "[]\n") || !(text2 == "[]\n") || !(text3 == "[]\n") || !(text4 == "[]\n") || !(text5 == "[]\n") || !(text6 == "[]\n"))
				{
					string signature = ComputeStableSignature("2026-07-21-ragdoll-visual-v2\n" + text + "\n---ai---\n" + text2 + "\n---attacks---\n" + text3 + "\n---loadout---\n" + text4 + "\n---projectile---\n" + text5 + "\n---textures---\n" + text6);
					CapturedReferenceFiles = new ReferenceFileSnapshot(text, text2, text3, text4, text5, text6, signature);
				}
			}
			catch (Exception ex)
			{
				CreatureManagerPlugin.Log.LogWarning((object)("Failed to capture pristine CreatureManager reference data; automatic reference generation is disabled until game data reloads: " + ex.Message));
			}
		}

		private static void WriteCapturedReferenceConfigurationFilesIfNeeded()
		{
			ReferenceFileSnapshot capturedReferenceFiles = CapturedReferenceFiles;
			if (capturedReferenceFiles == null)
			{
				return;
			}
			ConfigSync? configSync = ConfigSync;
			if ((configSync != null && !configSync.IsSourceOfTruth) || ReferenceFilesAreCurrent(capturedReferenceFiles.Signature))
			{
				return;
			}
			try
			{
				File.WriteAllText(ReferenceConfigurationPath, capturedReferenceFiles.CreatureYaml);
				File.WriteAllText(AiReferenceConfigurationPath, capturedReferenceFiles.AiYaml);
				File.WriteAllText(AttackReferenceConfigurationPath, capturedReferenceFiles.AttackYaml);
				File.WriteAllText(CreatureLoadoutReferenceConfigurationPath, capturedReferenceFiles.CreatureLoadout);
				File.WriteAllText(ProjectileReferenceConfigurationPath, capturedReferenceFiles.ProjectileYaml);
				File.WriteAllText(TextureReferenceConfigurationPath, capturedReferenceFiles.TextureReference);
				RecordReferenceSignature(capturedReferenceFiles.Signature);
				CreatureManagerPlugin.Log.LogInfo((object)("Updated reference files at " + ReferenceConfigurationPath + ", " + AiReferenceConfigurationPath + ", " + AttackReferenceConfigurationPath + ", " + CreatureLoadoutReferenceConfigurationPath + ", " + ProjectileReferenceConfigurationPath + ", and " + TextureReferenceConfigurationPath + "."));
			}
			catch (Exception ex)
			{
				CreatureManagerPlugin.Log.LogWarning((object)("Failed to update CreatureManager reference files: " + ex.Message));
			}
		}

		internal static bool IsGameDataReady()
		{
			if (!GameDataReady)
			{
				return HasGameDataInstances();
			}
			return true;
		}

		internal static bool IsSynchronizedConfigurationReady()
		{
			if (ActiveDefinitionsApplied && !GameDataRefreshPending)
			{
				ConfigSync? configSync = ConfigSync;
				if (configSync == null || !configSync.IsSourceOfTruth || DiskReloadPending)
				{
					ConfigSync? configSync2 = ConfigSync;
					if (configSync2 != null && !configSync2.IsSourceOfTruth && RemoteBundleReady)
					{
						return !SyncedApplyPending;
					}
					return false;
				}
				return true;
			}
			return false;
		}

		private static bool HasGameDataInstances()
		{
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				return (Object)(object)ObjectDB.instance != (Object)null;
			}
			return false;
		}

		private static bool ReferenceFilesAreCurrent(string signature)
		{
			if (!File.Exists(ReferenceConfigurationPath) || !File.Exists(AiReferenceConfigurationPath) || !File.Exists(AttackReferenceConfigurationPath) || !File.Exists(CreatureLoadoutReferenceConfigurationPath) || !File.Exists(ProjectileReferenceConfigurationPath) || !File.Exists(TextureReferenceConfigurationPath) || !File.Exists(ReferenceStatePath))
			{
				return false;
			}
			try
			{
				string[] array = File.ReadAllLines(ReferenceStatePath);
				return array.Length >= 2 && string.Equals(array[0], "2026-07-21-ragdoll-visual-v2", StringComparison.Ordinal) && string.Equals(array[1], signature, StringComparison.Ordinal);
			}
			catch (Exception ex)
			{
				CreatureManagerPlugin.Log.LogWarning((object)("Failed to read reference state '" + ReferenceStatePath + "': " + ex.Message));
				return false;
			}
		}

		private static void RecordReferenceSignature(string signature)
		{
			try
			{
				Directory.CreateDirectory(CacheDirectoryPath);
				File.WriteAllLines(ReferenceStatePath, new string[2] { "2026-07-21-ragdoll-visual-v2", signature });
			}
			catch (Exception ex)
			{
				CreatureManagerPlugin.Log.LogWarning((object)("Failed to write reference state '" + ReferenceStatePath + "': " + ex.Message));
			}
		}

		private static string ComputeStableSignature(string value)
		{
			ulong num = 14695981039346656037uL;
			foreach (char c in value)
			{
				num ^= c;
				num *= 1099511628211L;
			}
			return num.ToString("X16", CultureInfo.InvariantCulture);
		}

		private static void OnSourceOfTruthChanged(bool isSourceOfTruth)
		{
			if (isSourceOfTruth)
			{
				RemoteBundleReady = false;
				SyncedApplyPending = false;
				PendingSyncedApplyTime = DateTime.MaxValue;
				WriteCapturedReferenceConfigurationFilesIfNeeded();
				LoadDefinitionsFromDisk(assignSyncedValue: true);
				return;
			}
			DiskReloadPending = false;
			PendingDiskReloadTime = DateTime.MaxValue;
			RemoteBundleReady = false;
			if (WatcherResetPending)
			{
				TextureRefreshPending = true;
				PendingTextureRefreshTime = DateTime.UtcNow;
			}
			RequestSyncedYamlApply();
		}

		private static void ApplySyncedYaml()
		{
			if (SyncedYamlBundle == null)
			{
				return;
			}
			if (GameDataRefreshPending)
			{
				RequestSyncedYamlApply();
				return;
			}
			ConfigSync? configSync = ConfigSync;
			string text = ((configSync != null && configSync.IsSourceOfTruth) ? "local synchronized YAML bundle" : "server synchronized YAML bundle");
			if (!TryDeserializeBundle(SyncedYamlBundle.Value, text, out DefinitionSnapshot snapshot) || !CreatureKarmaManager.TryParseYaml(snapshot.KarmaYaml, text, out CreatureKarmaManager.ParsedConfiguration parsed))
			{
				CreatureManagerPlugin.Log.LogWarning((object)("Keeping the complete last-known-good CreatureManager configuration because " + text + " is invalid."));
				return;
			}
			if (!TryBeginDefinitionClonePreparation(snapshot, text, out var preparationStarted))
			{
				CreatureManagerPlugin.Log.LogWarning((object)("Keeping the complete last-known-good CreatureManager configuration because the clones from " + text + " could not be prepared."));
				return;
			}
			bool remoteBundleReady = RemoteBundleReady;
			ConfigSync? configSync2 = ConfigSync;
			RemoteBundleReady = configSync2 != null && !configSync2.IsSourceOfTruth;
			bool keepPreparedClones = false;
			try
			{
				if (!TrySetActiveDefinitions(snapshot, text, preparationStarted))
				{
					RemoteBundleReady = remoteBundleReady;
					return;
				}
				CreatureKarmaManager.CommitParsedConfiguration(parsed);
				keepPreparedClones = true;
			}
			finally
			{
				EndDefinitionClonePreparation(preparationStarted, keepPreparedClones);
			}
		}

		private static bool TryBuildDiskSnapshot(out DefinitionSnapshot snapshot)
		{
			snapshot = new DefinitionSnapshot();
			bool num = TryLoadOverrideFiles("factions", (TryReadYaml<FactionDefinition>)CreatureYaml.TryReadDefinitions, out snapshot.Factions);
			bool flag = TryLoadLevelDefinitions(out snapshot.Levels);
			bool flag2 = TryLoadOverrideFiles("ai", (TryReadYaml<AiDefinition>)CreatureYaml.TryReadDefinitions, out snapshot.Ai);
			bool flag3 = TryLoadOverrideFiles("attacks", (TryReadYaml<AttackDefinition>)CreatureYaml.TryReadDefinitions, out snapshot.Attacks);
			bool flag4 = TryLoadOverrideFiles("projectile", (TryReadYaml<ProjectileDefinition>)CreatureYaml.TryReadDefinitions, out snapshot.Projectiles);
			RemoveProjectileReferenceMetadata(snapshot.Projectiles);
			bool flag5 = TryLoadOverrideFiles("creatures", (TryReadYaml<CreatureDefinition>)CreatureYaml.TryReadDefinitions, out snapshot.Creatures);
			bool flag6 = TryReadTextFile(KarmaConfigurationPath, "Karma", out snapshot.KarmaYaml);
			return num && flag && flag2 && flag3 && flag4 && flag5 && flag6;
		}

		private static bool TryReadTextFile(string path, string domain, out string text)
		{
			text = "";
			try
			{
				if (!File.Exists(path))
				{
					CreatureManagerPlugin.Log.LogError((object)(domain + " configuration was not found at " + path + "."));
					return false;
				}
				text = File.ReadAllText(path);
				return true;
			}
			catch (Exception ex)
			{
				CreatureManagerPlugin.Log.LogError((object)("Failed to read " + domain + " configuration from " + path + ": " + ex.Message));
				return false;
			}
		}

		private static bool TrySerializeAndVerifyBundle(DefinitionSnapshot snapshot, out string serialized, out DefinitionSnapshot verified)
		{
			serialized = "";
			verified = new DefinitionSnapshot();
			try
			{
				SyncedYamlBundleData graph = new SyncedYamlBundleData
				{
					Version = 4,
					Factions = snapshot.Factions,
					Levels = snapshot.Levels,
					Ai = snapshot.Ai,
					Attacks = snapshot.Attacks,
					Projectiles = snapshot.Projectiles,
					Creatures = snapshot.Creatures,
					Karma = snapshot.KarmaYaml
				};
				serialized = Serializer.Serialize(graph);
			}
			catch (Exception ex)
			{
				CreatureManagerPlugin.Log.LogError((object)("Failed to serialize synchronized YAML bundle: " + ex.Message));
				return false;
			}
			return TryDeserializeBundle(serialized, "local synchronized YAML bundle round-trip", out verified);
		}

		private static bool TryDeserializeBundle(string yaml, string source, out DefinitionSnapshot snapshot)
		{
			snapshot = new DefinitionSnapshot();
			if (string.IsNullOrWhiteSpace(yaml))
			{
				CreatureManagerPlugin.Log.LogError((object)("Failed to read " + source + ": the bundle is empty."));
				return false;
			}
			try
			{
				CreatureYaml.ValidateUniqueMappingKeysInDocument(yaml, source);
				SyncedYamlBundleData syncedYamlBundleData = Deserializer.Deserialize<SyncedYamlBundleData>(yaml);
				if (syncedYamlBundleData == null || syncedYamlBundleData.Version != 4)
				{
					string arg = ((syncedYamlBundleData == null) ? "missing" : syncedYamlBundleData.Version.ToString(CultureInfo.InvariantCulture));
					CreatureManagerPlugin.Log.LogError((object)$"Failed to read {source}: expected bundle version {4} but got {arg}.");
					return false;
				}
				if (syncedYamlBundleData.Factions == null || syncedYamlBundleData.Levels == null || syncedYamlBundleData.Ai == null || syncedYamlBundleData.Attacks == null || syncedYamlBundleData.Projectiles == null || syncedYamlBundleData.Creatures == null || syncedYamlBundleData.Karma == null)
				{
					CreatureManagerPlugin.Log.LogError((object)("Failed to read " + source + ": all seven configuration domains must be present."));
					return false;
				}
				if (!CreatureYaml.ValidateDefinitions(syncedYamlBundleData.Factions, source + ".factions") || !CreatureYaml.ValidateDefinitions(syncedYamlBundleData.Levels, source + ".levels") || !CreatureYaml.ValidateDefinitions(syncedYamlBundleData.Ai, source + ".ai") || !CreatureYaml.ValidateDefinitions(syncedYamlBundleData.Attacks, source + ".attacks") || !CreatureYaml.ValidateDefinitions(syncedYamlBundleData.Projectiles, source + ".projectile") || !CreatureYaml.ValidateDefinitions(syncedYamlBundleData.Creatures, source + ".creatures"))
				{
					return false;
				}
				snapshot.Factions = syncedYamlBundleData.Factions;
				snapshot.Levels = syncedYamlBundleData.Levels;
				snapshot.Ai = syncedYamlBundleData.Ai;
				snapshot.Attacks = syncedYamlBundleData.Attacks;
				RemoveProjectileReferenceMetadata(syncedYamlBundleData.Projectiles);
				snapshot.Projectiles = syncedYamlBundleData.Projecti