Decompiled source of No Forest Falling Trees v1.3.0

NoAbomination.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("NoAbomination")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NoAbomination")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("455c9416-1048-44be-96cf-cd45598d67b4")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace NoForestAmbush;

[BepInPlugin("kumo.sulfur.no_forest_ambush", "No Forest Ambush", "1.3.0")]
public sealed class Plugin : BaseUnityPlugin
{
	[CompilerGenerated]
	private sealed class <CleanupBurst>d__14 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public string reason;

		public Plugin <>4__this;

		private int <iterations>5__1;

		private float <interval>5__2;

		private int <i>5__3;

		private int <neutralized>5__4;

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

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

		[DebuggerHidden]
		public <CleanupBurst>d__14(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>4__this.cleanupBurstRunning = true;
				if (<>4__this.logActions.Value)
				{
					((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)("Starting Forest Ambush cleanup burst: " + reason));
				}
				<iterations>5__1 = Mathf.Max(1, <>4__this.cleanupBurstIterations.Value);
				<interval>5__2 = Mathf.Max(0.05f, <>4__this.cleanupBurstInterval.Value);
				<i>5__3 = 0;
				break;
			case 1:
				<>1__state = -1;
				<i>5__3++;
				break;
			}
			if (<i>5__3 < <iterations>5__1)
			{
				<neutralized>5__4 = <>4__this.NeutralizeForestAmbushObjectsInLoadedScenes();
				if (<>4__this.logActions.Value && <neutralized>5__4 > 0)
				{
					((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)("Cleanup pass neutralized Forest Ambush objects: " + <neutralized>5__4));
				}
				<>2__current = (object)new WaitForSeconds(<interval>5__2);
				<>1__state = 1;
				return true;
			}
			<>4__this.cleanupBurstRunning = false;
			if (<>4__this.logActions.Value)
			{
				((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)("Finished Forest Ambush cleanup burst: " + reason));
			}
			return false;
		}

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

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

	[CompilerGenerated]
	private sealed class <SceneSignatureWatchLoop>d__11 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public Plugin <>4__this;

		private int <currentSignature>5__1;

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

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

		[DebuggerHidden]
		public <SceneSignatureWatchLoop>d__11(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				break;
			case 1:
				<>1__state = -1;
				<currentSignature>5__1 = <>4__this.ComputeSceneSignature();
				if (<currentSignature>5__1 != <>4__this.lastSceneSignature)
				{
					<>4__this.lastSceneSignature = <currentSignature>5__1;
					<>4__this.StartCleanupBurst("scene hierarchy changed");
				}
				break;
			}
			<>2__current = (object)new WaitForSeconds(Mathf.Max(0.25f, <>4__this.sceneSignatureCheckInterval.Value));
			<>1__state = 1;
			return true;
		}

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

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

	internal static ManualLogSource Log;

	private ConfigEntry<bool> logActions;

	private ConfigEntry<float> sceneSignatureCheckInterval;

	private ConfigEntry<int> cleanupBurstIterations;

	private ConfigEntry<float> cleanupBurstInterval;

	private int lastSceneSignature;

	private bool cleanupBurstRunning;

	private readonly HashSet<int> neutralizedAmbushIds = new HashSet<int>();

	private void Awake()
	{
		Log = ((BaseUnityPlugin)this).Logger;
		logActions = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "LogActions", false, "Log neutralized Forest Ambush objects.");
		sceneSignatureCheckInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Performance", "SceneSignatureCheckInterval", 1f, "How often to cheaply check whether the loaded scene hierarchy changed.");
		cleanupBurstIterations = ((BaseUnityPlugin)this).Config.Bind<int>("Performance", "CleanupBurstIterations", 24, "How many cleanup passes to run after a scene hierarchy change.");
		cleanupBurstInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Performance", "CleanupBurstInterval", 0.2f, "Delay between cleanup passes during a cleanup burst.");
		SceneManager.sceneLoaded += OnSceneLoaded;
		lastSceneSignature = ComputeSceneSignature();
		StartCleanupBurst("startup");
		((MonoBehaviour)this).StartCoroutine(SceneSignatureWatchLoop());
		((BaseUnityPlugin)this).Logger.LogInfo((object)"No Forest Ambush 1.3.0 loaded.");
	}

	private void OnDestroy()
	{
		SceneManager.sceneLoaded -= OnSceneLoaded;
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		neutralizedAmbushIds.Clear();
		lastSceneSignature = ComputeSceneSignature();
		StartCleanupBurst("scene loaded");
	}

	[IteratorStateMachine(typeof(<SceneSignatureWatchLoop>d__11))]
	private IEnumerator SceneSignatureWatchLoop()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <SceneSignatureWatchLoop>d__11(0)
		{
			<>4__this = this
		};
	}

	private int ComputeSceneSignature()
	{
		//IL_0016: 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)
		int num = 17;
		num = num * 31 + SceneManager.sceneCount;
		for (int i = 0; i < SceneManager.sceneCount; i++)
		{
			Scene sceneAt = SceneManager.GetSceneAt(i);
			if (((Scene)(ref sceneAt)).IsValid() && ((Scene)(ref sceneAt)).isLoaded)
			{
				num = num * 31 + ((Scene)(ref sceneAt)).name.GetHashCode();
				num = num * 31 + ((Scene)(ref sceneAt)).rootCount;
			}
		}
		return num;
	}

	private void StartCleanupBurst(string reason)
	{
		if (!cleanupBurstRunning)
		{
			((MonoBehaviour)this).StartCoroutine(CleanupBurst(reason));
		}
	}

	[IteratorStateMachine(typeof(<CleanupBurst>d__14))]
	private IEnumerator CleanupBurst(string reason)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <CleanupBurst>d__14(0)
		{
			<>4__this = this,
			reason = reason
		};
	}

	private int NeutralizeForestAmbushObjectsInLoadedScenes()
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		int num = 0;
		for (int i = 0; i < SceneManager.sceneCount; i++)
		{
			Scene sceneAt = SceneManager.GetSceneAt(i);
			if (((Scene)(ref sceneAt)).IsValid() && ((Scene)(ref sceneAt)).isLoaded)
			{
				GameObject[] rootGameObjects = ((Scene)(ref sceneAt)).GetRootGameObjects();
				GameObject[] array = rootGameObjects;
				foreach (GameObject val in array)
				{
					num += ScanTransformForForestAmbush(val.transform);
				}
			}
		}
		return num;
	}

	private int ScanTransformForForestAmbush(Transform transform)
	{
		if ((Object)(object)transform == (Object)null)
		{
			return 0;
		}
		GameObject gameObject = ((Component)transform).gameObject;
		if ((Object)(object)gameObject == (Object)null)
		{
			return 0;
		}
		if (IsForestAmbushRootName(((Object)gameObject).name))
		{
			int instanceID = ((Object)gameObject).GetInstanceID();
			if (neutralizedAmbushIds.Contains(instanceID))
			{
				return 0;
			}
			neutralizedAmbushIds.Add(instanceID);
			NeutralizeForestAmbushRoot(gameObject);
			return 1;
		}
		int num = 0;
		for (int num2 = transform.childCount - 1; num2 >= 0; num2--)
		{
			num += ScanTransformForForestAmbush(transform.GetChild(num2));
		}
		return num;
	}

	private void NeutralizeForestAmbushRoot(GameObject ambushRoot)
	{
		if ((Object)(object)ambushRoot == (Object)null)
		{
			return;
		}
		Transform val = ambushRoot.transform.Find("Contents");
		if ((Object)(object)val == (Object)null)
		{
			if (logActions.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Forest Ambush has no Contents: " + GetPath(ambushRoot)));
			}
			return;
		}
		GameObject gameObject = ((Component)val).gameObject;
		DisableBehaviourComponentByTypeName(gameObject, "Animator");
		DisableBehaviourComponentByTypeName(gameObject, "AudioSource");
		for (int num = val.childCount - 1; num >= 0; num--)
		{
			Transform child = val.GetChild(num);
			if (!((Object)(object)child == (Object)null))
			{
				GameObject gameObject2 = ((Component)child).gameObject;
				string name = ((Object)gameObject2).name;
				if (ShouldDisableAmbushVisualObject(name))
				{
					if (logActions.Value)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("Disabled Forest Ambush visual object: " + GetPath(gameObject2)));
					}
					gameObject2.SetActive(false);
				}
			}
		}
		if (logActions.Value)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Neutralized Forest Ambush visuals only: " + GetPath(ambushRoot)));
		}
	}

	private static bool ShouldDisableAmbushVisualObject(string objectName)
	{
		if (string.IsNullOrEmpty(objectName))
		{
			return false;
		}
		if (objectName.StartsWith("Tree", StringComparison.OrdinalIgnoreCase))
		{
			return true;
		}
		if (objectName.IndexOf("Particles", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return true;
		}
		return false;
	}

	private static bool IsForestAmbushRootName(string objectName)
	{
		if (string.IsNullOrEmpty(objectName))
		{
			return false;
		}
		return objectName.IndexOf("Event_Forest_Ambush", StringComparison.OrdinalIgnoreCase) >= 0 || objectName.IndexOf("Forest_Ambush", StringComparison.OrdinalIgnoreCase) >= 0;
	}

	private static void DisableBehaviourComponentByTypeName(GameObject go, string typeName)
	{
		if ((Object)(object)go == (Object)null || string.IsNullOrEmpty(typeName))
		{
			return;
		}
		Component[] components = go.GetComponents<Component>();
		Component[] array = components;
		foreach (Component val in array)
		{
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			Type type = ((object)val).GetType();
			if (string.Equals(type.Name, typeName, StringComparison.OrdinalIgnoreCase))
			{
				Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null);
				if ((Object)(object)val2 != (Object)null)
				{
					val2.enabled = false;
				}
			}
		}
	}

	private static string GetPath(GameObject go)
	{
		if ((Object)(object)go == (Object)null)
		{
			return string.Empty;
		}
		string text = ((Object)go).name;
		Transform parent = go.transform.parent;
		while ((Object)(object)parent != (Object)null)
		{
			text = ((Object)parent).name + "/" + text;
			parent = parent.parent;
		}
		return text;
	}
}