Decompiled source of Network Behaviour Event Injector v1.0.0

BepInEx/patchers/Daydream.NetworkBehaviourEvents.dll

Decompiled 9 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Daydream.NetworkBehaviourEvents")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Daydream.NetworkBehaviourEvents")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8D6B7A3E-C51F-4A44-8D6F-59A3565273B8")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Daydream.NetworkBehaviourEvents;

public class Test
{
	public virtual void OnTest()
	{
	}
}
public class Tester : Test
{
	public override void OnTest()
	{
		base.OnTest();
	}
}
public static class Preloader
{
	private const string NetworkBehaviourFullName = "Unity.Netcode.NetworkBehaviour";

	private static ManualLogSource Logger { get; set; }

	private static TypeReference NetworkBehaviourRef { get; set; }

	private static MethodReference[] NetworkBehaviourEvents { get; set; }

	public static IEnumerable<string> TargetDLLs { get; } = new string[1] { "Assembly-CSharp.dll" };


	public static void Patch(AssemblyDefinition assemblyDefinition)
	{
		Logger.LogInfo((object)"Patching NetworkBehaviour's sub-classes to always contain implementations of virtual methods..");
		NetworkBehaviourRef = assemblyDefinition.MainModule.GetTypeReferences().FirstOrDefault((Func<TypeReference, bool>)((TypeReference typeRef) => ((MemberReference)typeRef).FullName == "Unity.Netcode.NetworkBehaviour"));
		if (NetworkBehaviourRef == null)
		{
			Logger.LogError((object)"The game doesn't contain a reference to Unity.Netcode.NetworkBehaviour");
			return;
		}
		NetworkBehaviourEvents = (from methodDef in (IEnumerable<MethodDefinition>)NetworkBehaviourRef.Resolve().Methods
			where methodDef.IsVirtual && !((MethodReference)methodDef).HasGenericParameters && ((MemberReference)methodDef).Name.StartsWith("On")
			select assemblyDefinition.MainModule.ImportReference((MethodReference)(object)methodDef)).ToArray();
		CollectionExtensions.Do<TypeDefinition>(from typeDef in assemblyDefinition.MainModule.GetTypes()
			where typeDef.IsSubclassOf("Unity.Netcode.NetworkBehaviour")
			select typeDef, (Action<TypeDefinition>)delegate(TypeDefinition typeDef)
		{
			foreach (MethodReference item in NetworkBehaviourEvents.Where((MethodReference methodRef) => ((IEnumerable<MethodDefinition>)typeDef.Methods).All((MethodDefinition methodDef) => ((MemberReference)methodDef).Name != ((MemberReference)methodRef).Name)))
			{
				CreateEventMethod(assemblyDefinition, item, typeDef);
			}
		});
		assemblyDefinition.Write(Path.Combine(Paths.CachePath, "Assembly-CSharp.dll"));
	}

	private static void CreateEventMethod(AssemblyDefinition assemblyDefinition, MethodReference methodReference, TypeDefinition typeDef)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Expected O, but got Unknown
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		MethodDefinition val = new MethodDefinition(((MemberReference)methodReference).Name, (MethodAttributes)198, assemblyDefinition.MainModule.TypeSystem.Void);
		typeDef.Methods.Add(val);
		val.Body.InitLocals = true;
		Enumerator<ParameterDefinition> enumerator = methodReference.Parameters.GetEnumerator();
		try
		{
			while (enumerator.MoveNext())
			{
				ParameterDefinition current = enumerator.Current;
				((MethodReference)val).Parameters.Add(((ParameterReference)current).Resolve());
			}
		}
		finally
		{
			((IDisposable)enumerator).Dispose();
		}
		ILProcessor iLProcessor = val.Body.GetILProcessor();
		iLProcessor.Emit(OpCodes.Ldarg_0);
		for (int i = 0; i < methodReference.Parameters.Count; i++)
		{
			iLProcessor.Emit(OpCodes.Ldarg, i + 1);
		}
		iLProcessor.Emit(OpCodes.Call, methodReference);
		iLProcessor.Emit(OpCodes.Ret);
	}

	private static void Initialize()
	{
		Logger = Logger.CreateLogSource("DayDream.NetworkBehaviourEvents");
	}

	public static void Finish()
	{
		Logger.LogInfo((object)("Patching complete! Verifying types contain {" + string.Join(", ", NetworkBehaviourEvents.Select((MethodReference evt) => ((MemberReference)evt).Name).ToArray()) + "}..."));
		Assembly assembly2 = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly assembly) => assembly.FullName.StartsWith("Assembly-CSharp"));
		if ((object)assembly2 == null)
		{
			Logger.LogError((object)"Couldn't find Assembly-CSharp within the AppDomain! Was it even patched?!");
		}
		else
		{
			if (NetworkBehaviourRef == null || NetworkBehaviourEvents == null)
			{
				return;
			}
			Type[] array = (from type in assembly2.GetTypes()
				where type.IsSubclassOf("Unity.Netcode.NetworkBehaviour")
				select type).ToArray();
			int num = 0;
			Type[] array2 = array;
			foreach (Type allType in array2)
			{
				if (NetworkBehaviourEvents.Aggregate(0, (int i, MethodReference reference) => i + (((object)allType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo methodInfo) => methodInfo.Name == ((MemberReference)reference).Name) != null) ? 1 : 0)) == NetworkBehaviourEvents.Length)
				{
					num++;
				}
			}
			Logger.LogInfo((object)(num + "/" + array.Length + " NetworkBehaviour Sub-Classes are now in compliance! Useless reference dll can be found in /BepInEx/cache/."));
		}
	}

	private static bool IsSubclassOf(this Type type, string fullClassName)
	{
		if (type.FullName == fullClassName)
		{
			return false;
		}
		while ((object)type != null)
		{
			if (type.FullName == fullClassName)
			{
				return true;
			}
			type = type.BaseType;
		}
		return false;
	}

	private static bool IsSubclassOf(this TypeDefinition typeDefinition, string fullClassName)
	{
		if (((MemberReference)typeDefinition).FullName == fullClassName)
		{
			return false;
		}
		while (typeDefinition != null)
		{
			if (((MemberReference)typeDefinition).FullName == fullClassName)
			{
				return true;
			}
			TypeReference baseType = typeDefinition.BaseType;
			typeDefinition = ((baseType != null) ? baseType.Resolve() : null);
		}
		return false;
	}
}