Decompiled source of DropNSpawn v1.0.4

DropNSpawn.dll

Decompiled 11 hours ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Data;
using ExpandWorldData;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using ServerSync;
using Service;
using TMPro;
using UnityEngine;
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.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("DropNSpawn")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("sighsorry")]
[assembly: AssemblyProduct("DropNSpawn")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")]
[assembly: AssemblyFileVersion("1.0.4")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.4.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class ExtensionMarkerAttribute : Attribute
	{
		public ExtensionMarkerAttribute(string name)
		{
		}
	}
}
namespace LocalizationManager
{
	[PublicAPI]
	public class Localizer
	{
		private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors;

		private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts;

		private static readonly ConditionalWeakTable<Localization, string> localizationLanguage;

		private static readonly List<WeakReference<Localization>> localizationObjects;

		private static BaseUnityPlugin? _plugin;

		private static readonly List<string> fileExtensions;

		private static BaseUnityPlugin plugin
		{
			get
			{
				//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b2: 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;
			}
		}

		public static event Action? OnLocalizationComplete;

		private static void UpdatePlaceholderText(Localization localization, string key)
		{
			localizationLanguage.TryGetValue(localization, out string value);
			string text = loadedTexts[value][key];
			if (PlaceholderProcessors.TryGetValue(key, out Dictionary<string, Func<string>> value2))
			{
				text = value2.Aggregate(text, (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value()));
			}
			localization.AddWord(key, text);
		}

		public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, Func<T, string>? convertConfigValue = null) where T : notnull
		{
			string key2 = key;
			string placeholder2 = placeholder;
			Func<T, string> convertConfigValue2 = convertConfigValue;
			ConfigEntry<T> config2 = config;
			if (convertConfigValue2 == null)
			{
				convertConfigValue2 = (T val) => val.ToString();
			}
			if (!PlaceholderProcessors.ContainsKey(key2))
			{
				PlaceholderProcessors[key2] = new Dictionary<string, Func<string>>();
			}
			config2.SettingChanged += delegate
			{
				UpdatePlaceholder();
			};
			if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage()))
			{
				UpdatePlaceholder();
			}
			void UpdatePlaceholder()
			{
				PlaceholderProcessors[key2][placeholder2] = () => convertConfigValue2(config2.Value);
				UpdatePlaceholderText(Localization.instance, key2);
			}
		}

		public static void AddText(string key, string text)
		{
			List<WeakReference<Localization>> list = new List<WeakReference<Localization>>();
			foreach (WeakReference<Localization> localizationObject in localizationObjects)
			{
				if (localizationObject.TryGetTarget(out var target))
				{
					Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)];
					if (!target.m_translations.ContainsKey(key))
					{
						dictionary[key] = text;
						target.AddWord(key, text);
					}
				}
				else
				{
					list.Add(localizationObject);
				}
			}
			foreach (WeakReference<Localization> item in list)
			{
				localizationObjects.Remove(item);
			}
		}

		public static void Load()
		{
			_ = plugin;
		}

		public static void LoadLocalizationLater(Localization __instance)
		{
			LoadLocalization(Localization.instance, __instance.GetSelectedLanguage());
		}

		public static void SafeCallLocalizeComplete()
		{
			Localizer.OnLocalizationComplete?.Invoke();
		}

		private static void LoadLocalization(Localization __instance, string language)
		{
			if (!localizationLanguage.Remove(__instance))
			{
				localizationObjects.Add(new WeakReference<Localization>(__instance));
			}
			localizationLanguage.Add(__instance, 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('.');
				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;
				}
			}
			loadedTexts[language] = dictionary2;
			foreach (KeyValuePair<string, string> item3 in dictionary2)
			{
				UpdatePlaceholderText(__instance, item3.Key);
			}
		}

		static Localizer()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected O, but got Unknown
			PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>();
			loadedTexts = new Dictionary<string, Dictionary<string, string>>();
			localizationLanguage = new ConditionalWeakTable<Localization, string>();
			localizationObjects = new List<WeakReference<Localization>>();
			fileExtensions = new List<string>(2) { ".json", ".yml" };
			Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager");
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalizationLater", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "SafeCallLocalizeComplete", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		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)
		{
			string resourceFileName2 = resourceFileName;
			using MemoryStream memoryStream = new MemoryStream();
			if ((object)containingAssembly == null)
			{
				containingAssembly = Assembly.GetCallingAssembly();
			}
			string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName2, StringComparison.Ordinal));
			if (text != null)
			{
				containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream);
			}
			return (memoryStream.Length == 0L) ? null : memoryStream.ToArray();
		}
	}
	public static class LocalizationManagerVersion
	{
		public const string Version = "1.4.1";
	}
}
namespace DropNSpawn
{
	internal sealed class CllcDefinition
	{
		[YamlMember(Order = 1)]
		public string? Infusion { get; set; }

		[YamlMember(Order = 2)]
		public string? ExtraEffect { get; set; }

		[YamlMember(Order = 3)]
		public string? BossAffix { get; set; }

		internal bool HasValues()
		{
			return HasAnyValues();
		}

		internal bool HasAnyValues()
		{
			return HasModifierValues();
		}

		internal bool HasModifierValues()
		{
			return !string.IsNullOrWhiteSpace(Infusion) || !string.IsNullOrWhiteSpace(ExtraEffect) || !string.IsNullOrWhiteSpace(BossAffix);
		}

		internal void Normalize()
		{
			Infusion = NormalizeOptionalString(Infusion);
			ExtraEffect = NormalizeOptionalString(ExtraEffect);
			BossAffix = NormalizeOptionalString(BossAffix);
		}

		private static string? NormalizeOptionalString(string? value)
		{
			string text = (value ?? "").Trim();
			return (text.Length > 0) ? text : null;
		}
	}
	internal static class CllcIntegration
	{
		private static readonly object Sync = new object();

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

		private static bool _resolved;

		private static Type? _apiType;

		private static MethodInfo? _getWorldLevelMethod;

		private static MethodInfo? _isEnabledMethod;

		private static MethodInfo? _isInfusionEnabledMethod;

		private static MethodInfo? _isExtraEffectEnabledMethod;

		private static MethodInfo? _isAffixEnabledMethod;

		private static MethodInfo? _getInfusionMethod;

		private static MethodInfo? _getExtraEffectMethod;

		private static MethodInfo? _getBossAffixMethod;

		private static MethodInfo? _setInfusionMethod;

		private static MethodInfo? _setExtraEffectMethod;

		private static MethodInfo? _setBossAffixMethod;

		private static Type? _infusionEnumType;

		private static Type? _extraEffectEnumType;

		private static Type? _bossAffixEnumType;

		private static readonly List<Character> CharacterBuffer = new List<Character>();

		internal static bool AreWorldLevelConditionsSatisfied(int? minWorldLevel, int? maxWorldLevel)
		{
			if (!minWorldLevel.HasValue && !maxWorldLevel.HasValue)
			{
				return true;
			}
			if (!TryGetWorldLevel(out var worldLevel))
			{
				WarnOnce("cllc-conditions-missing", "CLLC world-level conditions require CreatureLevelControl. The condition was treated as not satisfied.");
				return false;
			}
			if (minWorldLevel.HasValue && worldLevel < minWorldLevel.Value)
			{
				return false;
			}
			if (maxWorldLevel.HasValue && worldLevel > maxWorldLevel.Value)
			{
				return false;
			}
			return true;
		}

		internal static bool TryGetWorldLevel(out int worldLevel)
		{
			worldLevel = 0;
			lock (Sync)
			{
				if (!TryResolveApi())
				{
					return false;
				}
				try
				{
					if (_isEnabledMethod?.Invoke(null, null) is bool flag && !flag)
					{
						return false;
					}
					object obj = _getWorldLevelMethod?.Invoke(null, null);
					if (obj is int)
					{
						int num = (int)obj;
						if (true)
						{
							worldLevel = num;
							return true;
						}
					}
				}
				catch (Exception ex)
				{
					WarnOnce("cllc-world-level-error", "Failed to query CreatureLevelControl world level. " + ex.Message);
				}
				return false;
			}
		}

		internal static bool TryGetInfusion(Character? character, out string infusion)
		{
			return TryGetEnumValue(character, _isInfusionEnabledMethod, _getInfusionMethod, "infusion", out infusion);
		}

		internal static bool TryGetExtraEffect(Character? character, out string effect)
		{
			return TryGetEnumValue(character, _isExtraEffectEnabledMethod, _getExtraEffectMethod, "extraEffect", out effect);
		}

		internal static bool TryGetBossAffix(Character? character, out string bossAffix)
		{
			return TryGetEnumValue(character, _isAffixEnabledMethod, _getBossAffixMethod, "bossAffix", out bossAffix);
		}

		internal static void Apply(Character? character, CllcDefinition? definition, string context)
		{
			if ((Object)(object)character == (Object)null || definition == null || !definition.HasModifierValues())
			{
				return;
			}
			lock (Sync)
			{
				if (!TryResolveApi())
				{
					WarnOnce("cllc-missing:" + context, "Entry '" + context + "' uses cllc, but CreatureLevelControl is not loaded. The cllc block was ignored.");
					return;
				}
				ZNetView component = ((Component)character).GetComponent<ZNetView>();
				if (((component != null) ? component.GetZDO() : null) == null)
				{
					WarnOnce("cllc-zdo:" + context, "Entry '" + context + "' tried to apply cllc before the spawned character ZDO was ready. The cllc block was ignored.");
					return;
				}
				if (!string.IsNullOrWhiteSpace(definition.Infusion))
				{
					ApplyEnumEffect(character, definition.Infusion, context, _isInfusionEnabledMethod, _setInfusionMethod, _infusionEnumType, "infusion");
				}
				bool flag = !string.IsNullOrWhiteSpace(definition.BossAffix);
				bool flag2 = !string.IsNullOrWhiteSpace(definition.ExtraEffect);
				if (flag && flag2)
				{
					WarnOnce("cllc-effect-conflict:" + context, "Entry '" + context + "' configured both cllc.extraEffect and cllc.bossAffix. bossAffix takes priority because both use the same CreatureLevelControl effect slot.");
				}
				if (flag)
				{
					if (!character.IsBoss())
					{
						WarnOnce("cllc-boss-affix-nonboss:" + context, "Entry '" + context + "' configured cllc.bossAffix for a non-boss character. The boss affix was ignored.");
					}
					else
					{
						ApplyEnumEffect(character, definition.BossAffix, context, _isAffixEnabledMethod, _setBossAffixMethod, _bossAffixEnumType, "bossAffix");
					}
				}
				else if (flag2)
				{
					ApplyEnumEffect(character, definition.ExtraEffect, context, _isExtraEffectEnabledMethod, _setExtraEffectMethod, _extraEffectEnumType, "extraEffect");
				}
			}
		}

		internal static HashSet<int> CaptureNearbyCharacterIds(Vector3 point, float radius)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			CharacterBuffer.Clear();
			Character.GetCharactersInRange(point, radius, CharacterBuffer);
			return (from character in CharacterBuffer
				where (Object)(object)character != (Object)null
				select ((Object)character).GetInstanceID()).ToHashSet();
		}

		internal static Character? FindNewCharacter(Vector3 point, float radius, HashSet<int>? existingCharacterIds, GameObject? expectedPrefab = null)
		{
			//IL_000c: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			CharacterBuffer.Clear();
			Character.GetCharactersInRange(point, radius, CharacterBuffer);
			Character result = null;
			float num = float.MaxValue;
			foreach (Character item in CharacterBuffer)
			{
				if (!((Object)(object)item == (Object)null) && (existingCharacterIds == null || !existingCharacterIds.Contains(((Object)item).GetInstanceID())) && MatchesExpectedPrefab(item, expectedPrefab))
				{
					Vector3 val = ((Component)item).transform.position - point;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (!(sqrMagnitude >= num))
					{
						num = sqrMagnitude;
						result = item;
					}
				}
			}
			return result;
		}

		private static bool MatchesExpectedPrefab(Character character, GameObject? expectedPrefab)
		{
			if ((Object)(object)expectedPrefab == (Object)null)
			{
				return true;
			}
			string text = NormalizePrefabName(((Object)expectedPrefab).name);
			if (text.Length == 0)
			{
				return true;
			}
			string text2 = ResolveCharacterPrefabName(character);
			return text2.Length > 0 && string.Equals(text2, text, StringComparison.OrdinalIgnoreCase);
		}

		private static string ResolveCharacterPrefabName(Character character)
		{
			if ((Object)(object)character == (Object)null)
			{
				return "";
			}
			ZNetView component = ((Component)character).GetComponent<ZNetView>();
			ZDO val = ((component != null) ? component.GetZDO() : null);
			if (val != null && (Object)(object)ZNetScene.instance != (Object)null)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab(val.GetPrefab());
				if ((Object)(object)prefab != (Object)null)
				{
					return NormalizePrefabName(((Object)prefab).name);
				}
			}
			string prefabName = Utils.GetPrefabName(((Component)character).gameObject);
			if (!string.IsNullOrWhiteSpace(prefabName))
			{
				return NormalizePrefabName(prefabName);
			}
			return NormalizePrefabName(((Object)((Component)character).gameObject).name);
		}

		private static string NormalizePrefabName(string? rawName)
		{
			string text = (rawName ?? "").Trim();
			if (text.EndsWith("(Clone)", StringComparison.Ordinal))
			{
				string text2 = text;
				int length = "(Clone)".Length;
				text = text2.Substring(0, text2.Length - length).TrimEnd();
			}
			return text;
		}

		private static bool TryGetEnumValue(Character? character, MethodInfo? isFeatureEnabledMethod, MethodInfo? getValueMethod, string key, out string value)
		{
			value = "";
			if ((Object)(object)character == (Object)null)
			{
				return false;
			}
			lock (Sync)
			{
				if (!TryResolveApi())
				{
					WarnOnce("cllc-condition-missing:" + key, "CLLC " + key + " conditions require CreatureLevelControl. The condition was treated as not satisfied.");
					return false;
				}
				try
				{
					if (_isEnabledMethod?.Invoke(null, null) is bool flag && !flag)
					{
						WarnOnce("cllc-condition-disabled:" + key, "CLLC " + key + " conditions require CreatureLevelControl to be enabled. The condition was treated as not satisfied.");
						return false;
					}
					if (isFeatureEnabledMethod?.Invoke(null, null) is bool flag2 && !flag2)
					{
						WarnOnce("cllc-condition-feature-disabled:" + key, "CLLC " + key + " conditions require that CreatureLevelControl feature to be enabled. The condition was treated as not satisfied.");
						return false;
					}
					ZNetView component = ((Component)character).GetComponent<ZNetView>();
					if (((component != null) ? component.GetZDO() : null) == null)
					{
						return false;
					}
					if (getValueMethod == null)
					{
						WarnOnce("cllc-condition-method-missing:" + key, "CreatureLevelControl does not expose a usable API for reading cllc." + key + ". The condition was treated as not satisfied.");
						return false;
					}
					object obj = getValueMethod.Invoke(null, new object[1] { character });
					if (obj == null)
					{
						return false;
					}
					value = obj.ToString();
					return !string.IsNullOrWhiteSpace(value);
				}
				catch (Exception ex)
				{
					WarnOnce("cllc-condition-read-error:" + key, "Failed to query CreatureLevelControl " + key + " state. The condition was treated as not satisfied. " + ex.Message);
					return false;
				}
			}
		}

		private static void ApplyEnumEffect(Character character, string configuredValue, string context, MethodInfo? isEnabledMethod, MethodInfo? setMethod, Type? enumType, string key)
		{
			if (setMethod == null || enumType == null)
			{
				WarnOnce("cllc-method-missing:" + key, "CreatureLevelControl does not expose a usable API for cllc." + key + ". The value was ignored.");
				return;
			}
			if (isEnabledMethod?.Invoke(null, null) is bool flag && !flag)
			{
				WarnOnce("cllc-feature-disabled:" + key, "Entry '" + context + "' configured cllc." + key + ", but that CreatureLevelControl feature is disabled. The value was ignored.");
				return;
			}
			object obj;
			try
			{
				obj = Enum.Parse(enumType, configuredValue, ignoreCase: true);
			}
			catch
			{
				string text = string.Join(", ", Enum.GetNames(enumType));
				WarnOnce("cllc-invalid:" + key + ":" + configuredValue, "Entry '" + context + "' uses invalid cllc." + key + " value '" + configuredValue + "'. Supported values: " + text + ".");
				return;
			}
			try
			{
				setMethod.Invoke(null, new object[2] { character, obj });
			}
			catch (Exception ex)
			{
				WarnOnce("cllc-apply-error:" + key + ":" + context, "Entry '" + context + "' failed to apply cllc." + key + ". " + ex.Message);
			}
		}

		private static bool TryResolveApi()
		{
			if (_resolved)
			{
				return _apiType != null;
			}
			_resolved = true;
			_apiType = SafeTypeLookup.FindLoadedType("CreatureLevelControl.API", "CreatureLevelControl");
			if (_apiType == null)
			{
				return false;
			}
			BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public;
			_getWorldLevelMethod = _apiType.GetMethod("GetWorldLevel", bindingAttr, null, Type.EmptyTypes, null);
			_isEnabledMethod = _apiType.GetMethod("IsEnabled", bindingAttr, null, Type.EmptyTypes, null);
			_isInfusionEnabledMethod = _apiType.GetMethod("IsInfusionEnabled", bindingAttr, null, Type.EmptyTypes, null);
			_isExtraEffectEnabledMethod = _apiType.GetMethod("IsExtraEffectEnabled", bindingAttr, null, Type.EmptyTypes, null);
			_isAffixEnabledMethod = _apiType.GetMethod("IsAffixEnabled", bindingAttr, null, Type.EmptyTypes, null);
			_getInfusionMethod = _apiType.GetMethod("GetInfusionCreature", bindingAttr, null, new Type[1] { typeof(Character) }, null);
			_getExtraEffectMethod = _apiType.GetMethod("GetExtraEffectCreature", bindingAttr, null, new Type[1] { typeof(Character) }, null);
			_getBossAffixMethod = _apiType.GetMethod("GetAffixBoss", bindingAttr, null, new Type[1] { typeof(Character) }, null);
			MethodInfo[] methods = _apiType.GetMethods(bindingAttr);
			foreach (MethodInfo methodInfo in methods)
			{
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (methodInfo.Name == "SetInfusionCreature" && parameters.Length == 2 && parameters[0].ParameterType == typeof(Character))
				{
					_setInfusionMethod = methodInfo;
					_infusionEnumType = parameters[1].ParameterType;
				}
				else if (methodInfo.Name == "SetExtraEffectCreature" && parameters.Length == 2 && parameters[0].ParameterType == typeof(Character))
				{
					_setExtraEffectMethod = methodInfo;
					_extraEffectEnumType = parameters[1].ParameterType;
				}
				else if (methodInfo.Name == "SetAffixBoss" && parameters.Length == 2 && parameters[0].ParameterType == typeof(Character))
				{
					_setBossAffixMethod = methodInfo;
					_bossAffixEnumType = parameters[1].ParameterType;
				}
			}
			return _apiType != null;
		}

		private static void WarnOnce(string key, string message)
		{
			if (WarningCache.Add(key))
			{
				DropNSpawnPlugin.DropNSpawnLogger.LogWarning((object)message);
			}
		}
	}
	internal sealed class LocationConfigurationEntry
	{
		[YamlMember(Order = 1)]
		public string Prefab { get; set; } = "";


		[YamlMember(Order = 2)]
		public bool Enabled { get; set; } = true;


		[YamlMember(Order = 3)]
		public ConditionsDefinition? Conditions { get; set; }

		[YamlMember(Order = 4)]
		public LocationOfferingBowlDefinition? OfferingBowl { get; set; }

		[YamlMember(Order = 5)]
		public List<LocationItemStandDefinition>? ItemStands { get; set; }

		[YamlMember(Order = 6)]
		public List<LocationVegvisirDefinition>? Vegvisirs { get; set; }

		[YamlIgnore]
		public string RuleId { get; set; } = "";


		[YamlIgnore]
		public string? SourcePath { get; set; }
	}
	internal sealed class LocationReferenceEntry
	{
		[YamlMember(Order = 1)]
		public string Prefab { get; set; } = "";


		[YamlMember(Order = 2)]
		public LocationOfferingBowlDefinition? OfferingBowl { get; set; }

		[YamlMember(Order = 3)]
		public List<LocationItemStandDefinition>? ItemStands { get; set; }

		[YamlMember(Order = 4)]
		public List<LocationVegvisirDefinition>? Vegvisirs { get; set; }
	}
	internal sealed class LocationOfferingBowlDefinition
	{
		[YamlMember(Order = 1)]
		public string? Name { get; set; }

		[YamlMember(Order = 2)]
		public string? UseItemText { get; set; }

		[YamlMember(Order = 3)]
		public string? UsedAltarText { get; set; }

		[YamlMember(Order = 4)]
		public string? CantOfferText { get; set; }

		[YamlMember(Order = 5)]
		public string? WrongOfferText { get; set; }

		[YamlMember(Order = 6)]
		public string? IncompleteOfferText { get; set; }

		[YamlMember(Order = 7)]
		public string? BossItem { get; set; }

		[YamlMember(Order = 8)]
		public int? BossItems { get; set; }

		[YamlMember(Order = 9)]
		public string? BossPrefab { get; set; }

		[YamlMember(Order = 10)]
		public string? ItemPrefab { get; set; }

		[YamlMember(Order = 11)]
		public string? SetGlobalKey { get; set; }

		[YamlMember(Order = 12)]
		public bool? RenderSpawnAreaGizmos { get; set; }

		[YamlMember(Order = 13)]
		public bool? AlertOnSpawn { get; set; }

		[YamlMember(Order = 14)]
		public float? SpawnBossDelay { get; set; }

		[YamlMember(Order = 15)]
		public FloatRangeDefinition? SpawnBossDistance { get; set; }

		[YamlIgnore]
		public float? SpawnBossMaxDistance { get; set; }

		[YamlIgnore]
		public float? SpawnBossMinDistance { get; set; }

		[YamlMember(Order = 18)]
		public float? SpawnBossMaxYDistance { get; set; }

		[YamlMember(Order = 19)]
		public int? GetSolidHeightMargin { get; set; }

		[YamlMember(Order = 20)]
		public bool? EnableSolidHeightCheck { get; set; }

		[YamlMember(Order = 21)]
		public float? SpawnPointClearingRadius { get; set; }

		[YamlMember(Order = 22)]
		public float? SpawnYOffset { get; set; }

		[YamlMember(Order = 23)]
		public bool? UseItemStands { get; set; }

		[YamlMember(Order = 24)]
		public string? ItemStandPrefix { get; set; }

		[YamlMember(Order = 25)]
		public float? ItemStandMaxRange { get; set; }

		[YamlMember(Order = 26)]
		public float? RespawnMinutes { get; set; }

		[YamlMember(Order = 27)]
		public string? Data { get; set; }

		[YamlMember(Order = 28)]
		public Dictionary<string, string>? Fields { get; set; }

		[YamlMember(Order = 29)]
		public List<string>? Objects { get; set; }

		[YamlMember(Order = 30)]
		public string? CllcInfusion { get; set; }

		[YamlMember(Order = 31)]
		public string? CllcEffect { get; set; }

		[YamlMember(Order = 32)]
		public string? CllcBossEffect { get; set; }
	}
	internal sealed class LocationVegvisirDefinition
	{
		[YamlMember(Order = 1)]
		public string Path { get; set; } = "";


		[YamlMember(Order = 2)]
		public List<string>? ExpectedLocations { get; set; }

		[YamlMember(Order = 3)]
		public string? Name { get; set; }

		[YamlMember(Order = 4)]
		public string? UseText { get; set; }

		[YamlMember(Order = 5)]
		public string? HoverName { get; set; }

		[YamlMember(Order = 6)]
		public string? SetsGlobalKey { get; set; }

		[YamlMember(Order = 7)]
		public string? SetsPlayerKey { get; set; }

		[YamlMember(Order = 8)]
		public List<LocationVegvisirTargetDefinition>? Locations { get; set; }
	}
	internal sealed class LocationItemStandDefinition
	{
		[YamlMember(Order = 1)]
		public string? Path { get; set; }

		[YamlMember(Order = 2)]
		public string? Name { get; set; }

		[YamlMember(Order = 3)]
		public bool? CanBeRemoved { get; set; }

		[YamlMember(Order = 4)]
		public bool? AutoAttach { get; set; }

		[YamlMember(Order = 5)]
		public string? OrientationType { get; set; }

		[YamlMember(Order = 6)]
		public List<string>? SupportedTypes { get; set; }

		[YamlMember(Order = 7)]
		public List<string>? SupportedItems { get; set; }

		[YamlMember(Order = 8)]
		public List<string>? UnsupportedItems { get; set; }

		[YamlMember(Order = 9)]
		public float? PowerActivationDelay { get; set; }

		[YamlMember(Order = 10)]
		public string? GuardianPower { get; set; }
	}
	internal sealed class LocationVegvisirTargetDefinition
	{
		[YamlMember(Order = 1)]
		public string LocationName { get; set; } = "";


		[YamlMember(Order = 2)]
		public string? PinName { get; set; }

		[YamlMember(Order = 3)]
		public string? PinType { get; set; }

		[YamlMember(Order = 4)]
		public bool? DiscoverAll { get; set; }

		[YamlMember(Order = 5)]
		public bool? ShowMap { get; set; }
	}
	internal static class LocationManager
	{
		private sealed class OfferingBowlSnapshot
		{
			public string Name { get; set; } = "";


			public string UseItemText { get; set; } = "";


			public string UsedAltarText { get; set; } = "";


			public string CantOfferText { get; set; } = "";


			public string WrongOfferText { get; set; } = "";


			public string IncompleteOfferText { get; set; } = "";


			public string BossItem { get; set; } = "";


			public int BossItems { get; set; }

			public string BossPrefab { get; set; } = "";


			public string ItemPrefab { get; set; } = "";


			public string SetGlobalKey { get; set; } = "";


			public bool RenderSpawnAreaGizmos { get; set; }

			public bool AlertOnSpawn { get; set; }

			public float SpawnBossDelay { get; set; }

			public float SpawnBossMaxDistance { get; set; }

			public float SpawnBossMinDistance { get; set; }

			public float SpawnBossMaxYDistance { get; set; }

			public int GetSolidHeightMargin { get; set; }

			public bool EnableSolidHeightCheck { get; set; }

			public float SpawnPointClearingRadius { get; set; }

			public float SpawnYOffset { get; set; }

			public bool UseItemStands { get; set; }

			public string ItemStandPrefix { get; set; } = "";


			public float ItemStandMaxRange { get; set; }

			public string? CllcInfusion { get; set; }

			public string? CllcEffect { get; set; }

			public string? CllcBossEffect { get; set; }
		}

		private sealed class VegvisirTargetSnapshot
		{
			public string LocationName { get; set; } = "";


			public string PinName { get; set; } = "";


			public string PinType { get; set; } = "";


			public bool DiscoverAll { get; set; }

			public bool ShowMap { get; set; }
		}

		private sealed class VegvisirSnapshot
		{
			public string Name { get; set; } = "";


			public string UseText { get; set; } = "";


			public string HoverName { get; set; } = "";


			public string SetsGlobalKey { get; set; } = "";


			public string SetsPlayerKey { get; set; } = "";


			public List<VegvisirTargetSnapshot> Locations { get; set; } = new List<VegvisirTargetSnapshot>();

		}

		private sealed class PathScopedVegvisirSnapshot
		{
			public string Path { get; set; } = "";


			public VegvisirSnapshot Snapshot { get; set; } = new VegvisirSnapshot();

		}

		private sealed class PathScopedOfferingBowlSnapshot
		{
			public string Path { get; set; } = "";


			public OfferingBowlSnapshot Snapshot { get; set; } = new OfferingBowlSnapshot();

		}

		private sealed class ItemStandSnapshot
		{
			public string Name { get; set; } = "";


			public bool CanBeRemoved { get; set; }

			public bool AutoAttach { get; set; }

			public string OrientationType { get; set; } = "";


			public List<string> SupportedTypes { get; set; } = new List<string>();


			public List<string> SupportedItems { get; set; } = new List<string>();


			public List<string> UnsupportedItems { get; set; } = new List<string>();


			public float PowerActivationDelay { get; set; }

			public string GuardianPower { get; set; } = "";

		}

		private sealed class PathScopedItemStandSnapshot
		{
			public string Path { get; set; } = "";


			public ItemStandSnapshot Snapshot { get; set; } = new ItemStandSnapshot();

		}

		private sealed class LocationSnapshot
		{
			public string Prefab { get; set; } = "";


			public OfferingBowlSnapshot? OfferingBowl { get; set; }

			public List<PathScopedItemStandSnapshot> ItemStands { get; set; } = new List<PathScopedItemStandSnapshot>();


			public List<PathScopedVegvisirSnapshot> Vegvisirs { get; set; } = new List<PathScopedVegvisirSnapshot>();

		}

		private sealed class LiveLocationSnapshot
		{
			public string Prefab { get; set; } = "";


			public PathScopedOfferingBowlSnapshot? OfferingBowl { get; set; }

			public List<PathScopedItemStandSnapshot> ItemStands { get; set; } = new List<PathScopedItemStandSnapshot>();


			public List<PathScopedVegvisirSnapshot> Vegvisirs { get; set; } = new List<PathScopedVegvisirSnapshot>();

		}

		private sealed class LocationComponentCatalog
		{
			public string Prefab { get; set; } = "";


			public string? OfferingBowlPath { get; set; }

			public List<string> ItemStandPaths { get; set; } = new List<string>();


			public List<string> VegvisirPaths { get; set; } = new List<string>();

		}

		private sealed class LocationRuntimeComponents
		{
			public Transform Root { get; set; } = null;


			public List<OfferingBowl> OfferingBowls { get; } = new List<OfferingBowl>();


			public OfferingBowl? PrimaryOfferingBowl { get; set; }

			public List<ItemStand> ItemStands { get; } = new List<ItemStand>();


			public List<Vegvisir> Vegvisirs { get; } = new List<Vegvisir>();


			public Dictionary<string, OfferingBowl> OfferingBowlsByPath { get; set; } = new Dictionary<string, OfferingBowl>(StringComparer.Ordinal);


			public Dictionary<string, ItemStand> ItemStandsByPath { get; set; } = new Dictionary<string, ItemStand>(StringComparer.Ordinal);


			public Dictionary<string, Vegvisir> VegvisirsByPath { get; set; } = new Dictionary<string, Vegvisir>(StringComparer.Ordinal);


			public List<ItemStand> RelevantItemStands { get; set; } = new List<ItemStand>();

		}

		private sealed class AuthoredItemStandSlotTemplate
		{
			public string Path { get; set; } = "";


			public Vector3 OfferingBowlLocalOffset { get; set; }
		}

		private enum PendingLocationRootPhase
		{
			TraverseHierarchy,
			FinalizeBundles,
			ReconcileLocations
		}

		private readonly struct PendingLocationTraversalNode
		{
			public Transform Transform { get; }

			public Location? CurrentLocation { get; }

			public PendingLocationTraversalNode(Transform transform, Location? currentLocation)
			{
				Transform = transform;
				CurrentLocation = currentLocation;
			}
		}

		private sealed class PendingLocationRootReconcile
		{
			public int RootInstanceId { get; set; }

			public GameObject RootObject { get; set; } = null;


			public int Epoch { get; set; }

			public PendingLocationRootPhase Phase { get; set; }

			public List<Location>? Locations { get; set; }

			public List<PendingLocationTraversalNode>? TraversalStack { get; set; }

			public Dictionary<int, LocationRuntimeComponents>? RuntimeComponentsByLocationId { get; set; }

			public List<SpawnArea>? SpawnAreasForProvenance { get; set; }

			public List<CreatureSpawner>? CreatureSpawnersForProvenance { get; set; }

			public int NextFinalizeIndex { get; set; }

			public int NextIndex { get; set; }
		}

		private readonly struct PendingLocationReconcile
		{
			public Location Location { get; }

			public int Epoch { get; }

			public PendingLocationReconcile(Location location, int epoch)
			{
				Location = location;
				Epoch = epoch;
			}
		}

		private readonly struct PendingLooseOfferingBowlOverride
		{
			public OfferingBowl OfferingBowl { get; }

			public int OfferingBowlInstanceId { get; }

			public int Epoch { get; }

			public PendingLooseOfferingBowlOverride(OfferingBowl offeringBowl, int offeringBowlInstanceId, int epoch)
			{
				OfferingBowl = offeringBowl;
				OfferingBowlInstanceId = offeringBowlInstanceId;
				Epoch = epoch;
			}
		}

		[CompilerGenerated]
		private sealed class <EnumerateOverrideConfigurationPaths>d__131 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private string <>2__current;

			private int <>l__initialThreadId;

			private IEnumerator<string> <>s__1;

			private string <path>5__2;

			string IEnumerator<string>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <EnumerateOverrideConfigurationPaths>d__131(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 3)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>s__1 = null;
				<path>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						if (!Directory.Exists(DropNSpawnPlugin.YamlConfigDirectoryPath))
						{
							return false;
						}
						if (File.Exists(PrimaryOverrideConfigurationPathYml))
						{
							<>2__current = PrimaryOverrideConfigurationPathYml;
							<>1__state = 1;
							return true;
						}
						goto IL_0085;
					case 1:
						<>1__state = -1;
						goto IL_0085;
					case 2:
						<>1__state = -1;
						goto IL_00b7;
					case 3:
						{
							<>1__state = -3;
							<path>5__2 = null;
							break;
						}
						IL_0085:
						if (File.Exists(PrimaryOverrideConfigurationPathYaml))
						{
							<>2__current = PrimaryOverrideConfigurationPathYaml;
							<>1__state = 2;
							return true;
						}
						goto IL_00b7;
						IL_00b7:
						<>s__1 = EnumerateSupplementalOverrideConfigurationPaths().GetEnumerator();
						<>1__state = -3;
						break;
					}
					if (<>s__1.MoveNext())
					{
						<path>5__2 = <>s__1.Current;
						<>2__current = <path>5__2;
						<>1__state = 3;
						return true;
					}
					<>m__Finally1();
					<>s__1 = null;
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>s__1 != null)
				{
					<>s__1.Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<string> IEnumerable<string>.GetEnumerator()
			{
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					return this;
				}
				return new <EnumerateOverrideConfigurationPaths>d__131(0);
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<string>)this).GetEnumerator();
			}
		}

		[CompilerGenerated]
		private sealed class <EnumerateSupplementalOverrideConfigurationPaths>d__132 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private string <>2__current;

			private int <>l__initialThreadId;

			private IEnumerator<string> <>s__1;

			private string <path>5__2;

			string IEnumerator<string>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <EnumerateSupplementalOverrideConfigurationPaths>d__132(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>s__1 = null;
				<path>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<>s__1 = DropNSpawnPlugin.EnumerateSupplementalOverrideConfigurationPaths(DropNSpawnPlugin.GetYamlDomainSupplementalPrefix("location") + "*.*", IsOverrideConfigurationFileName).GetEnumerator();
						<>1__state = -3;
						break;
					case 1:
						<>1__state = -3;
						<path>5__2 = null;
						break;
					}
					if (<>s__1.MoveNext())
					{
						<path>5__2 = <>s__1.Current;
						<>2__current = <path>5__2;
						<>1__state = 1;
						return true;
					}
					<>m__Finally1();
					<>s__1 = null;
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>s__1 != null)
				{
					<>s__1.Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<string> IEnumerable<string>.GetEnumerator()
			{
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					return this;
				}
				return new <EnumerateSupplementalOverrideConfigurationPaths>d__132(0);
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<string>)this).GetEnumerator();
			}
		}

		[CompilerGenerated]
		private sealed class <GetRegisteredLocations>d__159 : IEnumerable<Location>, IEnumerable, IEnumerator<Location>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private Location <>2__current;

			private int <>l__initialThreadId;

			private HashSet<string> dirtyPrefabs;

			public HashSet<string> <>3__dirtyPrefabs;

			private HashSet<Location> <visited>5__1;

			private HashSet<string>.Enumerator <>s__2;

			private string <prefabName>5__3;

			private HashSet<Location> <locations>5__4;

			private HashSet<Location>.Enumerator <>s__5;

			private Location <location>5__6;

			Location IEnumerator<Location>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <GetRegisteredLocations>d__159(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if ((uint)(num - -4) <= 1u || num == 1)
				{
					try
					{
						if (num == -4 || num == 1)
						{
							try
							{
							}
							finally
							{
								<>m__Finally2();
							}
						}
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<visited>5__1 = null;
				<>s__2 = default(HashSet<string>.Enumerator);
				<prefabName>5__3 = null;
				<locations>5__4 = null;
				<>s__5 = default(HashSet<Location>.Enumerator);
				<location>5__6 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					int num = <>1__state;
					if (num != 0)
					{
						if (num != 1)
						{
							return false;
						}
						<>1__state = -4;
						goto IL_0115;
					}
					<>1__state = -1;
					CleanupRegisteredLocations();
					<visited>5__1 = new HashSet<Location>();
					<>s__2 = dirtyPrefabs.GetEnumerator();
					<>1__state = -3;
					goto IL_014f;
					IL_014f:
					do
					{
						if (<>s__2.MoveNext())
						{
							<prefabName>5__3 = <>s__2.Current;
							continue;
						}
						<>m__Finally1();
						<>s__2 = default(HashSet<string>.Enumerator);
						return false;
					}
					while (!LiveLocationsByPrefab.TryGetValue(<prefabName>5__3, out <locations>5__4));
					<>s__5 = <locations>5__4.GetEnumerator();
					<>1__state = -4;
					goto IL_011d;
					IL_0115:
					<location>5__6 = null;
					goto IL_011d;
					IL_011d:
					if (<>s__5.MoveNext())
					{
						<location>5__6 = <>s__5.Current;
						if ((Object)(object)<location>5__6 != (Object)null && (Object)(object)((Component)<location>5__6).gameObject != (Object)null && <visited>5__1.Add(<location>5__6))
						{
							<>2__current = <location>5__6;
							<>1__state = 1;
							return true;
						}
						goto IL_0115;
					}
					<>m__Finally2();
					<>s__5 = default(HashSet<Location>.Enumerator);
					<locations>5__4 = null;
					<prefabName>5__3 = null;
					goto IL_014f;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>s__2).Dispose();
			}

			private void <>m__Finally2()
			{
				<>1__state = -3;
				((IDisposable)<>s__5).Dispose();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<Location> IEnumerable<Location>.GetEnumerator()
			{
				<GetRegisteredLocations>d__159 <GetRegisteredLocations>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<GetRegisteredLocations>d__ = this;
				}
				else
				{
					<GetRegisteredLocations>d__ = new <GetRegisteredLocations>d__159(0);
				}
				<GetRegisteredLocations>d__.dirtyPrefabs = <>3__dirtyPrefabs;
				return <GetRegisteredLocations>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<Location>)this).GetEnumerator();
			}
		}

		[CompilerGenerated]
		private sealed class <GetTrackedLooseItemStands>d__160 : IEnumerable<ItemStand>, IEnumerable, IEnumerator<ItemStand>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private ItemStand <>2__current;

			private int <>l__initialThreadId;

			private HashSet<string> dirtyPrefabs;

			public HashSet<string> <>3__dirtyPrefabs;

			private List<KeyValuePair<ItemStand, string>> <trackedItemStands>5__1;

			private List<KeyValuePair<ItemStand, string>>.Enumerator <>s__2;

			private ItemStand <itemStand>5__3;

			private string <prefabName>5__4;

			ItemStand IEnumerator<ItemStand>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <GetTrackedLooseItemStands>d__160(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<trackedItemStands>5__1 = null;
				<>s__2 = default(List<KeyValuePair<ItemStand, string>>.Enumerator);
				<itemStand>5__3 = null;
				<prefabName>5__4 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					int num = <>1__state;
					if (num != 0)
					{
						if (num != 1)
						{
							return false;
						}
						<>1__state = -3;
						goto IL_00e1;
					}
					<>1__state = -1;
					CleanupTrackedLooseItemStandPrefabs();
					<trackedItemStands>5__1 = TrackedLooseItemStandPrefabs.ToList();
					<>s__2 = <trackedItemStands>5__1.GetEnumerator();
					<>1__state = -3;
					goto IL_00f0;
					IL_00e1:
					<itemStand>5__3 = null;
					<prefabName>5__4 = null;
					goto IL_00f0;
					IL_00f0:
					if (!<>s__2.MoveNext())
					{
						<>m__Finally1();
						<>s__2 = default(List<KeyValuePair<ItemStand, string>>.Enumerator);
						return false;
					}
					(<itemStand>5__3, <prefabName>5__4) = (KeyValuePair<ItemStand, string>)(ref <>s__2.Current);
					if ((Object)(object)<itemStand>5__3 != (Object)null && (Object)(object)((Component)<itemStand>5__3).gameObject != (Object)null && dirtyPrefabs.Contains(<prefabName>5__4))
					{
						<>2__current = <itemStand>5__3;
						<>1__state = 1;
						return true;
					}
					goto IL_00e1;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>s__2).Dispose();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<ItemStand> IEnumerable<ItemStand>.GetEnumerator()
			{
				<GetTrackedLooseItemStands>d__160 <GetTrackedLooseItemStands>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<GetTrackedLooseItemStands>d__ = this;
				}
				else
				{
					<GetTrackedLooseItemStands>d__ = new <GetTrackedLooseItemStands>d__160(0);
				}
				<GetTrackedLooseItemStands>d__.dirtyPrefabs = <>3__dirtyPrefabs;
				return <GetTrackedLooseItemStands>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<ItemStand>)this).GetEnumerator();
			}
		}

		private const string ReferenceAutoUpdateStateKey = "location";

		private static readonly int OfferingBowlLastUseTicksKey = StringExtensionMethods.GetStableHashCode("DropNSpawn.offering_bowl_last_use_ticks");

		private static readonly object Sync = new object();

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

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

		private static readonly List<LocationSnapshot> Snapshots = new List<LocationSnapshot>();

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

		private static readonly Dictionary<string, List<LocationConfigurationEntry>> ActiveEntriesByPrefab = new Dictionary<string, List<LocationConfigurationEntry>>(StringComparer.OrdinalIgnoreCase);

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

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

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

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

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

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

		private static readonly Dictionary<OfferingBowl, HashSet<int>> PendingOfferingBowlNearbyCharacterIds = new Dictionary<OfferingBowl, HashSet<int>>();

		private static readonly Dictionary<ItemStand, ItemStandSnapshot> LooseItemStandSnapshots = new Dictionary<ItemStand, ItemStandSnapshot>();

		private static readonly Dictionary<Location, LiveLocationSnapshot> LiveLocationSnapshots = new Dictionary<Location, LiveLocationSnapshot>();

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

		private static readonly Dictionary<string, HashSet<Location>> LiveLocationsByPrefab = new Dictionary<string, HashSet<Location>>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<Location, string> LiveLocationPrefabsByInstance = new Dictionary<Location, string>();

		private static readonly Dictionary<string, List<AuthoredItemStandSlotTemplate>> AuthoredItemStandSlotsByPrefab = new Dictionary<string, List<AuthoredItemStandSlotTemplate>>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, List<LocationConfigurationEntry>> LooseItemStandEntriesByPrefab = new Dictionary<string, List<LocationConfigurationEntry>>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<ItemStand, string> TrackedLooseItemStandPrefabs = new Dictionary<ItemStand, string>();

		private static readonly Dictionary<ItemStand, string> LooseItemStandAuthoredPathsByInstance = new Dictionary<ItemStand, string>();

		private static readonly RingBufferQueue<PendingLocationReconcile> PendingLocationReconciles = new RingBufferQueue<PendingLocationReconcile>();

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

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

		private static readonly RingBufferQueue<PendingLocationRootReconcile> PendingLocationRootReconciles = new RingBufferQueue<PendingLocationRootReconcile>();

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

		private static readonly RingBufferQueue<PendingLooseOfferingBowlOverride> PendingLooseOfferingBowlOverrides = new RingBufferQueue<PendingLooseOfferingBowlOverride>();

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

		private static List<LocationConfigurationEntry> _configuration = new List<LocationConfigurationEntry>();

		private static string _configurationSignature = "";

		private static string _lastLoadedConfigurationPayload = "";

		private static bool _initialized;

		private static bool _snapshotsCaptured;

		private static int? _lastProcessedGameDataSignature;

		private static bool _referenceArtifactsAutoRefreshConsumed;

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

		private static string _lastAppliedConfigurationSignature = "";

		private static int? _lastAppliedGameDataSignature;

		private static bool? _lastAppliedDomainEnabled;

		private static int _reconcileQueueEpoch;

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

		private static string ReferenceConfigurationPath => Path.Combine(DropNSpawnPlugin.YamlConfigDirectoryPath, DropNSpawnPlugin.GetYamlDomainFilePrefix("location") + ".reference.yml");

		private static string PrimaryOverrideConfigurationPathYml => Path.Combine(DropNSpawnPlugin.YamlConfigDirectoryPath, DropNSpawnPlugin.GetYamlDomainFilePrefix("location") + ".yml");

		private static string PrimaryOverrideConfigurationPathYaml => Path.Combine(DropNSpawnPlugin.YamlConfigDirectoryPath, DropNSpawnPlugin.GetYamlDomainFilePrefix("location") + ".yaml");

		private static string FullScaffoldConfigurationPath => Path.Combine(DropNSpawnPlugin.YamlConfigDirectoryPath, DropNSpawnPlugin.GetYamlDomainFilePrefix("location") + ".full.yml");

		internal static bool ShouldReloadForPath(string? path)
		{
			return DropNSpawnPlugin.IsEligibleOverrideConfigurationPath(path) && IsOverrideConfigurationFileName(Path.GetFileName(path ?? ""));
		}

		internal static void Initialize()
		{
			lock (Sync)
			{
				if (!_initialized)
				{
					LoadConfiguration();
					_initialized = true;
				}
			}
		}

		internal static void ReloadConfiguration()
		{
			lock (Sync)
			{
				LoadConfiguration();
				ApplyIfReady();
			}
		}

		internal static void OnGameDataReady(string source)
		{
			lock (Sync)
			{
				if (!_initialized)
				{
					Initialize();
				}
				if (!IsGameDataReady())
				{
					return;
				}
				int num = ComputeGameDataSignature();
				if (_lastProcessedGameDataSignature == num)
				{
					return;
				}
				ResetReferenceSnapshots();
				ResetRuntimeState(preserveLiveRegistries: true);
				CleanupRegisteredLocations();
				if (DropNSpawnPlugin.IsSourceOfTruth)
				{
					if (!_referenceArtifactsAutoRefreshConsumed)
					{
						EnsureReferenceArtifactsUpToDate();
						_referenceArtifactsAutoRefreshConsumed = true;
					}
					if (EnsurePrimaryOverrideConfigurationFileExists())
					{
						LoadConfiguration();
					}
				}
				else
				{
					_referenceArtifactsAutoRefreshConsumed = true;
				}
				ApplyIfReady();
				_lastProcessedGameDataSignature = num;
				DropNSpawnPlugin.DropNSpawnLogger.LogInfo((object)("Locations processed after " + source + "."));
			}
		}

		internal static void ReconcileLocationInstance(Location location)
		{
			lock (Sync)
			{
				TrackLocationInstanceInternal(location);
				if (!_initialized)
				{
					Initialize();
				}
				if (IsGameDataReady())
				{
					ReconcileLocationInstanceInternal(location);
				}
			}
		}

		internal static void QueueLocationReconcile(Location? location)
		{
			lock (Sync)
			{
				if (!((Object)(object)location == (Object)null) && !((Object)(object)((Component)location).gameObject == (Object)null))
				{
					int instanceID = ((Object)location).GetInstanceID();
					if (PendingLocationReconcileIds.Add(instanceID))
					{
						PendingLocationReconciles.Enqueue(new PendingLocationReconcile(location, _reconcileQueueEpoch));
					}
				}
			}
		}

		internal static void ReconcileSpawnedLocationRoot(GameObject? rootObject)
		{
			QueueSpawnedLocationRootReconcile(rootObject);
		}

		internal static void QueueSpawnedLocationRootReconcile(GameObject? rootObject)
		{
			lock (Sync)
			{
				if (!((Object)(object)rootObject == (Object)null))
				{
					int instanceID = ((Object)rootObject).GetInstanceID();
					if (PendingLocationRootReconcileIds.Add(instanceID))
					{
						PendingLocationRootReconciles.Enqueue(new PendingLocationRootReconcile
						{
							RootInstanceId = instanceID,
							RootObject = rootObject,
							Epoch = _reconcileQueueEpoch,
							Phase = PendingLocationRootPhase.TraverseHierarchy
						});
					}
				}
			}
		}

		internal static void TrackLocationInstance(Location? location)
		{
			lock (Sync)
			{
				TrackLocationInstanceInternal(location);
			}
		}

		internal static void TrackSpawnedLocationRoot(GameObject? rootObject)
		{
			lock (Sync)
			{
				TrackSpawnedLocationRootInternal(rootObject);
			}
		}

		internal static void QueueLooseItemStandOverride(ItemStand? itemStand)
		{
			lock (Sync)
			{
				if (!((Object)(object)itemStand == (Object)null) && !((Object)(object)((Component)itemStand).gameObject == (Object)null) && LooseItemStandEntriesByPrefab.Count != 0 && !((Object)(object)((Component)itemStand).GetComponentInParent<Location>() != (Object)null) && AltarItemStandHoverInfoFormatter.TryGetRelevantOfferingBowl(itemStand, out OfferingBowl offeringBowl) && !((Object)(object)offeringBowl == (Object)null))
				{
					QueueLooseOfferingBowlOverrideInternal(offeringBowl);
				}
			}
		}

		internal static void QueueLooseOfferingBowlOverride(OfferingBowl? offeringBowl)
		{
			lock (Sync)
			{
				QueueLooseOfferingBowlOverrideInternal(offeringBowl);
			}
		}

		internal static void QueueLooseOfferingBowlOverridesUnderRoot(GameObject? rootObject)
		{
			lock (Sync)
			{
				if (!((Object)(object)rootObject == (Object)null) && LooseItemStandEntriesByPrefab.Count != 0)
				{
					OfferingBowl[] componentsInChildren = rootObject.GetComponentsInChildren<OfferingBowl>(true);
					foreach (OfferingBowl offeringBowl in componentsInChildren)
					{
						QueueLooseOfferingBowlOverrideInternal(offeringBowl);
					}
				}
			}
		}

		private static void QueueLooseOfferingBowlOverrideInternal(OfferingBowl? offeringBowl)
		{
			if (!((Object)(object)offeringBowl == (Object)null) && !((Object)(object)((Component)offeringBowl).gameObject == (Object)null) && LooseItemStandEntriesByPrefab.Count != 0 && offeringBowl.m_useItemStands && !((Object)(object)((Component)offeringBowl).GetComponentInParent<Location>() != (Object)null))
			{
				int instanceID = ((Object)offeringBowl).GetInstanceID();
				if (PendingLooseOfferingBowlOverrideIds.Add(instanceID))
				{
					PendingLooseOfferingBowlOverrides.Enqueue(new PendingLooseOfferingBowlOverride(offeringBowl, instanceID, _reconcileQueueEpoch));
				}
			}
		}

		internal static bool HasPendingReconcileWork()
		{
			lock (Sync)
			{
				return PendingLocationReconciles.Count > 0 || PendingLocationRootReconciles.Count > 0 || PendingLooseOfferingBowlOverrides.Count > 0;
			}
		}

		internal static bool ProcessQueuedReconcileStep(float deadline)
		{
			lock (Sync)
			{
				if (Time.realtimeSinceStartup >= deadline)
				{
					return false;
				}
				if (!IsGameDataReady() || DropNSpawnPlugin.IsGameDataRefreshDeferred(DropNSpawnPlugin.ReloadDomain.Location))
				{
					return false;
				}
				if (PendingLocationRootReconciles.Count > 0)
				{
					return ProcessQueuedLocationRootStep(deadline);
				}
				while (PendingLocationReconciles.Count > 0)
				{
					if (!PendingLocationReconciles.TryDequeue(out var item) || item.Epoch != _reconcileQueueEpoch || (Object)(object)item.Location == (Object)null)
					{
						continue;
					}
					Location location = item.Location;
					int instanceID = ((Object)location).GetInstanceID();
					PendingLocationReconcileIds.Remove(instanceID);
					if (SuppressedQueuedLocationReconciles.TryGetValue(instanceID, out var value) && value > 0)
					{
						if (value == 1)
						{
							SuppressedQueuedLocationReconciles.Remove(instanceID);
						}
						else
						{
							SuppressedQueuedLocationReconciles[instanceID] = value - 1;
						}
						return true;
					}
					TrackLocationInstanceInternal(location);
					if (!_initialized)
					{
						Initialize();
					}
					ReconcileLocationInstanceInternal(location);
					return true;
				}
				while (PendingLooseOfferingBowlOverrides.Count > 0)
				{
					if (!PendingLooseOfferingBowlOverrides.TryDequeue(out var item2))
					{
						continue;
					}
					PendingLooseOfferingBowlOverrideIds.Remove(item2.OfferingBowlInstanceId);
					if (item2.Epoch != _reconcileQueueEpoch || (Object)(object)item2.OfferingBowl == (Object)null)
					{
						continue;
					}
					if (!_initialized)
					{
						Initialize();
					}
					TryApplyLooseOfferingBowlOverrideInternal(item2.OfferingBowl);
					return true;
				}
			}
			return false;
		}

		internal static void UntrackLocationInstance(Location? location)
		{
			lock (Sync)
			{
				if ((Object)(object)location != (Object)null && LiveLocationPrefabsByInstance.TryGetValue(location, out string value))
				{
					UnregisterLiveLocation(location, value);
				}
			}
		}

		internal static bool TryBlockOfferingBowlRespawn(OfferingBowl offeringBowl, Humanoid? user, ref bool result)
		{
			lock (Sync)
			{
				if ((Object)(object)offeringBowl == (Object)null || (Object)(object)ZNet.instance == (Object)null)
				{
					return false;
				}
				OfferingBowlRuntimeState component = ((Component)offeringBowl).GetComponent<OfferingBowlRuntimeState>();
				if ((Object)(object)component == (Object)null || component.RespawnMinutes <= 0f)
				{
					return false;
				}
				long offeringBowlLastUseTicks = GetOfferingBowlLastUseTicks(offeringBowl, component);
				if (offeringBowlLastUseTicks <= 0)
				{
					return false;
				}
				if ((ZNet.instance.GetTime() - new DateTime(offeringBowlLastUseTicks)).TotalMinutes >= (double)component.RespawnMinutes)
				{
					return false;
				}
				if ((Object)(object)user != (Object)null)
				{
					((Character)user).Message((MessageType)2, Localization.instance.Localize(offeringBowl.m_cantOfferText), 0, (Sprite)null);
				}
				result = true;
				return true;
			}
		}

		internal static void MarkOfferingBowlUsed(OfferingBowl offeringBowl)
		{
			lock (Sync)
			{
				if ((Object)(object)offeringBowl == (Object)null || (Object)(object)ZNet.instance == (Object)null)
				{
					return;
				}
				OfferingBowlRuntimeState component = ((Component)offeringBowl).GetComponent<OfferingBowlRuntimeState>();
				if ((Object)(object)component == (Object)null || component.RespawnMinutes <= 0f)
				{
					return;
				}
				long num = (component.LocalLastUseTicks = ZNet.instance.GetTime().Ticks);
				ZNetView componentInParent = ((Component)offeringBowl).GetComponentInParent<ZNetView>();
				if (!((Object)(object)componentInParent == (Object)null) && componentInParent.IsValid())
				{
					if (!componentInParent.IsOwner())
					{
						componentInParent.ClaimOwnership();
					}
					if (componentInParent.IsOwner())
					{
						componentInParent.GetZDO().Set(OfferingBowlLastUseTicksKey, num);
					}
				}
			}
		}

		internal static bool TryWriteFullScaffoldConfigurationFile(out string path, out string error)
		{
			lock (Sync)
			{
				path = FullScaffoldConfigurationPath;
				error = "";
				if (!IsGameDataReady() && !_snapshotsCaptured)
				{
					error = "Location game data is not ready yet.";
					return false;
				}
				RefreshSnapshots();
				Directory.CreateDirectory(DropNSpawnPlugin.YamlConfigDirectoryPath);
				File.WriteAllText(path, BuildFullScaffoldConfigurationTemplate());
				DropNSpawnPlugin.DropNSpawnLogger.LogInfo((object)("Wrote location full scaffold configuration to " + path + "."));
				return true;
			}
		}

		internal static void RefreshReferenceConfigurationFile()
		{
			lock (Sync)
			{
				if (IsGameDataReady())
				{
					RefreshSnapshots();
					WriteReferenceConfigurationFile(BuildReferenceConfigurationTemplate(), "Updated location reference configuration at " + ReferenceConfigurationPath + ".");
					ReferenceRefreshSupport.RecordAutoUpdateState("location", ReferenceConfigurationPath, ComputeReferenceSourceSignature(), null, "2026-03-26-full-rewrite-v1");
					ResetReferenceSnapshots();
				}
			}
		}

		private static bool IsGameDataReady()
		{
			return (Object)(object)ZoneSystem.instance != (Object)null && (Object)(object)ZNetScene.instance != (Object)null && (Object)(object)ObjectDB.instance != (Object)null;
		}

		private static int ComputeGameDataSignature()
		{
			if (!IsGameDataReady() || (Object)(object)ZoneSystem.instance == (Object)null || (Object)(object)ZNetScene.instance == (Object)null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return 0;
			}
			int num = 17;
			num = num * 31 + ((Object)ZoneSystem.instance).GetInstanceID();
			num = num * 31 + ((Object)ZNetScene.instance).GetInstanceID();
			num = num * 31 + ((Object)ObjectDB.instance).GetInstanceID();
			num = HashGameObjectCollection(num, ZNetScene.instance.m_prefabs);
			num = HashGameObjectCollection(num, ZNetScene.instance.m_nonNetViewPrefabs);
			num = HashGameObjectCollection(num, ObjectDB.instance.m_items);
			foreach (ZoneLocation location in ZoneSystem.instance.m_locations)
			{
				num = num * 31 + (location?.m_prefabName?.GetHashCode()).GetValueOrDefault();
			}
			return num;
		}

		private static int HashGameObjectCollection(int hash, IEnumerable<GameObject> prefabs)
		{
			foreach (GameObject prefab in prefabs)
			{
				hash = hash * 31 + (((Object)(object)prefab != (Object)null) ? ((Object)prefab).GetInstanceID() : 0);
			}
			return hash;
		}

		private static string ComputeReferenceSourceSignature()
		{
			if ((Object)(object)ZoneSystem.instance == (Object)null)
			{
				return "";
			}
			return ReferenceRefreshSupport.ComputeStableHashForKeys(ZoneSystem.instance.m_locations.Select((ZoneLocation location) => location?.m_prefabName ?? location?.m_prefab.Name));
		}

		private static bool EnsurePrimaryOverrideConfigurationFileExists()
		{
			if (File.Exists(PrimaryOverrideConfigurationPathYml) || File.Exists(PrimaryOverrideConfigurationPathYaml) || EnumerateSupplementalOverrideConfigurationPaths().Any())
			{
				return false;
			}
			Directory.CreateDirectory(DropNSpawnPlugin.YamlConfigDirectoryPath);
			File.WriteAllText(PrimaryOverrideConfigurationPathYml, BuildPrimaryOverrideConfigurationTemplate());
			DropNSpawnPlugin.DropNSpawnLogger.LogInfo((object)("Created location override configuration at " + PrimaryOverrideConfigurationPathYml + "."));
			return true;
		}

		private static void EnsureReferenceArtifactsUpToDate()
		{
			if (!IsGameDataReady())
			{
				return;
			}
			string sourceSignature = ComputeReferenceSourceSignature();
			if (!File.Exists(ReferenceConfigurationPath))
			{
				if (DropNSpawnPlugin.ShouldAutoCreateMissingReferenceFiles())
				{
					RefreshSnapshots();
					WriteReferenceConfigurationFile(BuildReferenceConfigurationTemplate(), "Created location reference configuration at " + ReferenceConfigurationPath + ".");
					ReferenceRefreshSupport.RecordAutoUpdateState("location", ReferenceConfigurationPath, sourceSignature, null, "2026-03-26-full-rewrite-v1");
					ResetReferenceSnapshots();
				}
			}
			else if (DropNSpawnPlugin.ShouldAutoUpdateReferenceFiles() && !ReferenceRefreshSupport.ShouldSkipAutoUpdate("location", ReferenceConfigurationPath, sourceSignature, "2026-03-26-full-rewrite-v1"))
			{
				RefreshSnapshots();
				WriteReferenceConfigurationFile(BuildReferenceConfigurationTemplate(), "Updated location reference configuration at " + ReferenceConfigurationPath + ".");
				ReferenceRefreshSupport.RecordAutoUpdateState("location", ReferenceConfigurationPath, sourceSignature, null, "2026-03-26-full-rewrite-v1");
				ResetReferenceSnapshots();
			}
		}

		private static void LoadConfiguration()
		{
			List<LocationConfigurationEntry> entries2;
			string payloadToken;
			if (DropNSpawnPlugin.IsSourceOfTruth)
			{
				EnsurePrimaryOverrideConfigurationFileExists();
				List<ConfigurationLoadSupport.LocalYamlDocument> documents = ConfigurationLoadSupport.ReadLocalYamlDocuments(EnumerateOverrideConfigurationPaths().ToList());
				string text = ConfigurationLoadSupport.BuildLocalPayload(documents);
				List<LocationConfigurationEntry> entries;
				if (string.Equals(_lastLoadedConfigurationPayload, text, StringComparison.Ordinal))
				{
					entries = BuildSyncedClientProjectionEntries();
					DropNSpawnPlugin.UpdateSyncedLocationPayload(entries);
					return;
				}
				ResetLoadedConfigurationState();
				LoadLocalConfiguration(documents);
				_configurationSignature = Serializer.Serialize(_configuration);
				_lastLoadedConfigurationPayload = text;
				entries = BuildSyncedClientProjectionEntries();
				DropNSpawnPlugin.UpdateSyncedLocationPayload(entries);
			}
			else if (!DropNSpawnPlugin.TryGetSyncedLocationEntries(out entries2, out payloadToken))
			{
				DropNSpawnPlugin.DropNSpawnLogger.LogDebug((object)"Waiting for synchronized location override payload from the server.");
			}
			else
			{
				if (string.Equals(_lastLoadedConfigurationPayload, payloadToken, StringComparison.Ordinal))
				{
					return;
				}
				ResetLoadedConfigurationState();
				if (entries2.Count == 0)
				{
					_configurationSignature = Serializer.Serialize(_configuration);
					_lastLoadedConfigurationPayload = payloadToken;
					return;
				}
				try
				{
					MergeConfiguration(entries2, "ServerSync:DropNSpawnLocation");
					DropNSpawnPlugin.DropNSpawnLogger.LogInfo((object)$"Loaded {ActiveEntriesByPrefab.Count} synchronized location projection(s) from the server.");
				}
				catch (Exception arg)
				{
					DropNSpawnPlugin.DropNSpawnLogger.LogError((object)$"Failed to deserialize synchronized location payload DTO. {arg}");
				}
				_configurationSignature = Serializer.Serialize(_configuration);
				_lastLoadedConfigurationPayload = payloadToken;
			}
		}

		private static void ResetLoadedConfigurationState()
		{
			ClearQueuedReconcileState();
			ActiveEntriesByPrefab.Clear();
			AuthoredItemStandSlotsByPrefab.Clear();
			LooseItemStandEntriesByPrefab.Clear();
			InvalidEntryWarnings.Clear();
			ItemStandDiagnosticLogs.Clear();
			LocationDiagnosticLogs.Clear();
			_configuration = new List<LocationConfigurationEntry>();
		}

		private static void LoadLocalConfiguration(List<ConfigurationLoadSupport.LocalYamlDocument> documents)
		{
			if (documents.Count == 0)
			{
				DropNSpawnPlugin.DropNSpawnLogger.LogInfo((object)"Loaded 0 location configuration(s) from 0 override file(s).");
				return;
			}
			int num = 0;
			foreach (ConfigurationLoadSupport.LocalYamlDocument document in documents)
			{
				if (document.ReadError != null)
				{
					DropNSpawnPlugin.DropNSpawnLogger.LogError((object)("Failed to read " + document.Path + ". " + document.ReadError));
					continue;
				}
				try
				{
					string yaml = document.Yaml ?? "";
					List<LocationConfigurationEntry> configuration = ParseConfiguration(yaml);
					MergeConfiguration(configuration, document.Path);
					num++;
				}
				catch (Exception arg)
				{
					DropNSpawnPlugin.DropNSpawnLogger.LogError((object)$"Failed to parse location YAML '{document.Path}'. Location override YAML must start with a root list like '- prefab: ...'. {arg}");
				}
			}
			DropNSpawnPlugin.DropNSpawnLogger.LogInfo((object)$"Loaded {ActiveEntriesByPrefab.Count} location configuration(s) from {num} override file(s).");
		}

		private static List<LocationConfigurationEntry> ParseConfiguration(string yaml)
		{
			if (string.IsNullOrWhiteSpace(yaml))
			{
				return new List<LocationConfigurationEntry>();
			}
			List<LocationConfigurationEntry> list = Deserializer.Deserialize<List<LocationConfigurationEntry>>(yaml) ?? new List<LocationConfigurationEntry>();
			foreach (LocationConfigurationEntry item in list)
			{
				item.Prefab = (item.Prefab ?? "").Trim();
				NormalizeOfferingBowlDefinition(item.OfferingBowl);
				NormalizeItemStandDefinitions(item.ItemStands);
				NormalizeVegvisirDefinitions(item.Vegvisirs);
				FinalizeNormalizedEntry(item);
			}
			return list;
		}

		private static void MergeConfiguration(List<LocationConfigurationEntry> configuration, string source)
		{
			foreach (LocationConfigurationEntry item in configuration)
			{
				item.SourcePath = source;
				item.Prefab = (item.Prefab ?? "").Trim();
				NormalizeOfferingBowlDefinition(item.OfferingBowl);
				NormalizeItemStandDefinitions(item.ItemStands);
				NormalizeVegvisirDefinitions(item.Vegvisirs);
				FinalizeNormalizedEntry(item);
				StripRedundantLocationComponentConditions(item, source);
				if (item.Prefab.Length == 0)
				{
					WarnInvalidEntry("Entry in '" + source + "' is missing prefab.");
				}
				else
				{
					if (!item.Enabled)
					{
						continue;
					}
					RemoveEffectiveConfigurationEntry(item.Prefab, item.RuleId);
					_configuration.Add(item);
					if (HasOverride(item))
					{
						GetOrCreateActiveEntries(item.Prefab).Add(item);
						if (HasLooseItemStandOverride(item.ItemStands))
						{
							GetOrCreateLooseItemStandEntries(item.Prefab).Add(item);
						}
						LogLoadedLocationEntry(item);
					}
				}
			}
		}

		private static bool RemoveEffectiveConfigurationEntry(string prefabName, string ruleId)
		{
			bool result = false;
			for (int num = _configuration.Count - 1; num >= 0; num--)
			{
				LocationConfigurationEntry locationConfigurationEntry = _configuration[num];
				if (string.Equals(locationConfigurationEntry.Prefab, prefabName, StringComparison.OrdinalIgnoreCase) && string.Equals(locationConfigurationEntry.RuleId, ruleId, StringComparison.Ordinal))
				{
					_configuration.RemoveAt(num);
					result = true;
				}
			}
			if (ActiveEntriesByPrefab.TryGetValue(prefabName, out List<LocationConfigurationEntry> value))
			{
				for (int num2 = value.Count - 1; num2 >= 0; num2--)
				{
					if (string.Equals(value[num2].RuleId, ruleId, StringComparison.Ordinal))
					{
						value.RemoveAt(num2);
						result = true;
					}
				}
				if (value.Count == 0)
				{
					ActiveEntriesByPrefab.Remove(prefabName);
				}
			}
			if (LooseItemStandEntriesByPrefab.TryGetValue(prefabName, out List<LocationConfigurationEntry> value2))
			{
				for (int num3 = value2.Count - 1; num3 >= 0; num3--)
				{
					if (string.Equals(value2[num3].RuleId, ruleId, StringComparison.Ordinal))
					{
						value2.RemoveAt(num3);
						result = true;
					}
				}
				if (value2.Count == 0)
				{
					LooseItemStandEntriesByPrefab.Remove(prefabName);
				}
			}
			return result;
		}

		private static List<LocationConfigurationEntry> GetOrCreateActiveEntries(string prefabName)
		{
			if (!ActiveEntriesByPrefab.TryGetValue(prefabName, out List<LocationConfigurationEntry> value))
			{
				value = new List<LocationConfigurationEntry>();
				ActiveEntriesByPrefab[prefabName] = value;
			}
			return value;
		}

		private static List<LocationConfigurationEntry> GetOrCreateLooseItemStandEntries(string prefabName)
		{
			if (!LooseItemStandEntriesByPrefab.TryGetValue(prefabName, out List<LocationConfigurationEntry> value))
			{
				value = new List<LocationConfigurationEntry>();
				LooseItemStandEntriesByPrefab[prefabName] = value;
			}
			return value;
		}

		private static List<LocationConfigurationEntry> BuildSyncedClientProjectionEntries()
		{
			List<LocationConfigurationEntry> list = new List<LocationConfigurationEntry>();
			foreach (LocationConfigurationEntry item in _configuration)
			{
				LocationConfigurationEntry locationConfigurationEntry = CreateClientProjectionEntry(item);
				if (locationConfigurationEntry != null)
				{
					list.Add(locationConfigurationEntry);
				}
			}
			return list;
		}

		private static LocationConfigurationEntry? CreateClientProjectionEntry(LocationConfigurationEntry? entry)
		{
			if (entry == null || !entry.Enabled || string.IsNullOrWhiteSpace(entry.Prefab))
			{
				return null;
			}
			LocationOfferingBowlDefinition locationOfferingBowlDefinition = CreateClientProjectionOfferingBowlDefinition(entry.OfferingBowl);
			List<LocationItemStandDefinition> list = (HasItemStandOverride(entry.ItemStands) ? entry.ItemStands : null);
			List<LocationVegvisirDefinition> list2 = (HasVegvisirOverride(entry.Vegvisirs) ? entry.Vegvisirs : null);
			if (locationOfferingBowlDefinition == null && list == null && list2 == null)
			{
				return null;
			}
			return new LocationConfigurationEntry
			{
				RuleId = entry.RuleId,
				Prefab = entry.Prefab,
				Enabled = true,
				Conditions = entry.Conditions,
				OfferingBowl = locationOfferingBowlDefinition,
				ItemStands = list,
				Vegvisirs = list2
			};
		}

		private static LocationOfferingBowlDefinition? CreateClientProjectionOfferingBowlDefinition(LocationOfferingBowlDefinition? definition)
		{
			if (!HasClientVisibleOfferingBowlOverride(definition))
			{
				return null;
			}
			return new LocationOfferingBowlDefinition
			{
				Name = definition.Name,
				UseItemText = definition.UseItemText,
				UsedAltarText = definition.UsedAltarText,
				CantOfferText = definition.CantOfferText,
				WrongOfferText = definition.WrongOfferText,
				IncompleteOfferText = definition.IncompleteOfferText,
				BossItem = definition.BossItem,
				BossItems = definition.BossItems,
				BossPrefab = definition.BossPrefab,
				ItemPrefab = definition.ItemPrefab,
				RenderSpawnAreaGizmos = definition.RenderSpawnAreaGizmos,
				AlertOnSpawn = definition.AlertOnSpawn,
				UseItemStands = definition.UseItemStands,
				ItemStandPrefix = definition.ItemStandPrefix,
				ItemStandMaxRange = definition.ItemStandMaxRange,
				RespawnMinutes = definition.RespawnMinutes,
				CllcInfusion = definition.CllcInfusion,
				CllcEffect = definition.CllcEffect,
				CllcBossEffect = definition.CllcBossEffect
			};
		}

		private static void LogLoadedLocationEntry(LocationConfigurationEntry entry)
		{
			string text = ((entry.ItemStands == null) ? "(none)" : JoinDiagnosticValues(entry.ItemStands.Where(HasItemStandOverride).SelectMany(delegate(LocationItemStandDefinition itemStand)
			{
				IEnumerable<string> supportedItems = itemStand.SupportedItems;
				return supportedItems ?? Enumerable.Empty<string>();
			})));
			string item = $"config|{entry.Prefab}|{text}|{entry.ItemStands?.Count ?? 0}";
			if (LocationDiagnosticLogs.Add(item))
			{
				DropNSpawnPlugin.DropNSpawnLogger.LogDebug((object)$"Loaded location override entry: prefab='{entry.Prefab}', hasOfferingBowl={HasOfferingBowlOverride(entry.OfferingBowl)}, hasItemStands={HasItemStandOverride(entry.ItemStands)}, hasVegvisir={HasVegvisirOverride(entry.Vegvisirs)}, itemStands.supportedItems=[{text}].");
			}
		}

		private static void NormalizeOfferingBowlDefinition(LocationOfferingBowlDefinition? definition)
		{
			if (definition != null)
			{
				definition.BossItem = definition.BossItem?.Trim();
				definition.BossPrefab = definition.BossPrefab?.Trim();
				definition.ItemPrefab = definition.ItemPrefab?.Trim();
				definition.SetGlobalKey = definition.SetGlobalKey?.Trim();
				definition.ItemStandPrefix = definition.ItemStandPrefix?.Trim();
				definition.Data = NormalizeOptionalString(definition.Data);
				definition.Fields = NormalizeOptionalStringDictionary(definition.Fields);
				definition.Objects = NormalizeOptionalStringList(definition.Objects);
				FloatRangeDefinition? spawnBossDistance = definition.SpawnBossDistance;
				if (spawnBossDistance != null && spawnBossDistance.HasValues())
				{
					definition.SpawnBossMinDistance = RangeFormatting.GetMin(definition.SpawnBossDistance, definition.SpawnBossMinDistance);
					definition.SpawnBossMaxDistance = RangeFormatting.GetMax(definition.SpawnBossDistance, definition.SpawnBossMinDistance, definition.SpawnBossMaxDistance);
				}
				definition.CllcInfusion = definition.CllcInfusion?.Trim();
				definition.CllcEffect = definition.CllcEffect?.Trim();
				definition.CllcBossEffect = definition.CllcBossEffect?.Trim();
			}
		}

		private static string? NormalizeOptionalString(string? value)
		{
			if (value == null)
			{
				return null;
			}
			string text = value.Trim();
			return (text.Length == 0) ? null : text;
		}

		private static List<string>? NormalizeOptionalStringList(List<string>? values)
		{
			if (values == null)
			{
				return null;
			}
			List<string> list = (from value in values
				select (value ?? "").Trim() into value
				where value.Length > 0
				select value).ToList();
			return (list.Count == 0) ? null : list;
		}

		private static Dictionary<string, string>? NormalizeOptionalStringDictionary(Dictionary<string, string>? values)
		{
			if (values == null)
			{
				return null;
			}
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
			foreach (KeyValuePair<string, string> value2 in values)
			{
				value2.Deconstruct(out var key, out var value);
				string text = key;
				string text2 = value;
				string text3 = (text ?? "").Trim();
				if (text3.Length != 0)
				{
					dictionary[text3] = (text2 ?? "").Trim();
				}
			}
			return (dictionary.Count == 0) ? null : dictionary;
		}

		private static void NormalizeVegvisirDefinitions(List<LocationVegvisirDefinition>? definitions)
		{
			if (definitions == null)
			{
				return;
			}
			foreach (LocationVegvisirDefinition definition in definitions)
			{
				NormalizeVegvisirDefinition(definition);
			}
		}

		private static void NormalizeVegvisirDefinition(LocationVegvisirDefinition? definition)
		{
			if (definition == null)
			{
				return;
			}
			definition.Path = (definition.Path ?? "").Trim();
			definition.ExpectedLocations = (from value in definition.ExpectedLocations?.Select((string value) => (value ?? "").Trim())
				where value.Length > 0
				select value).Distinct<string>(StringComparer.OrdinalIgnoreCase).ToList();
			definition.Name = definition.Name?.Trim();
			definition.UseText = definition.UseText?.Trim();
			definition.HoverName = definition.HoverName?.Trim();
			definition.SetsGlobalKey = definition.SetsGlobalKey?.Trim();
			definition.SetsPlayerKey = definition.SetsPlayerKey?.Trim();
			if (definition.Locations == null)
			{
				return;
			}
			foreach (LocationVegvisirTargetDefinition location in definition.Locations)
			{
				location.LocationName = (location.LocationName ?? "").Trim();
				location.PinName = location.PinName?.Trim();
				location.PinType = location.PinType?.Trim();
			}
		}

		private static void NormalizeItemStandDefinitions(List<LocationItemStandDefinition>? definitions)
		{
			if (definitions == null)
			{
				return;
			}
			foreach (LocationItemStandDefinition definition in definitions)
			{
				NormalizeItemStandDefinition(definition);
			}
		}

		private static void NormalizeItemStandDefinition(LocationItemStandDefinition? definition)
		{
			if (definition != null)
			{
				definition.Path = definition.Path?.Trim();
				definition.Name = definition.Name?.Trim();
				definition.OrientationType = definition.OrientationType?.Trim();
				definition.GuardianPower = definition.GuardianPower?.Trim();
				definition.SupportedTypes = (from value in definition.SupportedTypes?.Select((string value) => (value ?? "").Trim())
					where value.Length > 0
					select value).Distinct<string>(StringComparer.OrdinalIgnoreCase).ToList();
				definition.SupportedItems = (from value in definition.SupportedItems?.Select((string value) => (value ?? "").Trim())
					where value.Length > 0
					select value).Distinct<string>(StringComparer.OrdinalIgnoreCase).ToList();
				definition.UnsupportedItems = (from value in definition.UnsupportedItems?.Select((string value) => (value ?? "").Trim())
					where value.Length > 0
					select value).Distinct<string>(StringComparer.OrdinalIgnoreCase).ToList();
			}
		}

		private static void FinalizeNormalizedEntry(LocationConfigurationEntry entry)
		{
			entry.RuleId = BuildRuleId(entry);
		}

		private static string BuildRuleId(LocationConfigurationEntry entry)
		{
			LocationConfigurationEntry entry2 = new LocationConfigurationEntry
			{
				Prefab = entry.Prefab,
				Enabled = true,
				Conditions = entry.Conditions,
				OfferingBowl = entry.OfferingBowl,
				ItemStands = entry.ItemStands,
				Vegvisirs = entry.Vegvisirs
			};
			return entry.Prefab + ":" + NetworkPayloadSyncSupport.ComputeLocationEntrySignature(entry2);
		}

		private static void StripRedundantLocationComponentConditions(LocationConfigurationEntry entry, string source)
		{
			StripRedundantLocationFilter(entry.Prefab, "conditions", entry.Conditions, source);
		}

		private static void StripRedundantLocationFilter(string prefabName, string componentName, ConditionsDefinition? conditions, string source)
		{
			if (conditions?.Locations != null && conditions.Locations.Count != 0)
			{
				conditions.Locations = null;
				string text = (string.IsNullOrWhiteSpace(prefabName) ? "(missing prefab)" : prefabName);
				string item = source + "|" + text + "|" + componentName;
				if (RedundantLocationConditionWarnings.Add(item))
				{
					DropNSpawnPlugin.DropNSpawnLogger.LogWarning((object)("Entry '" + text + "' in '" + source + "' uses '" + componentName + ".conditions.locations', but " + componentName + " is already scoped by the parent location prefab. This filter is ignored."));
				}
			}
		}

		private static bool HasOverride(LocationConfigurationEntry entry)
		{
			return HasOfferingBowlOverride(entry.OfferingBowl) || HasItemStandOverride(entry.ItemStands) || HasVegvisirOverride(entry.Vegvisirs);
		}

		private static bool HasOfferingBowlOverride(LocationOfferingBowlDefinition? definition)
		{
			if (definition == null)
			{
				return false;
			}
			int result;
			if (definition.Name == null && definition.UseItemText == null && definition.UsedAltarText == null && definition.CantOfferText == null && definition.WrongOfferText == null && definition.IncompleteOfferText == null && definition.BossItem == null && !definition.BossItems.HasValue && definition.BossPrefab == null && definition.ItemPrefab == null && definition.SetGlobalKey == null && !definition.RenderSpawnAreaGizmos.HasValue && !definition.AlertOnSpawn.HasValue && !definition.SpawnBossDelay.HasValue)
			{
				FloatRangeDefinition? spawnBossDistance = definition.SpawnBossDistance;
				if ((spawnBossDistance == null || !spawnBossDistance.HasValues()) && !definition.SpawnBossMaxDistance.HasValue && !definition.SpawnBossMinDistance.HasValue && !definition.SpawnBossMaxYDistance.HasValue && !definition.GetSolidHeightMargin.HasValue && !definition.EnableSolidHeightCheck.HasValue && !definition.SpawnPointClearingRadius.HasValue && !definition.SpawnYOffset.HasValue && !definition.UseItemStands.HasValue && definition.ItemStandPrefix == null && !definition.ItemStandMaxRange.HasValue && !definition.RespawnMinutes.HasValue && definition.Data == null && definition.Fields == null && definition.Objects == null)
				{
					result = (HasCllcEffectOverride(definition.CllcInfusion, definition.CllcEffect, definition.CllcBossEffect) ? 1 : 0);
					goto IL_01d3;
				}
			}
			result = 1;
			goto IL_01d3;
			IL_01d3:
			return (byte)result != 0;
		}

		private static bool HasClientVisibleOfferingBowlOverride(LocationOfferingBowlDefinition? definition)
		{
			if (definition == null)
			{
				return false;
			}
			return definition.Name != null || definition.UseItemText != null || definition.UsedAltarText != null || definition.CantOfferText != null || definition.WrongOfferText != null || definition.IncompleteOfferText != null || definition.BossItem != null || definition.BossItems.HasValue || definition.BossPrefab != null || definition.ItemPrefab != null || definition.RenderSpawnAreaGizmos.HasValue || definition.AlertOnSpawn.HasValue || definition.UseItemStands.HasValue || definition.ItemStandPrefix != null || definition.ItemStandMaxRange.HasValue || definition.RespawnMinutes.HasValue || HasCllcEffectOverride(definition.CllcInfusion, definition.CllcEffect, definition.CllcBossEffect);
		}

		private static bool HasCllcEffectOverride(string? infusion, string? effect, string? bossEffect)
		{
			return !string.IsNullOrWhiteSpace(infusion) || !string.IsNullOrWhiteSpace(effect) || !string.IsNullOrWhiteSpace(bossEffect);
		}

		private static CllcDefinition? BuildRuntimeCllcDefinition(string? infusion, string? effect, string? bossEffect)
		{
			if (!HasCllcEffectOverride(infusion, effect, bossEffect))
			{
				return null;
			}
			return new CllcDefinition
			{
				Infusion = infusion,
				ExtraEffect = effect,
				BossAffix = bossEffect
			};
		}

		private static bool HasVegvisirOverride(List<LocationVegvisirDefinition>? definitions)
		{
			return definitions?.Any(HasVegvisirOverride) ?? false;
		}

		private static bool HasVegvisirOverride(LocationVegvisirDefinition? definition)
		{
			if (definition == null)
			{
				return false;
			}
			return definition.Name != null || definition.UseText != null || definition.HoverName != null || definition.SetsGlobalKey != null || definition.SetsPlayerKey != null || definition.Locations != null;
		}

		private static bool HasItemStandOverride(List<LocationItemStandDefinition>? definitions)
		{
			return definitions?.Any(HasItemStandOverride) ?? false;
		}

		private static bool HasLooseItemStandOverride(List<LocationItemStandDefinition>? definitions)
		{
			return definitions?.Any(HasLooseItemStandOverride) ?? false;
		}

		private static bool HasItemStandOverride(LocationItemStandDefinition? definition)
		{
			if (definition == null)
			{
				return false;
			}
			return definition.Name != null || definition.CanBeRemoved.HasValue || definition.AutoAttach.HasValue || definition.OrientationType != null || definition.SupportedTypes != null || definition.SupportedItems != null || definition.UnsupportedItems != null || definition.PowerActivationDelay.HasValue || definition.GuardianPower != null;
		}

		private static bool HasLooseItemStandOverride(LocationItemStandDefinition? definition)
		{
			return HasItemStandOverride(definition);
		}

		private static bool HasConditions(ConditionsDefinition? conditions)
		{
			return DropConditionEvaluator.HasConditions(conditions);
		}

		[IteratorStateMachine(typeof(<EnumerateOverrideConfigurationPaths>d__131))]
		private static IEnumerable<string> EnumerateOverrideConfigurationPaths()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <EnumerateOverrideConfigurationPaths>d__131(-2);
		}

		[IteratorStateMachine(typeof(<EnumerateSupplementalOverrideConfigurationPaths>d__132))]
		private static IEnumerable<string> EnumerateSupplementalOverrideConfigurationPaths()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <EnumerateSupplementalOverrideConfigurationPaths>d__132(-2);
		}

		private static bool IsOverrideConfigurationFileName(string fileName)
		{
			if (string.IsNullOrWhiteSpace(fileName))
			{
				return false;
			}
			return fileName.Equals(DropNSpawnPlugin.GetYamlDomainFilePrefix("location") + ".yml", StringComparison.OrdinalIgnoreCase) || fileName.Equals(DropNSpawnPlugin.GetYamlDomainFilePrefix("location") + ".yaml", StringComparison.OrdinalIgnoreCase) || (fileName.StartsWith(DropNSpawnPlugin.GetYamlDomainSupplementalPrefix("location"), StringComparison.OrdinalIgnoreCase) && (fileName.EndsWith(".yml", StringComparison.OrdinalIgnoreCase) || fileName.EndsWith(".yaml", StringComparison.OrdinalIgnoreCase)));
		}

		private static void CaptureSnapshotsIfNeeded()
		{
			if (_snapshotsCaptured || (Object)(object)ZoneSystem.instance == (Object)null)
			{
				return;
			}
			foreach (ZoneLocation location in ZoneSystem.instance.m_locations)
			{
				CaptureSnapshot(location);
			}
			_snapshotsCaptured = true;
			DropNSpawnPlugin.DropNSpawnLogger.LogInfo((object)$"Captured {Snapshots.Count} location snapshot(s).");
		}

		private static void ResetReferenceSnapshots()
		{
			Snapshots.Clear();
			SnapshotsByPrefab.Clear();
			DuplicateComponentWarnings.Clear();
			_snapshotsCaptured = false;
		}

		private static void ResetRuntimeState(bool preserveLiveRegistries)
		{
			ClearQueuedReconcileState();
			CatalogsByPrefab.Clear();
			LiveLocationSnapshots.Clear();
			PendingOfferingBowlNearbyCharacterIds.Clear();
			LooseItemStandSnapshots.Clear();
			TrackedLooseItemStandPrefabs.Clear();
			LooseItemStandAuthoredPathsByInstance.Clear();
			if (!preserveLiveRegistries)
			{
				LiveLocationsByPrefab.Clear();
				LiveLocationPrefabsByInstance.Clear();
			}
		}

		private static void ClearQueuedReconcileState()
		{
			_reconcileQueueEpoch++;
			PendingLocationReconciles.Clear();
			PendingLocationReconcileIds.Clear();
			SuppressedQueuedLocationReconciles.Clear();
			PendingLocationRootReconciles.Clear();
			PendingLocationRootReconcileIds.Clear();
			PendingLooseOfferingBowlOverrides.Clear();
			PendingLooseOfferingBowlOverrideIds.Clear();
		}

		private static void RefreshSnapshots()
		{
			ResetReferenceSnapshots();
			CaptureSnapshotsIfNeeded();
		}

		private static void CaptureSnapshot(ZoneLocation location)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if (!location.m_prefab.IsValid)
			{
				return;
			}
			string text = (location.m_prefab.Name ?? "").Trim();
			if (text.Length == 0 || SnapshotsByPrefab.ContainsKey(text))
			{
				return;
			}
			location.m_prefab.Load();
			GameObject rootPrefab = location.m_prefab.Asset;
			if ((Object)(object)rootPrefab == (Object)null)
			{
				return;
			}
			List<OfferingBowl> list = new List<OfferingBowl>();
			List<ItemStand> list2 = new List<ItemStand>();
			List<Vegvisir> list3 = new List<Vegvisir>();
			CollectLocationRuntimeComponents(rootPrefab.transform, list, list2, list3);
			OfferingBowl[] array = list.ToArray();
			ItemStand[] array2 = list2.ToArray();
			Vegvisir[] array3 = list3.ToArray();
			if (array.Length != 0 || array2.Length != 0 || array3.Length != 0)
			{
				WarnDuplicateComponent(text, "OfferingBowl", array.Length);
				LocationSnapshot locationSnapshot = new LocationSnapshot
				{
					Prefab = text,
					OfferingBowl = ((array.Length != 0) ? CaptureOfferingBowlSnapshot(array[0]) : null),
					ItemStands = array2.Select((ItemStand itemStand) => CapturePathScopedItemStandSnapshot(rootPrefab.transform, itemStand)).OrderBy<PathScopedItemStandSnapshot, string>((PathScopedItemStandSnapshot itemStand) => itemStand.Path, StringComparer.Ordinal).ToList(),
					Vegvisirs = array3.Select((Vegvisir vegvisir) => CaptureVegvisirSnapshot(rootPrefab.transform, vegvisir)).OrderBy<PathScopedVegvisirSnapshot, string>((PathScopedVegvisirSnapshot vegvisir) => vegvisir.Path, StringComparer.Ordinal).ToList()
				};
				Snapshots.Add(locationSnapshot);
				SnapshotsByPrefab[text] = locationSnapshot;
			}
		}

		private static void WarnDuplicateComponent(string prefabName, string componentName, int count)
		{
			if (count > 1)
			{
				string item = prefabName + "@" + componentName;
				if