Decompiled source of DropNSpawn v1.4.11

DropNSpawn.dll

Decompiled 12 hours ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.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 HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using ServerSync;
using SoftReferenceableAssets;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.ObjectPool;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.RepresentationModel;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Callbacks;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("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.4.11")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.4.11.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
	[CompilerGenerated]
	[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
	{
		private readonly string <Name>k__BackingField;

		public string Name => <Name>k__BackingField;

		public ExtensionMarkerAttribute(string name)
		{
			<Name>k__BackingField = name;
		}
	}
}
namespace LocalizationManager
{
	[PublicAPI]
	public class Localizer
	{
		private static readonly Action<Localization, string, string> AddWord;

		private static readonly FieldRef<Localization, Dictionary<string, string>> Translations;

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

		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()));
			}
			AddWord(localization, key, text);
		}

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

		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 (!Translations.Invoke(target).ContainsKey(key))
					{
						dictionary[key] = text;
						AddWord(target, 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Expected O, but got Unknown
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Expected O, but got Unknown
			AddWord = AccessTools.MethodDelegate<Action<Localization, string, string>>(AccessTools.Method(typeof(Localization), "AddWord", new Type[2]
			{
				typeof(string),
				typeof(string)
			}, (Type[])null), (object)null, true);
			Translations = AccessTools.FieldRefAccess<Localization, Dictionary<string, string>>("m_translations");
			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)
		{
			using MemoryStream memoryStream = new MemoryStream();
			if ((object)containingAssembly == null)
			{
				containingAssembly = Assembly.GetCallingAssembly();
			}
			string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal));
			if (text != null)
			{
				containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream);
			}
			return (memoryStream.Length == 0L) ? null : memoryStream.ToArray();
		}
	}
	public static class LocalizationManagerVersion
	{
		public const string Version = "1.4.1";
	}
}
namespace DropNSpawn
{
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class ZNetSceneAwakePatch
	{
		private static void Postfix()
		{
			DropNSpawnPlugin.QueueGameDataRefresh(DropNSpawnPlugin.ReloadDomain.All, "ZNetScene.Awake");
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	internal static class ObjectDBAwakePatch
	{
		private static void Postfix()
		{
			DropNSpawnPlugin.QueueGameDataRefresh(DropNSpawnPlugin.ReloadDomain.All, "ObjectDB.Awake");
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
	internal static class ObjectDBCopyOtherDBPatch
	{
		private static void Postfix()
		{
			DropNSpawnPlugin.QueueGameDataRefresh(DropNSpawnPlugin.ReloadDomain.All, "ObjectDB.CopyOtherDB");
		}
	}
	[HarmonyPatch(typeof(ZNet), "Shutdown")]
	internal static class ZNetShutdownPatch
	{
		private static void Prefix()
		{
			CharacterDropManager.ResetWorldRuntimeState();
			DungeonSpawnManager.ResetWorld();
		}
	}
	[HarmonyPatch(typeof(ZoneSystem), "Start")]
	internal static class ZoneSystemStartPatch
	{
		private static void Postfix()
		{
			DropNSpawnPlugin.QueueGameDataRefresh(DropNSpawnPlugin.ReloadDomain.SpawnSystem, "ZoneSystem.Start");
		}
	}
	[HarmonyPatch(typeof(RandEventSystem), "Awake")]
	internal static class RandEventSystemAwakePatch
	{
		private static void Postfix()
		{
			EventManager.ApplyGlobalEventSettings();
		}
	}
	[HarmonyPatch(typeof(RandEventSystem), "Start")]
	internal static class RandEventSystemStartPatch
	{
		private static void Postfix()
		{
			EventManager.ApplyGlobalEventSettings();
		}
	}
	[HarmonyPatch(typeof(ZoneSystem), "Start")]
	internal static class ZoneSystemStartEventPatch
	{
		[HarmonyPriority(0)]
		private static void Postfix()
		{
			EventManager.NotifyGameDataReady("ZoneSystem.Start");
		}
	}
	[HarmonyPatch(typeof(RandEventSystem), "OnDestroy")]
	internal static class RandEventSystemOnDestroyPatch
	{
		private static void Prefix()
		{
			EventManager.OnRandEventSystemDestroyed();
		}
	}
	[HarmonyPatch(typeof(RandEventSystem), "FixedUpdate")]
	internal static class RandEventSystemFixedUpdatePatch
	{
		private static bool Prefix(RandEventSystem __instance)
		{
			return !EventManager.TryRunMultipleEventsFixedUpdate(__instance);
		}
	}
	[HarmonyPatch(typeof(RandEventSystem), "SetRandomEvent")]
	internal static class RandEventSystemSetRandomEventPatch
	{
		private static bool Prefix(RandEventSystem __instance, RandomEvent ev, Vector3 pos)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return !EventManager.TryHandleMultipleSetRandomEvent(__instance, ev, pos);
		}
	}
	[HarmonyPatch(typeof(RandEventSystem), "SendCurrentRandomEvent")]
	internal static class RandEventSystemSendCurrentRandomEventPatch
	{
		private static bool Prefix(RandEventSystem __instance)
		{
			return !EventManager.TrySendMultipleCurrentRandomEvent(__instance);
		}
	}
	[HarmonyPatch(typeof(RandEventSystem), "UpdateRandomEvent")]
	internal static class RandEventSystemUpdateRandomEventPatch
	{
		private static bool Prefix(RandEventSystem __instance, float dt)
		{
			return !EventManager.TryRunCheckPerPlayerRandomUpdate(__instance, dt);
		}
	}
	[HarmonyPatch(typeof(RandomEvent), "Clone")]
	internal static class RandomEventClonePatch
	{
		private static void Postfix(RandomEvent __instance, RandomEvent __result)
		{
			EventManager.CopySpawnPayloads(__instance, __result);
		}
	}
	[HarmonyPatch(typeof(RandEventSystem), "CheckBase")]
	internal static class RandEventSystemCheckBasePatch
	{
		private static bool Prefix(RandomEvent ev, PlayerEventData player, ref bool __result)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if (!EventManager.TryCheckBase(ev, player, out var result))
			{
				return true;
			}
			__result = result;
			return false;
		}
	}
	[HarmonyPatch(typeof(RandEventSystem), "InValidBiome")]
	internal static class RandEventSystemInValidBiomePatch
	{
		private static void Postfix(RandomEvent ev, Vector3 point, ref bool __result)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			__result = EventManager.PassesExtraChecks(ev, point, __result);
		}
	}
	[HarmonyPatch(typeof(RandomEvent), "OnStart")]
	internal static class RandomEventOnStartPatch
	{
		private static void Postfix(RandomEvent __instance)
		{
			EventManager.RunStartCommands(__instance);
		}
	}
	[HarmonyPatch(typeof(RandomEvent), "OnStop")]
	internal static class RandomEventOnStopPatch
	{
		private static void Postfix(RandomEvent __instance)
		{
			EventManager.RunEndCommands(__instance);
		}
	}
	[HarmonyPatch(typeof(Location), "OnDestroy")]
	internal static class LocationOnDestroyPatch
	{
		private static void Prefix(Location __instance)
		{
			SpawnerManager.UntrackLocationInstanceProvenance(__instance);
		}
	}
	[HarmonyPatch(typeof(LocationProxy), "SpawnLocation")]
	internal static class LocationProxySpawnLocationPatch
	{
		private static readonly FieldRef<LocationProxy, GameObject> InstanceRef = AccessTools.FieldRefAccess<LocationProxy, GameObject>("m_instance");

		private static void Postfix(LocationProxy __instance, bool __result)
		{
			if (__result && PluginSettingsFacade.IsSpawnerDomainEnabled() && !DropNSpawnPlugin.IsGameDataRefreshDeferred(DropNSpawnPlugin.ReloadDomain.Spawner))
			{
				GameObject spawnedRoot = (((Object)(object)__instance != (Object)null) ? InstanceRef.Invoke(__instance) : null);
				SpawnerManager.RecordSpawnedLocationProxyProvenance(__instance, spawnedRoot);
			}
		}
	}
	internal readonly struct TemporaryFieldOverrideState<T> where T : class
	{
		internal bool Applied { get; }

		internal T? Previous { get; }

		internal TemporaryFieldOverrideState(T? previous)
		{
			Applied = true;
			Previous = previous;
		}
	}
	[HarmonyPatch(typeof(Piece), "Awake")]
	internal static class PieceAwakePatch
	{
		private static void Postfix(Piece __instance)
		{
			ObjectDropManager.QueueObjectInstanceReconcile(((Component)__instance).gameObject, ObjectDropManager.LiveObjectComponentKind.Piece);
		}
	}
	[HarmonyPatch(typeof(Piece), "SetCreator")]
	internal static class PieceSetCreatorPatch
	{
		private static void Postfix(Piece __instance)
		{
			if (PluginSettingsFacade.IsObjectDomainEnabled())
			{
				ObjectDropManager.ReconcilePieceInstance(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Piece), "OnDestroy")]
	internal static class PieceOnDestroyPatch
	{
		private static void Prefix(Piece __instance)
		{
			ObjectDropManager.UntrackObjectInstance(((Component)__instance).gameObject);
		}
	}
	[HarmonyPatch(typeof(ZNetView), "OnDestroy")]
	internal static class ZNetViewOnDestroyPatch
	{
		private static void Prefix(ZNetView __instance)
		{
			ObjectDropManager.UntrackObjectInstance(((Component)__instance).gameObject);
			SpawnArea component = ((Component)__instance).GetComponent<SpawnArea>();
			if ((Object)(object)component != (Object)null)
			{
				SpawnerManager.UntrackSpawnAreaInstance(component);
			}
		}
	}
	[HarmonyPatch(typeof(Destructible), "Awake")]
	internal static class DestructibleAwakePatch
	{
		private static void Postfix(Destructible __instance)
		{
			ObjectDropManager.QueueObjectInstanceReconcile(((Component)__instance).gameObject, ObjectDropManager.LiveObjectComponentKind.Destructible);
		}
	}
	[HarmonyPatch(typeof(Destructible), "GetDestructibleType")]
	internal static class DestructibleGetDestructibleTypePatch
	{
		private static void Prefix(Destructible __instance)
		{
			if (PluginSettingsFacade.IsObjectDomainEnabled())
			{
				ObjectDropManager.ApplyLazyDestructibleTypeIfNeeded(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Destructible), "RPC_Damage")]
	internal static class DestructibleDamagePatch
	{
		private static void Prefix(Destructible __instance)
		{
			if (PluginSettingsFacade.IsObjectDomainEnabled())
			{
				ObjectDropManager.ApplyLazyDestructibleScalarsIfNeeded(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Destructible), "Destroy")]
	internal static class DestructibleDestroyPatch
	{
		private static void Prefix(Destructible __instance, out TemporaryFieldOverrideState<GameObject> __state)
		{
			__state = default(TemporaryFieldOverrideState<GameObject>);
			if (PluginSettingsFacade.IsObjectDomainEnabled() && ObjectDropManager.TryOverrideConditionalDestructibleSpawnWhenDestroyed(__instance, out GameObject previous))
			{
				__state = new TemporaryFieldOverrideState<GameObject>(previous);
			}
		}

		private static void Postfix(Destructible __instance, TemporaryFieldOverrideState<GameObject> __state)
		{
			if (__state.Applied)
			{
				__instance.m_spawnWhenDestroyed = __state.Previous;
			}
		}

		private static Exception? Finalizer(Destructible __instance, TemporaryFieldOverrideState<GameObject> __state, Exception? __exception)
		{
			if (__exception != null && __state.Applied)
			{
				__instance.m_spawnWhenDestroyed = __state.Previous;
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(DropOnDestroyed), "Awake")]
	internal static class DropOnDestroyedAwakePatch
	{
		private static void Postfix(DropOnDestroyed __instance)
		{
			ObjectDropManager.QueueObjectInstanceReconcile(((Component)__instance).gameObject, ObjectDropManager.LiveObjectComponentKind.DropOnDestroyed);
		}
	}
	[HarmonyPatch(typeof(Container), "Awake")]
	internal static class ContainerAwakePatch
	{
		private static void Postfix(Container __instance)
		{
			ObjectDropManager.QueueObjectInstanceReconcile(((Component)__instance).gameObject, ObjectDropManager.LiveObjectComponentKind.Container);
		}
	}
	[HarmonyPatch(typeof(Pickable), "Awake")]
	internal static class PickableAwakePatch
	{
		private static void Postfix(Pickable __instance)
		{
			if (!PluginSettingsFacade.IsObjectDomainEnabled())
			{
				ObjectDropManager.TrackObjectInstance(((Component)__instance).gameObject);
			}
			else
			{
				ObjectDropManager.QueueObjectInstanceReconcile(((Component)__instance).gameObject, ObjectDropManager.LiveObjectComponentKind.Pickable);
			}
		}
	}
	[HarmonyPatch(typeof(PickableItem), "Awake")]
	internal static class PickableItemAwakePatch
	{
		private static void Postfix(PickableItem __instance)
		{
			if (!PluginSettingsFacade.IsObjectDomainEnabled())
			{
				ObjectDropManager.TrackObjectInstance(((Component)__instance).gameObject);
			}
			else
			{
				ObjectDropManager.QueueObjectInstanceReconcile(((Component)__instance).gameObject, ObjectDropManager.LiveObjectComponentKind.PickableItem);
			}
		}
	}
	[HarmonyPatch(typeof(Fish), "Awake")]
	internal static class FishAwakePatch
	{
		private static void Postfix(Fish __instance)
		{
			ObjectDropManager.QueueObjectInstanceReconcile(((Component)__instance).gameObject, ObjectDropManager.LiveObjectComponentKind.Fish);
		}
	}
	[HarmonyPatch(typeof(Container), "AddDefaultItems")]
	internal static class ContainerAddDefaultItemsPatch
	{
		private static void Prefix(Container __instance, out TemporaryFieldOverrideState<DropTable> __state)
		{
			__state = default(TemporaryFieldOverrideState<DropTable>);
			if (PluginSettingsFacade.IsObjectDomainEnabled() && ObjectDropManager.TryOverrideContainerDrops(__instance, out DropTable previous))
			{
				__state = new TemporaryFieldOverrideState<DropTable>(previous);
			}
		}

		private static void Postfix(Container __instance, TemporaryFieldOverrideState<DropTable> __state)
		{
			if (__state.Applied)
			{
				__instance.m_defaultItems = __state.Previous;
			}
		}

		private static Exception? Finalizer(Container __instance, TemporaryFieldOverrideState<DropTable> __state, Exception? __exception)
		{
			if (__exception != null && __state.Applied)
			{
				__instance.m_defaultItems = __state.Previous;
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(DropOnDestroyed), "OnDestroyed")]
	internal static class DropOnDestroyedPatch
	{
		private static void Prefix(DropOnDestroyed __instance, out TemporaryFieldOverrideState<DropTable> __state)
		{
			__state = default(TemporaryFieldOverrideState<DropTable>);
			if (PluginSettingsFacade.IsObjectDomainEnabled() && ObjectDropManager.TryOverrideConditionalDropOnDestroyed(__instance, out DropTable previous))
			{
				__state = new TemporaryFieldOverrideState<DropTable>(previous);
			}
		}

		private static void Postfix(DropOnDestroyed __instance, TemporaryFieldOverrideState<DropTable> __state)
		{
			if (__state.Applied)
			{
				__instance.m_dropWhenDestroyed = __state.Previous;
			}
		}

		private static Exception? Finalizer(DropOnDestroyed __instance, TemporaryFieldOverrideState<DropTable> __state, Exception? __exception)
		{
			if (__exception != null && __state.Applied)
			{
				__instance.m_dropWhenDestroyed = __state.Previous;
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(MineRock), "RPC_Hit")]
	internal static class MineRockHitPatch
	{
		private static void Prefix(MineRock __instance, out TemporaryFieldOverrideState<DropTable> __state)
		{
			__state = default(TemporaryFieldOverrideState<DropTable>);
			if (PluginSettingsFacade.IsObjectDomainEnabled())
			{
				ObjectDropManager.ApplyLazyMineRockScalarsIfNeeded(__instance);
				if (ObjectDropManager.TryOverrideConditionalMineRockDrops(__instance, out DropTable previous))
				{
					__state = new TemporaryFieldOverrideState<DropTable>(previous);
				}
			}
		}

		private static void Postfix(MineRock __instance, TemporaryFieldOverrideState<DropTable> __state)
		{
			if (__state.Applied)
			{
				__instance.m_dropItems = __state.Previous;
			}
		}

		private static Exception? Finalizer(MineRock __instance, TemporaryFieldOverrideState<DropTable> __state, Exception? __exception)
		{
			if (__exception != null && __state.Applied)
			{
				__instance.m_dropItems = __state.Previous;
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(MineRock), "Start")]
	internal static class MineRockStartPatch
	{
		private static void Postfix(MineRock __instance)
		{
			ObjectDropManager.QueueObjectInstanceReconcile(((Component)__instance).gameObject, ObjectDropManager.LiveObjectComponentKind.MineRock);
		}
	}
	[HarmonyPatch(typeof(MineRock5), "RPC_Damage")]
	internal static class MineRock5DamagePatch
	{
		private static void Prefix(MineRock5 __instance, out TemporaryFieldOverrideState<DropTable> __state)
		{
			__state = default(TemporaryFieldOverrideState<DropTable>);
			if (PluginSettingsFacade.IsObjectDomainEnabled())
			{
				ObjectDropManager.ApplyLazyMineRock5ScalarsIfNeeded(__instance);
				if (ObjectDropManager.TryOverrideConditionalMineRock5Drops(__instance, out DropTable previous))
				{
					__state = new TemporaryFieldOverrideState<DropTable>(previous);
				}
			}
		}

		private static void Postfix(MineRock5 __instance, TemporaryFieldOverrideState<DropTable> __state)
		{
			if (__state.Applied)
			{
				__instance.m_dropItems = __state.Previous;
			}
		}

		private static Exception? Finalizer(MineRock5 __instance, TemporaryFieldOverrideState<DropTable> __state, Exception? __exception)
		{
			if (__exception != null && __state.Applied)
			{
				__instance.m_dropItems = __state.Previous;
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(MineRock5), "Awake")]
	internal static class MineRock5AwakePatch
	{
		private static void Postfix(MineRock5 __instance)
		{
			ObjectDropManager.QueueObjectInstanceReconcile(((Component)__instance).gameObject, ObjectDropManager.LiveObjectComponentKind.MineRock5);
		}
	}
	[HarmonyPatch(typeof(TreeBase), "RPC_Damage")]
	internal static class TreeBaseDamagePatch
	{
		private static void Prefix(TreeBase __instance, out TemporaryFieldOverrideState<DropTable> __state)
		{
			__state = default(TemporaryFieldOverrideState<DropTable>);
			if (PluginSettingsFacade.IsObjectDomainEnabled())
			{
				ObjectDropManager.ApplyLazyTreeBaseScalarsIfNeeded(__instance);
				if (ObjectDropManager.TryOverrideConditionalTreeBaseDrops(__instance, out DropTable previous))
				{
					__state = new TemporaryFieldOverrideState<DropTable>(previous);
				}
			}
		}

		private static void Postfix(TreeBase __instance, TemporaryFieldOverrideState<DropTable> __state)
		{
			if (__state.Applied)
			{
				__instance.m_dropWhenDestroyed = __state.Previous;
			}
		}

		private static Exception? Finalizer(TreeBase __instance, TemporaryFieldOverrideState<DropTable> __state, Exception? __exception)
		{
			if (__exception != null && __state.Applied)
			{
				__instance.m_dropWhenDestroyed = __state.Previous;
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(TreeBase), "Awake")]
	internal static class TreeBaseAwakePatch
	{
		private static void Postfix(TreeBase __instance)
		{
			ObjectDropManager.QueueObjectInstanceReconcile(((Component)__instance).gameObject, ObjectDropManager.LiveObjectComponentKind.TreeBase);
		}
	}
	[HarmonyPatch(typeof(TreeLog), "Destroy")]
	internal static class TreeLogDestroyPatch
	{
		private static void Prefix(TreeLog __instance, out TemporaryFieldOverrideState<DropTable> __state)
		{
			__state = default(TemporaryFieldOverrideState<DropTable>);
			if (PluginSettingsFacade.IsObjectDomainEnabled() && ObjectDropManager.TryOverrideConditionalTreeLogDrops(__instance, out DropTable previous))
			{
				__state = new TemporaryFieldOverrideState<DropTable>(previous);
			}
		}

		private static void Postfix(TreeLog __instance, TemporaryFieldOverrideState<DropTable> __state)
		{
			if (__state.Applied)
			{
				__instance.m_dropWhenDestroyed = __state.Previous;
			}
		}

		private static Exception? Finalizer(TreeLog __instance, TemporaryFieldOverrideState<DropTable> __state, Exception? __exception)
		{
			if (__exception != null && __state.Applied)
			{
				__instance.m_dropWhenDestroyed = __state.Previous;
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(TreeLog), "RPC_Damage")]
	internal static class TreeLogDamagePatch
	{
		private static void Prefix(TreeLog __instance)
		{
			if (PluginSettingsFacade.IsObjectDomainEnabled())
			{
				ObjectDropManager.ApplyLazyTreeLogScalarsIfNeeded(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(TreeLog), "Awake")]
	internal static class TreeLogAwakePatch
	{
		private static void Postfix(TreeLog __instance)
		{
			ObjectDropManager.QueueObjectInstanceReconcile(((Component)__instance).gameObject, ObjectDropManager.LiveObjectComponentKind.TreeLog);
		}
	}
	[HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")]
	internal static class CharacterDropGenerateDropListPatch
	{
		private readonly struct State
		{
			internal List<Drop>? PreviousDrops { get; }

			internal bool HasOnePerPlayerScope { get; }

			internal IReadOnlyList<Drop>? AmountSourceDrops { get; }

			internal State(List<Drop>? previousDrops, bool hasOnePerPlayerScope, IReadOnlyList<Drop>? amountSourceDrops)
			{
				PreviousDrops = previousDrops;
				HasOnePerPlayerScope = hasOnePerPlayerScope;
				AmountSourceDrops = amountSourceDrops;
			}
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return CharacterLootPatchInstructions.TryRewrite(instructions, ref CharacterDropManager.DropRowTrackingAvailable, delegate(List<CodeInstruction> input)
			{
				int num = CharacterLootPatchInstructions.FindSingleCall(input, CharacterLootPatchInstructions.AddDrop);
				if (num < 4 || input[num - 3].opcode != OpCodes.Ldfld || !object.Equals(input[num - 3].operand, AccessTools.Field(typeof(Drop), "m_prefab")))
				{
					throw new InvalidOperationException("CharacterDrop successful-row contract changed; refusing partial loot scaling.");
				}
				CodeInstruction val = CharacterLootPatchInstructions.LoadLocal(input[num - 4], typeof(Drop), __originalMethod);
				CharacterLootPatchInstructions.ReplaceCall(input, num, (CodeInstruction[])(object)new CodeInstruction[1] { val }, AccessTools.Method(typeof(CharacterDropManager), "RecordGeneratedDrop", (Type[])null, (Type[])null));
				return input;
			});
		}

		private static void Prefix(CharacterDrop __instance, out State __state)
		{
			__state = new State(null, hasOnePerPlayerScope: false, null);
			bool flag = PluginSettingsFacade.IsCharacterDomainEnabled();
			if (flag || CharacterDropManager.IsGlobalCharacterLootLevelScalingEnabled() || PluginSettingsFacade.IsLinearChanceOnlyDropScalingEnabled())
			{
				List<Drop> list = (flag ? CharacterDropManager.OverrideConditionalDrops(__instance) : null);
				__state = new State(list, hasOnePerPlayerScope: false, null);
				IReadOnlyList<Drop> sourceDrops;
				List<Drop> list2 = CharacterDropManager.PrepareCharacterLootScalingDrops(__instance, out sourceDrops);
				if (list == null)
				{
					list = list2;
				}
				__state = new State(list, hasOnePerPlayerScope: false, sourceDrops);
				bool hasOnePerPlayerScope = flag && CharacterDropManager.BeginOnePerPlayerNearbyPlayerScope(__instance);
				__state = new State(list, hasOnePerPlayerScope, sourceDrops);
			}
		}

		[HarmonyPriority(0)]
		private static void Postfix(CharacterDrop __instance, List<KeyValuePair<GameObject, int>> __result, State __state)
		{
			CharacterDropManager.KeepUnmatchedDropsLoose(__result);
			CharacterDropManager.ApplyGlobalCharacterLootLevelMultiplier(__instance, __result, __state.AmountSourceDrops);
			if (__state.PreviousDrops != null)
			{
				__instance.m_drops = __state.PreviousDrops;
			}
			CharacterDropKillerFilter.SuppressScopedGeneratedDrops(__instance, __result);
		}

		private static Exception? Finalizer(CharacterDrop __instance, State __state, List<KeyValuePair<GameObject, int>>? __result, Exception? __exception)
		{
			if (__state.PreviousDrops != null)
			{
				__instance.m_drops = __state.PreviousDrops;
			}
			if (__state.HasOnePerPlayerScope)
			{
				CharacterDropManager.EndOnePerPlayerNearbyPlayerScope();
			}
			if (__exception == null && __result != null)
			{
				CharacterDropManager.KeepUnmatchedDropsLoose(__result);
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(Ragdoll), "SaveLootList")]
	internal static class RagdollSaveDropPolicyPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return CharacterLootPatchInstructions.TryRewrite(instructions, ref CharacterDropManager.SaveStackPolicyAvailable, delegate(List<CodeInstruction> input)
			{
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Expected O, but got Unknown
				int index = CharacterLootPatchInstructions.FindSingleCall(input, AccessTools.Method(typeof(CharacterDrop), "GenerateDropList", (Type[])null, (Type[])null));
				CharacterLootPatchInstructions.ReplaceCall(input, index, (CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Ldarg_0, (object)null)
				}, AccessTools.Method(typeof(CharacterDropManager), "GenerateAndSaveStackPolicy", (Type[])null, (Type[])null));
				return input;
			});
		}
	}
	[HarmonyPatch(typeof(Ragdoll), "SpawnLoot")]
	internal static class RagdollLoadDropPolicyPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			return CharacterLootPatchInstructions.TryRewrite(instructions, ref CharacterDropManager.LoadStackPolicyAvailable, delegate(List<CodeInstruction> input)
			{
				CodeInstruction[] array = FindLocals("drop_hash");
				CodeInstruction[] array2 = FindLocals("drop_amount");
				if (!object.Equals(array[0].operand, array2[0].operand) || !object.Equals(array[1].operand, array2[1].operand))
				{
					throw new InvalidOperationException("Ragdoll saved rows no longer share a ZDO/index.");
				}
				int index = CharacterLootPatchInstructions.FindSingleCall(input, CharacterLootPatchInstructions.AddDrop);
				CharacterLootPatchInstructions.ReplaceCall(input, index, array, AccessTools.Method(typeof(CharacterDropManager), "RecordSavedDrop", (Type[])null, (Type[])null));
				return input;
			});
			CodeInstruction[] FindLocals(string key)
			{
				int[] array = (from pair in P_1.input.Select((CodeInstruction instruction, int index) => (instruction: instruction, index: index))
					where pair.instruction.opcode == OpCodes.Ldstr && object.Equals(pair.instruction.operand, key)
					select pair.index).ToArray();
				if (array.Length != 1 || array[0] < 1 || array[0] + 1 >= P_1.input.Count)
				{
					throw new InvalidOperationException("Ragdoll saved-row contract changed: " + key);
				}
				int num = array[0];
				return (CodeInstruction[])(object)new CodeInstruction[2]
				{
					CharacterLootPatchInstructions.LoadLocal(P_1.input[num - 1], typeof(ZDO), __originalMethod),
					CharacterLootPatchInstructions.LoadLocal(P_1.input[num + 1], typeof(int), __originalMethod, address: true)
				};
			}
		}
	}
	internal static class CharacterLootPatchInstructions
	{
		internal static readonly MethodInfo AddDrop = AccessTools.Method(typeof(List<KeyValuePair<GameObject, int>>), "Add", (Type[])null, (Type[])null);

		internal static IEnumerable<CodeInstruction> TryRewrite(IEnumerable<CodeInstruction> instructions, ref bool available, Func<List<CodeInstruction>, List<CodeInstruction>> rewrite)
		{
			List<CodeInstruction> list = instructions.ToList();
			available = false;
			try
			{
				List<CodeInstruction> result = rewrite(((IEnumerable<CodeInstruction>)list).Select((Func<CodeInstruction, CodeInstruction>)((CodeInstruction instruction) => new CodeInstruction(instruction))).ToList());
				available = true;
				return result;
			}
			catch (InvalidOperationException ex)
			{
				ManualLogSource dropNSpawnLogger = DropNSpawnPlugin.DropNSpawnLogger;
				if (dropNSpawnLogger != null)
				{
					dropNSpawnLogger.LogWarning((object)("Loot row tracking hook unavailable; affected native amount/stack overrides are disabled, and existing loot is preserved. " + ex.Message));
				}
				return list;
			}
		}

		internal static int FindSingleCall(List<CodeInstruction> instructions, MethodInfo target)
		{
			int[] array = (from pair in instructions.Select((CodeInstruction instruction, int index) => (instruction: instruction, index: index))
				where CodeInstructionExtensions.Calls(pair.instruction, target)
				select pair.index).ToArray();
			if (array.Length != 1)
			{
				throw new InvalidOperationException("Loot row hook requires one call to " + target);
			}
			return array[0];
		}

		internal static CodeInstruction LoadLocal(CodeInstruction instruction, Type type, MethodBase method, bool address = false)
		{
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Expected O, but got Unknown
			int num;
			bool num2;
			if (!address && instruction.opcode == OpCodes.Ldloc_0)
			{
				num = 0;
			}
			else if (!address && instruction.opcode == OpCodes.Ldloc_1)
			{
				num = 1;
			}
			else if (!address && instruction.opcode == OpCodes.Ldloc_2)
			{
				num = 2;
			}
			else
			{
				if (address || !(instruction.opcode == OpCodes.Ldloc_3))
				{
					if (!address)
					{
						if (!(instruction.opcode == OpCodes.Ldloc))
						{
							num2 = instruction.opcode == OpCodes.Ldloc_S;
							goto IL_00bf;
						}
					}
					else if (!(instruction.opcode == OpCodes.Ldloca))
					{
						num2 = instruction.opcode == OpCodes.Ldloca_S;
						goto IL_00bf;
					}
					goto IL_00c1;
				}
				num = 3;
			}
			goto IL_0108;
			IL_0108:
			if (num < 0 || num >= method.GetMethodBody().LocalVariables.Count || method.GetMethodBody().LocalVariables[num].LocalType != type)
			{
				throw new InvalidOperationException("Unexpected loot local type.");
			}
			return new CodeInstruction(OpCodes.Ldloc, (object)num);
			IL_00c1:
			num = ((instruction.operand is LocalVariableInfo localVariableInfo) ? localVariableInfo.LocalIndex : ((instruction.operand is LocalBuilder localBuilder) ? localBuilder.LocalIndex : Convert.ToInt32(instruction.operand)));
			goto IL_0108;
			IL_00bf:
			if (!num2)
			{
				throw new InvalidOperationException("Unexpected loot local instruction.");
			}
			goto IL_00c1;
		}

		internal static void ReplaceCall(List<CodeInstruction> instructions, int index, CodeInstruction[] arguments, MethodInfo target)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			arguments[0].labels.AddRange(instructions[index].labels);
			arguments[0].blocks.AddRange(instructions[index].blocks);
			instructions[index] = new CodeInstruction(OpCodes.Call, (object)target);
			instructions.InsertRange(index, arguments);
		}
	}
	[HarmonyPatch(typeof(ZNet), "GetNrOfPlayers")]
	internal static class ZNetGetNrOfPlayersPatch
	{
		private static bool Prefix(ref int __result)
		{
			if (!PluginSettingsFacade.IsCharacterDomainEnabled())
			{
				return true;
			}
			if (!CharacterDropManager.TryGetScopedOnePerPlayerNearbyPlayerCount(out var playerCount))
			{
				return true;
			}
			__result = playerCount;
			return false;
		}
	}
	[HarmonyPatch(typeof(CharacterDrop), "Start")]
	internal static class CharacterDropStartPatch
	{
		private static void Postfix(CharacterDrop __instance)
		{
			if (PluginSettingsFacade.IsCharacterDomainEnabled())
			{
				CharacterDropManager.TrackCharacterDropInstance(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Character), "OnDestroy")]
	internal static class CharacterOnDestroyCharacterDropPatch
	{
		private static void Postfix(Character __instance)
		{
			CharacterDropKillerFilter.ForgetCharacter(__instance);
			CharacterDrop characterDrop = default(CharacterDrop);
			if ((Object)(object)__instance != (Object)null && ((Component)__instance).TryGetComponent<CharacterDrop>(ref characterDrop))
			{
				CharacterDropManager.UntrackCharacterDropInstance(characterDrop);
			}
		}
	}
	[HarmonyPatch(typeof(CharacterDrop), "OnDeath")]
	internal static class CharacterDropOnDeathPatch
	{
		private static bool Prefix(CharacterDrop __instance)
		{
			if (CharacterDropKillerFilter.ShouldSuppressDeathCallback(__instance))
			{
				return false;
			}
			if (!PluginSettingsFacade.IsCharacterDomainEnabled())
			{
				return true;
			}
			return !CharacterDropManager.TryHandleConfiguredDeath(__instance);
		}
	}
	[HarmonyPatch(typeof(CharacterDrop), "DropItems")]
	internal static class CharacterDropDropItemsPatch
	{
		private static void Prefix(ref List<KeyValuePair<GameObject, int>> drops, Vector3 centerPos, float dropArea, bool cheated)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (PluginSettingsFacade.IsCharacterDomainEnabled())
			{
				CharacterDropManager.ApplyGlobalDropInStack(ref drops, centerPos, dropArea, cheated);
			}
		}
	}
	[HarmonyPatch(typeof(Ragdoll), "Setup")]
	internal static class RagdollSetupMonsterInstantLootDropPatch
	{
		internal const string EpicLootGuid = "randyknapp.mods.epicloot";

		private static readonly MethodInfo SpawnLootMethod = AccessTools.Method(typeof(Ragdoll), "SpawnLoot", new Type[1] { typeof(Vector3) }, (Type[])null);

		private static readonly Action<Ragdoll, Vector3> SpawnLoot = AccessTools.MethodDelegate<Action<Ragdoll, Vector3>>(SpawnLootMethod, (object)null, true);

		private static bool _instantLootCompatible;

		[ThreadStatic]
		private static Ragdoll? _instantLootRagdoll;

		internal static void InitializeEpicLootCompatibility(Harmony harmony)
		{
			PluginInfo value;
			bool present = Chainloader.PluginInfos.TryGetValue("randyknapp.mods.epicloot", out value);
			ConfigureEpicLootCompatibility(harmony, present, (value == null) ? null : ((object)value.Instance)?.GetType().Assembly);
		}

		private static void ConfigureEpicLootCompatibility(Harmony harmony, bool present, Assembly? assembly)
		{
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Expected O, but got Unknown
			_instantLootCompatible = !present;
			if (!present)
			{
				return;
			}
			try
			{
				MethodInfo callback = assembly?.GetType("EpicLoot.Ragdoll_SpawnLoot_Patch", throwOnError: false)?.GetMethod("Postfix", BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2]
				{
					typeof(Ragdoll),
					typeof(Vector3)
				}, null);
				if (!(callback == null) && !(callback.ReturnType != typeof(void)) && !callback.ContainsGenericParameters)
				{
					Patches patchInfo = Harmony.GetPatchInfo((MethodBase)SpawnLootMethod);
					if (patchInfo != null && patchInfo.Postfixes.Any((Patch p) => p.PatchMethod == callback))
					{
						MethodInfo guard = AccessTools.DeclaredMethod(typeof(RagdollSetupMonsterInstantLootDropPatch), "EpicLootSpawnLootPrefix", (Type[])null, (Type[])null);
						Patches patchInfo2 = Harmony.GetPatchInfo((MethodBase)callback);
						if (patchInfo2 == null || !patchInfo2.Prefixes.Any((Patch p) => p.owner == harmony.Id && p.PatchMethod == guard))
						{
							harmony.Patch((MethodBase)callback, new HarmonyMethod(guard), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						}
						Patches patchInfo3 = Harmony.GetPatchInfo((MethodBase)callback);
						if (patchInfo3 == null || !patchInfo3.Prefixes.Any((Patch p) => p.owner == harmony.Id && p.PatchMethod == guard))
						{
							throw new InvalidOperationException("The EpicLoot early-loot guard was not installed.");
						}
						_instantLootCompatible = true;
						return;
					}
				}
				throw new InvalidOperationException("The registered EpicLoot Ragdoll.SpawnLoot callback could not be verified.");
			}
			catch (Exception arg)
			{
				DropNSpawnPlugin.DropNSpawnLogger.LogWarning((object)$"EpicLoot instant-loot compatibility unavailable; monster loot will use normal ragdoll timing. Settings are unchanged. {arg}");
			}
		}

		private static bool EpicLootSpawnLootPrefix(Ragdoll __0)
		{
			if (_instantLootRagdoll != null)
			{
				return _instantLootRagdoll != __0;
			}
			return true;
		}

		private static void SpawnInstantLoot(Ragdoll ragdoll, Vector3 center)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			Ragdoll instantLootRagdoll = _instantLootRagdoll;
			_instantLootRagdoll = ragdoll;
			try
			{
				SpawnLoot(ragdoll, center);
			}
			finally
			{
				_instantLootRagdoll = instantLootRagdoll;
			}
		}

		private static void Postfix(Ragdoll __instance, CharacterDrop characterDrop, ZNetView ___m_nview)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if (!_instantLootCompatible || !PluginSettingsFacade.IsMonsterInstantLootDropEnabled() || (Object)(object)characterDrop == (Object)null || !__instance.m_dropItems)
			{
				return;
			}
			if ((Object)(object)___m_nview == (Object)null || !___m_nview.IsValid() || !___m_nview.IsOwner())
			{
				return;
			}
			ZDO zDO = ___m_nview.GetZDO();
			if (zDO.GetInt(ZDOVars.s_drops, 0) > 0 && !PluginSettingsFacade.IsMonsterInstantLootDropBlacklisted(CharacterDropManager.GetPrefabName(((Component)characterDrop).gameObject)))
			{
				Vector3 center = __instance.GetAverageBodyPosition();
				if ((Object)(object)__instance.m_lootSpawnJoint != (Object)null)
				{
					center = __instance.m_lootSpawnJoint.transform.position;
				}
				SpawnInstantLoot(__instance, center);
				zDO.Set(ZDOVars.s_drops, 0, false);
			}
		}
	}
	[HarmonyPatch(typeof(ZoneSystem), "SpawnLocation", new Type[]
	{
		typeof(ZoneLocation),
		typeof(int),
		typeof(Vector3),
		typeof(Quaternion),
		typeof(SpawnMode),
		typeof(List<GameObject>),
		typeof(bool)
	})]
	[HarmonyAfter(new string[] { "expand_world_data" })]
	internal static class ZoneSystemSpawnLocationContextPatch
	{
		private sealed class SpawnLocationContextState
		{
			public bool HasContext { get; set; }
		}

		private static void Prefix(ZoneLocation location, ref SpawnLocationContextState? __state)
		{
			__state = null;
			if (PluginSettingsFacade.IsSpawnerDomainEnabled() && !DropNSpawnPlugin.IsGameDataRefreshDeferred(DropNSpawnPlugin.ReloadDomain.Spawner))
			{
				SpawnerManager.BeginLocationSpawnContext(location);
				__state = new SpawnLocationContextState
				{
					HasContext = true
				};
			}
		}

		private static void Postfix(GameObject __result, SpawnLocationContextState? __state)
		{
			if (__state != null && __state.HasContext)
			{
				SpawnerManager.RecordSpawnedLocationRootProvenance(__result);
			}
		}

		private static void Finalizer(SpawnLocationContextState? __state)
		{
			if (__state != null && __state.HasContext)
			{
				SpawnerManager.EndLocationSpawnContext();
			}
		}
	}
	[HarmonyPatch(typeof(DungeonGenerator), "Generate", new Type[] { typeof(SpawnMode) })]
	internal static class DungeonGeneratorGenerateContextPatch
	{
		private static void Prefix(DungeonGenerator __instance, ref bool __state)
		{
			__state = false;
			if (PluginSettingsFacade.IsSpawnerDomainEnabled() && !DropNSpawnPlugin.IsGameDataRefreshDeferred(DropNSpawnPlugin.ReloadDomain.Spawner))
			{
				__state = SpawnerManager.TryBeginDerivedLocationSpawnContext(__instance);
			}
		}

		private static void Finalizer(bool __state)
		{
			if (__state)
			{
				SpawnerManager.EndLocationSpawnContext();
			}
		}
	}
	[HarmonyPatch(typeof(DungeonGenerator), "Spawn")]
	internal static class DungeonGeneratorSpawnContextPatch
	{
		private static void Prefix(DungeonGenerator __instance, ref bool __state)
		{
			__state = false;
			if (PluginSettingsFacade.IsSpawnerDomainEnabled() && !DropNSpawnPlugin.IsGameDataRefreshDeferred(DropNSpawnPlugin.ReloadDomain.Spawner))
			{
				__state = SpawnerManager.TryBeginDerivedLocationSpawnContext(__instance);
			}
		}

		private static void Finalizer(bool __state)
		{
			if (__state)
			{
				SpawnerManager.EndLocationSpawnContext();
			}
		}
	}
	[HarmonyPatch(typeof(SpawnArea), "Awake")]
	internal static class SpawnAreaAwakePatch
	{
		private static void Postfix(SpawnArea __instance)
		{
			SpawnerManager.HandleSpawnAreaInstanceAwake(__instance);
		}
	}
	[HarmonyPatch(typeof(SpawnArea), "UpdateSpawn")]
	internal static class SpawnAreaUpdateSpawnPatch
	{
		private static bool Prefix(SpawnArea __instance)
		{
			if (!PluginSettingsFacade.IsSpawnerDomainEnabled())
			{
				return true;
			}
			if (SpawnerManager.ShouldBlockClientSpawnerUpdate())
			{
				return false;
			}
			return SpawnerManager.PrepareSpawnAreaForUpdate(__instance);
		}
	}
	[HarmonyPatch(typeof(SpawnArea), "SelectWeightedPrefab")]
	internal static class SpawnAreaSelectWeightedPrefabPatch
	{
		private static void Postfix(SpawnArea __instance, SpawnData __result)
		{
			if (PluginSettingsFacade.IsSpawnerDomainEnabled())
			{
				SpawnerManager.RecordSelectedSpawnAreaPrefab(__instance, __result);
			}
		}
	}
	[HarmonyPatch(typeof(SpawnArea), "FindSpawnPoint")]
	internal static class SpawnAreaFindSpawnPointPatch
	{
		private static void Postfix(SpawnArea __instance, GameObject prefab, ref Vector3 point, bool __result)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (PluginSettingsFacade.IsSpawnerDomainEnabled())
			{
				SpawnerManager.RecordSpawnAreaSpawnPoint(__instance, __result, point);
				if (__result)
				{
					SpawnerManager.InitializeSpawnAreaSpawnData(__instance, prefab, point);
				}
			}
		}
	}
	[HarmonyPatch(typeof(SpawnArea), "SpawnOne")]
	internal static class SpawnAreaSpawnOnePatch
	{
		private static readonly MethodInfo InstantiateGameObjectMethod = (from method in typeof(Object).GetMethods(BindingFlags.Static | BindingFlags.Public)
			where method.Name == "Instantiate" && method.IsGenericMethodDefinition
			select method).First(delegate(MethodInfo method)
		{
			ParameterInfo[] parameters = method.GetParameters();
			return parameters.Length == 3 && parameters[2].ParameterType == typeof(Quaternion);
		}).MakeGenericMethod(typeof(GameObject));

		private static void Prefix(SpawnArea __instance)
		{
			if (PluginSettingsFacade.IsSpawnerDomainEnabled())
			{
				SpawnerManager.BeginSpawnAreaSpawnAttempt(__instance);
			}
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null);
			val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Call, (object)InstantiateGameObjectMethod, (string)null)
			});
			if (!val.IsValid)
			{
				DropNSpawnPlugin.DropNSpawnLogger.LogError((object)"Failed to locate SpawnArea.SpawnOne instantiate call for faction tracking.");
				return instructions;
			}
			return val.Advance(1).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Dup, (object)null)
			}).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Ldarg_0, (object)null)
			})
				.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Call, Transpilers.EmitDelegate<Action<GameObject, SpawnArea>>((Action<GameObject, SpawnArea>)RecordSpawnedObject).operand)
				})
				.InstructionEnumeration();
		}

		private static void Postfix(SpawnArea __instance, bool __result)
		{
			if (PluginSettingsFacade.IsSpawnerDomainEnabled())
			{
				SpawnerManager.FinalizeSpawnAreaSpawnAttempt(__instance, __result);
			}
		}

		private static void RecordSpawnedObject(GameObject spawnedObject, SpawnArea spawnArea)
		{
			SpawnerManager.RecordDirectSpawnAreaSpawnedObject(spawnArea, spawnedObject);
		}
	}
	[HarmonyPatch(typeof(CreatureSpawner), "Awake")]
	internal static class CreatureSpawnerAwakePatch
	{
		private static void Postfix(CreatureSpawner __instance)
		{
			SpawnerManager.HandleCreatureSpawnerInstanceAwake(__instance);
		}
	}
	[HarmonyPatch(typeof(CreatureSpawner), "OnDestroy")]
	internal static class CreatureSpawnerOnDestroyPatch
	{
		private static void Prefix(CreatureSpawner __instance)
		{
			SpawnerManager.UntrackCreatureSpawnerInstance(__instance);
		}
	}
	[HarmonyPatch(typeof(CreatureSpawner), "UpdateSpawner")]
	internal static class CreatureSpawnerUpdateSpawnerPatch
	{
		private static bool Prefix(CreatureSpawner __instance)
		{
			if (!PluginSettingsFacade.IsSpawnerDomainEnabled())
			{
				return true;
			}
			if (SpawnerManager.ShouldBlockClientSpawnerUpdate())
			{
				return false;
			}
			return SpawnerManager.PrepareCreatureSpawnerForUpdate(__instance);
		}
	}
	[HarmonyPatch(typeof(CreatureSpawner), "Spawn")]
	internal static class CreatureSpawnerSpawnPatch
	{
		private static bool Prefix(CreatureSpawner __instance, out ZDO? __state)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			__state = null;
			if (!PluginSettingsFacade.IsSpawnerDomainEnabled())
			{
				return true;
			}
			if (!SpawnerManager.PrepareCreatureSpawnerSpawn(__instance, out __state))
			{
				return false;
			}
			Vector3 position = ((Component)__instance).transform.position;
			float y = default(float);
			if ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.FindFloor(position, ref y))
			{
				position.y = y;
			}
			SpawnerManager.InitializeCreatureSpawnerSpawnData(__instance, __instance.m_creaturePrefab, position);
			return true;
		}

		private static void Postfix(CreatureSpawner __instance, ZNetView __result, ZDO? __state, bool __runOriginal)
		{
			SpawnerManager.RecordCreatureSpawnerTotalSpawn(__state, __runOriginal && (Object)(object)__result != (Object)null && __result.IsValid());
			if (PluginSettingsFacade.IsSpawnerDomainEnabled())
			{
				SpawnerManager.ApplyCreatureSpawnerSpawnOverrides(__instance, __result);
			}
		}
	}
	[HarmonyPatch(typeof(Group), "SpawnWeighted")]
	internal static class CreatureSpawnerGroupSpawnPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Expected O, but got Unknown
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Expected O, but got Unknown
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			MethodInfo add = AccessTools.Method(typeof(List<CreatureSpawner>), "Add", (Type[])null, (Type[])null);
			int num = list.FindIndex((CodeInstruction instruction) => CodeInstructionExtensions.Calls(instruction, add));
			int num2 = num - 3;
			if (num2 < 1 || list[num2].opcode != OpCodes.Ldarg_0 || list[num2 + 1].opcode != OpCodes.Ldfld || !(list[num2 + 1].operand is FieldInfo fieldInfo) || fieldInfo.Name != "m_activeSpawners" || (list[num2 - 1].opcode != OpCodes.Brtrue && list[num2 - 1].opcode != OpCodes.Brtrue_S) || !(list[num2 - 1].operand is Label label))
			{
				throw new InvalidOperationException("CreatureSpawner.Group.SpawnWeighted candidate/weight contract changed.");
			}
			CodeInstruction val = new CodeInstruction(list[num - 1].opcode, list[num - 1].operand);
			val.labels.AddRange(list[num2].labels);
			val.blocks.AddRange(list[num2].blocks);
			list[num2].labels.Clear();
			list[num2].blocks.Clear();
			list.InsertRange(num2, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[3]
			{
				val,
				new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(SpawnerManager), "IsCreatureSpawnerGroupCandidate", (Type[])null, (Type[])null)),
				new CodeInstruction(OpCodes.Brfalse, (object)label)
			});
			return list;
		}
	}
	[HarmonyPatch(typeof(BaseAI), "Awake")]
	internal static class BaseAIAwakeFactionPatch
	{
		private static void Postfix(BaseAI __instance)
		{
			FactionIntegration.ApplyFromZdo(__instance);
		}
	}
	[HarmonyPatch(typeof(SpawnSystem), "Awake")]
	[HarmonyPriority(0)]
	internal static class SpawnSystemAwakePatch
	{
		private static void Prefix(SpawnSystem __instance)
		{
			SpawnSystemManager.PreAttachCompiledTableToAwakeningSystem(__instance);
		}

		private static void Postfix(SpawnSystem __instance)
		{
			SpawnSystemManager.OnSpawnSystemAwake(__instance);
		}
	}
	[HarmonyPatch(typeof(SpawnSystem), "OnDestroy")]
	internal static class SpawnSystemOnDestroyPatch
	{
		private static void Prefix(SpawnSystem __instance)
		{
			SpawnSystemTimers.Detach(__instance);
			SpawnSystemManager.UntrackLiveSystem(__instance);
		}
	}
	[HarmonyPatch(typeof(SpawnSystem), "UpdateSpawnList", new Type[]
	{
		typeof(List<SpawnData>),
		typeof(DateTime),
		typeof(bool),
		typeof(string)
	})]
	internal static class SpawnSystemTimerPatch
	{
		private static bool Prefix(SpawnSystem __instance, List<SpawnData> spawners, bool eventSpawners, string groupSalt, ZNetView ___m_nview, out SpawnSystemTimers.ZoneState? __state)
		{
			return SpawnSystemTimers.Begin(__instance, spawners, eventSpawners, groupSalt, ___m_nview, out __state);
		}

		private static Exception? Finalizer(SpawnSystemTimers.ZoneState? __state, Exception? __exception)
		{
			try
			{
				SpawnSystemTimers.End(__state);
				return __exception;
			}
			catch (Exception ex)
			{
				DropNSpawnPlugin.DropNSpawnLogger.LogError((object)$"Failed to persist SpawnSystem timer batch: {ex}");
				return __exception ?? ex;
			}
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Expected O, but got Unknown
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Expected O, but got Unknown
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Expected O, but got Unknown
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			LocalVariableInfo[] array = __originalMethod.GetMethodBody().LocalVariables.Where((LocalVariableInfo local) => local.LocalType == typeof(SpawnData)).ToArray();
			MethodInfo get = AccessTools.Method(typeof(ZDO), "GetLong", new Type[2]
			{
				typeof(int),
				typeof(long)
			}, (Type[])null);
			MethodInfo set = AccessTools.Method(typeof(ZDO), "Set", new Type[2]
			{
				typeof(int),
				typeof(long)
			}, (Type[])null);
			if (array.Length != 1 || list.Count((CodeInstruction i) => CodeInstructionExtensions.Calls(i, get)) != 1 || list.Count((CodeInstruction i) => CodeInstructionExtensions.Calls(i, set)) != 1)
			{
				throw new InvalidOperationException("SpawnSystem.UpdateSpawnList timer contract changed; refusing a partial timer replacement.");
			}
			List<CodeInstruction> list2 = new List<CodeInstruction>(list.Count + 8);
			foreach (CodeInstruction item in list)
			{
				bool flag = CodeInstructionExtensions.Calls(item, get);
				if (!flag && !CodeInstructionExtensions.Calls(item, set))
				{
					list2.Add(item);
					continue;
				}
				CodeInstruction val = new CodeInstruction(OpCodes.Ldarg_0, (object)null);
				val.labels.AddRange(item.labels);
				val.blocks.AddRange(item.blocks);
				list2.Add(val);
				list2.Add(new CodeInstruction(OpCodes.Ldloc, (object)array[0].LocalIndex));
				list2.Add(new CodeInstruction(OpCodes.Ldarg_3, (object)null));
				list2.Add(new CodeInstruction(OpCodes.Ldarg_S, (object)(byte)4));
				list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(SpawnSystemTimers), flag ? "ReadTime" : "WriteTime", (Type[])null, (Type[])null)));
			}
			return list2;
		}
	}
	[HarmonyPatch(typeof(SpawnSystem), "UpdateSpawnList", new Type[]
	{
		typeof(List<SpawnData>),
		typeof(DateTime),
		typeof(bool),
		typeof(string)
	})]
	internal static class SpawnSystemSpawnLimitPatch
	{
		private static int CountForLimit(int existing, int allNew, SpawnData row, bool enabled, Dictionary<int, int>? recent, ref int groupCount)
		{
			if (!enabled)
			{
				return existing + allNew;
			}
			int value = 0;
			recent?.TryGetValue(StringExtensionMethods.GetStableHashCode(((Object)row.m_prefab).name), out value);
			groupCount = existing + value;
			return groupCount;
		}

		private static void RecordSpawn(SpawnData row, bool enabled, ref Dictionary<int, int>? recent)
		{
			if (enabled)
			{
				if (recent == null)
				{
					recent = new Dictionary<int, int>();
				}
				int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)row.m_prefab).name);
				recent.TryGetValue(stableHashCode, out var value);
				recent[stableHashCode] = value + 1;
			}
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod, ILGenerator generator)
		{
			//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c6: Expected O, but got Unknown
			//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d7: Expected O, but got Unknown
			//IL_03de: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e8: Expected O, but got Unknown
			//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fe: Expected O, but got Unknown
			//IL_041a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0424: Expected O, but got Unknown
			//IL_042c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0436: Expected O, but got Unknown
			//IL_043d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0447: Expected O, but got Unknown
			//IL_044f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0459: Expected O, but got Unknown
			//IL_046b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0472: Expected O, but got Unknown
			//IL_0489: Unknown result type (might be due to invalid IL or missing references)
			//IL_0490: Expected O, but got Unknown
			//IL_04c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d2: Expected O, but got Unknown
			//IL_04db: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e5: Expected O, but got Unknown
			//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fd: Expected O, but got Unknown
			//IL_051a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0524: Expected O, but got Unknown
			//IL_0543: Unknown result type (might be due to invalid IL or missing references)
			//IL_054d: Expected O, but got Unknown
			//IL_0556: Unknown result type (might be due to invalid IL or missing references)
			//IL_0560: Expected O, but got Unknown
			//IL_0569: Unknown result type (might be due to invalid IL or missing references)
			//IL_0573: Expected O, but got Unknown
			//IL_0590: Unknown result type (might be due to invalid IL or missing references)
			//IL_059a: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			MethodInfo count = AccessTools.Method(typeof(SpawnSystem), "GetNrOfZDOInstances", new Type[3]
			{
				typeof(GameObject),
				typeof(List<ZDO>),
				typeof(bool)
			}, (Type[])null);
			MethodInfo spawn = AccessTools.Method(typeof(SpawnSystem), "Spawn", new Type[3]
			{
				typeof(SpawnData),
				typeof(Vector3),
				typeof(bool)
			}, (Type[])null);
			FieldInfo fieldInfo = AccessTools.Field(typeof(SpawnData), "m_maxSpawned");
			MethodBody methodBody = __originalMethod.GetMethodBody();
			if (count == null || spawn == null || fieldInfo == null || methodBody == null)
			{
				return SkipCorrection(list);
			}
			int num = list.FindIndex((CodeInstruction i) => CodeInstructionExtensions.Calls(i, count));
			int num2 = list.FindIndex((CodeInstruction i) => CodeInstructionExtensions.Calls(i, spawn));
			int num3 = ((num >= 0 && num + 7 < list.Count) ? LocalIndex(list[num + 1], store: true) : (-1));
			int num4 = ((num3 >= 0) ? LocalIndex(list[num + 3]) : (-1));
			int num5 = ((num3 >= 0) ? LocalIndex(list[num + 5]) : (-1));
			IList<LocalVariableInfo> locals = methodBody.LocalVariables;
			bool flag = num >= 0 && num2 > num + 7 && num2 + 4 < list.Count && list.Count((CodeInstruction i) => CodeInstructionExtensions.Calls(i, count)) == 1 && list.Count((CodeInstruction i) => CodeInstructionExtensions.Calls(i, spawn)) == 1 && LocalIs(num3, typeof(int)) && LocalIs(num4, typeof(int)) && num3 != num4 && LocalIs(num5, typeof(SpawnData)) && LocalIndex(list[num + 2]) == num3 && list[num + 4].opcode == OpCodes.Add && CodeInstructionExtensions.LoadsField(list[num + 6], fieldInfo, false) && (list[num + 7].opcode == OpCodes.Bge || list[num + 7].opcode == OpCodes.Bge_S) && LocalIndex(list[num2 + 1]) == num4 && list[num2 + 2].opcode == OpCodes.Ldc_I4_1 && list[num2 + 3].opcode == OpCodes.Add && LocalIndex(list[num2 + 4], store: true) == num4;
			if (flag)
			{
				int num6 = 0;
				for (int num7 = num + 8; num7 + 3 < num2; num7++)
				{
					if (LocalIndex(list[num7]) == num5 && CodeInstructionExtensions.LoadsField(list[num7 + 1], fieldInfo, false) && LocalIndex(list[num7 + 2]) == num3 && list[num7 + 3].opcode == OpCodes.Sub)
					{
						num6++;
					}
				}
				flag = num6 == 1;
			}
			if (!flag)
			{
				return SkipCorrection(list);
			}
			LocalBuilder localBuilder = generator.DeclareLocal(typeof(bool));
			LocalBuilder localBuilder2 = generator.DeclareLocal(typeof(Dictionary<int, int>));
			List<CodeInstruction> list2 = new List<CodeInstruction>(list.Count + 18)
			{
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Ldarg_1, (object)null),
				new CodeInstruction(OpCodes.Ldarg_3, (object)null),
				new CodeInstruction(OpCodes.Ldarg_S, (object)(byte)4),
				new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(SpawnSystemTimers), "IsManagedList", (Type[])null, (Type[])null)),
				new CodeInstruction(OpCodes.Stloc, (object)localBuilder),
				new CodeInstruction(OpCodes.Ldnull, (object)null),
				new CodeInstruction(OpCodes.Stloc, (object)localBuilder2)
			};
			for (int num8 = 0; num8 < list.Count; num8++)
			{
				CodeInstruction val = new CodeInstruction(list[num8]);
				if (num8 == num + 4)
				{
					CodeInstruction val2 = new CodeInstruction(OpCodes.Ldloc, (object)num5);
					val2.labels.AddRange(val.labels);
					val2.blocks.AddRange(val.blocks);
					list2.Add(val2);
					list2.Add(new CodeInstruction(OpCodes.Ldloc, (object)localBuilder));
					list2.Add(new CodeInstruction(OpCodes.Ldloc, (object)localBuilder2));
					list2.Add(new CodeInstruction(OpCodes.Ldloca, (object)num3));
					list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(SpawnSystemSpawnLimitPatch), "CountForLimit", (Type[])null, (Type[])null)));
				}
				else
				{
					list2.Add(val);
					if (num8 == num2)
					{
						list2.Add(new CodeInstruction(OpCodes.Ldloc, (object)num5));
						list2.Add(new CodeInstruction(OpCodes.Ldloc, (object)localBuilder));
						list2.Add(new CodeInstruction(OpCodes.Ldloca, (object)localBuilder2));
						list2.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(SpawnSystemSpawnLimitPatch), "RecordSpawn", (Type[])null, (Type[])null)));
					}
				}
			}
			return list2;
			bool LocalIs(int index, Type type)
			{
				if (index >= 0 && index < locals.Count)
				{
					return locals[index].LocalType == type;
				}
				return false;
			}
		}

		private static IEnumerable<CodeInstruction> SkipCorrection(List<CodeInstruction> input)
		{
			DropNSpawnPlugin.DropNSpawnLogger.LogWarning((object)"Natural spawn limit correction skipped: UpdateSpawnList count/group contract changed. Existing spawn and timer behavior is unchanged.");
			return input;
		}

		private static int LocalIndex(CodeInstruction instruction, bool store = false)
		{
			OpCode opcode = instruction.opcode;
			if (opcode == (store ? OpCodes.Stloc_0 : OpCodes.Ldloc_0))
			{
				return 0;
			}
			if (opcode == (store ? OpCodes.Stloc_1 : OpCodes.Ldloc_1))
			{
				return 1;
			}
			if (opcode == (store ? OpCodes.Stloc_2 : OpCodes.Ldloc_2))
			{
				return 2;
			}
			if (opcode == (store ? OpCodes.Stloc_3 : OpCodes.Ldloc_3))
			{
				return 3;
			}
			if (opcode != (store ? OpCodes.Stloc : OpCodes.Ldloc) && opcode != (store ? OpCodes.Stloc_S : OpCodes.Ldloc_S))
			{
				return -1;
			}
			object operand = instruction.operand;
			if (!(operand is LocalVariableInfo { LocalIndex: var localIndex }))
			{
				if (!(operand is int result))
				{
					if (!(operand is short result2))
					{
						if (operand is byte result3)
						{
							return result3;
						}
						return -1;
					}
					return result2;
				}
				return result;
			}
			return localIndex;
		}
	}
	[HarmonyPatch(typeof(SpawnSystem), "UpdateSpawning")]
	internal static class SpawnSystemUpdateSpawningRequiredGlobalKeyPatch
	{
		private static bool Prefix(SpawnSystem __instance, out bool __state)
		{
			__state = false;
			if (!PluginSettingsFacade.IsSpawnSystemDomainEnabled())
			{
				return true;
			}
			if (SpawnSystemManager.ShouldBlockClientSpawnSystemUpdate(__instance))
			{
				return false;
			}
			SpawnSystemManager.RefreshRuntimeTimeOfDayState();
			__state = true;
			SpawnSystemManager.EnterRequiredGlobalKeyEvaluation();
			return true;
		}

		private static Exception? Finalizer(bool __state, Exception? __exception)
		{
			if (__state)
			{
				SpawnSystemManager.ExitRequiredGlobalKeyEvaluation();
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(ZoneSystem), "GetGlobalKey", new Type[] { typeof(string) })]
	internal static class ZoneSystemGetGlobalKeyStringPatch
	{
		private static bool Prefix(ZoneSystem __instance, string name, ref bool __result)
		{
			if (!PluginSettingsFacade.IsSpawnSystemDomainEnabled())
			{
				return true;
			}
			if (!SpawnSystemManager.TryEvaluateExtendedRequiredGlobalKey(__instance, name, out var result))
			{
				return true;
			}
			__result = result;
			return false;
		}
	}
	[HarmonyPatch(typeof(ZoneSystem), "RPC_SetGlobalKey")]
	internal static class ZoneSystemRpcSetGlobalKeyPatch
	{
		private static void Prefix(ZoneSystem __instance, ref string name)
		{
			if (DropNSpawnPlugin.IsSourceOfTruth && PluginSettingsFacade.IsSpawnSystemDomainEnabled() && SpawnSystemManager.TryRewriteExtendedGlobalKeyMutation(__instance, name, out string rewrittenValue))
			{
				name = rewrittenValue;
			}
		}
	}
	[HarmonyPatch(typeof(SpawnSystem), "Spawn")]
	internal static class SpawnSystemSpawnPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			int num = list.FindIndex((CodeInstruction instruction) => instruction.opcode == OpCodes.Call && instruction.operand is MethodInfo methodInfo && methodInfo.DeclaringType == typeof(Object) && methodInfo.Name == "Instantiate" && methodInfo.IsGenericMethod && methodInfo.GetGenericArguments().SequenceEqual(new Type[1] { typeof(GameObject) }) && (from parameter in methodInfo.GetParameters()
				select parameter.ParameterType).SequenceEqual(new Type[3]
			{
				typeof(GameObject),
				typeof(Vector3),
				typeof(Quaternion)
			}));
			if (num < 0)
			{
				throw new InvalidOperationException("SpawnSystem.Spawn instantiate contract changed; cannot preserve standalone faction overrides.");
			}
			list.InsertRange(num + 1, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[3]
			{
				new CodeInstruction(OpCodes.Dup, (object)null),
				new CodeInstruction(OpCodes.Ldarg_1, (object)null),
				new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(SpawnSystemCustomDataSupport), "ApplyStandaloneFaction", (Type[])null, (Type[])null))
			});
			return list;
		}

		private static void Prefix(SpawnData critter, Vector3 spawnPoint, out bool __state)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			__state = false;
			if (PluginSettingsFacade.IsSpawnSystemDomainEnabled() || SpawnSystemCustomDataSupport.HasPreparedPayload(critter) || ExpandWorldDataCompatibility.HasAltBiomeKeyConsumer(critter))
			{
				__state = true;
				SpawnSystemCustomDataSupport.InitializeSpawn(critter, spawnPoint);
			}
		}

		private static void Postfix(SpawnData critter, Vector3 spawnPoint, bool __state)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (__state)
			{
				if (!ExpandWorldDataCompatibility.ConsumeAltBiomeKeys(critter) && PluginSettingsFacade.IsSpawnSystemDomainEnabled())
				{
					SpawnSystemManager.ConsumeExtendedRequiredGlobalKeyAfterSpawn(critter);
				}
				SpawnSystemCustomDataSupport.SpawnObjects(critter, spawnPoint);
			}
		}
	}
	internal static class GeneratedFileWriter
	{
		internal static bool WriteAllTextIfChanged(string path, string content)
		{
			if (path == null)
			{
				throw new ArgumentNullException("path");
			}
			if (content == null)
			{
				content = "";
			}
			string directoryName = Path.GetDirectoryName(path);
			if (!string.IsNullOrEmpty(directoryName))
			{
				Directory.CreateDirectory(directoryName);
			}
			if (File.Exists(path) && string.Equals(File.ReadAllText(path), content, StringComparison.Ordinal))
			{
				return false;
			}
			File.WriteAllText(path, content);
			return true;
		}
	}
	internal static class GeneratedArtifactWriter
	{
		internal static bool WriteText(string path, string content, string? logMessage = null, bool logOnlyWhenChanged = false)
		{
			bool flag = GeneratedFileWriter.WriteAllTextIfChanged(path, content);
			if (!string.IsNullOrWhiteSpace(logMessage) && (!logOnlyWhenChanged || flag))
			{
				DropNSpawnPlugin.DropNSpawnLogger.LogInfo((object)logMessage);
			}
			return flag;
		}

		internal static void WriteTextAlways(string path, string content, string? logMessage = null)
		{
			string directoryName = Path.GetDirectoryName(path);
			if (!string.IsNullOrWhiteSpace(directoryName))
			{
				Directory.CreateDirectory(directoryName);
			}
			File.WriteAllText(path, content ?? "");
			if (!string.IsNullOrWhiteSpace(logMessage))
			{
				DropNSpawnPlugin.DropNSpawnLogger.LogInfo((object)logMessage);
			}
		}
	}
	internal static class ReferenceRefreshSupport
	{
		internal sealed class LocationReferenceScan
		{
			private readonly HashSet<AssetID>? _excludedAssets;

			internal string Signature { get; }

			internal unsafe LocationReferenceScan(HashSet<AssetID>? excludedAssets)
			{
				_excludedAssets = excludedAssets;
				string[] first = new string[1] { "# DropNSpawn location scan: automatic-mwl-excluded-v1" };
				IEnumerable<string> second;
				if (excludedAssets != null)
				{
					second = excludedAssets.Select((AssetID id) => ((object)(*(AssetID*)(&id))/*cast due to .constrained prefix*/).ToString());
				}
				else
				{
					IEnumerable<string> enumerable = new string[1] { "all-locations-deferred" };
					second = enumerable;
				}
				Signature = ComputeStableHashForKeys(first.Concat(second));
			}

			internal bool ShouldSkip(AssetID assetId)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				if (_excludedAssets != null)
				{
					return _excludedAssets.Contains(assetId);
				}
				return true;
			}

			internal string Annotate(string content)
			{
				return "# DropNSpawn location scan: automatic-mwl-excluded-v1" + Environment.NewLine + ((_excludedAssets == null) ? "# Location interiors were not scanned because the MWL manifest could not be read." : "# MWL location interiors were not scanned; registered prefab references are still included.") + Environment.NewLine + "# Explicit dns:reference object/spawner exports include all locations and can be expensive." + Environment.NewLine + content;
			}
		}

		internal const string CurrentReferenceLogicVersion = "2026-03-26-full-rewrite-v1";

		internal const string MoreWorldLocationsGuid = "warpalicious.More_World_Locations_AIO";

		internal const string PartialLocationReferenceHeader = "# DropNSpawn location scan: automatic-mwl-excluded-v1";

		internal static LocationReferenceScan? CreateAutomaticLocationScan()
		{
			if (!Chainloader.PluginInfos.TryGetValue("warpalicious.More_World_Locations_AIO", out var value))
			{
				return null;
			}
			try
			{
				string text = Directory.EnumerateFiles(Path.GetDirectoryName(value.Location)).FirstOrDefault((string file) => string.Equals(Path.GetFileName(file), "assetBundleManifest_full", StringComparison.OrdinalIgnoreCase));
				AssetBundleManifest val = ((text == null) ? null : AssetBundleManifest.DeserializeFromDisk(text));
				if (val != null && val.AssetCount != 0)
				{
					return new LocationReferenceScan(val.m_assetToLocationMap.Keys.ToHashSet());
				}
			}
			catch (Exception ex)
			{
				DropNSpawnPlugin.DropNSpawnLogger.LogWarning((object)("Could not read MWL reference-scan metadata: " + ex.Message));
			}
			DropNSpawnPlugin.DropNSpawnLogger.LogWarning((object)"MWL manifest unavailable: automatic location-interior references are deferred; registered prefab references and override rules remain available.");
			return new LocationReferenceScan(null);
		}

		internal static IEnumerable<(string LocationPrefab, GameObject RootPrefab)> EnumerateLocationRootPrefabs(LocationReferenceScan? scan = null)
		{
			if ((Object)(object)ZoneSystem.instance == (Object)null)
			{
				yield break;
			}
			HashSet<string> seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			foreach (ZoneLocation location in ZoneSystem.instance.m_locations)
			{
				SoftReference<GameObject> prefab = location.m_prefab;
				if (!prefab.IsValid || (scan?.ShouldSkip(prefab.m_assetID) ?? false))
				{
					continue;
				}
				string text = (prefab.Name ?? "").Trim();
				if (text.Length == 0 || !seen.Add(text))
				{
					continue;
				}
				try
				{
					if ((int)prefab.Load() == 0)
					{
						GameObject asset = prefab.Asset;
						if ((Object)(object)asset != (Object)null)
						{
							yield return (LocationPrefab: text, RootPrefab: asset);
						}
					}
				}
				finally
				{
					prefab.Release();
				}
			}
		}

		internal static void WarnBeforeFullLocationScan()
		{
			if (Chainloader.PluginInfos.ContainsKey("warpalicious.More_World_Locations_AIO"))
			{
				DropNSpawnPlugin.DropNSpawnLogger.LogWarning((object)"Explicit full location reference export includes MWL interiors. This can take minutes and use substantial memory on low-memory systems.");
			}
		}

		internal static string ComputeStableHashForKeys(IEnumerable<string?> keys)
		{
			StringBuilder stringBuilder = new StringBuilder();
			foreach (string item in (from key in (keys ?? Enumerable.Empty<string>()).Select(NormalizeKey)
				where key.Length > 0
				select key).OrderBy<string, string>((string key) => key, StringComparer.OrdinalIgnoreCase))
			{
				stringBuilder.AppendLine(item);
			}
			return ComputeStableHash(stringBuilder.ToString());
		}

		internal static string SerializeReferenceSections<T>(IEnumerable<T> entries, Func<T, string> getPrefabName, ISerializer serializer)
		{
			return PrefabOutputSections.SerializeReferenceSections(PrefabOutputSections.BuildSections(entries ?? Enumerable.Empty<T>(), getPrefabName), serializer);
		}

		internal static HashSet<string> ToNormalizedKeySet(IEnumerable<string?> keys)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			foreach (string item in keys ?? Enumerable.Empty<string>())
			{
				string text = NormalizeKey(item);
				if (text.Length > 0)
				{
					hashSet.Add(text);
				}
			}
			return hashSet;
		}

		internal static string NormalizeKey(string? key)
		{
			return (key ?? "").Trim();
		}

		internal static bool ShouldSkipAutoUpdate(string stateKey, string referencePath, string sourceSignature, string? logicVersion = null)
		{
			if (string.IsNullOrWhiteSpace(stateKey) || string.IsNullOrWhiteSpace(referencePath) || string.IsNullOrWhiteSpace(sourceSignature) || !File.Exists(referencePath))
			{
				return false;
			}
			string autoUpdateStatePath = GetAutoUpdateStatePath(stateKey);
			if (!File.Exists(autoUpdateStatePath))
			{
				return false;
			}
			try
			{
				string text = (logicVersion ?? "").Trim();
				string[] array = File.ReadAllLines(autoUpdateStatePath);
				if (array.Length < 2)
				{
					return false;
				}
				string a = (array[0] ?? "").Trim();
				string a2 = (array[1] ?? "").Trim();
				string a3 = ((array.Length >= 4) ? (array[3] ?? "").Trim() : "");
				if (text.Length > 0 && !string.Equals(a3, text, StringComparison.Ordinal))
				{
					return false;
				}
				return string.Equals(a, sourceSignature, StringComparison.Ordinal) && string.Equals(a2, BuildReferenceFileStamp(referencePath), StringComparison.Ordinal);
			}
			catch
			{
				return false;
			}
		}

		internal static void RecordAutoUpdateState(string stateKey, string referencePath, string sourceSignature, string? precheckSignature = null, string? logicVersion = null)
		{
			if (!string.IsNullOrWhiteSpace(stateKey) && !string.IsNullOrWhiteSpace(referencePath) && !string.IsNullOrWhiteSpace(sourceSignature) && File.Exists(referencePath))
			{
				string autoUpdateStatePath = GetAutoUpdateStatePath(stateKey);
				string content = sourceSignature.Trim() + Environment.NewLine + BuildReferenceFileStamp(referencePath) + Environment.NewLine + (precheckSignature ?? "").Trim() + Environment.NewLine + (logicVersion ?? "").Trim() + Environment.NewLine;
				GeneratedFileWriter.WriteAllTextIfChanged(autoUpdateStatePath, content);
			}
		}

		internal static string ComputeStableHash(string? value)
		{
			using SHA256 sHA = SHA256.Create();
			byte[] bytes = Encoding.UTF8.GetBytes(value ?? "");
			byte[] array = sHA.ComputeHash(bytes);
			StringBuilder stringBuilder = new StringBuilder(array.Length * 2);
			byte[] array2 = array;
			foreach (byte b in array2)
			{
				stringBuilder.Append(b.ToString("x2"));
			}
			return stringBuilder.ToString();
		}

		private static string GetAutoUpdateStatePath(string stateKey)
		{
			string text = SanitizeFileName(stateKey);
			return Path.Combine(GetAutoUpdateStateDirectoryPath(), ".reference-state." + text + ".txt");
		}

		private static string GetAutoUpdateStateDirectoryPath()
		{
			return Path.Combine(DropNSpawnPlugin.YamlConfigDirectoryPath, "cache");
		}

		private static string BuildReferenceFileStamp(string referencePath)
		{
			FileInfo fileInfo = new FileInfo(referencePath);
			return $"{fileInfo.Length}:{fileInfo.LastWriteTimeUtc.Ticks}";
		}

		private static string SanitizeFileName(string value)
		{
			StringBuilder stringBuilder = new StringBuilder(value.Length);
			HashSet<char> hashSet = Path.GetInvalidFileNameChars().ToHashSet();
			foreach (char c in value)
			{
				stringBuilder.Append(hashSet.Contains(c) ? '_' : c);
			}
			return stringBuilder.ToString();
		}
	}
	internal enum ReferenceArtifactUpdateKind
	{
		None,
		Created,
		Updated
	}
	internal static class ReferenceArtifactLifecycle
	{
		internal static bool TryPlanUpdate(string stateKey, string referencePath, string sourceSignature, out ReferenceArtifactUpdateKind updateKind, string? requiredExistingHeader = null)
		{
			updateKind = ReferenceArtifactUpdateKind.None;
			if (!File.Exists(referencePath))
			{
				updateKind = ReferenceArtifactUpdateKind.Created;
				return true;
			}
			if (requiredExistingHeader != null && !HasHeader(referencePath, requiredExistingHeader))
			{
				DropNSpawnPlugin.DropNSpawnLogger.LogInfo((object)("Preserved existing reference at " + referencePath + ": automatic MWL location scanning is restricted. Use dns:reference for an explicit full refresh."));
				return false;
			}
			if (ReferenceRefreshSupport.ShouldSkipAutoUpdate(stateKey, referencePath, sourceSignature, "2026-03-26-full-rewrite-v1"))
			{
				return false;
			}
			updateKind = ReferenceArtifactUpdateKind.Updated;
			return true;
		}

		internal static void RecordUpdate(string stateKey, string referencePath, string sourceSignature)
		{
			ReferenceRefreshSupport.RecordAutoUpdateState(stateKey, referencePath, sourceSignature, null, "2026-03-26-full-rewrite-v1");
		}

		private static bool HasHeader(string path, string header)
		{
			using StreamReader streamReader = File.OpenText(path);
			return string.Equals(streamReader.ReadLine(), header, StringComparison.Ordinal);
		}

		internal static string FormatAction(ReferenceArtifactUpdateKind updateKind)
		{
			if (updateKind != ReferenceArtifactUpdateKind.Created)
			{
				return "Updated";
			}
			return "Created";
		}
	}
	internal sealed class CharacterDropPrefabEntry
	{
		[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 CharacterDropDefinition? CharacterDrop { get; set; }

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

		[YamlIgnore]
		public string? SourcePath { get; set; }

		[YamlIgnore]
		public int SourceLine { get; set; }

		[YamlIgnore]
		public int SourceColumn { get; set; }
	}
	internal sealed class CharacterDropReferenceEntry
	{
		[YamlMember(Order = 1)]
		public string Prefab { get; set; } = "";

		[YamlMember(Order = 2)]
		public CharacterDropDefinition? CharacterDrop { get; set; }
	}
	internal sealed class CharacterDropDefinition
	{
		[YamlMember(Order = 1)]
		public List<CharacterDropEntryDefinition>? Drops { get; set; }
	}
	internal sealed class CharacterDropEntryDefinition
	{
		[YamlMember(Order = 1)]
		public string Item { get; set; } = "";

		[YamlMember(Order = 2)]
		public IntRangeDefinition? Amount { get; set; }

		[YamlIgnore]
		public int? AmountMin { get; set; }

		[YamlIgnore]
		public int? AmountMax { get; set; }

		[YamlMember(Order = 3)]
		public float? Chance { get; set; }

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

		[YamlMember(Order = 5)]
		public bool? LevelMultiplier { get; set; }

		[YamlMember(Order = 6)]
		public bool? LevelMultiplierNotAmount { get; set; }

		[YamlMember(Order = 7)]
		public bool? OnePerPlayer { get; set; }

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

		[YamlMember(Order = 9)]
		public bool? DropInStack { get; set; }
	}
	internal sealed class CompiledCharacterDropDefinition
	{
		public string Fingerprint { get; set; } = "";

		public GameObject Prefab { get; set; }

		public int AmountMin { get; set; }

		public int AmountMax { get; set; }

		public float Chance { get; set; }

		public bool DontScale { get; set; }

		public bool LevelMultiplier { get; set; }

		public bool? LevelMultiplierOverride { get; set; }

		public bool LevelMultiplierNotAmount { get; set; }

		public bool OnePerPlayer { get; set; }

		public int? AmountLimit { get; set; }

		public bool? DropInStack { get; set; }
	}
	internal sealed class CompiledCharacterDropRule
	{
		public CharacterDropPrefabEntry Entry { get; set; }

		public List<CompiledCharacterDropDefinition> Drops { get; } = new List<CompiledCharacterDropDefinition>();
	}
	internal sealed class CachedCharacterRuntimeDropResolution
	{
		public bool HasMatchedRuntimeRule { get; set; }

		public CompiledCharacterDropDefinition[] Definitions { get; set; } = Array.Empty<CompiledCharacterDropDefinition>();

		public List<Drop>? OverrideDrops { get; set; }

		public bool HasCustomDropHandling { get; set; }
	}
	internal sealed class CharacterRuntimeDropCacheState
	{
		public bool IsCacheable { get; set; } = true;

		public bool UsesLevel { get; set; }

		public bool UsesFaction { get; set; }

		public bool UsesState { get; set; }

		public bool UsesTimeOfDay { get; set; }

		public bool UsesRequiredEnvironments { get; set; }

		public bool UsesInsidePlayerBase { get; set; }

		public string[] RequiredGlobalKeys { get; set; } = Array.Empty<string>();

		public string[] ForbiddenGlobalKeys { get; set; } = Array.Empty<string>();

		public Dictionary<int, CachedCharacterRuntimeDropResolution> ResolutionsBySignature { get; } = new Dictionary<int, CachedCharacterRuntimeDropResolution>();
	}
	internal sealed class CharacterCompiledState
	{
		public static CharacterCompiledState Empty { get; } = new CharacterCompiledState();

		public Dictionary<string, List<CompiledCharacterDropRule>> RuntimeRulesByPrefab { get; } = new Dictionary<string, List<CompiledCharacterDropRule>>(StringComparer.OrdinalIgnoreCase);

		public Dictionary<string, CharacterRuntimeDropCacheState> RuntimeDropCachesByPrefab { get; } = new Dictionary<string, CharacterRuntimeDropCacheState>(StringComparer.OrdinalIgnoreCase);

		public Dictionary<string, List<CompiledCharacterDropDefinition>> StaticDropsByPrefab { get; } = new Dictionary<string, List<CompiledCharacterDropDefinition>>(StringComparer.OrdinalIgnoreCase);

		public Dictionary<string, List<Drop>> StaticBuiltDropsByPrefab { get; } = new Dictionary<string, List<Drop>>(StringComparer.OrdinalIgnoreCase);
	}
	internal sealed class CharacterDropSnapshot
	{
		public GameObject Prefab { get; set; }

		public List<Drop> BuiltDrops { get; set; } = new List<Drop>();
	}
	internal sealed class PendingCharacterDropSnapshotBuildState
	{
		public int GameDataSignature { get; set; }

		public int SnapshotSignature { get; set; }

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

		public List<GameObject> Prefabs { get; } = new List<GameObject>();

		public List<CharacterDropSnapshot> Snapshots { get; } = new List<CharacterDropSnapshot>();

		public Dictionary<string, CharacterDropSnapshot> SnapshotsByPrefab { get; } = new Dictionary<string, CharacterDropSnapshot>(StringComparer.OrdinalIgnoreCase);

		public int NextIndex { get; set; }
	}
	internal static class CharacterDropRuntime
	{
		private static readonly List<CharacterDropSnapshot> Snapshots = new List<CharacterDropSnapshot>();

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

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

		private static readonly Dictionary<CharacterDrop, string> LiveCharacterDropPrefabsByInstance = new Dictionary<CharacterDrop, string>();

		private static int? _lastProcessedSnapshotSignature;

		private static int? _lastProcessedGameDataSignature;

		private static int? _lastBootstrappedLiveObjectsSceneSignature;

		private static PendingCharacterDropSnapshotBuildState? _pendingSnapshotBuild;

		internal static void Reset()
		{
			Snapshots.Clear();
			SnapshotsByPrefab.Clear();
			LiveCharacterDropsByPrefab.Clear();
			LiveCharacterDropPrefabsByInstance.Clear();
			_lastProcessedSnapshotSignature = null;
			_lastProcessedGameDataSignature = null;
			_lastBootstrappedLiveObjectsSceneSignature = null;
			_pendingSnapshotBuild = null;
		}

		internal static bool HasSnapshots()
		{
			return Snapshots.Count > 0;
		}

		internal static IReadOnlyList<CharacterDropSnapshot> GetSnapshots()
		{
			return Snapshots;
		}

		internal static bool HasSnapshot(string prefabName)
		{
			if (!string.IsNullOrWhiteSpace(prefabName))
			{
				return SnapshotsByPrefab.ContainsKey(prefabName);
			}
			return false;
		}

		internal static bool TryGetSnapshot(string prefabName, out CharacterDropSnapshot? snapshot)
		{
			return SnapshotsByPrefab.TryGetValue(prefabName ?? "", out snapshot);
		}

		internal static bool IsGameDataAlreadyProcessed(int gameDataSignature)
		{
			return _lastProcessedGameDataSignature == gameDataSignature;
		}

		internal static bool NeedsSnapshotBuild(int snapshotSignature)
		{
			if (_lastProcessedSnapshotSignature == snapshotSignature)
			{
				return Snapshots.Count == 0;
			}
			return true;
		}

		internal static void ScheduleSnapshotBuild(string source, int gameDataSignature, int snapshotSignature, IEnumerable<GameObject> prefabs)
		{
			if (_pendingSnapshotBuild == null || _pendingSnapshotBuild.GameDataSignature != gameDataSignature || _pendingSnapshotBuild.SnapshotSignature != snapshotSignature)
			{
				PendingCharacterDropSnapshotBuildState pendingCharacterDropSnapshotBuildState = new PendingCharacterDropSnapshotBuildState();
				pendingCharacterDropSnapshotBuildState.GameDataSignature = gameDataSignature;
				pendingCharacterDropSnapshotBuildState.SnapshotSignature = snapshotSignature;
				pendingCharacterDropSnapshotBuildState.Source = source;
				pendingCharacterDropSnapshotBuildState.Prefabs.AddRange(prefabs);
				_pendingSnapshotBuild = pendingCharacterDropSnapshotBuildState;
			}
		}

		internal static bool HasPendingSnapshotBuildWork()
		{
			return _pendingSnapshotBuild != null;
		}

		internal static bool ProcessPendingSnapshotBuildStep(double deadline, Func<GameObject, CharacterDropSnapshot?> captureSnapshot, Action<string, int, int> onCompleted)
		{
			PendingCharacterDropSnapshotBuildState pendingSnapshotBuild = _pendingSnapshotBuild;
			if (pendingSnapshotBuild == null)
			{
				return false;
			}
			if (pendingSnapshotBuild.NextIndex >= pendingSnapshotBuild.Prefabs.Count)
			{
				CompletePendingSnapshotBuild(pendingSnapshotBuild, onCompleted);
				return true;
			}
			GameObject val = pendingSnapshotBuild.Prefabs[pendingSnapshotBuild.NextIndex];
			pendingSnapshotBuild.NextIndex++;
			CharacterDropSnapshot characterDropSnapshot = (((Object)(object)val != (Object)null) ? captureSnapshot(val) : null);
			if (_pendingSnapshotBuild == null || _pendingSnapshotBuild != pendingSnapshotBuild)
			{
				return true;
			}
			if (characterDropSnapshot != null)
			{
				pendingSnapshotBuild.Snapshots.Add(characterDropSnapshot);
				if (!pendingSnapshotBuild.SnapshotsByPrefab.ContainsKey(((Object)characterDropSnapshot.Prefab).name))
				{
					pendingSnapshotBuild.SnapshotsByPrefab.Add(((Object)characterDropSnapshot.Prefab).name, characterDropSnapshot);
				}
			}
			if (pendingSnapshotBuild.NextIndex >= pendingSnapshotBuild.Prefabs.Count && Time.realtimeSinceStartupAsDouble <= deadline)
			{
				CompletePendingSnapshotBuild(pendingSnapshotBuild, onCompleted);
			}
			return true;
		}

		internal static void CaptureSnapshotsIfNeeded(IEnumerable<GameObject> prefabs, Func<GameObject, CharacterDropSnapshot?> captureSnapshot)
		{
			if (Snapshots.Count > 0)
			{
				return;
			}
			foreach (GameObject prefab in prefabs)
			{
				CharacterDropSnapshot characterDropSnapshot = captureSnapshot(prefab);
				if (characterDropSnapshot != null)
				{
					Snapshots.Add(characterDropSnapshot);
					if (!SnapshotsByPrefab.ContainsKey(((Object)characterDropSnapshot.Prefab).name))
					{
						SnapshotsByPrefab.Add(((Object)characterDropSnapshot.Prefab).name, characterDropSnapshot);
					}
				}
			}
		}

		internal static void RegisterLiveCharacterDrop(CharacterDrop characterDrop, string prefabName)
		{
			if ((Object)(object)characterDrop == (Object)null || string.IsNullOrWhiteSpace(prefabName))
			{
				return;
			}
			if (LiveCharacterDropPrefabsByInstance.TryGetValue(characterDrop, out string value))
			{
				if (string.Equals(value, prefabName, StringComparison.OrdinalIgnoreCase))
				{
					return;
				}
				UnregisterLiveCharacterDrop(characterDrop, value);
			}
			LiveCharacterDropPrefabsByInstance[characterDrop] = prefabName;
			if (!LiveCharacterDropsByPrefab.TryGetValue(prefabName, out HashSet<CharacterDrop> value2))
			{
				value2 = new HashSet<CharacterDrop>();
				LiveCharacterDropsByPrefab[prefabName] = value2;
			}
			value2.Add(characterDrop);
		}

		internal static bool TryGetRegisteredPrefabName(CharacterDrop characterDrop, out string prefabName)
		{
			return LiveCharacterDropPrefabsByInstance.TryGetValue(characterDrop, out prefabName);
		}

		internal static void UnregisterLiveCharacterDrop(CharacterDrop characterDrop, string prefabName)
		{
			LiveCharacterDropPrefabsByInstance.Remove(characterDrop);
			if (LiveCharacterDropsByPrefab.TryGetValue(prefabName, out HashSet<CharacterDrop> value))
			{
				value.Remove(characterDrop);
				if (value.Count == 0)
				{
					LiveCharacterDropsByPrefab.Remove(prefabName);
				}
			}
		}

		internal static void BootstrapRegisteredCharacterDropsIfNeeded(int sceneSignature, IEnumerabl