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;
}
}
}