Decompiled source of ChatCommandAPI v0.4.1

baer1.ChatCommandAPI.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ChatCommandAPI.BuiltinCommands;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Steamworks.Data;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("DunGen")]
[assembly: IgnoresAccessChecksTo("DunGen.Integration.ASPP")]
[assembly: IgnoresAccessChecksTo("DunGen.Integration.UnityNav")]
[assembly: IgnoresAccessChecksTo("EasyTextEffects")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.XR.CoreUtils")]
[assembly: IgnoresAccessChecksTo("Unity.XR.Management")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.ConformanceAutomation")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MetaQuestSupport")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MockRuntime")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.OculusQuestSupport")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.RuntimeDebugger")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.SpatialTracking")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: IgnoresAccessChecksTo("UnityEngine.XR.LegacyInputHelpers")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("baer1")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright (c) baer1 2025")]
[assembly: AssemblyDescription("A Lethal Company modding API for easy creation of Minecraft-style Chat Commands")]
[assembly: AssemblyFileVersion("0.4.1.0")]
[assembly: AssemblyInformationalVersion("0.4.1+45a5755de4e6f3759a230e50d7ca2bcaf508ef3b")]
[assembly: AssemblyProduct("ChatCommandsAPI")]
[assembly: AssemblyTitle("baer1.ChatCommandAPI")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/baerchen201/LethalChatCommands.git")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.4.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[CompilerGenerated]
internal sealed class <>z__ReadOnlySingleElementList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T>
	{
		object IEnumerator.Current => _item;

		T IEnumerator<T>.Current => _item;

		public Enumerator(T item)
		{
			_item = item;
		}

		bool IEnumerator.MoveNext()
		{
			if (!_moveNextCalled)
			{
				return _moveNextCalled = true;
			}
			return false;
		}

		void IEnumerator.Reset()
		{
			_moveNextCalled = false;
		}

		void IDisposable.Dispose()
		{
		}
	}

	int ICollection.Count => 1;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

	object IList.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => 1;

	T IReadOnlyList<T>.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
	}

	int ICollection<T>.Count => 1;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlySingleElementList(T item)
	{
		_item = item;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return new Enumerator(_item);
	}

	void ICollection.CopyTo(Array array, int index)
	{
		array.SetValue(_item, index);
	}

	int IList.Add(object value)
	{
		throw new NotSupportedException();
	}

	void IList.Clear()
	{
		throw new NotSupportedException();
	}

	bool IList.Contains(object value)
	{
		return EqualityComparer<T>.Default.Equals(_item, (T)value);
	}

	int IList.IndexOf(object value)
	{
		if (!EqualityComparer<T>.Default.Equals(_item, (T)value))
		{
			return -1;
		}
		return 0;
	}

	void IList.Insert(int index, object value)
	{
		throw new NotSupportedException();
	}

	void IList.Remove(object value)
	{
		throw new NotSupportedException();
	}

	void IList.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}

	IEnumerator<T> IEnumerable<T>.GetEnumerator()
	{
		return new Enumerator(_item);
	}

	void ICollection<T>.Add(T item)
	{
		throw new NotSupportedException();
	}

	void ICollection<T>.Clear()
	{
		throw new NotSupportedException();
	}

	bool ICollection<T>.Contains(T item)
	{
		return EqualityComparer<T>.Default.Equals(_item, item);
	}

	void ICollection<T>.CopyTo(T[] array, int arrayIndex)
	{
		array[arrayIndex] = _item;
	}

	bool ICollection<T>.Remove(T item)
	{
		throw new NotSupportedException();
	}

	int IList<T>.IndexOf(T item)
	{
		if (!EqualityComparer<T>.Default.Equals(_item, item))
		{
			return -1;
		}
		return 0;
	}

	void IList<T>.Insert(int index, T item)
	{
		throw new NotSupportedException();
	}

	void IList<T>.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}
}
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 ChatCommandAPI
{
	[BepInPlugin("baer1.ChatCommandAPI", "ChatCommandsAPI", "0.4.1")]
	public class ChatCommandAPI : BaseUnityPlugin
	{
		internal struct ConfirmationRequest
		{
			public string? action;

			public Action<bool> callback;
		}

		internal static ConfirmationRequest? confirmationRequest;

		internal static Dictionary<ulong, ConfirmationRequest> confirmationRequests = new Dictionary<ulong, ConfirmationRequest>();

		internal static ulong? targetClientId;

		internal ConfigEntry<bool> builtInCommands;

		private List<ServerCommand> builtInServerCommandList;

		private List<Command> commandList;

		private ConfigEntry<string> commandPrefix;

		private ConfigEntry<bool> enableServerMode;

		internal List<ServerCommand> serverCommandList;

		private ConfigEntry<string> serverCommandPrefix;

		private ConfigEntry<string> serverWelcomeMessage;

		public static ChatCommandAPI Instance { get; private set; } = null;


		internal static ManualLogSource Logger { get; private set; } = null;


		internal static Harmony? Harmony { get; set; }

		public string CommandPrefix => commandPrefix.Value;

		public IReadOnlyList<Command> CommandList => commandList;

		public bool EnableServerMode => enableServerMode.Value;

		public string ServerCommandPrefix => serverCommandPrefix.Value;

		public IReadOnlyList<ServerCommand> ServerCommandList
		{
			get
			{
				if (!builtInCommands.Value)
				{
					return serverCommandList;
				}
				return builtInServerCommandList.Concat(serverCommandList).ToList();
			}
		}

		public string? ServerWelcomeMessage
		{
			get
			{
				if (!Utility.IsNullOrWhiteSpace(serverWelcomeMessage.Value))
				{
					return string.Format(serverWelcomeMessage.Value.Trim(), ServerCommandPrefix);
				}
				return null;
			}
		}

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			commandPrefix = ((BaseUnityPlugin)this).Config.Bind<string>("General", "CommandPrefix", "/", "Client Command Prefix");
			enableServerMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "EnableServerMode", true, "Whether to enable server functionality (if you are host, anyone can use commands, even without the mods)");
			serverCommandPrefix = ((BaseUnityPlugin)this).Config.Bind<string>("Server", "ServerCommandPrefix", "!", "Sever Command Prefix");
			builtInCommands = ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "BuiltInCommands", true, "Enables 'status' and 'servermods' commands");
			serverWelcomeMessage = ((BaseUnityPlugin)this).Config.Bind<string>("Server", "ServerWelcomeMessage", "This server has available commands.\nType {0}help for more information", "A welcome message that is displayed to any player that joins (clear to disable). {0} is replaced with ServerCommandPrefix");
			RegisterCommands();
			Patch();
			Logger.LogInfo((object)"ChatCommandsAPI v0.4.1 has loaded!");
			static void Patch()
			{
				//IL_000c: 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: Expected O, but got Unknown
				if (Harmony == null)
				{
					Harmony = new Harmony("baer1.ChatCommandAPI");
				}
				Logger.LogDebug((object)"Patching...");
				Harmony.PatchAll();
				Logger.LogDebug((object)"Finished patching!");
			}
		}

		private void RegisterCommands()
		{
			commandList = new List<Command>();
			new Help();
			new Position();
			new PlayerList();
			new Confirm();
			new Deny();
			new ErrorCommand();
			serverCommandList = new List<ServerCommand>();
			builtInServerCommandList = new List<ServerCommand>();
			new ServerHelp();
			new ServerStatus();
			new ServerMods();
			new ServerConfirm();
			new ServerDeny();
		}

		public bool RegisterCommand(Command command)
		{
			Command command2 = command;
			if (commandList.Any((Command i) => i.GetType() == command2.GetType()))
			{
				return false;
			}
			commandList.Add(command2);
			return true;
		}

		public bool RegisterServerCommand(ServerCommand command)
		{
			ServerCommand command2 = command;
			if (serverCommandList.Any((ServerCommand i) => i.GetType() == command2.GetType()))
			{
				return false;
			}
			serverCommandList.Add(command2);
			return true;
		}

		public bool RegisterBuiltInServerCommand(ServerCommand command)
		{
			ServerCommand command2 = command;
			if (builtInServerCommandList.Any((ServerCommand i) => i.GetType() == command2.GetType()))
			{
				return false;
			}
			builtInServerCommandList.Add(command2);
			return true;
		}

		public bool IsCommand(string command)
		{
			return command.StartsWith(CommandPrefix);
		}

		public bool IsServerCommand(string command)
		{
			return command.StartsWith(ServerCommandPrefix);
		}

		public bool ParseCommand(string input, out string command, out string[] args, out Dictionary<string, string> kwargs)
		{
			command = null;
			args = null;
			kwargs = null;
			Match match = new Regex("(?:" + Regex.Escape(CommandPrefix) + "|" + Regex.Escape(ServerCommandPrefix) + ")([a-z]+)(?: ([^ =\"]+|(?:\"[^\"]*?\")))*?(?: ([^ =\"]+=[^ \"]+|[^ =\"]+=\"[^\"]*?\"))*\\s*$", RegexOptions.IgnoreCase | RegexOptions.Multiline).Match(input);
			if (!match.Success)
			{
				return false;
			}
			command = match.Groups[1].Value;
			List<string> list = new List<string>();
			foreach (Capture capture3 in match.Groups[2].Captures)
			{
				list.Add(capture3.Value.Replace("\"", ""));
			}
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (Capture capture4 in match.Groups[3].Captures)
			{
				dictionary.Add(capture4.Value.Split('=')[0], capture4.Value.Split('=')[1].Replace("\"", ""));
			}
			args = list.ToArray();
			kwargs = dictionary;
			return true;
		}

		public bool RunCommand(string command, string[] args, Dictionary<string, string> kwargs, out string? error)
		{
			string command2 = command;
			Command[] array = CommandList.Where((Command i) => i.Commands.Select((string s) => s.ToLower()).Contains(command2.ToLower())).ToArray();
			int num = array.Length;
			if (num <= 1)
			{
				if (num == 0)
				{
					error = "Command " + command2 + " not found";
					return false;
				}
			}
			else
			{
				Logger.LogWarning((object)("Command " + command2 + " has multiple matches: " + GeneralExtensions.Join<string>(array.Select((Command i) => i.Name + " (" + i.GetType().Assembly.FullName + ")"), (Func<string, string>)null, ", ")));
			}
			try
			{
				return array[0].Invoke(args, kwargs, out error);
			}
			catch (Exception ex)
			{
				Logger.LogError((object)ex.ToString());
				error = ex.ToString();
				return false;
			}
		}

		public bool RunCommand(PlayerControllerB caller, string command, string[] args, Dictionary<string, string> kwargs, out string? error)
		{
			string command2 = command;
			ServerCommand[] array = ServerCommandList.Where((ServerCommand i) => i.Commands.Select((string s) => s.ToLower()).Contains(command2.ToLower())).ToArray();
			int num = array.Length;
			if (num <= 1)
			{
				if (num == 0)
				{
					error = "Command " + command2 + " not found";
					return false;
				}
			}
			else
			{
				Logger.LogWarning((object)("Server command " + command2 + " has multiple matches: " + GeneralExtensions.Join<string>(array.Select((ServerCommand i) => i.Name + " (" + i.GetType().Assembly.FullName + ")"), (Func<string, string>)null, ", ")));
			}
			try
			{
				return array[0].Invoke(caller, args, kwargs, out error);
			}
			catch (Exception ex)
			{
				Logger.LogError((object)ex.ToString());
				error = ex.ToString();
				return false;
			}
		}

		public static void AskConfirm(string action, Action<bool> callback)
		{
			ConfirmationRequest value = default(ConfirmationRequest);
			value.action = action;
			value.callback = callback;
			confirmationRequest = value;
		}

		public static void AskConfirm(Action<bool> callback)
		{
			ConfirmationRequest value = default(ConfirmationRequest);
			value.callback = callback;
			confirmationRequest = value;
		}

		public static Task<bool> AskConfirmAsync(string action)
		{
			TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();
			ConfirmationRequest value = default(ConfirmationRequest);
			value.action = action;
			value.callback = taskCompletionSource.SetResult;
			confirmationRequest = value;
			return taskCompletionSource.Task;
		}

		public static Task<bool> AskConfirmAsync()
		{
			TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();
			ConfirmationRequest value = default(ConfirmationRequest);
			value.callback = taskCompletionSource.SetResult;
			confirmationRequest = value;
			return taskCompletionSource.Task;
		}

		public static void AskConfirm(PlayerControllerB caller, string action, Action<bool> callback)
		{
			confirmationRequests[caller.actualClientId] = new ConfirmationRequest
			{
				action = action,
				callback = callback
			};
		}

		public static void AskConfirm(PlayerControllerB caller, Action<bool> callback)
		{
			confirmationRequests[caller.actualClientId] = new ConfirmationRequest
			{
				callback = callback
			};
		}

		public static Task<bool> AskConfirmAsync(PlayerControllerB caller, string action)
		{
			TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();
			confirmationRequests[caller.actualClientId] = new ConfirmationRequest
			{
				action = action,
				callback = taskCompletionSource.SetResult
			};
			return taskCompletionSource.Task;
		}

		public static Task<bool> AskConfirmAsync(PlayerControllerB caller)
		{
			TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();
			confirmationRequests[caller.actualClientId] = new ConfirmationRequest
			{
				callback = taskCompletionSource.SetResult
			};
			return taskCompletionSource.Task;
		}

		private static void UpdateChat()
		{
			((TMP_Text)HUDManager.Instance.chatText).text = string.Join("\n", HUDManager.Instance.ChatMessageHistory);
			HUDManager.Instance.PingHUDElement(HUDManager.Instance.Chat, 4f, 1f, 0.2f);
		}

		public static void Print(string text)
		{
			HUDManager.Instance.ChatMessageHistory.Add("<color=#00ffff>" + text + "</color>");
			UpdateChat();
		}

		public static void Print(string text, Color color)
		{
			//IL_0017: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			HUDManager.Instance.ChatMessageHistory.Add($"<color=#{(byte)(color.r * 255f):x2}{(byte)(color.g * 255f):x2}{(byte)(color.b * 255f):x2}>{text}</color>");
			UpdateChat();
		}

		[Obsolete]
		public static void Print(string text, Tuple<byte, byte, byte> color)
		{
			HUDManager.Instance.ChatMessageHistory.Add($"<color=#{color.Item1:x2}{color.Item2:x2}{color.Item3:x2}>{text}</color>");
			UpdateChat();
		}

		public static void Print(string text, (byte, byte, byte) color)
		{
			HUDManager.Instance.ChatMessageHistory.Add($"<color=#{color.Item1:x2}{color.Item2:x2}{color.Item3:x2}>{text}</color>");
			UpdateChat();
		}

		public static void Print(string text, byte r, byte g, byte b)
		{
			HUDManager.Instance.ChatMessageHistory.Add($"<color=#{r:x2}{g:x2}{b:x2}>{text}</color>");
			UpdateChat();
		}

		public static void PrintWarning(string text)
		{
			HUDManager.Instance.ChatMessageHistory.Add("<color=#ffff00>" + text + "</color>");
			UpdateChat();
		}

		public static void PrintError(string text)
		{
			HUDManager.Instance.ChatMessageHistory.Add("<color=#ff0000>" + text + "</color>");
			UpdateChat();
		}

		public static void PrintCommandError(string? error)
		{
			PrintError("Error running command" + (Utility.IsNullOrWhiteSpace(error) ? "" : (": <noparse>" + error + "</noparse>")));
		}

		public static void Print(PlayerControllerB caller, string text)
		{
			SendToPlayer("<color=#00ffff>" + text + "</color>", caller.actualClientId);
		}

		public static void Print(PlayerControllerB caller, string text, Color color)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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)
			SendToPlayer($"<color=#{(byte)(color.r * 255f):x2}{(byte)(color.g * 255f):x2}{(byte)(color.b * 255f):x2}>{text}</color>", caller.actualClientId);
		}

		[Obsolete]
		public static void Print(PlayerControllerB caller, string text, Tuple<byte, byte, byte> color)
		{
			SendToPlayer($"<color=#{color.Item1:x2}{color.Item2:x2}{color.Item3:x2}>{text}</color>", caller.actualClientId);
		}

		public static void Print(PlayerControllerB caller, string text, (byte, byte, byte) color)
		{
			SendToPlayer($"<color=#{color.Item1:x2}{color.Item2:x2}{color.Item3:x2}>{text}</color>", caller.actualClientId);
		}

		public static void Print(PlayerControllerB caller, string text, byte r, byte g, byte b)
		{
			SendToPlayer($"<color=#{r:x2}{g:x2}{b:x2}>{text}</color>", caller.actualClientId);
		}

		public static void PrintWarning(PlayerControllerB caller, string text)
		{
			SendToPlayer("<color=#ffff00>" + text + "</color>", caller.actualClientId);
		}

		public static void PrintError(PlayerControllerB caller, string text)
		{
			SendToPlayer("<color=#ff0000>" + text + "</color>", caller.actualClientId);
		}

		public static void PrintCommandError(PlayerControllerB caller, string? error)
		{
			PrintError(caller, "Error running command" + (Utility.IsNullOrWhiteSpace(error) ? "" : (": <noparse>" + error + "</noparse>")));
		}

		private static void SendToPlayer(string text, ulong clientId)
		{
			targetClientId = clientId;
			HUDManager.Instance.AddTextMessageClientRpc(text);
			targetClientId = null;
		}
	}
	public abstract class Command
	{
		public virtual string Name => GetType().Name;

		public virtual string[] Commands => new string[1] { Name.ToLower() };

		public virtual string? Description => null;

		public virtual string[]? Syntax => null;

		public virtual bool Hidden => false;

		protected Command()
		{
			ChatCommandAPI.Instance.RegisterCommand(this);
		}

		public abstract bool Invoke(string[] args, Dictionary<string, string> kwargs, out string? error);
	}
	public abstract class ServerCommand
	{
		public virtual string Name => GetType().Name;

		public virtual string[] Commands => new string[1] { Name.ToLower() };

		public virtual string? Description => null;

		public virtual string[]? Syntax => null;

		public virtual bool Hidden => false;

		protected ServerCommand()
		{
			ChatCommandAPI.Instance.RegisterServerCommand(this);
		}

		internal ServerCommand(bool builtIn = true)
		{
			if (builtIn)
			{
				ChatCommandAPI.Instance.RegisterBuiltInServerCommand(this);
			}
			else
			{
				ChatCommandAPI.Instance.RegisterServerCommand(this);
			}
		}

		public abstract bool Invoke(PlayerControllerB caller, string[] args, Dictionary<string, string> kwargs, out string? error);
	}
	public abstract class ToggleCommand : Command
	{
		public virtual string? ToggleDescription => null;

		public sealed override string Description
		{
			get
			{
				if (ToggleDescription != null)
				{
					return ToggleDescription + " - " + ValueString;
				}
				return ValueString;
			}
		}

		public sealed override string[] Syntax => new string[2] { "", "{ on | off }" };

		public virtual string EnabledString => "enabled";

		public virtual string DisabledString => "disabled";

		public virtual bool Value { get; set; }

		public virtual string ValueString
		{
			get
			{
				if (!Value)
				{
					return DisabledString;
				}
				return EnabledString;
			}
		}

		public virtual void PrintValue()
		{
			ChatCommandAPI.Print(Name + " " + ValueString);
		}

		public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error)
		{
			error = "Invalid argument";
			if (args.Length == 0)
			{
				Value = !Value;
			}
			else
			{
				switch (args[0])
				{
				case "on":
				case "enable":
					Value = true;
					break;
				case "off":
				case "disable":
					Value = false;
					break;
				default:
					return false;
				}
			}
			PrintValue();
			return true;
		}
	}
	public static class Utils
	{
		public static bool IsPlayerControlled(PlayerControllerB? player)
		{
			if ((Object)(object)player != (Object)null && player != null && !player.disconnectedMidGame && !player.isTestingPlayer)
			{
				if (!player.isPlayerControlled)
				{
					return player.isPlayerDead;
				}
				return true;
			}
			return false;
		}

		public static PlayerControllerB? GetPlayer(string id, out string error, bool strict = false)
		{
			string id2 = id;
			id2 = id2.Trim();
			error = "No player specified";
			if (id2.Length == 0)
			{
				return null;
			}
			error = null;
			string text = id2.ToLower();
			if ((text == "@s" || text == "@me") ? true : false)
			{
				return GameNetworkManager.Instance.localPlayerController;
			}
			uint result;
			PlayerControllerB[] array;
			switch (id2[0])
			{
			case '#':
				if (uint.TryParse(id2.TrimStart('#'), out result) && result < StartOfRound.Instance.allPlayerScripts.Length && IsPlayerControlled(StartOfRound.Instance.allPlayerScripts[result]))
				{
					return StartOfRound.Instance.allPlayerScripts[result];
				}
				error = "Invalid player id";
				return null;
			case '@':
				array = StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB i) => IsPlayerControlled(i) && string.Equals(i.playerUsername, id2.TrimStart('@'), StringComparison.CurrentCultureIgnoreCase)).ToArray();
				if (array.Length == 0 && !strict)
				{
					array = StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB i) => IsPlayerControlled(i) && i.playerUsername.ToLower().StartsWith(id2.ToLower().TrimStart('@'))).ToArray();
				}
				break;
			default:
				if (uint.TryParse(id2, out result) && result < StartOfRound.Instance.allPlayerScripts.Length && IsPlayerControlled(StartOfRound.Instance.allPlayerScripts[result]))
				{
					return StartOfRound.Instance.allPlayerScripts[result];
				}
				array = StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB i) => IsPlayerControlled(i) && string.Equals(i.playerUsername, id2, StringComparison.CurrentCultureIgnoreCase)).ToArray();
				if (array.Length == 0 && !strict)
				{
					array = StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB i) => IsPlayerControlled(i) && i.playerUsername.ToLower().StartsWith(id2.ToLower())).ToArray();
				}
				break;
			}
			if (array.Length > 1)
			{
				if (strict)
				{
					error = "Multiple players match";
					return null;
				}
				ChatCommandAPI.PrintWarning("Multiple players match, selecting first...");
			}
			if (array.Length != 0)
			{
				return array[0];
			}
			error = "No player matches";
			return null;
		}

		public static bool GetPlayer(string id, out PlayerControllerB player, out string error, bool strict = false)
		{
			player = GameNetworkManager.Instance.localPlayerController;
			PlayerControllerB player2 = GetPlayer(id, out error, strict);
			if ((Object)(object)player2 == (Object)null)
			{
				return false;
			}
			player = player2;
			return true;
		}

		public static Vector3? ParsePosition(Vector3 origin, Quaternion rotation, string x, string y, string z)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			x = x.Trim();
			y = y.Trim();
			z = z.Trim();
			ChatCommandAPI.Logger.LogDebug((object)("x:" + x + " y:" + y + ", z:" + z));
			if (!x.StartsWith("^") || !y.StartsWith("^") || !z.StartsWith("^"))
			{
				return ParsePosition(origin, x, y, z);
			}
			string text = x;
			x = text.Substring(1, text.Length - 1);
			text = y;
			y = text.Substring(1, text.Length - 1);
			text = z;
			z = text.Substring(1, text.Length - 1);
			if ((!float.TryParse(x, out var result) && x.Length > 0) || (!float.TryParse(y, out var result2) && y.Length > 0) || (!float.TryParse(z, out var result3) && z.Length > 0))
			{
				return null;
			}
			return origin + rotation * Vector3.forward * result3 + rotation * Vector3.up * result2 + rotation * Vector3.right * result;
		}

		public static Vector3? ParsePosition(Vector3 origin, string x, string y, string z)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_010a: Unknown result type (might be due to invalid IL or missing references)
			x = x.Trim();
			y = y.Trim();
			z = z.Trim();
			float result;
			if (x.StartsWith('~'))
			{
				string text = x;
				x = text.Substring(1, text.Length - 1);
				if (!float.TryParse(x, out result) && x.Length > 0)
				{
					return null;
				}
				result += origin.x;
			}
			else if (!float.TryParse(x, out result))
			{
				return null;
			}
			float result2;
			if (y.StartsWith('~'))
			{
				string text = y;
				y = text.Substring(1, text.Length - 1);
				if (!float.TryParse(y, out result2) && y.Length > 0)
				{
					return null;
				}
				result2 += origin.y;
			}
			else if (!float.TryParse(y, out result2))
			{
				return null;
			}
			float result3;
			if (z.StartsWith('~'))
			{
				string text = z;
				z = text.Substring(1, text.Length - 1);
				if (!float.TryParse(z, out result3) && z.Length > 0)
				{
					return null;
				}
				result3 += origin.z;
			}
			else if (!float.TryParse(z, out result3))
			{
				return null;
			}
			return new Vector3(result, result2, result3);
		}

		public static Vector3? ParsePosition(string x, string y, string z)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			x = x.Trim();
			y = y.Trim();
			z = z.Trim();
			if (!float.TryParse(x, out var result) || !float.TryParse(y, out var result2) || !float.TryParse(z, out var result3))
			{
				return null;
			}
			return new Vector3(result, result2, result3);
		}

		public static bool ParsePosition(Vector3 origin, Quaternion rotation, string x, string y, string z, out Vector3 position)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			position = default(Vector3);
			Vector3? val = ParsePosition(origin, rotation, x, y, z);
			if (!val.HasValue)
			{
				return false;
			}
			position = val.Value;
			return true;
		}

		public static bool ParsePosition(Vector3 origin, string x, string y, string z, out Vector3 position)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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)
			position = default(Vector3);
			Vector3? val = ParsePosition(origin, x, y, z);
			if (!val.HasValue)
			{
				return false;
			}
			position = val.Value;
			return true;
		}

		public static bool ParsePosition(string x, string y, string z, out Vector3 position)
		{
			//IL_0001: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			position = default(Vector3);
			Vector3? val = ParsePosition(x, y, z);
			if (!val.HasValue)
			{
				return false;
			}
			position = val.Value;
			return true;
		}

		public static Vector3? ParsePosition(Vector3 origin, Quaternion rotation, string input)
		{
			//IL_000e: 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)
			if (ParseSingleCommaSeparatedPositionString(input, out string x, out string y, out string z))
			{
				return ParsePosition(origin, rotation, x, y, z);
			}
			return null;
		}

		public static Vector3? ParsePosition(Vector3 origin, string input)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (ParseSingleCommaSeparatedPositionString(input, out string x, out string y, out string z))
			{
				return ParsePosition(origin, x, y, z);
			}
			return null;
		}

		public static Vector3? ParsePosition(string input)
		{
			if (ParseSingleCommaSeparatedPositionString(input, out string x, out string y, out string z))
			{
				return ParsePosition(x, y, z);
			}
			return null;
		}

		public static bool ParsePosition(Vector3 origin, Quaternion rotation, string input, out Vector3 position)
		{
			//IL_0001: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			position = default(Vector3);
			if (ParseSingleCommaSeparatedPositionString(input, out string x, out string y, out string z))
			{
				return ParsePosition(origin, rotation, x, y, z, out position);
			}
			return false;
		}

		public static bool ParsePosition(Vector3 origin, string input, out Vector3 position)
		{
			//IL_0001: 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)
			position = default(Vector3);
			if (ParseSingleCommaSeparatedPositionString(input, out string x, out string y, out string z))
			{
				return ParsePosition(origin, x, y, z, out position);
			}
			return false;
		}

		public static bool ParsePosition(string input, out Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			position = default(Vector3);
			if (ParseSingleCommaSeparatedPositionString(input, out string x, out string y, out string z))
			{
				return ParsePosition(x, y, z, out position);
			}
			return false;
		}

		internal static bool ParseSingleCommaSeparatedPositionString(string input, out string x, out string y, out string z)
		{
			x = "0";
			y = "0";
			z = "0";
			Match match = new Regex("^(?:([^,]+),){2}([^,]+)$", RegexOptions.Multiline).Match(input);
			if (!match.Success)
			{
				return false;
			}
			x = match.Groups[1].Captures[0].Value;
			y = match.Groups[1].Captures[1].Value;
			z = match.Groups[2].Captures[0].Value;
			return true;
		}

		[Obsolete]
		public static bool IsInsideFactory(Vector3 position)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return Object.FindObjectsOfType<OutOfBoundsTrigger>().Any((OutOfBoundsTrigger i) => position.y < ((Component)i).gameObject.transform.position.y);
		}

		[Obsolete]
		public static PlayerControllerB? GetPlayer(string id, bool strict = false)
		{
			string id2 = id;
			id2 = id2.Trim();
			string text = id2.ToLower();
			if ((text == "@s" || text == "@me") ? true : false)
			{
				return GameNetworkManager.Instance.localPlayerController;
			}
			uint result;
			PlayerControllerB[] array;
			switch (id2[0])
			{
			case '#':
				if (uint.TryParse(id2.TrimStart('#'), out result) && result < StartOfRound.Instance.allPlayerScripts.Length && IsPlayerControlled(StartOfRound.Instance.allPlayerScripts[result]))
				{
					return StartOfRound.Instance.allPlayerScripts[result];
				}
				ChatCommandAPI.PrintError("Invalid player id");
				return null;
			case '@':
				array = StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB i) => IsPlayerControlled(i) && string.Equals(i.playerUsername, id2.TrimStart('@'), StringComparison.CurrentCultureIgnoreCase)).ToArray();
				if (array.Length == 0 && !strict)
				{
					array = StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB i) => IsPlayerControlled(i) && i.playerUsername.ToLower().StartsWith(id2.ToLower().TrimStart('@'))).ToArray();
				}
				break;
			default:
				if (uint.TryParse(id2, out result) && result < StartOfRound.Instance.allPlayerScripts.Length && IsPlayerControlled(StartOfRound.Instance.allPlayerScripts[result]))
				{
					return StartOfRound.Instance.allPlayerScripts[result];
				}
				array = StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB i) => IsPlayerControlled(i) && string.Equals(i.playerUsername, id2, StringComparison.CurrentCultureIgnoreCase)).ToArray();
				if (array.Length == 0 && !strict)
				{
					array = StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB i) => IsPlayerControlled(i) && i.playerUsername.ToLower().StartsWith(id2.ToLower())).ToArray();
				}
				break;
			}
			if (array.Length > 1)
			{
				ChatCommandAPI.PrintWarning("Multiple players with this name exist, selecting first...");
			}
			if (array.Length != 0)
			{
				return array[0];
			}
			ChatCommandAPI.PrintError("No player with username found");
			return null;
		}

		[Obsolete]
		public static bool GetPlayer(string id, out PlayerControllerB player, bool strict = false)
		{
			player = GameNetworkManager.Instance.localPlayerController;
			PlayerControllerB player2 = GetPlayer(id, strict);
			if ((Object)(object)player2 == (Object)null)
			{
				return false;
			}
			player = player2;
			return true;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "baer1.ChatCommandAPI";

		public const string PLUGIN_NAME = "ChatCommandsAPI";

		public const string PLUGIN_VERSION = "0.4.1";
	}
}
namespace ChatCommandAPI.Patches
{
	[HarmonyPatch(typeof(GameNetworkManager), "StartHost")]
	internal static class GameNetworkManager_StartHost
	{
		private static void Postfix()
		{
			ServerStatus.startTime = DateTime.Now;
			ChatCommandAPI.confirmationRequests.Clear();
		}
	}
	[HarmonyPatch(typeof(HUDManager), "AddPlayerChatMessageServerRpc")]
	internal static class HUDManager_AddPlayerChatMessageServerRpc
	{
		private static bool Prefix(ref HUDManager __instance, ref string chatMessage, ref int playerId)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)((NetworkBehaviour)__instance).__rpc_exec_stage != 1 || (!((NetworkBehaviour)__instance).NetworkManager.IsServer && !((NetworkBehaviour)__instance).NetworkManager.IsHost) || Utility.IsNullOrWhiteSpace(chatMessage) || !ChatCommandAPI.Instance.IsServerCommand(chatMessage))
			{
				return true;
			}
			ChatCommandAPI.Logger.LogInfo((object)$">> Parsing server command by player {playerId}: {chatMessage}");
			PlayerControllerB val = null;
			if (playerId >= 0 && playerId < StartOfRound.Instance.allPlayerScripts.Length)
			{
				val = StartOfRound.Instance.allPlayerScripts[playerId];
			}
			ChatCommandAPI.Logger.LogDebug((object)("   caller: " + (((Object)(object)val == (Object)null) ? "null" : val.playerUsername)));
			if ((Object)(object)val == (Object)null || !Utils.IsPlayerControlled(val))
			{
				ChatCommandAPI.Logger.LogWarning((object)$"Server command sent by invalid player {playerId}: {chatMessage}");
				return true;
			}
			if (ChatCommandAPI.Instance.ParseCommand(chatMessage, out string command, out string[] args, out Dictionary<string, string> kwargs))
			{
				StringBuilder stringBuilder = new StringBuilder("<< Parsed command: " + command + "(" + (((Object)(object)val == (Object)null) ? "null" : $"#{val.playerClientId} {val.playerUsername}") + ((args.Length != 0 || kwargs.Count > 0) ? ", " : ""));
				if (args.Length != 0)
				{
					stringBuilder.Append(GeneralExtensions.Join<string>((IEnumerable<string>)args, (Func<string, string>)null, ", "));
					if (kwargs.Count > 0)
					{
						stringBuilder.Append(", ");
					}
				}
				stringBuilder.Append(GeneralExtensions.Join<string>(kwargs.Select((KeyValuePair<string, string> kvp) => kvp.Key + ": " + kvp.Value), (Func<string, string>)null, ", "));
				ChatCommandAPI.Logger.LogInfo((object)(stringBuilder?.ToString() + ")"));
				if (!ChatCommandAPI.Instance.RunCommand(val, command, args, kwargs, out string error))
				{
					ChatCommandAPI.Logger.LogWarning((object)("   Error running command: " + (error ?? "null")));
					if ((Object)(object)val != (Object)null && error != null)
					{
						ChatCommandAPI.PrintCommandError(val, error);
					}
				}
				return false;
			}
			ChatCommandAPI.Logger.LogInfo((object)"<< Invalid command");
			if ((Object)(object)val != (Object)null)
			{
				ChatCommandAPI.PrintError(val, "Invalid command");
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(HUDManager), "AddTextMessageClientRpc")]
	internal static class HUDManager_AddTextMessageClientRpc
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(NetworkBehaviour), "__endSendClientRpc", (Type[])null, (Type[])null), (string)null)
			}).Advance(-1).Insert((CodeInstruction[])(object)new CodeInstruction[1] { CodeInstruction.Call(typeof(HUDManager_AddTextMessageClientRpc), "RedirectMessageToClient", (Type[])null, (Type[])null) })
				.InstructionEnumeration();
		}

		public static ClientRpcParams RedirectMessageToClient(ClientRpcParams clientRpcParams)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (!ChatCommandAPI.targetClientId.HasValue)
			{
				return clientRpcParams;
			}
			ClientRpcParams result = default(ClientRpcParams);
			result.Send.TargetClientIds = new <>z__ReadOnlySingleElementList<ulong>(ChatCommandAPI.targetClientId.Value);
			return result;
		}
	}
	[HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")]
	internal static class HUDManager_SubmitChat_performed
	{
		private static bool Prefix(ref HUDManager __instance, ref CallbackContext context)
		{
			string text = __instance.chatTextField.text;
			if (!((CallbackContext)(ref context)).performed || Utility.IsNullOrWhiteSpace(text) || !ChatCommandAPI.Instance.IsCommand(text))
			{
				return true;
			}
			__instance.localPlayer.isTypingChat = false;
			__instance.chatTextField.text = "";
			EventSystem.current.SetSelectedGameObject((GameObject)null);
			__instance.PingHUDElement(__instance.Chat, 2f, 1f, 0.2f);
			((Behaviour)__instance.typingIndicator).enabled = false;
			ChatCommandAPI.Logger.LogInfo((object)(">> Parsing command: " + text));
			if (ChatCommandAPI.Instance.ParseCommand(text, out string command, out string[] args, out Dictionary<string, string> kwargs))
			{
				StringBuilder stringBuilder = new StringBuilder("<< Parsed command: " + command + "(");
				if (args.Length != 0)
				{
					stringBuilder.Append(GeneralExtensions.Join<string>((IEnumerable<string>)args, (Func<string, string>)null, ", "));
					if (kwargs.Count > 0)
					{
						stringBuilder.Append(", ");
					}
				}
				stringBuilder.Append(GeneralExtensions.Join<string>(kwargs.Select((KeyValuePair<string, string> kvp) => kvp.Key + ": " + kvp.Value), (Func<string, string>)null, ", "));
				ChatCommandAPI.Logger.LogInfo((object)(stringBuilder?.ToString() + ")"));
				if (!ChatCommandAPI.Instance.RunCommand(command, args, kwargs, out string error))
				{
					ChatCommandAPI.Logger.LogWarning((object)("   Error running command: " + (error ?? "null")));
					if (error != null)
					{
						ChatCommandAPI.PrintCommandError(error);
					}
				}
				return false;
			}
			ChatCommandAPI.Logger.LogInfo((object)"<< Invalid command");
			ChatCommandAPI.PrintError("Invalid command");
			return false;
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "SyncAlreadyHeldObjectsServerRpc")]
	internal static class StartOfRound_SyncAlreadyHeldObjectsServerRpc
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Debug), "Log", new Type[1] { typeof(string) }, (Type[])null), (string)null)
			}).Insert((CodeInstruction[])(object)new CodeInstruction[2]
			{
				new CodeInstruction(OpCodes.Ldarg_1, (object)null),
				CodeInstruction.Call(typeof(StartOfRound_SyncAlreadyHeldObjectsServerRpc), "SendWelcomeMessage", (Type[])null, (Type[])null)
			}).InstructionEnumeration();
		}

		internal static void SendWelcomeMessage(ulong clientId)
		{
			if (ChatCommandAPI.Instance.ServerWelcomeMessage != null && !Utility.IsNullOrWhiteSpace(ChatCommandAPI.Instance.ServerWelcomeMessage) && !ChatCommandAPI.Instance.serverCommandList.All((ServerCommand i) => i.Hidden))
			{
				ChatCommandAPI.targetClientId = clientId;
				HUDManager.Instance.AddTextMessageClientRpc("<color=#7069ff>" + ChatCommandAPI.Instance.ServerWelcomeMessage + "</color>");
				ChatCommandAPI.targetClientId = null;
			}
		}
	}
}
namespace ChatCommandAPI.BuiltinCommands
{
	public class Confirm : Command
	{
		public override string[] Commands => new string[3]
		{
			Name.ToLower(),
			"c",
			"con"
		};

		public override string Description
		{
			get
			{
				if (ChatCommandAPI.confirmationRequest.HasValue && ChatCommandAPI.confirmationRequest.Value.action != null)
				{
					return "Confirms " + ChatCommandAPI.confirmationRequest.Value.action;
				}
				return "Confirms an action";
			}
		}

		public override bool Hidden => !ChatCommandAPI.confirmationRequest.HasValue;

		public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error)
		{
			error = "No action currently needs confirmation";
			if (!ChatCommandAPI.confirmationRequest.HasValue)
			{
				return false;
			}
			ChatCommandAPI.confirmationRequest.Value.callback(obj: true);
			ChatCommandAPI.confirmationRequest = null;
			return true;
		}
	}
	public class Deny : Command
	{
		public override string[] Commands => new string[3]
		{
			Name.ToLower(),
			"d",
			"den"
		};

		public override string Description
		{
			get
			{
				if (ChatCommandAPI.confirmationRequest.HasValue && ChatCommandAPI.confirmationRequest.Value.action != null)
				{
					return "Cancels " + ChatCommandAPI.confirmationRequest.Value.action;
				}
				return "Cancels an action";
			}
		}

		public override bool Hidden => !ChatCommandAPI.confirmationRequest.HasValue;

		public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error)
		{
			error = "No action currently needs confirmation";
			if (!ChatCommandAPI.confirmationRequest.HasValue)
			{
				return false;
			}
			ChatCommandAPI.confirmationRequest.Value.callback(obj: false);
			ChatCommandAPI.confirmationRequest = null;
			return true;
		}
	}
	public class ErrorCommand : Command
	{
		public override string Name => "Error";

		public override string Description => "Raises a NullReferenceException, for testing";

		public override bool Hidden => true;

		public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error)
		{
			error = null;
			return Func().EndsWith("a");
			static string Func()
			{
				return null;
			}
		}
	}
	public class Position : Command
	{
		public override string[] Commands => new string[4] { "pos", "getpos", "showpos", Name };

		public override string Description => "Shows the current position of [player] or yourself";

		public override string[] Syntax => new string[1] { "[player]" };

		public override bool Hidden => true;

		public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string? error)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			error = null;
			PlayerControllerB player = GameNetworkManager.Instance.localPlayerController;
			if (args.Length != 0 && !Utils.GetPlayer(args[0], out player, out error))
			{
				return false;
			}
			error = "This player is dead";
			if (player.isPlayerDead)
			{
				return false;
			}
			string[] obj = new string[6] { "Position of player <noparse>", player.playerUsername, ":\n", null, null, null };
			Vector3 position = ((Component)player).transform.position;
			obj[3] = ((object)(Vector3)(ref position)).ToString();
			obj[4] = (((Object)(object)((Component)player).transform.parent != (Object)null) ? $"\nrelative to {((Object)((Component)player).transform.parent).name}:\n{((Component)player).transform.parent.InverseTransformPoint(((Component)player).transform.position)}" : "");
			obj[5] = "</noparse>";
			ChatCommandAPI.Print(string.Concat(obj));
			ChatCommandAPI.Logger.LogInfo((object)string.Format("Position of player {0}: {1}{2}", player.playerUsername, ((Component)player).transform.position, ((Object)(object)((Component)player).transform.parent != (Object)null) ? $" - ({((Object)((Component)player).transform.parent).name}){((Component)player).transform.parent.InverseTransformPoint(((Component)player).transform.position)}" : ""));
			return true;
		}
	}
	public class Help : Command
	{
		internal const string SEPARATOR = "<color=#00FFFF>===============</color>\n";

		public override bool Hidden => true;

		public override string Description => "Displays all available commands";

		public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error)
		{
			error = "No commands have been registered yet";
			if (ChatCommandAPI.Instance.CommandList == null || ChatCommandAPI.Instance.CommandList.Count((Command i) => !i.Hidden) == 0)
			{
				return false;
			}
			ChatCommandAPI.Print("<color=#00FFFF>===============</color>\n" + string.Join("<color=#00FFFF>===============</color>\n", ChatCommandAPI.Instance.CommandList.Where((Command i) => !i.Hidden).Select(delegate(Command i)
			{
				StringBuilder stringBuilder = new StringBuilder(i.Name + ((i.Description == null) ? "" : (" - " + i.Description)) + "\n");
				string[] array = i.Syntax ?? new string[1];
				foreach (string text in array)
				{
					stringBuilder.Append("<color=#ffff00>" + ChatCommandAPI.Instance.CommandPrefix + i.Commands[0] + (Utility.IsNullOrWhiteSpace(text) ? "" : " ") + "</color><color=#dddd00><noparse>" + text + "</noparse></color>\n");
				}
				return stringBuilder.ToString();
			})) + "<color=#00FFFF>===============</color>\n".Trim());
			return true;
		}
	}
	public class PlayerList : Command
	{
		public override string[] Commands => new string[2] { "players", Name };

		public override string Description => "Lists all active players";

		public override bool Hidden => true;

		public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error)
		{
			error = "No players connected";
			if (!StartOfRound.Instance.allPlayerScripts.Any(Utils.IsPlayerControlled))
			{
				return false;
			}
			ChatCommandAPI.Print("<noparse>" + string.Join('\n', from i in StartOfRound.Instance.allPlayerScripts.Where(Utils.IsPlayerControlled)
				select $"#{i.playerClientId}: {i.playerUsername}") + "</noparse>");
			return true;
		}
	}
	public class ServerConfirm : ServerCommand
	{
		public override string[] Commands => new string[3]
		{
			"Confirm".ToLower(),
			"c",
			"con"
		};

		public override string Description
		{
			get
			{
				if (ChatCommandAPI.confirmationRequest.HasValue && ChatCommandAPI.confirmationRequest.Value.action != null)
				{
					return "Confirms " + ChatCommandAPI.confirmationRequest.Value.action;
				}
				return "Confirms an action";
			}
		}

		public override bool Hidden => !ChatCommandAPI.confirmationRequest.HasValue;

		public ServerConfirm()
			: base(builtIn: true)
		{
		}

		public override bool Invoke(PlayerControllerB caller, string[] args, Dictionary<string, string> kwargs, out string? error)
		{
			error = "No action currently needs confirmation";
			if (!ChatCommandAPI.confirmationRequests.TryGetValue(caller.actualClientId, out var value))
			{
				return false;
			}
			value.callback(obj: true);
			ChatCommandAPI.confirmationRequests.Remove(caller.actualClientId);
			return true;
		}
	}
	public class ServerDeny : ServerCommand
	{
		public override string[] Commands => new string[3]
		{
			"Deny".ToLower(),
			"d",
			"den"
		};

		public override string Description
		{
			get
			{
				if (ChatCommandAPI.confirmationRequest.HasValue && ChatCommandAPI.confirmationRequest.Value.action != null)
				{
					return "Cancels " + ChatCommandAPI.confirmationRequest.Value.action;
				}
				return "Cancels an action";
			}
		}

		public override bool Hidden => !ChatCommandAPI.confirmationRequest.HasValue;

		public ServerDeny()
			: base(builtIn: true)
		{
		}

		public override bool Invoke(PlayerControllerB caller, string[] args, Dictionary<string, string> kwargs, out string? error)
		{
			error = "No action currently needs confirmation";
			if (!ChatCommandAPI.confirmationRequests.TryGetValue(caller.actualClientId, out var value))
			{
				return false;
			}
			value.callback(obj: false);
			ChatCommandAPI.confirmationRequests.Remove(caller.actualClientId);
			return true;
		}
	}
	public class ServerHelp : ServerCommand
	{
		public override string Name => "Help";

		public override bool Hidden => true;

		public override string Description => "Displays all available commands on the server";

		public override bool Invoke(PlayerControllerB caller, string[] args, Dictionary<string, string> kwargs, out string? error)
		{
			error = "This server has no available commands";
			if (ChatCommandAPI.Instance.ServerCommandList == null || ChatCommandAPI.Instance.ServerCommandList.Count((ServerCommand i) => !i.Hidden) == 0)
			{
				return false;
			}
			ChatCommandAPI.Print(caller, "<color=#00FFFF>===============</color>\n" + string.Join("<color=#00FFFF>===============</color>\n", ChatCommandAPI.Instance.ServerCommandList.Where((ServerCommand i) => !i.Hidden).Select(delegate(ServerCommand i)
			{
				StringBuilder stringBuilder = new StringBuilder(i.Name + ((i.Description == null) ? "" : (" - " + i.Description)) + "\n");
				string[] array = i.Syntax ?? new string[1];
				foreach (string text in array)
				{
					stringBuilder.Append("<color=#ffff00>" + ChatCommandAPI.Instance.ServerCommandPrefix + i.Commands[0] + (Utility.IsNullOrWhiteSpace(text) ? "" : " ") + "</color><color=#dddd00><noparse>" + text + "</noparse></color>\n");
				}
				return stringBuilder.ToString();
			})) + "<color=#00FFFF>===============</color>\n".Trim());
			return true;
		}
	}
	public class ServerMods : ServerCommand
	{
		public override string Name => "ServerMods";

		public override string Description => "Shows a list of all mods installed on the server";

		public ServerMods()
			: base(builtIn: true)
		{
		}

		public override bool Invoke(PlayerControllerB caller, string[] args, Dictionary<string, string> kwargs, out string? error)
		{
			error = null;
			ChatCommandAPI.Print(caller, $"Mods ({Chainloader.PluginInfos.Count}):\n" + GeneralExtensions.Join<string>((IEnumerable<string>)Chainloader.PluginInfos.Select((KeyValuePair<string, PluginInfo> i) => $"{i.Key} ({i.Value.Metadata.Version})").OrderBy<string, string>((string s) => s, StringComparer.CurrentCultureIgnoreCase), (Func<string, string>)null, "\n"));
			return true;
		}
	}
	public class ServerStatus : ServerCommand
	{
		internal static DateTime startTime = new DateTime(0L);

		public override string Name => "Status";

		public override string Description => "Displays information about this server";

		public ServerStatus()
			: base(builtIn: true)
		{
		}

		public override bool Invoke(PlayerControllerB caller, string[] args, Dictionary<string, string> kwargs, out string? error)
		{
			//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)
			error = null;
			StringBuilder stringBuilder = new StringBuilder("Current game: ");
			Lobby? currentLobby = GameNetworkManager.Instance.currentLobby;
			object obj;
			if (currentLobby.HasValue)
			{
				Lobby value = currentLobby.Value;
				obj = ((Lobby)(ref value)).GetData("name");
			}
			else
			{
				obj = "unknown";
			}
			stringBuilder.Append((string?)obj + "\n");
			stringBuilder.Append("Players:\n");
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (Utils.IsPlayerControlled(val))
				{
					stringBuilder.Append(val.isPlayerDead ? "<color=#ff0000>" : "");
					stringBuilder.Append($" #{val.playerClientId} {val.playerUsername}");
					if (val.isHostPlayerObject)
					{
						stringBuilder.Append(" (HOST)");
					}
					stringBuilder.Append(val.isPlayerDead ? "</color>\n" : "\n");
				}
			}
			if (startTime.Ticks > 0)
			{
				TimeSpan timeSpan = DateTime.Now - startTime;
				stringBuilder.Append($"\nGame time: {(int)timeSpan.TotalHours:D2}:{timeSpan.Minutes:D2}:{timeSpan.Seconds:D2}");
			}
			ChatCommandAPI.Print(caller, stringBuilder.ToString());
			return true;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}