using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.0.0.0")] namespace DragonMotion.BalrondNatureOptimizer; [BepInPlugin("dragonmotion.balrondnatureoptimizer", "BalrondNatureOptimizer", "0.6.6")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class BalrondNatureOptimizerPlugin : BaseUnityPlugin { public const string PluginGuid = "dragonmotion.balrondnatureoptimizer"; public const string PluginName = "BalrondNatureOptimizer"; public const string PluginVersion = "0.6.6"; private const string BalrondGuid = "balrond.astafaraios.BalrondAmazingNature"; private static readonly Harmony Harmony = new Harmony("dragonmotion.balrondnatureoptimizer"); private static readonly HashSet BalrondSwampWorldVegetation = new HashSet(StringComparer.Ordinal) { "WetTree1_bal", "WetTree2_bal", "WetTree3_bal", "WetTree_Stub_bal", "LinedSwampTreeLarge_bal", "LinedSwampTreeLarge2_bal", "Oak_Swamp_bal", "sapling_Swamp_bal", "Swamp_Seedling_bal", "MineRock_Guck_bal", "Pickable_GuckSack_bal" }; private static readonly HashSet AdjustedBiomeMessageTitles = new HashSet(); private static ConfigEntry _enableCustomLavaDamagePatch; private static ConfigEntry _enableMonsterDoorSensor; private static ConfigEntry _enableMonsterClimbPatch; private static ConfigEntry _fixBiomeMessageWidth; private static ConfigEntry _disablePoisonGeysers; private static ConfigEntry _deleteExistingPoisonGeyserZdos; private static ConfigEntry _disableBalrondSwampClutter; private static ConfigEntry _disableBalrondSwampWorldVegetation; private static ConfigEntry _cleanupRuntimeOnTeleport; private static bool _worldVegetationFilterInstalled; private static bool _teleportCleanupPending; private static bool _wasTeleporting; private static bool _poisonGeyserZdoCleanupStarted; private static readonly FieldInfo MessageHudBiomeMsgInstanceField = AccessTools.Field(typeof(MessageHud), "m_biomeMsgInstance"); private static readonly FieldInfo ZdoManObjectsByIdField = AccessTools.Field(typeof(ZDOMan), "m_objectsByID"); private static readonly FieldInfo ZdoUidField = AccessTools.Field(typeof(ZDO), "m_uid"); private void Awake() { _enableCustomLavaDamagePatch = ((BaseUnityPlugin)this).Config.Bind("Balrond Hot Paths", "Enable CustomLavaDamagePatch", false, "Keeps Balrond's custom lava and plains heat patches. Disabled by default because they add Character.CustomFixedUpdate/UpdateLava/UpdateHeatDamage/UpdateHeatEffects work."); _enableMonsterDoorSensor = ((BaseUnityPlugin)this).Config.Bind("Balrond Hot Paths", "Enable MonsterDoorSensor", false, "Keeps Balrond's monster door-opening sensors. Disabled by default to avoid per-door Update checks."); _enableMonsterClimbPatch = ((BaseUnityPlugin)this).Config.Bind("Balrond Hot Paths", "Enable MonsterClimbPatch", false, "Keeps Balrond's monster climb/slope movement postfix. Disabled by default because it adds Character.CustomFixedUpdate work and can cause monster movement issues."); _fixBiomeMessageWidth = ((BaseUnityPlugin)this).Config.Bind("Balrond Bug Fixes", "Fix Biome Message Width", true, "Stops Balrond from increasing biome discovery title width every UpdateBiomeFound call."); _disablePoisonGeysers = ((BaseUnityPlugin)this).Config.Bind("Balrond Swamp", "Disable Poison Geysers", true, "Removes Balrond poison geyser and poison geyser spawner vegetation and disables their runtime effects while keeping prefabs loadable for existing world ZDOs."); _deleteExistingPoisonGeyserZdos = ((BaseUnityPlugin)this).Config.Bind("Balrond Swamp", "Delete Existing Poison Geyser ZDOs", true, "Permanently deletes already-spawned PoisonGeyser_bal and PoisonGeyserSpawner_bal world ZDOs when poison geysers are disabled."); _disableBalrondSwampClutter = ((BaseUnityPlugin)this).Config.Bind("Balrond Swamp", "Disable Balrond Swamp Clutter", true, "Removes Balrond's Swampy1-Swampy12 clutter entries before the clutter system rebuilds."); _disableBalrondSwampWorldVegetation = ((BaseUnityPlugin)this).Config.Bind("Balrond Swamp", "Disable Balrond Swamp World Vegetation", true, "Removes Balrond's extra swamp world vegetation entries while keeping item prefabs, recipes, cultivator pieces, and loot sources intact."); _cleanupRuntimeOnTeleport = ((BaseUnityPlugin)this).Config.Bind("Balrond Cleanup", "Cleanup Runtime On Teleport", true, "After distant teleports, clears disabled Balrond runtime components and stale lists without deleting world ZDOs or recipes."); ApplyBalrondOptimizations(); } private void OnDestroy() { Harmony.UnpatchSelf(); } private static void ApplyBalrondOptimizations() { if (!_enableCustomLavaDamagePatch.Value) { DisableBalrondLavaPatch(); } if (!_enableMonsterDoorSensor.Value) { DisableBalrondMonsterDoorSensors(); } if (!_enableMonsterClimbPatch.Value) { DisableBalrondMonsterClimbPatch(); } if (_fixBiomeMessageWidth.Value) { FixBalrondBiomeMessageWidth(); } if (_disablePoisonGeysers.Value) { DisableBalrondPoisonGeysers(); } if (_disableBalrondSwampWorldVegetation.Value) { InstallBalrondWorldVegetationFilter(); } if (_disableBalrondSwampClutter.Value) { DisableBalrondSwampClutter(); } if (_cleanupRuntimeOnTeleport.Value) { InstallBalrondRuntimeCleanup(); } } private static void DisableBalrondLavaPatch() { Type type = AccessTools.TypeByName("BalrondNature.Launch+CustomLavaDamagePatch"); FieldInfo fieldInfo = ((type == null) ? null : AccessTools.Field(type, "Enabled")); if (fieldInfo != null) { fieldInfo.SetValue(null, false); } UnpatchSpecificBalrondPatch(typeof(Character), "CustomFixedUpdate", "BalrondNature.Launch+CustomLavaDamagePatch", "Postfix"); UnpatchSpecificBalrondPatch(typeof(Character), "UpdateLava", "BalrondNature.PlainsMiniHeatPatches+Character_UpdateLava_PlainsMiniHeat_Patch", "Prefix", new Type[1] { typeof(float) }); UnpatchSpecificBalrondPatch(typeof(Character), "UpdateHeatDamage", "BalrondNature.PlainsMiniHeatPatches+Character_UpdateHeatDamage_PlainsMiniHeatDamage_Patch", "Prefix", new Type[1] { typeof(float) }); UnpatchSpecificBalrondPatch(typeof(Character), "UpdateHeatEffects", "BalrondNature.PlainsMiniHeatPatches+Character_UpdateHeatEffects_PlainsVisuals_Patch", "Postfix", new Type[1] { typeof(float) }); } private static void DisableBalrondMonsterDoorSensors() { UnpatchSpecificBalrondPatch(typeof(ZNetScene), "Awake", "BalrondNature.WorldGenPatches+Patch_ZNetScene_Awake_MonsterDoorSensors", "Postfix"); PatchPostfix(typeof(ZNetScene), "Awake", "ZNetSceneAwakePostfixRemoveMonsterDoorSensors"); } private static void DisableBalrondMonsterClimbPatch() { UnpatchSpecificBalrondPatch(typeof(Character), "CustomFixedUpdate", "BalrondNature.CombatPatches+MonsterClimbPatch", "Postfix", new Type[1] { typeof(float) }); } private static void DisableBalrondPoisonGeysers() { InstallBalrondWorldVegetationFilter(); PatchPostfixAfterBalrond(typeof(ZNetScene), "Awake", "ZNetSceneAwakePostfixDisablePoisonGeysers"); Type type = AccessTools.TypeByName("BalrondNature.MonsterManager"); if (type != null) { PatchPrefix(type, "doSpawnerChanges", "SkipPoisonGeyserSpawnerSetupPrefix"); } } private static void DisableBalrondSwampClutter() { PatchPostfixAfterBalrond(typeof(ClutterSystem), "Awake", "ClutterSystemAwakePostfixRemoveBalrondSwampClutter"); } private static void InstallBalrondWorldVegetationFilter() { if (!_worldVegetationFilterInstalled) { _worldVegetationFilterInstalled = true; PatchPostfixAfterBalrond(typeof(ZoneSystem), "SetupLocations", "ZoneSystemSetupLocationsPostfixRemoveDisabledBalrondVegetation"); } } private static void InstallBalrondRuntimeCleanup() { PatchPrefix(typeof(Player), "TeleportTo", "PlayerTeleportToPrefix", new Type[3] { typeof(Vector3), typeof(Quaternion), typeof(bool) }); PatchPostfix(typeof(Player), "UpdateTeleport", "PlayerUpdateTeleportPostfix", new Type[1] { typeof(float) }); PatchPostfix(typeof(Game), "Logout", "GameLogoutPostfix"); } private static void FixBalrondBiomeMessageWidth() { UnpatchSpecificBalrondPatch(typeof(MessageHud), "UpdateBiomeFound", "BalrondNature.WorldGenPatches+MessageHud_UpdateBiomeFound_Awake", "Postfix"); PatchPostfix(typeof(MessageHud), "UpdateBiomeFound", "MessageHudUpdateBiomeFoundPostfix"); } private static void PatchPostfix(Type originalType, string originalName, string postfixName, Type[] argumentTypes = null) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown MethodInfo methodInfo = ((argumentTypes == null) ? AccessTools.Method(originalType, originalName, (Type[])null, (Type[])null) : AccessTools.Method(originalType, originalName, argumentTypes, (Type[])null)); MethodInfo methodInfo2 = AccessTools.Method(typeof(BalrondNatureOptimizerPlugin), postfixName, (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null) { Debug.LogWarning((object)("[BalrondNatureOptimizer] Could not patch " + originalType?.FullName + "." + originalName + " with " + postfixName + ".")); } else { Harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static void PatchPostfixAfterBalrond(Type originalType, string originalName, string postfixName, Type[] argumentTypes = null) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown MethodInfo methodInfo = ((argumentTypes == null) ? AccessTools.Method(originalType, originalName, (Type[])null, (Type[])null) : AccessTools.Method(originalType, originalName, argumentTypes, (Type[])null)); MethodInfo methodInfo2 = AccessTools.Method(typeof(BalrondNatureOptimizerPlugin), postfixName, (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null) { Debug.LogWarning((object)("[BalrondNatureOptimizer] Could not patch " + originalType?.FullName + "." + originalName + " with " + postfixName + ".")); } else { Harmony harmony = Harmony; HarmonyMethod val = new HarmonyMethod(methodInfo2); val.after = new string[1] { "balrond.astafaraios.BalrondAmazingNature" }; harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static void PatchPrefix(Type originalType, string originalName, string prefixName, Type[] argumentTypes = null) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown MethodInfo methodInfo = ((argumentTypes == null) ? AccessTools.Method(originalType, originalName, (Type[])null, (Type[])null) : AccessTools.Method(originalType, originalName, argumentTypes, (Type[])null)); MethodInfo methodInfo2 = AccessTools.Method(typeof(BalrondNatureOptimizerPlugin), prefixName, (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null) { Debug.LogWarning((object)("[BalrondNatureOptimizer] Could not patch " + originalType?.FullName + "." + originalName + " with " + prefixName + ".")); } else { Harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static void UnpatchSpecificBalrondPatch(Type originalType, string originalName, string patchTypeName, string patchMethodName, Type[] argumentTypes = null) { MethodInfo methodInfo = ((argumentTypes == null) ? AccessTools.Method(originalType, originalName, (Type[])null, (Type[])null) : AccessTools.Method(originalType, originalName, argumentTypes, (Type[])null)); Type type = AccessTools.TypeByName(patchTypeName); MethodInfo methodInfo2 = ((type == null) ? null : AccessTools.Method(type, patchMethodName, (Type[])null, (Type[])null)); if (methodInfo == null || methodInfo2 == null) { Debug.LogWarning((object)("[BalrondNatureOptimizer] Could not find Balrond patch " + patchTypeName + "." + patchMethodName + " for " + originalType?.FullName + "." + originalName + ".")); } else { Harmony.Unpatch((MethodBase)methodInfo, methodInfo2); Debug.Log((object)("[BalrondNatureOptimizer] Disabled Balrond patch " + patchTypeName + "." + patchMethodName + ".")); } } private static void ZNetSceneAwakePostfixRemoveMonsterDoorSensors(ZNetScene __instance) { if (_enableMonsterDoorSensor.Value || (Object)(object)__instance == (Object)null || __instance.m_prefabs == null) { return; } Type type = AccessTools.TypeByName("MonsterDoorSensor"); if (type == null) { return; } int num = 0; foreach (GameObject prefab in __instance.m_prefabs) { if ((Object)(object)prefab == (Object)null) { continue; } Component[] componentsInChildren = prefab.GetComponentsInChildren(type, true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); num++; } } } if (num > 0) { Debug.Log((object)string.Format("[{0}] Removed {1} MonsterDoorSensor component(s) from loaded prefabs.", "BalrondNatureOptimizer", num)); } } private static void ZoneSystemSetupLocationsPostfixRemoveDisabledBalrondVegetation(ZoneSystem __instance) { IList fieldValue = GetFieldValue(__instance, "m_vegetation"); if (fieldValue != null) { int num = RemoveMatching(fieldValue, IsDisabledBalrondWorldVegetation); int num2 = RemoveDisabledBalrondVegetationFromBuilder(); if (num > 0) { Debug.Log((object)string.Format("[{0}] Removed {1} disabled Balrond vegetation entries from ZoneSystem.", "BalrondNatureOptimizer", num)); } if (num2 > 0) { Debug.Log((object)string.Format("[{0}] Removed {1} disabled Balrond vegetation entries from VegetationBuilder.", "BalrondNatureOptimizer", num2)); } } } private static void ZNetSceneAwakePostfixDisablePoisonGeysers(ZNetScene __instance) { if (!_disablePoisonGeysers.Value || __instance?.m_prefabs == null) { return; } int num = 0; foreach (GameObject prefab in __instance.m_prefabs) { if (!((Object)(object)prefab == (Object)null) && IsPoisonGeyserName(((Object)prefab).name)) { num++; RemoveComponentsInChildren(prefab, typeof(SpawnArea)); RemoveComponentsInChildren(prefab, typeof(LightFlicker)); RemoveComponentsInChildren(prefab, typeof(Light)); RemoveComponentsInChildren(prefab, AccessTools.TypeByName("UnityEngine.ParticleSystem")); RemoveComponentsInChildren(prefab, AccessTools.TypeByName("UnityEngine.AudioSource")); } } if (num > 0) { Debug.Log((object)string.Format("[{0}] Disabled {1} poison geyser prefab(s).", "BalrondNatureOptimizer", num)); } if (_deleteExistingPoisonGeyserZdos.Value && !_poisonGeyserZdoCleanupStarted) { _poisonGeyserZdoCleanupStarted = true; ((MonoBehaviour)__instance).StartCoroutine(DelayedDeleteExistingPoisonGeyserZdos()); } } private static IEnumerator DelayedDeleteExistingPoisonGeyserZdos() { yield return (object)new WaitForSeconds(1f); DeleteExistingPoisonGeyserZdos("startup"); } private static void DeleteExistingPoisonGeyserZdos(string reason) { if (!_disablePoisonGeysers.Value || !_deleteExistingPoisonGeyserZdos.Value || ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null) { return; } IList allZdosSnapshot = GetAllZdosSnapshot(); if (allZdosSnapshot == null) { Debug.LogWarning((object)"[BalrondNatureOptimizer] Could not inspect ZDOMan.m_objectsByID for poison geyser cleanup."); return; } int num = 0; int num2 = 0; foreach (object item in allZdosSnapshot) { ZDO val = (ZDO)((item is ZDO) ? item : null); if (val == null) { continue; } GameObject prefab = ZNetScene.instance.GetPrefab(val.GetPrefab()); if (!((Object)(object)prefab == (Object)null) && IsPoisonGeyserName(((Object)prefab).name)) { if (!val.IsOwner()) { num2++; continue; } ZDOMan.instance.DestroyZDO(val); num++; } } if (num > 0 || num2 > 0) { Debug.Log((object)string.Format("[{0}] Deleted {1} existing poison geyser ZDO(s) during {2}; skipped {3} not owned.", "BalrondNatureOptimizer", num, reason, num2)); } } private static IList GetAllZdosSnapshot() { if (!(ZdoManObjectsByIdField?.GetValue(ZDOMan.instance) is IDictionary dictionary)) { return null; } ArrayList arrayList = new ArrayList(dictionary.Count); foreach (object value in dictionary.Values) { arrayList.Add(value); } return arrayList; } private static string GetZdoIdString(ZDO zdo) { return ((zdo == null) ? null : ZdoUidField?.GetValue(zdo))?.ToString() ?? ""; } private static void ClutterSystemAwakePostfixRemoveBalrondSwampClutter(ClutterSystem __instance) { IList fieldValue = GetFieldValue(__instance, "m_clutter"); if (_disableBalrondSwampClutter.Value && fieldValue != null) { int num = RemoveMatching(fieldValue, IsBalrondSwampClutter); int num2 = RemoveBalrondSwampClutterFromBuilder(); if (num > 0) { __instance.ClearAll(); } if (num > 0 || num2 > 0) { Debug.Log((object)string.Format("[{0}] Removed {1} active and {2} pending Balrond swamp clutter entries.", "BalrondNatureOptimizer", num, num2)); } } } private static bool SkipPoisonGeyserSpawnerSetupPrefix(string name) { if (_disablePoisonGeysers.Value) { return !IsPoisonGeyserName(name); } return true; } private static bool PlayerTeleportToPrefix(Player __instance, bool distantTeleport) { if (_cleanupRuntimeOnTeleport.Value && distantTeleport && (Object)(object)__instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer) { _teleportCleanupPending = true; _wasTeleporting = true; } return true; } private static void PlayerUpdateTeleportPostfix(Player __instance) { if (_cleanupRuntimeOnTeleport.Value && _teleportCleanupPending && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { bool flag = ((Character)__instance).IsTeleporting(); if (_wasTeleporting && !flag) { _teleportCleanupPending = false; _wasTeleporting = false; CleanupBalrondRuntime("teleport"); } else { _wasTeleporting = flag; } } } private static void GameLogoutPostfix() { CleanupBalrondRuntime("logout"); AdjustedBiomeMessageTitles.Clear(); _teleportCleanupPending = false; _wasTeleporting = false; } private static void MessageHudUpdateBiomeFoundPostfix(MessageHud __instance) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) if (!_fixBiomeMessageWidth.Value || (Object)(object)__instance == (Object)null) { return; } object? obj = MessageHudBiomeMsgInstanceField?.GetValue(__instance); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val == (Object)null) { return; } Transform val2 = val.transform.Find("UnlockMessage/Title"); RectTransform val3 = (((Object)(object)val2 == (Object)null) ? null : ((Component)val2).GetComponent()); if (!((Object)(object)val3 == (Object)null)) { int instanceID = ((Object)val3).GetInstanceID(); if (AdjustedBiomeMessageTitles.Add(instanceID)) { val3.sizeDelta += new Vector2(200f, 0f); } } } private static int RemoveComponentsInChildren(GameObject prefab, Type componentType) { if (componentType == null) { return 0; } Component[] componentsInChildren = prefab.GetComponentsInChildren(componentType, true); int num = 0; for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); num++; } } return num; } private static bool IsDisabledBalrondWorldVegetation(object vegetation) { if (vegetation == null) { return false; } string fieldValue = GetFieldValue(vegetation, "m_name"); GameObject fieldValue2 = GetFieldValue(vegetation, "m_prefab"); string name = (((Object)(object)fieldValue2 == (Object)null) ? null : ((Object)fieldValue2).name); if (!IsDisabledBalrondWorldVegetationName(fieldValue)) { return IsDisabledBalrondWorldVegetationName(name); } return true; } private static bool IsDisabledBalrondWorldVegetationName(string name) { if (string.IsNullOrEmpty(name)) { return false; } if (_disablePoisonGeysers.Value && IsPoisonGeyserName(name)) { return true; } if (_disableBalrondSwampWorldVegetation.Value) { return BalrondSwampWorldVegetation.Contains(name); } return false; } private static bool IsPoisonGeyserName(string name) { if (!string.Equals(name, "PoisonGeyser_bal", StringComparison.Ordinal)) { return string.Equals(name, "PoisonGeyserSpawner_bal", StringComparison.Ordinal); } return true; } private static bool IsBalrondSwampClutter(object clutter) { if (clutter == null) { return false; } GameObject fieldValue = GetFieldValue(clutter, "m_prefab"); if ((Object)(object)fieldValue == (Object)null) { return false; } return ((Object)fieldValue).name?.StartsWith("Swampy", StringComparison.Ordinal) ?? false; } private static int RemoveBalrondSwampClutterFromBuilder() { Type type = AccessTools.TypeByName("BalrondNature.Launch"); object obj = ((type == null) ? null : AccessTools.Field(type, "clutterBuilder"))?.GetValue(null); if (!(((obj == null) ? null : AccessTools.Field(obj.GetType(), "clutterObjects"))?.GetValue(obj) is IList list)) { return 0; } int num = 0; for (int num2 = list.Count - 1; num2 >= 0; num2--) { if (IsBalrondSwampClutter(list[num2])) { list.RemoveAt(num2); num++; } } return num; } private static int RemoveDisabledBalrondVegetationFromBuilder() { Type type = AccessTools.TypeByName("BalrondNature.VegetationBuilder"); if (!(((type == null) ? null : AccessTools.Field(type, "ZoneVegetations"))?.GetValue(null) is IList list)) { return 0; } return RemoveMatching(list, IsDisabledBalrondWorldVegetation); } private static void CleanupBalrondRuntime(string reason) { int num = 0; Type type = AccessTools.TypeByName("MonsterDoorSensor"); if (type != null && !_enableMonsterDoorSensor.Value) { num += RemoveLiveComponents(type); } if ((Object)(object)ZNetScene.instance != (Object)null) { ZNetSceneAwakePostfixRemoveMonsterDoorSensors(ZNetScene.instance); ZNetSceneAwakePostfixDisablePoisonGeysers(ZNetScene.instance); DeleteExistingPoisonGeyserZdos(reason); } Debug.Log((object)string.Format("[{0}] Runtime cleanup after {1}: removed {2} live disabled component(s).", "BalrondNatureOptimizer", reason, num)); } private static int RemoveLiveComponents(Type componentType) { if (componentType == null) { return 0; } Object[] array = Object.FindObjectsOfType(componentType); int num = 0; foreach (Object obj in array) { Component val = (Component)(object)((obj is Component) ? obj : null); if (val != null && (Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); num++; } } return num; } private static int RemoveMatching(IList list, Predicate predicate) { int num = 0; for (int num2 = list.Count - 1; num2 >= 0; num2--) { if (predicate(list[num2])) { list.RemoveAt(num2); num++; } } return num; } private static T GetFieldValue(object instance, string fieldName) { if (instance == null) { return default(T); } object obj = AccessTools.Field(instance.GetType(), fieldName)?.GetValue(instance); if (obj is T) { return (T)obj; } return default(T); } }