Decompiled source of LethalAutocomplete v0.4.5

LethalAutocomplete.dll

Decompiled 5 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using LethalCompanyInputUtils.Api;
using Newtonsoft.Json;
using TerminalApi;
using TerminalApi.Events;
using UnityEngine;
using UnityEngine.InputSystem;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("LethalAutocomplete")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LethalAutocomplete")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("B5A3A159-6BFF-43BE-840B-173ABE0E1D7F")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace LethalAutocomplete;

public class WordNode
{
	public string Word { get; set; }

	public List<WordNode> Children { get; set; }

	public int Weight { get; set; }

	public WordNode(string word, int weight)
	{
		Word = word;
		Weight = weight;
		Children = new List<WordNode>();
	}

	public List<WordNode> FindMatchingWords(string[] inputs)
	{
		List<WordNode> list = new List<WordNode>();
		if (inputs.Length == 0 || Word.ToLower().StartsWith(inputs[0].ToLower()))
		{
			if (inputs.Length == 1)
			{
				list.Add(this);
			}
			else
			{
				foreach (WordNode child in Children)
				{
					list.AddRange(child.FindMatchingWords(inputs.Skip(1).ToArray()));
				}
			}
		}
		return list;
	}
}
public class Autocomplete
{
	private List<WordNode> _words;

	public List<string> blacklist;

	public static ManualLogSource Logger;

	private readonly int _defaultWeight = 10;

	public Autocomplete()
	{
		_words = new List<WordNode>();
		blacklist = new List<string>();
	}

	public void Insert(TerminalKeyword terminalKeyword)
	{
		try
		{
			if ((Object)(object)terminalKeyword == (Object)null)
			{
				Logger.LogWarning((object)"Tried to add null keyword");
				return;
			}
			string word = ((Object)terminalKeyword).name;
			Logger.LogInfo((object)"blacklist");
			if (blacklist == null)
			{
				blacklist = new List<string>();
			}
			bool flag = blacklist.Contains(word);
			if (ListContainsWord(word, _words))
			{
				if (flag)
				{
					_words = _words.Where((WordNode x) => x.Word != word).ToList();
				}
			}
			else
			{
				if (flag)
				{
					return;
				}
				Logger.LogInfo((object)"create WordNode node");
				WordNode wordNode = new WordNode(word, _defaultWeight);
				Logger.LogInfo((object)"terminalKeyword.compatibleNouns");
				if (terminalKeyword.compatibleNouns != null)
				{
					for (int i = 0; i < terminalKeyword.compatibleNouns.Length; i++)
					{
						string text = "";
						text = ((!new string[2] { "route", "info" }.Any(word.ToLower().Contains)) ? ((object)terminalKeyword.compatibleNouns[i].noun).ToString().Split(new char[1] { ' ' })[0] : terminalKeyword.compatibleNouns[i].noun.word);
						WordNode wordNode2 = new WordNode(text, _defaultWeight);
						if (word.ToLower() == "buy")
						{
							for (int j = 1; j < 10; j++)
							{
								wordNode2.Children.Add(new WordNode(j.ToString(), 10 - j));
							}
						}
						wordNode.Children.Add(wordNode2);
					}
				}
				Logger.LogInfo((object)"_words.Add");
				_words.Add(wordNode);
			}
		}
		catch (Exception arg2)
		{
			string arg = "None";
			if (Object.op_Implicit((Object)(object)terminalKeyword) && ((Object)terminalKeyword).name != "")
			{
				arg = ((Object)terminalKeyword).name;
			}
			Logger.LogError((object)$"Failed to add terminal keyword '{arg}' in to autocomplete dictionary! Exception: {arg2}");
		}
	}

	private bool ListContainsWord(string word, List<WordNode> list)
	{
		return list.Any((WordNode node) => node.Word == word);
	}

	public List<string> GetAutocomplete(string input)
	{
		try
		{
			string[] array = input.Split(new char[1] { ' ' });
			List<WordNode> list = new List<WordNode>();
			string matching_start = "";
			for (int i = 0; i < array.Length - 1; i++)
			{
				matching_start = matching_start + array[i] + " ";
			}
			foreach (WordNode word in _words)
			{
				list.AddRange(word.FindMatchingWords(array));
			}
			list = (from n in list.Distinct()
				where n.Weight > 0
				orderby n.Weight descending
				select n).ToList();
			return list.Select((WordNode n) => matching_start + n.Word).ToList();
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"Failed on autocomplete search. Error: {arg}");
			return null;
		}
	}

	public List<WordNode> GetWords()
	{
		return _words;
	}

	public void SetWords(List<WordNode> words)
	{
		_words = new List<WordNode>(words);
	}
}
internal class AutocompleteManager
{
	private class SaveData
	{
		public List<WordNode> Words { get; set; }

		public Dictionary<string, List<string>> History { get; set; }

		public List<string> CommandsBlacklist { get; set; }

		public List<string> HistoryBlacklist { get; set; }
	}

	public static Keybinds keybinds;

	public static string saveFilePath = "";

	public static string autocompleteKey = "<Keyboard>/tab";

	public static string historyNextKey = "<Keyboard>/upArrow";

	public static string historyPrevKey = "<Keyboard>/downArrow";

	public static bool saveHistory = true;

	public static int historyMaxCount = 20;

	public bool exited;

	private Terminal _terminal;

	private string _input;

	private List<string> _terminalCommands;

	private List<string> _commandsHistory;

	private List<string> _historyBlacklist;

	private int _historyIndex;

	private string _lastAutocomplete = "";

	private bool _startedAutocomplete;

	private List<string> _autocompleteOptions;

	private int _autocompleteOptionIndex;

	public static ManualLogSource Logger;

	private Autocomplete _autocomplete;

	public void Awake()
	{
		if (Plugin.IsDebug)
		{
			Logger.LogInfo((object)("Lethal Autocomplete Plugin is loaded! Autocomplete Key: " + autocompleteKey));
		}
		_terminalCommands = new List<string>();
		_commandsHistory = new List<string>();
		_historyBlacklist = new List<string>();
		_autocomplete = new Autocomplete();
		Autocomplete.Logger = Logger;
		LoadFromJson();
		SetupTerminalCallbacks();
	}

	private void OnTerminalTextChanged(object sender, TerminalTextChangedEventArgs e)
	{
		try
		{
			_input = TerminalApi.GetTerminalInput();
			_input = _input.Replace("\n", "");
			if (Plugin.IsDebug)
			{
				Logger.LogMessage((object)("OnTerminalTextChanged: " + _input));
			}
			if (_input != _lastAutocomplete)
			{
				ResetAutocomplete();
			}
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"On terminal text changed event. Error: {arg}");
		}
	}

	private void OnTerminalExit(object sender, TerminalEventArgs e)
	{
		if (Plugin.IsDebug)
		{
			Logger.LogMessage((object)"Terminal Exited");
		}
		if (!saveHistory)
		{
			_commandsHistory = new List<string>();
		}
		try
		{
			RemoveKeybindCallbacks();
			SaveToJson();
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"On terminal exit. Error: {arg}");
		}
	}

	private void TerminalIsStarting(object sender, TerminalEventArgs e)
	{
		try
		{
			if (Plugin.IsDebug)
			{
				Logger.LogMessage((object)"Terminal is starting");
			}
			_terminal = TerminalApi.Terminal;
			if (autocompleteKey.Contains("tab"))
			{
				RemoveTerminalExitBinding();
			}
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"On terminal starting. Error: {arg}");
		}
	}

	private void RemoveTerminalExitBinding()
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			MovementActions movement = _terminal.playerActions.Movement;
			InputAction openMenu = ((MovementActions)(ref movement)).OpenMenu;
			if (Plugin.IsDebug)
			{
				Logger.LogMessage((object)(openMenu.name + " " + InputActionRebindingExtensions.GetBindingDisplayString(openMenu, (DisplayStringOptions)0, (string)null)));
			}
			openMenu.Disable();
			InputBinding val = default(InputBinding);
			((InputBinding)(ref val)).path = "<Keyboard>/tab";
			((InputBinding)(ref val)).overridePath = "";
			InputActionRebindingExtensions.ApplyBindingOverride(openMenu, val);
			openMenu.Enable();
			if (Plugin.IsDebug)
			{
				Logger.LogMessage((object)(openMenu.name + " " + InputActionRebindingExtensions.GetBindingDisplayString(openMenu, (DisplayStringOptions)0, (string)null)));
			}
		}
		catch (Exception ex)
		{
			Logger.LogWarning((object)"Remove terminal tab exit binded key");
			Logger.LogError((object)ex);
			throw;
		}
	}

	private void TerminalIsStarted(object sender, TerminalEventArgs e)
	{
		try
		{
			if (Plugin.IsDebug)
			{
				Logger.LogMessage((object)"Terminal is started");
			}
			_terminalCommands.Clear();
			for (int i = 0; i < _terminal.terminalNodes.allKeywords.Length; i++)
			{
				Logger.LogWarning((object)$"Add: {_terminal.terminalNodes.allKeywords[i]}");
				_autocomplete.Insert(_terminal.terminalNodes.allKeywords[i]);
			}
		}
		catch (Exception ex)
		{
			Logger.LogWarning((object)"Terminal is started");
			Logger.LogError((object)ex);
			throw;
		}
	}

	private void TextSubmitted(object sender, TerminalParseSentenceEventArgs e)
	{
		if (Plugin.IsDebug)
		{
			Logger.LogMessage((object)("TextSubmitted: " + _input));
		}
		try
		{
			if (e.SubmittedText != "" && !_historyBlacklist.Contains(e.SubmittedText))
			{
				if (_commandsHistory.Count + 1 > historyMaxCount)
				{
					_commandsHistory.RemoveAt(0);
				}
				if (_commandsHistory.Contains(e.SubmittedText))
				{
					_commandsHistory.Remove(e.SubmittedText);
				}
				_commandsHistory.Add(e.SubmittedText);
				_historyIndex = _commandsHistory.Count;
			}
			_input = "";
			ResetAutocomplete();
		}
		catch (Exception ex)
		{
			Logger.LogWarning((object)$"Text submitted: {e.SubmittedText} Node Returned: {e.ReturnedNode}");
			Logger.LogError((object)ex);
		}
	}

	private void OnBeginUsing(object sender, TerminalEventArgs e)
	{
		Logger.LogMessage((object)"Player has just started using the terminal");
		SetupKeybindCallbacks();
	}

	private void OnBeganUsing(object sender, TerminalEventArgs e)
	{
		if (autocompleteKey.Contains("tab"))
		{
			HUDManager.Instance.ChangeControlTip(0, "Quit terminal : [Esc]", true);
		}
	}

	private void SetupTerminalCallbacks()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Expected O, but got Unknown
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Expected O, but got Unknown
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Expected O, but got Unknown
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Expected O, but got Unknown
		Events.TerminalStarting += new TerminalEventHandler(TerminalIsStarting);
		Events.TerminalStarted += new TerminalEventHandler(TerminalIsStarted);
		Events.TerminalParsedSentence += new TerminalParseSentenceEventHandler(TextSubmitted);
		Events.TerminalBeginUsing += new TerminalEventHandler(OnBeginUsing);
		Events.TerminalBeganUsing += new TerminalEventHandler(OnBeganUsing);
		Events.TerminalExited += new TerminalEventHandler(OnTerminalExit);
		Events.TerminalTextChanged += new TerminalTextChangedEventHandler(OnTerminalTextChanged);
	}

	private void SetupKeybindCallbacks()
	{
		Logger.LogMessage((object)"Setup Keybind Callbacks");
		keybinds.AutocompleteAction.performed += OnAutocompleteKey;
		keybinds.HistoryNextAction.performed += OnHistoryNextKey;
		keybinds.HistoryPrevAction.performed += OnHistoryPrevKey;
	}

	private void RemoveKeybindCallbacks()
	{
		Logger.LogMessage((object)"Remove Keybind Callbacks");
		keybinds.AutocompleteAction.performed -= OnAutocompleteKey;
		keybinds.HistoryNextAction.performed -= OnHistoryNextKey;
		keybinds.HistoryPrevAction.performed -= OnHistoryPrevKey;
	}

	private void OnHistoryNextKey(CallbackContext ctx)
	{
		try
		{
			if (_commandsHistory.Count >= 1 && _historyIndex >= 1)
			{
				_historyIndex--;
				Logger.LogInfo((object)("Set input to '" + _commandsHistory[_historyIndex] + "'."));
				TerminalApi.SetTerminalInput(_commandsHistory[_historyIndex]);
			}
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"Failed on history next key performed. Error: {arg}");
			Logger.LogInfo((object)$"_commandsHistory.Count={_commandsHistory.Count}");
			Logger.LogInfo((object)$"historyIndex={_historyIndex}");
		}
	}

	private void OnHistoryPrevKey(CallbackContext ctx)
	{
		TerminalApi.SetTerminalInput("");
		try
		{
			if (_commandsHistory.Count >= 1)
			{
				if (_historyIndex + 1 >= _commandsHistory.Count)
				{
					_historyIndex = _commandsHistory.Count;
					TerminalApi.SetTerminalInput("");
					Logger.LogInfo((object)"Set input to ''.");
					Logger.LogInfo((object)("INPUT: " + TerminalApi.GetTerminalInput()));
				}
				else
				{
					_historyIndex++;
					Logger.LogInfo((object)("Set input to '" + _commandsHistory[_historyIndex] + "'."));
					TerminalApi.SetTerminalInput(_commandsHistory[_historyIndex]);
				}
			}
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"Failed on history prev key performed. Error: {arg}");
			Logger.LogInfo((object)$"_commandsHistory.Count={_commandsHistory.Count}");
			Logger.LogInfo((object)$"historyIndex={_historyIndex}");
		}
	}

	private void OnAutocompleteKey(CallbackContext ctx)
	{
		try
		{
			if (_startedAutocomplete)
			{
				NextAutocomplete();
			}
			else
			{
				StartAutocomplete();
			}
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"Failed on autocomplete key performed. Error: {arg}");
			Logger.LogInfo((object)$"_startedAutocomplete={_startedAutocomplete}");
		}
	}

	private void StartAutocomplete()
	{
		try
		{
			List<string> autocomplete = _autocomplete.GetAutocomplete(_input);
			if (Plugin.IsDebug)
			{
				Logger.LogInfo((object)"Autocomplete options:");
				foreach (string item in autocomplete)
				{
					Logger.LogInfo((object)(item ?? ""));
				}
			}
			if (autocomplete != null && autocomplete.Count > 0)
			{
				_autocompleteOptions = new List<string>(autocomplete);
				_startedAutocomplete = true;
				_lastAutocomplete = _autocompleteOptions.First();
				Logger.LogMessage((object)("Set Autocomplete " + _lastAutocomplete));
				TerminalApi.SetTerminalInput(_lastAutocomplete);
			}
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"Failed on autocomplete new options search. Error: {arg}");
		}
	}

	private void NextAutocomplete()
	{
		try
		{
			if (Plugin.IsDebug)
			{
				Logger.LogInfo((object)"Autocomplete Options:");
				for (int i = 0; i < _autocompleteOptions.Count; i++)
				{
					Logger.LogInfo((object)_autocompleteOptions[i]);
				}
				Logger.LogInfo((object)$"Autocomplete Index: {_autocompleteOptionIndex + 1}");
			}
			_autocompleteOptionIndex++;
			if (_autocompleteOptionIndex >= _autocompleteOptions.Count)
			{
				_autocompleteOptionIndex = 0;
			}
			_lastAutocomplete = _autocompleteOptions[_autocompleteOptionIndex];
			TerminalApi.SetTerminalInput(_lastAutocomplete);
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"Failed on autocomplete next options search. Error: {arg}");
		}
	}

	private void ResetAutocomplete()
	{
		try
		{
			if (Plugin.IsDebug)
			{
				Logger.LogInfo((object)"Reset autocomplete state");
			}
			_startedAutocomplete = false;
			_autocompleteOptionIndex = 0;
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"Failed on autocomplete reset. Error: {arg}");
		}
	}

	public void SaveToJson()
	{
		List<WordNode> words = _autocomplete.GetWords();
		Dictionary<string, List<string>> history = new Dictionary<string, List<string>> { ["value"] = _commandsHistory };
		List<string> list = new List<string>();
		list = _autocomplete.blacklist;
		List<string> list2 = new List<string>();
		list2 = _historyBlacklist;
		string contents = JsonConvert.SerializeObject((object)new
		{
			Words = words,
			History = history,
			CommandsBlacklist = list,
			HistoryBlacklist = list2
		}, (Formatting)1);
		File.WriteAllText(saveFilePath, contents);
	}

	private void LoadFromJson()
	{
		try
		{
			if (File.Exists(saveFilePath))
			{
				string text = File.ReadAllText(saveFilePath);
				if (!string.IsNullOrEmpty(text))
				{
					SaveData saveData = JsonConvert.DeserializeObject<SaveData>(text);
					_autocomplete.blacklist = saveData.CommandsBlacklist;
					_historyBlacklist = saveData.HistoryBlacklist;
					List<string> first = saveData.History["value"];
					_commandsHistory = new List<string>(first.Except(_historyBlacklist));
					_historyIndex = _commandsHistory.Count;
					_autocomplete.SetWords(saveData.Words);
					Logger.LogMessage((object)"Loaded save from JSON!");
				}
			}
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"Failed on loading json save file. Error: {arg}");
		}
	}
}
internal class Keybinds : LcInputActions
{
	public InputAction AutocompleteAction => ((LcInputActions)this).Asset["Autocomplete"];

	public InputAction HistoryNextAction => ((LcInputActions)this).Asset["HistoryNext"];

	public InputAction HistoryPrevAction => ((LcInputActions)this).Asset["HistoryPrev"];

	public override void CreateInputActions(in InputActionMapBuilder builder)
	{
		((LcInputActions)this).CreateInputActions(ref builder);
		builder.NewActionBinding().WithActionId("Autocomplete").WithActionType((InputActionType)1)
			.WithKbmPath(AutocompleteManager.autocompleteKey)
			.WithBindingName("Autocomplete Key")
			.Finish();
		builder.NewActionBinding().WithActionId("HistoryNext").WithActionType((InputActionType)1)
			.WithKbmPath(AutocompleteManager.historyNextKey)
			.WithBindingName("HistoryNext Key")
			.Finish();
		builder.NewActionBinding().WithActionId("HistoryPrev").WithActionType((InputActionType)1)
			.WithKbmPath(AutocompleteManager.historyPrevKey)
			.WithBindingName("HistoryPrev Key")
			.Finish();
	}
}
[BepInPlugin("redeye.lethalautocomplete", "Lethal Autocomplete", "0.4.5")]
[BepInDependency("atomic.terminalapi", "1.3.0")]
[BepInDependency("com.rune580.LethalCompanyInputUtils", "0.4.2")]
public class Plugin : BaseUnityPlugin
{
	private const string _GUID = "redeye.lethalautocomplete";

	private const string _Name = "Lethal Autocomplete";

	private const string _Version = "0.4.5";

	public static bool IsDebug;

	private AutocompleteManager _autocomplete;

	public string PluginPath = "";

	private void Awake()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Lethal Autocomplete Plugin is loaded!");
		Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
		try
		{
			PluginPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)ex);
		}
		try
		{
			_autocomplete = new AutocompleteManager();
			AutocompleteManager.Logger = ((BaseUnityPlugin)this).Logger;
			ConfigFile();
			AutocompleteManager.keybinds = new Keybinds();
			_autocomplete.Awake();
		}
		catch (Exception ex2)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)ex2);
		}
	}

	private void OnApplicationQuit()
	{
		_autocomplete.SaveToJson();
	}

	private void ConfigFile()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Expected O, but got Unknown
		string path = "save.json";
		string text = Path.Combine(PluginPath, path);
		string text2 = ((BaseUnityPlugin)this).Config.Bind<string>("Basic", "Save Data Path", "", "Absolute path to the json file with autocomplete words and commands history. By default save.json generated in plugins/red_eye-LethalAutocomplete folder.").Value;
		if (!File.Exists(text2) && text2 != "")
		{
			text2 = text;
			((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("Basic", "Save Data Path"));
			((BaseUnityPlugin)this).Config.Bind<string>("Basic", "Save Data Path", text, "Absolute path to the json file with autocomplete words and commands history. By default save.json generated in plugins/red_eye-LethalAutocomplete folder.");
			((BaseUnityPlugin)this).Logger.LogWarning((object)"The save file wasn't found in the directory specified by the configuration file! Using default path.");
		}
		AutocompleteManager.saveFilePath = ((text2 == "") ? text : text2);
		ConfigEntry<string> val = ((BaseUnityPlugin)this).Config.Bind<string>("Keyboard Bindings", "Autocomplete", "<Keyboard>/tab", "Get autocomplete for current input");
		AutocompleteManager.autocompleteKey = (val.Value.ToLower().StartsWith("<keyboard>") ? val.Value : ("<Keyboard>/" + val.Value));
		ConfigEntry<string> val2 = ((BaseUnityPlugin)this).Config.Bind<string>("Keyboard Bindings", "History Next", "<Keyboard>/upArrow", "Get current terminal session next command");
		AutocompleteManager.historyNextKey = (val2.Value.ToLower().StartsWith("<keyboard>") ? val2.Value : ("<Keyboard>/" + val2.Value));
		ConfigEntry<string> val3 = ((BaseUnityPlugin)this).Config.Bind<string>("Keyboard Bindings", "History Prev", "<Keyboard>/downArrow", "Get current terminal session prev command");
		AutocompleteManager.historyPrevKey = (val3.Value.ToLower().StartsWith("<keyboard>") ? val3.Value : ("<Keyboard>/" + val3.Value));
		AutocompleteManager.saveHistory = ((BaseUnityPlugin)this).Config.Bind<bool>("History", "Save History", true, "Regulates if the history be saved after the re-entry").Value;
		AutocompleteManager.historyMaxCount = ((BaseUnityPlugin)this).Config.Bind<int>("History", "Buffer Length", 20, "Max amount of commands to remember during terminal session").Value;
		IsDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("Other", "Enable Debug", false, "").Value;
	}
}