Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of UnityHotReload v1.0.1
UnityHotReload.dll
Decompiled 6 months agousing 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 System.Text; using BepInEx; using BepInEx.Logging; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; using MonoMod.Cil; using MonoMod.RuntimeDetour; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("UnityHotReload")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+bcfa4c369b6149b8781209a4d6a848e88aad5aca")] [assembly: AssemblyProduct("UnityHotReload")] [assembly: AssemblyTitle("UnityHotReload")] [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 UnityHotReloadNS { internal static class Log { private static ManualLogSource _logSource; internal static void Init(ManualLogSource logSource) { _logSource = logSource; } internal static void Debug(object data) { _logSource.LogDebug(data); } internal static void Error(object data) { _logSource.LogError(data); } internal static void Fatal(object data) { _logSource.LogFatal(data); } internal static void Info(object data) { _logSource.LogInfo(data); } internal static void Message(object data) { _logSource.LogMessage(data); } internal static void Warning(object data) { _logSource.LogWarning(data); } } public static class UnityHotReload { [CompilerGenerated] private static class <>O { public static Manipulator <0>__GatherOriginalReferences; public static Manipulator <1>__GatherInstructionsFromNewMethodAndMakeThemReferenceOriginalAssembly; } private const BindingFlags allFlags = (BindingFlags)(-1); internal static int CompilationCount = 0; private static List<ILHook> _activeILHooks = new List<ILHook>(); private static Assembly OriginalAss = null; private static Dictionary<string, TypeReference> OriginalAssTypeRefs = new Dictionary<string, TypeReference>(); private static Dictionary<string, MethodReference> OriginalAssMethodRefs = new Dictionary<string, MethodReference>(); private static Dictionary<string, FieldReference> OriginalAssFieldRefs = new Dictionary<string, FieldReference>(); private static Dictionary<string, CallSite> OriginalAssCallSites = new Dictionary<string, CallSite>(); public static void LoadNewAssemblyVersion(Assembly originalAss, string pathOfTheNewAssembly) { LoadNewAssemblyVersionInternal(originalAss, pathOfTheNewAssembly); } private static void LoadNewAssemblyVersionInternal(Assembly originalAss, string path) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Expected O, but got Unknown //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Expected O, but got Unknown //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Expected O, but got Unknown //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Expected O, but got Unknown //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Expected O, but got Unknown //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Expected O, but got Unknown OriginalAss = originalAss; DefaultAssemblyResolver val = new DefaultAssemblyResolver(); ((BaseAssemblyResolver)val).AddSearchDirectory(Paths.ManagedPath); ((BaseAssemblyResolver)val).AddSearchDirectory(Paths.BepInExAssemblyDirectory); Log.Debug(path); AssemblyDefinition val2 = AssemblyDefinition.ReadAssembly(path, new ReaderParameters { AssemblyResolver = (IAssemblyResolver)(object)val, ReadSymbols = true }); try { ((AssemblyNameReference)val2.Name).Name = $"{originalAss.GetName().Name}_HotReload_{++CompilationCount}"; Assembly assembly; using (MemoryStream memoryStream = new MemoryStream()) { val2.Write((Stream)memoryStream); assembly = Assembly.Load(memoryStream.ToArray()); } Log.Debug("originalAss: " + originalAss.GetName().Name); Log.Debug("newAss: " + assembly.GetName().Name); foreach (Type item in GetTypesSafe(assembly)) { MethodInfo[] methods = item.GetMethods((BindingFlags)(-1)); foreach (MethodInfo method in methods) { Type type = originalAss.GetType(item.FullName); MethodInfo methodInfo = GetMethodResolveAmbiguous(method, type); if (methodInfo == null) { methodInfo = method; } try { List<ILHook> activeILHooks = _activeILHooks; MethodInfo methodInfo2 = methodInfo; object obj = <>O.<0>__GatherOriginalReferences; if (obj == null) { Manipulator val3 = GatherOriginalReferences; <>O.<0>__GatherOriginalReferences = val3; obj = (object)val3; } activeILHooks.Add(new ILHook((MethodBase)methodInfo2, (Manipulator)obj)); List<ILHook> activeILHooks2 = _activeILHooks; MethodInfo methodInfo3 = method; object obj2 = <>O.<1>__GatherInstructionsFromNewMethodAndMakeThemReferenceOriginalAssembly; if (obj2 == null) { Manipulator val4 = GatherInstructionsFromNewMethodAndMakeThemReferenceOriginalAssembly; <>O.<1>__GatherInstructionsFromNewMethodAndMakeThemReferenceOriginalAssembly = val4; obj2 = (object)val4; } activeILHooks2.Add(new ILHook((MethodBase)methodInfo3, (Manipulator)obj2)); if (!(methodInfo != method)) { continue; } _activeILHooks.Add(new ILHook((MethodBase)methodInfo, (Manipulator)delegate(ILContext il) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) ILCursor val5 = new ILCursor(il); for (int j = 0; j < ((MethodReference)il.Method).Parameters.Count; j++) { val5.Emit(OpCodes.Ldarg, j); } val5.Emit(OpCodes.Call, (MethodBase)method); val5.Emit(OpCodes.Ret); })); } catch (Exception arg) { Log.Error($"Failed to hot reload method: {item.FullName}.{method.Name}\n{arg}"); } } } } finally { ((IDisposable)val2)?.Dispose(); } } private static MethodInfo GetMethodResolveAmbiguous(MethodReference methodRef, Type originalType) { List<MethodInfo> list = (from m in originalType.GetMethods((BindingFlags)(-1)) where m.Name == ((MemberReference)methodRef).Name select m).ToList(); if (list.Count == 1) { return list[0]; } if (list.Count > 1) { foreach (MethodInfo item in list) { ParameterInfo[] parameters = item.GetParameters(); Collection<ParameterDefinition> parameters2 = methodRef.Parameters; if (parameters.Length != parameters2.Count) { continue; } bool flag = true; for (int i = 0; i < parameters.Length; i++) { if (parameters[i].ParameterType.FullName != ((MemberReference)((ParameterReference)parameters2[i]).ParameterType).FullName) { flag = false; break; } } if (flag) { Log.Debug("Resolved ambiguous method: " + originalType.FullName + "." + ((MemberReference)methodRef).Name); return item; } } } return null; } private static MethodInfo GetMethodResolveAmbiguous(MethodInfo method, Type originalType) { List<MethodInfo> list = (from m in originalType.GetMethods((BindingFlags)(-1)) where m.Name == method.Name select m).ToList(); if (list.Count == 1) { return list[0]; } if (list.Count > 1) { foreach (MethodInfo item in list) { ParameterInfo[] parameters = item.GetParameters(); ParameterInfo[] parameters2 = method.GetParameters(); if (parameters.Length != parameters2.Length) { continue; } bool flag = true; for (int i = 0; i < parameters.Length; i++) { if (parameters[i].ParameterType.ToString() != parameters2[i].ParameterType.ToString()) { flag = false; break; } } if (flag) { Log.Debug("Resolved ambiguous method: " + originalType.FullName + "." + method.Name); return item; } } } return null; } private static IEnumerable<Type> GetTypesSafe(Assembly ass) { try { return ass.GetTypes(); } catch (ReflectionTypeLoadException ex) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("\r\n-- LoaderExceptions --"); Exception[] loaderExceptions = ex.LoaderExceptions; foreach (Exception ex2 in loaderExceptions) { stringBuilder.AppendLine(ex2.ToString()); } stringBuilder.AppendLine("\r\n-- StackTrace --"); stringBuilder.AppendLine(ex.StackTrace); Log.Error(stringBuilder.ToString()); return ex.Types.Where((Type x) => x != null); } } private static void GatherOriginalReferences(ILContext il) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Enumerator<Instruction> enumerator = il.Instrs.GetEnumerator(); try { while (enumerator.MoveNext()) { Instruction current = enumerator.Current; object operand = current.Operand; TypeReference val = (TypeReference)((operand is TypeReference) ? operand : null); if (val != null) { if (!OriginalAssTypeRefs.ContainsKey(((MemberReference)val).FullName)) { OriginalAssTypeRefs.Add(((MemberReference)val).FullName, val); } continue; } object operand2 = current.Operand; MethodReference val2 = (MethodReference)((operand2 is MethodReference) ? operand2 : null); if (val2 != null) { if (!OriginalAssMethodRefs.ContainsKey(((MemberReference)val2).FullName)) { OriginalAssMethodRefs.Add(((MemberReference)val2).FullName, val2); } continue; } object operand3 = current.Operand; FieldReference val3 = (FieldReference)((operand3 is FieldReference) ? operand3 : null); if (val3 != null) { if (!OriginalAssFieldRefs.ContainsKey(((MemberReference)val3).FullName)) { OriginalAssFieldRefs.Add(((MemberReference)val3).FullName, val3); } continue; } object operand4 = current.Operand; CallSite val4 = (CallSite)((operand4 is CallSite) ? operand4 : null); if (val4 != null && !OriginalAssCallSites.ContainsKey(val4.FullName)) { OriginalAssCallSites.Add(val4.FullName, val4); } } } finally { ((IDisposable)enumerator).Dispose(); } } private static void GatherInstructionsFromNewMethodAndMakeThemReferenceOriginalAssembly(ILContext il) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Enumerator<Instruction> enumerator = il.Instrs.GetEnumerator(); try { while (enumerator.MoveNext()) { Instruction current = enumerator.Current; object operand = current.Operand; object operand2 = current.Operand; TypeReference val = (TypeReference)((operand2 is TypeReference) ? operand2 : null); if (val != null) { if (!OriginalAssTypeRefs.ContainsKey(((MemberReference)val).FullName)) { Type type = OriginalAss.GetType(((MemberReference)val).FullName); if (type != null) { Log.Debug("Adding missing type ref: " + ((MemberReference)val).FullName + " / " + ((ModuleReference)((MemberReference)il.Method).Module).Name); OriginalAssTypeRefs.Add(((MemberReference)val).FullName, il.Import(type)); } } if (OriginalAssTypeRefs.TryGetValue(((MemberReference)val).FullName, out var value)) { operand = value; } } else { object operand3 = current.Operand; MethodReference val2 = (MethodReference)((operand3 is MethodReference) ? operand3 : null); if (val2 != null) { if (!OriginalAssMethodRefs.ContainsKey(((MemberReference)val2).FullName)) { Type type2 = OriginalAss.GetType(((MemberReference)((MemberReference)val2).DeclaringType).FullName); if (type2 != null) { MethodInfo methodResolveAmbiguous = GetMethodResolveAmbiguous(val2, type2); if (methodResolveAmbiguous != null) { Log.Debug("Adding missing method ref: " + ((MemberReference)val2).FullName + " / " + ((ModuleReference)((MemberReference)il.Method).Module).Name); OriginalAssMethodRefs.Add(((MemberReference)val2).FullName, il.Import((MethodBase)methodResolveAmbiguous)); } } } if (OriginalAssMethodRefs.TryGetValue(((MemberReference)val2).FullName, out var value2)) { operand = value2; } } else { object operand4 = current.Operand; FieldReference val3 = (FieldReference)((operand4 is FieldReference) ? operand4 : null); if (val3 != null) { if (!OriginalAssFieldRefs.ContainsKey(((MemberReference)val3).FullName)) { FieldInfo fieldInfo = OriginalAss.GetType(((MemberReference)((MemberReference)val3).DeclaringType).FullName)?.GetField(((MemberReference)val3).Name, (BindingFlags)(-1)); if (fieldInfo != null) { Log.Debug("Adding missing field ref: " + ((MemberReference)val3).FullName + " / " + ((ModuleReference)((MemberReference)il.Method).Module).Name); OriginalAssFieldRefs.Add(((MemberReference)val3).FullName, il.Import(fieldInfo)); } } if (OriginalAssFieldRefs.TryGetValue(((MemberReference)val3).FullName, out var value3)) { operand = value3; } } else { object operand5 = current.Operand; CallSite val4 = (CallSite)((operand5 is CallSite) ? operand5 : null); if (val4 != null && OriginalAssCallSites.TryGetValue(val4.FullName, out var value4)) { operand = value4; } } } } current.Operand = operand; } } finally { ((IDisposable)enumerator).Dispose(); } } } [BepInPlugin("iDeathHD.UnityHotReload", "UnityHotReload", "1.0.1")] public class UnityHotReloadPlugin : BaseUnityPlugin { public const string PluginGUID = "iDeathHD.UnityHotReload"; public const string PluginAuthor = "iDeathHD"; public const string PluginName = "UnityHotReload"; public const string PluginVersion = "1.0.1"; public void Awake() { Log.Init(((BaseUnityPlugin)this).Logger); } } }