Decompiled source of Bloodpebble v1.2.1

Bloodpebble.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Loader;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Bloodpebble.API;
using Bloodpebble.Extensions;
using Bloodpebble.Features;
using Bloodpebble.Hooks;
using Bloodpebble.Reloading;
using Bloodpebble.Utils;
using HarmonyLib;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using ProjectM;
using ProjectM.Network;
using ScarletRCON.Shared;
using SemanticVersioning;
using Stunlock.Core;
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.2.1.0")]
[assembly: AssemblyInformationalVersion("1.2.1+58eee0326f052d9bb7c3e9a79e630d093d77090f")]
[assembly: AssemblyProduct("Bloodpebble")]
[assembly: AssemblyTitle("Bloodpebble")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.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
{
	[BepInPlugin("Bloodpebble", "Bloodpebble", "1.2.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class BloodpebblePlugin : BasePlugin
	{
		private ConfigEntry<string> _reloadCommand;

		private ConfigEntry<string> _reloadPluginsFolder;

		private ConfigEntry<bool> _enableAutoReload;

		private ConfigEntry<float> _autoReloadDelaySeconds;

		public static ManualLogSource Logger { get; private set; }

		internal static BloodpebblePlugin Instance { get; private set; }

		public BloodpebblePlugin()
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			Logger = ((BasePlugin)this).Log;
			Instance = this;
			_reloadCommand = ((BasePlugin)this).Config.Bind<string>("General", "ReloadCommand", "!reload", "Server chat command to reload plugins. User must first be AdminAuth'd (accomplished via console command).");
			_reloadPluginsFolder = ((BasePlugin)this).Config.Bind<string>("General", "ReloadablePluginsFolder", "BepInEx/BloodpebblePlugins", "The folder to (re)load plugins from, relative to the game directory.");
			_enableAutoReload = ((BasePlugin)this).Config.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 = ((BasePlugin)this).Config.Bind<float>("AutoReload", "AutoReloadDelaySeconds", 2f, new ConfigDescription("Delay in seconds before auto reloading.", (AcceptableValueBase)null, Array.Empty<object>()));
		}

		public override void Load()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			if (VWorld.IsServer)
			{
				Chat.Initialize();
			}
			OnInitialize.Initialize();
			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.2.1");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded.");
			}
			logger.LogInfo(val);
			Reload.Initialize(_reloadCommand.Value, _reloadPluginsFolder.Value, _enableAutoReload.Value, _autoReloadDelaySeconds.Value);
			RconCommandRegistrar.RegisterAll();
		}

		public override bool Unload()
		{
			RconCommandRegistrar.UnregisterAssembly();
			if (VWorld.IsServer)
			{
				Chat.Uninitialize();
			}
			OnInitialize.Uninitialize();
			return true;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "Bloodpebble";

		public const string PLUGIN_NAME = "Bloodpebble";

		public const string PLUGIN_VERSION = "1.2.1";
	}
}
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.Reloading
{
	internal class BloodpebbleChainloader
	{
		private IList<PluginInfo> _plugins = new List<PluginInfo>();

		private ModifiedBepInExChainloader _bepinexChainloader = new ModifiedBepInExChainloader();

		public IList<PluginInfo> LoadPlugins(string pluginsPath)
		{
			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;
			});
			return _plugins = _bepinexChainloader.LoadPlugins(pluginsPath);
		}

		public void UnloadPlugins()
		{
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			bool flag = default(bool);
			for (int num = _plugins.Count - 1; num >= 0; num--)
			{
				PluginInfo pluginInfo = _plugins[num];
				BasePlugin val = (BasePlugin)_plugins[num].Instance;
				AssemblyName name = ((object)val).GetType().Assembly.GetName();
				string text = $"{name.Name} {name.Version}";
				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(24, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Error unloading plugin ");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(text);
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(":");
					}
					logger2.LogError(val3);
					BloodpebblePlugin.Logger.LogError((object)ex);
				}
				((BaseChainloader<BasePlugin>)(object)_bepinexChainloader).Plugins.Remove(pluginInfo.Metadata.GUID);
				_plugins.RemoveAt(num);
			}
			_bepinexChainloader.UnloadAssemblies();
		}
	}
	internal class ModifiedBepInExChainloader : IL2CPPChainloader
	{
		private BaseAssemblyResolver _assemblyResolver;

		private AssemblyLoadContext _assemblyLoadContext;

		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"));
			_assemblyLoadContext = CreateNewAssemblyLoadContext();
		}

		public void UnloadAssemblies()
		{
			_assemblyLoadContext.Unload();
			_assemblyLoadContext = CreateNewAssemblyLoadContext();
		}

		private AssemblyLoadContext CreateNewAssemblyLoadContext()
		{
			return new AssemblyLoadContext("BloodpebbleContext", isCollectible: true);
		}

		public IList<PluginInfo> LoadPlugins(IList<PluginInfo> plugins)
		{
			//IL_043e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0440: Unknown result type (might be due to invalid IL or missing references)
			//IL_0442: Unknown result type (might be due to invalid IL or missing references)
			//IL_0447: Unknown result type (might be due to invalid IL or missing references)
			//IL_044b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0452: Expected O, but got Unknown
			//IL_04a1: 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_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Expected O, but got Unknown
			IList<PluginInfo> list = ((BaseChainloader<BasePlugin>)(object)this).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> list2 = new List<PluginInfo>();
			bool flag3 = default(bool);
			foreach (PluginInfo item in list)
			{
				bool flag = false;
				List<BepInDependency> list3 = 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))
						{
							list3.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 (list3.Count != 0)
				{
					string text2 = $"Could not load [{item}] because it has missing dependencies: {string.Join(", ", list3.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))
					{
						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 = (dictionary2[item.Location] = _assemblyLoadContext.LoadFromStream(memoryStream));
						}
						finally
						{
							((IDisposable)val4)?.Dispose();
						}
					}
					PluginInfo pluginInfo = new PluginInfo
					{
						Metadata = item.Metadata,
						Processes = item.Processes,
						Dependencies = item.Dependencies,
						Incompatibilities = item.Incompatibilities,
						Location = item.Location,
						Instance = item.Instance,
						TypeName = item.TypeName
					};
					((BaseChainloader<BasePlugin>)this).Plugins[item.Metadata.GUID] = (PluginInfo)(object)pluginInfo;
					TryRunModuleCtor(item, value3);
					pluginInfo.Instance = ((BaseChainloader<BasePlugin>)(object)this).LoadPlugin(item, value3);
					list2.Add(pluginInfo);
				}
				catch (Exception ex)
				{
					hashSet.Add(item.Metadata.GUID);
					((BaseChainloader<BasePlugin>)this).Plugins.Remove(item.Metadata.GUID);
					ManualLogSource logger2 = BloodpebblePlugin.Logger;
					LogLevel val5 = (LogLevel)2;
					LogLevel val6 = val5;
					BepInExLogInterpolatedStringHandler val3 = new BepInExLogInterpolatedStringHandler(18, 2, val5, 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());
					}
					logger2.Log(val6, val3);
				}
			}
			return list2;
			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(((BaseChainloader<BasePlugin>)this).DiscoverPluginsFrom(text, "chainloader"));
				_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);
			}
		}
	}
	internal class PluginInfo : 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; }

		internal Version TargettedBepInExVersion { get; set; }
	}
}
namespace Bloodpebble.Hooks
{
	public static class Chat
	{
		public delegate void ChatEventHandler(VChatEvent e);

		private static Harmony? _harmony;

		public static event ChatEventHandler? OnChatMessage;

		public static void Initialize()
		{
			if (_harmony != null)
			{
				throw new Exception("Detour already initialized. You don't need to call this. The Bloodpebble plugin will do it for you.");
			}
			_harmony = Harmony.CreateAndPatchAll(typeof(Chat), "Bloodpebble");
		}

		public static void Uninitialize()
		{
			if (_harmony == null)
			{
				throw new Exception("Detour wasn't initialized. Are you trying to unload Bloodpebble twice?");
			}
			_harmony.UnpatchSelf();
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ChatMessageSystem), "OnUpdate")]
		public static void OnUpdatePrefix(ChatMessageSystem __instance)
		{
			//IL_0002: 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_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			EntityQuery _query_661171423_ = __instance.__query_661171423_0;
			Enumerator<Entity> enumerator = ((EntityQuery)(ref _query_661171423_)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)).GetEnumerator();
			bool flag = default(bool);
			while (enumerator.MoveNext())
			{
				Entity current = enumerator.Current;
				EntityManager entityManager = VWorld.Server.EntityManager;
				ChatMessageEvent componentData = ((EntityManager)(ref entityManager)).GetComponentData<ChatMessageEvent>(current);
				entityManager = VWorld.Server.EntityManager;
				FromCharacter componentData2 = ((EntityManager)(ref entityManager)).GetComponentData<FromCharacter>(current);
				VChatEvent vChatEvent = new VChatEvent(componentData2.User, componentData2.Character, ((object)(FixedString512Bytes)(ref componentData.MessageText)).ToString(), componentData.MessageType);
				ManualLogSource logger = BloodpebblePlugin.Logger;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(12, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Chat] [");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<ChatMessageType>(vChatEvent.Type);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<FixedString64Bytes>(vChatEvent.User.CharacterName);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(vChatEvent.Message);
				}
				logger.LogInfo(val);
				try
				{
					Chat.OnChatMessage?.Invoke(vChatEvent);
					if (vChatEvent.Cancelled)
					{
						entityManager = VWorld.Server.EntityManager;
						((EntityManager)(ref entityManager)).DestroyEntity(current);
					}
				}
				catch (Exception ex)
				{
					BloodpebblePlugin.Logger.LogError((object)"Error dispatching chat event:");
					BloodpebblePlugin.Logger.LogError((object)ex);
				}
			}
		}
	}
	public class VChatEvent
	{
		public Entity SenderUserEntity { get; }

		public Entity SenderCharacterEntity { get; }

		public string Message { get; }

		public ChatMessageType Type { get; }

		public bool Cancelled { get; private set; } = false;


		public User User
		{
			get
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				EntityManager entityManager = VWorld.Server.EntityManager;
				return ((EntityManager)(ref entityManager)).GetComponentData<User>(SenderUserEntity);
			}
		}

		internal VChatEvent(Entity userEntity, Entity characterEntity, string message, ChatMessageType type)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			SenderUserEntity = userEntity;
			SenderCharacterEntity = characterEntity;
			Message = message;
			Type = type;
		}

		public void Cancel()
		{
			Cancelled = true;
		}
	}
	internal static class OnInitialize
	{
		private static class ServerDetours
		{
			[HarmonyPatch(typeof(GameBootstrap), "Start")]
			[HarmonyPostfix]
			public static void Initialize()
			{
				InvokePlugins();
			}
		}

		private static class ClientDetours
		{
			[HarmonyPatch(typeof(WorldBootstrapUtilities), "AddSystemsToWorld")]
			[HarmonyPostfix]
			public static void Initialize()
			{
				InvokePlugins();
			}
		}

		private static Harmony _harmony;

		public static bool HasInitialized { get; private set; }

		public static void Initialize()
		{
			_harmony = Harmony.CreateAndPatchAll(VWorld.IsServer ? typeof(ServerDetours) : typeof(ClientDetours), (string)null);
		}

		public static void Uninitialize()
		{
			_harmony.UnpatchSelf();
		}

		private static void InvokePlugins()
		{
			BloodpebblePlugin.Logger.LogInfo((object)"Game has bootstrapped. Worlds and systems now exist.");
			if (HasInitialized)
			{
				return;
			}
			HasInitialized = true;
			foreach (var (text2, val2) in ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins)
			{
				if (val2.Instance is IRunOnInitialized runOnInitialized)
				{
					runOnInitialized.OnGameInitialized();
				}
			}
		}
	}
}
namespace Bloodpebble.Features
{
	public static class Reload
	{
		private class ReloadBehaviour : MonoBehaviour
		{
			private void Update()
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				if (Input.GetKeyDown(_keybinding))
				{
					BloodpebblePlugin.Logger.LogInfo((object)"Reloading client plugins...");
					ReloadPlugins();
					_isPendingAutoReload = false;
				}
				else if (_isPendingAutoReload)
				{
					autoReloadTimer -= Time.unscaledDeltaTime;
					if (autoReloadTimer <= 0f)
					{
						_isPendingAutoReload = false;
						BloodpebblePlugin.Logger.LogInfo((object)"Automatically reloading plugins...");
						ReloadPlugins();
					}
				}
			}
		}

		[RconCommandCategory("Server Administration")]
		public static class RconCommands
		{
			[RconCommand("reloadplugins", "Reloads plugins in the BloodpebblePlugins folder", null)]
			public static string Reload()
			{
				BloodpebblePlugin.Logger.LogInfo((object)"Reloading plugins (triggered by RCON)...");
				ReloadPlugins();
				return "Reloaded Bloodpebble plugins";
			}
		}

		private static string _reloadCommand;

		private static string _reloadPluginsFolder;

		private static float _autoReloadDelaySeconds;

		private static ReloadBehaviour _reloadBehavior;

		private static FileSystemWatcher _fileSystemWatcher;

		private static KeyCode _keybinding = (KeyCode)287;

		private static bool _isPendingAutoReload = false;

		private static float autoReloadTimer;

		private static BloodpebbleChainloader _chainloader = new BloodpebbleChainloader();

		internal static void Initialize(string reloadCommand, string reloadPluginsFolder, bool enableAutoReload, float autoReloadDelaySeconds)
		{
			_reloadCommand = reloadCommand;
			_reloadPluginsFolder = reloadPluginsFolder;
			_autoReloadDelaySeconds = autoReloadDelaySeconds;
			Chat.OnChatMessage += HandleChatMessage;
			_reloadBehavior = ((BasePlugin)BloodpebblePlugin.Instance).AddComponent<ReloadBehaviour>();
			LoadPlugins();
			if (enableAutoReload)
			{
				StartFileSystemWatcher();
			}
		}

		internal static void Uninitialize()
		{
			_fileSystemWatcher = null;
			Chat.OnChatMessage -= HandleChatMessage;
			if ((Object)(object)_reloadBehavior != (Object)null)
			{
				Object.Destroy((Object)(object)_reloadBehavior);
			}
		}

		private static void HandleChatMessage(VChatEvent ev)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			if (ev.Message != _reloadCommand || !ev.User.IsAdmin)
			{
				return;
			}
			ev.Cancel();
			UnloadPlugins();
			IList<PluginInfo> list = LoadPlugins();
			if (list.Count > 0)
			{
				IEnumerable<string> values = list.Select((PluginInfo plugin) => plugin.Metadata.Name);
				ev.User.SendSystemMessage("Reloaded " + string.Join(", ", values) + ". See console for details.");
			}
			else
			{
				ev.User.SendSystemMessage("Did not reload any plugins because no reloadable plugins were found. Check the console for more details.");
			}
		}

		private static IList<PluginInfo> LoadPlugins()
		{
			if (!Directory.Exists(_reloadPluginsFolder))
			{
				Directory.CreateDirectory(_reloadPluginsFolder);
			}
			return _chainloader.LoadPlugins(_reloadPluginsFolder);
		}

		private static void UnloadPlugins()
		{
			_chainloader.UnloadPlugins();
		}

		private static void ReloadPlugins()
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			UnloadPlugins();
			IList<PluginInfo> list = LoadPlugins();
			bool flag = default(bool);
			if (list.Count > 0)
			{
				IEnumerable<string> values = list.Select((PluginInfo plugin) => plugin.Metadata.Name);
				ManualLogSource logger = BloodpebblePlugin.Logger;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(10, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Reloaded ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(string.Join(", ", values));
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
				}
				logger.LogInfo(val);
			}
			else
			{
				ManualLogSource logger2 = BloodpebblePlugin.Logger;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(68, 0, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Did not reload any plugins because no reloadable plugins were found.");
				}
				logger2.LogInfo(val);
			}
		}

		private static void StartFileSystemWatcher()
		{
			_fileSystemWatcher = new FileSystemWatcher(_reloadPluginsFolder);
			_fileSystemWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite;
			_fileSystemWatcher.Filter = "*.dll";
			_fileSystemWatcher.Changed += FileChangedEventHandler;
			_fileSystemWatcher.Deleted += FileChangedEventHandler;
			_fileSystemWatcher.Created += FileChangedEventHandler;
			_fileSystemWatcher.Renamed += FileChangedEventHandler;
			_fileSystemWatcher.EnableRaisingEvents = true;
		}

		private static void FileChangedEventHandler(object sender, FileSystemEventArgs args)
		{
			_isPendingAutoReload = true;
			autoReloadTimer = _autoReloadDelaySeconds;
		}
	}
}
namespace Bloodpebble.Extensions
{
	public static class VExtensions
	{
		public static void SendSystemMessage(this User user, string message)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (!VWorld.IsServer)
			{
				throw new Exception("SendSystemMessage can only be called on the server.");
			}
			FixedString512Bytes val = default(FixedString512Bytes);
			((FixedString512Bytes)(ref val))..ctor(message);
			ServerChatUtils.SendSystemMessageToClient(VWorld.Server.EntityManager, user, ref val);
		}
	}
}
namespace Bloodpebble.API
{
	public interface IRunOnInitialized
	{
		void OnGameInitialized();
	}
}
namespace ScarletRCON.Shared
{
	[AttributeUsage(AttributeTargets.Class)]
	public class RconCommandCategoryAttribute : Attribute
	{
		public string Name { get; }

		public RconCommandCategoryAttribute(string categoryName)
		{
			Name = categoryName;
			base..ctor();
		}
	}
	[AttributeUsage(AttributeTargets.Method)]
	public class RconCommandAttribute : Attribute
	{
		public string Name { get; set; }

		public string Description { get; set; }

		public string Usage { get; set; }

		public RconCommandAttribute(string name, string description = null, string usage = null)
		{
			Name = name;
			Description = description;
			Usage = usage;
			base..ctor();
		}
	}
	public static class RconCommandRegistrar
	{
		private static bool? _isScarletRconAvailable;

		public static bool IsScarletRconAvailable()
		{
			bool valueOrDefault = _isScarletRconAvailable.GetValueOrDefault();
			if (!_isScarletRconAvailable.HasValue)
			{
				valueOrDefault = Type.GetType("ScarletRCON.CommandSystem.CommandHandler, ScarletRCON") != null;
				_isScarletRconAvailable = valueOrDefault;
			}
			return _isScarletRconAvailable.Value;
		}

		public static void RegisterAll()
		{
			if (!IsScarletRconAvailable())
			{
				return;
			}
			Assembly callingAssembly = Assembly.GetCallingAssembly();
			string item = callingAssembly.GetName().Name.ToLowerInvariant() + ".";
			List<(string, string, MethodInfo, string, string, string)> list = new List<(string, string, MethodInfo, string, string, string)>();
			Type[] types = callingAssembly.GetTypes();
			foreach (Type type in types)
			{
				string item2 = type.GetCustomAttribute<RconCommandCategoryAttribute>()?.Name ?? "Uncategorized";
				MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					RconCommandAttribute customAttribute = methodInfo.GetCustomAttribute<RconCommandAttribute>();
					if (customAttribute == null)
					{
						continue;
					}
					string text = customAttribute.Usage;
					if (string.IsNullOrWhiteSpace(text))
					{
						ParameterInfo[] parameters = methodInfo.GetParameters();
						text = ((parameters.Length == 0) ? "" : string.Join(" ", parameters.Select((ParameterInfo p) => (p.ParameterType == typeof(List<string>)) ? "<...text>" : ("<" + p.Name + ">"))));
					}
					list.Add((item2, item, methodInfo, customAttribute.Name, customAttribute.Description, text));
				}
			}
			Type type2 = Type.GetType("ScarletRCON.CommandSystem.CommandHandler, ScarletRCON");
			MethodInfo method = type2.GetMethod("RegisterExternalCommandsBatch", BindingFlags.Static | BindingFlags.Public);
			method.Invoke(null, new object[1] { list });
		}

		public static void UnregisterAssembly()
		{
			if (IsScarletRconAvailable())
			{
				Type type = Type.GetType("ScarletRCON.CommandSystem.CommandHandler, ScarletRCON");
				MethodInfo method = type.GetMethod("UnregisterAssembly", BindingFlags.Static | BindingFlags.Public);
				method.Invoke(null, new object[1] { Assembly.GetCallingAssembly() });
			}
		}
	}
}