Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of DropNSpawn v1.3.6
DropNSpawn.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
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 ExpandWorldData; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; 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.3.6")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.6.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 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())); } localization.AddWord(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 (!target.m_translations.ContainsKey(key)) { dictionary[key] = text; target.AddWord(key, text); } } else { list.Add(localizationObject); } } foreach (WeakReference<Localization> item in list) { localizationObjects.Remove(item); } } public static void Load() { _ = plugin; } public static void LoadLocalizationLater(Localization __instance) { LoadLocalization(Localization.instance, __instance.GetSelectedLanguage()); } public static void SafeCallLocalizeComplete() { Localizer.OnLocalizationComplete?.Invoke(); } private static void LoadLocalization(Localization __instance, string language) { if (!localizationLanguage.Remove(__instance)) { localizationObjects.Add(new WeakReference<Localization>(__instance)); } localizationLanguage.Add(__instance, language); Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories) where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0 select f) { string[] array = Path.GetFileNameWithoutExtension(item).Split('.'); if (array.Length >= 2) { string text = array[1]; if (dictionary.ContainsKey(text)) { Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped.")); } else { dictionary[text] = item; } } } byte[] array2 = LoadTranslationFromAssembly("English"); if (array2 == null) { throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml."); } Dictionary<string, string> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array2)); if (dictionary2 == null) { throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty."); } string text2 = null; if (language != "English") { if (dictionary.TryGetValue(language, out var value)) { text2 = File.ReadAllText(value); } else { byte[] array3 = LoadTranslationFromAssembly(language); if (array3 != null) { text2 = Encoding.UTF8.GetString(array3); } } } if (text2 == null && dictionary.TryGetValue("English", out var value2)) { text2 = File.ReadAllText(value2); } if (text2 != null) { foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>()) { dictionary2[item2.Key] = item2.Value; } } loadedTexts[language] = dictionary2; foreach (KeyValuePair<string, string> item3 in dictionary2) { UpdatePlaceholderText(__instance, item3.Key); } } static Localizer() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>(); loadedTexts = new Dictionary<string, Dictionary<string, string>>(); localizationLanguage = new ConditionalWeakTable<Localization, string>(); localizationObjects = new List<WeakReference<Localization>>(); fileExtensions = new List<string>(2) { ".json", ".yml" }; Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager"); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalizationLater", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "SafeCallLocalizeComplete", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static byte[]? LoadTranslationFromAssembly(string language) { foreach (string fileExtension in fileExtensions) { byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension); if (array != null) { return array; } } return null; } public static byte[]? ReadEmbeddedFileBytes(string resourceFileName, Assembly? containingAssembly = null) { 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(); } } [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 void Prefix(CharacterDrop __instance, out State __state) { __state = new State(null, hasOnePerPlayerScope: false, null); bool flag = PluginSettingsFacade.IsCharacterDomainEnabled(); if (flag || CharacterDropManager.IsGlobalCharacterLootLevelScalingEnabled()) { List<Drop> list = (flag ? CharacterDropManager.OverrideConditionalDrops(__instance) : null); __state = new State(list, hasOnePerPlayerScope: false, null); IReadOnlyList<Drop> sourceDrops; List<Drop> list2 = CharacterDropManager.SuppressGlobalCharacterLootLevelMultiplierDrops(__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.ApplyGlobalCharacterLootLevelMultiplier(__instance, __result, __state.AmountSourceDrops); if (__state.PreviousDrops != null) { __instance.m_drops = __state.PreviousDrops; } } private static Exception? Finalizer(CharacterDrop __instance, State __state, Exception? __exception) { if (__state.PreviousDrops != null) { __instance.m_drops = __state.PreviousDrops; } if (__state.HasOnePerPlayerScope) { CharacterDropManager.EndOnePerPlayerNearbyPlayerScope(); } return __exception; } } [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) { 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 (!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) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (PluginSettingsFacade.IsCharacterDomainEnabled()) { CharacterDropManager.ApplyGlobalDropInStack(ref drops, centerPos, dropArea); } } } [HarmonyPatch(typeof(Ragdoll), "Setup")] internal static class RagdollSetupMonsterInstantLootDropPatch { private static void Postfix(Ragdoll __instance, CharacterDrop characterDrop) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (!PluginSettingsFacade.IsMonsterInstantLootDropEnabled() || (Object)(object)characterDrop == (Object)null || !__instance.m_dropItems) { return; } ZNetView nview = __instance.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner()) { return; } ZDO zDO = nview.GetZDO(); if (zDO.GetInt(ZDOVars.s_drops, 0) > 0) { Vector3 val = __instance.GetAverageBodyPosition(); if ((Object)(object)__instance.m_lootSpawnJoint != (Object)null) { val = __instance.m_lootSpawnJoint.transform.position; } __instance.SpawnLoot(val); 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>) })] [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 void Prefix(CreatureSpawner __instance) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (PluginSettingsFacade.IsSpawnerDomainEnabled()) { 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); } } private static void Postfix(CreatureSpawner __instance, ZNetView __result) { if (PluginSettingsFacade.IsSpawnerDomainEnabled()) { SpawnerManager.ApplyCreatureSpawnerSpawnOverrides(__instance, __result); } } } [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) { SpawnSystemManager.UntrackLiveSystem(__instance); } } [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 void Prefix(SpawnData critter, Vector3 spawnPoint, out bool __state) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) __state = false; if (PluginSettingsFacade.IsSpawnSystemDomainEnabled() || SpawnSystemCustomDataSupport.HasPreparedPayload(critter)) { __state = true; SpawnSystemCustomDataSupport.InitializeSpawn(critter, spawnPoint); } } private static void Postfix(SpawnData critter, Vector3 spawnPoint, bool __state) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (__state) { SpawnSystemManager.ConsumeExtendedRequiredGlobalKeyAfterSpawn(critter); SpawnSystemCustomDataSupport.SpawnObjects(critter, spawnPoint); } } private static Exception? Finalizer(SpawnData critter, bool __state, Exception? __exception) { return __exception; } } 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 const string CurrentReferenceLogicVersion = "2026-03-26-full-rewrite-v1"; 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) { updateKind = ReferenceArtifactUpdateKind.None; if (!File.Exists(referencePath)) { updateKind = ReferenceArtifactUpdateKind.Created; return true; } 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"); } 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? OnePerPlayer { get; set; } [YamlMember(Order = 7)] public int? AmountLimit { get; set; } [YamlMember(Order = 8)] 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 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 CharacterDropItemSnapshot { public GameObject? ItemPrefab { get; set; } public int AmountMin { get; set; } public int AmountMax { get; set; } public float Chance { get; set; } public bool OnePerPlayer { get; set; } public bool LevelMultiplier { get; set; } public bool DontScale { get; set; } } internal sealed class CharacterDropSnapshot { public GameObject Prefab { get; set; } public List<CharacterDropItemSnapshot> Drops { get; set; } = new List<CharacterDropItemSnapshot>(); 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, IEnumerable<CharacterDrop> liveCharacterDrops, Func<CharacterDrop, string> getPrefabName, Func<string, bool> shouldRegisterPrefab, ISet<string>? additionalPrefabs = null, bool forceRescan = false) { if (!forceRescan && _lastBootstrappedLiveObjectsSceneSignature == sceneSignature) { return; } CleanupRegisteredCharacterDrops(); foreach (CharacterDrop liveCharacterDrop in liveCharacterDrops) { if (!((Object)(object)liveCharacterDrop == (Object)null) && !((Object)(object)((Component)liveCharacterDrop).gameObject == (Object)null)) { string text = getPrefabName(liveCharacterDrop); if (text.Length != 0 && (shouldRegisterPrefab(text) || (additionalPrefabs != null && additionalPrefabs.Contains(text)))) { RegisterLiveCharacterDrop(liveCharacterDrop, text); } } } _lastBootstrappedLiveObjectsSceneSignature = sceneSignature; } internal static IReadOnlyList<CharacterDrop> GetRegisteredCharacterDrops(HashSet<string>? dirtyPrefabs = null) { CleanupRegisteredCharacterDrops(); HashSet<CharacterDrop> visited = new HashSet<CharacterDrop>(); List<CharacterDrop> list = new List<CharacterDrop>(); if (dirtyPrefabs == null) { foreach (HashSet<CharacterDrop> value2 in LiveCharacterDropsByPrefab.Values) { AddRegisteredCharacterDrops(value2, visited, list); } return list; } foreach (string dirtyPrefab in dirtyPrefabs) { if (LiveCharacterDropsByPrefab.TryGetValue(dirtyPrefab, out HashSet<CharacterDrop> value)) { AddRegisteredCharacterDrops(value, visited, list); } } return list; } private static void AddRegisteredCharacterDrops(IEnumerable<CharacterDrop> characterDrops, ISet<CharacterDrop> visited, ICollection<CharacterDrop> registered) { foreach (CharacterDrop item in characterDrops ?? Enumerable.Empty<CharacterDrop>()) { if ((Object)(object)item != (Object)null && (Object)(object)((Component)item).gameObject != (Object)null && visited.Add(item)) { registered.Add(item); } } } private static void CleanupRegisteredCharacterDrops() { List<CharacterDrop> list = null; foreach (CharacterDrop item in LiveCharacterDropPrefabsByInstance.Keys.ToList()) { if ((Object)(object)item == (Object)null || (Object)(object)((Component)item).gameObject == (Object)null) { if (list == null) { list = new List<CharacterDrop>(); } list.Add(item); } } if (list == null) { return; } foreach (CharacterDrop item2 in list) { if (LiveCharacterDropPrefabsByInstance.TryGetValue(item2, out string value)) { UnregisterLiveCharacterDrop(item2, value); } } } private static void CompletePendingSnapshotBuild(PendingCharacterDropSnapshotBuildState buildState, Action<string, int, int> onCompleted) { if (_pendingSnapshotBuild == null || _pendingSnapshotBuild != buildState) { return; } Snapshots.Clear(); Snapshots.AddRange(buildState.Snapshots); SnapshotsByPrefab.Clear(); foreach (var (key, value) in buildState.SnapshotsByPrefab) { SnapshotsByPrefab[key] = value; } _lastBootstrappedLiveObjectsSceneSignature = null; _pendingSnapshotBuild = null; _lastProcessedSnapshotSignature = buildState.SnapshotSignature; _lastProcessedGameDataSignature = buildState.GameDataSignature; onCompleted(buildState.Source, buildState.GameDataSignature, buildState.SnapshotSignature); } } internal static class CharacterDropManager { private sealed class ResolvedConfiguredDrop { public GameObject Prefab { get; set; } public int Amount { get; set; } public bool DropInStack { get; set; } } private sealed class CharacterConfigurationState { public List<CharacterDropPrefabEntry> Configuration { get; } = new List<CharacterDropPrefabEntry>(); public Dictionary<string, List<CharacterDropPrefabEntry>> ActiveEntriesByPrefab { get; } = new Dictionary<string, List<CharacterDropPrefabEntry>>(StringComparer.OrdinalIgnoreCase); public HashSet<string> PrefabsWithCharacterDropOverrides { get; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public Dictionary<string, string> CurrentEntrySignaturesByPrefab { get; set; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); public string ConfigurationSignature { get; set; } = ""; } private sealed class CharacterRuntimeContextSnapshot { public int Frame { get; set; } public int TimeOfDayPhaseMarker { get; set; } public string EnvironmentName { get; set; } = ""; public Dictionary<string, bool> GlobalKeyStates { get; } = new Dictionary<string, bool>(StringComparer.Ordinal); } private sealed class CharacterApplyOperations : StandardBaselineDesiredStateOperations<CharacterDesiredState> { public static CharacterApplyOperations Instance { get; } = new CharacterApplyOperations(); public override string DomainKey => "character"; public override BaselineDesiredStateCapabilities Capabilities => BaselineDesiredStateCapabilities.Validation | BaselineDesiredStateCapabilities.StaticBaseline | BaselineDesiredStateCapabilities.StaticApply | BaselineDesiredStateCapabilities.LiveApply | BaselineDesiredStateCapabilities.StaticRollback; public override void Validate(CharacterDesiredState desiredState) { ValidateCharacterDesiredState(desiredState); } public override void RestoreStaticBaseline(CharacterDesiredState desiredState) { RestoreCharacterStaticBaseline(desiredState); } public override void ApplyDesiredStateToStaticBaseline(CharacterDesiredState desiredState) { ApplyCharacterDesiredStateToStaticBaseline(desiredState); } public override void ApplyDesiredStateToLive(CharacterDesiredState desiredState) { ApplyCharacterDesiredStateToLive(desiredState); } public override void Commit(CharacterDesiredState desiredState) { RecordAppliedState(desiredState.GameDataSignature, desiredState.DomainEnabled, desiredState.CurrentEntrySignatures, desiredState.EffectiveConfigurationSignature); } } private sealed class CharacterDesiredState { public StandardDomainApplyPlan ApplyPlan { get; set; } public CharacterCompiledState CompiledState { get; set; } = CharacterCompiledState.Empty; public int GameDataSignature { get; set; } public string EffectiveConfigurationSignature { get; set; } = ""; public Dictionary<string, string> CurrentEntrySignatures { get; set; } = EmptyEntrySignatures; public bool DomainEnabled { get; set; } } private const string ReferenceAutoUpdateStateKey = "character"; internal static readonly DomainModuleDefinition<CharacterDropPrefabEntry> Module = new DomainModuleDefinition<CharacterDropPrefabEntry>(new DomainModuleOptions<CharacterDropPrefabEntry> { DomainKey = "character", ReloadDomain = DropNSpawnPlugin.ReloadDomain.Character, ManifestSettingKey = "character_yaml", ManifestPriority = 99, ShouldReloadForPath = ShouldReloadForPath, Reload = ReloadConfiguration, InitializeRuntime = Initialize, OnGameDataReady = OnGameDataReady, HandleExpandWorldDataReady = HandleExpandWorldDataReady, DtoVersion = 10, TransportProfile = DomainTransportProfile.SmallConfig, DisplayName = "character", CacheDirectoryName = "character", ClientRequestPriority = 10, KeySelector = (CharacterDropPrefabEntry entry) => entry.RuleId, ApplyPayloadAction = ApplySyncedPayload, HasPendingSnapshotBuildWork = HasPendingSnapshotBuildWork, ProcessPendingSnapshotBuildStep = ProcessPendingSnapshotBuildStep, BeforeClientManifestChanged = MarkSyncedPayloadPending, OnClientAuthorityCutover = EnterPendingSyncedPayloadState }); private static readonly object Sync = new object(); private static readonly IDeserializer Deserializer = new DeserializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).Build(); private static readonly ISerializer Serializer = new SerializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitNull | DefaultValuesHandling.OmitDefaults).Build(); private static CharacterConfigurationState RuntimeState = new CharacterConfigurationState(); private static readonly InvalidEntryDiagnostics InvalidEntryWarnings = new InvalidEntryDiagnostics(); private static readonly FieldInfo? DropsEnabledField = AccessTools.Field(typeof(CharacterDrop), "m_dropsEnabled"); [ThreadStatic] private static CharacterDrop? OnePerPlayerScopeCharacterDrop; [ThreadStatic] private static int OnePerPlayerScopeDepth; private static bool _initialized; private static CharacterCompiledState _compiledState = CharacterCompiledState.Empty; private static string _compiledStateConfigurationSignature = ""; private static int? _compiledStateGameDataSignature; private static bool _referenceArtifactsAutoRefreshConsumed; private static readonly Dictionary<string, string> _lastAppliedEntrySignaturesByPrefab = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); private static string _lastAppliedConfigurationSignature = ""; private static int? _lastAppliedGameDataSignature; private static bool? _lastAppliedDomainEnabled; private static bool _lastAppliedSynchronizedPayloadReady; private static bool _synchronizedPayloadReady; private static int? _lastCommittedAuthorityEpoch; private static CharacterRuntimeContextSnapshot? _runtimeContextSnapshot; private static int _cachedFrameGameDataSignatureFrame = -1; private static int _cachedFrameGameDataSignatureValue; private const string MockPrefabPrefix = "JVLmock_"; private const float ConfiguredDropGroundOffset = 0.2f; private const int MaxCachedRuntimeDropResolutionsPerPrefab = 32; private static readonly DomainConfigurationRuntime<CharacterDropPrefabEntry, CharacterConfigurationState> ConfigurationRuntime = new DomainConfigurationRuntime<CharacterDropPrefabEntry, CharacterConfigurationState>(new DomainLoadHooks<CharacterDropPrefabEntry, CharacterConfigurationState>(ParseLocalConfigurationDocuments, BuildSyncedConfigurationState, CommitSyncedConfigurationState, RejectLocalConfigurationPayload, (CharacterConfigurationState state) => state.Configuration.Count, LogPartiallyAcceptedLocalConfiguration, LogLocalConfigurationLoaded, OnSourceOfTruthPayloadUnchanged, delegate { ConfigurationDomainHost.PublishSyncedPayload(DropNSpawnPlugin.IsSourceOfTruth, Descriptor, RuntimeState.Configuration, RuntimeState.ConfigurationSignature); }), new DomainSyncHooks<CharacterDropPrefabEntry, CharacterConfigurationState>(delegate(out List<CharacterDropPrefabEntry> configuration, out string payloadToken) { return ConfigurationDomainHost.TryGetSyncedEntries(Descriptor, out configuration, out payloadToken); }, (string payloadToken) => ConfigurationDomainHost.ShouldSkipSyncedPayload(LoadState, payloadToken, Volatile.Read(in _synchronizedPayloadReady)), BuildSyncedConfigurationState, CommitSyncedConfigurationState, (CharacterConfigurationState state) => state.ActiveEntriesByPrefab.Count, "ServerSync:DropNSpawnCharacter", MarkSyncedPayloadPending, LogSyncedCharacterConfigurationLoaded, LogSyncedCharacterConfigurationFailure)); private static readonly Dictionary<string, string> EmptyEntrySignatures = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); internal static DomainDescriptor<CharacterDropPrefabEntry> Descriptor => Module.DescriptorTyped; internal static DomainTransportMetadata<CharacterDropPrefabEntry> TransportMetadata => Module.TransportMetadataTyped; private static DomainLoadState LoadState => ConfigurationRuntime.LoadState; private static string ReferenceConfigurationPath => Path.Combine(DropNSpawnPlugin.YamlConfigDirectoryPath, PluginSettingsFacade.GetYamlDomainFilePrefix("character") + ".reference.yml"); private static string PrimaryOverrideConfigurationPathYml => Path.Combine(DropNSpawnPlugin.YamlConfigDirectoryPath, PluginSettingsFacade.GetYamlDomainFilePrefix("character") + ".yml"); private static string PrimaryOverrideConfigurationPathYaml => Path.Combine(DropNSpawnPlugin.YamlConfigDirectoryPath, PluginSettingsFacade.GetYamlDomainFilePrefix("character") + ".yaml"); private static string FullScaffoldConfigurationPath => Path.Combine(DropNSpawnPlugin.YamlConfigDirectoryPath, PluginSettingsFacade.GetYamlDomainFilePrefix("character") + ".full.yml"); internal static bool ShouldReloadForPath(string? path) { if (PluginSettingsFacade.IsEligibleOverrideConfigurationPath(path)) { return IsOverrideConfigurationFileName(Path.GetFileName(path ?? "")); } return false; } private static bool ShouldApplyLocally() { return PluginSettingsFacade.IsCharacterDomainEnabled(); } internal static void Initialize() { lock (Sync) { if (!_initialized) { LoadConfiguration(); _initialized = true; } } } internal static void ReloadConfiguration() { lock (Sync) { LoadConfiguration(); ApplyIfReady(); } } internal static void MarkSyncedPayloadPending() { lock (Sync) { ConfigurationRuntime.MarkSyncedPayloadPending(DropNSpawnPlugin.IsSourceOfTruth, delegate { Volatile.Write(ref _synchronizedPayloadReady, value: false); }); } } internal static void EnterPendingSyncedPayloadState() { lock (Sync) { Dictionary<string, string> previousEntrySignatures = CloneCurrentEntrySignaturesByPrefab(); HashSet<string> previouslyAppliedPrefabs = BuildLastAppliedPrefabs(); ConfigurationRuntime.EnterPendingSyncedPayloadState(DropNSpawnPlugin.IsSourceOfTruth, ResetLoadedConfigurationState, delegate { RuntimeState.ConfigurationSignature = ""; _lastAppliedSynchronizedPayloadReady = false; RestoreSnapshots(previouslyAppliedPrefabs); RestoreTrackedCharacterDrops(previouslyAppliedPrefabs); RefreshVneiCompatibility(previousEntrySignatures); }); } } private static bool CanUseCurrentRuntimeState() { if (!DropNSpawnPlugin.IsSourceOfTruth && !Volatile.Read(in _synchronizedPayloadReady)) { return _lastCommittedAuthorityEpoch == NetworkPayloadSyncSupport.CurrentAuthorityEpoch; } return true; } private static HashSet<string> BuildLastAppliedPrefabs() { HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); if (_lastAppliedDomainEnabled != true) { return hashSet; } foreach (string key in _lastAppliedEntrySignaturesByPrefab.Keys) { hashSet.Add(key); } return hashSet; } internal static bool HandleExpandWorldDataReady() { lock (Sync) { if (!DropNSpawnPlugin.IsSourceOfTruth) { return false; } string text = NetworkPayloadSyncSupport.ComputeCharacterConfigurationSignature(RuntimeState.Configuration); if (string.Equals(text, RuntimeState.ConfigurationSignature, StringComparison.Ordinal)) { return false; } RuntimeState.ConfigurationSignature = text; ConfigurationDomainHost.PublishSyncedPayload(DropNSpawnPlugin.IsSourceOfTruth, Descriptor, RuntimeState.Configuration, RuntimeState.ConfigurationSignature); ApplyIfReady(); return true; } } internal static void ApplySyncedPayload() { lock (Sync) { Dictionary<string, string> previousEntrySignatures = CloneCurrentEntrySignaturesByPrefab(); ConfigurationRuntime.ApplySyncedPayload(delegate { RefreshVneiCompatibility(previousEntrySignatures, CloneCurrentEntrySignaturesByPrefab()); ApplyIfReady(); }); } } internal static void OnGameDataReady(string source) { lock (Sync) { if (!_initialized) { Initialize(); } if (!IsGameDataReady()) { return; } int gameDataSignature = ComputeGameDataSignature(); if (!CharacterDropRuntime.IsGameDataAlreadyProcessed(gameDataSignature)) { int snapshotSignature = ComputeSnapshotSignature(); if (CharacterDropRuntime.NeedsSnapshotBuild(snapshotSignature)) { CharacterDropRuntime.ScheduleSnapshotBuild(source, gameDataSignature, snapshotSignature, EnumerateRelevantPrefabs()); } else { CompleteGameDataReadyLocked(source, gameDataSignature, snapshotSignature); } } } } internal static bool HasPendingSnapshotBuildWork() { lock (Sync) { return CharacterDropRuntime.HasPendingSnapshotBuildWork(); } } internal static bool ProcessPendingSnapshotBuildStep(double deadline) { lock (Sync) { return CharacterDropRuntime.ProcessPendingSnapshotBuildStep(deadline, CaptureSnapshot, CompleteGameDataReadyLocked); } } private static bool IsGameDataReady() { if ((Object)(object)ZNetScene.instance != (Object)null) { return (Object)(object)ObjectDB.instance != (Object)null; } return false; } private static bool EnsurePrimaryOverrideConfigurationFileExists() { if (DomainConfigurationFileSupport.HasAnyOverrideConfigurationFile("character", PrimaryOverrideConfigurationPathYml, PrimaryOverrideConfigurationPathYaml)) { return false; } if (!IsGameDataReady() || !CharacterDropRuntime.HasSnapshots()) { return false; } GeneratedArtifactWriter.WriteTextAlways(PrimaryOverrideConfigurationPathYml, BuildPrimaryOverrideConfigurationTemplate(), "Created character override configuration at " + PrimaryOverrideConfigurationPathYml + "."); return true; } private static void LoadConfiguration() { Dictionary<string, string> previousEntrySignatures = CloneCurrentEntrySignaturesByPrefab(); if (DropNSpawnPlugin.IsSourceOfTruth) { EnsurePrimaryOverrideConfigurationFileExists(); if (ConfigurationRuntime.ReloadSourceOfTruth(EnumerateOverrideConfigurationPaths().ToList()) == DomainReloadOutcome.Loaded) { RefreshVneiCompatibility(previousEntrySignatures); } } else if (ConfigurationRuntime.ReloadSynced() == DomainReloadOutcome.Loaded) { RefreshVneiCompatibility(previousEntrySignatures, CloneCurrentEntrySignaturesByPrefab()); } } private static void CompleteGameDataReadyLocked(string source, int gameDataSignature, int snapshotSignature) { if (DropNSpawnPlugin.IsSourceOfTruth && !_referenceArtifactsAutoRefreshConsumed) { EnsureReferenceArtifactsUpToDate(); _referenceArtifactsAutoRefreshConsumed = true; } if (DropNSpawnPlugin.IsSourceOfTruth && EnsurePrimaryOverrideConfigurationFileExists()) { LoadConfiguration(); } ApplyIfReady(); } private static void ResetLoadedConfigurationState() { RuntimeState = new CharacterConfigurationState(); InvalidEntryWarnings.Clear(); _compiledState = CharacterCompiledState.Empty; _compiledStateConfigurationSignature = ""; _compiledStateGameDataSignature = null; _cachedFrameGameDataSignatureFrame = -1; _cachedFrameGameDataSignatureValue = 0; Volatile.Write(ref _synchronizedPayloadReady, value: false); } internal static void ResetWorldRuntimeState() { lock (Sync) { HashSet<string> hashSet = BuildLastAppliedPrefabs(); RestoreSnapshots(hashSet); RestoreTrackedCharacterDrops(hashSet); CharacterDropRuntime.Reset(); _compiledState = CharacterCompiledState.Empty; _compiledStateConfigurationSignature = ""; _compiledStateGameDataSignature = null; _lastAppliedEntrySignaturesByPrefab.Clear(); _lastAppliedConfigurationSignature = ""; _lastAppliedGameDataSignature = null; _lastAppliedDomainEnabled = null; _lastAppliedSynchronizedPayloadReady = false; _runtimeContextSnapshot = null; _cachedFrameGameDataSignatureFrame = -1; _cachedFrameGameDataSignatureValue = 0; OnePerPlayerScopeCharacterDrop = null; OnePerPlayerScopeDepth = 0; } } private static List<CharacterDropPrefabEntry> CloneAndNormalizeConfigurationEntries(List<CharacterDropPrefabEntry>? configuration, string sourceName) { List<CharacterDropPrefabEntry> list = NetworkPayloadSyncSupport.CloneEntries(Descriptor, configuration); foreach (CharacterDropPrefabEntry item in list) { NormalizeEntry(item); item.SourcePath = (string.IsNullOrWhiteSpace(item.SourcePath) ? sourceName : item.SourcePath); } return list; } private static List<CharacterDropPrefabEntry> PrepareLocalConfigurationEntries(List<CharacterDropPrefabEntry>? configuration, string sourceName, List<string> warnings) { List<CharacterDropPrefabEntry> list = CloneAndNormalizeConfigurationEntries(configuration, sourceName); List<CharacterDropPrefabEntry> list2 = new List<CharacterDropPrefabEntry>(); foreach (CharacterDropPrefabEntry item in list) { if (TryAcceptLocalConfigurationEntry(item, warnings)) { list2.Add(item); } } return list2; } private static bool TryAcceptLocalConfigurationEntry(CharacterDropPrefabEntry entry, List<string> warnings) { if (!entry.Enabled) { return true; } string text = CreateConfigurationContext(entry); bool flag = entry.CharacterDrop != null; if (string.IsNullOrWhiteSpace(entry.Prefab)) { warnings.Add("Entry '" + text + "' is missing required prefab."); return false; } if (!flag) { warnings.Add("Entry '" + text + "' does not define characterDrop."); return false; } if (!TryResolveConfiguredCharacterPrefab(entry.Prefab, out var hasCharacterComponent, out var hasCharacterDropComponent)) { warnings.Add("Entry '" + text + "' references unknown character prefab '" + entry.Prefab + "'."); return false; } if (!hasCharacterComponent) { warnings.Add("Entry '" + text + "' references '" + entry.Prefab + "', but it is not a Character prefab."); return false; } if (flag && !hasCharacterDropComponent) { warnings.Add("Entry '" + text + "' references '" + entry.Prefab + "', but it is not a CharacterDrop prefab."); return false; } return true; } private static bool TryResolveConfiguredCharacterPrefab(string prefabName, out bool hasCharacterComponent, out bool hasCharacterDropComponent) { hasCharacterComponent = true; hasCharacterDropComponent = true; if ((Object)(object)ZNetScene.instance == (Object)null || string.IsNullOrWhiteSpace(prefabName)) { return true; } GameObject prefab = ZNetScene.instance.GetPrefab(prefabName.Trim()); if ((Object)(object)prefab == (Object)null) { hasCharacterComponent = false; hasCharacterDropComponent = false; return false; } hasCharacterComponent = (Object)(object)prefab.GetComponent<Character>() != (Object)null; hasCharacterDropComponent = (Object)(object)prefab.GetComponent<CharacterDrop>() != (Object)null; return true; } private static CharacterConfigurationState BuildSyncedConfigurationState(List<CharacterDropPrefabEntry> configuration, string sourceName) { using (BeginInvalidEntryWarningSuppressionForSyncedClientBuild(sourceName)) { CharacterConfigurationState characterConfigurationState = new CharacterConfigurationState(); foreach (CharacterDropPrefabEntry item in CloneAndNormalizeConfigurationEntries(configuration, sourceName)) { if (!string.IsNullOrWhiteSpace(item.Prefab)) { RemoveEffectiveConfigurationEntry(characterConfigurationState.Configuration, characterConfigurationState.ActiveEntriesByPrefab, item.Prefab, item.RuleId); if (item.Enabled) { characterConfigurationState.Configuration.Add(item); GetOrCreateActiveEntries(characterConfigurationState.ActiveEntriesByPrefab, item.Prefab).Add(item); } } } RebuildCharacterDropOverridePrefabSet(characterConfigurationState.ActiveEntriesByPrefab, characterConfigurationState.PrefabsWithCharacterDropOverrides); characterConfigurationState.ConfigurationSignature = NetworkPayloadSyncSupport.ComputeCharacterConfigurationSignature(characterConfigurationState.Configuration); characterConfigurationState.CurrentEntrySignaturesByPrefab = BuildActiveEntrySignaturesByPrefab(characterConfigurationState.ActiveEntriesByPrefab); return characterConfigurationState; } } private static void CommitSyncedConfigurationState(CharacterConfigurationState state, string payloadToken) { ResetLoadedConfigurationState(); RuntimeState = state; LoadState.LastLoadedPayload = payloadToken; LoadState.LastRejectedPayload = ""; LoadState.PendingStrictPayload = ""; LoadState.LastRejectedValidationKey = ""; Volatile.Write(ref _synchronizedPayloadReady, value: true); _lastCommittedAuthorityEpoch = (DropNSpawnPlugin.IsSourceOfTruth ? ((int?)null) : new int?(NetworkPayloadSyncSupport.CurrentAuthorityEpoch)); } private static LocalLoadResult<CharacterDropPrefabEntry> ParseLocalConfigurationDocuments(List<ConfigurationLoadSupport.LocalYamlDocument> documents) { return ConfigurationLoadSupport.ParseLocalConfigurationDocuments(documents, ParseConfiguration, PrepareLocalConfigurationEntries, FormatYamlExceptionLocation, "Character override YAML must start with a root list like '- prefab: ...'."); } private static void RejectLocalConfigurationPayload(string payload, IEnumerable<string> errors) { ConfigurationDomainHost.RejectLocalConfigurationPayload(LoadState, payload, errors, "character"); } private static void RebuildCharacterDropOverridePrefabSet(Dictionary<string, List<CharacterDropPrefabEntry>> activeEntriesByPrefab, HashSet<string> target) { target.Clear(); foreach (var (item, source) in activeEntriesByPrefab) { if (source.Any((CharacterDropPrefabEntry entry) => entry.CharacterDrop != null)) { target.Add(item); } } } private static bool RemoveEffectiveConfigurationEntry(List<CharacterDropPrefabEntry> configuration, Dictionary<string, List<CharacterDropPrefabEntry>> activeEntriesByPrefab, string prefabName, string ruleId) { bool result = false; for (int num = configuration.Count - 1; num >= 0; num--) { CharacterDropPrefabEntry characterDropPrefabEntry = configuration[num]; if (string.Equals(characterDropPrefabEntry.Prefab, prefabName, StringComparison.OrdinalIgnoreCase) && string.Equals(characterDropPrefabEntry.RuleId, ruleId, StringComparison.Ordinal)) { configuration.RemoveAt(num); result = true; } } if (activeEntriesByPrefab.TryGetValue(prefabName, out List<CharacterDropPrefabEntry> value)) { for (int num2 = value.Count - 1; num2 >= 0; num2--) { if (string.Equals(value[num2].RuleId, ruleId, StringComparison.Ordinal)) { value.RemoveAt(num2); result = true; } } if (value.Count == 0) { activeEntriesByPrefab.Remove(prefabName); } } return result; } private static ConfigurationLoadSupport.ParsedLocalConfiguration<CharacterDropPrefabEntry> ParseConfiguration(string yaml, string? sourcePath) { ConfigurationLoadSupport.ParsedLocalConfiguration<CharacterDropPrefabEntry> parsedLocalConfiguration = new ConfigurationLoadSupport.ParsedLocalConfiguration<CharacterDropPrefabEntry>(); if (string.IsNullOrWhiteSpace(yaml)) { return parsedLocalConfiguration; } checked { using StringReader input = new StringReader(yaml); YamlStream yamlStream = new YamlStream(); yamlStream.Load(input); if (yamlStream.Documents.Count == 0) { return parsedLocalConfiguration; } foreach (YamlNode child in ((yamlStream.Documents[0].RootNode as YamlSequenceNode) ?? throw new YamlException(yamlStream.Documents[0].RootNode.Start, yamlStream.Documents[0].RootNode.End, "Character override YAML root must be a sequence.")).Children) { if (!(child is YamlMappingNode yamlMappingNode)) { parsedLocalConfiguration.Warnings.Add("Skipped character YAML node at " + FormatYamlNodeLocation(sourcePath, child.Start) + ". Expected a list item object like '- prefab: Fox' but found " + DescribeYamlNode(child) + "."); continue; } try { string input2 = SerializeYamlNode(yamlMappingNode); CharacterDropPrefabEntry characterDropPrefabEntry = Deserializer.Deserialize<CharacterDropPrefabEntry>(input2) ?? new CharacterDropPrefabEntry(); characterDropPrefabEntry.SourceLine = (int)yamlMappingNode.Start.Line; characterDropPrefabEntry.SourceColumn = (int)yamlMappingNode.Start.Column; parsedLocalConfiguration.Configuration.Add(characterDropPrefabEntry); } catch (Exception ex) { parsedLocalConfiguration.Warnings.Add("Skipped invalid character entry at " + FormatYamlNodeLocation(sourcePath, yamlMappingNode.Start) + ". " + FormatEntryParseFailure(ex)); } } return parsedLocalConfiguration; } } private static string SerializeYamlNode(YamlNode node) { YamlStream yamlStream = new YamlStream(new YamlDocument(node)); using StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); yamlStream.Save(stringWriter, assignAnchors: false); return stringWriter.ToString(); } private static string DescribeYamlNode(YamlNode node) { if (node is YamlScalarNode yamlScalarNode) { string text = yamlScalarNode.Value ?? ""; if (text.Length != 0) { return "scalar '" + text + "'"; } return "an empty scalar"; } if (node is YamlSequenceNode) { return "a nested sequence"; } if (node is YamlMappingNode) { return "a mapping"; } return "an unknown YAML node"; } private static string FormatYamlNodeLocation(string? sourcePath, Mark mark) { string text = (string.IsNullOrWhiteSpace(sourcePath) ? "inline YAML" : Path.GetFileName(sourcePath)); if (mark.Line > 0) { text = text + ":" + mark.Line.ToString(CultureInfo.InvariantCulture); } return text; } private static string FormatEntryParseFailure(Exception ex) { if (ex is YamlException ex2) { return ex2.Message; } return ex.Message; } private static void NormalizeEntry(CharacterDropPrefabEntry entry) { entry.Prefab = (entry.Prefab ?? "").Trim(); if (entry.CharacterDrop != null) { CharacterDropDefinition characterDrop = entry.CharacterDrop; if (characterDrop.Drops == null) { List<CharacterDropEntryDefinition> list = (characterDrop.Drops = new List<CharacterDropEntryDefinition>()); } foreach (CharacterDropEntryDefinition drop in entry.CharacterDrop.Drops) { drop.Item = (drop.Item ?? "").Trim(); IntRangeDefinition? amount = drop.Amount; if (amount != null && amount.HasValues()) { drop.AmountMin = RangeFormatting.GetMin(drop.Amount, drop.AmountMin); drop.AmountMax = RangeFormatting.GetMax(drop.Amount, drop.AmountMin, drop.AmountMax); } } } entry.RuleId = NormalizeOptionalRuleId(entry.RuleId) ?? BuildRuleId(entry); } private static string BuildRuleId(CharacterDropPrefabEntry entry) { CharacterDropPrefabEntry entry2 = new CharacterDropPrefabEntry { Prefab = entry.Prefab, Enabled = true, Conditions = entry.Conditions, CharacterDrop = entry.CharacterDrop }; return entry.Prefab + ":" + NetworkPayloadSyncSupport.ComputeCharacterEntryIdentitySignature(entry2); } private static string? NormalizeOptionalRuleId(string? ruleId) { if (ruleId == null) { return null; } string text = ruleId.Trim(); if (text.Length != 0) { return text; } return null; } private static bool HasCustomDropHandling(IReadOnlyList<CompiledCharacterDropDefinition>? drops) { return drops?.Any((CompiledCharacterDropDefinition drop) => (drop.AmountLimit.HasValue && drop.AmountLimit.Value >= 0) || drop.DropInStack) ?? false; } internal static void ApplyGlobalDropInStack(ref List<KeyValuePair<GameObject, int>> drops, Vector3 centerPos, float dropArea) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (!PluginSettingsFacade.IsGlobalCharacterDropInStackEnabled() || drops.Count == 0) { return; } List<KeyValuePair<GameObject, int>> list = new List<KeyValuePair<GameObject, int>>(drops.Count); bool flag = false; foreach (KeyValuePair<GameObject, int> drop in drops) { if (!ShouldDropInStack(drop.Key, drop.Value, explicitDropInStack: false)) { list.Add(drop); continue; } SpawnStackedDrops(drop.Key, drop.Value, centerPos, dropArea); flag = true; } if (flag) { drops = list; } } internal static bool IsGlobalCharacterLootLevelScalingEnabled() { if (PluginSettingsFacade.ShouldDisableCharacterLootScalingForCreatureLevelControl()) { return false; } if (!PluginSettingsFacade.IsCharacterDropCalculateChanceLootSystemEnabled()) { return PluginSettingsFacade.IsGlobalCharacterDropTrophyLevelMultiplierEnabled(); } return true; } internal static List<Drop>? SuppressGlobalCharacterLootLevelMultiplierDrops(CharacterDrop characterDrop, out IReadOnlyList<Drop>? sourceDrops) { sourceDrops = null; if (!IsGlobalCharacterLootLevelScalingEnabled() || (Object)(object)characterDrop == (Object)null || characterDrop.m_drops == null || characterDrop.m_drops.Count == 0) { return null; } List<Drop> list = (List<Drop>)(sourceDrops = characterDrop.m_drops); List<Drop> list2 = null; for (int