Decompiled source of Bloodpebble v1.4.2

Bloodpebble.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Loader;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Bloodpebble.Extensions;
using Bloodpebble.Features;
using Bloodpebble.Hooks;
using Bloodpebble.ReloadExecution;
using Bloodpebble.ReloadExecution.LoadingStategyBasic;
using Bloodpebble.ReloadExecution.LoadingStrategyIslands;
using Bloodpebble.ReloadExecution.LoadingStrategySilverBullet;
using Bloodpebble.ReloadRequestHandling;
using Bloodpebble.ReloadRequesting;
using Bloodpebble.Utils;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using ProjectM;
using ProjectM.Network;
using ScarletRCON.Shared;
using SemanticVersioning;
using Unity.Collections;
using Unity.Entities;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("cheesasaurus, deca, molenzwiebel")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Hot reloader for V Rising mods.")]
[assembly: AssemblyFileVersion("1.4.2.0")]
[assembly: AssemblyInformationalVersion("1.4.2+27fb295f18f328b7f2818cb38d33ad3c840a1574")]
[assembly: AssemblyProduct("Bloodpebble")]
[assembly: AssemblyTitle("Bloodpebble")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.4.2.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.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]
	[Microsoft.CodeAnalysis.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]
	[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 Bloodpebble
{
	internal class BloodpebbleConfig
	{
		internal ConfigEntry<string> ReloadCommand;

		internal ConfigEntry<string> PluginsFolder;

		internal ConfigEntry<bool> EnableAutoReload;

		internal ConfigEntry<float> AutoReloadDelaySeconds;

		internal ConfigEntry<string> LoadingStrategy;

		internal BloodpebbleConfig(ConfigFile configFile)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			ReloadCommand = configFile.Bind<string>("General", "ReloadCommand", "!reload", "Server chat command to reload plugins. User must first be AdminAuth'd (accomplished via console command).");
			PluginsFolder = configFile.Bind<string>("General", "ReloadablePluginsFolder", "BepInEx/BloodpebblePlugins", "The folder to (re)load plugins from, relative to the game directory.");
			EnableAutoReload = configFile.Bind<bool>("AutoReload", "EnableAutoReload", true, new ConfigDescription("Automatically reloads all plugins if any of the files get changed (added/removed/modified).", (AcceptableValueBase)null, Array.Empty<object>()));
			AutoReloadDelaySeconds = configFile.Bind<float>("AutoReload", "AutoReloadDelaySeconds", 2f, new ConfigDescription("Delay in seconds before auto reloading.", (AcceptableValueBase)null, Array.Empty<object>()));
			LoadingStrategy = CreateConfigEntry_LoadingStrategy(configFile);
		}

		private ConfigEntry<string> CreateConfigEntry_LoadingStrategy(ConfigFile configFile)
		{
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Expected O, but got Unknown
			string text = new StringBuilder().AppendLine("Which strategy to use for (re)loading plugins. Possible values:").AppendLine().AppendLine("SilverBullet -> Robust and fast. Only reloads what's necessary.")
				.AppendLine("                Each plugin is put into its own custom loading context and a DAG is used for resolution.")
				.AppendLine("                Handles plugin errors with troubleshooting messages;")
				.AppendLine("                attempts to recover and load every valid plugin.")
				.AppendLine()
				.AppendLine("Basic --------> [Deprecated]")
				.AppendLine("                Robust, but slow if you have a lot of plugins and only want to reload one.")
				.AppendLine("                All plugins share a loading context. Reloading one plugin reloads them all.")
				.AppendLine("                Handles plugin errors with troubleshooting messages;")
				.AppendLine("                attempts to recover and load every valid plugin.")
				.AppendLine()
				.AppendLine("Islands ------> [Deprecated]")
				.AppendLine("                Potentially faster than Basic when you have a lot of plugins and only want to reload one.")
				.AppendLine("                Plugins are partitioned into loading islands based on their dependencies.")
				.AppendLine("                Minimal handling of plugin errors. Either loads everything or nothing.")
				.ToString();
			return configFile.Bind<string>("Loader", "LoadingStrategy", "SilverBullet", new ConfigDescription(text, (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "SilverBullet", "Basic_Deprecated", "Islands_Deprecated" }), Array.Empty<object>()));
		}
	}
	[BepInPlugin("Bloodpebble", "Bloodpebble", "1.4.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class BloodpebblePlugin : BasePlugin
	{
		private readonly BloodpebbleConfig cfg;

		private readonly EventLogger _eventLogger;

		private IReloadRequestHandler? _reloadRequestHandler;

		private ReloadViaChatCommand? _reloadViaChatCommand;

		private ReloadViaFileSystemChanges? _reloadViaFileSystemChanges;

		private ReloadViaKeyPress? _reloadViaKeyPress;

		private IPluginLoader? _pluginLoader;

		private Harmony? _harmony;

		public static ManualLogSource Logger { get; private set; }

		internal static BloodpebblePlugin Instance { get; private set; }

		public BloodpebblePlugin()
		{
			Logger = ((BasePlugin)this).Log;
			Instance = this;
			cfg = new BloodpebbleConfig(((BasePlugin)this).Config);
			_eventLogger = new EventLogger(((BasePlugin)this).Log);
		}

		public override void Load()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			_harmony = new Harmony("Bloodpebble");
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
			if (VWorld.IsServer)
			{
				Chat.Initialize();
			}
			GameFrame.Initialize();
			InitReloadFeatures();
			DoInitialPluginsLoad_After_BepInExLoadedOtherPlugins();
			ManualLogSource logger = Logger;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(21, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Bloodpebble v");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.4.2");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded.");
			}
			logger.LogInfo(val);
		}

		public override bool Unload()
		{
			_eventLogger.Unsubscribe();
			_reloadRequestHandler?.Dispose();
			ReloadViaRCON.Uninitialize();
			_reloadViaFileSystemChanges?.Dispose();
			_reloadViaChatCommand?.Dispose();
			_reloadViaKeyPress?.Dispose();
			GameFrame.Initialize();
			if (VWorld.IsServer)
			{
				Chat.Uninitialize();
			}
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			return true;
		}

		private void InitReloadFeatures()
		{
			Directory.CreateDirectory(cfg.PluginsFolder.Value);
			PluginLoaderConfig config = new PluginLoaderConfig(cfg.PluginsFolder.Value);
			IPluginLoader pluginLoader = cfg.LoadingStrategy.Value.ToLowerInvariant() switch
			{
				"basic_deprecated" => new BasicPluginLoader(config), 
				"islands_deprecated" => new IslandsPluginLoader(config), 
				_ => new SilverBulletPluginLoader(config, ((BasePlugin)this).Log), 
			};
			_eventLogger.Subscribe(pluginLoader);
			_pluginLoader = pluginLoader;
			_reloadRequestHandler = new LateUpdateReloadRequestHandler(pluginLoader, ((BasePlugin)this).Log);
			_eventLogger.Subscribe(_reloadRequestHandler);
			_reloadViaChatCommand = new ReloadViaChatCommand(cfg.ReloadCommand.Value);
			_reloadRequestHandler.Subscribe(_reloadViaChatCommand);
			if (cfg.EnableAutoReload.Value)
			{
				_reloadViaFileSystemChanges = new ReloadViaFileSystemChanges(cfg.PluginsFolder.Value, cfg.AutoReloadDelaySeconds.Value);
				_reloadRequestHandler.Subscribe(_reloadViaFileSystemChanges);
			}
			if (VWorld.IsClient)
			{
				_reloadViaKeyPress = new ReloadViaKeyPress((KeyCode)287);
				_reloadRequestHandler.Subscribe(_reloadViaKeyPress);
			}
			ReloadViaRCON requestor = ReloadViaRCON.Initialize();
			_reloadRequestHandler.Subscribe(requestor);
		}

		private void DoInitialPluginsLoad()
		{
			if (_pluginLoader == null)
			{
				throw new Exception("_pluginLoader is null");
			}
			((BasePlugin)this).Log.LogInfo((object)"Starting the Initial load of plugins.");
			_pluginLoader.ReloadAll();
		}

		private void DoInitialPluginsLoad_After_BepInExLoadedOtherPlugins()
		{
			GameFrame.OnUpdate += runOnce;
			void runOnce()
			{
				try
				{
					DoInitialPluginsLoad();
				}
				finally
				{
					GameFrame.OnUpdate -= runOnce;
				}
			}
		}
	}
	internal class EventLogger
	{
		private List<IReloadRequestHandler> _requestHandlerSubscriptions;

		private List<IPluginLoader> _pluginLoaderSubscriptions;

		private ManualLogSource Log { get; }

		public EventLogger(ManualLogSource Log)
		{
			this.Log = Log;
			_requestHandlerSubscriptions = new List<IReloadRequestHandler>();
			_pluginLoaderSubscriptions = new List<IPluginLoader>();
			base..ctor();
		}

		public void Subscribe(IReloadRequestHandler requestHandler)
		{
			_requestHandlerSubscriptions.Add(requestHandler);
			requestHandler.FullReloadStarting += HandleFullReloadStarting;
			requestHandler.PartialReloadStarting += HandlePartialReloadStarting;
			requestHandler.SoftReloadStarting += HandleSoftReloadStarting;
		}

		public void Subscribe(IPluginLoader pluginLoader)
		{
			_pluginLoaderSubscriptions.Add(pluginLoader);
			pluginLoader.ReloadedPlugins += HandleReloadedPlugins;
		}

		public void Unsubscribe()
		{
			foreach (IReloadRequestHandler requestHandlerSubscription in _requestHandlerSubscriptions)
			{
				requestHandlerSubscription.FullReloadStarting -= HandleFullReloadStarting;
				requestHandlerSubscription.PartialReloadStarting -= HandlePartialReloadStarting;
				requestHandlerSubscription.SoftReloadStarting -= HandleSoftReloadStarting;
			}
			_requestHandlerSubscriptions.Clear();
			foreach (IPluginLoader pluginLoaderSubscription in _pluginLoaderSubscriptions)
			{
				pluginLoaderSubscription.ReloadedPlugins -= HandleReloadedPlugins;
			}
			_pluginLoaderSubscriptions.Clear();
		}

		private void HandleFullReloadStarting(object? sender, FullReloadStartingEventArgs ev)
		{
			IEnumerable<string> values = ev.FullReloadRequests.Select((FullReloadRequest r) => r.Requestor.GetType().Name);
			IEnumerable<string> enumerable = ev.PartialReloadRequests.Select((PartialReloadRequest r) => r.Requestor.GetType().Name);
			IEnumerable<string> enumerable2 = ev.SoftReloadRequests.Select((SoftReloadRequest r) => r.Requestor.GetType().Name);
			StringBuilder stringBuilder = new StringBuilder().AppendLine("Starting a Full reload of plugins.");
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(16, 1, stringBuilder);
			handler.AppendLiteral("  Requestor(s): ");
			handler.AppendFormatted(string.Join(", ", values));
			StringBuilder stringBuilder2 = stringBuilder.AppendLine(ref handler);
			StringBuilder.AppendInterpolatedStringHandler handler2 = new StringBuilder.AppendInterpolatedStringHandler(11, 1, stringBuilder2);
			handler2.AppendLiteral("  Handler: ");
			handler2.AppendFormatted(ev.RequestHandler.GetType().Name);
			StringBuilder stringBuilder3 = stringBuilder2.AppendLine(ref handler2);
			StringBuilder stringBuilder4 = stringBuilder3;
			StringBuilder.AppendInterpolatedStringHandler handler3 = new StringBuilder.AppendInterpolatedStringHandler(12, 1, stringBuilder3);
			handler3.AppendLiteral("  Strategy: ");
			handler3.AppendFormatted(ev.PluginLoader.GetType().Name);
			StringBuilder stringBuilder5 = stringBuilder4.Append(ref handler3);
			if (enumerable.Any() || enumerable2.Any())
			{
				stringBuilder5.AppendLine();
				stringBuilder5.AppendLine("  Supercedes other reload requests.");
				if (enumerable.Any())
				{
					stringBuilder3 = stringBuilder5;
					StringBuilder stringBuilder6 = stringBuilder3;
					handler = new StringBuilder.AppendInterpolatedStringHandler(36, 1, stringBuilder3);
					handler.AppendLiteral("    Partial reload request(s) from: ");
					handler.AppendFormatted(string.Join(", ", enumerable));
					stringBuilder6.Append(ref handler);
				}
				if (enumerable2.Any())
				{
					stringBuilder3 = stringBuilder5;
					StringBuilder stringBuilder7 = stringBuilder3;
					handler = new StringBuilder.AppendInterpolatedStringHandler(33, 1, stringBuilder3);
					handler.AppendLiteral("    Soft reload request(s) from: ");
					handler.AppendFormatted(string.Join(", ", enumerable2));
					stringBuilder7.Append(ref handler);
				}
			}
			Log.LogInfo((object)stringBuilder5.ToString());
		}

		private void HandlePartialReloadStarting(object? sender, PartialReloadStartingEventArgs ev)
		{
			IEnumerable<string> values = ev.PartialReloadRequests.Select((PartialReloadRequest r) => r.Requestor.GetType().Name);
			StringBuilder stringBuilder = new StringBuilder().AppendLine("Starting a Partial reload of plugins.");
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(16, 1, stringBuilder);
			handler.AppendLiteral("  Requestor(s): ");
			handler.AppendFormatted(string.Join(", ", values));
			StringBuilder stringBuilder2 = stringBuilder.AppendLine(ref handler);
			StringBuilder.AppendInterpolatedStringHandler handler2 = new StringBuilder.AppendInterpolatedStringHandler(11, 1, stringBuilder2);
			handler2.AppendLiteral("  Handler: ");
			handler2.AppendFormatted(ev.RequestHandler.GetType().Name);
			StringBuilder stringBuilder3 = stringBuilder2.AppendLine(ref handler2);
			StringBuilder.AppendInterpolatedStringHandler handler3 = new StringBuilder.AppendInterpolatedStringHandler(12, 1, stringBuilder3);
			handler3.AppendLiteral("  Strategy: ");
			handler3.AppendFormatted(ev.PluginLoader.GetType().Name);
			StringBuilder stringBuilder4 = stringBuilder3.AppendLine(ref handler3);
			StringBuilder.AppendInterpolatedStringHandler handler4 = new StringBuilder.AppendInterpolatedStringHandler(26, 1, stringBuilder4);
			handler4.AppendLiteral("  Requested plugin GUIDs: ");
			handler4.AppendFormatted(string.Join(", ", ev.AllRequestedPluginGuids));
			StringBuilder stringBuilder5 = stringBuilder4.Append(ref handler4);
			Log.LogInfo((object)stringBuilder5.ToString());
		}

		private void HandleSoftReloadStarting(object? sender, SoftReloadStartingEventArgs ev)
		{
			IEnumerable<string> values = ev.SoftReloadRequests.Select((SoftReloadRequest r) => r.Requestor.GetType().Name);
			StringBuilder stringBuilder = new StringBuilder().AppendLine("Starting a Soft reload of plugins.");
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(16, 1, stringBuilder);
			handler.AppendLiteral("  Requestor(s): ");
			handler.AppendFormatted(string.Join(", ", values));
			StringBuilder stringBuilder2 = stringBuilder.AppendLine(ref handler);
			StringBuilder.AppendInterpolatedStringHandler handler2 = new StringBuilder.AppendInterpolatedStringHandler(11, 1, stringBuilder2);
			handler2.AppendLiteral("  Handler: ");
			handler2.AppendFormatted(ev.RequestHandler.GetType().Name);
			StringBuilder stringBuilder3 = stringBuilder2.AppendLine(ref handler2);
			StringBuilder.AppendInterpolatedStringHandler handler3 = new StringBuilder.AppendInterpolatedStringHandler(12, 1, stringBuilder3);
			handler3.AppendLiteral("  Strategy: ");
			handler3.AppendFormatted(ev.PluginLoader.GetType().Name);
			StringBuilder stringBuilder4 = stringBuilder3.Append(ref handler3);
			Log.LogInfo((object)stringBuilder4.ToString());
		}

		private void HandleReloadedPlugins(object? sender, ReloadedPluginsEventArgs e)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Expected O, but got Unknown
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Expected O, but got Unknown
			bool flag = default(bool);
			if (!e.UnloadedPluginGuids.Any() && !e.LoadedPlugins.Any())
			{
				ManualLogSource log = Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(27, 0, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Did not reload any plugins.");
				}
				log.LogInfo(val);
				return;
			}
			HashSet<string> first = e.UnloadedPluginGuids.ToHashSet();
			HashSet<string> hashSet = e.LoadedPlugins.Select((PluginInfo p) => p.Metadata.GUID).ToHashSet();
			IEnumerable<string> enumerable = first.Intersect(hashSet);
			first = first.Except(enumerable).ToHashSet();
			hashSet = hashSet.Except(enumerable).ToHashSet();
			if (first.Any())
			{
				ManualLogSource log2 = Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(10, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Unloaded ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(string.Join(", ", first));
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
				}
				log2.LogInfo(val);
			}
			if (hashSet.Any())
			{
				ManualLogSource log3 = Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(8, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Loaded ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(string.Join(", ", hashSet));
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
				}
				log3.LogInfo(val);
			}
			if (enumerable.Any())
			{
				ManualLogSource log4 = Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(10, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Reloaded ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(string.Join(", ", enumerable));
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
				}
				log4.LogInfo(val);
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "Bloodpebble";

		public const string PLUGIN_NAME = "Bloodpebble";

		public const string PLUGIN_VERSION = "1.4.2";
	}
}
namespace Bloodpebble.Utils
{
	internal static class VWorld
	{
		private static World? _clientWorld;

		private static World? _serverWorld;

		public static World Server
		{
			get
			{
				if (_serverWorld != null && _serverWorld.IsCreated)
				{
					return _serverWorld;
				}
				_serverWorld = GetWorld("Server") ?? throw new Exception("There is no Server world (yet). Did you install a server mod on the client?");
				return _serverWorld;
			}
		}

		public static World Client
		{
			get
			{
				if (_clientWorld != null && _clientWorld.IsCreated)
				{
					return _clientWorld;
				}
				_clientWorld = GetWorld("Client_0") ?? throw new Exception("There is no Client world (yet). Did you install a client mod on the server?");
				return _clientWorld;
			}
		}

		public static World Default => World.DefaultGameObjectInjectionWorld;

		public static World Game => IsClient ? Client : Server;

		public static bool IsServer => Application.productName == "VRisingServer";

		public static bool IsClient => Application.productName == "VRising";

		private static World? GetWorld(string name)
		{
			Enumerator<World> enumerator = World.s_AllWorlds.GetEnumerator();
			while (enumerator.MoveNext())
			{
				World current = enumerator.Current;
				if (current.Name == name)
				{
					_serverWorld = current;
					return current;
				}
			}
			return null;
		}
	}
}
namespace Bloodpebble.ReloadRequesting
{
	internal interface IReloadRequestHandler : IReloadRequestSubscriber
	{
		event EventHandler<FullReloadStartingEventArgs>? FullReloadStarting;

		event EventHandler<PartialReloadStartingEventArgs>? PartialReloadStarting;

		event EventHandler<SoftReloadStartingEventArgs>? SoftReloadStarting;

		void Dispose();

		void Update();

		void HandleFullReloadRequested(FullReloadRequest request);

		void HandleFullReloadRequested(object? sender, FullReloadRequestedEventArgs ev);

		void HandlePartialReloadRequested(PartialReloadRequest request);

		void HandlePartialReloadRequested(object? sender, PartialReloadRequestedEventArgs ev);

		void HandleSoftReloadRequested(SoftReloadRequest request);

		void HandleSoftReloadRequested(object? sender, SoftReloadRequestedEventArgs ev);
	}
	internal interface IReloadRequestSubscriber
	{
		void Subscribe(IReloadRequestor requestor);

		void Unsubscribe();
	}
	internal class FullReloadStartingEventArgs : EventArgs
	{
		internal IReloadRequestHandler RequestHandler;

		internal IPluginLoader PluginLoader;

		internal IEnumerable<FullReloadRequest> FullReloadRequests;

		internal IEnumerable<PartialReloadRequest> PartialReloadRequests;

		internal IEnumerable<SoftReloadRequest> SoftReloadRequests;

		public FullReloadStartingEventArgs(IReloadRequestHandler requestHandler, IPluginLoader pluginLoader, IEnumerable<FullReloadRequest> fullReloadRequests, IEnumerable<PartialReloadRequest> partialReloadRequests, IEnumerable<SoftReloadRequest> softReloadRequests)
		{
			RequestHandler = requestHandler;
			PluginLoader = pluginLoader;
			FullReloadRequests = fullReloadRequests;
			PartialReloadRequests = partialReloadRequests;
			SoftReloadRequests = softReloadRequests;
			base..ctor();
		}
	}
	internal class PartialReloadStartingEventArgs : EventArgs
	{
		internal IReloadRequestHandler RequestHandler;

		internal IPluginLoader PluginLoader;

		internal IEnumerable<PartialReloadRequest> PartialReloadRequests;

		internal ISet<string> AllRequestedPluginGuids;

		public PartialReloadStartingEventArgs(IReloadRequestHandler requestHandler, IPluginLoader pluginLoader, IEnumerable<PartialReloadRequest> partialReloadRequests, ISet<string> allRequestedPluginGuids)
		{
			RequestHandler = requestHandler;
			PluginLoader = pluginLoader;
			PartialReloadRequests = partialReloadRequests;
			AllRequestedPluginGuids = allRequestedPluginGuids;
			base..ctor();
		}
	}
	internal class SoftReloadStartingEventArgs : EventArgs
	{
		internal IReloadRequestHandler RequestHandler;

		internal IPluginLoader PluginLoader;

		internal IEnumerable<SoftReloadRequest> SoftReloadRequests;

		public SoftReloadStartingEventArgs(IReloadRequestHandler requestHandler, IPluginLoader pluginLoader, IEnumerable<SoftReloadRequest> softReloadRequests)
		{
			RequestHandler = requestHandler;
			PluginLoader = pluginLoader;
			SoftReloadRequests = softReloadRequests;
			base..ctor();
		}
	}
	internal abstract class BaseReloadRequestor : IReloadRequestor
	{
		public event EventHandler<FullReloadRequestedEventArgs>? FullReloadRequested;

		public event EventHandler<PartialReloadRequestedEventArgs>? PartialReloadRequested;

		public event EventHandler<SoftReloadRequestedEventArgs>? SoftReloadRequested;

		protected Task<FullReloadResult> RequestFullReloadAsync()
		{
			TaskCompletionSource<FullReloadResult> taskCompletionSource = new TaskCompletionSource<FullReloadResult>();
			RequestFullReload(taskCompletionSource.SetResult);
			return taskCompletionSource.Task;
		}

		protected void RequestFullReload(Action<FullReloadResult> responseHandler)
		{
			string name = GetType().Name;
			FullReloadRequest request = new FullReloadRequest(this, responseHandler);
			this.FullReloadRequested?.Invoke(this, new FullReloadRequestedEventArgs(request));
		}

		protected Task<PartialReloadResult> RequestPartialReloadAsync(IEnumerable<string> pluginGuidsToReload)
		{
			TaskCompletionSource<PartialReloadResult> taskCompletionSource = new TaskCompletionSource<PartialReloadResult>();
			RequestPartialReload(pluginGuidsToReload, taskCompletionSource.SetResult);
			return taskCompletionSource.Task;
		}

		protected void RequestPartialReload(IEnumerable<string> pluginGuidsToReload, Action<PartialReloadResult> responseHandler)
		{
			string name = GetType().Name;
			PartialReloadRequest request = new PartialReloadRequest(this, responseHandler, pluginGuidsToReload);
			this.PartialReloadRequested?.Invoke(this, new PartialReloadRequestedEventArgs(request));
		}

		protected Task<SoftReloadResult> RequestSoftReloadAsync()
		{
			TaskCompletionSource<SoftReloadResult> taskCompletionSource = new TaskCompletionSource<SoftReloadResult>();
			RequestSoftReload(taskCompletionSource.SetResult);
			return taskCompletionSource.Task;
		}

		protected void RequestSoftReload(Action<SoftReloadResult> responseHandler)
		{
			string name = GetType().Name;
			SoftReloadRequest request = new SoftReloadRequest(this, responseHandler);
			this.SoftReloadRequested?.Invoke(this, new SoftReloadRequestedEventArgs(request));
		}
	}
	internal interface IReloadRequestor
	{
		event EventHandler<FullReloadRequestedEventArgs>? FullReloadRequested;

		event EventHandler<PartialReloadRequestedEventArgs>? PartialReloadRequested;

		event EventHandler<SoftReloadRequestedEventArgs>? SoftReloadRequested;
	}
	internal class PartialReloadRequestedEventArgs : EventArgs
	{
		internal PartialReloadRequest Request;

		public PartialReloadRequestedEventArgs(PartialReloadRequest request)
		{
			Request = request;
			base..ctor();
		}
	}
	internal class FullReloadRequestedEventArgs : EventArgs
	{
		internal FullReloadRequest Request;

		public FullReloadRequestedEventArgs(FullReloadRequest request)
		{
			Request = request;
			base..ctor();
		}
	}
	internal class SoftReloadRequestedEventArgs : EventArgs
	{
		internal SoftReloadRequest Request;

		public SoftReloadRequestedEventArgs(SoftReloadRequest request)
		{
			Request = request;
			base..ctor();
		}
	}
	internal record FullReloadRequest(IReloadRequestor Requestor, Action<FullReloadResult> Respond);
	internal record FullReloadResult(IEnumerable<PluginInfo> PluginsReloaded, ReloadResultStatus Status);
	internal record PartialReloadRequest(IReloadRequestor Requestor, Action<PartialReloadResult> Respond, IEnumerable<string> PluginGuidsToReload);
	internal record PartialReloadResult(IEnumerable<PluginInfo> PluginsReloaded, ReloadResultStatus Status, bool WasSuperseded);
	internal record SoftReloadRequest(IReloadRequestor Requestor, Action<SoftReloadResult> Respond);
	internal record SoftReloadResult(IEnumerable<PluginInfo> PluginsReloaded, ReloadResultStatus Status, bool WasSuperseded);
	internal enum ReloadResultStatus
	{
		Success,
		PartialSuccess,
		Faulted
	}
}
namespace Bloodpebble.ReloadRequestHandling
{
	internal abstract class BaseReloadRequestHandler : IReloadRequestHandler, IReloadRequestSubscriber
	{
		private List<IReloadRequestor> _subscriptions = new List<IReloadRequestor>();

		protected IPluginLoader PluginLoader { get; }

		public event EventHandler<FullReloadStartingEventArgs>? FullReloadStarting;

		public event EventHandler<PartialReloadStartingEventArgs>? PartialReloadStarting;

		public event EventHandler<SoftReloadStartingEventArgs>? SoftReloadStarting;

		protected BaseReloadRequestHandler(IPluginLoader pluginLoader)
		{
			PluginLoader = pluginLoader;
		}

		public void Subscribe(IReloadRequestor requestor)
		{
			_subscriptions.Add(requestor);
			requestor.FullReloadRequested += HandleFullReloadRequested;
			requestor.PartialReloadRequested += HandlePartialReloadRequested;
			requestor.SoftReloadRequested += HandleSoftReloadRequested;
		}

		public void Unsubscribe()
		{
			foreach (IReloadRequestor subscription in _subscriptions)
			{
				subscription.FullReloadRequested -= HandleFullReloadRequested;
				subscription.PartialReloadRequested -= HandlePartialReloadRequested;
				subscription.SoftReloadRequested -= HandleSoftReloadRequested;
			}
			_subscriptions.Clear();
		}

		public void HandleFullReloadRequested(object? sender, FullReloadRequestedEventArgs ev)
		{
			HandleFullReloadRequested(ev.Request);
		}

		public void HandlePartialReloadRequested(object? sender, PartialReloadRequestedEventArgs ev)
		{
			HandlePartialReloadRequested(ev.Request);
		}

		public void HandleSoftReloadRequested(object? sender, SoftReloadRequestedEventArgs ev)
		{
			HandleSoftReloadRequested(ev.Request);
		}

		public virtual void Dispose()
		{
			Unsubscribe();
		}

		protected void OnFullReloadStarting(IEnumerable<FullReloadRequest> fullReloadRequests, IEnumerable<PartialReloadRequest> partialReloadRequests, IEnumerable<SoftReloadRequest> softReloadRequests)
		{
			this.FullReloadStarting?.Invoke(this, new FullReloadStartingEventArgs(this, PluginLoader, fullReloadRequests, partialReloadRequests, softReloadRequests));
		}

		protected void OnPartialReloadStarting(IEnumerable<PartialReloadRequest> partialReloadRequests, ISet<string> allRequestedPluginGuids)
		{
			this.PartialReloadStarting?.Invoke(this, new PartialReloadStartingEventArgs(this, PluginLoader, partialReloadRequests, allRequestedPluginGuids));
		}

		protected void OnSoftReloadStarting(IEnumerable<SoftReloadRequest> softReloadRequests)
		{
			this.SoftReloadStarting?.Invoke(this, new SoftReloadStartingEventArgs(this, PluginLoader, softReloadRequests));
		}

		public abstract void HandleFullReloadRequested(FullReloadRequest request);

		public abstract void HandlePartialReloadRequested(PartialReloadRequest request);

		public abstract void HandleSoftReloadRequested(SoftReloadRequest request);

		public abstract void Update();

		protected static ReloadResultStatus PartialReloadResultStatus(bool faulted, ISet<string> requestedGuids, ISet<string> reloadedGuids)
		{
			if (faulted)
			{
				return ReloadResultStatus.Faulted;
			}
			if (!requestedGuids.IsSubsetOf(reloadedGuids))
			{
				return ReloadResultStatus.PartialSuccess;
			}
			return ReloadResultStatus.Success;
		}
	}
	internal class DeferredReloadRequestHandler : BaseReloadRequestHandler
	{
		private ManualLogSource _log;

		private ConcurrentQueue<FullReloadRequest> _fullReloadRequests = new ConcurrentQueue<FullReloadRequest>();

		private ConcurrentQueue<PartialReloadRequest> _partialReloadRequests = new ConcurrentQueue<PartialReloadRequest>();

		private ConcurrentQueue<SoftReloadRequest> _softReloadRequests = new ConcurrentQueue<SoftReloadRequest>();

		private bool _shouldUpdate = false;

		public DeferredReloadRequestHandler(IPluginLoader pluginLoader, ManualLogSource log)
			: base(pluginLoader)
		{
			_log = log;
		}

		public override void HandleFullReloadRequested(FullReloadRequest request)
		{
			_fullReloadRequests.Enqueue(request);
			_shouldUpdate = true;
		}

		public override void HandlePartialReloadRequested(PartialReloadRequest request)
		{
			_partialReloadRequests.Enqueue(request);
			_shouldUpdate = true;
		}

		public override void HandleSoftReloadRequested(SoftReloadRequest request)
		{
			_softReloadRequests.Enqueue(request);
			_shouldUpdate = true;
		}

		public override void Update()
		{
			if (!_shouldUpdate)
			{
				return;
			}
			_shouldUpdate = false;
			(List<FullReloadRequest> fullReloadRequests, List<PartialReloadRequest> partialReloadRequests, List<SoftReloadRequest> softReloadRequests, HashSet<string> allRequestedPluginGuids) tuple = ExtractReloadRequests();
			List<FullReloadRequest> item = tuple.fullReloadRequests;
			List<PartialReloadRequest> item2 = tuple.partialReloadRequests;
			List<SoftReloadRequest> item3 = tuple.softReloadRequests;
			HashSet<string> item4 = tuple.allRequestedPluginGuids;
			bool faulted = false;
			bool flag = item.Any();
			bool flag2 = !flag && item2.Any();
			IEnumerable<PluginInfo> enumerable;
			try
			{
				if (flag)
				{
					OnFullReloadStarting(item, item2, item3);
					enumerable = base.PluginLoader.ReloadAll();
				}
				else if (flag2)
				{
					OnPartialReloadStarting(item2, item4);
					enumerable = base.PluginLoader.ReloadGiven(item4);
				}
				else
				{
					OnSoftReloadStarting(item3);
					enumerable = base.PluginLoader.ReloadChanges();
				}
			}
			catch (Exception ex)
			{
				_log.LogError((object)ex);
				enumerable = new List<PluginInfo>();
				faulted = true;
			}
			foreach (FullReloadRequest item5 in item)
			{
				RespondToFullReloadRequest(item5, enumerable, faulted);
			}
			HashSet<string> reloadedPluginGuids = enumerable.Select((PluginInfo pluginInfo) => pluginInfo.Metadata.GUID).ToHashSet();
			foreach (PartialReloadRequest item6 in item2)
			{
				RespondToPartialReloadRequest(item6, enumerable, reloadedPluginGuids, item4, faulted, flag);
			}
			foreach (SoftReloadRequest item7 in item3)
			{
				RespondToSoftReloadRequest(item7, enumerable, faulted, flag, flag2);
			}
		}

		private (List<FullReloadRequest> fullReloadRequests, List<PartialReloadRequest> partialReloadRequests, List<SoftReloadRequest> softReloadRequests, HashSet<string> allRequestedPluginGuids) ExtractReloadRequests()
		{
			List<FullReloadRequest> list = new List<FullReloadRequest>();
			List<PartialReloadRequest> list2 = new List<PartialReloadRequest>();
			List<SoftReloadRequest> list3 = new List<SoftReloadRequest>();
			HashSet<string> hashSet = new HashSet<string>();
			FullReloadRequest result;
			while (_fullReloadRequests.TryDequeue(out result))
			{
				list.Add(result);
			}
			PartialReloadRequest result2;
			while (_partialReloadRequests.TryDequeue(out result2))
			{
				list2.Add(result2);
				foreach (string item in result2.PluginGuidsToReload)
				{
					hashSet.Add(item);
				}
			}
			SoftReloadRequest result3;
			while (_softReloadRequests.TryDequeue(out result3))
			{
				list3.Add(result3);
			}
			return (list, list2, list3, hashSet);
		}

		private void RespondToFullReloadRequest(FullReloadRequest request, IEnumerable<PluginInfo> pluginsReloaded, bool faulted)
		{
			try
			{
				request.Respond(new FullReloadResult(pluginsReloaded, faulted ? ReloadResultStatus.Faulted : ReloadResultStatus.Success));
			}
			catch (Exception ex)
			{
				_log.LogError((object)ex);
			}
		}

		private void RespondToPartialReloadRequest(PartialReloadRequest request, IEnumerable<PluginInfo> pluginsReloaded, HashSet<string> reloadedPluginGuids, HashSet<string> allRequestedPluginGuids, bool faulted, bool wasFullReload)
		{
			try
			{
				HashSet<string> hashSet = request.PluginGuidsToReload.ToHashSet();
				request.Respond(new PartialReloadResult(pluginsReloaded, BaseReloadRequestHandler.PartialReloadResultStatus(faulted, hashSet, reloadedPluginGuids), wasFullReload || hashSet.IsProperSubsetOf(allRequestedPluginGuids)));
			}
			catch (Exception ex)
			{
				_log.LogError((object)ex);
			}
		}

		private void RespondToSoftReloadRequest(SoftReloadRequest request, IEnumerable<PluginInfo> pluginsReloaded, bool faulted, bool wasFullReload, bool wasPartialReload)
		{
			try
			{
				request.Respond(new SoftReloadResult(pluginsReloaded, faulted ? ReloadResultStatus.Faulted : ReloadResultStatus.Success, wasFullReload || wasPartialReload));
			}
			catch (Exception ex)
			{
				_log.LogError((object)ex);
			}
		}
	}
	internal class ImmediateReloadRequestHandler : BaseReloadRequestHandler
	{
		private ManualLogSource _log;

		public ImmediateReloadRequestHandler(IPluginLoader pluginLoader, ManualLogSource log)
			: base(pluginLoader)
		{
			_log = log;
		}

		public override void HandleFullReloadRequested(FullReloadRequest request)
		{
			bool flag = false;
			IEnumerable<PluginInfo> pluginsReloaded;
			try
			{
				OnFullReloadStarting(new <>z__ReadOnlySingleElementList<FullReloadRequest>(request), Array.Empty<PartialReloadRequest>(), Array.Empty<SoftReloadRequest>());
				pluginsReloaded = base.PluginLoader.ReloadAll();
			}
			catch (Exception ex)
			{
				_log.LogError((object)ex);
				pluginsReloaded = new List<PluginInfo>();
				flag = true;
			}
			request.Respond(new FullReloadResult(pluginsReloaded, flag ? ReloadResultStatus.Faulted : ReloadResultStatus.Success));
		}

		public override void HandlePartialReloadRequested(PartialReloadRequest request)
		{
			bool faulted = false;
			IEnumerable<PluginInfo> enumerable;
			try
			{
				OnPartialReloadStarting(new <>z__ReadOnlySingleElementList<PartialReloadRequest>(request), request.PluginGuidsToReload.ToHashSet());
				enumerable = base.PluginLoader.ReloadGiven(request.PluginGuidsToReload);
			}
			catch (Exception ex)
			{
				_log.LogError((object)ex);
				enumerable = new List<PluginInfo>();
				faulted = true;
			}
			HashSet<string> requestedGuids = request.PluginGuidsToReload.ToHashSet();
			HashSet<string> reloadedGuids = enumerable.Select((PluginInfo pluginInfo) => pluginInfo.Metadata.GUID).ToHashSet();
			request.Respond(new PartialReloadResult(enumerable, BaseReloadRequestHandler.PartialReloadResultStatus(faulted, requestedGuids, reloadedGuids), WasSuperseded: false));
		}

		public override void HandleSoftReloadRequested(SoftReloadRequest request)
		{
			bool flag = false;
			IEnumerable<PluginInfo> pluginsReloaded;
			try
			{
				OnSoftReloadStarting(new <>z__ReadOnlySingleElementList<SoftReloadRequest>(request));
				pluginsReloaded = base.PluginLoader.ReloadAll();
			}
			catch (Exception ex)
			{
				_log.LogError((object)ex);
				pluginsReloaded = new List<PluginInfo>();
				flag = true;
			}
			request.Respond(new SoftReloadResult(pluginsReloaded, flag ? ReloadResultStatus.Faulted : ReloadResultStatus.Success, WasSuperseded: false));
		}

		public override void Update()
		{
		}
	}
	internal class LateUpdateReloadRequestHandler : DeferredReloadRequestHandler
	{
		public LateUpdateReloadRequestHandler(IPluginLoader pluginLoader, ManualLogSource log)
			: base(pluginLoader, log)
		{
			GameFrame.OnLateUpdate += Update;
		}

		public override void Dispose()
		{
			GameFrame.OnLateUpdate -= Update;
			base.Dispose();
		}
	}
}
namespace Bloodpebble.ReloadExecution
{
	internal abstract class BasePluginLoader : ITriggersPluginLoaderEvents
	{
		public event EventHandler<ReloadedPluginsEventArgs>? ReloadedPlugins;

		protected void OnReloadedPlugins(IList<PluginInfo> loadedPlugins, IEnumerable<string> unloadedPluginGuids)
		{
			this.ReloadedPlugins?.Invoke(this, new ReloadedPluginsEventArgs(loadedPlugins, unloadedPluginGuids));
		}
	}
	public class BloodpebblePluginInfo : PluginInfo
	{
		public BepInPlugin __Metadata { get; internal set; }

		public IEnumerable<BepInProcess> __Processes { get; internal set; }

		public IEnumerable<BepInDependency> __Dependencies { get; internal set; }

		public IEnumerable<BepInIncompatibility> __Incompatibilities { get; internal set; }

		public string __Location { get; internal set; }

		public object __Instance { get; internal set; }

		public string __TypeName { get; internal set; }

		public BloodpebblePluginInfo(BepInPlugin metadata, IEnumerable<BepInProcess> processes, IEnumerable<BepInDependency> dependencies, IEnumerable<BepInIncompatibility> incompatibilities, string location, object instance, string typeName)
		{
			__Metadata = metadata;
			__Processes = processes;
			__Dependencies = dependencies;
			__Incompatibilities = incompatibilities;
			__Location = location;
			__Instance = instance;
			__TypeName = typeName;
		}

		public void SetInstance(object instance)
		{
			__Instance = instance;
		}
	}
	[HarmonyPatch]
	public static class BloodpebblePluginInfoPatch
	{
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		public static void Metadata_Get(PluginInfo __instance, ref BepInPlugin __result)
		{
			if (__instance is BloodpebblePluginInfo bloodpebblePluginInfo)
			{
				__result = bloodpebblePluginInfo.__Metadata;
			}
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		public static void Processes_Get(PluginInfo __instance, ref IEnumerable<BepInProcess> __result)
		{
			if (__instance is BloodpebblePluginInfo bloodpebblePluginInfo)
			{
				__result = bloodpebblePluginInfo.__Processes;
			}
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		public static void Dependencies_Get(PluginInfo __instance, ref IEnumerable<BepInDependency> __result)
		{
			if (__instance is BloodpebblePluginInfo bloodpebblePluginInfo)
			{
				__result = bloodpebblePluginInfo.__Dependencies;
			}
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		public static void Incompatibilities_Get(PluginInfo __instance, ref IEnumerable<BepInIncompatibility> __result)
		{
			if (__instance is BloodpebblePluginInfo bloodpebblePluginInfo)
			{
				__result = bloodpebblePluginInfo.__Incompatibilities;
			}
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		public static void Location_Get(PluginInfo __instance, ref string __result)
		{
			if (__instance is BloodpebblePluginInfo bloodpebblePluginInfo)
			{
				__result = bloodpebblePluginInfo.__Location;
			}
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		public static void Instance_Get(PluginInfo __instance, ref object __result)
		{
			if (__instance is BloodpebblePluginInfo bloodpebblePluginInfo)
			{
				__result = bloodpebblePluginInfo.__Instance;
			}
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		public static void TypeName_Get(PluginInfo __instance, ref string __result)
		{
			if (__instance is BloodpebblePluginInfo bloodpebblePluginInfo)
			{
				__result = bloodpebblePluginInfo.__TypeName;
			}
		}
	}
	internal interface IPluginLoader : ITriggersPluginLoaderEvents
	{
		IList<PluginInfo> ReloadAll();

		IList<PluginInfo> ReloadGiven(IEnumerable<string> pluginGUIDs);

		IList<PluginInfo> ReloadChanges();

		IEnumerable<string> UnloadAll();
	}
	internal interface ITriggersPluginLoaderEvents
	{
		event EventHandler<ReloadedPluginsEventArgs>? ReloadedPlugins;
	}
	internal class ReloadedPluginsEventArgs : EventArgs
	{
		internal IList<PluginInfo> LoadedPlugins { get; }

		internal IEnumerable<string> UnloadedPluginGuids { get; }

		public ReloadedPluginsEventArgs(IList<PluginInfo> loadedPlugins, IEnumerable<string> unloadedPluginGuids)
		{
			LoadedPlugins = loadedPlugins;
			UnloadedPluginGuids = unloadedPluginGuids;
			base..ctor();
		}
	}
	internal record PluginLoaderConfig(string PluginsPath);
}
namespace Bloodpebble.ReloadExecution.LoadingStrategySilverBullet
{
	internal class BloodpebbleLoadContext : AssemblyLoadContext
	{
		protected static Dictionary<string, Assembly> DefaultAssemblyLookupByFullName = new Dictionary<string, Assembly>();

		private Dictionary<string, Assembly> _bloodpebbleAssemblyLookupByPartialName;

		internal BloodpebbleLoadContext(string name, Dictionary<string, Assembly> assemblyLookupByPartialName)
			: base(name, isCollectible: true)
		{
			_bloodpebbleAssemblyLookupByPartialName = assemblyLookupByPartialName;
		}

		protected override Assembly? Load(AssemblyName assemblyName)
		{
			Assembly assembly = LoadAssembly_PreloadedBloodpebblePlugin(assemblyName);
			if ((object)assembly == null)
			{
				assembly = LoadAssembly_NotPloodpebblePlugin(assemblyName);
			}
			return assembly;
		}

		private Assembly? LoadAssembly_PreloadedBloodpebblePlugin(AssemblyName assemblyName)
		{
			if (assemblyName.Name == null)
			{
				return null;
			}
			if (_bloodpebbleAssemblyLookupByPartialName.TryGetValue(assemblyName.Name, out Assembly value))
			{
				return value;
			}
			return null;
		}

		private Assembly? LoadAssembly_NotPloodpebblePlugin(AssemblyName assemblyName)
		{
			if (DefaultAssemblyLookupByFullName.TryGetValue(assemblyName.FullName, out Assembly value))
			{
				return value;
			}
			try
			{
				value = AssemblyLoadContext.Default.LoadFromAssemblyName(assemblyName);
				if (value != null)
				{
					DefaultAssemblyLookupByFullName.Add(assemblyName.FullName, value);
				}
				return value;
			}
			catch (Exception ex)
			{
				CheckAndLogBadSearchForBloodpebblePlugin(assemblyName, ex);
				throw;
			}
		}

		private void CheckAndLogBadSearchForBloodpebblePlugin(AssemblyName assemblyName, Exception ex)
		{
			for (Exception ex2 = ex; ex2 != null; ex2 = ex.InnerException)
			{
				if (ex2.Message.Equals("Resolving to a collectible assembly is not supported."))
				{
					StringBuilder stringBuilder = new StringBuilder();
					stringBuilder.AppendLine("Potential fallback to default assembly resolution, for a plugin that was already loaded by Bloodpebble.");
					StringBuilder stringBuilder2 = stringBuilder;
					StringBuilder stringBuilder3 = stringBuilder2;
					StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(47, 1, stringBuilder2);
					handler.AppendLiteral("  Assembly load context triggering the search: ");
					handler.AppendFormatted(base.Name);
					stringBuilder3.AppendLine(ref handler);
					stringBuilder2 = stringBuilder;
					StringBuilder stringBuilder4 = stringBuilder2;
					handler = new StringBuilder.AppendInterpolatedStringHandler(31, 1, stringBuilder2);
					handler.AppendLiteral("  Assembly being searched for: ");
					handler.AppendFormatted(assemblyName.FullName);
					stringBuilder4.Append(ref handler);
					BloodpebblePlugin.Logger.LogWarning((object)stringBuilder.ToString());
					break;
				}
			}
		}
	}
	internal class DependencyGraph
	{
		private HashSet<string> AddedVertexIds = new HashSet<string>();

		private Dictionary<string, HashSet<string>> DirectDependenciesLookup = new Dictionary<string, HashSet<string>>();

		private Dictionary<string, HashSet<string>> DescendentsLookup = new Dictionary<string, HashSet<string>>();

		private Dictionary<string, HashSet<string>> AncestorsLookup = new Dictionary<string, HashSet<string>>();

		internal bool AddVertex(string vertexId, HashSet<string> directDependencyIds)
		{
			if (AddedVertexIds.Contains(vertexId))
			{
				return false;
			}
			AddedVertexIds.Add(vertexId);
			DirectDependenciesLookup.Add(vertexId, directDependencyIds.ToHashSet());
			HashSet<string> orCreate = DescendentsLookup.GetOrCreate(vertexId);
			orCreate.UnionWith(directDependencyIds);
			HashSet<string> orCreate2 = AncestorsLookup.GetOrCreate(vertexId);
			HashSet<string> visitedIds = new HashSet<string>();
			foreach (string item in orCreate)
			{
				DfsWalkDescendentsForAdd(vertexId, orCreate, orCreate2, visitedIds, item);
			}
			foreach (string item2 in orCreate2)
			{
				HashSet<string> orCreate3 = DescendentsLookup.GetOrCreate(item2);
				orCreate3.UnionWith(orCreate);
			}
			return true;
		}

		private void DfsWalkDescendentsForAdd(string ownVertexId, HashSet<string> ownDescendentIds, HashSet<string> ownAncestorIds, HashSet<string> visitedIds, string otherId)
		{
			if (visitedIds.Contains(otherId))
			{
				return;
			}
			visitedIds.Add(otherId);
			HashSet<string> orCreate = AncestorsLookup.GetOrCreate(otherId);
			orCreate.Add(ownVertexId);
			orCreate.UnionWith(ownAncestorIds);
			HashSet<string> orCreate2 = DescendentsLookup.GetOrCreate(otherId);
			ownDescendentIds.UnionWith(orCreate2);
			foreach (string item in orCreate2)
			{
				DfsWalkDescendentsForAdd(ownVertexId, ownDescendentIds, ownAncestorIds, visitedIds, item);
			}
		}

		internal bool RemoveVertex(string vertexId)
		{
			if (!AddedVertexIds.Contains(vertexId))
			{
				return false;
			}
			HashSet<string> hashSet = DescendentsLookup[vertexId];
			foreach (string item in hashSet)
			{
				if (AncestorsLookup.TryGetValue(item, out HashSet<string> value))
				{
					value.Remove(vertexId);
				}
			}
			HashSet<string> hashSet2 = AncestorsLookup[vertexId];
			foreach (string item2 in hashSet2)
			{
				if (DescendentsLookup.TryGetValue(item2, out HashSet<string> value2))
				{
					value2.Remove(vertexId);
				}
			}
			AddedVertexIds.Remove(vertexId);
			DescendentsLookup.Remove(vertexId);
			AncestorsLookup.Remove(vertexId);
			DirectDependenciesLookup.Remove(vertexId);
			return true;
		}

		internal ISet<string> FindAllVertexesToLoad(ISet<string> targetedVertexIdsToLoad)
		{
			HashSet<string> hashSet = new HashSet<string>();
			hashSet.UnionWith(targetedVertexIdsToLoad);
			foreach (string item in targetedVertexIdsToLoad)
			{
				if (DescendentsLookup.TryGetValue(item, out HashSet<string> value))
				{
					hashSet.UnionWith(value);
				}
			}
			return hashSet;
		}

		internal ISet<string> FindAllVertexesToUnload(ISet<string> targetedVertexIdsToUnload)
		{
			HashSet<string> hashSet = new HashSet<string>();
			hashSet.UnionWith(targetedVertexIdsToUnload);
			foreach (string item in targetedVertexIdsToUnload)
			{
				if (AncestorsLookup.TryGetValue(item, out HashSet<string> value))
				{
					hashSet.UnionWith(value);
				}
			}
			return hashSet;
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("===========================================");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("VertexIds ---------------------------------");
			if (!AddedVertexIds.Any())
			{
				stringBuilder.AppendLine("  (empty)");
			}
			foreach (string addedVertexId in AddedVertexIds)
			{
				StringBuilder stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder3 = stringBuilder2;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 1, stringBuilder2);
				handler.AppendLiteral("  ");
				handler.AppendFormatted(addedVertexId);
				stringBuilder3.AppendLine(ref handler);
			}
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("DirectDependenciesLookup ------------------");
			if (!DirectDependenciesLookup.Any())
			{
				stringBuilder.AppendLine("  (empty)");
			}
			string key;
			HashSet<string> value;
			foreach (KeyValuePair<string, HashSet<string>> item in DirectDependenciesLookup)
			{
				item.Deconstruct(out key, out value);
				string value2 = key;
				HashSet<string> hashSet = value;
				StringBuilder stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder4 = stringBuilder2;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 1, stringBuilder2);
				handler.AppendLiteral("  ");
				handler.AppendFormatted(value2);
				stringBuilder4.AppendLine(ref handler);
				if (!hashSet.Any())
				{
					stringBuilder.AppendLine("    (empty)");
				}
				foreach (string item2 in hashSet)
				{
					stringBuilder2 = stringBuilder;
					StringBuilder stringBuilder5 = stringBuilder2;
					handler = new StringBuilder.AppendInterpolatedStringHandler(4, 1, stringBuilder2);
					handler.AppendLiteral("    ");
					handler.AppendFormatted(item2);
					stringBuilder5.AppendLine(ref handler);
				}
			}
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("DescendentsLookup -------------------------");
			if (!DescendentsLookup.Any())
			{
				stringBuilder.AppendLine("  (empty)");
			}
			foreach (KeyValuePair<string, HashSet<string>> item3 in DescendentsLookup)
			{
				item3.Deconstruct(out key, out value);
				string value3 = key;
				HashSet<string> hashSet2 = value;
				StringBuilder stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder6 = stringBuilder2;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 1, stringBuilder2);
				handler.AppendLiteral("  ");
				handler.AppendFormatted(value3);
				stringBuilder6.AppendLine(ref handler);
				if (!hashSet2.Any())
				{
					stringBuilder.AppendLine("    (empty)");
				}
				foreach (string item4 in hashSet2)
				{
					stringBuilder2 = stringBuilder;
					StringBuilder stringBuilder7 = stringBuilder2;
					handler = new StringBuilder.AppendInterpolatedStringHandler(4, 1, stringBuilder2);
					handler.AppendLiteral("    ");
					handler.AppendFormatted(item4);
					stringBuilder7.AppendLine(ref handler);
				}
			}
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("AncestorsLookup ---------------------------");
			if (!AncestorsLookup.Any())
			{
				stringBuilder.AppendLine("  (empty)");
			}
			foreach (KeyValuePair<string, HashSet<string>> item5 in AncestorsLookup)
			{
				item5.Deconstruct(out key, out value);
				string value4 = key;
				HashSet<string> hashSet3 = value;
				StringBuilder stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder8 = stringBuilder2;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 1, stringBuilder2);
				handler.AppendLiteral("  ");
				handler.AppendFormatted(value4);
				stringBuilder8.AppendLine(ref handler);
				if (!hashSet3.Any())
				{
					stringBuilder.AppendLine("    (empty)");
				}
				foreach (string item6 in hashSet3)
				{
					stringBuilder2 = stringBuilder;
					StringBuilder stringBuilder9 = stringBuilder2;
					handler = new StringBuilder.AppendInterpolatedStringHandler(4, 1, stringBuilder2);
					handler.AppendLiteral("    ");
					handler.AppendFormatted(item6);
					stringBuilder9.AppendLine(ref handler);
				}
			}
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("===========================================");
			return stringBuilder.ToString();
		}
	}
	internal class ModifiedBepInExChainloader : IL2CPPChainloader
	{
		private BaseAssemblyResolver _assemblyResolver;

		private Dictionary<string, BloodpebbleLoadContext> _loadContextLookupByPluginGuid = new Dictionary<string, BloodpebbleLoadContext>();

		private Dictionary<string, Assembly> _assemblyLookupByPartialName = new Dictionary<string, Assembly>();

		private Dictionary<string, Assembly> _assemblyLookupByPluginGuid = new Dictionary<string, Assembly>();

		public ModifiedBepInExChainloader()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			_assemblyResolver = (BaseAssemblyResolver)new DefaultAssemblyResolver();
			_assemblyResolver.AddSearchDirectory(Paths.ManagedPath);
			_assemblyResolver.AddSearchDirectory(Paths.BepInExAssemblyDirectory);
			_assemblyResolver.AddSearchDirectory(Path.Combine(Paths.BepInExRootPath, "interop"));
		}

		private BloodpebbleLoadContext CreateNewAssemblyLoadContext(string pluginGuid)
		{
			return new BloodpebbleLoadContext("BloodpebbleContext-" + pluginGuid, _assemblyLookupByPartialName);
		}

		public IList<PluginInfo> DiscoverPluginsFrom(string path)
		{
			return ((BaseChainloader<BasePlugin>)this).DiscoverPluginsFrom(path, "chainloader");
		}

		public IEnumerable<PluginInfo> ModifyLoadOrder(IEnumerable<PluginInfo> plugins)
		{
			return ((BaseChainloader<BasePlugin>)this).ModifyLoadOrder((IList<PluginInfo>)plugins.ToList());
		}

		public IEnumerable<PluginInfo> ModifyUnloadOrder(IEnumerable<PluginInfo> plugins)
		{
			SortedDictionary<string, IEnumerable<string>> dependencyDict = new SortedDictionary<string, IEnumerable<string>>(StringComparer.InvariantCultureIgnoreCase);
			Dictionary<string, PluginInfo> pluginsByGuid = new Dictionary<string, PluginInfo>();
			foreach (PluginInfo plugin in plugins)
			{
				pluginsByGuid[plugin.Metadata.GUID] = plugin;
				dependencyDict[plugin.Metadata.GUID] = plugin.Dependencies.Select((BepInDependency d) => d.DependencyGUID);
			}
			string[] emptyDependencies = new string[0];
			Func<string, IEnumerable<string>> func = (string guid) => dependencyDict.GetValueOrDefault(guid) ?? emptyDependencies;
			IEnumerable<string> source = Utility.TopologicalSort<string>((IEnumerable<string>)dependencyDict.Keys, func);
			IEnumerable<string> source2 = source.Reverse();
			return (from guid in source2.Where(pluginsByGuid.ContainsKey)
				select pluginsByGuid[guid]).ToList();
		}

		public IList<PluginInfo> LoadPlugins(IList<PluginInfo> plugins)
		{
			//IL_05ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0603: Expected O, but got Unknown
			//IL_0652: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Expected O, but got Unknown
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Expected O, but got Unknown
			//IL_0531: Unknown result type (might be due to invalid IL or missing references)
			//IL_0533: Unknown result type (might be due to invalid IL or missing references)
			//IL_0535: Unknown result type (might be due to invalid IL or missing references)
			//IL_053a: Unknown result type (might be due to invalid IL or missing references)
			//IL_053e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0545: Expected O, but got Unknown
			//IL_0576: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Expected O, but got Unknown
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03de: Expected O, but got Unknown
			//IL_0399: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			IEnumerable<PluginInfo> enumerable = ModifyLoadOrder(plugins);
			HashSet<string> hashSet = new HashSet<string>();
			Dictionary<string, Version> dictionary = new Dictionary<string, Version>();
			Dictionary<string, Assembly> dictionary2 = new Dictionary<string, Assembly>();
			List<PluginInfo> list = new List<PluginInfo>();
			bool flag3 = default(bool);
			foreach (PluginInfo item in enumerable)
			{
				bool flag = false;
				List<BepInDependency> list2 = new List<BepInDependency>();
				foreach (BepInDependency dependency in item.Dependencies)
				{
					Version value;
					bool flag2 = dictionary.TryGetValue(dependency.DependencyGUID, out value);
					if (!flag2)
					{
						flag2 = ((BaseChainloader<BasePlugin>)this).Plugins.TryGetValue(dependency.DependencyGUID, out var value2);
						value = ((value2 != null) ? value2.Metadata.Version : null);
					}
					if (!flag2 || (dependency.VersionRange != (Range)null && !dependency.VersionRange.IsSatisfied(value, false)))
					{
						if (IsHardDependency(dependency))
						{
							list2.Add(dependency);
						}
					}
					else if (hashSet.Contains(dependency.DependencyGUID) && IsHardDependency(dependency))
					{
						flag = true;
						break;
					}
				}
				dictionary.Add(item.Metadata.GUID, item.Metadata.Version);
				if (flag)
				{
					string text = $"Skipping [{item}] because it has a dependency that was not loaded. See previous errors for details.";
					((BaseChainloader<BasePlugin>)this).DependencyErrors.Add(text);
					BloodpebblePlugin.Logger.Log((LogLevel)4, (object)text);
					continue;
				}
				if (list2.Count != 0)
				{
					string text2 = $"Could not load [{item}] because it has missing dependencies: {string.Join(", ", list2.Select((BepInDependency s) => (s.VersionRange == (Range)null) ? s.DependencyGUID : $"{s.DependencyGUID} ({s.VersionRange})").ToArray())}";
					((BaseChainloader<BasePlugin>)this).DependencyErrors.Add(text2);
					BloodpebblePlugin.Logger.Log((LogLevel)2, (object)text2);
					hashSet.Add(item.Metadata.GUID);
					continue;
				}
				try
				{
					ManualLogSource logger = BloodpebblePlugin.Logger;
					LogLevel val = (LogLevel)16;
					LogLevel val2 = val;
					BepInExLogInterpolatedStringHandler val3 = new BepInExLogInterpolatedStringHandler(10, 1, val, ref flag3);
					if (flag3)
					{
						val3.AppendLiteral("Loading [");
						val3.AppendFormatted<PluginInfo>(item);
						val3.AppendLiteral("]");
					}
					logger.Log(val2, val3);
					if (dictionary2.TryGetValue(item.Location, out var value3))
					{
						goto IL_0476;
					}
					string gUID = item.Metadata.GUID;
					BloodpebbleLoadContext bloodpebbleLoadContext = CreateNewAssemblyLoadContext(gUID);
					AssemblyDefinition val4 = AssemblyDefinition.ReadAssembly(item.Location, new ReaderParameters
					{
						AssemblyResolver = (IAssemblyResolver)(object)_assemblyResolver
					});
					try
					{
						using MemoryStream memoryStream = new MemoryStream();
						val4.Write((Stream)memoryStream);
						memoryStream.Seek(0L, SeekOrigin.Begin);
						value3 = bloodpebbleLoadContext.LoadFromStream(memoryStream);
						if (value3.FullName == null)
						{
							ManualLogSource logger2 = BloodpebblePlugin.Logger;
							LogLevel val5 = (LogLevel)2;
							LogLevel val6 = val5;
							val3 = new BepInExLogInterpolatedStringHandler(39, 1, val5, ref flag3);
							if (flag3)
							{
								val3.AppendLiteral("Assembly.FullName is null for plugin [");
								val3.AppendFormatted<PluginInfo>(item);
								val3.AppendLiteral("]");
							}
							logger2.Log(val6, val3);
							continue;
						}
						string name = value3.GetName().Name;
						if (name == null)
						{
							ManualLogSource logger3 = BloodpebblePlugin.Logger;
							LogLevel val7 = (LogLevel)2;
							LogLevel val8 = val7;
							val3 = new BepInExLogInterpolatedStringHandler(45, 1, val7, ref flag3);
							if (flag3)
							{
								val3.AppendLiteral("Assembly.GetName().Name is null for plugin [");
								val3.AppendFormatted<PluginInfo>(item);
								val3.AppendLiteral("]");
							}
							logger3.Log(val8, val3);
							continue;
						}
						dictionary2[item.Location] = value3;
						_loadContextLookupByPluginGuid[gUID] = bloodpebbleLoadContext;
						_assemblyLookupByPluginGuid.Add(gUID, value3);
						_assemblyLookupByPartialName.Add(name, value3);
						goto IL_0476;
					}
					finally
					{
						((IDisposable)val4)?.Dispose();
					}
					IL_0476:
					BloodpebblePluginInfo bloodpebblePluginInfo = new BloodpebblePluginInfo(item.Metadata, item.Processes, item.Dependencies, item.Incompatibilities, item.Location, item.Instance, item.TypeName);
					((BaseChainloader<BasePlugin>)this).Plugins[item.Metadata.GUID] = (PluginInfo)(object)bloodpebblePluginInfo;
					TryRunModuleCtor(item, value3);
					bool flag4 = (from att in value3.GetCustomAttributes<AssemblyMetadataAttribute>()
						where att.Key.ToLowerInvariant().Equals("reloadable")
						where att.Value?.ToLowerInvariant().Equals("true") ?? false
						select att).Any();
					ManualLogSource logger4 = BloodpebblePlugin.Logger;
					LogLevel val9 = (LogLevel)16;
					LogLevel val10 = val9;
					val3 = new BepInExLogInterpolatedStringHandler(32, 2, val9, ref flag3);
					if (flag3)
					{
						val3.AppendFormatted<string>(value3.GetName().Name);
						val3.AppendLiteral(" metadata indicates reloadable: ");
						val3.AppendFormatted<bool>(flag4);
					}
					logger4.Log(val10, val3);
					BasePlugin instance = ((BaseChainloader<BasePlugin>)(object)this).LoadPlugin(item, value3);
					bloodpebblePluginInfo.SetInstance(instance);
					list.Add((PluginInfo)(object)bloodpebblePluginInfo);
				}
				catch (Exception ex)
				{
					hashSet.Add(item.Metadata.GUID);
					((BaseChainloader<BasePlugin>)this).Plugins.Remove(item.Metadata.GUID);
					UnloadPluginAssembly(item.Metadata.GUID);
					ManualLogSource logger5 = BloodpebblePlugin.Logger;
					LogLevel val11 = (LogLevel)2;
					LogLevel val12 = val11;
					BepInExLogInterpolatedStringHandler val3 = new BepInExLogInterpolatedStringHandler(18, 2, val11, ref flag3);
					if (flag3)
					{
						val3.AppendLiteral("Error loading [");
						val3.AppendFormatted<PluginInfo>(item);
						val3.AppendLiteral("]: ");
						val3.AppendFormatted<string>((ex is ReflectionTypeLoadException ex2) ? TypeLoader.TypeLoadExceptionToString(ex2) : ex.ToString());
					}
					logger5.Log(val12, val3);
				}
			}
			return list;
			static bool IsHardDependency(BepInDependency dep)
			{
				//IL_0001: 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_0009: Invalid comparison between Unknown and I4
				return (dep.Flags & 1) > 0;
			}
		}

		public IList<PluginInfo> LoadPlugins(params string[] pluginsPaths)
		{
			List<PluginInfo> list = new List<PluginInfo>();
			foreach (string text in pluginsPaths)
			{
				list.AddRange(DiscoverPluginsFrom(text));
				_assemblyResolver.AddSearchDirectory(text);
			}
			IList<PluginInfo> result = LoadPlugins(list);
			foreach (string text2 in pluginsPaths)
			{
				_assemblyResolver.RemoveSearchDirectory(text2);
			}
			return result;
		}

		protected static void TryRunModuleCtor(PluginInfo plugin, Assembly assembly)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				RuntimeHelpers.RunModuleConstructor(assembly.GetType(plugin.TypeName).Module.ModuleHandle);
			}
			catch (Exception ex)
			{
				ManualLogSource logger = BloodpebblePlugin.Logger;
				LogLevel val = (LogLevel)4;
				LogLevel val2 = val;
				bool flag = default(bool);
				BepInExLogInterpolatedStringHandler val3 = new BepInExLogInterpolatedStringHandler(40, 3, val, ref flag);
				if (flag)
				{
					val3.AppendLiteral("Couldn't run Module constructor for ");
					val3.AppendFormatted<string>(assembly.FullName);
					val3.AppendLiteral("::");
					val3.AppendFormatted<string>(plugin.TypeName);
					val3.AppendLiteral(": ");
					val3.AppendFormatted<Exception>(ex);
				}
				logger.Log(val2, val3);
			}
		}

		public void UnloadPlugin(PluginInfo plugin)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			BasePlugin val = (BasePlugin)plugin.Instance;
			AssemblyName name = ((object)val).GetType().Assembly.GetName();
			string text = $"{name.Name} {name.Version}";
			bool flag = default(bool);
			try
			{
				if (!val.Unload())
				{
					ManualLogSource logger = BloodpebblePlugin.Logger;
					BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(63, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Plugin ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" might not be reloadable. (Plugin.Unload returned false)");
					}
					logger.LogWarning(val2);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger2 = BloodpebblePlugin.Logger;
				BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(25, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Error unloading plugin ");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(text);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(": ");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Exception>(ex);
				}
				logger2.LogError(val3);
			}
			UnloadPluginAssembly(plugin.Metadata.GUID);
			((BaseChainloader<BasePlugin>)this).Plugins.Remove(plugin.Metadata.GUID);
		}

		public void UnloadPluginAssembly(string pluginGuid)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			if (_loadContextLookupByPluginGuid.Remove(pluginGuid, out BloodpebbleLoadContext value))
			{
				value.Unload();
			}
			if (!_assemblyLookupByPluginGuid.Remove(pluginGuid, out Assembly value2))
			{
				return;
			}
			string name = value2.GetName().Name;
			if (name == null)
			{
				ManualLogSource logger = BloodpebblePlugin.Logger;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(26, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Assembly for ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(pluginGuid);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" has no Name.");
				}
				logger.LogWarning(val);
			}
			else
			{
				_assemblyLookupByPartialName.Remove(name);
			}
		}
	}
	internal class SilverBulletPluginLoader : BasePluginLoader, IPluginLoader, ITriggersPluginLoaderEvents
	{
		private Dictionary<string, PluginInfo> _reloadablePlugins = new Dictionary<string, PluginInfo>();

		private Dictionary<string, DateTime> _lastWriteTimes = new Dictionary<string, DateTime>();

		private ModifiedBepInExChainloader _bepinexChainloader = new ModifiedBepInExChainloader();

		private PluginLoaderConfig _config;

		protected ManualLogSource Log;

		private DependencyGraph _dependencyGraph = new DependencyGraph();

		public SilverBulletPluginLoader(PluginLoaderConfig config, ManualLogSource log)
		{
			_config = config;
			Log = log;
		}

		public IList<PluginInfo> ReloadAll()
		{
			IEnumerable<string> unloadedPluginGuids = UnloadAll();
			IList<PluginInfo> list = LoadAll();
			OnReloadedPlugins(list, unloadedPluginGuids);
			return list;
		}

		public IEnumerable<string> UnloadAll()
		{
			Dictionary<string, PluginInfo>.KeyCollection keys = _reloadablePlugins.Keys;
			return UnloadGiven(keys);
		}

		private IList<PluginInfo> LoadAll()
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			PrepareForLoad();
			IList<PluginInfo> list = _bepinexChainloader.LoadPlugins(_config.PluginsPath);
			ProcessFreshlyLoadedPlugins(list);
			IEnumerable<string> values = list.Select((PluginInfo p) => p.Metadata.GUID);
			ManualLogSource log = Log;
			bool flag = default(bool);
			BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(38, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Loaded plugin(s): ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(string.Join(", ", values));
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". \nResulting graph:\n");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<DependencyGraph>(_dependencyGraph);
			}
			log.LogDebug(val);
			return list;
		}

		public IList<PluginInfo> ReloadGiven(IEnumerable<string> pluginGUIDs)
		{
			IEnumerable<string> enumerable = UnloadGivenAndDependents(pluginGUIDs);
			IList<PluginInfo> list = LoadGivenAndDependencies(enumerable);
			OnReloadedPlugins(list, enumerable);
			return list;
		}

		private IEnumerable<string> UnloadGivenAndDependents(IEnumerable<string> pluginGUIDs)
		{
			ISet<string> pluginGUIDs2 = _dependencyGraph.FindAllVertexesToUnload(pluginGUIDs.ToHashSet());
			return UnloadGiven(pluginGUIDs2);
		}

		private IEnumerable<string> UnloadGiven(IEnumerable<string> pluginGUIDs)
		{
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Expected O, but got Unknown
			IEnumerable<string> pluginGUIDs2 = pluginGUIDs;
			IEnumerable<PluginInfo> enumerable = _reloadablePlugins.Values.Where((PluginInfo p) => pluginGUIDs2.Contains(p.Metadata.GUID));
			_bepinexChainloader.ModifyUnloadOrder(enumerable);
			if (!enumerable.Any())
			{
				StringBuilder stringBuilder = new StringBuilder().Append("Nothing to unload.");
				if (pluginGUIDs2.Any())
				{
					StringBuilder stringBuilder2 = stringBuilder;
					StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(40, 1, stringBuilder2);
					handler.AppendLiteral(" [");
					handler.AppendFormatted(string.Join(", ", pluginGUIDs2));
					handler.AppendLiteral("] requested, but not currently loaded.");
					stringBuilder2.Append(ref handler);
				}
				Log.LogDebug((object)stringBuilder.ToString());
				return Array.Empty<string>();
			}
			List<string> list = new List<string>();
			foreach (PluginInfo item in enumerable)
			{
				string gUID = item.Metadata.GUID;
				_dependencyGraph.RemoveVertex(gUID);
				_bepinexChainloader.UnloadPlugin(item);
				if (_reloadablePlugins.Remove(gUID))
				{
					list.Add(gUID);
				}
			}
			ManualLogSource log = Log;
			bool flag = default(bool);
			BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(40, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Unloaded plugin(s): ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(string.Join(", ", pluginGUIDs2));
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". \nResulting graph:\n");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<DependencyGraph>(_dependencyGraph);
			}
			log.LogDebug(val);
			return list;
		}

		private IList<PluginInfo> LoadGivenAndDependencies(IEnumerable<string> pluginGUIDs)
		{
			IEnumerable<PluginInfo> pluginsToLoad = DiscoverPluginsToLoad(pluginGUIDs);
			return LoadGiven(pluginsToLoad);
		}

		private IList<PluginInfo> LoadGiven(IEnumerable<PluginInfo> pluginsToLoad)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			bool flag = default(bool);
			if (!pluginsToLoad.Any())
			{
				ManualLogSource log = Log;
				BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(33, 0, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Did not find any plugins to load.");
				}
				log.LogDebug(val);
				return new List<PluginInfo>();
			}
			PrepareForLoad();
			_bepinexChainloader.ModifyLoadOrder(pluginsToLoad);
			IList<PluginInfo> list = _bepinexChainloader.LoadPlugins(pluginsToLoad.ToList());
			ProcessFreshlyLoadedPlugins(list);
			IEnumerable<string> enumerable = list.Select((PluginInfo p) => p.Metadata.GUID);
			if (enumerable.Any())
			{
				ManualLogSource log2 = Log;
				BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(38, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Loaded plugin(s): ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(string.Join(", ", enumerable));
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". \nResulting graph:\n");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<DependencyGraph>(_dependencyGraph);
				}
				log2.LogDebug(val);
			}
			else
			{
				ManualLogSource log3 = Log;
				BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(33, 0, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Was not able to load any plugins.");
				}
				log3.LogDebug(val);
			}
			return list;
		}

		private void PrepareForLoad()
		{
			Dictionary<string, PluginInfo> plugins = ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins;
			plugins.ToList().ForEach(delegate(KeyValuePair<string, PluginInfo> x)
			{
				((BaseChainloader<BasePlugin>)(object)_bepinexChainloader).Plugins[x.Key] = x.Value;
			});
		}

		private void ProcessFreshlyLoadedPlugins(IEnumerable<PluginInfo> loadedPlugins)
		{
			foreach (PluginInfo loadedPlugin in loadedPlugins)
			{
				_reloadablePlugins.Add(loadedPlugin.Metadata.GUID, loadedPlugin);
				_lastWriteTimes[loadedPlugin.Metadata.GUID] = File.GetLastWriteTime(loadedPlugin.Location);
				HashSet<string> directDependencyIds = loadedPlugin.Dependencies.Select((BepInDependency d) => d.DependencyGUID).ToHashSet();
				_dependencyGraph.AddVertex(loadedPlugin.Metadata.GUID, directDependencyIds);
			}
		}

		private IEnumerable<PluginInfo> DiscoverPluginsToLoad(IEnumerable<string> targetedPluginGUIDs)
		{
			DependencyGraph dependencyGraph = new DependencyGraph();
			IList<PluginInfo> list = _bepinexChainloader.DiscoverPluginsFrom(_config.PluginsPath);
			foreach (PluginInfo item in list)
			{
				HashSet<string> directDependencyIds = item.Dependencies.Select((BepInDependency d) => d.DependencyGUID).ToHashSet();
				dependencyGraph.AddVertex(item.Metadata.GUID, directDependencyIds);
			}
			ISet<string> pluginGuidsToLoad = dependencyGraph.FindAllVertexesToLoad(targetedPluginGUIDs.ToHashSet());
			return from p in list.Where(IsNotPluginLoaded)
				where pluginGuidsToLoad.Contains(p.Metadata.GUID)
				select p;
		}

		private bool IsPluginDirty(PluginInfo plugin)
		{
			if (!File.Exists(plugin.Location))
			{
				return true;
			}
			if (_lastWriteTimes.TryGetValue(plugin.Metadata.GUID, out var value))
			{
				try
				{
					return value < File.GetLastWriteTime(plugin.Location);
				}
				catch (Exception ex)
				{
					Log.LogWarning((object)ex);
				}
			}
			return true;
		}

		private bool IsNotPluginLoaded(PluginInfo plugin)
		{
			return !_reloadablePlugins.ContainsKey(plugin.Metadata.GUID);
		}

		public IList<PluginInfo> ReloadChanges()
		{
			IEnumerable<string> pluginGUIDs = from p in _reloadablePlugins.Values.Where(IsPluginDirty)
				select p.Metadata.GUID;
			IEnumerable<string> unloadedPluginGuids = UnloadGivenAndDependents(pluginGUIDs);
			IEnumerable<PluginInfo> enumerable = _bepinexChainloader.DiscoverPluginsFrom(_config.PluginsPath).Where(IsNotPluginLoaded);
			if (!enumerable.Any())
			{
				OnReloadedPlugins(new List<PluginInfo>(), unloadedPluginGuids);
				return new List<PluginInfo>();
			}
			IList<PluginInfo> list = LoadGiven(enumerable);
			OnReloadedPlugins(list, unloadedPluginGuids);
			return list;
		}
	}
}
namespace Bloodpebble.ReloadExecution.LoadingStrategyIslands
{
	[Obsolete("Will be removed once SilverBullet is stable")]
	internal class IslandsPluginLoader : BasePluginLoader, IPluginLoader, ITriggersPluginLoaderEvents
	{
		private readonly Dictionary<string, AssemblyLoadContext> _pluginToContextMap = new Dictionary<string, AssemblyLoadContext>();

		private readonly Dictionary<string, PluginInfo> _loadedPlugins = new Dictionary<string, PluginInfo>();

		private ModifiedBepInExChainloader _bepinexChainloader = new ModifiedBepInExChainloader();

		private PluginLoaderConfig _config;

		public IslandsPluginLoader(PluginLoaderConfig config)
		{
			_config = config;
		}

		public IList<PluginInfo> ReloadAll()
		{
			IEnumerable<string> unloadedPluginGuids = UnloadAll();
			IList<PluginInfo> list = LoadPlugins(_config.PluginsPath);
			OnReloadedPlugins(list, unloadedPluginGuids);
			return list;
		}

		public IList<PluginInfo> ReloadGiven(IEnumerable<string> pluginGUIDs)
		{
			if (pluginGUIDs.Count() == 1)
			{
				List<PluginInfo> list = new List<PluginInfo>();
				if (TryReloadPlugin(pluginGUIDs.First(), out PluginInfo freshPlugin))
				{
					list.Add(freshPlugin);
				}
				return list;
			}
			return ReloadAll();
		}

		private IList<PluginInfo> LoadPlugins(string pluginsPath)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			_bepinexChainloader = new ModifiedBepInExChainloader();
			List<PluginInfo> plugins = _bepinexChainloader.DiscoverAndSortPlugins(pluginsPath);
			Dictionary<string, List<string>> neighborhoods = BuildNeighborhoods(plugins);
			List<List<PluginInfo>> list = FindPluginGroups(plugins, neighborhoods);
			List<PluginInfo> list2 = new List<PluginInfo>();
			bool flag = default(bool);
			foreach (List<PluginInfo> item in list)
			{
				try
				{
					List<PluginInfo> collection = LoadGroup(item);
					list2.AddRange(collection);
				}
				catch (Exception ex)
				{
					ManualLogSource logger = BloodpebblePlugin.Logger;
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(63, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to load a plugin group. Halting further loading. Error: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
					}
					logger.LogError(val);
					UnloadAll();
					return new List<PluginInfo>();
				}
			}
			return list2;
		}

		private List<PluginInfo> LoadGroup(List<PluginInfo> groupPlugins)
		{
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			List<PluginInfo> list = new List<PluginInfo>();
			IEnumerable<PluginInfo> enumerable = _bepinexChainloader.SortPluginList(groupPlugins);
			AssemblyLoadContext assemblyLoadContext = new AssemblyLoadContext($"BloodpebbleGroup-{Guid.NewGuid()}", isCollectible: true);
			Dictionary<string, Assembly> loadedAssembliesInContext = new Dictionary<string, Assembly>();
			assemblyLoadContext.Resolving += (AssemblyLoadContext context, AssemblyName assemblyName) => loadedAssembliesInContext.TryGetValue(assemblyName.Name, out Assembly value) ? value : null;
			foreach (PluginInfo item in enumerable)
			{
				Assembly assembly;
				PluginInfo val = _bepinexChainloader.LoadPlugin(item, assemblyLoadContext, out assembly);
				_loadedPlugins[val.Metadata.GUID] = val;
				_pluginToContextMap[val.Metadata.GUID] = assemblyLoadContext;
				loadedAssembliesInContext[assembly.GetName().Name] = assembly;
				list.Add(val);
			}
			ManualLogSource logger = BloodpebblePlugin.Logger;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(47, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Successfully loaded plugin group with plugins: ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(string.Join(", ", list.Select((PluginInfo p) => p.Metadata.Name)));
			}
			logger.LogInfo(val2);
			return list;
		}

		public IEnumerable<string> UnloadAll()
		{
			List<string> result = _loadedPlugins.Keys.ToList();
			foreach (PluginInfo value in _loadedPlugins.Values)
			{
				try
				{
					object instance = value.Instance;
					object obj = ((instance is BasePlugin) ? instance : null);
					if (obj != null)
					{
						((BasePlugin)obj).Unload();
					}
				}
				catch (Exception ex)
				{
					BloodpebblePlugin.Logger.LogError((object)ex);
				}
			}
			List<AssemblyLoadContext> list = _pluginToContextMap.Values.Distinct().ToList();
			if (!list.Any())
			{
				return Array.Empty<string>();
			}
			foreach (AssemblyLoadContext item in list)
			{
				item.Unload();
			}
			_pluginToContextMap.Clear();
			_loadedPlugins.Clear();
			((BaseChainloader<BasePlugin>)(object)_bepinexChainloader).Plugins.Clear();
			GC.Collect();
			GC.WaitForPendingFinalizers();
			BloodpebblePlugin.Logger.LogInfo((object)"All reloadable plugins have been unloaded.");
			return result;
		}

		private bool TryReloadPlugin(string guid, [NotNullWhen(true)] out PluginInfo? freshPlugin)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Expected O, but got Unknown
			string guid2 = guid;
			freshPlugin = null;
			bool flag = default(bool);
			if (!_pluginToContextMap.TryGetValue(guid2, out AssemblyLoadContext contextToUnload))
			{
				ManualLogSource logger = BloodpebblePlugin.Logger;
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(59, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Cannot reload plugin with GUID '");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(guid2);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' because it is not loaded.");
				}
				logger.LogError(val);
				return false;
			}
			List<PluginInfo> list = _loadedPlugins.Values.Where((PluginInfo p) => _pluginToContextMap.ContainsKey(p.Metadata.GUID) && _pluginToContextMap[p.Metadata.GUID] == contextToUnload).ToList();
			List<string> list2 = list.Select((PluginInfo p) => p.Metadata.GUID).ToList();
			List<string> list3 = list.Select((PluginInfo p) => p.Location).ToList();
			ManualLogSource logger2 = BloodpebblePlugin.Logger;
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(44, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Reload request for '");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(guid2);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("'. Unloading its group: ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(string.Join(", ", list2));
			}
			logger2.LogInfo(val2);
			foreach (PluginInfo item in list)
			{
				try
				{
					object instance = item.Instance;
					object obj = ((instance is BasePlugin) ? instance : null);
					if (obj != null)
					{
						((BasePlugin)obj).Unload();
					}
				}
				catch (Exception ex)
				{
					BloodpebblePlugin.Logger.LogError((object)ex);
				}
			}
			contextToUnload.Unload();
			foreach (string item2 in list2)
			{
				_pluginToContextMap.Remove(item2);
				_loadedPlugins.Remove(item2);
				((BaseChainloader<BasePlugin>)(object)_bepinexChainloader).Plugins.Remove(item2);
			}
			GC.Collect();
			GC.WaitForPendingFinalizers();
			string text = Path.Combine(Path.GetTempPath(), $"BloodpebbleReload-{Guid.NewGuid()}");
			Directory.CreateDirectory(text);
			try
			{
				foreach (string item3 in list3)
				{
					if (File.Exists(item3))
					{
						File.Copy(item3, Path.Combine(text, Path.GetFileName(item3)));
					}
				}
				ModifiedBepInExChainloader modifiedBepInExChainloader = new ModifiedBepInExChainloader();
				List<PluginInfo> groupPlugins = modifiedBepInExChainloader.DiscoverAndSortPlugins(text);
				ManualLogSource logger3 = BloodpebblePlugin.Logger;
				val2 = new BepInExInfoLogInterpolatedStringHandler(49, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Reloading group for '");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(guid2);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' from temporary location...");
				}
				logger3.LogInfo(val2);
				List<PluginInfo> source = LoadGroup(groupPlugins);
				freshPlugin = ((IEnumerable<PluginInfo>)source).FirstOrDefault((Func<PluginInfo, bool>)((PluginInfo p) => p.Metadata.GUID == guid2));
				return freshPlugin != null;
			}
			finally
			{
				if (Directory.Exists(text))
				{
					Directory.Delete(text, recursive: true);
				}
			}
		}

		public IList<PluginInfo> ReloadChanges()
		{
			IEnumerable<string> unloadedPluginGuids = UnloadAll();
			IList<PluginInfo> list = LoadPlugins(_config.PluginsPath);
			OnReloadedPlugins(list, unloadedPluginGuids);
			return list;
		}

		private Dictionary<string, List<string>> BuildNeighborhoods(IEnumerable<PluginInfo> plugins)
		{
			Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>();
			HashSet<string> hashSet = new HashSet<string>(plugins.Select((PluginInfo p) => p.Metadata.GUID));
			foreach (PluginInfo plugin in plugins)
			{
				if (!dictionary.ContainsKey(plugin.Metadata.GUID))
				{
					dictionary[plugin.Metadata.GUID] = new List<string>();
				}
				foreach (BepInDependency dependency in plugin.Dependencies)
				{
					if (hashSet.Contains(dependency.DependencyGUID))
					{
						dictionary[plugin.Metadata.GUID].Add(dependency.DependencyGUID);
						if (!dictionary.ContainsKey(dependency.DependencyGUID))
						{
							dictionary[dependency.DependencyGUID] = new List<string>();
						}
						dictionary[dependency.DependencyGUID].Add(plugin.Metadata.GUID);
					}
				}
			}
			return dictionary;
		}

		private List<List<PluginInfo>> FindPluginGroups(IEnumerable<PluginInfo> plugins, Dictionary<string, List<string>> neighborhoods)
		{
			List<List<PluginInfo>> list = new List<List<PluginInfo>>();
			HashSet<string> hashSet = new HashSet<string>();
			Dictionary<string, PluginInfo> pluginDict = plugins.ToDictionary((PluginInfo p) => p.Metadata.GUID);
			foreach (PluginInfo plugin in plugins)
			{
				if (hashSet.Contains(plugin.Metadata.GUID))
				{
					continue;
				}
				HashSet<string> hashSet2 = new HashSet<string>();
				Stack<string> stack = new Stack<string>();
				stack.Push(plugin.Metadata.GUID);
				hashSet.Add(plugin.Metadata.GUID);
				while (stack.Count > 0)
				{
					string text = stack.Pop();
					hashSet2.Add(text);
					if (!neighborhoods.TryGetValue(text, out List<string> value))
					{
						continue;
					}
					foreach (string item2 in value)
					{
						if (!hashSet.Contains(item2))
						{
							hashSet.Add(item2);
							stack.Push(item2);
						}
					}
				}
				List<PluginInfo> item = hashSet2.Select((string guid) => pluginDict[guid]).ToList();
				list.Add(item);
			}
			return list;
		}
	}
	internal class ModifiedBepInExChainloader : IL2CPPChainloader
	{
		private readonly BaseAssemblyResolver _assemblyResolver;

		public ModifiedBepInExChainloader()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			_assemblyResolver = (BaseAssemblyResolver)new DefaultAssemblyResolver();
			_assemblyResolver.AddSearchDirectory(Paths.ManagedPath);
			_assemblyResolver.AddSearchDirectory(Paths.BepInExAssemblyDirectory);
			_assemblyResolver.AddSearchDirectory(Path.Combine(Paths.BepInExRootPath, "interop"));
		}

		public List<PluginInfo> DiscoverAndSortPlugins(string pluginsPath)
		{
			List<PluginInfo> list = ((BaseChainloader<BasePlugin>)this).DiscoverPluginsFrom(pluginsPath, "chainloader").ToList();
			if (list.Any())
			{
				_assemblyResolver.AddSearchDirectory(pluginsPath);
			}
			IList<PluginInfo> source = ((BaseChainloader<BasePlugin>)(object)this).ModifyLoadOrder((IList<PluginInfo>)list);
			return source.ToList();
		}

		public IEnumerable<PluginInfo> SortPluginList(IEnumerable<PluginInfo> plugins)
		{
			return ((BaseChainloader<BasePlugin>)(object)this).ModifyLoadOrder((IList<PluginInfo>)plugins.ToList());
		}

		public PluginInfo LoadPlugin(PluginInfo plugin, AssemblyLoadContext context, out Assembly assembly)
		{
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: 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)
			//IL_0148: Expected O, but got Unknown
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			bool flag = default(bool);
			try
			{
				ManualLogSource logger = BloodpebblePlugin.Logger;
				LogLevel val = (LogLevel)16;
				LogLevel val2 = val;
				BepInExLogInterpolatedStringHandler val3 = new BepInExLogInterpolatedStringHandler(10, 1, val, ref flag);
				if (flag)
				{
					val3.AppendLiteral("Loading [");
					val3.AppendFormatted<PluginInfo>(plugin);
					val3.AppendLiteral("]");
				}
				logger.Log(val2, val3);
				AssemblyDefinition val4 = AssemblyDefinition.ReadAssembly(plugin.Location, new ReaderParameters
				{
					AssemblyResolver = (IAssemblyResolver)(object)_assemblyResolver
				});
				try
				{
					using MemoryStream memoryStream = new MemoryStream();
					val4.Write((Stream)memoryStream);
					memoryStream.Seek(0L, SeekOrigin.Begin);
					assembly = context.LoadFromStream(memoryStream);
					BloodpebblePluginInfo bloodpebblePluginInfo = new BloodpebblePluginInfo(plugin.Metadata, plugin.Processes, plugin.Dependencies, plugin.Incompatibilities, plugin.Location, plugin.Instance, plugin.TypeName);
					((BaseChainloader<BasePlugin>)this).Plugins[plugin.Metadata.GUID] = (PluginInfo)(object)bloodpebblePluginInfo;
					TryRunModuleCtor(plugin, assembly);
					BasePlugin instance = ((BaseChainloader<BasePlugin>)(object)this).LoadPlugin(plugin, assembly);
					bloodpebblePluginInfo.SetInstance(instance);
					return (PluginInfo)(object)bloodpebblePluginInfo;
				}
				finally
				{
					((IDisposable)val4)?.Dispose();
				}
			}
			catch (Exception ex)
			{
				((BaseChainloader<BasePlugin>)this).Plugins.Remove(plugin.Metadata.GUID);
				ManualLogSource logger2 = BloodpebblePlugin.Logger;
				LogLevel val5 = (LogLevel)2;
				LogLevel val6 = val5;
				BepInExLogInterpolatedStringHandler val3 = new BepInExLogInterpolatedStringHandler(18, 2, val5, ref flag);
				if (flag)
				{
					val3.AppendLiteral("Error loading [");
					val3.AppendFormatted<PluginInfo>(plugin);
					val3.AppendLiteral("]: ");
					val3.AppendFormatted<string>((ex is ReflectionTypeLoadException ex2) ? TypeLoader.TypeLoadExceptionToString(ex2) : ex.ToString());
				}
				logger2.Log(val6, val3);
				throw;
			}
		}

		public void RemoveSearchDirectory(string pluginsPath)
		{
			_assemblyResolver.RemoveSearchDirectory(pluginsPath);
		}

		protected static void TryRunModuleCtor(PluginInfo plugin, Assembly assembly)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				RuntimeHelpers.RunModuleConstructor(assembly.GetType(plugin.TypeName).Module.ModuleHandle);
			}
			catch (Exception ex)
			{
				ManualLogSource logger = BloodpebblePlugin.Logger;
				LogLevel val = (LogLevel)4;
				LogLevel val2 = val;
				bool flag = default(bool);
				BepInExLogInterpolatedStringHandler val3 = new BepInExLogInterpolatedStringHandler(40, 3, val, ref flag);
				if (flag)
				{
					val3.AppendLiteral("Couldn't run Module constructor for ");
					val3.AppendFormatted<string>(assembly.FullName);
					val3.AppendLiteral("::");
					val3.AppendFormatted<string>(plugin.TypeName);
					val3.AppendLiteral(": ");
					val3.AppendFormatted<Exception>(ex);
				}
				logger.Log(val2, val3);
			}
		}
	}
}
namespace Bloodpebble.ReloadExecution.LoadingStategyBasic
{
	[Obsolete("Will be removed once SilverBullet is stable")]
	internal class BasicPluginLoader : BasePluginLoader, IPluginLoader, ITriggersPluginLoaderEvents
	{
		private IList<PluginInfo> _plugins = new List<PluginInfo>();

		private ModifiedBepInExChainloader _bepinexChainloader = new ModifiedBepInExChainloader();

		private PluginLoaderConfig _config;

		public BasicPluginLoader(PluginLoaderConfig config)
		{
			_config = config;
		}

		public IList<PluginInfo> ReloadAll()
		{
			IEnumerable<string> unloadedPluginGuids = UnloadAll();
			IList<PluginInfo> list = LoadAll();
			OnReloadedPlugins(list, unloadedPluginGuids);
			return list;
		}

		public IList<PluginInfo> ReloadGiven(IEnumerable<string> pluginGUIDs)
		{
			IEnumerable<string> unloadedPluginGuids = UnloadAll();
			IList<PluginInfo> list = LoadAll();
			OnReloadedPlugins(list, unloadedPluginGuids);
			return list;
		}

		public IEnumerable<string> UnloadAll()
		{
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			List<string> result = _plugins.Select((PluginInfo p) => p.Metadata.GUID).ToList();
			bool flag = default(bool);
			for (int num = _plugins.Count - 1; num >= 0; num--)
			{
				PluginInfo val = _plugins[num];
				BasePlugin val2 = (BasePlugin)_plugins[num].Instance;
				AssemblyName name = ((object)val2).GetType().Assembly.GetName();
				string text = $"{name.Name} {name.Version}";
				try
				{
					if (!val2.Unload())
					{
						ManualLogSource logger = BloodpebblePlugin.Logger;
						BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(63, 1, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Plugin ")