Decompiled source of Terminal Tools v1.0.2

LethalAPI.Terminal.dll

Decompiled 10 months ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalAPI.LibTerminal.Attributes;
using LethalAPI.LibTerminal.Commands;
using LethalAPI.LibTerminal.Helpers;
using LethalAPI.LibTerminal.Interfaces;
using LethalAPI.LibTerminal.Models;
using LethalAPI.LibTerminal.Models.Enums;
using LethalAPI.LibTerminal.Patches;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using UnityEngine.Video;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("ShimmyMySherbet, LethalAPI Modding Team")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A library that allows the creation of custom terminal commands for Lethal Company mods")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+3abb9ab9dd16dac2bfc11bf6e7b10e642706a0c8")]
[assembly: AssemblyProduct("LethalAPI.Terminal")]
[assembly: AssemblyTitle("LethalAPI.Terminal")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/LethalCompany/LethalAPI.Terminal")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.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 LethalApi.LibTerminal.Attributes
{
	public class InverseTeleporterUnlockedAttribute : AccessControlAttribute
	{
		public override bool CheckAllowed()
		{
			if ((Object)(object)StartOfRound.Instance == (Object)null)
			{
				return false;
			}
			return StartOfRound.Instance.SpawnedShipUnlockables.ContainsKey(6);
		}
	}
	public class TeleporterUnlockedAttribute : AccessControlAttribute
	{
		public override bool CheckAllowed()
		{
			if ((Object)(object)StartOfRound.Instance == (Object)null)
			{
				return false;
			}
			return StartOfRound.Instance.SpawnedShipUnlockables.ContainsKey(5);
		}
	}
}
namespace LethalAPI.LibTerminal
{
	[HarmonyPatch(typeof(Terminal), "ParsePlayerSentence")]
	internal static class ParseSentencePatch
	{
		[HarmonyPrefix]
		public static bool ParsePrefix(Terminal __instance, ref TerminalNode __state)
		{
			__state = null;
			string command = __instance.screenText.text.Substring(__instance.screenText.text.Length - __instance.textAdded);
			__state = CommandHandler.HandleCommandInput(command, __instance);
			return (Object)(object)__state == (Object)null;
		}

		[HarmonyPostfix]
		public static TerminalNode ParsePostfix(TerminalNode __result, TerminalNode __state, Terminal __instance)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Invalid comparison between Unknown and I4
			if ((Object)(object)__state != (Object)null)
			{
				TerminalSubmitPatch.LastNode = __state;
				return __state;
			}
			if ((int)__instance.videoPlayer.source == 1)
			{
				__instance.videoPlayer.source = (VideoSource)0;
			}
			TerminalSubmitPatch.LastNode = __result;
			return __result;
		}
	}
	public static class TerminalExtensions
	{
		public static void PlayVideoFile(this Terminal terminal, string filePath)
		{
			string url = "file:///" + filePath.Replace('\\', '/');
			terminal.PlayVideoLink(url);
		}

		public static void PlayVideoLink(this Terminal terminal, Uri url)
		{
			((MonoBehaviour)terminal).StartCoroutine(PlayVideoLink(url.AbsoluteUri, terminal));
		}

		public static void PlayVideoLink(this Terminal terminal, string url)
		{
			((MonoBehaviour)terminal).StartCoroutine(PlayVideoLink(url, terminal));
		}

		private static IEnumerator PlayVideoLink(string url, Terminal terminal)
		{
			yield return (object)new WaitForFixedUpdate();
			((Behaviour)terminal.terminalImage).enabled = true;
			terminal.terminalImage.texture = (Texture)(object)terminal.videoTexture;
			terminal.displayingPersistentImage = null;
			terminal.videoPlayer.clip = null;
			terminal.videoPlayer.source = (VideoSource)1;
			terminal.videoPlayer.url = url;
			((Behaviour)terminal.videoPlayer).enabled = true;
		}
	}
	[BepInPlugin("LethalAPI.Terminal", "LethalAPI.Terminal", "1.0.0")]
	public class TerminalLibPlugin : BaseUnityPlugin
	{
		private Harmony HarmonyInstance = new Harmony("LethalAPI.Terminal");

		private TerminalModRegistry Terminal;

		private void Awake()
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"LethalAPI.Terminal is loading...");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Installing patches");
			HarmonyInstance.PatchAll(typeof(TerminalLibPlugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Registering built-in Commands");
			Terminal = TerminalRegistry.CreateTerminalRegistry();
			Terminal.RegisterFrom<CommandInfoCommands>();
			Terminal.RegisterFrom<CheatCommands>();
			Terminal.RegisterFrom<EntityCommands>();
			Terminal.RegisterFrom<EquipmentCommands>();
			Terminal.RegisterFrom<InfoCommands>();
			Terminal.RegisterFrom<PlayerCommands>();
			Terminal.RegisterFrom<ShipCommands>();
			Object.DontDestroyOnLoad((Object)(object)this);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin LethalAPI.Terminal is loaded!");
		}
	}
	public static class TerminalNodeExtensions
	{
		public static TerminalNode WithDisplayText(this TerminalNode node, object displayText)
		{
			node.displayText = displayText.ToString();
			return node;
		}

		public static TerminalNode WithDisplayTexture(this TerminalNode node, Texture texture)
		{
			node.displayTexture = texture;
			return node;
		}

		public static TerminalNode WithVideoClip(this TerminalNode node, VideoClip video)
		{
			node.displayVideo = video;
			return node;
		}

		public static TerminalNode WithAcceptsAnything(this TerminalNode node)
		{
			node.acceptAnything = true;
			return node;
		}

		public static TerminalNode WithBuyItemIndex(this TerminalNode node, int index)
		{
			node.buyItemIndex = index;
			return node;
		}

		public static TerminalNode WithMoonIndex(this TerminalNode node, int index)
		{
			node.buyRerouteToMoon = index;
			return node;
		}

		public static TerminalNode ClearText(this TerminalNode node)
		{
			node.clearPreviousText = true;
			return node;
		}

		public static TerminalNode WithItemCost(this TerminalNode node, int cost)
		{
			node.itemCost = cost;
			return node;
		}

		public static TerminalNode LoadImageSlowly(this TerminalNode node)
		{
			node.loadImageSlowly = true;
			return node;
		}

		public static TerminalNode PersistImage(this TerminalNode node)
		{
			node.persistentImage = true;
			return node;
		}

		public static TerminalNode WithAudio(this TerminalNode node, AudioClip audio)
		{
			node.playClip = audio;
			return node;
		}

		public static TerminalNode WithTerminalEvent(this TerminalNode node, string eventName)
		{
			node.terminalEvent = eventName;
			return node;
		}

		public static TerminalNode ReturnItemFromStorage(this TerminalNode node, int unlockID)
		{
			node.shipUnlockableID = unlockID;
			node.returnFromStorage = true;
			return node;
		}

		public static TerminalNode PlayEffect(this TerminalNode node, SyncedTerminalClip clip)
		{
			node.playSyncedClip = (int)clip;
			return node;
		}

		public static TerminalNode PlayError(this TerminalNode node)
		{
			node.playSyncedClip = 1;
			return node;
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "LethalAPI.Terminal";

		public const string PLUGIN_NAME = "LethalAPI.Terminal";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace LethalAPI.LibTerminal.Patches
{
	[HarmonyPatch(typeof(Terminal), "BeginUsingTerminal")]
	internal static class BeginUsingTerminalPatch
	{
		[HarmonyPostfix]
		public static void Postfix(Terminal __instance)
		{
			ITerminalInterface currentInterface = CommandHandler.CurrentInterface;
			if (currentInterface != null)
			{
				TerminalNode splashScreen = currentInterface.GetSplashScreen(__instance);
				if ((Object)(object)splashScreen != (Object)null)
				{
					__instance.LoadNewNode(splashScreen);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Terminal), "selectTextFieldDelayed")]
	internal static class SelectTextFieldPatch
	{
		[HarmonyPrefix]
		public static bool Prefix()
		{
			return false;
		}

		[HarmonyPostfix]
		public static void Postfix(Terminal __instance, ref IEnumerator __result)
		{
			__result = Patch(__instance);
		}

		private static IEnumerator Patch(Terminal terminal)
		{
			yield return (object)new WaitForSeconds(0.2f);
			terminal.screenText.ActivateInputField();
			((Selectable)terminal.screenText).Select();
		}
	}
	[HarmonyPatch(typeof(Terminal), "OnSubmit")]
	internal static class TerminalSubmitPatch
	{
		private static ManualLogSource m_LogSource = new ManualLogSource("LethalAPI.Terminal");

		public static TerminalNode LastNode { get; set; }

		[HarmonyPrefix]
		public static void Prefix()
		{
			LastNode = null;
		}

		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			CodeInstruction[] array = instructions.ToArray();
			for (int num = array.Length - 1; num >= 0; num--)
			{
				if (!(array[num].opcode != OpCodes.Callvirt))
				{
					if (array[num + 1].opcode != OpCodes.Ldarg_0)
					{
						ReportTranspileError("Ldarg_0 expected after final callVirt, not found");
						return array;
					}
					array[num + 1] = new CodeInstruction(OpCodes.Ret, (object)null);
					return array;
				}
			}
			ReportTranspileError("Failed to find Callvirt in backward scan");
			return array;
		}

		private static void ReportTranspileError(string message)
		{
			m_LogSource.LogError((object)("Failed to transpile OnSubmit to remove Scroll To Bottom. Did the method get modified in an update? (" + message + ")"));
			m_LogSource.LogWarning((object)"This won't break the mod, but it will cause some odd terminal scrolling behavior");
		}

		[HarmonyPostfix]
		public static void Postfix(Terminal __instance, ref Coroutine ___forceScrollbarCoroutine)
		{
			if ((Object)(object)LastNode == (Object)null || LastNode.clearPreviousText)
			{
				ExecuteScrollCoroutine(__instance, ref ___forceScrollbarCoroutine);
			}
			else
			{
				((MonoBehaviour)__instance).StartCoroutine("forceScrollbarDown");
			}
		}

		private static void ExecuteScrollCoroutine(Terminal terminal, ref Coroutine forceScrollbarCoroutine)
		{
			if (forceScrollbarCoroutine != null)
			{
				((MonoBehaviour)terminal).StopCoroutine(forceScrollbarCoroutine);
			}
			forceScrollbarCoroutine = ((MonoBehaviour)terminal).StartCoroutine("forceScrollbarUp");
		}
	}
	[HarmonyPatch(typeof(Terminal), "TextPostProcess")]
	internal static class TextPostProcessPatch
	{
		[HarmonyPrefix]
		public static bool Prefix(Terminal __instance, ref string modifiedDisplayText, ref string __state)
		{
			__state = null;
			if (CommandHandler.CurrentInterface == null)
			{
				modifiedDisplayText = modifiedDisplayText.TrimStart('\n', ' ').SetEndPadding('\n', 2);
				return true;
			}
			bool num = ProcessInterface(CommandHandler.CurrentInterface, ref modifiedDisplayText, __instance);
			if (!num)
			{
				__state = modifiedDisplayText;
			}
			return num;
		}

		[HarmonyPostfix]
		public static string Postfix(string __result, Terminal __instance, string __state)
		{
			string text = __state ?? __result;
			if (CommandHandler.CurrentInterface != null)
			{
				text = CommandHandler.CurrentInterface.PostProcessText(__instance, text);
			}
			return text;
		}

		private static bool ProcessInterface(ITerminalInterface terminalInterface, ref string modifiedDisplayText, Terminal terminal)
		{
			if (terminalInterface.APITextPostProcessing)
			{
				modifiedDisplayText = modifiedDisplayText.TrimStart('\n', ' ').SetEndPadding('\n', 2);
			}
			modifiedDisplayText = terminalInterface.PreProcessText(terminal, modifiedDisplayText);
			return terminalInterface.VanillaTextPostProcessing;
		}
	}
}
namespace LethalAPI.LibTerminal.Models
{
	public class ArgumentStream
	{
		public string[] Arguments { get; }

		public int Index { get; set; }

		public bool EndOfStream => Index >= Arguments.Length;

		public ArgumentStream(string[] arguments)
		{
			Arguments = arguments;
		}

		public ArgumentStream(IEnumerable<string> arguments)
		{
			Arguments = arguments.ToArray();
		}

		public void Reset()
		{
			Index = 0;
		}

		public bool TryReadNext(Type type, out object value)
		{
			if (EndOfStream)
			{
				value = null;
				return false;
			}
			return StringConverter.TryConvert(Arguments[Index++], type, out value);
		}

		public bool TryReadRemaining(out string result)
		{
			if (EndOfStream)
			{
				result = null;
				return false;
			}
			result = string.Join(" ", Arguments.Skip(Index));
			return true;
		}

		public bool TryReadNext(out string value)
		{
			value = string.Empty;
			if (EndOfStream)
			{
				return false;
			}
			value = Arguments[Index++];
			return true;
		}

		public bool TryReadNext(out sbyte value)
		{
			value = 0;
			if (EndOfStream)
			{
				return false;
			}
			return sbyte.TryParse(Arguments[Index++], out value);
		}

		public bool TryReadNext(out byte value)
		{
			value = 0;
			if (EndOfStream)
			{
				return false;
			}
			return byte.TryParse(Arguments[Index++], out value);
		}

		public bool TryReadNext(out short value)
		{
			value = 0;
			if (EndOfStream)
			{
				return false;
			}
			return short.TryParse(Arguments[Index++], out value);
		}

		public bool TryReadNext(out ushort value)
		{
			value = 0;
			if (EndOfStream)
			{
				return false;
			}
			return ushort.TryParse(Arguments[Index++], out value);
		}

		public bool TryReadNext(out int value)
		{
			value = 0;
			if (EndOfStream)
			{
				return false;
			}
			return int.TryParse(Arguments[Index++], out value);
		}

		public bool TryReadNext(out uint value)
		{
			value = 0u;
			if (EndOfStream)
			{
				return false;
			}
			return uint.TryParse(Arguments[Index++], out value);
		}

		public bool TryReadNext(out long value)
		{
			value = 0L;
			if (EndOfStream)
			{
				return false;
			}
			return long.TryParse(Arguments[Index++], out value);
		}

		public bool TryReadNext(out ulong value)
		{
			value = 0uL;
			if (EndOfStream)
			{
				return false;
			}
			return ulong.TryParse(Arguments[Index++], out value);
		}

		public bool TryReadNext(out float value)
		{
			value = 0f;
			if (EndOfStream)
			{
				return false;
			}
			return float.TryParse(Arguments[Index++], out value);
		}

		public bool TryReadNext(out double value)
		{
			value = 0.0;
			if (EndOfStream)
			{
				return false;
			}
			return double.TryParse(Arguments[Index++], out value);
		}
	}
	public static class CommandActivator
	{
		public static bool TryCreateInvoker(ArgumentStream arguments, ServiceCollection services, MethodInfo method, out Func<object, object> invoker)
		{
			TerminalCommandAttribute commandAttribute = method.GetCustomAttribute<TerminalCommandAttribute>();
			ParameterInfo[] parameters = method.GetParameters();
			object[] values = new object[parameters.Length];
			invoker = null;
			for (int i = 0; i < parameters.Length; i++)
			{
				ParameterInfo parameterInfo = parameters[i];
				Type parameterType = parameterInfo.ParameterType;
				if (services.TryGetService(parameterType, out var service))
				{
					values[i] = service;
				}
				else if (parameterType == typeof(string) && parameterInfo.GetCustomAttribute<RemainingTextAttribute>() != null)
				{
					if (!arguments.TryReadRemaining(out var result))
					{
						return false;
					}
					values[i] = result;
				}
				else
				{
					if (!arguments.TryReadNext(parameterType, out var value))
					{
						return false;
					}
					values[i] = value;
				}
			}
			arguments.Reset();
			invoker = (object instance) => ExecuteCommand(method, instance, values, commandAttribute?.ClearText ?? false);
			return true;
		}

		private static object ExecuteCommand(MethodInfo method, object instance, object[] arguments, bool clearConsole)
		{
			object obj;
			try
			{
				obj = method.Invoke(instance, arguments);
			}
			catch (Exception ex)
			{
				Console.WriteLine("Error caught while invoking command hander: " + ex.Message);
				Console.WriteLine(ex.StackTrace);
				return null;
			}
			if (obj == null)
			{
				return null;
			}
			Type type = obj.GetType();
			if (typeof(TerminalNode).IsAssignableFrom(type))
			{
				return obj;
			}
			if (typeof(ITerminalInteraction).IsAssignableFrom(type))
			{
				return obj;
			}
			if (typeof(ITerminalInterface).IsAssignableFrom(type))
			{
				return obj;
			}
			TerminalNode obj2 = ScriptableObject.CreateInstance<TerminalNode>();
			obj2.displayText = obj.ToString() + "\n";
			obj2.clearPreviousText = clearConsole;
			return obj2;
		}
	}
	public class CommandComparer : IComparer<TerminalCommand>
	{
		public int Compare(TerminalCommand x, TerminalCommand y)
		{
			if (x.Priority > y.Priority)
			{
				return 1;
			}
			if (x.Priority < y.Priority)
			{
				return -1;
			}
			return x.ArgumentCount.CompareTo(y.ArgumentCount);
		}
	}
	public static class CommandHandler
	{
		private static readonly Stack<ITerminalInteraction> m_Interactions = new Stack<ITerminalInteraction>();

		private static readonly Regex m_SplitRegex = new Regex("[\\\"](.+?)[\\\"]|([^ ]+)", RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture | RegexOptions.Compiled);

		private static readonly CommandComparer m_Comparer = new CommandComparer();

		public static int InteractionDepth => m_Interactions.Count;

		public static ITerminalInterface CurrentInterface { get; private set; }

		public static TerminalNode HandleCommandInput(string command, Terminal terminal)
		{
			string[] array = (from Match x in m_SplitRegex.Matches(command.Trim())
				select x.Value.Trim('"', ' ')).ToArray();
			ArgumentStream arguments = new ArgumentStream(array);
			if (CurrentInterface != null)
			{
				return CurrentInterface.HandleInput(terminal, arguments);
			}
			TerminalNode val = ExecuteInteractions(arguments, terminal);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			string commandName = array.First();
			ArgumentStream arguments2 = new ArgumentStream(array.Skip(1));
			return ExecuteCommand(commandName, arguments2, terminal);
		}

		public static TerminalNode ExecuteInteractions(ArgumentStream arguments, Terminal terminal)
		{
			while (m_Interactions.Count > 0)
			{
				ITerminalInteraction terminalInteraction = m_Interactions.Pop();
				arguments.Reset();
				try
				{
					terminalInteraction.Services.WithServices(arguments, terminal, arguments.Arguments);
					object obj = terminalInteraction.HandleTerminalResponse(arguments);
					if (obj != null)
					{
						return HandleCommandResult(obj, terminal);
					}
				}
				catch (Exception ex)
				{
					Console.WriteLine(ex.GetType().Name);
					Console.WriteLine("Error executing interaction: " + ex.Message + ", " + ex.StackTrace);
				}
			}
			return null;
		}

		public static TerminalNode ExecuteCommand(ArgumentStream arguments, Terminal terminal)
		{
			arguments.Reset();
			if (!arguments.TryReadNext(out string value))
			{
				return null;
			}
			ArgumentStream arguments2 = new ArgumentStream(arguments.Arguments.Skip(1));
			return ExecuteCommand(value, arguments2, terminal);
		}

		public static TerminalNode ExecuteCommand(string commandName, ArgumentStream arguments, Terminal terminal)
		{
			List<(TerminalCommand, Func<TerminalNode>)> list = new List<(TerminalCommand, Func<TerminalNode>)>();
			TerminalCommand[] array = TerminalRegistry.GetCommands(commandName).ToArray();
			ServiceCollection services = new ServiceCollection(arguments, arguments.Arguments, terminal);
			foreach (TerminalCommand terminalCommand in array)
			{
				if (!terminalCommand.CheckAllowed())
				{
					continue;
				}
				arguments.Reset();
				if (terminalCommand.TryCreateInvoker(arguments, services, out var invoker))
				{
					Func<TerminalNode> item = () => HandleCommandResult(invoker(), terminal);
					list.Add((terminalCommand, item));
				}
			}
			foreach (var item2 in list.OrderByDescending<(TerminalCommand, Func<TerminalNode>), TerminalCommand>(((TerminalCommand command, Func<TerminalNode> invoker) x) => x.command, m_Comparer))
			{
				TerminalNode val = item2.Item2();
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static TerminalNode HandleCommandResult(object result, Terminal terminal)
		{
			TerminalNode val = (TerminalNode)((result is TerminalNode) ? result : null);
			if (val != null)
			{
				return val;
			}
			if (result is ITerminalInteraction terminalInteraction)
			{
				SetInteraction(terminalInteraction);
				return terminalInteraction.Prompt;
			}
			if (result is ITerminalInterface terminalInterface)
			{
				SetInterface(terminalInterface);
				return terminalInterface.GetSplashScreen(terminal);
			}
			return ScriptableObject.CreateInstance<TerminalNode>().WithDisplayText(result);
		}

		public static void SetInteraction(ITerminalInteraction interaction)
		{
			m_Interactions.Push(interaction);
		}

		public static void SetInterface(ITerminalInterface terminalInterface)
		{
			CurrentInterface = terminalInterface;
		}

		public static void ResetInterface()
		{
			CurrentInterface = null;
		}

		public static void ResetInterface<T>() where T : ITerminalInterface
		{
			if (CurrentInterface != null && CurrentInterface is T)
			{
				ResetInterface();
			}
		}
	}
	public static class DefaultStringConverters
	{
		[StringConverter]
		public static string ParseString(string input)
		{
			return input;
		}

		[StringConverter]
		public static sbyte ParseSByte(string input)
		{
			if (sbyte.TryParse(input, out var result))
			{
				return result;
			}
			throw new ArgumentException();
		}

		[StringConverter]
		public static byte ParseByte(string input)
		{
			if (byte.TryParse(input, out var result))
			{
				return result;
			}
			throw new ArgumentException();
		}

		[StringConverter]
		public static short ParseShort(string input)
		{
			if (short.TryParse(input, out var result))
			{
				return result;
			}
			throw new ArgumentException();
		}

		[StringConverter]
		public static ushort ParseUShort(string input)
		{
			if (ushort.TryParse(input, out var result))
			{
				return result;
			}
			throw new ArgumentException();
		}

		[StringConverter]
		public static int ParseInt(string input)
		{
			if (int.TryParse(input, out var result))
			{
				return result;
			}
			throw new ArgumentException();
		}

		[StringConverter]
		public static uint ParseUInt(string input)
		{
			if (uint.TryParse(input, out var result))
			{
				return result;
			}
			throw new ArgumentException();
		}

		[StringConverter]
		public static long ParseLong(string input)
		{
			if (long.TryParse(input, out var result))
			{
				return result;
			}
			throw new ArgumentException();
		}

		[StringConverter]
		public static ulong ParseULong(string input)
		{
			if (ulong.TryParse(input, out var result))
			{
				return result;
			}
			throw new ArgumentException();
		}

		[StringConverter]
		public static float ParseFloat(string input)
		{
			if (float.TryParse(input, out var result))
			{
				return result;
			}
			throw new ArgumentException();
		}

		[StringConverter]
		public static double ParseDouble(string input)
		{
			if (double.TryParse(input, out var result))
			{
				return result;
			}
			throw new ArgumentException();
		}

		[StringConverter]
		public static decimal ParseDecimal(string input)
		{
			if (decimal.TryParse(input, out var result))
			{
				return result;
			}
			throw new ArgumentException();
		}

		[StringConverter]
		public static PlayerControllerB ParsePlayerControllerB(string value)
		{
			if ((Object)(object)StartOfRound.Instance == (Object)null)
			{
				throw new ArgumentException("Game has not started");
			}
			PlayerControllerB val = null;
			if (ulong.TryParse(value, out var steamID))
			{
				val = ((IEnumerable<PlayerControllerB>)StartOfRound.Instance.allPlayerScripts).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB x) => x.playerSteamId == steamID));
			}
			if ((Object)(object)val == (Object)null)
			{
				val = ((IEnumerable<PlayerControllerB>)StartOfRound.Instance.allPlayerScripts).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB x) => x.playerUsername.IndexOf(value, StringComparison.InvariantCultureIgnoreCase) != -1));
			}
			if ((Object)(object)val == (Object)null)
			{
				throw new ArgumentException("Failed to find player");
			}
			return val;
		}
	}
	public struct ServiceCollection
	{
		private Dictionary<Type, object> m_Services;

		public ServiceCollection(params object[] services)
		{
			m_Services = new Dictionary<Type, object>();
			WithServices(services);
		}

		public ServiceCollection()
		{
			m_Services = new Dictionary<Type, object>();
		}

		public bool TryGetService(Type t, out object service)
		{
			if (m_Services == null)
			{
				service = null;
				return false;
			}
			return m_Services.TryGetValue(t, out service);
		}

		public void WithService<T>(T instance)
		{
			if (m_Services != null)
			{
				m_Services[typeof(T)] = instance;
			}
		}

		public void WithServices(params object[] services)
		{
			if (m_Services == null)
			{
				return;
			}
			foreach (object obj in services)
			{
				if (obj != null)
				{
					m_Services.Add(obj.GetType(), obj);
				}
			}
		}
	}
	public delegate object StringConversionHandler(string value);
	public static class StringConverter
	{
		private static bool m_Initialized = false;

		public static ConcurrentDictionary<Type, StringConversionHandler> StringConverters { get; } = new ConcurrentDictionary<Type, StringConversionHandler>();


		public static bool TryConvert(string value, Type type, out object result)
		{
			if (!m_Initialized)
			{
				m_Initialized = true;
				RegisterFromType(typeof(DefaultStringConverters), null, replaceExisting: false);
			}
			if (!StringConverters.TryGetValue(type, out var value2))
			{
				result = null;
				return false;
			}
			try
			{
				result = value2(value);
				return true;
			}
			catch (Exception)
			{
			}
			result = null;
			return false;
		}

		public static void RegisterFrom<T>(T instance, bool replaceExisting = true) where T : class
		{
			RegisterFromType(typeof(T), instance, replaceExisting);
		}

		public static void RegisterFromType(Type type, object instance = null, bool replaceExisting = true)
		{
			MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo method in methods)
			{
				if (method.GetCustomAttribute<StringConverterAttribute>() == null)
				{
					continue;
				}
				ParameterInfo[] parameters = method.GetParameters();
				if (parameters.Length == 1 && !(parameters[0].ParameterType != typeof(string)))
				{
					Type returnType = method.ReturnType;
					StringConversionHandler value2 = (string value) => method.Invoke(instance, new object[1] { value });
					if (replaceExisting || !StringConverters.ContainsKey(returnType))
					{
						StringConverters[returnType] = value2;
					}
				}
			}
		}
	}
	public class TerminalCommand
	{
		private ManualLogSource m_LogSource = new ManualLogSource("LethalAPI.Terminal");

		public string Name { get; }

		public MethodInfo Method { get; }

		public object Instance { get; }

		public bool ClearConsole { get; }

		public int ArgumentCount { get; }

		public string Syntax { get; }

		public string Description { get; }

		public int Priority { get; }

		public TerminalCommand(string name, MethodInfo method, object instance, bool clearConsole, string syntax = null, string description = null, int priority = 0)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			Name = name;
			Method = method;
			Instance = instance;
			ClearConsole = clearConsole;
			ArgumentCount = method.GetParameters().Length;
			Syntax = syntax;
			Description = description;
			Priority = priority;
		}

		public bool CheckAllowed()
		{
			foreach (AccessControlAttribute customAttribute in Method.GetCustomAttributes<AccessControlAttribute>())
			{
				if (!customAttribute.CheckAllowed())
				{
					return false;
				}
			}
			return true;
		}

		public static TerminalCommand FromMethod(MethodInfo info, object instance, string overrideName = null)
		{
			bool clearConsole = false;
			string syntax = null;
			string description = null;
			string text = overrideName;
			int priority = 0;
			TerminalCommandAttribute customAttribute = info.GetCustomAttribute<TerminalCommandAttribute>();
			if (customAttribute != null)
			{
				text = text ?? customAttribute.CommandName;
				clearConsole = customAttribute.ClearText;
			}
			CommandInfoAttribute customAttribute2 = info.GetCustomAttribute<CommandInfoAttribute>();
			if (customAttribute2 != null)
			{
				syntax = customAttribute2.Syntax;
				description = customAttribute2.Description;
			}
			CommandPriority customAttribute3 = info.GetCustomAttribute<CommandPriority>();
			if (customAttribute3 != null)
			{
				priority = customAttribute3.Priority;
			}
			return new TerminalCommand(text, info, instance, clearConsole, syntax, description, priority);
		}

		public bool TryCreateInvoker(ArgumentStream arguments, ServiceCollection services, out Func<object> invoker)
		{
			if (CommandActivator.TryCreateInvoker(arguments, services, Method, out var activatedInvoker))
			{
				invoker = () => activatedInvoker(Instance);
				return true;
			}
			invoker = null;
			return false;
		}
	}
	public class TerminalModRegistry
	{
		public List<TerminalCommand> Commands { get; } = new List<TerminalCommand>();


		public T RegisterFrom<T>() where T : class, new()
		{
			return RegisterFrom(new T());
		}

		public T RegisterFrom<T>(T instance) where T : class
		{
			foreach (MethodInfo commandMethod in TerminalRegistry.GetCommandMethods<T>())
			{
				TerminalCommand terminalCommand = TerminalCommand.FromMethod(commandMethod, instance);
				TerminalRegistry.RegisterCommand(terminalCommand);
				lock (Commands)
				{
					Commands.Add(terminalCommand);
				}
			}
			StringConverter.RegisterFrom(instance);
			return instance;
		}

		public void Deregister()
		{
			if (Commands != null)
			{
				for (int i = 0; i < Commands.Count; i++)
				{
					TerminalRegistry.Deregister(Commands[i]);
				}
			}
		}
	}
	public class TerminalRegistry
	{
		private static readonly ConcurrentDictionary<string, List<TerminalCommand>> m_RegisteredCommands = new ConcurrentDictionary<string, List<TerminalCommand>>(StringComparer.InvariantCultureIgnoreCase);

		public static TerminalModRegistry RegisterFrom<T>(T instance) where T : class
		{
			TerminalModRegistry terminalModRegistry = new TerminalModRegistry();
			foreach (MethodInfo commandMethod in GetCommandMethods<T>())
			{
				TerminalCommand terminalCommand = TerminalCommand.FromMethod(commandMethod, instance);
				RegisterCommand(terminalCommand);
				terminalModRegistry.Commands.Add(terminalCommand);
			}
			StringConverter.RegisterFrom(instance);
			return terminalModRegistry;
		}

		public static TerminalModRegistry CreateTerminalRegistry()
		{
			return new TerminalModRegistry();
		}

		public static void RegisterCommand(TerminalCommand command)
		{
			if (!m_RegisteredCommands.TryGetValue(command.Name, out var value))
			{
				value = new List<TerminalCommand>();
				m_RegisteredCommands[command.Name] = value;
			}
			lock (value)
			{
				value.Add(command);
			}
		}

		public static void Deregister(TerminalCommand command)
		{
			if (!m_RegisteredCommands.TryGetValue(command.Name, out var value))
			{
				return;
			}
			lock (value)
			{
				value.Remove(command);
			}
		}

		public static IReadOnlyList<TerminalCommand> GetCommands(string commandName)
		{
			if (m_RegisteredCommands.TryGetValue(commandName, out var value))
			{
				return value;
			}
			return new List<TerminalCommand>();
		}

		public static IEnumerable<TerminalCommand> EnumerateCommands(string name)
		{
			if (!m_RegisteredCommands.TryGetValue(name, out var value))
			{
				return Enumerable.Empty<TerminalCommand>();
			}
			return value;
		}

		public static IEnumerable<TerminalCommand> EnumerateCommands()
		{
			string[] keys = m_RegisteredCommands.Keys.ToArray();
			for (int i = 0; i < keys.Length; i++)
			{
				List<TerminalCommand> overloads = m_RegisteredCommands[keys[i]];
				for (int c = 0; c < overloads.Count; c++)
				{
					yield return overloads[c];
				}
			}
		}

		public static IEnumerable<MethodInfo> GetCommandMethods<T>()
		{
			MethodInfo[] methods = typeof(T).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.GetCustomAttribute<TerminalCommandAttribute>() != null)
				{
					yield return methodInfo;
				}
			}
		}
	}
	public static class TextUtil
	{
		public static string SetEndPadding(this string text, char character, int minPadding)
		{
			string text2 = text;
			int num = 0;
			int num2 = text.Length - 1;
			while (num2 >= 0 && text[num2] == character)
			{
				num++;
				num2--;
			}
			int num3 = minPadding - num;
			if (num3 > 0)
			{
				text2 += new string(character, num3);
			}
			return text2;
		}

		public static string SetStartPadding(this string text, char character, int minPadding)
		{
			string text2 = text;
			int num = 0;
			for (int i = 0; i < text.Length && text[i] == character; i++)
			{
				num++;
			}
			int num2 = minPadding - num;
			if (num2 > 0)
			{
				text2 = new string(character, num2) + text2;
			}
			return text2;
		}
	}
}
namespace LethalAPI.LibTerminal.Models.Enums
{
	public enum AllowedCaller
	{
		None = -1,
		Player,
		Host
	}
	public enum SyncedTerminalClip
	{
		ItemPurchased,
		Error,
		BroadcastEffect
	}
}
namespace LethalAPI.LibTerminal.Interfaces
{
	public interface ITerminalInteraction
	{
		TerminalNode Prompt { get; }

		ServiceCollection Services { get; }

		object HandleTerminalResponse(ArgumentStream arguments);
	}
	public interface ITerminalInterface
	{
		bool APITextPostProcessing { get; }

		bool VanillaTextPostProcessing { get; }

		TerminalNode HandleInput(Terminal instance, ArgumentStream arguments);

		string PreProcessText(Terminal instance, string text);

		string PostProcessText(Terminal terminal, string text);

		TerminalNode GetSplashScreen(Terminal terminal);
	}
}
namespace LethalAPI.LibTerminal.Interactions
{
	public class ConfirmInteraction : ITerminalInteraction
	{
		public TerminalNode Prompt { get; private set; }

		public ServiceCollection Services { get; } = new ServiceCollection();


		public Delegate ConfirmHandler { get; set; }

		public Delegate DenyHandler { get; set; }

		public ConfirmInteraction()
		{
		}

		public ConfirmInteraction(TerminalNode prompt)
		{
			Prompt = prompt;
			PostprocessPrompt();
		}

		public ConfirmInteraction(Action<TerminalNode> promptBuilder)
		{
			TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
			promptBuilder(val);
			WithPrompt(val);
		}

		public ConfirmInteraction(TerminalNode prompt, Delegate confirm, Delegate deny)
		{
			WithPrompt(prompt);
			ConfirmHandler = confirm;
			DenyHandler = deny;
		}

		public ConfirmInteraction(Action<TerminalNode> promptBuilder, Delegate confirm, Delegate deny)
		{
			WithPrompt(promptBuilder);
			ConfirmHandler = confirm;
			DenyHandler = deny;
		}

		public ConfirmInteraction(string prompt)
		{
			WithPrompt(prompt);
		}

		public ConfirmInteraction(string prompt, Delegate confirm, Delegate deny)
		{
			WithPrompt(prompt);
			ConfirmHandler = confirm;
			DenyHandler = deny;
		}

		public ConfirmInteraction WithPrompt(string prompt)
		{
			Prompt = ScriptableObject.CreateInstance<TerminalNode>();
			Prompt.WithDisplayText(prompt);
			PostprocessPrompt();
			return this;
		}

		public ConfirmInteraction WithPrompt(TerminalNode prompt)
		{
			Prompt = prompt;
			PostprocessPrompt();
			return this;
		}

		public ConfirmInteraction WithPrompt(Action<TerminalNode> promptBuilder)
		{
			TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
			promptBuilder(val);
			WithPrompt(val);
			return this;
		}

		public ConfirmInteraction Confirm(Delegate confirmHandler)
		{
			ConfirmHandler = confirmHandler;
			return this;
		}

		public ConfirmInteraction Deny(Delegate denyHandler)
		{
			DenyHandler = denyHandler;
			return this;
		}

		public ConfirmInteraction WithContext(params object[] services)
		{
			Services.WithServices(services);
			return this;
		}

		public object HandleTerminalResponse(ArgumentStream arguments)
		{
			if (!arguments.TryReadNext(out string value))
			{
				return Deny(arguments);
			}
			if (value.Trim().Equals("confirm", StringComparison.InvariantCultureIgnoreCase))
			{
				return Confirm(arguments);
			}
			return Deny(arguments);
		}

		private object Confirm(ArgumentStream arguments)
		{
			if ((object)DenyHandler == null)
			{
				return string.Empty;
			}
			if (CommandActivator.TryCreateInvoker(arguments, Services, ConfirmHandler.GetMethodInfo(), out var invoker))
			{
				return invoker(ConfirmHandler.Target);
			}
			return null;
		}

		private object Deny(ArgumentStream arguments)
		{
			if ((object)DenyHandler == null)
			{
				return string.Empty;
			}
			if (CommandActivator.TryCreateInvoker(arguments, Services, DenyHandler.GetMethodInfo(), out var invoker))
			{
				return invoker(DenyHandler.Target);
			}
			return null;
		}

		private void PostprocessPrompt()
		{
			string text = Prompt.displayText ?? string.Empty;
			text = text.SetEndPadding('\n', 2) + "Please CONFIRM or DENY.\n";
			Prompt.displayText = text;
		}
	}
	public class TerminalInteraction : ITerminalInteraction
	{
		public TerminalNode Prompt { get; private set; }

		public ServiceCollection Services { get; } = new ServiceCollection();


		public List<Delegate> Handlers { get; } = new List<Delegate>();


		public TerminalInteraction()
		{
		}

		public TerminalInteraction(TerminalNode prompt, Delegate handler)
		{
			Prompt = prompt;
			Handlers.Add(handler);
		}

		public TerminalInteraction(Action<TerminalNode> promptBuilder, Delegate handler)
		{
			TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
			promptBuilder(val);
			WithPrompt(val);
			Handlers.Add(handler);
		}

		public TerminalInteraction WithContext(params object[] services)
		{
			Services.WithServices(services);
			return this;
		}

		public TerminalInteraction WithPrompt(TerminalNode prompt)
		{
			Prompt = prompt;
			return this;
		}

		public TerminalInteraction WithPrompt(Action<TerminalNode> promptBuilder)
		{
			TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
			promptBuilder(val);
			WithPrompt(val);
			return this;
		}

		public TerminalInteraction WithPrompt(string prompt)
		{
			Prompt = ScriptableObject.CreateInstance<TerminalNode>();
			Prompt.WithDisplayText(prompt);
			return this;
		}

		public TerminalInteraction WithHandler(Delegate handler)
		{
			Handlers.Add(handler);
			return this;
		}

		public object HandleTerminalResponse(ArgumentStream arguments)
		{
			(from x in Handlers
				select (x.GetMethodInfo(), x.Target) into x
				orderby x.info.GetParameters().Length descending
				select x).ToList();
			foreach (Delegate handler in Handlers)
			{
				MethodInfo methodInfo = handler.GetMethodInfo();
				arguments.Reset();
				if (CommandActivator.TryCreateInvoker(arguments, Services, methodInfo, out var invoker))
				{
					object obj = invoker(handler.Target);
					if (obj != null)
					{
						return obj;
					}
				}
			}
			return null;
		}
	}
}
namespace LethalAPI.LibTerminal.Helpers
{
	internal static class MiscHelper
	{
		public static string Buffer(string input)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine();
			stringBuilder.AppendLine();
			stringBuilder.AppendLine();
			stringBuilder.AppendLine(input);
			Console.WriteLine(stringBuilder.ToString());
			return stringBuilder.ToString();
		}

		public static bool IsGameStarted()
		{
			return Object.FindFirstObjectByType<StartMatchLever>().leverHasBeenPulled;
		}

		public static string GetObjectProperties(object obj)
		{
			if (obj == null)
			{
				return "The provided object is null.";
			}
			StringBuilder stringBuilder = new StringBuilder();
			Type type = obj.GetType();
			stringBuilder.AppendLine("Properties of " + type.Name + ":");
			PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (PropertyInfo propertyInfo in properties)
			{
				try
				{
					object value = propertyInfo.GetValue(obj, null);
					stringBuilder.AppendLine($"{propertyInfo.Name}: {value}");
				}
				catch (Exception ex)
				{
					stringBuilder.AppendLine(propertyInfo.Name + ": Could not read value (" + ex.Message + ")");
				}
			}
			return stringBuilder.ToString();
		}
	}
	internal static class TimeHelper
	{
		public static string GetTime()
		{
			if (MiscHelper.IsGameStarted())
			{
				return DecimalToTimeString(TimeOfDay.Instance.normalizedTimeOfDay);
			}
			return null;
		}

		public static string DecimalToTimeString(float time)
		{
			int num = 8;
			int num2 = 1080;
			int num3 = (int)(time * (float)num2);
			return DateTime.Today.AddHours(num).AddMinutes(num3).AddHours(-2.0)
				.ToString("h:mm tt");
		}
	}
}
namespace LethalAPI.LibTerminal.Commands
{
	internal class CheatCommands
	{
		[TerminalCommand("GiveMoney", true, false)]
		[CommandInfo("Makes you a dirty cheater", "[Amount]")]
		public string GiveMoneyCommand(int amount)
		{
			Terminal obj = Object.FindObjectOfType<Terminal>();
			obj.groupCredits += amount;
			return MiscHelper.Buffer($"${amount} was added, cheater!");
		}
	}
	public class CommandInfoCommands
	{
		[TerminalCommand("Other", true, true)]
		public string CommandList()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine(MiscHelper.Buffer("Other commands:"));
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("> VIEW MONITOR");
			stringBuilder.AppendLine("To toggle on/off the main monitor's map cam");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("> SWITCH {RADAR}");
			stringBuilder.AppendLine("To switch the player view on the main monitor");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("> PING [Radar booster name]");
			stringBuilder.AppendLine("Ping the designated radar booster");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("> SCAN");
			stringBuilder.AppendLine("To scan for the number of items left on the current planet");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("> TRANSMIT [message]");
			stringBuilder.AppendLine("Transmit a message with the signal translator");
			stringBuilder.AppendLine();
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string namespaceName = GetType().Namespace;
			foreach (Type item in from t in executingAssembly.GetTypes()
				where string.Equals(t.Namespace, namespaceName, StringComparison.Ordinal)
				select t)
			{
				MethodInfo[] methods = item.GetMethods(BindingFlags.Instance | BindingFlags.Public);
				foreach (MethodInfo methodInfo in methods)
				{
					TerminalCommandAttribute customAttribute = methodInfo.GetCustomAttribute<TerminalCommandAttribute>();
					if (customAttribute == null || (methodInfo.DeclaringType == GetType() && methodInfo.Name.Equals("CommandList", StringComparison.OrdinalIgnoreCase)) || !customAttribute.ShowHelp)
					{
						continue;
					}
					string text = customAttribute.CommandName ?? methodInfo.Name;
					CommandInfoAttribute customAttribute2 = methodInfo.GetCustomAttribute<CommandInfoAttribute>();
					stringBuilder.AppendLine("> " + text.ToUpper());
					if (customAttribute2 != null)
					{
						if (!string.IsNullOrWhiteSpace(customAttribute2.Syntax))
						{
							stringBuilder.AppendLine(customAttribute2.Description + " - " + customAttribute2.Syntax);
						}
						else
						{
							stringBuilder.AppendLine(customAttribute2.Description);
						}
					}
					stringBuilder.AppendLine();
				}
			}
			return stringBuilder.ToString();
		}

		[TerminalCommand("Help", false, true)]
		[CommandInfo("Shows further information about a command", "[Command]")]
		public string HelpCommand(string name)
		{
			StringBuilder stringBuilder = new StringBuilder();
			TerminalCommand[] array = TerminalRegistry.EnumerateCommands(name).ToArray();
			if (array.Length == 0)
			{
				return "Unknown command: '" + name + "'";
			}
			TerminalCommand[] array2 = array;
			foreach (TerminalCommand terminalCommand in array2)
			{
				stringBuilder.AppendLine(">" + terminalCommand.Name.ToUpper() + " " + terminalCommand.Syntax?.ToUpper());
				stringBuilder.AppendLine(terminalCommand.Description);
				if (!terminalCommand.CheckAllowed())
				{
					stringBuilder.AppendLine("[Host Only]");
				}
				stringBuilder.AppendLine();
			}
			return stringBuilder.ToString();
		}
	}
	internal class EntityCommands
	{
		[TerminalCommand("ListMines", true, true)]
		[CommandInfo("Lists all landmines", "")]
		public string ListMines()
		{
			return ListObjectsByName("Landmine");
		}

		[TerminalCommand("ListTurrets", true, true)]
		[CommandInfo("Lists all turrets", "")]
		public string ListTurrets()
		{
			return ListObjectsByName("TurretScript");
		}

		[TerminalCommand("ListDoors", true, true)]
		[CommandInfo("Lists all facility doors", "")]
		public string ListDoors()
		{
			return ListObjectsByName("BigDoor", startsWith: true);
		}

		[TerminalCommand("Detonate", true, true)]
		[CommandInfo("Detonates designated landmine(s)", "[All / Mine Id]")]
		public string DetonateLandmineCommand(string code)
		{
			if (string.IsNullOrEmpty(code))
			{
				return MiscHelper.Buffer("No valid identifier provided!");
			}
			TerminalAccessibleObject[] source = Object.FindObjectsOfType<TerminalAccessibleObject>();
			Landmine[] array = Object.FindObjectsOfType<Landmine>();
			TerminalAccessibleObject selectedObject = source.Where((TerminalAccessibleObject tao) => tao.objectCode.ToLower() == code.ToLower()).FirstOrDefault();
			if ((Object)(object)selectedObject != (Object)null)
			{
				Landmine val = array.Where((Landmine l) => ((NetworkBehaviour)l).NetworkObjectId == ((NetworkBehaviour)selectedObject).NetworkObjectId).FirstOrDefault();
				if (val.hasExploded)
				{
					return MiscHelper.Buffer(code + " has already detonated!");
				}
				val.ExplodeMineServerRpc();
				val.Detonate();
				return MiscHelper.Buffer("Kaboom! " + code + " has been detonated!");
			}
			if (code.ToLower() == "all")
			{
				int num = 0;
				Landmine[] array2 = array;
				foreach (Landmine val2 in array2)
				{
					if (!val2.hasExploded)
					{
						num++;
						val2.ExplodeMineServerRpc();
						val2.Detonate();
					}
				}
				if (num > 0)
				{
					return MiscHelper.Buffer($"Kaboom! Detonating {num} landmines!");
				}
				return MiscHelper.Buffer("There were no mines to detonate!");
			}
			return MiscHelper.Buffer("Landmine " + code + " not found!");
		}

		[TerminalCommand("Berserk", true, true)]
		[CommandInfo("Makes designated turret(s) go berserk", "[All / Turret Id]")]
		public string TurretBerserkCommand(string code)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Invalid comparison between Unknown and I4
			if (string.IsNullOrEmpty(code))
			{
				return MiscHelper.Buffer("No valid identifier provided!");
			}
			int num = (int)GameNetworkManager.Instance.localPlayerController.playerClientId;
			TerminalAccessibleObject[] source = Object.FindObjectsOfType<TerminalAccessibleObject>();
			Turret[] array = Object.FindObjectsOfType<Turret>();
			TerminalAccessibleObject selectedObject = source.Where((TerminalAccessibleObject tao) => tao.objectCode.ToLower() == code.ToLower()).FirstOrDefault();
			if ((Object)(object)selectedObject != (Object)null)
			{
				Turret val = array.Where((Turret l) => ((NetworkBehaviour)l).NetworkObjectId == ((NetworkBehaviour)selectedObject).NetworkObjectId).FirstOrDefault();
				if ((int)val.turretMode == 3)
				{
					val.SetToModeClientRpc(0);
					return MiscHelper.Buffer(code + " has calmed down.");
				}
				val.EnterBerserkModeServerRpc(num);
				return MiscHelper.Buffer("Danger! " + code + " has gone berserk!");
			}
			if (code.ToLower() == "all")
			{
				int num2 = 0;
				Turret[] array2 = array;
				foreach (Turret obj in array2)
				{
					num2++;
					obj.EnterBerserkModeServerRpc(num);
				}
				if (num2 > 0)
				{
					return MiscHelper.Buffer($"Danger! {num2} turrets have gone berserk!");
				}
				return MiscHelper.Buffer("There were no turrets found!");
			}
			return MiscHelper.Buffer("Turret " + code + " not found!");
		}

		private string ListObjectsByName(string objectName, bool startsWith = false)
		{
			StringBuilder stringBuilder = new StringBuilder();
			TerminalAccessibleObject[] array = Object.FindObjectsOfType<TerminalAccessibleObject>();
			foreach (TerminalAccessibleObject val in array)
			{
				if (startsWith ? ((Object)val).name.StartsWith(objectName) : (((Object)val).name == objectName))
				{
					stringBuilder.AppendLine(val.objectCode);
				}
			}
			return MiscHelper.Buffer(stringBuilder.ToString());
		}
	}
	internal class EquipmentCommands
	{
		[TerminalCommand("Teleport", false, false)]
		[CommandInfo("Teleport the specified member of the crew", "[Player Name]")]
		public string TeleportCommand()
		{
			return TeleportCommand(null);
		}

		[TerminalCommand("Teleport", false, true)]
		[CommandInfo("Teleport the specified member of the crew", "[Player Name]")]
		public string TeleportCommand(PlayerControllerB player = null)
		{
			Console.WriteLine("Teleporting");
			ShipTeleporter teleporter = FindTeleporter(isInverse: false);
			string text = CanUseTeleporter(teleporter);
			if (text != null)
			{
				return MiscHelper.Buffer(text);
			}
			if ((Object)(object)player == (Object)null && (Object)(object)StartOfRound.Instance.mapScreen.targetedPlayer == (Object)null)
			{
				return MiscHelper.Buffer("No player selected or found to teleport.");
			}
			if ((Object)(object)player == (Object)null)
			{
				player = StartOfRound.Instance.mapScreen.targetedPlayer;
				Teleport(teleporter);
			}
			else
			{
				PlayerControllerB targetedPlayer = StartOfRound.Instance.mapScreen.targetedPlayer;
				StartOfRound.Instance.mapScreen.targetedPlayer = player;
				Teleport(teleporter);
				StartOfRound.Instance.mapScreen.targetedPlayer = targetedPlayer;
			}
			return MiscHelper.Buffer("Teleporting " + player.playerUsername + "...");
		}

		[TerminalCommand("Inverse", false, true)]
		[CommandInfo("Start the inverse teleporter", "")]
		public string InverseTeleportCommand()
		{
			Console.WriteLine("Inverse Teleporting");
			ShipTeleporter teleporter = FindTeleporter(isInverse: true);
			string text = CanUseTeleporter(teleporter);
			if (text != null)
			{
				return MiscHelper.Buffer(text);
			}
			Teleport(teleporter);
			return MiscHelper.Buffer("Have a safe trip!");
		}

		[TerminalCommand("ResetInverse", false, true)]
		[CommandInfo("Resets the inverse teleporter cooldown. DO NOT ABUSE.", "")]
		public string ResetInverseCommand()
		{
			ShipTeleporter teleporter = FindTeleporter(isInverse: true);
			ResetCooldown(teleporter);
			return MiscHelper.Buffer("Inverse Teleporter Cooldown reset.");
		}

		[TerminalCommand("Reset", false, false)]
		[CommandInfo("Shortcut for ResetInverse.", "")]
		public string ResetCommand()
		{
			return ResetInverseCommand();
		}

		[TerminalCommand("Scramble", false, true)]
		[CommandInfo("Reset then activate inverse teleporter.", "")]
		public string ScrambleCommand()
		{
			ResetInverseCommand();
			return InverseTeleportCommand();
		}

		private ShipTeleporter FindTeleporter(bool isInverse)
		{
			return ((IEnumerable<ShipTeleporter>)Object.FindObjectsOfType<ShipTeleporter>()).FirstOrDefault((Func<ShipTeleporter, bool>)((ShipTeleporter t) => t.isInverseTeleporter == isInverse));
		}

		private void Teleport(ShipTeleporter teleporter)
		{
			((UnityEvent<PlayerControllerB>)(object)teleporter.buttonTrigger.onInteract).Invoke(GameNetworkManager.Instance.localPlayerController);
		}

		private void ResetCooldown(ShipTeleporter teleporter)
		{
			teleporter.buttonTrigger.currentCooldownValue = 0f;
			teleporter.buttonTrigger.interactable = true;
		}

		private string CanUseTeleporter(ShipTeleporter teleporter)
		{
			if (teleporter == null)
			{
				return "There is no teleporter to use.";
			}
			if (!teleporter.buttonTrigger.interactable)
			{
				int privateFieldValue = GetPrivateFieldValue<int>(teleporter, "cooldownTime");
				if (privateFieldValue != 0)
				{
					Console.WriteLine("Cooldown Time: " + privateFieldValue);
					return $"The teleporter is on cooldown for {privateFieldValue}.";
				}
				Console.WriteLine("Field 'cooldownTime' not found.");
				return "The teleporter is on cooldown.";
			}
			return null;
		}

		private T GetPrivateFieldValue<T>(object instance, string fieldName)
		{
			FieldInfo field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
			if (field != null)
			{
				return (T)field.GetValue(instance);
			}
			return default(T);
		}
	}
	internal class InfoCommands
	{
		[TerminalCommand("Time", true, true)]
		[CommandInfo("Tells time", "")]
		public string TimeCommand()
		{
			string time = TimeHelper.GetTime();
			if (string.IsNullOrEmpty(time))
			{
				return MiscHelper.Buffer("There are no clocks in interstellar space.");
			}
			return MiscHelper.Buffer("Time: " + time);
		}

		[TerminalCommand("Status", true, true)]
		[CommandInfo("Get status of all crewmembers.", "")]
		public string StatusCommand()
		{
			PlayerControllerB[] array = Object.FindObjectsOfType<PlayerControllerB>();
			StringBuilder stringBuilder = new StringBuilder();
			PlayerControllerB[] array2 = array;
			foreach (PlayerControllerB val in array2)
			{
				if (!val.playerUsername.StartsWith("Player #"))
				{
					stringBuilder.AppendLine(BuildPlayerStatus(val));
				}
			}
			return MiscHelper.Buffer(stringBuilder.ToString());
		}

		[TerminalCommand("Status", true, true)]
		[CommandInfo("Get status of selected crewmembers.", "[Player name]")]
		public string StatusCommand(PlayerControllerB selectedPlayer)
		{
			return MiscHelper.Buffer(BuildPlayerStatus(selectedPlayer));
		}

		[TerminalCommand("Clear", true, true)]
		[CommandInfo("Clear the console.", "")]
		public string ClearCommand()
		{
			return MiscHelper.Buffer("");
		}

		private string BuildPlayerStatus(PlayerControllerB player)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("/// " + player.playerUsername + " ///");
			stringBuilder.AppendLine((!player.isPlayerDead) ? $"Health: {player.health}%" : $"Cause of death: {player.causeOfDeath}");
			stringBuilder.AppendLine();
			return stringBuilder.ToString();
		}
	}
	internal class PlayerCommands
	{
	}
	internal class ShipCommands
	{
		[TerminalCommand("Lights", false, true)]
		[CommandInfo("Toggle the lights.", "")]
		public string LightsCommand()
		{
			((UnityEvent<PlayerControllerB>)(object)GameObject.Find("LightSwitch").GetComponent<InteractTrigger>().onInteract).Invoke(GameNetworkManager.Instance.localPlayerController);
			return MiscHelper.Buffer("Toggled lights.");
		}

		[TerminalCommand("Doors", false, false)]
		public string ToggleDoorsCommand()
		{
			return ToggleDoorCommand();
		}

		[TerminalCommand("Door", false, true)]
		[CommandInfo("Toggle the door", "")]
		public string ToggleDoorCommand()
		{
			if (!StartOfRound.Instance.hangarDoorsClosed)
			{
				return CloseCommand();
			}
			return OpenCommand();
		}

		[TerminalCommand("Close", false, true)]
		[CommandInfo("Close the door", "")]
		public string CloseCommand()
		{
			Console.WriteLine("Closing Door");
			string text = CanUseDoor();
			if (text != null)
			{
				return text;
			}
			TriggerInteract("StopButton");
			HangarShipDoor val = FindHangarShipDoor();
			val.PlayDoorAnimation(true);
			return "Closing Door. Door power: " + GetDoorPower(val.doorPower);
		}

		[TerminalCommand("Open", false, true)]
		[CommandInfo("Open the door", "")]
		public string OpenCommand()
		{
			Console.WriteLine("Opening Door");
			string text = CanUseDoor();
			if (text != null)
			{
				return text;
			}
			TriggerInteract("StartButton");
			HangarShipDoor val = FindHangarShipDoor();
			val.PlayDoorAnimation(false);
			return "Opening Door. Door power: " + GetDoorPower(val.doorPower);
		}

		[TerminalCommand("Launch", false, true)]
		[CommandInfo("Launch the ship", "")]
		public string LaunchCommand()
		{
			if (!StartOfRound.Instance.shipHasLanded)
			{
				return MiscHelper.Buffer("You need to land first!");
			}
			InteractTrigger componentInChildren = GameObject.Find("StartGameLever").GetComponentInChildren<InteractTrigger>();
			StartMatchLever val = Object.FindObjectOfType<StartMatchLever>();
			((UnityEvent<PlayerControllerB>)(object)componentInChildren.onInteract).Invoke(GameNetworkManager.Instance.localPlayerController);
			val.EndGame();
			val.PlayLeverPullEffectsServerRpc(false);
			return MiscHelper.Buffer("Launching the ship...");
		}

		[TerminalCommand("GTFO", false, false)]
		[CommandInfo("GET ME OUTTA HERE!", "")]
		public string GTFOCommand()
		{
			LaunchCommand();
			return MiscHelper.Buffer("RUN AWAY!!!1!!");
		}

		[TerminalCommand("Land", false, true)]
		[CommandInfo("Land the ship", "")]
		public string LandCommand()
		{
			if (StartOfRound.Instance.shipHasLanded)
			{
				return MiscHelper.Buffer("You're already on the ground, dummy!");
			}
			string text = CanStartGame();
			if (!string.IsNullOrEmpty(text))
			{
				return MiscHelper.Buffer(text);
			}
			Console.WriteLine("Landing");
			InteractTrigger componentInChildren = GameObject.Find("StartGameLever").GetComponentInChildren<InteractTrigger>();
			StartMatchLever val = Object.FindObjectOfType<StartMatchLever>();
			((UnityEvent<PlayerControllerB>)(object)componentInChildren.onInteract).Invoke(GameNetworkManager.Instance.localPlayerController);
			val.StartGame();
			val.PlayLeverPullEffectsServerRpc(true);
			return MiscHelper.Buffer("Landing the ship...");
		}

		private string CanStartGame()
		{
			GameNetworkManager val = ((IEnumerable<GameNetworkManager>)Object.FindObjectsOfType<GameNetworkManager>()).FirstOrDefault((Func<GameNetworkManager, bool>)((GameNetworkManager x) => (Object)(object)x.localPlayerController != (Object)null));
			if (val.gameHasStarted)
			{
				return null;
			}
			if (val.isHostingGame)
			{
				return null;
			}
			return "The host must be the one to start the game!";
		}

		private string CanUseDoor()
		{
			if (MiscHelper.IsGameStarted())
			{
				return null;
			}
			return "You really shouldn't mess with the doors while in orbit.";
		}

		private string GetDoorPower(float doorPower)
		{
			return $"{doorPower * 100f:0\\%}";
		}

		private void TriggerInteract(string buttonName)
		{
			((UnityEvent<PlayerControllerB>)(object)GameObject.Find(buttonName).GetComponentInChildren<InteractTrigger>().onInteract).Invoke(GameNetworkManager.Instance.localPlayerController);
		}

		private HangarShipDoor FindHangarShipDoor()
		{
			return Object.FindObjectsOfType<HangarShipDoor>().FirstOrDefault();
		}
	}
}
namespace LethalAPI.LibTerminal.Attributes
{
	[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
	public abstract class AccessControlAttribute : Attribute
	{
		public abstract bool CheckAllowed();
	}
	[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
	public class AllowedCallerAttribute : AccessControlAttribute
	{
		public AllowedCaller Caller { get; }

		public AllowedCallerAttribute(AllowedCaller caller)
		{
			Caller = caller;
		}

		public override bool CheckAllowed()
		{
			switch (Caller)
			{
			case AllowedCaller.None:
				return false;
			case AllowedCaller.Player:
				return true;
			case AllowedCaller.Host:
				if ((Object)(object)StartOfRound.Instance == (Object)null)
				{
					return false;
				}
				return ((NetworkBehaviour)StartOfRound.Instance).IsHost;
			default:
				return true;
			}
		}
	}
	[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
	public class CommandInfoAttribute : Attribute
	{
		public string Syntax { get; }

		public string Description { get; }

		public CommandInfoAttribute(string description, string syntax = "")
		{
			Syntax = syntax;
			Description = description;
		}
	}
	public sealed class CommandPriority : Attribute
	{
		public int Priority { get; }

		public CommandPriority(int priority)
		{
			Priority = priority;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter)]
	public sealed class RemainingTextAttribute : Attribute
	{
	}
	public class RequireInterfaceAttribute : AccessControlAttribute
	{
		public Type InterfaceType { get; }

		public RequireInterfaceAttribute(Type interfaceType)
		{
			InterfaceType = interfaceType;
		}

		public override bool CheckAllowed()
		{
			if (CommandHandler.CurrentInterface != null)
			{
				return CommandHandler.CurrentInterface.GetType() == InterfaceType;
			}
			return false;
		}
	}
	public sealed class RequireInterfaceAttribute<T> : RequireInterfaceAttribute where T : ITerminalInterface
	{
		public RequireInterfaceAttribute()
			: base(typeof(T))
		{
		}
	}
	public sealed class StringConverterAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
	public class TerminalCommandAttribute : Attribute
	{
		public string CommandName { get; }

		public bool ClearText { get; }

		public bool ShowHelp { get; }

		public TerminalCommandAttribute(string name, bool clearText = false, bool showHelp = true)
		{
			CommandName = name;
			ClearText = clearText;
			ShowHelp = showHelp;
		}
	}
}