Decompiled source of BalrondNatureOptimizer v0.6.6

BalrondNatureOptimizer.dll

Decompiled a day ago
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<string> BalrondSwampWorldVegetation = new HashSet<string>(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<int> AdjustedBiomeMessageTitles = new HashSet<int>();

	private static ConfigEntry<bool> _enableCustomLavaDamagePatch;

	private static ConfigEntry<bool> _enableMonsterDoorSensor;

	private static ConfigEntry<bool> _enableMonsterClimbPatch;

	private static ConfigEntry<bool> _fixBiomeMessageWidth;

	private static ConfigEntry<bool> _disablePoisonGeysers;

	private static ConfigEntry<bool> _deleteExistingPoisonGeyserZdos;

	private static ConfigEntry<bool> _disableBalrondSwampClutter;

	private static ConfigEntry<bool> _disableBalrondSwampWorldVegetation;

	private static ConfigEntry<bool> _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<bool>("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<bool>("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<bool>("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<bool>("Balrond Bug Fixes", "Fix Biome Message Width", true, "Stops Balrond from increasing biome discovery title width every UpdateBiomeFound call.");
		_disablePoisonGeysers = ((BaseUnityPlugin)this).Config.Bind<bool>("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<bool>("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<bool>("Balrond Swamp", "Disable Balrond Swamp Clutter", true, "Removes Balrond's Swampy1-Swampy12 clutter entries before the clutter system rebuilds.");
		_disableBalrondSwampWorldVegetation = ((BaseUnityPlugin)this).Config.Bind<bool>("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<bool>("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<IList>(__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() ?? "<unknown>";
	}

	private static void ClutterSystemAwakePostfixRemoveBalrondSwampClutter(ClutterSystem __instance)
	{
		IList fieldValue = GetFieldValue<IList>(__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<RectTransform>());
		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<string>(vegetation, "m_name");
		GameObject fieldValue2 = GetFieldValue<GameObject>(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<GameObject>(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<object> 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<T>(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);
	}
}