using System; using System.Collections; using System.Collections.Concurrent; 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; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Mono.Cecil; 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("com.github.Hamunii.AutoReload")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2+1d62c2c7b5afc79510878103403930785f259062")] [assembly: AssemblyProduct("com.github.Hamunii.AutoReload")] [assembly: AssemblyTitle("AutoReload")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [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 BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace AutoReload { [BepInPlugin("com.github.Hamunii.AutoReload", "AutoReload", "1.0.2")] public class Plugin : BaseUnityPlugin { private static readonly string dumpedAssembliesPath = Path.Combine(Paths.BepInExRootPath, "AutoReloadDumpedAssemblies"); private static DefaultAssemblyResolver defaultResolver = null; private static FileSystemWatcher fileSystemWatcher = null; private static Dictionary pathToId = new Dictionary(); internal static ConcurrentDictionary pendingReloads = new ConcurrentDictionary(); private static Reloader reloader = null; public const string Id = "com.github.Hamunii.AutoReload"; internal static ConfigEntry QuietMode { get; set; } = null; internal static ManualLogSource Logger { get; private set; } = null; internal static Plugin Instance { get; private set; } = null; public static string Name => "AutoReload"; public static string Version => "1.0.2"; private void Awake() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; Instance = this; defaultResolver = new DefaultAssemblyResolver(); ((BaseAssemblyResolver)defaultResolver).AddSearchDirectory(Paths.PluginPath); ((BaseAssemblyResolver)defaultResolver).AddSearchDirectory(Paths.ManagedPath); ((BaseAssemblyResolver)defaultResolver).AddSearchDirectory(Paths.BepInExAssemblyDirectory); QuietMode = ((BaseUnityPlugin)this).Config.Bind("General", "QuietMode", false, new ConfigDescription("Disable all logging except for error messages.", (AcceptableValueBase)null, Array.Empty())); if (Directory.Exists(dumpedAssembliesPath)) { Directory.Delete(dumpedAssembliesPath, recursive: true); } GameObject val = new GameObject("com.github.Hamunii.AutoReload:Reloader") { hideFlags = (HideFlags)61 }; Object.DontDestroyOnLoad((Object)(object)val); reloader = val.AddComponent(); StartFileSystemWatcher(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Plugin " + Name + " is loaded!")); } private static void StartFileSystemWatcher() { fileSystemWatcher = new FileSystemWatcher(Paths.PluginPath) { IncludeSubdirectories = true, NotifyFilter = NotifyFilters.LastWrite, Filter = "*.dll" }; fileSystemWatcher.Changed += FileChangedEventHandler; fileSystemWatcher.Created += FileChangedEventHandler; fileSystemWatcher.EnableRaisingEvents = true; } private static void FileChangedEventHandler(object sender, FileSystemEventArgs args) { pendingReloads.TryAdd(args.FullPath, value: true); } private static void UnloadPlugin(string path) { if (pathToId.TryGetValue(path, out string value) && Chainloader.PluginInfos.TryGetValue(value, out var value2)) { Chainloader.PluginInfos.Remove(value); Object.Destroy((Object)(object)value2.Instance); } } internal static void LoadPlugin(string path) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown if (!File.Exists(path)) { Logger.LogWarning((object)("File at '" + path + "' has been deleted.")); return; } AssemblyDefinition val = AssemblyDefinition.ReadAssembly(path, new ReaderParameters { AssemblyResolver = (IAssemblyResolver)(object)defaultResolver, ReadSymbols = true }); try { ((AssemblyNameReference)val.Name).Name = $"{((AssemblyNameReference)val.Name).Name}-{DateTime.Now.Ticks}"; if (!Directory.Exists(dumpedAssembliesPath)) { Directory.CreateDirectory(dumpedAssembliesPath); } string text = Path.Combine(dumpedAssembliesPath, ((AssemblyNameReference)val.Name).Name + Path.GetExtension(((ModuleReference)val.MainModule).Name)); using (FileStream fileStream = new FileStream(text, FileMode.Create)) { val.Write((Stream)fileStream, new WriterParameters { WriteSymbols = true }); } Assembly ass = Assembly.LoadFile(text); if (!QuietMode.Value) { Logger.Log((LogLevel)16, (object)("Loaded dumped Assembly from '" + text + "'")); } foreach (Type type in GetTypesSafe(ass)) { try { if (!typeof(BaseUnityPlugin).IsAssignableFrom(type)) { continue; } BepInPlugin metadata = MetadataHelper.GetMetadata(type); if (metadata == null) { continue; } pathToId[path] = metadata.GUID; UnloadPlugin(path); TypeDefinition val2 = ((IEnumerable)val.MainModule.Types).First((TypeDefinition x) => ((MemberReference)x).FullName == type.FullName); PluginInfo pluginInfo = Chainloader.ToPluginInfo(val2); ((MonoBehaviour)reloader).StartCoroutine(DelayAction(delegate { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown if (!QuietMode.Value) { Logger.Log((LogLevel)16, (object)$"Loading [{metadata.Name} {metadata.Version}]"); } try { Chainloader.PluginInfos[metadata.GUID] = pluginInfo; Traverse val3 = Traverse.Create((object)pluginInfo); val3.Property("Location", (object[])null).Value = path; BaseUnityPlugin value = (BaseUnityPlugin)((Component)Instance).gameObject.AddComponent(type); val3.Property("Instance", (object[])null).Value = value; } catch (Exception arg2) { Logger.LogError((object)$"Failed to load plugin {metadata.GUID} because of exception: {arg2}"); Chainloader.PluginInfos.Remove(metadata.GUID); } })); } catch (Exception arg) { Logger.LogError((object)$"Failed to load plugin {type.Name} because of exception: {arg}"); } } } finally { ((IDisposable)val)?.Dispose(); } } private static IEnumerable GetTypesSafe(Assembly ass) { try { return ass.GetTypes(); } catch (ReflectionTypeLoadException ex) { return ex.Types.Where((Type x) => (object)x != null); } } private static IEnumerator DelayAction(Action action) { yield return null; action(); } } public class Reloader : MonoBehaviour { private void Update() { foreach (string key in Plugin.pendingReloads.Keys) { Plugin.pendingReloads.Remove(key, out var _); if (!Plugin.QuietMode.Value) { Plugin.Logger.LogInfo((object)("File '" + Path.GetFileName(key) + "' changed.")); } Plugin.LoadPlugin(key); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }