Decompiled source of Chat Commands Manager v0.0.1

OutwardChatCommandsManager.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using OutwardChatCommandsManager.Commands;
using OutwardChatCommandsManager.Events;
using OutwardChatCommandsManager.Managers;
using OutwardChatCommandsManager.Utility;
using OutwardChatCommandsManager.Utility.Data;
using OutwardChatCommandsManager.Utility.Data.Executors;
using OutwardChatCommandsManager.Utility.Data.Interfaces;
using OutwardChatCommandsManager.Utility.Data.Serialization;
using OutwardChatCommandsManager.Utility.Enums;
using OutwardChatCommandsManager.Utility.Helpers;
using OutwardModsCommunicator.EventBus;
using OutwardModsCommunicator.Managers;
using SideLoader;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("OutwardChatCommandsManager")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OutwardChatCommandsManager")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("c5450fe0-edcf-483f-b9ea-4b1ef9d36da7")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace OutwardChatCommandsManager
{
	[BepInPlugin("gymmed.chat_commands_manager", "Chat Commands Manager", "0.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class OCCM : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(ResourcesPrefabManager), "Load")]
		public class ResourcesPrefabManager_Load
		{
			private static void Postfix(ResourcesPrefabManager __instance)
			{
				foreach (KeyValuePair<ManagerChatCommands, ChatCommand> command in ManagerChatCommandsHelper.Commands)
				{
					ChatCommandsManager.Instance.AddChatCommand(command.Value);
				}
			}
		}

		public const string GUID = "gymmed.chat_commands_manager";

		public const string NAME = "Chat Commands Manager";

		public const string VERSION = "0.0.1";

		public static string prefix = "[Chat-Commands-Manager]";

		public const string EVENTS_LISTENER_GUID = "gymmed.chat_commands_manager_*";

		public const string COMMAND_KEY = "Execute last/locked command";

		internal static ManualLogSource Log;

		public static ConfigEntry<int> HistorySize;

		internal void Awake()
		{
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			LogMessage("Hello world from Chat Commands Manager 0.0.1!");
			HistorySize = ((BaseUnityPlugin)this).Config.Bind<int>("Commands History", "HistorySize", 10, "How many previously typed commands should be kept in history?");
			HistorySize.SettingChanged += delegate
			{
				ChatCommandsManager.History.MaxSize = HistorySize.Value;
			};
			int length = Enum.GetValues(typeof(HotkeySlots)).Length;
			for (int i = 0; i < length; i++)
			{
				CustomKeybindings.AddAction("Execute last/locked command " + (i + 1), (KeybindingsCategory)0, (ControlType)2, (InputType)1);
			}
			new Harmony("gymmed.chat_commands_manager").PatchAll();
			EventBusRegister.RegisterEvents();
			EventBusSubscriber.AddSubscribers();
			SL.OnSceneLoaded += delegate
			{
				Character firstLocalCharacter = CharacterManager.Instance.GetFirstLocalCharacter();
				if ((Object)(object)firstLocalCharacter != (Object)null)
				{
					ChatCommandsSerializer.Instance.LoadManagerState(firstLocalCharacter);
				}
				Character secondLocalCharacter = CharacterManager.Instance.GetSecondLocalCharacter();
				if ((Object)(object)secondLocalCharacter != (Object)null)
				{
					ChatCommandsSerializer.Instance.LoadManagerState(secondLocalCharacter);
				}
			};
		}

		internal void Update()
		{
			int length = Enum.GetValues(typeof(HotkeySlots)).Length;
			int num = 0;
			for (int i = 0; i < length; i++)
			{
				if (!HotkeySlotsHelper.TryGet((HotkeySlots)i, out var invocation))
				{
					num++;
				}
				if (!CustomKeybindings.GetKeyDown("Execute last/locked command " + (i + 1)))
				{
					continue;
				}
				if (invocation != null)
				{
					invocation.TriggerFunction();
					continue;
				}
				IReadOnlyList<ChatCommandInvocation> items = ChatCommandsManager.History.Items;
				int num2 = items.Count();
				if (num2 > num)
				{
					ChatCommandInvocation chatCommandInvocation = items[num2 - num];
					if (chatCommandInvocation != null)
					{
						chatCommandInvocation.TriggerFunction();
						continue;
					}
				}
				CharacterHelpers.BroadCastChatMessageToLocalCharacters($"Could not retrieve command for {i + 1} hotkey.", ChatLogStatus.Warning);
			}
		}

		public static void LogMessage(string message)
		{
			Log.LogMessage((object)(prefix + " " + message));
		}

		public static void LogSL(string message)
		{
			SL.Log(prefix + " " + message);
		}

		public static string GetProjectLocation()
		{
			return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
		}
	}
}
namespace OutwardChatCommandsManager.Utility
{
	internal class ChatPanelHistoryState
	{
		public int HistoryIndex = -1;

		public string CachedLiveInput;
	}
}
namespace OutwardChatCommandsManager.Utility.Helpers
{
	public static class CharacterHelpers
	{
		public static void BroadCastChatMessageToLocalCharacters(string message, ChatLogStatus status = ChatLogStatus.Info)
		{
			Character firstLocalCharacter = CharacterManager.Instance.GetFirstLocalCharacter();
			object obj;
			if (firstLocalCharacter == null)
			{
				obj = null;
			}
			else
			{
				CharacterUI characterUI = firstLocalCharacter.CharacterUI;
				obj = ((characterUI != null) ? characterUI.ChatPanel : null);
			}
			if ((Object)obj != (Object)null)
			{
				ChatHelpers.SendChatLog(firstLocalCharacter.CharacterUI.ChatPanel, message, status);
			}
			Character secondLocalCharacter = CharacterManager.Instance.GetSecondLocalCharacter();
			object obj2;
			if (secondLocalCharacter == null)
			{
				obj2 = null;
			}
			else
			{
				CharacterUI characterUI2 = secondLocalCharacter.CharacterUI;
				obj2 = ((characterUI2 != null) ? characterUI2.ChatPanel : null);
			}
			if ((Object)obj2 != (Object)null)
			{
				ChatHelpers.SendChatLog(secondLocalCharacter.CharacterUI.ChatPanel, message, status);
			}
		}
	}
	public static class ChatHelpers
	{
		public static void SendChatLog(ChatPanel panel, string message, ChatLogStatus status = ChatLogStatus.Info)
		{
			panel.ChatMessageReceived("System", ChatLogStatusHelper.GetChatLogText(message, status));
		}

		public static void LogAllCommandsToChat(Character character)
		{
			object panel;
			if (character == null)
			{
				panel = null;
			}
			else
			{
				CharacterUI characterUI = character.CharacterUI;
				panel = ((characterUI != null) ? characterUI.ChatPanel : null);
			}
			SendChatLog((ChatPanel)panel, "Providing a list of all registered commands by Chat Commands Manager Mod:", ChatLogStatus.Warning);
			ChatLogAllChatCommands(character);
		}

		public static void ChatLogAllChatCommands(Character character)
		{
			object obj;
			if (character == null)
			{
				obj = null;
			}
			else
			{
				CharacterUI characterUI = character.CharacterUI;
				obj = ((characterUI != null) ? characterUI.ChatPanel : null);
			}
			ChatPanel panel = (ChatPanel)obj;
			foreach (KeyValuePair<OriginalChatCommands, OriginalChatCommand> command in OriginalChatCommandsHelper.Commands)
			{
				SendChatLog(panel, command.Value.Name, ChatLogStatus.Success);
			}
			foreach (KeyValuePair<string, ChatCommand> chatCommand in ChatCommandsManager.ChatCommands)
			{
				SendChatLog(panel, chatCommand.Value.Name, ChatLogStatus.Success);
			}
			SendChatLog(panel, $"Total {OriginalChatCommandsHelper.Commands.Count() + ChatCommandsManager.ChatCommands.Count()} commands. {OriginalChatCommandsHelper.Commands.Count()} original commands. {ChatCommandsManager.ChatCommands.Count()} added commands.");
			SendChatLog(panel, "For more info use:\"/help\"");
		}

		public static void ShowCommandsHistory(Character character, Dictionary<string, string> arguments)
		{
			object obj;
			if (character == null)
			{
				obj = null;
			}
			else
			{
				CharacterUI characterUI = character.CharacterUI;
				obj = ((characterUI != null) ? characterUI.ChatPanel : null);
			}
			ChatPanel val = (ChatPanel)obj;
			if ((Object)(object)val == (Object)null)
			{
				OCCM.LogMessage("ChatHelpers@ShowCommandsHistory Tried to log chat command to missing chatPanel.");
				return;
			}
			SendChatLog(val, "History of chat commands invocations:");
			arguments.TryGetValue("detailed", out var value);
			if (!string.IsNullOrWhiteSpace(value))
			{
				foreach (ChatCommandInvocation item in ChatCommandsManager.History.Items)
				{
					SendChatLog(val, "");
					ChatLogChatCommand(val, item.Command);
					ChatLogChatCommandArguments(val, item.Arguments);
				}
				return;
			}
			string text = null;
			foreach (ChatCommandInvocation item2 in ChatCommandsManager.History.Items)
			{
				text = item2.Command?.Name;
				if (string.IsNullOrEmpty(text))
				{
					text = "null";
				}
				SendChatLog(val, text, ChatLogStatus.Success);
			}
		}

		public static void LockKey(Character character, Dictionary<string, string> arguments)
		{
			object obj;
			if (character == null)
			{
				obj = null;
			}
			else
			{
				CharacterUI characterUI = character.CharacterUI;
				obj = ((characterUI != null) ? characterUI.ChatPanel : null);
			}
			ChatPanel val = (ChatPanel)obj;
			if ((Object)(object)val == (Object)null)
			{
				OCCM.LogMessage("ChatHelpers@ChatLogChatCommand Tried to log chat command to missing chatPanel.");
				return;
			}
			arguments.TryGetValue("index", out var value);
			if (string.IsNullOrWhiteSpace(value))
			{
				value = "1";
			}
			string value2;
			ChatCommandInvocation invocation;
			if (!int.TryParse(value, out var result))
			{
				int num = 1;
				int length = Enum.GetValues(typeof(HotkeySlots)).Length;
				SendChatLog(val, $"Error: \"Provided incorrect {value} lock key index. Can use from {num} to {length}. " + "Ex.: \"/lockKey 1\"\"", ChatLogStatus.Error);
			}
			else if (!arguments.TryGetValue("show", out value2) || string.IsNullOrWhiteSpace(value2))
			{
				IReadOnlyList<ChatCommandInvocation> items = ChatCommandsManager.History.Items;
				int num2 = items.Count();
				if (num2 < 2)
				{
					SendChatLog(val, "No previous command to lock to key.", ChatLogStatus.Warning);
					return;
				}
				ChatCommandInvocation chatCommandInvocation = items[num2 - 2];
				HotkeySlotsHelper.Lock((HotkeySlots)(result - 1), chatCommandInvocation);
				SendChatLog(val, $"Successfully assigned lock key {result} to {chatCommandInvocation.Command?.Name}.", ChatLogStatus.Success);
			}
			else if (!string.Equals(value2, "show", StringComparison.OrdinalIgnoreCase))
			{
				SendChatLog(val, "Provided argument \"" + value2 + "\" is incorrect! It can only be \"show\" or left empty.", ChatLogStatus.Error);
			}
			else if (!HotkeySlotsHelper.TryGet((HotkeySlots)(result - 1), out invocation))
			{
				SendChatLog(val, "Your slot key " + value + " doesn't have assigned chat command.", ChatLogStatus.Warning);
			}
			else
			{
				SendChatLog(val, $"Lock key {result} was assigned to {invocation.Command.Name} chat command with arguments:");
				ChatLogChatCommandArguments(val, invocation.Arguments);
			}
		}

		public static void ReleaseKey(Character character, Dictionary<string, string> arguments)
		{
			object obj;
			if (character == null)
			{
				obj = null;
			}
			else
			{
				CharacterUI characterUI = character.CharacterUI;
				obj = ((characterUI != null) ? characterUI.ChatPanel : null);
			}
			ChatPanel val = (ChatPanel)obj;
			if ((Object)(object)val == (Object)null)
			{
				OCCM.LogMessage("ChatHelpers@ChatLogChatCommand Tried to log chat command to missing chatPanel.");
				return;
			}
			arguments.TryGetValue("index", out var value);
			if (string.IsNullOrWhiteSpace(value))
			{
				value = "1";
			}
			if (!int.TryParse(value, out var result))
			{
				int num = 1;
				int length = Enum.GetValues(typeof(HotkeySlots)).Length;
				SendChatLog(val, $"Error: \"Provided incorrect {result} lock key index. Can use from {num} to {length}. " + "Ex.: \"/lockKey 1\"\"", ChatLogStatus.Error);
				return;
			}
			HotkeySlots slot = (HotkeySlots)(result - 1);
			if (!HotkeySlotsHelper.TryGet(slot, out var invocation))
			{
				SendChatLog(val, "Your slot key " + value + " doesn't have assigned chat command.", ChatLogStatus.Warning);
				return;
			}
			HotkeySlotsHelper.Release(slot);
			SendChatLog(val, $"Lock key {result} was released from {invocation.Command.Name} chat command with arguments:", ChatLogStatus.Success);
			ChatLogChatCommandArguments(val, invocation.Arguments);
		}

		public static void ChatLogChatCommand(Character character, Dictionary<string, string> arguments)
		{
			object obj;
			if (character == null)
			{
				obj = null;
			}
			else
			{
				CharacterUI characterUI = character.CharacterUI;
				obj = ((characterUI != null) ? characterUI.ChatPanel : null);
			}
			ChatPanel val = (ChatPanel)obj;
			if ((Object)(object)val == (Object)null)
			{
				OCCM.LogMessage("ChatHelpers@ChatLogChatCommand Tried to log chat command to missing chatPanel.");
				return;
			}
			arguments.TryGetValue("command", out var value);
			if (string.IsNullOrWhiteSpace(value))
			{
				if (!ChatCommandsManager.ChatCommands.TryGetValue("help", out var value2))
				{
					SendChatLog(val, "help command not found!", ChatLogStatus.Error);
					return;
				}
				SendChatLog(val, "Help command triggered!");
				ChatLogChatCommand(val, value2);
				return;
			}
			SendChatLog(val, "Help command triggered!");
			if (!ChatCommandsManager.ChatCommands.TryGetValue(value, out var value3))
			{
				if (!OriginalChatCommandsHelper.CommandsByName.TryGetValue(value, out var value4))
				{
					SendChatLog(val, value + " command not found! Are you sure it exist? Type:\"/commands\"", ChatLogStatus.Error);
				}
				else
				{
					ChatLogChatCommand(val, value4);
				}
			}
			else
			{
				ChatLogChatCommand(val, value3);
			}
		}

		public static void ChatLogChatCommand(ChatPanel panel, IChatCommand chatCommand)
		{
			if ((Object)(object)panel == (Object)null)
			{
				OCCM.LogMessage("ChatHelpers@ChatLogChatCommand Tried to log chat command to missing chatPanel.");
				return;
			}
			SendChatLog(panel, "Command Name: " + chatCommand.Name, ChatLogStatus.Success);
			SendChatLog(panel, "Command Description: " + chatCommand.Description, ChatLogStatus.Success);
			SendChatLog(panel, "Command Parameters: ", ChatLogStatus.Success);
			ChatLogChatCommandParameters(panel, chatCommand);
			SendChatLog(panel, $"Command Is Cheat: {chatCommand.IsCheat}", ChatLogStatus.Success);
			SendChatLog(panel, $"Command Require Debug Mode: {chatCommand.RequireDebugMode}", ChatLogStatus.Success);
		}

		public static void ChatLogChatCommandParameters(ChatPanel panel, IChatCommand chatCommand)
		{
			foreach (KeyValuePair<string, (string, string)> parameter in chatCommand.Parameters)
			{
				string text = (string.IsNullOrEmpty(parameter.Value.Item2) ? "null" : parameter.Value.Item2);
				SendChatLog(panel, "-parameter name: " + parameter.Key + " => default value: " + text + "\n-description: " + parameter.Value.Item1, ChatLogStatus.Success);
			}
		}

		public static void ChatLogChatCommandArguments(ChatPanel panel, Dictionary<string, string> arguments)
		{
			string text = "";
			foreach (KeyValuePair<string, string> argument in arguments)
			{
				text = ((!string.IsNullOrWhiteSpace(argument.Value)) ? ("-parameter name: " + argument.Key + " => argument value: " + argument.Value) : ("-parameter name: " + argument.Key));
				SendChatLog(panel, text, ChatLogStatus.Success);
			}
		}

		public static ChatPanel GetChatPanel(Character character)
		{
			if (character == null)
			{
				return null;
			}
			CharacterUI characterUI = character.CharacterUI;
			if (characterUI == null)
			{
				return null;
			}
			return characterUI.ChatPanel;
		}

		public static bool TryGetValidCommand(string message, out IChatCommand command)
		{
			command = null;
			if (message.StartsWith("/"))
			{
				MessageCommand messageCommand = new MessageCommand(message);
				string key = messageCommand.Command.Substring(1);
				IChatCommand chatCommand = null;
				if (!ChatCommandsManager.ChatCommands.TryGetValue(key, out var value))
				{
					if (!OriginalChatCommandsHelper.CommandsByName.TryGetValue(key, out var value2))
					{
						return false;
					}
					chatCommand = value2;
				}
				else
				{
					chatCommand = value;
				}
				if (chatCommand.RequireDebugMode && !Global.CheatsEnabled)
				{
					return false;
				}
				if (messageCommand.Arguments.Count > chatCommand.Parameters.Count)
				{
					OCCM.LogMessage("Command " + chatCommand.Name + " retrieved too many arguments from user.");
					return false;
				}
				command = chatCommand;
				return true;
			}
			return false;
		}

		public static bool HasValidCommand(string message)
		{
			if (message.StartsWith("/"))
			{
				MessageCommand messageCommand = new MessageCommand(message);
				if (!ChatCommandsManager.ChatCommands.TryGetValue(messageCommand.Command.Substring(1), out var value))
				{
					return false;
				}
				if (messageCommand.Arguments.Count > value.Parameters.Count)
				{
					OCCM.LogMessage("Command " + value.Name + " retrieved too many arguments from user.");
					return false;
				}
				return true;
			}
			return false;
		}

		public static List<string> Tokenize(string input)
		{
			List<string> list = new List<string>();
			StringBuilder stringBuilder = new StringBuilder();
			bool flag = false;
			char c = '\0';
			bool flag2 = false;
			foreach (char c2 in input)
			{
				if (flag2)
				{
					stringBuilder.Append(c2);
					flag2 = false;
				}
				else if (c2 == '\\')
				{
					flag2 = true;
				}
				else if (flag)
				{
					if (c2 == c)
					{
						flag = false;
					}
					else
					{
						stringBuilder.Append(c2);
					}
				}
				else if (c2 == '"' || c2 == '\'')
				{
					flag = true;
					c = c2;
				}
				else if (char.IsWhiteSpace(c2))
				{
					if (stringBuilder.Length > 0)
					{
						list.Add(stringBuilder.ToString());
						stringBuilder.Clear();
					}
				}
				else
				{
					stringBuilder.Append(c2);
				}
			}
			if (stringBuilder.Length > 0)
			{
				list.Add(stringBuilder.ToString());
			}
			return list;
		}

		public static Dictionary<string, string> GetArgumentsForCommand(string message, IChatCommand command)
		{
			return GetArguments(GetArgumentsFromMessage(message), command.Parameters);
		}

		public static List<string> GetArgumentsFromMessage(string message)
		{
			return Tokenize(message).Skip(1).ToList();
		}

		public static Dictionary<string, string> GetArguments(List<string> arguments, Dictionary<string, (string description, string defaultValue)> parameters)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			List<string> list = new List<string>(arguments);
			Dictionary<string, (string, string)> dictionary2 = new Dictionary<string, (string, string)>(parameters);
			for (int num = list.Count - 1; num >= 0; num--)
			{
				string text = list[num];
				if (text.StartsWith("--") && text.Contains("="))
				{
					int num2 = text.IndexOf('=');
					string key = text.Substring(2, num2 - 2);
					string value = text.Substring(num2 + 1);
					dictionary[key] = value;
					list.RemoveAt(num);
					dictionary2.Remove(key);
				}
			}
			int num3 = 0;
			foreach (KeyValuePair<string, (string, string)> item in dictionary2)
			{
				string key2 = item.Key;
				if (num3 < list.Count)
				{
					dictionary[key2] = list[num3];
				}
				else
				{
					dictionary[key2] = item.Value.Item2;
				}
				num3++;
			}
			return dictionary;
		}
	}
}
namespace OutwardChatCommandsManager.Utility.Enums
{
	public enum ChatLogStatus
	{
		Info,
		Success,
		Warning,
		Error
	}
	public static class ChatLogStatusHelper
	{
		public static string GetChatLogText(string message, ChatLogStatus status = ChatLogStatus.Info)
		{
			//IL_0019: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			return status switch
			{
				ChatLogStatus.Success => Global.SetTextColor(message, Global.LIGHT_GREEN), 
				ChatLogStatus.Warning => Global.SetTextColor(message, Global.LIGHT_ORANGE), 
				ChatLogStatus.Error => "<color=#" + UnityEngineExtensions.ToHex(Global.LIGHT_RED) + ">" + message + "</color>", 
				_ => message, 
			};
		}
	}
	public enum CommandExecutors
	{
		OriginalCommand,
		ChatCommand
	}
	public static class CommandExecutorsHelper
	{
		public static Dictionary<CommandExecutors, ICommandExecutor> Executors(Character character)
		{
			object obj;
			if (character == null)
			{
				obj = null;
			}
			else
			{
				CharacterUI characterUI = character.CharacterUI;
				obj = ((characterUI != null) ? characterUI.ChatPanel : null);
			}
			if ((Object)obj == (Object)null)
			{
				OCCM.LogMessage("CommandExecutorsHelper@Executors Chracter panel is missing!");
				return null;
			}
			return new Dictionary<CommandExecutors, ICommandExecutor>
			{
				{
					CommandExecutors.OriginalCommand,
					new GameChatForwardExecutor(character.CharacterUI.ChatPanel)
				},
				{
					CommandExecutors.ChatCommand,
					new ManagedCommandExecutor()
				}
			};
		}

		public static ICommandExecutor GetCommandExecutor(CommandExecutors executor, Character character)
		{
			Dictionary<CommandExecutors, ICommandExecutor> dictionary = Executors(character);
			if (dictionary == null)
			{
				return new ManagedCommandExecutor();
			}
			return dictionary[executor];
		}
	}
	public enum EventRegistryParams
	{
		CommandName,
		CommandParameters,
		CommandAction,
		IsCheatCommand,
		CommandDescription,
		CommandRequiresDebugMode
	}
	public static class EventRegistryParamsHelper
	{
		private static readonly Dictionary<EventRegistryParams, (string key, Type type, string description)> _registry = new Dictionary<EventRegistryParams, (string, Type, string)>
		{
			[EventRegistryParams.CommandName] = ("command", typeof(string), "Required. The text players type in chat (e.g. \"/command\") to trigger your handler."),
			[EventRegistryParams.CommandParameters] = ("parameters", typeof(Dictionary<string, (string, string)>), "Optional. Parameters with name and (description, default value) provided as dictionary."),
			[EventRegistryParams.CommandAction] = ("function", typeof(Action<Character, Dictionary<string, string>>), "Required. The method to execute when the command is triggered. Character is the command caller and Dictionary stores parameter and argument(value)."),
			[EventRegistryParams.IsCheatCommand] = ("isCheatCommand", typeof(bool), "Optional. Default false. Determines if player game will be saved after triggering your command."),
			[EventRegistryParams.CommandDescription] = ("description", typeof(string), "Optional. Default null. Provides description of command for users."),
			[EventRegistryParams.CommandRequiresDebugMode] = ("debugMode", typeof(bool), "Optional. Default false. Determines if command requires debug mode to work.")
		};

		public static (string key, Type type, string description) Get(EventRegistryParams param)
		{
			return _registry[param];
		}

		public static (string key, Type type, string description)[] Combine(params object[] items)
		{
			List<(string, Type, string)> list = new List<(string, Type, string)>();
			foreach (object obj in items)
			{
				if (obj is (string, Type, string) item)
				{
					list.Add(item);
					continue;
				}
				if (obj is (string, Type, string)[] collection)
				{
					list.AddRange(collection);
					continue;
				}
				throw new ArgumentException("Unsupported item type: " + obj?.GetType().FullName);
			}
			return list.ToArray();
		}
	}
	public enum HotkeySlots
	{
		Slot1,
		Slot2,
		Slot3
	}
	public static class HotkeySlotsHelper
	{
		private static readonly Dictionary<HotkeySlots, ChatCommandInvocation> _locked = new Dictionary<HotkeySlots, ChatCommandInvocation>();

		public static Dictionary<HotkeySlots, ChatCommandInvocation> Locked => _locked;

		public static void Lock(HotkeySlots slot, ChatCommandInvocation invocation)
		{
			_locked[slot] = invocation;
		}

		public static void Release(HotkeySlots slot)
		{
			_locked.Remove(slot);
		}

		public static bool TryGet(HotkeySlots slot, out ChatCommandInvocation invocation)
		{
			return _locked.TryGetValue(slot, out invocation);
		}
	}
	public enum ManagerChatCommands
	{
		Help,
		Commands,
		LockKey,
		ReleaseKey,
		ShowCommandsHistory
	}
	public static class ManagerChatCommandsHelper
	{
		public static readonly Dictionary<ManagerChatCommands, ChatCommand> Commands = new Dictionary<ManagerChatCommands, ChatCommand>
		{
			{
				ManagerChatCommands.Help,
				new ChatCommand("help", new Dictionary<string, (string, string)> { 
				{
					"command",
					("name of command like \"toggleDebug\".", "")
				} }, "Provides details about command. Ex.:\"/help toggleDebug\".", isCheat: false, delegate(Character character, Dictionary<string, string> parameters)
				{
					ChatHelpers.ChatLogChatCommand(character, parameters);
				})
			},
			{
				ManagerChatCommands.Commands,
				new ChatCommand("commands", new Dictionary<string, (string, string)>(), "Provides details about command. Ex.:\"/help toggleDebug\".", isCheat: false, delegate(Character character, Dictionary<string, string> parameters)
				{
					ChatHelpers.LogAllCommandsToChat(character);
				})
			},
			{
				ManagerChatCommands.LockKey,
				new ChatCommand("lockKey", new Dictionary<string, (string, string)>
				{
					{
						"index",
						("Required. Key number example \"1\".", "1")
					},
					{
						"show",
						("Optional. Shows which command is already locked instead of locking it. Ex.:\".lockKey 1 show\".", "")
					}
				}, "Locks last command with arguments to provided Chat Commands Manager key. Ex.:\"/lockKey 1\".", isCheat: false, delegate(Character character, Dictionary<string, string> parameters)
				{
					ChatHelpers.LockKey(character, parameters);
				})
			},
			{
				ManagerChatCommands.ReleaseKey,
				new ChatCommand("releaseKey", new Dictionary<string, (string, string)> { 
				{
					"index",
					("Required. Key number example \"1\".", "1")
				} }, "Releases command from provided Chat Commands Manager key. Ex.:\"/releaseKey 1\".", isCheat: false, delegate(Character character, Dictionary<string, string> parameters)
				{
					ChatHelpers.ReleaseKey(character, parameters);
				})
			},
			{
				ManagerChatCommands.ShowCommandsHistory,
				new ChatCommand("history", new Dictionary<string, (string, string)> { 
				{
					"detailed",
					("Optional. Provides commands with arguments used example \"/history detailed\".", "")
				} }, "Show used commands history. Ex.:\"/history\".", isCheat: false, delegate(Character character, Dictionary<string, string> parameters)
				{
					ChatHelpers.ShowCommandsHistory(character, parameters);
				})
			}
		};
	}
	public enum OriginalChatCommands
	{
		ToggleDebug,
		Teleport,
		Defeat,
		Weather
	}
	public static class OriginalChatCommandsHelper
	{
		public static readonly Dictionary<OriginalChatCommands, OriginalChatCommand> Commands = new Dictionary<OriginalChatCommands, OriginalChatCommand>
		{
			{
				OriginalChatCommands.ToggleDebug,
				new OriginalChatCommand("toggleDebug", new Dictionary<string, (string, string)> { 
				{
					"status",
					("Enable or disable debug mode. Can be provided as on or off, everything else is ignored.", null)
				} }, "Turns on Debug mode. Ex.:\"/toggleDebug on\"", isCheat: true, requireDebugMode: false)
			},
			{
				OriginalChatCommands.Teleport,
				new OriginalChatCommand("tp", new Dictionary<string, (string, string)> { 
				{
					"position",
					("Teleport position.", null)
				} }, "Tries to teleport player to provided position. Ex.:\"/tp 12.5,0,-4\"", isCheat: true, requireDebugMode: true)
			},
			{
				OriginalChatCommands.Defeat,
				new OriginalChatCommand("defeat", new Dictionary<string, (string, string)>
				{
					{
						"subcommand",
						("One of: \nlist - provides list of deafeats | \nforce - forces defeat scenario | \nclear - restores normal defeat behaviour.", null)
					},
					{
						"id",
						("Defeat ID (required for 'force')", "")
					}
				}, "Defeat scenario managing command. Ex.:\"/defeat list\"", isCheat: true, requireDebugMode: true)
			},
			{
				OriginalChatCommands.Weather,
				new OriginalChatCommand("weather", new Dictionary<string, (string, string)>
				{
					{
						"id",
						("Weather ID index(0..n)", "0")
					},
					{
						"instant",
						("If true, apply change immediately (true/false)", "true")
					}
				}, "Checks/sets the weather. Ex.:\"/weather 1 true\"", isCheat: true, requireDebugMode: true)
			}
		};

		public static readonly Dictionary<string, OriginalChatCommand> CommandsByName = Commands.Values.ToDictionary<OriginalChatCommand, string, OriginalChatCommand>((OriginalChatCommand c) => c.Name, (OriginalChatCommand c) => c, StringComparer.InvariantCultureIgnoreCase);
	}
}
namespace OutwardChatCommandsManager.Utility.Data
{
	public class ChatCommandHistory
	{
		private int _maxSize;

		private readonly List<ChatCommandInvocation> _items = new List<ChatCommandInvocation>();

		public IReadOnlyList<ChatCommandInvocation> Items => _items;

		public int MaxSize
		{
			get
			{
				return _maxSize;
			}
			set
			{
				_maxSize = value;
			}
		}

		public ChatCommandHistory(int maxSize = 10)
		{
			MaxSize = maxSize;
		}

		public ChatCommandHistory()
		{
			MaxSize = OCCM.HistorySize.Value;
		}

		public ChatCommandHistory(List<ChatCommandInvocation> oldHistory)
		{
			MaxSize = OCCM.HistorySize.Value;
			_items = new List<ChatCommandInvocation>(oldHistory);
		}

		public void Add(ChatCommandInvocation invocation)
		{
			if (_items.Count >= MaxSize)
			{
				_items.RemoveAt(0);
			}
			_items.Add(invocation);
		}

		public ChatCommandInvocation GetFirst()
		{
			if (_items.Count <= 0)
			{
				return null;
			}
			return _items.First();
		}

		public ChatCommandInvocation GetLast()
		{
			if (_items.Count <= 0)
			{
				return null;
			}
			return _items.Last();
		}

		public ChatCommandInvocation ElementAt(int index)
		{
			if (_items.Count <= index || index <= -1)
			{
				return null;
			}
			return _items.ElementAt(index);
		}

		public int FindPreviousUnique(int start)
		{
			if (start < 1 || start > Items.Count - 1)
			{
				return -1;
			}
			if (start <= 0 || start >= Items.Count)
			{
				return start;
			}
			string message = Items[start].Message;
			for (int num = start - 1; num >= 0; num--)
			{
				if (Items[num].Message != message)
				{
					return num;
				}
			}
			return start;
		}
	}
	public class ChatCommandInvocation
	{
		private Character _character;

		private IChatCommand _command;

		private Dictionary<string, string> _arguments;

		private string _message;

		private ICommandExecutor executor;

		public Character Character
		{
			get
			{
				return _character;
			}
			set
			{
				_character = value;
			}
		}

		public IChatCommand Command
		{
			get
			{
				return _command;
			}
			set
			{
				_command = value;
			}
		}

		public Dictionary<string, string> Arguments
		{
			get
			{
				return _arguments;
			}
			set
			{
				_arguments = value;
			}
		}

		public string Message
		{
			get
			{
				return _message;
			}
			set
			{
				_message = value;
			}
		}

		public ICommandExecutor Executor
		{
			get
			{
				return executor;
			}
			set
			{
				executor = value;
			}
		}

		public ChatCommandInvocation(Character character, IChatCommand command, Dictionary<string, string> arguments, ICommandExecutor executor, string message = null)
		{
			Character = character;
			Command = command;
			Arguments = arguments;
			Message = message;
			Executor = executor;
		}

		public ChatCommandInvocation(Character character, IChatCommand command, ICommandExecutor executor, string message = null)
		{
			Character = character;
			Command = command;
			Message = message;
			Arguments = ChatHelpers.GetArgumentsForCommand(message, command);
			Executor = executor;
		}

		public void TriggerFunction()
		{
			if (Command == null)
			{
				OCCM.LogMessage("ChatCommandInvocation@TriggerFunction doesn't have a command to trigger!");
				return;
			}
			if ((Object)(object)Character == (Object)null)
			{
				OCCM.LogMessage("ChatCommandInvocation@TriggerFunction doesn't have a character triggering command!");
				return;
			}
			if (Arguments == null)
			{
				OCCM.LogMessage("ChatCommandInvocation@TriggerFunction doesn't have provided arguments to trigger command!");
				return;
			}
			ChatCommandsManager.History.Add(this);
			Executor.Execute(this);
		}
	}
	internal class ChatForwardExecutor
	{
	}
}
namespace OutwardChatCommandsManager.Utility.Data.Serialization
{
	public class ArgumentData
	{
		[XmlElement("Parameter")]
		[DefaultValue("")]
		public string Parameter { get; set; } = "";


		[XmlElement("Argument")]
		[DefaultValue("")]
		public string Argument { get; set; } = "";

	}
	public class ChatCommandData
	{
		[XmlElement("Name")]
		[DefaultValue("")]
		public string Name { get; set; } = "";

	}
	public class ChatCommandInvocationData
	{
		[XmlElement("CharacterUID")]
		[DefaultValue(null)]
		public UID CharacterUID { get; set; } = UID.op_Implicit((string)null);


		[XmlElement("Command")]
		[DefaultValue(null)]
		public ChatCommandData Command { get; set; }

		[XmlArray("Arguments")]
		[XmlArrayItem("Argument")]
		[DefaultValue(null)]
		public List<ArgumentData> Arguments { get; set; }

		[XmlElement("Message")]
		[DefaultValue(null)]
		public string Message { get; set; }

		[XmlElement("Executor")]
		[DefaultValue(null)]
		public string ExecutorName { get; set; }

		[XmlIgnore]
		public CommandExecutors? Executor
		{
			get
			{
				if (!string.IsNullOrWhiteSpace(ExecutorName))
				{
					if (!Enum.TryParse<CommandExecutors>(ExecutorName, out var result))
					{
						return null;
					}
					return result;
				}
				return null;
			}
		}
	}
	public class ChatCommandsManagerState
	{
		public List<ChatCommandInvocation> History;

		public Dictionary<HotkeySlots, ChatCommandInvocation> LockedHotKeys;

		public ChatCommandsManagerState(List<ChatCommandInvocation> history = null, Dictionary<HotkeySlots, ChatCommandInvocation> lockedHotKeys = null)
		{
			History = history;
			LockedHotKeys = lockedHotKeys;
		}

		public ChatCommandsManagerState(IReadOnlyList<ChatCommandInvocation> history = null, Dictionary<HotkeySlots, ChatCommandInvocation> lockedHotKeys = null)
		{
			History = history.ToList();
			LockedHotKeys = lockedHotKeys;
		}

		public ChatCommandsManagerState()
		{
			History = null;
			LockedHotKeys = null;
		}
	}
	[XmlRoot("ChatCommandsManager")]
	public class ChatCommandsManagerStateFile
	{
		[XmlArray("History")]
		[XmlArrayItem("ChatCommandInvocation")]
		[DefaultValue(null)]
		public List<ChatCommandInvocationData> History { get; set; }

		[XmlArray("HotkeyBindings")]
		[XmlArrayItem("Hotkey")]
		[DefaultValue(null)]
		public List<HotkeyBindingData> HotkeyBindings { get; set; }
	}
	public class HotkeyBindingData
	{
		[XmlElement("Slot")]
		[DefaultValue(null)]
		public string SlotName { get; set; } = "";


		[XmlElement("Invocation")]
		[DefaultValue(null)]
		public ChatCommandInvocationData Invocation { get; set; }

		[XmlIgnore]
		public HotkeySlots? Slot
		{
			get
			{
				if (!string.IsNullOrWhiteSpace(SlotName))
				{
					if (!Enum.TryParse<HotkeySlots>(SlotName, out var result))
					{
						return null;
					}
					return result;
				}
				return null;
			}
		}
	}
	public class ParameterDefinitionData
	{
		[XmlElement("Name")]
		[DefaultValue("")]
		public string Name { get; set; } = "";


		[XmlElement("Description")]
		[DefaultValue("")]
		public string Description { get; set; } = "";


		[XmlElement("Default")]
		[DefaultValue("")]
		public string DefaultValue { get; set; } = "";

	}
}
namespace OutwardChatCommandsManager.Utility.Data.Interfaces
{
	public interface IChatCommand
	{
		string Name { get; set; }

		Dictionary<string, (string, string)> Parameters { get; set; }

		string Description { get; set; }

		bool IsCheat { get; set; }

		bool RequireDebugMode { get; set; }

		void TriggerFunction(Character character, Dictionary<string, string> Arguments);
	}
	public interface ICommandExecutor
	{
		CommandExecutors ExecutorType { get; }

		void Execute(ChatCommandInvocation invocation);
	}
}
namespace OutwardChatCommandsManager.Utility.Data.Executors
{
	public static class ChatExecutionGuard
	{
		[ThreadStatic]
		public static bool IsForwarding;
	}
	public sealed class GameChatForwardExecutor : ICommandExecutor
	{
		private readonly ChatPanel _panel;

		public CommandExecutors ExecutorType => CommandExecutors.OriginalCommand;

		public GameChatForwardExecutor(ChatPanel panel)
		{
			_panel = panel;
		}

		public void Execute(ChatCommandInvocation invocation)
		{
			ChatExecutionGuard.IsForwarding = true;
			try
			{
				_panel.m_chatEntry.text = invocation.Message;
				_panel.SendChatMessage();
			}
			finally
			{
				ChatExecutionGuard.IsForwarding = false;
			}
		}
	}
	public sealed class ManagedCommandExecutor : ICommandExecutor
	{
		public CommandExecutors ExecutorType => CommandExecutors.ChatCommand;

		public void Execute(ChatCommandInvocation invocation)
		{
			invocation.Command.TriggerFunction(invocation.Character, invocation.Arguments);
		}
	}
}
namespace OutwardChatCommandsManager.Patches
{
	[HarmonyPatch(typeof(ChatPanel), "SendChatMessage")]
	public static class Patch_ChatPanel_SendChatMessage
	{
		private static bool Prefix(ChatPanel __instance)
		{
			if (ChatExecutionGuard.IsForwarding)
			{
				return true;
			}
			if (!ChatHelpers.TryGetValidCommand(__instance.m_chatEntry.text, out var command))
			{
				return true;
			}
			if (command is OriginalChatCommand)
			{
				new ChatCommandInvocation(((UIElement)__instance).LocalCharacter, command, new GameChatForwardExecutor(__instance), __instance.m_chatEntry.text).TriggerFunction();
				return true;
			}
			new ChatCommandInvocation(((UIElement)__instance).LocalCharacter, command, new ManagedCommandExecutor(), __instance.m_chatEntry.text).TriggerFunction();
			return false;
		}

		private static void Postfix(ChatPanel __instance)
		{
			if (!((Object)(object)__instance?.m_chatEntry == (Object)null))
			{
				__instance.m_chatEntry.text = "";
				if (!__instance.m_chatEntry.isFocused)
				{
					__instance.m_chatEntry.ActivateInputField();
				}
			}
		}
	}
	[HarmonyPatch(typeof(ChatPanel), "Update")]
	public static class Patch_ChatPanel_Update
	{
		private static readonly ConditionalWeakTable<ChatPanel, ChatPanelHistoryState> _state = new ConditionalWeakTable<ChatPanel, ChatPanelHistoryState>();

		private static void Postfix(ChatPanel __instance)
		{
			if (!((Object)(object)__instance.m_chatEntry == (Object)null) && __instance.m_chatEntry.isFocused)
			{
				ChatPanelHistoryState orCreateValue = _state.GetOrCreateValue(__instance);
				InputField chatEntry = __instance.m_chatEntry;
				if (Input.GetKeyDown((KeyCode)273))
				{
					HandleArrowUp(chatEntry, orCreateValue);
				}
				else if (Input.GetKeyDown((KeyCode)274))
				{
					HandleArrowDown(chatEntry, orCreateValue);
				}
				else if (Input.anyKeyDown && !Input.GetKeyDown((KeyCode)13))
				{
					ExitHistoryMode(orCreateValue);
				}
			}
		}

		private static void PlayErrorSound()
		{
			Global.AudioManager.PlaySound((Sounds)10055, 0f, 1f, 1f, 1f, 1f);
		}

		private static void HandleArrowUp(InputField input, ChatPanelHistoryState state)
		{
			IReadOnlyList<ChatCommandInvocation> items = ChatCommandsManager.History.Items;
			if (items.Count == 0)
			{
				PlayErrorSound();
				return;
			}
			if (state.HistoryIndex == -1)
			{
				state.CachedLiveInput = input.text;
				state.HistoryIndex = items.Count - 1;
			}
			else
			{
				int num = ChatCommandsManager.History.FindPreviousUnique(state.HistoryIndex);
				if (num == state.HistoryIndex)
				{
					PlayErrorSound();
					return;
				}
				state.HistoryIndex = num;
			}
			input.text = items[state.HistoryIndex].Message;
			input.caretPosition = input.text.Length;
		}

		private static void HandleArrowDown(InputField input, ChatPanelHistoryState state)
		{
			if (state.HistoryIndex == -1)
			{
				PlayErrorSound();
				return;
			}
			IReadOnlyList<ChatCommandInvocation> items = ChatCommandsManager.History.Items;
			int historyIndex = state.HistoryIndex;
			string message = items[historyIndex].Message;
			for (int i = historyIndex + 1; i < items.Count; i++)
			{
				if (items[i].Message != message)
				{
					state.HistoryIndex = i;
					input.text = items[i].Message;
					input.caretPosition = input.text.Length;
					return;
				}
			}
			input.text = state.CachedLiveInput ?? "";
			ExitHistoryMode(state);
			input.caretPosition = input.text.Length;
			PlayErrorSound();
		}

		private static void ExitHistoryMode(ChatPanelHistoryState state)
		{
			state.HistoryIndex = -1;
			state.CachedLiveInput = null;
		}
	}
	[HarmonyPatch(typeof(WorldSave), "PrepareSave")]
	public class Patch_WorldSave_PrepareSave
	{
		private static bool Prefix()
		{
			foreach (PlayerSystem item in Global.Lobby.PlayersInLobby)
			{
				ChatCommandsSerializer.Instance.AutomaticSaveManagerToXml(item.ControlledCharacter);
			}
			if (ChatCommandsManager.HasUsedCheat)
			{
				return false;
			}
			return true;
		}
	}
}
namespace OutwardChatCommandsManager.Managers
{
	public class ChatCommandsManager
	{
		private static ChatCommandsManager _instance;

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

		private static bool _hasUsedCheat = false;

		private static ChatCommandHistory _history = new ChatCommandHistory();

		public static ChatCommandsManager Instance
		{
			get
			{
				if (_instance == null)
				{
					_instance = new ChatCommandsManager();
				}
				return _instance;
			}
		}

		public static Dictionary<string, ChatCommand> ChatCommands
		{
			get
			{
				return _chatCommands;
			}
			set
			{
				_chatCommands = value;
			}
		}

		public static bool HasUsedCheat
		{
			get
			{
				return _hasUsedCheat;
			}
			set
			{
				_hasUsedCheat = value;
			}
		}

		public static ChatCommandHistory History
		{
			get
			{
				return _history;
			}
			set
			{
				_history = value;
			}
		}

		private ChatCommandsManager()
		{
		}

		public void RestoreHistory(List<ChatCommandInvocation> oldHistory)
		{
			History = new ChatCommandHistory(oldHistory);
		}

		public void AddChatCommand(ChatCommand chatCommand)
		{
			if (string.IsNullOrEmpty(chatCommand.Name))
			{
				OCCM.LogMessage("ChatCommandManager@AddChatCommand Tried to create empty chat command!");
				return;
			}
			if (ChatCommands.ContainsKey(chatCommand.Name))
			{
				OCCM.LogMessage("ChatCommandManager@AddChatCommand Command already exist with name " + chatCommand.Name + "!");
				return;
			}
			ChatCommands.Add(chatCommand.Name, chatCommand);
			EventBusPublisher.SendAddedCommand(chatCommand);
		}

		public void RemoveChatCommand(string name)
		{
			ChatCommand value;
			if (string.IsNullOrEmpty(name))
			{
				OCCM.LogMessage("ChatCommandManager@RemoveChatCommand Tried to remove empty chat command!");
			}
			else if (ChatCommands.TryGetValue(name, out value))
			{
				ChatCommands.Remove(name);
				EventBusPublisher.SendRemovedCommand(value);
			}
		}
	}
	public class ChatCommandsSerializer
	{
		private static ChatCommandsSerializer _instance;

		private string _configPath = "";

		public static ChatCommandsSerializer Instance
		{
			get
			{
				if (_instance == null)
				{
					_instance = new ChatCommandsSerializer();
				}
				return _instance;
			}
		}

		public string ConfigPath
		{
			get
			{
				return _configPath;
			}
			set
			{
				_configPath = value;
			}
		}

		private ChatCommandsSerializer()
		{
			ConfigPath = Path.Combine(PathsManager.ConfigPath, "Chat_Commands_Manager");
		}

		public string GetCharacterXmlFilePath(Character character)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (character != null)
			{
				_ = character.UID;
				if (0 == 0)
				{
					string configPath = ConfigPath;
					UID uID = character.UID;
					return Path.Combine(configPath, ((UID)(ref uID)).Value, "ChatCommandsManagerState.xml");
				}
			}
			OCCM.LogMessage("ChatCommandsSerializer@GetCharacterXmlFilePath Provided null character!");
			return Path.Combine(ConfigPath, "ChatCommandsManagerState.xml");
		}

		public ChatCommandsManagerStateFile Load(string path)
		{
			try
			{
				if (!File.Exists(path))
				{
					OCCM.LogMessage("Chat Commands Manager file not found at: " + path);
					return null;
				}
				XmlSerializer xmlSerializer = new XmlSerializer(typeof(ChatCommandsManagerStateFile));
				using FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read);
				return xmlSerializer.Deserialize(stream) as ChatCommandsManagerStateFile;
			}
			catch (Exception ex)
			{
				OCCM.LogSL("Failed to load Chat Commands Manager file at '" + path + "': " + ex.Message);
				return null;
			}
		}

		public void LoadManagerState(Character character)
		{
			string characterXmlFilePath = GetCharacterXmlFilePath(character);
			if (File.Exists(characterXmlFilePath))
			{
				LoadManagerState(characterXmlFilePath);
			}
		}

		public void LoadManagerState(string path)
		{
			try
			{
				if (!File.Exists(path))
				{
					OCCM.LogSL("ChatCommandsSerializer@LoadManagerState file not found at: " + path);
					return;
				}
				ChatCommandsManagerStateFile chatCommandsManagerStateFile = Load(path);
				if (chatCommandsManagerStateFile == null)
				{
					return;
				}
				ChatCommandsManagerState managerState = GetManagerState(chatCommandsManagerStateFile);
				ChatCommandsManager.Instance.RestoreHistory(managerState.History);
				int length = Enum.GetValues(typeof(HotkeySlots)).Length;
				int num = 0;
				while (num < managerState.LockedHotKeys.Count && length > num)
				{
					HotkeySlots hotkeySlots = (HotkeySlots)num;
					if (managerState.LockedHotKeys.TryGetValue(hotkeySlots, out var _))
					{
						HotkeySlotsHelper.Lock(hotkeySlots, managerState.LockedHotKeys[hotkeySlots]);
					}
					num++;
					num++;
				}
			}
			catch (Exception ex)
			{
				OCCM.LogMessage("ChatCommandsSerializer@LoadManagerState failed loading '" + path + "': " + ex.Message);
			}
		}

		public ChatCommandsManagerState GetChatManagerState()
		{
			return new ChatCommandsManagerState(ChatCommandsManager.History.Items, HotkeySlotsHelper.Locked);
		}

		public void AutomaticSaveManagerToXml(Character character)
		{
			SaveManagerStateToXml(GetCharacterXmlFilePath(character), GetChatManagerState());
		}

		public void SaveManagerStateToXml(string filePath, ChatCommandsManagerState state)
		{
			try
			{
				string directoryName = Path.GetDirectoryName(filePath);
				if (!string.IsNullOrEmpty(directoryName) && !Directory.Exists(directoryName))
				{
					Directory.CreateDirectory(directoryName);
				}
				ChatCommandsManagerStateFile o = BuildManagerStateFile(state);
				XmlSerializer xmlSerializer = new XmlSerializer(typeof(ChatCommandsManagerStateFile));
				XmlWriterSettings settings = new XmlWriterSettings
				{
					Indent = true,
					NewLineOnAttributes = false
				};
				using XmlWriter xmlWriter = XmlWriter.Create(filePath, settings);
				xmlSerializer.Serialize(xmlWriter, o);
			}
			catch (Exception ex)
			{
				OCCM.LogMessage("ChatCommandsSerializer@SaveManagerStateToXml failed saving '" + filePath + "': " + ex.Message);
			}
		}

		public ChatCommandsManagerState GetManagerState(ChatCommandsManagerStateFile file)
		{
			ChatCommandsManagerState chatCommandsManagerState = new ChatCommandsManagerState();
			List<ChatCommandInvocation> list = new List<ChatCommandInvocation>();
			Dictionary<HotkeySlots, ChatCommandInvocation> dictionary = new Dictionary<HotkeySlots, ChatCommandInvocation>();
			foreach (ChatCommandInvocationData item in file.History)
			{
				if (GetInvocationFromData(item, out var invocation))
				{
					list.Add(invocation);
				}
			}
			foreach (HotkeyBindingData hotkeyBinding in file.HotkeyBindings)
			{
				if (GetInvocationFromData(hotkeyBinding.Invocation, out var invocation2) && hotkeyBinding.Slot.HasValue)
				{
					dictionary.Add(hotkeyBinding.Slot.Value, invocation2);
				}
			}
			chatCommandsManagerState.History = list;
			chatCommandsManagerState.LockedHotKeys = dictionary;
			return chatCommandsManagerState;
		}

		public bool GetInvocationFromData(ChatCommandInvocationData invocationData, out ChatCommandInvocation invocation)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			invocation = null;
			ChatCommandData command = invocationData.Command;
			if (!ChatCommandsManager.ChatCommands.TryGetValue(command.Name, out var value))
			{
				OCCM.LogMessage("ChatCommandsSerializer@GetManagerState command " + command.Name + " not found!");
				return false;
			}
			Character character = CharacterManager.Instance.GetCharacter(UID.op_Implicit(invocationData.CharacterUID));
			if ((Object)(object)character == (Object)null)
			{
				OCCM.LogMessage("ChatCommandsSerializer@GetManagerState character not found!");
				return false;
			}
			ICommandExecutor commandExecutor = null;
			invocation = new ChatCommandInvocation(executor: (!invocationData.Executor.HasValue) ? new ManagedCommandExecutor() : CommandExecutorsHelper.GetCommandExecutor(invocationData.Executor.Value, character), character: character, command: value, arguments: GetArgumentsFromInvocationData(invocationData.Arguments), message: invocationData.Message);
			return true;
		}

		public Dictionary<string, string> GetArgumentsFromInvocationData(List<ArgumentData> argumentsData)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (ArgumentData argumentsDatum in argumentsData)
			{
				dictionary.Add(argumentsDatum.Parameter, argumentsDatum.Argument);
			}
			return dictionary;
		}

		public ChatCommandsManagerStateFile BuildManagerStateFile(ChatCommandsManagerState state)
		{
			ChatCommandsManagerStateFile chatCommandsManagerStateFile = new ChatCommandsManagerStateFile
			{
				History = new List<ChatCommandInvocationData>(),
				HotkeyBindings = new List<HotkeyBindingData>()
			};
			foreach (ChatCommandInvocation item2 in state.History)
			{
				chatCommandsManagerStateFile.History.Add(GetInvocationData(item2));
			}
			foreach (KeyValuePair<HotkeySlots, ChatCommandInvocation> lockedHotKey in state.LockedHotKeys)
			{
				HotkeyBindingData item = new HotkeyBindingData
				{
					SlotName = (lockedHotKey.Key.ToString() ?? ""),
					Invocation = GetInvocationData(lockedHotKey.Value)
				};
				chatCommandsManagerStateFile.HotkeyBindings.Add(item);
			}
			return chatCommandsManagerStateFile;
		}

		public ChatCommandInvocationData GetInvocationData(ChatCommandInvocation invocation)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			IChatCommand command = invocation.Command;
			ChatCommandData command2 = new ChatCommandData
			{
				Name = command.Name
			};
			ChatCommandInvocationData chatCommandInvocationData = new ChatCommandInvocationData
			{
				CharacterUID = invocation.Character.UID,
				Command = command2,
				Arguments = new List<ArgumentData>(),
				ExecutorName = invocation.Executor.ExecutorType.ToString(),
				Message = invocation.Message
			};
			foreach (KeyValuePair<string, string> argument in invocation.Arguments)
			{
				ArgumentData item = new ArgumentData
				{
					Parameter = argument.Key,
					Argument = argument.Value
				};
				chatCommandInvocationData.Arguments.Add(item);
			}
			return chatCommandInvocationData;
		}
	}
}
namespace OutwardChatCommandsManager.Events
{
	public static class EventBusPublisher
	{
		public const string Event_AddedCommand = "ChatCommandsManager@AddChatCommand_After";

		public const string Event_RemovedCommand = "ChatCommandsManager@RemoveChatCommand_After";

		public static void SendAddedCommand(ChatCommand chatCommand)
		{
			//IL_001a: 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_0038: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			//IL_00c6: Expected O, but got Unknown
			OCCM.LogMessage("Added " + chatCommand.Name + " command!");
			EventPayload val = new EventPayload { };
			string item;
			((Dictionary<string, object>)val)[item] = chatCommand.Name;
			string item2 = EventRegistryParamsHelper.Get(EventRegistryParams.CommandDescription).key;
			((Dictionary<string, object>)val)[item2] = chatCommand.Description;
			string item3 = EventRegistryParamsHelper.Get(EventRegistryParams.CommandParameters).key;
			((Dictionary<string, object>)val)[item3] = chatCommand.Parameters;
			string item4 = EventRegistryParamsHelper.Get(EventRegistryParams.CommandAction).key;
			((Dictionary<string, object>)val)[item4] = chatCommand.Function;
			string item5 = EventRegistryParamsHelper.Get(EventRegistryParams.CommandRequiresDebugMode).key;
			((Dictionary<string, object>)val)[item5] = chatCommand.RequireDebugMode;
			string item6 = EventRegistryParamsHelper.Get(EventRegistryParams.IsCheatCommand).key;
			((Dictionary<string, object>)val)[item6] = chatCommand.IsCheat;
			EventPayload val2 = val;
			EventBus.Publish("gymmed.chat_commands_manager", "ChatCommandsManager@AddChatCommand_After", val2);
		}

		public static void SendRemovedCommand(ChatCommand chatCommand)
		{
			//IL_001a: 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_0038: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			//IL_00c6: Expected O, but got Unknown
			OCCM.LogMessage("Removed " + chatCommand.Name + " command!");
			EventPayload val = new EventPayload { };
			string item;
			((Dictionary<string, object>)val)[item] = chatCommand.Name;
			string item2 = EventRegistryParamsHelper.Get(EventRegistryParams.CommandDescription).key;
			((Dictionary<string, object>)val)[item2] = chatCommand.Description;
			string item3 = EventRegistryParamsHelper.Get(EventRegistryParams.CommandParameters).key;
			((Dictionary<string, object>)val)[item3] = chatCommand.Parameters;
			string item4 = EventRegistryParamsHelper.Get(EventRegistryParams.CommandAction).key;
			((Dictionary<string, object>)val)[item4] = chatCommand.Function;
			string item5 = EventRegistryParamsHelper.Get(EventRegistryParams.CommandRequiresDebugMode).key;
			((Dictionary<string, object>)val)[item5] = chatCommand.RequireDebugMode;
			string item6 = EventRegistryParamsHelper.Get(EventRegistryParams.IsCheatCommand).key;
			((Dictionary<string, object>)val)[item6] = chatCommand.IsCheat;
			EventPayload val2 = val;
			EventBus.Publish("gymmed.chat_commands_manager", "ChatCommandsManager@RemoveChatCommand_After", val2);
		}
	}
	public static class EventBusRegister
	{
		private static readonly (string key, Type type, string description)[] CommandData = new(string, Type, string)[6]
		{
			EventRegistryParamsHelper.Get(EventRegistryParams.CommandName),
			EventRegistryParamsHelper.Get(EventRegistryParams.CommandDescription),
			EventRegistryParamsHelper.Get(EventRegistryParams.CommandParameters),
			EventRegistryParamsHelper.Get(EventRegistryParams.CommandAction),
			EventRegistryParamsHelper.Get(EventRegistryParams.IsCheatCommand),
			EventRegistryParamsHelper.Get(EventRegistryParams.CommandRequiresDebugMode)
		};

		public static void RegisterEvents()
		{
			EventBus.RegisterEvent("gymmed.chat_commands_manager_*", "ChatCommandsManager@AddChatCommand", "Adds command to chat commands manager.", CommandData);
			EventBus.RegisterEvent("gymmed.chat_commands_manager_*", "ChatCommandsManager@RemoveChatCommand", "Removes command from chat commands manager.", new(string, Type, string)[1] { EventRegistryParamsHelper.Get(EventRegistryParams.CommandName) });
			EventBus.RegisterEvent("gymmed.chat_commands_manager", "ChatCommandsManager@AddChatCommand_After", "Fires event when comment was added to chat commands manager.", CommandData);
			EventBus.RegisterEvent("gymmed.chat_commands_manager", "ChatCommandsManager@RemoveChatCommand_After", "Fires event when comment was removed from chat commands manager.", CommandData);
		}
	}
	public static class EventBusSubscriber
	{
		public const string Event_AddCommand = "ChatCommandsManager@AddChatCommand";

		public const string Event_RemoveCommand = "ChatCommandsManager@RemoveChatCommand";

		public static void AddSubscribers()
		{
			EventBus.Subscribe("gymmed.chat_commands_manager_*", "ChatCommandsManager@AddChatCommand", (Action<EventPayload>)AddCommand);
			EventBus.Subscribe("gymmed.chat_commands_manager_*", "ChatCommandsManager@RemoveChatCommand", (Action<EventPayload>)RemoveCommand);
		}

		public static void AddCommand(EventPayload payload)
		{
			if (payload == null)
			{
				return;
			}
			string text = payload.Get<string>(EventRegistryParamsHelper.Get(EventRegistryParams.CommandName).key, (string)null);
			if (string.IsNullOrEmpty(text))
			{
				OCCM.LogMessage("command is required field! Name your command.");
				return;
			}
			Action<Character, Dictionary<string, string>> val = payload.Get<Action<Character, Dictionary<string, string>>>(EventRegistryParamsHelper.Get(EventRegistryParams.CommandAction).key, (Action<Character, Dictionary<string, string>>)null);
			if (val == null)
			{
				OCCM.LogMessage("function is required field! Please define what your command will do.");
				return;
			}
			Dictionary<string, (string, string)> parameters = payload.Get<Dictionary<string, (string, string)>>(EventRegistryParamsHelper.Get(EventRegistryParams.CommandParameters).key, (Dictionary<string, (string, string)>)null);
			string description = payload.Get<string>(EventRegistryParamsHelper.Get(EventRegistryParams.CommandDescription).key, (string)null);
			bool isCheat = payload.Get<bool>(EventRegistryParamsHelper.Get(EventRegistryParams.IsCheatCommand).key, false);
			bool requireDebugMode = payload.Get<bool>(EventRegistryParamsHelper.Get(EventRegistryParams.CommandRequiresDebugMode).key, false);
			ChatCommandsManager.Instance.AddChatCommand(new ChatCommand(text, parameters, description, isCheat, val, requireDebugMode));
		}

		public static void RemoveCommand(EventPayload payload)
		{
			if (payload != null)
			{
				string text = payload.Get<string>(EventRegistryParamsHelper.Get(EventRegistryParams.CommandName).key, (string)null);
				if (string.IsNullOrEmpty(text))
				{
					OCCM.LogMessage("command is required field! Name your command.");
				}
				else
				{
					ChatCommandsManager.Instance.RemoveChatCommand(text);
				}
			}
		}
	}
}
namespace OutwardChatCommandsManager.Commands
{
	public class ChatCommand : IChatCommand
	{
		private string _name;

		private Dictionary<string, (string, string)> _parameters;

		private string _description;

		private bool _isCheat;

		private bool _requireDebugMode;

		private Action<Character, Dictionary<string, string>> _function;

		public string Name
		{
			get
			{
				return _name;
			}
			set
			{
				_name = value;
			}
		}

		public Dictionary<string, (string, string)> Parameters
		{
			get
			{
				return _parameters;
			}
			set
			{
				_parameters = value;
			}
		}

		public string Description
		{
			get
			{
				return _description;
			}
			set
			{
				_description = value;
			}
		}

		public bool IsCheat
		{
			get
			{
				return _isCheat;
			}
			set
			{
				_isCheat = value;
			}
		}

		public bool RequireDebugMode
		{
			get
			{
				return _requireDebugMode;
			}
			set
			{
				_requireDebugMode = value;
			}
		}

		public Action<Character, Dictionary<string, string>> Function
		{
			get
			{
				return _function;
			}
			set
			{
				_function = value;
			}
		}

		public ChatCommand(string name, Dictionary<string, (string, string)> parameters, string description, bool isCheat, Action<Character, Dictionary<string, string>> function, bool requireDebugMode = false)
		{
			Name = name;
			Parameters = parameters;
			Description = description;
			IsCheat = isCheat;
			Function = function;
			RequireDebugMode = requireDebugMode;
		}

		public virtual void TriggerFunction(Character character, Dictionary<string, string> arguments)
		{
			if (RequireDebugMode && !Global.CheatsEnabled)
			{
				return;
			}
			if (IsCheat)
			{
				ChatCommandsManager.HasUsedCheat = true;
			}
			try
			{
				Function?.Invoke(character, arguments);
			}
			catch (Exception ex)
			{
				if (string.IsNullOrEmpty(Name))
				{
					OCCM.LogMessage("ChatCommand@TriggerFunction encountered an error: \"" + ex.Message + "\"");
					return;
				}
				OCCM.LogMessage("Command " + Name + " encountered an error: \"" + ex.Message + "\"");
			}
		}
	}
	public class MessageCommand
	{
		private string _command = "";

		private List<string> _arguments;

		public string Command
		{
			get
			{
				return _command;
			}
			set
			{
				_command = value;
			}
		}

		public List<string> Arguments
		{
			get
			{
				return _arguments;
			}
			set
			{
				_arguments = value;
			}
		}

		public MessageCommand(string message)
		{
			List<string> list = ChatHelpers.Tokenize(message);
			string command = "";
			if (list.Count > 0)
			{
				command = list[0];
			}
			List<string> arguments = list.Skip(1).ToList();
			Command = command;
			Arguments = arguments;
		}
	}
	public class OriginalChatCommand : IChatCommand
	{
		private string _name;

		private Dictionary<string, (string, string)> _parameters;

		private string _description;

		private bool _isCheat;

		private bool _requireDebugMode;

		public string Name
		{
			get
			{
				return _name;
			}
			set
			{
				_name = value;
			}
		}

		public Dictionary<string, (string, string)> Parameters
		{
			get
			{
				return _parameters;
			}
			set
			{
				_parameters = value;
			}
		}

		public string Description
		{
			get
			{
				return _description;
			}
			set
			{
				_description = value;
			}
		}

		public bool IsCheat
		{
			get
			{
				return _isCheat;
			}
			set
			{
				_isCheat = value;
			}
		}

		public bool RequireDebugMode
		{
			get
			{
				return _requireDebugMode;
			}
			set
			{
				_requireDebugMode = value;
			}
		}

		public OriginalChatCommand(string name, Dictionary<string, (string, string)> parameters, string description, bool isCheat, bool requireDebugMode)
		{
			Name = name;
			Parameters = parameters;
			Description = description;
			IsCheat = isCheat;
			RequireDebugMode = requireDebugMode;
		}

		public void TriggerFunction(Character character, Dictionary<string, string> Arguments)
		{
		}
	}
}