Decompiled source of ComponentBundler v1.0.2

patchers/ComponentBundler.Preloader.dll

Decompiled 4 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.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Newtonsoft.Json;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Kesomannen")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Preload patcher for ComponentBundler.")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+53f977741280d51e7853900d4d33ad3755f3ef2f")]
[assembly: AssemblyProduct("ComponentBundler")]
[assembly: AssemblyTitle("ComponentBundler.Preloader")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.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 ComponentBundler.Preloader
{
	public static class ComponentBundlingPreloader
	{
		internal static readonly ManualLogSource Logger = Logger.CreateLogSource("ComponentBundler.Preloader");

		internal static readonly Dictionary<string, List<string>> BundledComponents = new Dictionary<string, List<string>>();

		public static IReadOnlyCollection<string> TargettedComponentFullNames => BundledComponents.Keys;

		public static bool Bundle(AssemblyDefinition targetAssembly, string targetFullName, string toAddFullName)
		{
			if (BundledComponents.TryGetValue(targetFullName, out var value))
			{
				value.Add(toAddFullName);
				Logger.LogInfo((object)("Bundled " + toAddFullName + " with " + targetFullName));
				return true;
			}
			MethodGenerator.CreateMethod(targetAssembly, targetFullName, "Awake");
			BundledComponents.Add(targetFullName, new List<string> { toAddFullName });
			Logger.LogInfo((object)("Bundled " + toAddFullName + " with " + targetFullName));
			return true;
		}

		public static IEnumerable<string> GetBundle(string targetComponentFullName)
		{
			if (!BundledComponents.TryGetValue(targetComponentFullName, out var value))
			{
				return Enumerable.Empty<string>();
			}
			return value;
		}

		public static bool TryGetBundle(string targetComponentFullName, out IEnumerable<string> bundle)
		{
			if (BundledComponents.TryGetValue(targetComponentFullName, out var value))
			{
				bundle = value;
				return true;
			}
			bundle = Enumerable.Empty<string>();
			return false;
		}
	}
	public static class MethodGenerator
	{
		internal static readonly ManualLogSource Logger = Logger.CreateLogSource("ComponentBundler.MethodGenerator");

		public static bool CreateMethod(AssemblyDefinition assembly, string classFullName, string methodName)
		{
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Expected O, but got Unknown
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			TypeDefinition type = assembly.MainModule.GetType(classFullName);
			if (type == null)
			{
				string text = "Target type " + classFullName + " not found in " + ((AssemblyNameReference)assembly.Name).Name + "!";
				if (!classFullName.Contains('.'))
				{
					text += " Did you forget to include the namespace?";
				}
				Logger.LogError((object)text);
				return false;
			}
			if (((IEnumerable<MethodDefinition>)type.Methods).Any((MethodDefinition m) => ((MemberReference)m).Name == methodName))
			{
				return true;
			}
			MethodDefinition val = null;
			TypeReference baseType = type.BaseType;
			while (baseType != null)
			{
				TypeDefinition val2 = baseType.Resolve();
				if (val2 == null)
				{
					Logger.LogError((object)("Failed to resolve base type " + ((MemberReference)baseType).FullName));
					return false;
				}
				val = ((IEnumerable<MethodDefinition>)val2.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition m) => ((MemberReference)m).Name == methodName));
				if (val != null)
				{
					break;
				}
				baseType = val2.BaseType;
			}
			MethodDefinition val3 = new MethodDefinition(methodName, (MethodAttributes)1, assembly.MainModule.TypeSystem.Void);
			ILProcessor iLProcessor = val3.Body.GetILProcessor();
			if (val != null)
			{
				iLProcessor.Emit(OpCodes.Ldarg_0);
				iLProcessor.Emit(OpCodes.Call, (MethodReference)(object)val);
				Logger.LogInfo((object)("Added call to base method " + ((MemberReference)val).Name + " in " + classFullName + "." + methodName));
			}
			iLProcessor.Emit(OpCodes.Ret);
			type.Methods.Add(val3);
			Logger.LogInfo((object)("Added " + methodName + " to " + classFullName));
			return true;
		}
	}
	public static class Patcher
	{
		public static IEnumerable<string> TargetDLLs
		{
			get
			{
				yield return "Assembly-CSharp.dll";
			}
		}

		public static void Patch(AssemblyDefinition assembly)
		{
			string? directoryName = Path.GetDirectoryName(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
			RecursiveSearch(directoryName, "bundler_config", delegate(Dictionary<string, string[]> file)
			{
				foreach (KeyValuePair<string, string[]> item in file)
				{
					item.Deconstruct(out var key2, out var value2);
					string targetFullName = key2;
					value2 = value2;
					foreach (string toAddFullName in value2)
					{
						ComponentBundlingPreloader.Bundle(assembly, targetFullName, toAddFullName);
					}
				}
			});
			RecursiveSearch(directoryName, "method_gen_config", delegate(Dictionary<string, string[]> file)
			{
				foreach (KeyValuePair<string, string[]> item2 in file)
				{
					item2.Deconstruct(out var key, out var value);
					string classFullName = key;
					value = value;
					foreach (string methodName in value)
					{
						MethodGenerator.CreateMethod(assembly, classFullName, methodName);
					}
				}
			});
		}

		private static void RecursiveSearch<T>(string pluginDirectory, string fileName, Action<T> action)
		{
			//IL_0028: Expected O, but got Unknown
			string[] files = Directory.GetFiles(pluginDirectory, fileName, SearchOption.AllDirectories);
			foreach (string text in files)
			{
				try
				{
					string text2 = File.ReadAllText(text);
					action(JsonConvert.DeserializeObject<T>(text2));
				}
				catch (JsonException val)
				{
					JsonException val2 = val;
					ComponentBundlingPreloader.Logger.LogError((object)("Failed to read config file " + text + ": " + ((Exception)(object)val2).Message));
				}
			}
		}
	}
}

plugins/ComponentBundler.dll

Decompiled 4 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using ComponentBundler.Preloader;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Kesomannen")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Allows you to bundle your own components with built-in ones.")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+53f977741280d51e7853900d4d33ad3755f3ef2f")]
[assembly: AssemblyProduct("ComponentBundler")]
[assembly: AssemblyTitle("ComponentBundler")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.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 ComponentBundler
{
	[BepInPlugin("ComponentBundler", "ComponentBundler", "1.0.1")]
	public class Plugin : BaseUnityPlugin
	{
		private static readonly Dictionary<Type, Type[]> _loadedBundles = new Dictionary<Type, Type[]>();

		internal static ManualLogSource Log { get; } = Logger.CreateLogSource("ComponentBundler");


		private void Awake()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			Harmony val = new Harmony("ComponentBundler");
			HarmonyMethod val2 = new HarmonyMethod(typeof(Plugin), "Awake_Prefix", (Type[])null);
			IEnumerable<string> source = default(IEnumerable<string>);
			foreach (string targettedComponentFullName in ComponentBundlingPreloader.TargettedComponentFullNames)
			{
				Type type = AccessTools.TypeByName(targettedComponentFullName);
				MethodInfo methodInfo = AccessTools.Method(type, "Awake", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					Log.LogError((object)("Method " + targettedComponentFullName + ".Awake not found, please report this to the mod author"));
					continue;
				}
				if (!ComponentBundlingPreloader.TryGetBundle(targettedComponentFullName, ref source))
				{
					Log.LogWarning((object)("No bundle found for " + targettedComponentFullName + ". Skipping..."));
					continue;
				}
				_loadedBundles[type] = (from t in source.Select(ValidateBundledType)
					where t != null
					select t).ToArray();
				val.Patch((MethodBase)methodInfo, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			Log.LogInfo((object)"Plugin loaded!");
		}

		private static Type ValidateBundledType(string fullName)
		{
			Type type = AccessTools.TypeByName(fullName);
			if (type == null)
			{
				Log.LogError((object)("Bundled type " + fullName + " not found!"));
				return null;
			}
			if (!type.IsSubclassOf(typeof(MonoBehaviour)))
			{
				Log.LogError((object)$"Bundled type {type} is not a MonoBehaviour!");
				return null;
			}
			return type;
		}

		private static void Awake_Prefix(Component __instance)
		{
			Type[] array = _loadedBundles[((object)__instance).GetType()];
			foreach (Type type in array)
			{
				__instance.gameObject.AddComponent(type);
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "ComponentBundler";

		public const string PLUGIN_NAME = "ComponentBundler";

		public const string PLUGIN_VERSION = "1.0.1";
	}
}