Decompiled source of Donkey Castrator v1.0.0

Mods/DonkeyCastrator.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using DonkeyCastrator;
using Il2Cpp;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MelonLoader;
using Microsoft.CodeAnalysis;
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: MelonInfo(typeof(Core), "DonkeyCastrator", "1.0.0", "Caleb Orchard", null)]
[assembly: MelonGame("DefaultCompany", "BabySteps")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("DonkeyCastrator")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+bc364cca4ff5e2260188c9314b0086602acdd915")]
[assembly: AssemblyProduct("DonkeyCastrator")]
[assembly: AssemblyTitle("DonkeyCastrator")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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;
		}
	}
}
namespace DonkeyCastrator
{
	public class Core : MelonMod
	{
		private readonly HashSet<int> reportedInstanceIds = new HashSet<int>();

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

		private readonly Dictionary<int, int> childCountCache = new Dictionary<int, int>();

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

		private readonly Dictionary<int, int> discoveryChildCountCache = new Dictionary<int, int>();

		private readonly Queue<Transform> discoveryQueue = new Queue<Transform>();

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

		private readonly List<Transform> censorRoots = new List<Transform>();

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

		private readonly List<Transform> censoredTargets = new List<Transform>();

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

		private float nextScanTime;

		private float nextDiscoveryTime;

		private float nextWarningTime;

		private const float ScanInterval = 1f;

		private const float DiscoveryInterval = 5f;

		private const float WarningCooldown = 2f;

		private const float DiscoveryFrameBudgetMs = 1f;

		private const int MaxDiscoveryNodesPerFrame = 200;

		public override void OnInitializeMelon()
		{
			((MelonBase)this).LoggerInstance.Msg("Initialized.");
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			DiscoverCensorRoots(force: true);
		}

		public override void OnSceneWasUnloaded(int buildIndex, string sceneName)
		{
			reportedInstanceIds.Clear();
			scannedIds.Clear();
			childCountCache.Clear();
			discoveredNodeIds.Clear();
			discoveryChildCountCache.Clear();
			discoveryQueue.Clear();
			queuedDiscoveryIds.Clear();
			censorRoots.Clear();
			censorRootIds.Clear();
			censoredTargets.Clear();
			censoredTargetIds.Clear();
		}

		public override void OnUpdate()
		{
			EnforceCensoredTargets();
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime >= nextDiscoveryTime)
			{
				nextDiscoveryTime = unscaledTime + 5f;
				DiscoverCensorRoots(force: false);
			}
			ProcessDiscoveryQueue();
			if (!(unscaledTime < nextScanTime))
			{
				nextScanTime = unscaledTime + 1f;
				ScanKnownRoots();
			}
		}

		public override void OnLateUpdate()
		{
			EnforceCensoredTargets();
		}

		private void ScanKnownRoots()
		{
			try
			{
				List<string> found = new List<string>();
				for (int num = censorRoots.Count - 1; num >= 0; num--)
				{
					Transform t = censorRoots[num];
					if (!IsLoaded(t))
					{
						censorRoots.RemoveAt(num);
					}
					else
					{
						CheckObjectRecursive(t, found);
					}
				}
			}
			catch (Exception ex)
			{
				if (Time.unscaledTime >= nextWarningTime)
				{
					MelonLogger.Warning("DonkeyCastrator scan error: " + ex.Message);
					nextWarningTime = Time.unscaledTime + 2f;
				}
			}
		}

		private void DiscoverCensorRoots(bool force)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			if (force)
			{
				discoveredNodeIds.Clear();
				discoveryChildCountCache.Clear();
				discoveryQueue.Clear();
				queuedDiscoveryIds.Clear();
				censorRoots.Clear();
				censorRootIds.Clear();
			}
			for (int i = 0; i < SceneManager.sceneCount; i++)
			{
				Scene sceneAt = SceneManager.GetSceneAt(i);
				if (!((Scene)(ref sceneAt)).isLoaded)
				{
					continue;
				}
				foreach (GameObject item in (Il2CppArrayBase<GameObject>)(object)((Scene)(ref sceneAt)).GetRootGameObjects())
				{
					if (!((Object)(object)item == (Object)null))
					{
						EnqueueForDiscovery(item.transform);
					}
				}
			}
		}

		private void ProcessDiscoveryQueue()
		{
			if (discoveryQueue.Count == 0)
			{
				return;
			}
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			int num = 0;
			while (discoveryQueue.Count > 0 && num < 200 && !((Time.realtimeSinceStartup - realtimeSinceStartup) * 1000f >= 1f))
			{
				Transform val = discoveryQueue.Dequeue();
				if ((Object)(object)val != (Object)null)
				{
					queuedDiscoveryIds.Remove(((Object)val).GetInstanceID());
				}
				num++;
				DiscoverCensorRootsStep(val);
			}
		}

		private void DiscoverCensorRootsStep(Transform t)
		{
			if ((Object)(object)t == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)t).GetInstanceID();
			int childCount = t.childCount;
			if (!discoveredNodeIds.Contains(instanceID) || !discoveryChildCountCache.TryGetValue(instanceID, out var value) || value != childCount)
			{
				if ((Object)(object)((Component)t).GetComponent<RegisterCensorBones>() != (Object)null && censorRootIds.Add(instanceID))
				{
					censorRoots.Add(t);
				}
				for (int i = 0; i < childCount; i++)
				{
					EnqueueForDiscovery(t.GetChild(i));
				}
				discoveredNodeIds.Add(instanceID);
				discoveryChildCountCache[instanceID] = childCount;
			}
		}

		private void EnqueueForDiscovery(Transform t)
		{
			if (!((Object)(object)t == (Object)null))
			{
				int instanceID = ((Object)t).GetInstanceID();
				if (queuedDiscoveryIds.Add(instanceID))
				{
					discoveryQueue.Enqueue(t);
				}
			}
		}

		private void CheckObjectRecursive(Transform t, List<string> found)
		{
			if ((Object)(object)t == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)t).GetInstanceID();
			int childCount = t.childCount;
			if (reportedInstanceIds.Contains(instanceID))
			{
				EnsureZeroScale(t);
				CacheScanState(instanceID, childCount);
			}
			else
			{
				if (scannedIds.Contains(instanceID) && childCountCache.TryGetValue(instanceID, out var value) && value == childCount)
				{
					return;
				}
				string name = ((Object)((Component)t).gameObject).name;
				if (name.IndexOf("penis", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("testes", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					if (name.IndexOf("Boing", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Censor", StringComparison.OrdinalIgnoreCase) < 0)
					{
						reportedInstanceIds.Add(instanceID);
						found.Add(name);
						if (censoredTargetIds.Add(instanceID))
						{
							censoredTargets.Add(t);
						}
						EnsureZeroScale(t);
					}
					CacheScanState(instanceID, childCount);
				}
				else
				{
					for (int i = 0; i < childCount; i++)
					{
						CheckObjectRecursive(t.GetChild(i), found);
					}
					CacheScanState(instanceID, childCount);
				}
			}
		}

		private void EnforceCensoredTargets()
		{
			for (int num = censoredTargets.Count - 1; num >= 0; num--)
			{
				Transform t = censoredTargets[num];
				if (!IsLoaded(t))
				{
					censoredTargets.RemoveAt(num);
				}
				else
				{
					EnsureZeroScale(t);
				}
			}
		}

		private bool IsLoaded(Transform t)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			int result;
			if ((Object)(object)t != (Object)null)
			{
				Scene scene = ((Component)t).gameObject.scene;
				result = (((Scene)(ref scene)).isLoaded ? 1 : 0);
			}
			else
			{
				result = 0;
			}
			return (byte)result != 0;
		}

		private void EnsureZeroScale(Transform t)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if (t.localScale != Vector3.zero)
			{
				t.localScale = Vector3.zero;
			}
		}

		private void CacheScanState(int id, int childCount)
		{
			scannedIds.Add(id);
			childCountCache[id] = childCount;
		}
	}
}