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;
}
}
}