Decompiled source of Chat Commands v1.0.2

BepInEx/plugins/ChatCommands/ChatCommands.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using ChatCommands.Attributes;
using ChatCommands.BuiltinCommands;
using ChatCommands.Parsers;
using ComputerysModdingUtilities;
using FishNet;
using FishNet.Connection;
using FishNet.Object;
using HarmonyLib;
using HeathenEngineering.DEMO;
using HeathenEngineering.SteamworksIntegration;
using HeathenEngineering.SteamworksIntegration.UI;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using TMPro;
using Unity.Collections;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: StraftatMod(true)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ChatCommands")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A library mod for straftat that allows developers to create their own chat commands")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2")]
[assembly: AssemblyProduct("kestrel.straftat.chatcommands")]
[assembly: AssemblyTitle("ChatCommands")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ChatCommands
{
	public static class ChatPatches
	{
		[HarmonyPatch(typeof(LobbyChatUILogic))]
		internal static class LobbyChatUILogicPatch
		{
			[HarmonyPatch("Start")]
			[HarmonyPostfix]
			public static void ModifyPanel(GameObject ___theirChatTemplate, Transform ___messageRoot, List<IChatMessage> ___chatMessages, GameObject ___chatPanel, LobbyManager ___lobbyManager)
			{
				m_lobbyManager = ___lobbyManager;
				m_messageTemplate = ___theirChatTemplate;
				m_messageRoot = ___messageRoot;
				m_chatMessages = ___chatMessages;
			}

			[HarmonyPatch("OnSendChatMessage")]
			[HarmonyPrefix]
			public static bool DetectCommand(TMP_InputField ___inputField)
			{
				string text = ___inputField.text;
				if (!text.StartsWith("/"))
				{
					return true;
				}
				Evaluator.Evaluate(text.Remove(0, "/".Length));
				return false;
			}
		}

		[HarmonyPatch(typeof(MatchChat))]
		internal static class MatchChatPatch
		{
			private static bool m_activeLast = true;

			[HarmonyPatch("Update")]
			[HarmonyPrefix]
			public static void OpenOnCommandPrefix(GameObject ___ChatBox, TMP_InputField ___inputLine)
			{
				if (Input.GetKeyDown((KeyCode)47) && !___ChatBox.activeSelf)
				{
					___ChatBox.SetActive(true);
					___inputLine.text = "/";
					___inputLine.MoveToEndOfLine(false, true);
				}
				bool activeInHierarchy = ___ChatBox.activeInHierarchy;
				if (!activeInHierarchy && m_activeLast)
				{
					___inputLine.text = string.Empty;
				}
				m_activeLast = activeInHierarchy;
			}
		}

		public const string c_commandPrefix = "/";

		public const KeyCode c_commandHotkey = 47;

		private static LobbyManager m_lobbyManager;

		private static GameObject m_messageTemplate;

		private static Transform m_messageRoot;

		private static List<IChatMessage> m_chatMessages;

		public static void SendChatMessage(string message)
		{
			((LobbyData)(ref m_lobbyManager.Lobby)).SendChatMessage(message);
		}

		public static void ClearChat()
		{
			foreach (IChatMessage chatMessage in m_chatMessages)
			{
				try
				{
					Object.Destroy((Object)(object)chatMessage.GameObject);
				}
				catch
				{
				}
			}
			m_chatMessages.Clear();
		}

		public static void SendSystemMessage(object message, bool showUsername = true, TextAlignmentOptions alignment = 260)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(m_messageTemplate, m_messageRoot);
			val.transform.SetAsLastSibling();
			((LayoutGroup)val.GetComponent<VerticalLayoutGroup>()).padding.right = 0;
			BasicChatMessage component = val.GetComponent<BasicChatMessage>();
			if (component != null)
			{
				TextMeshProUGUI component2 = ((Component)component.username).GetComponent<TextMeshProUGUI>();
				((TMP_Text)component2).alignment = alignment;
				TextMeshProUGUI message2 = component.message;
				((TMP_Text)message2).alignment = alignment;
				((TMP_Text)component2).text = "SYSTEM";
				((TMP_Text)message2).text = message.ToString();
				if (!showUsername)
				{
					((Component)component.username).gameObject.SetActive(false);
				}
				component.IsExpanded = false;
				m_chatMessages.Add((IChatMessage)(object)component);
			}
			else
			{
				Object.Destroy((Object)(object)val);
				Plugin.Logger.LogError((object)$"Failed to send system message \"{message}\" in chat~ null BasicChatMessage.");
			}
		}
	}
	[Flags]
	public enum CommandFlags
	{
		None = 0,
		HostOnly = 1,
		ExplorationOnly = 2,
		IngameOnly = 4,
		Silent = 8
	}
	public class Command
	{
		public readonly MethodInfo method;

		public readonly string description;

		public readonly CommandFlags flags;

		public readonly string name;

		public readonly string[] aliases;

		public readonly string categoryName;

		public readonly ParameterInfo[] parameterInfos;

		public readonly int maxParameters;

		public readonly int minParameters;

		public readonly int registryPriority;

		public bool isOverriden;

		public Command(MethodInfo method, string name, string description = "no description found", string categoryName = "Misc", CommandFlags flags = CommandFlags.None, int registryPriority = 0, params string[] aliases)
		{
			this.name = name;
			this.aliases = aliases;
			this.method = method;
			this.description = description;
			this.flags = flags;
			this.categoryName = categoryName;
			this.registryPriority = registryPriority;
			parameterInfos = method.GetParameters();
			maxParameters = parameterInfos.Length;
			minParameters = parameterInfos.Count((ParameterInfo p) => !p.HasDefaultValue);
		}

		public object Invoke(object[] args)
		{
			return method.Invoke(null, args);
		}
	}
	public static class CommandRegistry
	{
		internal static Dictionary<string, Command> Commands { get; private set; } = new Dictionary<string, Command>();


		internal static HashSet<string> Categories { get; private set; } = new HashSet<string>();


		public static void RegisterCommandsFromAssembly(Assembly assembly)
		{
			PopulateFromAssembly(assembly);
		}

		public static void RegisterCommandsFromAssembly()
		{
			PopulateFromAssembly(Assembly.GetCallingAssembly());
		}

		public static bool CommandExists(string alias)
		{
			return Commands.ContainsKey(alias);
		}

		public static bool CategoryExists(string categoryName)
		{
			return Categories.Contains(categoryName.ToLower());
		}

		public static bool TryGet(string alias, out Command command)
		{
			return Commands.TryGetValue(alias, out command);
		}

		private static Command[] GetCollisions(Command command)
		{
			HashSet<Command> hashSet = new HashSet<Command>();
			foreach (string item in command.aliases.Append(command.name))
			{
				if (TryGet(item, out var command2))
				{
					hashSet.Add(command2);
				}
			}
			return hashSet.ToArray();
		}

		private static void Add(Command command)
		{
			Categories.Add(command.categoryName.ToLower());
			Commands.Add(command.name, command);
			string[] aliases = command.aliases;
			foreach (string key in aliases)
			{
				Commands.Add(key, command);
			}
		}

		private static void AddOverride(Command command)
		{
			Categories.Add(command.categoryName.ToLower());
			Commands[command.name] = command;
			string[] aliases = command.aliases;
			foreach (string key in aliases)
			{
				Commands[key] = command;
			}
		}

		internal static void RegisterCommand(Command command)
		{
			Command[] collisions = GetCollisions(command);
			if (collisions.Length == 0)
			{
				Add(command);
			}
			else if (collisions.All((Command c) => c.registryPriority < command.registryPriority))
			{
				Command[] array = collisions;
				foreach (Command command2 in array)
				{
					foreach (string item in command2.aliases.Append(command2.name))
					{
						Commands.Remove(item);
					}
				}
				command.isOverriden = true;
				AddOverride(command);
			}
			else if (collisions.Any((Command c) => c.registryPriority == command.registryPriority))
			{
				Assembly definingAssembly = command.method.DeclaringType?.Assembly ?? Assembly.GetCallingAssembly();
				LogConflictError(command.aliases.Prepend(command.name).ToArray(), command.registryPriority, definingAssembly);
			}
		}

		private static void PopulateFromAssembly(Assembly assembly)
		{
			Plugin.Logger.LogInfo((object)("Registering commands from \"" + assembly.GetName().Name + "\""));
			foreach (MethodInfo item in from method in assembly.GetTypes().SelectMany((Type type) => type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
				where method.IsDefined(typeof(CommandAttribute), inherit: false)
				select method)
			{
				Type declaringType = item.DeclaringType;
				CommandAttribute customAttribute = item.GetCustomAttribute<CommandAttribute>();
				bool flag = item.IsDefined(typeof(CommandAliasesAttribute), inherit: false);
				bool num = item.IsDefined(typeof(CommandOverrideAttribute), inherit: false);
				string categoryName = (((object)declaringType == null || !declaringType.IsDefined(typeof(CommandCategoryAttribute), inherit: false)) ? "Misc" : declaringType.GetCustomAttribute<CommandCategoryAttribute>()?.name);
				int registryPriority = (num ? item.GetCustomAttribute<CommandOverrideAttribute>().priority : 0);
				Command command;
				if (flag)
				{
					CommandAliasesAttribute customAttribute2 = item.GetCustomAttribute<CommandAliasesAttribute>();
					command = new Command(item, customAttribute.name, customAttribute.description, categoryName, customAttribute.flags, registryPriority, customAttribute2.aliases);
				}
				else
				{
					command = new Command(item, customAttribute.name, customAttribute.description, categoryName, customAttribute.flags, registryPriority);
				}
				RegisterCommand(command);
			}
		}

		private static void LogConflictError(string[] problematicCommandNames, int priorityAttempted, Assembly definingAssembly)
		{
			Plugin.Logger.LogError((object)($"Error when registering command \"{problematicCommandNames[0]}\" from \"{definingAssembly.GetName().Name}\" w/ priority {priorityAttempted}:" + " a command with the same name or one of the same aliases is already registered with the same priority!"));
			Plugin.Logger.LogError((object)"Command conflicts:");
			for (int i = 0; i < problematicCommandNames.Length; i++)
			{
				if (!TryGet(problematicCommandNames[i], out var command))
				{
					continue;
				}
				StringBuilder stringBuilder = new StringBuilder("\"" + (command.method.DeclaringType?.Assembly.GetName().Name ?? "UNKNOWN ASSEMBLY") + "\" registers [");
				stringBuilder.Append("\"").Append(command.name).Append("\" w/ priority: ")
					.Append(command.registryPriority);
				if (command.aliases.Length != 0)
				{
					stringBuilder.Append(", aliases: ");
					string[] aliases = command.aliases;
					foreach (string value in aliases)
					{
						stringBuilder.Append("\"").Append(value).Append("\" ");
					}
				}
				stringBuilder.Append("\b]");
				Plugin.Logger.LogWarning((object)stringBuilder.ToString());
				stringBuilder.Clear();
			}
		}

		[Obsolete("slow. bad idea.")]
		internal static void PopulateAll()
		{
			foreach (Assembly item in from plugin in Chainloader.PluginInfos.Values
				select (plugin == null) ? null : ((object)plugin.Instance)?.GetType().Assembly into assembly
				where (object)assembly != null
				select assembly)
			{
				PopulateFromAssembly(item);
			}
		}
	}
	public static class Evaluator
	{
		public static void Evaluate(string input)
		{
			Queue<CommandLexer.Token> tokens = new CommandLexer(input).GetTokens();
			List<string> list = new List<string>();
			object obj = null;
			while (tokens.Count > 0)
			{
				CommandLexer.Token token = tokens.Dequeue();
				switch (token.type)
				{
				case CommandLexer.TokenType.Seperator:
					if (list.Count != 0)
					{
						string name2 = list[0];
						list.RemoveAt(0);
						if (obj != null)
						{
							list.Add(obj.ToString());
							obj = null;
						}
						RunCommand(name2, list.ToArray());
						list.Clear();
					}
					break;
				case CommandLexer.TokenType.Pipe:
					if (list.Count != 0)
					{
						string name = list[0];
						list.RemoveAt(0);
						if (obj != null)
						{
							list.Add(obj.ToString());
						}
						obj = RunCommand(name, list.ToArray(), sendResult: false);
						list.Clear();
					}
					break;
				default:
					list.Add(token.content);
					break;
				}
			}
		}

		public static object RunCommand(string name, string[] args, bool sendResult = true)
		{
			if (!CommandRegistry.TryGet(name, out var command))
			{
				SystemMessage("No command found with name \"" + name + "\".");
				return null;
			}
			if (command.flags.HasFlag(CommandFlags.IngameOnly) && Settings.Instance.inMenu)
			{
				SystemMessage("The command \"" + name + "\" can only be run while in a game!");
				return null;
			}
			if (command.flags.HasFlag(CommandFlags.HostOnly) && !InstanceFinder.IsHost)
			{
				SystemMessage("The command \"" + name + "\" can only be run as a lobby host!");
			}
			if (command.flags.HasFlag(CommandFlags.ExplorationOnly) && !SceneMotor.Instance.testMap)
			{
				SystemMessage("The command \"" + name + "\" can only be run in exploration mode!");
				return null;
			}
			int num = args.Length;
			if (num < command.minParameters)
			{
				SystemMessage(string.Format("Mismatched parameter counts: command \"{0}\" expects at least {1}, but {2} {3} provided.", name, command.minParameters, num, (num == 1) ? "was" : "were"));
				return null;
			}
			if (num > command.maxParameters)
			{
				SystemMessage(string.Format("Mismatched parameter counts: command \"{0}\" expects at most {1}, but {2} {3} provided.", name, command.maxParameters, num, (num == 1) ? "was" : "were"));
				return null;
			}
			object[] array = new object[command.maxParameters];
			for (int i = 0; i < num; i++)
			{
				Type parameterType = command.parameterInfos[i].ParameterType;
				try
				{
					array[i] = ParserLocator.ParseTo(parameterType, args[i]);
				}
				catch
				{
					SystemMessage("Invalid parameter: command \"" + name + "\" expects the parameter \"" + command.parameterInfos[i].Name + "\" to be of type " + parameterType.Name + ", but the provided parameter (\"" + args[i] + "\") could not be converted to it!");
					return null;
				}
			}
			if (command.maxParameters > num)
			{
				for (int j = num; j < command.maxParameters; j++)
				{
					array[j] = command.parameterInfos[j].DefaultValue;
				}
			}
			try
			{
				object obj2 = command.Invoke(array);
				if (obj2 != null && !command.flags.HasFlag(CommandFlags.Silent) && sendResult)
				{
					SystemMessage(obj2);
				}
				return obj2;
			}
			catch (Exception ex)
			{
				Exception innerMostException = ex.GetInnerMostException();
				if (innerMostException is CommandException ex2)
				{
					SystemMessage("Command \"" + name + "\" failed: " + ex2.Message);
				}
				else
				{
					SystemMessage($"Unknown error running command \"{name}\": {innerMostException}");
				}
				return null;
			}
		}

		private static void SystemMessage(object msg)
		{
			ChatPatches.SendSystemMessage(msg, showUsername: true, (TextAlignmentOptions)260);
		}
	}
	internal class CommandLexer
	{
		public enum TokenType
		{
			Identifier,
			NestedString,
			Seperator,
			Pipe
		}

		public readonly struct Token
		{
			public readonly string content;

			public readonly TokenType type;

			public static Token Seperator => new Token(";", TokenType.Seperator);

			public static Token Pipe => new Token("|", TokenType.Pipe);

			public Token(string content, TokenType type)
			{
				this.content = content;
				this.type = type;
			}
		}

		[CompilerGenerated]
		private string <source>P;

		private int m_pos;

		private StringBuilder m_builder;

		public CommandLexer(string source)
		{
			<source>P = source;
			m_builder = new StringBuilder();
			base..ctor();
		}

		private static bool IsSeperator(char c)
		{
			if (c == '\n' || c == ';')
			{
				return true;
			}
			return false;
		}

		private static bool IsPipe(char c)
		{
			if (c == '>' || c == '|')
			{
				return true;
			}
			return false;
		}

		private static bool IsQuote(char c)
		{
			if (c == '"' || c == '\'')
			{
				return true;
			}
			return false;
		}

		private static bool IsIdentifierChar(char c)
		{
			bool flag = char.IsLetterOrDigit(c);
			if (!flag)
			{
				bool flag2;
				switch (c)
				{
				case '(':
				case ')':
				case ',':
				case '-':
				case '.':
				case ':':
				case '_':
					flag2 = true;
					break;
				default:
					flag2 = false;
					break;
				}
				flag = flag2;
			}
			return flag;
		}

		private static bool IsIgnorable(char c)
		{
			if (!IsSeperator(c) && !IsQuote(c) && !IsIdentifierChar(c))
			{
				return !IsPipe(c);
			}
			return false;
		}

		private static char GetEscaped(char c)
		{
			return c switch
			{
				'n' => '\n', 
				'r' => '\r', 
				't' => '\t', 
				'b' => '\b', 
				_ => c, 
			};
		}

		private void SkipIgnorables()
		{
			while (m_pos < <source>P.Length && IsIgnorable(<source>P[m_pos]))
			{
				m_pos++;
			}
		}

		private bool TryGetNextToken(out Token token)
		{
			SkipIgnorables();
			token = default(Token);
			if (m_pos == <source>P.Length)
			{
				return false;
			}
			TokenType tokenType = TokenType.Identifier;
			char c = '\0';
			char c2 = <source>P[m_pos];
			if (IsQuote(c2))
			{
				tokenType = TokenType.NestedString;
				c = c2;
				m_pos++;
			}
			else
			{
				if (IsSeperator(c2))
				{
					m_pos++;
					token = Token.Seperator;
					return true;
				}
				if (IsPipe(c2))
				{
					m_pos++;
					token = Token.Pipe;
					return true;
				}
			}
			while (m_pos < <source>P.Length)
			{
				char c3 = <source>P[m_pos];
				if (tokenType == TokenType.Identifier)
				{
					if (!IsIdentifierChar(c3))
					{
						break;
					}
				}
				else if (c3 == '\\' && m_pos + 1 < <source>P.Length)
				{
					c3 = GetEscaped(<source>P[++m_pos]);
				}
				else if (c3 == c)
				{
					m_pos++;
					break;
				}
				m_builder.Append(c3);
				m_pos++;
			}
			string content = m_builder.ToString();
			token = new Token(content, tokenType);
			m_builder.Clear();
			return true;
		}

		public Queue<Token> GetTokens()
		{
			Queue<Token> queue = new Queue<Token>();
			Token token;
			while (TryGetNextToken(out token))
			{
				queue.Enqueue(token);
			}
			queue.Enqueue(Token.Seperator);
			return queue;
		}
	}
	public class CommandException : Exception
	{
		public CommandException()
		{
		}

		public CommandException(string message)
			: base(message)
		{
		}

		public CommandException(string message, Exception inner)
			: base(message, inner)
		{
		}
	}
	[BepInPlugin("kestrel.straftat.chatcommands", "ChatCommands", "1.0.2")]
	internal class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		public static readonly string loadBearingColonThree = ":3";

		public static Plugin Instance { get; private set; }

		private void Awake()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if (loadBearingColonThree != ":3")
			{
				Application.Quit();
			}
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			WeaponLoader.Init();
			BindingCommands.Init();
			AdminCommands.Init();
			CommandRegistry.RegisterCommandsFromAssembly();
			new Harmony("kestrel.straftat.chatcommands").PatchAll();
			Logger.LogInfo((object)"Hiiiiiiiiiiii :3");
		}

		private void Update()
		{
			BindingCommands.Update();
		}
	}
	internal static class ExceptionExtensions
	{
		public static Exception GetInnerMostException(this Exception ex)
		{
			while (ex.InnerException != null && ex != null)
			{
				ex = ex.InnerException;
			}
			return ex;
		}
	}
	internal static class Utils
	{
		public static IEnumerable<TValue> RandomValues<TKey, TValue>(IDictionary<TKey, TValue> dict)
		{
			List<TValue> values = dict.Values.ToList();
			int size = dict.Count;
			while (true)
			{
				yield return values[Random.Range(0, size - 1)];
			}
		}

		public static bool AnyInputFieldFocused()
		{
			GameObject currentSelectedGameObject = EventSystem.current.currentSelectedGameObject;
			if (!Object.op_Implicit((Object)(object)currentSelectedGameObject))
			{
				return false;
			}
			TMP_InputField component = currentSelectedGameObject.GetComponent<TMP_InputField>();
			if (component != null)
			{
				return component.isFocused;
			}
			return false;
		}

		public static T LoadFromJsonFile<T>(string path)
		{
			if (!File.Exists(path))
			{
				return default(T);
			}
			return JsonConvert.DeserializeObject<T>(File.ReadAllText(path));
		}

		public static void SaveToJsonFile<T>(T obj, string path)
		{
			File.WriteAllText(path, JsonConvert.SerializeObject((object)obj, (Formatting)1));
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "kestrel.straftat.chatcommands";

		public const string PLUGIN_NAME = "ChatCommands";

		public const string PLUGIN_VERSION = "1.0.2";
	}
}
namespace ChatCommands.Parsers
{
	internal class BoolParser : ParserBase
	{
		public override Type ParseResultType => typeof(bool);

		public override object Parse(string value)
		{
			if (bool.TryParse(value, out var result))
			{
				return result;
			}
			if (int.TryParse(value, out var result2))
			{
				return result2 > 0;
			}
			throw new InvalidCastException();
		}
	}
	internal class KeyCodeParser : ParserBase
	{
		private static Dictionary<string, KeyCode> m_alternativeStrings = new Dictionary<string, KeyCode>
		{
			{
				"1",
				(KeyCode)257
			},
			{
				"2",
				(KeyCode)258
			},
			{
				"3",
				(KeyCode)259
			},
			{
				"4",
				(KeyCode)260
			},
			{
				"5",
				(KeyCode)261
			},
			{
				"6",
				(KeyCode)262
			},
			{
				"7",
				(KeyCode)263
			},
			{
				"8",
				(KeyCode)264
			},
			{
				"9",
				(KeyCode)265
			},
			{
				"0",
				(KeyCode)256
			},
			{
				"!",
				(KeyCode)33
			},
			{
				"\"",
				(KeyCode)34
			},
			{
				"#",
				(KeyCode)35
			},
			{
				"$",
				(KeyCode)36
			},
			{
				"&",
				(KeyCode)38
			},
			{
				"'",
				(KeyCode)39
			},
			{
				"(",
				(KeyCode)40
			},
			{
				")",
				(KeyCode)41
			},
			{
				"*",
				(KeyCode)42
			},
			{
				"+",
				(KeyCode)43
			},
			{
				",",
				(KeyCode)44
			},
			{
				"-",
				(KeyCode)45
			},
			{
				".",
				(KeyCode)46
			},
			{
				"/",
				(KeyCode)47
			},
			{
				":",
				(KeyCode)58
			},
			{
				";",
				(KeyCode)59
			},
			{
				"<",
				(KeyCode)60
			},
			{
				"=",
				(KeyCode)61
			},
			{
				">",
				(KeyCode)62
			},
			{
				"?",
				(KeyCode)63
			},
			{
				"@",
				(KeyCode)64
			},
			{
				"[",
				(KeyCode)91
			},
			{
				"\\",
				(KeyCode)92
			},
			{
				"]",
				(KeyCode)93
			},
			{
				"^",
				(KeyCode)94
			},
			{
				"_",
				(KeyCode)95
			},
			{
				"`",
				(KeyCode)96
			},
			{
				"shift",
				(KeyCode)304
			},
			{
				"rshift",
				(KeyCode)303
			},
			{
				"ctrl",
				(KeyCode)306
			},
			{
				"rctrl",
				(KeyCode)305
			},
			{
				"alt",
				(KeyCode)308
			},
			{
				"ralt",
				(KeyCode)307
			},
			{
				"enter",
				(KeyCode)13
			},
			{
				"lwin",
				(KeyCode)311
			},
			{
				"rwin",
				(KeyCode)312
			},
			{
				"apps",
				(KeyCode)319
			},
			{
				"ins",
				(KeyCode)277
			},
			{
				"del",
				(KeyCode)127
			},
			{
				"pgdn",
				(KeyCode)281
			},
			{
				"pgup",
				(KeyCode)280
			},
			{
				"kp_end",
				(KeyCode)257
			},
			{
				"kp_downarrow",
				(KeyCode)258
			},
			{
				"kp_pgdn",
				(KeyCode)259
			},
			{
				"kp_leftarrow",
				(KeyCode)260
			},
			{
				"kp_5",
				(KeyCode)261
			},
			{
				"kp_rightarrow",
				(KeyCode)262
			},
			{
				"kp_home",
				(KeyCode)263
			},
			{
				"kp_uparrow",
				(KeyCode)264
			},
			{
				"kp_pgup",
				(KeyCode)265
			},
			{
				"kp_enter",
				(KeyCode)271
			},
			{
				"kp_ins",
				(KeyCode)256
			},
			{
				"kp_del",
				(KeyCode)266
			},
			{
				"kp_slash",
				(KeyCode)267
			},
			{
				"kp_multiply",
				(KeyCode)268
			},
			{
				"kp_minus",
				(KeyCode)269
			},
			{
				"kp_plus",
				(KeyCode)270
			}
		};

		public override Type ParseResultType => typeof(KeyCode);

		public override object Parse(string value)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (m_alternativeStrings.TryGetValue(value.ToLower(), out var value2))
			{
				return value2;
			}
			if (Enum.TryParse(typeof(KeyCode), value, ignoreCase: true, out object result))
			{
				return result;
			}
			throw new InvalidCastException();
		}
	}
	public abstract class ParserBase
	{
		public abstract Type ParseResultType { get; }

		public abstract object Parse(string value);
	}
	public static class ParserLocator
	{
		private static Dictionary<Type, ParserBase> m_parsers;

		static ParserLocator()
		{
			m_parsers = new Dictionary<Type, ParserBase>();
			foreach (Type item in from t in Assembly.GetExecutingAssembly().GetTypes()
				where t.IsSubclassOf(typeof(ParserBase)) && !t.IsAbstract
				select t)
			{
				ParserBase parserBase = Activator.CreateInstance(item) as ParserBase;
				m_parsers.TryAdd(parserBase.ParseResultType, parserBase);
			}
		}

		public static void RegisterParsersFromAssembly()
		{
			RegisterParsersFromAssembly(Assembly.GetCallingAssembly());
		}

		public static void RegisterParsersFromAssembly(Assembly assembly)
		{
			foreach (Type item in from t in assembly.GetTypes()
				where t.IsSubclassOf(typeof(ParserBase)) && !t.IsAbstract
				select t)
			{
				ParserBase parserBase = Activator.CreateInstance(item) as ParserBase;
				m_parsers.TryAdd(parserBase.ParseResultType, parserBase);
			}
		}

		private static bool TryIConvertible(Type resultType, string input, out object result)
		{
			result = null;
			if (!typeof(IConvertible).IsAssignableFrom(resultType) || m_parsers.ContainsKey(resultType))
			{
				return false;
			}
			result = Convert.ChangeType(input, resultType);
			return true;
		}

		public static object ParseTo(Type type, string input)
		{
			if (TryIConvertible(type, input, out var result))
			{
				return result;
			}
			if (m_parsers.TryGetValue(type, out var value))
			{
				return value.Parse(input);
			}
			throw new NotSupportedException("Type not supported.");
		}

		public static bool TryParseTo(Type type, string input, out object result)
		{
			if (TryIConvertible(type, input, out result))
			{
				return true;
			}
			if (!m_parsers.TryGetValue(type, out var value))
			{
				return false;
			}
			try
			{
				result = value.Parse(input);
			}
			catch
			{
				return false;
			}
			return true;
		}

		public static T ParseTo<T>(string input)
		{
			return (T)ParseTo(typeof(T), input);
		}

		public static bool TryParseTo<T>(string input, out T result)
		{
			result = default(T);
			if (!TryParseTo(typeof(T), input, out var result2))
			{
				return false;
			}
			result = (T)result2;
			return true;
		}
	}
	public class Vector2Parser : ParserBase
	{
		public override Type ParseResultType => typeof(Vector2);

		public override object Parse(string value)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			value = string.Join(' ', value.Split(new char[3] { ',', '(', ')' }, StringSplitOptions.RemoveEmptyEntries));
			string[] array = value.Split(' ', StringSplitOptions.RemoveEmptyEntries);
			val.x = float.Parse(array[0].Trim(), CultureInfo.CurrentCulture);
			val.y = float.Parse(array[1].Trim(), CultureInfo.CurrentCulture);
			return val;
		}
	}
	public class Vector3Parser : ParserBase
	{
		public override Type ParseResultType => typeof(Vector3);

		public override object Parse(string value)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = default(Vector3);
			value = string.Join(' ', value.Split(new char[3] { ',', '(', ')' }, StringSplitOptions.RemoveEmptyEntries));
			string[] array = value.Split(' ', StringSplitOptions.RemoveEmptyEntries);
			val.x = float.Parse(array[0].Trim(), CultureInfo.CurrentCulture);
			val.y = float.Parse(array[1].Trim(), CultureInfo.CurrentCulture);
			val.z = float.Parse(array[2].Trim(), CultureInfo.CurrentCulture);
			return val;
		}
	}
}
namespace ChatCommands.BuiltinCommands
{
	[CommandCategory("Admin")]
	public static class AdminCommands
	{
		private struct SavedLists
		{
			public HashSet<ulong> bans;

			public HashSet<ulong> ignores;
		}

		[HarmonyPatch(typeof(LobbyChatUILogic))]
		internal static class LobbyChatUILogicPatch
		{
			[HarmonyPatch("HandleChatMessage")]
			[HarmonyPrefix]
			public static bool DontHandleIfIgnored(LobbyChatMsg message)
			{
				return !m_ignoredPlayers.Contains(((UserData)(ref message.sender)).SteamId);
			}
		}

		[HarmonyPatch(typeof(LobbyController))]
		internal static class LobbyControllerPatch
		{
			private static List<PlayerListItem> m_playerListItems;

			public static void KickBannedPlayers()
			{
				foreach (PlayerListItem item in m_playerListItems.Where((PlayerListItem player) => m_bannedPlayers.Contains(player.PlayerSteamID)))
				{
					PauseManager.Instance.WriteLog("Kicked \"" + item.PlayerName + "\": banned from this lobby");
					item.KickPlayer();
				}
			}

			[HarmonyPatch("Start")]
			[HarmonyPrefix]
			public static void CapturePlayerlist(List<PlayerListItem> ___PlayerListItems)
			{
				m_playerListItems = ___PlayerListItems;
			}

			[HarmonyPatch("CreateClientPlayerItem")]
			[HarmonyPostfix]
			public static void HandleBans()
			{
				KickBannedPlayers();
			}
		}

		private static HashSet<ulong> m_ignoredPlayers;

		private static HashSet<ulong> m_bannedPlayers;

		private static string m_savePath = Path.Combine(Paths.ConfigPath, "kestrel.straftat.chatcommands.adminlists.json");

		public static void Init()
		{
			SavedLists? savedLists = Utils.LoadFromJsonFile<SavedLists?>(m_savePath);
			m_ignoredPlayers = savedLists?.ignores ?? new HashSet<ulong>();
			m_bannedPlayers = savedLists?.bans ?? new HashSet<ulong>();
		}

		private static void SaveToJson()
		{
			SavedLists obj = default(SavedLists);
			obj.bans = m_bannedPlayers;
			obj.ignores = m_ignoredPlayers;
			Utils.SaveToJsonFile(obj, m_savePath);
		}

		[Command("ignore", "ignores a player, hiding their chat messages. if no steam id is provided, ignores your opponent.", CommandFlags.None)]
		public static string Ignore(ulong steamID = 0uL)
		{
			if (steamID == 0L && (steamID = GetOpponentId()) == 0L)
			{
				throw new CommandException("could not get opponent's steam id");
			}
			if (!m_ignoredPlayers.Add(steamID))
			{
				throw new CommandException($"\"{steamID}\" is already ignored");
			}
			SaveToJson();
			return $"ignored {steamID}";
		}

		[Command("unignore", "unignores a player. if no steam id is provided, unignores your opponent.", CommandFlags.None)]
		public static string Unignore(ulong steamID = 0uL)
		{
			if (steamID == 0L && (steamID = GetOpponentId()) == 0L)
			{
				throw new CommandException("could not get opponent's steam id");
			}
			if (!m_ignoredPlayers.Remove(steamID))
			{
				throw new CommandException($"\"{steamID}\" was not ignored");
			}
			SaveToJson();
			return $"unignored {steamID}";
		}

		[Command("ignorelist", "lists ignored players", CommandFlags.None)]
		public static string ListIgnored()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("<u>ignored players</u>");
			if (m_ignoredPlayers.Count == 0)
			{
				stringBuilder.AppendLine("[none]");
			}
			foreach (ulong ignoredPlayer in m_ignoredPlayers)
			{
				stringBuilder.AppendLine(ignoredPlayer.ToString());
			}
			return stringBuilder.ToString();
		}

		[Command("clearignores", "removes ALL ignores. use with caution!", CommandFlags.None)]
		public static string ClearIgnores()
		{
			m_ignoredPlayers.Clear();
			SaveToJson();
			return "cleared ignorelist";
		}

		[Command("ban", "bans a player, automatically kicking them from any of your lobbies. if no steam id is provided, bans your opponent.", CommandFlags.None)]
		public static string Ban(ulong steamID = 0uL)
		{
			if (steamID == 0L && (steamID = GetOpponentId()) == 0L)
			{
				throw new CommandException("could not get opponent's steam id");
			}
			if (!m_bannedPlayers.Add(steamID))
			{
				throw new CommandException($"\"{steamID}\" is already banned");
			}
			LobbyControllerPatch.KickBannedPlayers();
			SaveToJson();
			return $"banned {steamID}";
		}

		[Command("unban", "unbans a player. if no steam id is provided, unbans your opponent.", CommandFlags.None)]
		public static string Unban(ulong steamID = 0uL)
		{
			if (steamID == 0L && (steamID = GetOpponentId()) == 0L)
			{
				throw new CommandException("could not get opponent's steam id");
			}
			if (!m_bannedPlayers.Remove(steamID))
			{
				throw new CommandException($"\"{steamID}\" was not banned");
			}
			SaveToJson();
			return $"unbanned {steamID}";
		}

		[Command("banlist", "lists banned players", CommandFlags.None)]
		public static string ListBanned()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("<u>banned players</u>");
			if (m_bannedPlayers.Count == 0)
			{
				stringBuilder.AppendLine("[none]");
			}
			foreach (ulong bannedPlayer in m_bannedPlayers)
			{
				stringBuilder.AppendLine(bannedPlayer.ToString());
			}
			return stringBuilder.ToString();
		}

		[Command("clearbans", "removes ALL bans. use with caution!", CommandFlags.None)]
		public static string ClearBans()
		{
			m_bannedPlayers.Clear();
			SaveToJson();
			return "cleared banlist";
		}

		private static ulong GetOpponentId()
		{
			return ClientInstance.Instance.Enemy()?.PlayerSteamID ?? 0;
		}
	}
	[CommandCategory("Binding")]
	public static class BindingCommands
	{
		private const KeyCode c_mwheelupKey = 295;

		private const KeyCode c_mwheeldownKey = 296;

		private const string c_mwheelup = "mwheelup";

		private const string c_mwheeldown = "mwheeldown";

		private static Dictionary<KeyCode, List<string>> m_binds;

		private static string m_savePath = Path.Combine(Paths.ConfigPath, "kestrel.straftat.chatcommands.binds.json");

		public static void Init()
		{
			m_binds = Utils.LoadFromJsonFile<Dictionary<KeyCode, List<string>>>(m_savePath) ?? new Dictionary<KeyCode, List<string>>();
		}

		public static void Update()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (!Cursor.visible)
			{
				float y = Input.mouseScrollDelta.y;
				List<string> value2;
				if (!(y > 0f))
				{
					if (y < 0f && m_binds.TryGetValue((KeyCode)296, out var value))
					{
						value.ForEach(Evaluator.Evaluate);
					}
				}
				else if (m_binds.TryGetValue((KeyCode)295, out value2))
				{
					value2.ForEach(Evaluator.Evaluate);
				}
			}
			if (!Input.anyKeyDown || Utils.AnyInputFieldFocused())
			{
				return;
			}
			foreach (string item in m_binds.Where((KeyValuePair<KeyCode, List<string>> bind) => Input.GetKeyDown(bind.Key)).SelectMany((KeyValuePair<KeyCode, List<string>> bind) => bind.Value))
			{
				Evaluator.Evaluate(item);
			}
		}

		[Command("bind", "binds a command to a specified key", CommandFlags.None)]
		public static string Bind(string key, string command)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: 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)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			KeyCode key2 = ParseKey(key);
			if (m_binds.TryGetValue(key2, out var value))
			{
				if (value.Contains(command))
				{
					throw new CommandException("bind already exists");
				}
				value.Add(command);
			}
			else if (!m_binds.TryAdd(key2, new List<string>(1) { command }))
			{
				throw new CommandException("unknown error while adding bind");
			}
			Utils.SaveToJsonFile(m_binds, m_savePath);
			return "bound " + key.ToLower() + " -> \"" + command + "\"";
		}

		[Command("unbind", "removes all bindings from the specified key", CommandFlags.None)]
		public static string Unbind(string key)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: 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)
			KeyCode key2 = ParseKey(key);
			m_binds.Remove(key2);
			Utils.SaveToJsonFile(m_binds, m_savePath);
			return "unbound " + key.ToLower();
		}

		private static KeyCode ParseKey(string key)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			if (!ParserLocator.TryParseTo<KeyCode>(key, out var result) && key != "mwheelup" && key != "mwheeldown")
			{
				throw new CommandException("unknown key: \"" + key + "\"");
			}
			string text = key.ToLower();
			if (!(text == "mwheelup"))
			{
				if (text == "mwheeldown")
				{
					return (KeyCode)296;
				}
				return result;
			}
			return (KeyCode)295;
		}

		[Command("unbindall", "removes all bindings", CommandFlags.None)]
		public static string UnbindAll()
		{
			m_binds.Clear();
			Utils.SaveToJsonFile(m_binds, m_savePath);
			return "removed all bindings";
		}

		[Command("listbinds", "lists all bound keys", CommandFlags.None)]
		[CommandAliases(new string[] { "key_listboundkeys" })]
		public static string ListBinds()
		{
			//IL_0020: 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)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Invalid comparison between Unknown and I4
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder();
			foreach (KeyValuePair<KeyCode, List<string>> bind in m_binds)
			{
				KeyCode key = bind.Key;
				string text;
				if ((int)key != 295)
				{
					if ((int)key == 296)
					{
						text = "mwheeldown";
					}
					else
					{
						KeyCode key2 = bind.Key;
						text = ((object)(KeyCode)(ref key2)).ToString();
					}
				}
				else
				{
					text = "mwheelup";
				}
				string text2 = text;
				stringBuilder.Append("\"" + text2 + "\" = ");
				for (int i = 0; i < bind.Value.Count; i++)
				{
					stringBuilder.Append("\"" + bind.Value[i] + "\"");
					if (i < bind.Value.Count - 1)
					{
						stringBuilder.Append(", ");
					}
				}
				stringBuilder.Append("\n");
			}
			string text3 = stringBuilder.ToString();
			if (!(text3 == string.Empty))
			{
				return text3;
			}
			return "no binds";
		}
	}
	[CommandCategory("Fun")]
	public static class FunCommands
	{
		private const CommandFlags c_weaponCommandFlags = CommandFlags.HostOnly | CommandFlags.ExplorationOnly | CommandFlags.IngameOnly;

		private static bool m_weaponRainEnabled;

		[Command("weapon", "spawns a weapon", CommandFlags.HostOnly | CommandFlags.ExplorationOnly | CommandFlags.IngameOnly)]
		[CommandAliases(new string[] { "w" })]
		public static void Weapon(string weaponName)
		{
			//IL_0021: 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)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (WeaponLoader.TryGetWeapon(weaponName, out var prefab))
			{
				Transform transform = ((Component)Settings.Instance.localPlayer.playerPickupScript).transform;
				GameObject gameObject = ((Component)Object.Instantiate<Weapon>(prefab, transform.position, transform.rotation)).gameObject;
				InstanceFinder.ServerManager.Spawn(gameObject, (NetworkConnection)null);
				gameObject.GetComponent<ItemBehaviour>().DispenserDrop(Vector3.zero);
				return;
			}
			throw new CommandException("No weapon found with name " + weaponName);
		}

		[Command("randomweapon", "spawns a random weapon", CommandFlags.HostOnly | CommandFlags.ExplorationOnly | CommandFlags.IngameOnly)]
		[CommandAliases(new string[] { "rw" })]
		public static void RandomWeapon()
		{
			//IL_001b: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			Weapon obj = WeaponLoader.RandomWeapon();
			Transform transform = ((Component)Settings.Instance.localPlayer.playerPickupScript).transform;
			GameObject gameObject = ((Component)Object.Instantiate<Weapon>(obj, transform.position, transform.rotation)).gameObject;
			InstanceFinder.ServerManager.Spawn(gameObject, (NetworkConnection)null);
			gameObject.GetComponent<ItemBehaviour>().DispenserDrop(Vector3.zero);
		}

		[Command("weaponrain", "toggles weapon rain", CommandFlags.HostOnly | CommandFlags.ExplorationOnly | CommandFlags.IngameOnly)]
		public static void ToggleWeaponRain()
		{
			m_weaponRainEnabled = !m_weaponRainEnabled;
			if (m_weaponRainEnabled)
			{
				((MonoBehaviour)Plugin.Instance).StartCoroutine(WeaponRain());
			}
		}

		private static IEnumerator WeaponRain()
		{
			Transform playerTransform = ((Component)Settings.Instance.localPlayer.playerPickupScript).transform;
			Vector3 val2 = default(Vector3);
			while (m_weaponRainEnabled)
			{
				Weapon obj = WeaponLoader.RandomWeapon();
				Vector2 val = Random.insideUnitCircle * 10f;
				((Vector3)(ref val2))..ctor(playerTransform.position.x + val.x, playerTransform.position.y + 10f, playerTransform.position.z + val.y);
				GameObject gameObject = ((Component)Object.Instantiate<Weapon>(obj, val2, playerTransform.rotation)).gameObject;
				InstanceFinder.ServerManager.Spawn(gameObject, (NetworkConnection)null);
				gameObject.GetComponent<ItemBehaviour>().DispenserDrop(Vector3.zero);
				yield return (object)new WaitForSeconds(0.1f);
			}
		}

		[Command("weapons", "spawns a number of weapons", CommandFlags.HostOnly | CommandFlags.ExplorationOnly | CommandFlags.IngameOnly)]
		public static void Weapons(string weaponName, int count)
		{
			//IL_0025: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			if (WeaponLoader.TryGetWeapon(weaponName, out var prefab))
			{
				Transform transform = ((Component)Settings.Instance.localPlayer.playerPickupScript).transform;
				for (int i = 0; i < count; i++)
				{
					GameObject gameObject = ((Component)Object.Instantiate<Weapon>(prefab, transform.position, transform.rotation)).gameObject;
					InstanceFinder.ServerManager.Spawn(gameObject, (NetworkConnection)null);
					gameObject.GetComponent<ItemBehaviour>().DispenserDrop(Vector3.zero);
				}
				return;
			}
			throw new CommandException("No weapon found with name " + weaponName);
		}

		[Command("clearweapons", "removes all spawned weapons in the scene", CommandFlags.HostOnly | CommandFlags.ExplorationOnly | CommandFlags.IngameOnly)]
		public static void ClearWeapons()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			foreach (GameObject item in from w in ((Scene)(ref activeScene)).GetRootGameObjects()
				where Object.op_Implicit((Object)(object)w.GetComponent<Weapon>()) && Object.op_Implicit((Object)(object)w.GetComponent<Rigidbody>())
				select w)
			{
				InstanceFinder.ServerManager.Despawn(item, (DespawnType?)null);
				Object.Destroy((Object)(object)item);
			}
		}

		[Command("fling", "flings you", CommandFlags.ExplorationOnly | CommandFlags.IngameOnly)]
		public static void Fling(int magnitude)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			FirstPersonController localPlayer = Settings.Instance.localPlayer;
			localPlayer.CustomAddForce(((Component)localPlayer.playerCamera).transform.forward, (float)magnitude);
		}
	}
	[CommandCategory("Input")]
	public static class InputCommands
	{
		private static int m_mouseDownFrames;

		private static ButtonControl m_buttonControl;

		[Command("jump", "triggers a jump", CommandFlags.None)]
		public static void Jump()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			PauseManager.Instance.chatting = false;
			Settings.Instance.localPlayer.Jump(default(CallbackContext));
		}

		[Command("click", "triggers a click with the specified mouse button, left by default", CommandFlags.None)]
		public static void Click(int button = 1)
		{
			m_buttonControl = (ButtonControl)(button switch
			{
				1 => Mouse.current.leftButton, 
				2 => Mouse.current.rightButton, 
				3 => Mouse.current.middleButton, 
				4 => Mouse.current.forwardButton, 
				5 => Mouse.current.backButton, 
				_ => throw new CommandException($"invalid mouse button: {button}"), 
			});
			m_mouseDownFrames = 0;
			InputSystem.onBeforeUpdate += QueueMDown;
		}

		private static void QueueMDown()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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)
			InputEventPtr val = default(InputEventPtr);
			NativeArray<byte> val2 = StateEvent.From((InputDevice)(object)Mouse.current, ref val, (Allocator)2);
			try
			{
				InputControlExtensions.WriteValueIntoEvent<float>((InputControl<float>)(object)m_buttonControl, (float)(1 - m_mouseDownFrames), val);
				InputSystem.QueueEvent(val);
			}
			finally
			{
				((IDisposable)val2).Dispose();
			}
			if (++m_mouseDownFrames > 1)
			{
				InputSystem.onBeforeUpdate -= QueueMDown;
			}
		}
	}
	[CommandCategory("Utility")]
	public static class UtilityCommands
	{
		private static CommandFlags[] m_allFlags = (CommandFlags[])Enum.GetValues(typeof(CommandFlags));

		[Command("echo", "outputs its input", CommandFlags.None)]
		public static string Echo(string input)
		{
			return input;
		}

		[Command("eval", "evaluates its input as a command", CommandFlags.None)]
		public static void Eval(string input)
		{
			Evaluator.Evaluate(input);
		}

		[Command("repeat", "executes a command a specified number of times", CommandFlags.None)]
		public static void Repeat(string command, int n)
		{
			for (int i = 0; i < n; i++)
			{
				Evaluator.Evaluate(command);
			}
		}

		[Command("concat", "concatenates two strings", CommandFlags.None)]
		public static string Concat(string first, string second)
		{
			return first + second;
		}

		[Command("add", "adds the provided numbers", CommandFlags.None)]
		public static float Add(float first, float second)
		{
			return first + second;
		}

		[Command("subtract", "subtracts the second number from the first", CommandFlags.None)]
		public static float Subtract(float first, float second)
		{
			return first - second;
		}

		[Command("rsubtract", "subtracts the first number from the second", CommandFlags.None)]
		public static float RSubtract(float first, float second)
		{
			return second - first;
		}

		[Command("multiply", "multiplies the provided numbers", CommandFlags.None)]
		public static float Multiply(float first, float second)
		{
			return first * second;
		}

		[Command("divide", "divides the first number by the second", CommandFlags.None)]
		public static float Divide(float first, float second)
		{
			return first / second;
		}

		[Command("rdivide", "divides the second number by the first", CommandFlags.None)]
		public static float RDivide(float first, float second)
		{
			return second / first;
		}

		[Command("randint", "gets a random int in [min, max) (min inclusive, max exclusive)", CommandFlags.None)]
		public static int RandInt(int minInclusive, int maxExclusive)
		{
			return Random.Range(minInclusive, maxExclusive);
		}

		[Command("randfloat", "gets a random float in [min, max] (inclusive)", CommandFlags.None)]
		public static float RandFloat(float minInclusive, float maxInclusive)
		{
			return Random.Range(minInclusive, maxInclusive);
		}

		[Command("clear", "clears the chat", CommandFlags.None)]
		[CommandAliases(new string[] { "cls" })]
		public static void Clear()
		{
			ChatPatches.ClearChat();
		}

		[Command("say", "sends a message in chat", CommandFlags.None)]
		public static void Say(string message)
		{
			ChatPatches.SendChatMessage(ProfanityFilterProvider.Filter.CensorString(message));
		}

		[Command("help", "prints command info", CommandFlags.None)]
		[CommandAliases(new string[] { "h" })]
		public static string Help(string commandOrCategoryName = "")
		{
			StringBuilder stringBuilder = new StringBuilder();
			if (commandOrCategoryName != string.Empty)
			{
				if (CommandRegistry.TryGet(commandOrCategoryName, out var command))
				{
					stringBuilder.AppendHelpTextForCommand(command);
				}
				else
				{
					if (!CommandRegistry.CategoryExists(commandOrCategoryName))
					{
						throw new CommandException("No command or category with the name " + commandOrCategoryName + " found.");
					}
					Command[] array = CommandRegistry.Commands.Values.Where((Command c) => string.Equals(c.categoryName, commandOrCategoryName, StringComparison.InvariantCultureIgnoreCase)).Distinct().ToArray();
					if (array.Length == 0)
					{
						throw new CommandException("No command or category with the name " + commandOrCategoryName + " found.");
					}
					stringBuilder.AppendLine("<u><size=150%><#B4F6B7>" + array[0].categoryName + "</color></size></u>").AppendLine();
					foreach (Command item in array.OrderBy((Command c) => c.name))
					{
						stringBuilder.AppendHelpTextForCommand(item);
						stringBuilder.AppendLine().AppendLine();
					}
				}
			}
			else
			{
				string text = "";
				foreach (Command item2 in (from c in CommandRegistry.Commands.Values
					orderby c.categoryName, c.name
					select c).Distinct())
				{
					if (item2.categoryName != text)
					{
						text = item2.categoryName;
						stringBuilder.AppendLine("<u><size=150%><#B4F6B7>" + item2.categoryName + "</color></size></u>");
						stringBuilder.AppendLine();
					}
					stringBuilder.AppendHelpTextForCommand(item2);
					stringBuilder.AppendLine().AppendLine();
				}
			}
			return stringBuilder.ToString();
		}

		private static void AppendHelpTextForCommand(this StringBuilder builder, Command command)
		{
			if (command.isOverriden)
			{
				builder.Append(SmallText("(overriden) "));
			}
			builder.AppendLine("<u>" + command.name + "</u>");
			builder.AppendLine(command.description);
			builder.Append("aliases: [");
			if (command.aliases.Length == 0)
			{
				builder.Append("none");
			}
			for (int i = 0; i < command.aliases.Length; i++)
			{
				builder.Append(command.aliases[i]);
				if (i < command.aliases.Length - 1)
				{
					builder.Append(", ");
				}
			}
			builder.AppendLine("]");
			builder.Append("parameters: [");
			if (command.maxParameters == 0)
			{
				builder.Append("none");
			}
			else
			{
				for (int j = 0; j < command.maxParameters; j++)
				{
					ParameterInfo parameterInfo = command.parameterInfos[j];
					if (parameterInfo.HasDefaultValue)
					{
						builder.Append(SmallText("(optional) "));
					}
					builder.Append(parameterInfo.Name).Append(": ").Append(parameterInfo.ParameterType.Name.ToLower());
					if (j < command.parameterInfos.Length - 1)
					{
						builder.Append(", ");
					}
				}
			}
			builder.AppendLine("]");
			if (command.flags != 0)
			{
				builder.Append("flags: [");
				for (int k = 0; k < m_allFlags.Length; k++)
				{
					if (m_allFlags[k] != 0 && command.flags.HasFlag(m_allFlags[k]))
					{
						builder.Append(m_allFlags[k]);
						if (k < m_allFlags.Length - 1)
						{
							builder.Append(", ");
						}
					}
				}
				builder.AppendLine("]");
			}
			builder.Append("returns: ").Append((command.method.ReturnType == typeof(void)) ? "none" : command.method.ReturnType.Name.ToLower());
		}

		private static string SmallText(string text)
		{
			return "<alpha=#AA><voffset=0.1em><size=65%>" + text + "</size></voffset><alpha=#FF>";
		}
	}
	[CommandCategory("Settings")]
	public static class SettingsCommands
	{
		private static float PseudoConvarFloat(float value, Func<float> getter, Func<float, float> setter)
		{
			if (value == float.MinValue)
			{
				return getter();
			}
			return setter(value);
		}

		private static int PseudoConvarInt(int value, Func<int> getter, Func<int, int> setter)
		{
			if (value == int.MinValue)
			{
				return getter();
			}
			return setter(value);
		}

		private static float PseudoConvarSetting(float value, string settingName)
		{
			FieldInfo field = typeof(Settings).GetField(settingName);
			Settings instance = Settings.Instance;
			if (value == float.MinValue)
			{
				return (float)field.GetValue(instance);
			}
			field.SetValue(instance, value);
			PlayerPrefs.SetFloat(settingName, value);
			PlayerPrefs.Save();
			return value;
		}

		[Command("maxfps", "changes max fps", CommandFlags.Silent)]
		public static int MaxFps(int fps = int.MinValue)
		{
			return PseudoConvarInt(fps, () => Application.targetFrameRate, (int f) => Application.targetFrameRate = f);
		}

		[Command("fov", "changes fov", CommandFlags.Silent)]
		public static float Fov(float fov = float.MinValue)
		{
			return PseudoConvarSetting(fov, "fovValue");
		}

		[Command("gamma", "changes gamma (brightness)", CommandFlags.Silent)]
		public static float Gamma(float gamma = float.MinValue)
		{
			return PseudoConvarSetting(gamma, "brightness");
		}

		[Command("sensitivity", "changes sensitivity", CommandFlags.Silent)]
		public static float Sensitivity(float sensitivity = float.MinValue)
		{
			return PseudoConvarSetting(sensitivity, "mouseSensitivity");
		}

		[Command("aimsensitivity", "changes aiming sensitivity", CommandFlags.Silent)]
		public static float AimSensitivity(float sensitivity = float.MinValue)
		{
			return PseudoConvarSetting(sensitivity, "mouseAimSensitivity");
		}

		[Command("scopesensitivity", "changes scope sensitivity", CommandFlags.Silent)]
		public static float ScopeSensitivity(float sensitivity = float.MinValue)
		{
			return PseudoConvarSetting(sensitivity, "mouseAimScopeSensitivity");
		}
	}
	internal static class WeaponLoader
	{
		private static Dictionary<string, Weapon> m_weaponPrefabs = new Dictionary<string, Weapon>();

		private static Dictionary<string, string> m_nameRedirects = new Dictionary<string, string>();

		public static void Init()
		{
			Weapon[] array = Resources.LoadAll<Weapon>("RandomWeapons");
			foreach (Weapon val in array)
			{
				string value = ((Object)val).name.ToUpper().Replace(" ", "");
				string key = ((Component)val).GetComponent<ItemBehaviour>().weaponName.ToUpper().Replace(" ", "");
				m_weaponPrefabs.TryAdd(((Object)val).name.ToUpper().Replace(" ", ""), val);
				m_nameRedirects.TryAdd(key, value);
			}
		}

		public static bool TryGetWeapon(string name, out Weapon prefab)
		{
			string key = name.ToUpper().Replace(" ", "");
			if (!m_weaponPrefabs.TryGetValue(key, out prefab))
			{
				if (m_nameRedirects.TryGetValue(key, out var value))
				{
					return m_weaponPrefabs.TryGetValue(value, out prefab);
				}
				return false;
			}
			return true;
		}

		public static Weapon RandomWeapon()
		{
			return Utils.RandomValues(m_weaponPrefabs).Take(1).First();
		}

		public static Weapon[] RandomWeapons(int count)
		{
			return Utils.RandomValues(m_weaponPrefabs).Take(count).ToArray();
		}
	}
}
namespace ChatCommands.Attributes
{
	[AttributeUsage(AttributeTargets.Method)]
	public class CommandAliasesAttribute : Attribute
	{
		public readonly string[] aliases;

		public CommandAliasesAttribute(params string[] aliases)
		{
			this.aliases = aliases;
			base..ctor();
		}
	}
	[AttributeUsage(AttributeTargets.Method)]
	public class CommandAttribute : Attribute
	{
		public readonly string name;

		public readonly string description;

		public readonly CommandFlags flags;

		public CommandAttribute(string name, string description, CommandFlags flags = CommandFlags.None)
		{
			this.name = name;
			this.description = description;
			this.flags = flags;
			base..ctor();
		}
	}
	[AttributeUsage(AttributeTargets.Class)]
	public class CommandCategoryAttribute : Attribute
	{
		public readonly string name;

		public CommandCategoryAttribute(string name)
		{
			this.name = name;
			base..ctor();
		}
	}
	[AttributeUsage(AttributeTargets.Method)]
	public class CommandOverrideAttribute : Attribute
	{
		public readonly int priority;

		public CommandOverrideAttribute(int priority = int.MaxValue)
		{
			this.priority = priority;
			base..ctor();
		}
	}
}