using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using LethalNetworkAPI;
using TMPro;
using TerminalApi;
using TerminalApi.Classes;
using TerminalCommander.Patches;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Terminal Commander")]
[assembly: AssemblyDescription("Terminal Commander is a mod for Lethal Company designed to enhance your terminal operation experience by introducing convenient hotkeys. This mod simplifies various tasks, allowing you to manage turrets, landmines, player views, and communication more efficiently.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Tronal")]
[assembly: AssemblyProduct("Terminal Commander")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("a339852b-b956-4a52-89e6-21f22b77c5cc")]
[assembly: AssemblyFileVersion("1.8.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.8.0.0")]
namespace TerminalCommander
{
[Serializable]
public class TerminalCommanderConfiguration
{
public bool AllowJamming { get; set; } = true;
public bool AllowBigDoors { get; set; } = true;
public int JammingCoolDown { get; set; } = 0;
public int BigDoorsCoolDown { get; set; } = 0;
public KeyCode JammingKey { get; set; } = (KeyCode)106;
public KeyCode DoorKey { get; set; } = (KeyCode)100;
public KeyCode SwitchKey { get; set; } = (KeyCode)115;
public KeyCode MonitorKey { get; set; } = (KeyCode)109;
public KeyCode TransmitKey { get; set; } = (KeyCode)116;
public KeyCode TeleportKey { get; set; } = (KeyCode)119;
public KeyCode InverseTeleportKey { get; set; } = (KeyCode)105;
public void Set_Configs(Commander c)
{
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_0146: Unknown result type (might be due to invalid IL or missing references)
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
//IL_018e: Unknown result type (might be due to invalid IL or missing references)
AllowJamming = ((BaseUnityPlugin)c).Config.Bind<bool>("Gameplay", "Allow jamming", true, "If false, removes turret and mine jamming ability.").Value;
AllowBigDoors = ((BaseUnityPlugin)c).Config.Bind<bool>("Gameplay", "Allow door control", true, "If false, removes ability to operate facility powered doors.").Value;
JammingCoolDown = ((BaseUnityPlugin)c).Config.Bind<int>("Gameplay", "Jamming cool down", 0, "Cool down time in seconds before the same player can send another jamming signal.").Value;
BigDoorsCoolDown = ((BaseUnityPlugin)c).Config.Bind<int>("Gameplay", "Door control cool down", 0, "Cool down time in seconds before the same player can send another command to open / close all doors.").Value;
JammingKey = ((BaseUnityPlugin)c).Config.Bind<KeyCode>("Key Binds", "Jamming (Ctrl+)", (KeyCode)106, (ConfigDescription)null).Value;
DoorKey = ((BaseUnityPlugin)c).Config.Bind<KeyCode>("Key Binds", "Open/Close facility doors (Ctrl+)", (KeyCode)100, (ConfigDescription)null).Value;
SwitchKey = ((BaseUnityPlugin)c).Config.Bind<KeyCode>("Key Binds", "Play switch on monitor (Ctrl+)", (KeyCode)115, (ConfigDescription)null).Value;
MonitorKey = ((BaseUnityPlugin)c).Config.Bind<KeyCode>("Key Binds", "Turn on/off monitor (Ctrl+)", (KeyCode)109, (ConfigDescription)null).Value;
TransmitKey = ((BaseUnityPlugin)c).Config.Bind<KeyCode>("Key Binds", "Start transmission (Ctrl+)", (KeyCode)116, (ConfigDescription)null).Value;
TeleportKey = ((BaseUnityPlugin)c).Config.Bind<KeyCode>("Key Binds", "Teleport (Ctrl+)", (KeyCode)119, (ConfigDescription)null).Value;
InverseTeleportKey = ((BaseUnityPlugin)c).Config.Bind<KeyCode>("Key Binds", "Inverse Teleport (Ctrl+)", (KeyCode)105, (ConfigDescription)null).Value;
}
public void Set_Configs(TerminalCommanderConfiguration hostConfig)
{
AllowJamming = hostConfig.AllowJamming;
AllowBigDoors = hostConfig.AllowBigDoors;
JammingCoolDown = hostConfig.JammingCoolDown;
BigDoorsCoolDown = hostConfig.BigDoorsCoolDown;
}
}
[BepInPlugin("Tronald.TerminalCommander", "TerminalCommander", "1.8.0")]
public class Commander : BaseUnityPlugin
{
public const string modGUID = "Tronald.TerminalCommander";
public const string modName = "TerminalCommander";
public const string modVersion = "1.8.0";
private readonly Harmony harmony = new Harmony("Tronald.TerminalCommander");
private static Commander instance;
public TerminalCommanderConfiguration Configs = new TerminalCommanderConfiguration();
public bool StartOfRound = true;
public DateTime LastJamEvent = default(DateTime);
public DateTime LastDoorEvent = default(DateTime);
internal ManualLogSource log;
private void Awake()
{
if ((Object)(object)instance == (Object)null)
{
instance = this;
}
log = Logger.CreateLogSource("Tronald.TerminalCommander");
log.LogInfo((object)"TerminalCommander is loaded!");
Configs.Set_Configs(this);
TerminalHotkeys.SetSource(this);
TerminalCommands.SetSource(this);
GameManagement.SetSource(this);
RoundManagerPatch.SetSource(this);
harmony.PatchAll(typeof(Commander));
harmony.PatchAll(typeof(TerminalHotkeys));
harmony.PatchAll(typeof(TerminalCommands));
harmony.PatchAll(typeof(GameManagement));
harmony.PatchAll(typeof(RoundManagerPatch));
}
}
}
namespace TerminalCommander.Patches
{
[HarmonyPatch(typeof(StartOfRound))]
internal class GameManagement
{
private static ManualLogSource logSource;
private static Commander commanderSource;
private static LethalClientMessage<TerminalCommanderConfiguration> clientMessage = new LethalClientMessage<TerminalCommanderConfiguration>("config");
private static LethalServerMessage<TerminalCommanderConfiguration> serverMessage = new LethalServerMessage<TerminalCommanderConfiguration>("config");
public static void SetSource(Commander source)
{
commanderSource = source;
logSource = commanderSource.log;
clientMessage.OnReceived += CustomClientMessage_OnReceived;
serverMessage.OnReceived += ServerMessage_OnReceived;
}
[HarmonyPatch("OnClientConnect")]
[HarmonyPostfix]
private static void FollowHostConfigurationPatch(StartOfRound __instance, ulong clientId)
{
try
{
if (((NetworkBehaviour)__instance).IsHost)
{
logSource.LogInfo((object)string.Format("{0} syncing configurations for connected player: clientId {1}.", "TerminalCommander", clientId));
serverMessage.SendAllClients(commanderSource.Configs);
}
}
catch (Exception ex)
{
logSource.LogError((object)("GAME MANAGEMENT ERROR (CONFIGS NOT SYNCED): " + ex.Message));
}
}
private static void CustomClientMessage_OnReceived(TerminalCommanderConfiguration obj)
{
logSource.LogInfo((object)"Host configurations received.");
commanderSource.Configs.AllowBigDoors = obj.AllowBigDoors;
commanderSource.Configs.AllowJamming = obj.AllowJamming;
}
private static void ServerMessage_OnReceived(TerminalCommanderConfiguration arg1, ulong arg2)
{
logSource.LogInfo((object)"Sending host configurations to clients.");
clientMessage.SendServer(commanderSource.Configs);
}
}
[HarmonyPatch(typeof(RoundManager))]
internal class RoundManagerPatch
{
private static ManualLogSource logSource;
private static Commander commanderSource;
public static void SetSource(Commander source)
{
commanderSource = source;
logSource = commanderSource.log;
}
[HarmonyPatch("SetLevelObjectVariables")]
[HarmonyPostfix]
private static void ResetVariable()
{
try
{
commanderSource.StartOfRound = true;
commanderSource.LastJamEvent = default(DateTime);
commanderSource.LastDoorEvent = default(DateTime);
}
catch (Exception ex)
{
logSource.LogError((object)("ROUND MANAGER ERROR: " + ex.Message));
}
}
}
[HarmonyPatch(typeof(Terminal))]
internal class TerminalCommands
{
private static ManualLogSource logSource;
private static Commander commanderSource;
public static void SetSource(Commander source)
{
commanderSource = source;
logSource = commanderSource.log;
SetCommands();
}
private static void SetCommands()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Expected O, but got Unknown
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Expected O, but got Unknown
CommandInfo val = new CommandInfo();
val.Category = "help";
val.Description = "View the Terminal Commander hotkeys and commands.";
val.DisplayTextSupplier = OnHotKeyHelpCommand;
TerminalApi.AddCommand("Commander", val, (string)null, true);
val = new CommandInfo();
val.Category = "Commander";
val.DisplayTextSupplier = TeleportCommand;
TerminalApi.AddCommand("tp", val, (string)null, true);
val = new CommandInfo();
val.Category = "Commander";
val.DisplayTextSupplier = InverseTeleportCommand;
TerminalApi.AddCommand("itp", val, (string)null, true);
}
private static string OnHotKeyHelpCommand()
{
return "HOTKEYS\n\n>Ctrl+D\nOpen / close all doors.\n\n>Ctrl+J\nJam all turrets and land mines.\n\n>Ctrl+M\nTurn monitor on and off.\n\n>Ctrl+S\nQuickly switch players on the monitor.\n\n>Ctrl+T\nBegin a signal transmission command.\n\nCOMMANDS\n\n>TP\nTeleport currently viewed player on monitor.\n\n>ITP\nActivate inverse teleporter.\n\n";
}
public static string TeleportCommand()
{
ShipTeleporter[] array = Object.FindObjectsOfType<ShipTeleporter>();
if (array != null && array.Length != 0)
{
ShipTeleporter[] array2 = array;
foreach (ShipTeleporter val in array2)
{
if (!val.isInverseTeleporter)
{
val.PressTeleportButtonOnLocalClient();
return "Teleporting...\n\n";
}
}
}
return "Nuh uh, no teleporter\n\n";
}
public static string EntranceTeleportCommand()
{
EntranceTeleport[] array = Object.FindObjectsOfType<EntranceTeleport>();
if (array == null || array.Length == 0)
{
return "No inverse teleporter detected.\n\n";
}
EntranceTeleport val = array[0];
val.TeleportPlayer();
return "Teleporting...\n\n";
}
public static string InverseTeleportCommand()
{
ShipTeleporter[] array = Object.FindObjectsOfType<ShipTeleporter>();
if (array != null && array.Length != 0)
{
ShipTeleporter[] array2 = array;
foreach (ShipTeleporter val in array2)
{
if (val.isInverseTeleporter)
{
if (!StartOfRound.Instance.shipHasLanded)
{
return "Cannot inverse teleport until ship has fully landed and stabilized.\n\n";
}
FieldInfo field = ((object)val).GetType().GetField("cooldownTime", BindingFlags.Instance | BindingFlags.NonPublic);
float num = (float)field.GetValue(val);
if (num > 0f)
{
return $"Cooldown time for inverse teleporter: {Math.Round(num)} seconds.\n\n";
}
val.PressTeleportButtonOnLocalClient();
return "Teleporting...\n\n";
}
}
}
return "Nuh uh, no inverse teleporter\n\n";
}
}
[HarmonyPatch(typeof(Terminal))]
internal class TerminalHotkeys
{
private static string turretName = "turretscript";
private static string landmineName = "landmine";
private static string doorName = "bigdoor";
private static bool openDoors = true;
private static ManualLogSource logSource;
private static Commander commanderSource;
public static void SetSource(Commander source)
{
commanderSource = source;
logSource = commanderSource.log;
}
[HarmonyPatch("Update")]
[HarmonyPostfix]
private static void HotKeyPatch(ref bool ___terminalInUse, ref TMP_InputField ___screenText)
{
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
//IL_0141: Unknown result type (might be due to invalid IL or missing references)
//IL_0170: Unknown result type (might be due to invalid IL or missing references)
try
{
if ((___terminalInUse && UnityInput.Current.GetKey((KeyCode)306)) || UnityInput.Current.GetKey((KeyCode)305))
{
Terminal val = FindActiveObject<Terminal>();
if ((Object)(object)val == (Object)null)
{
logSource.LogInfo((object)"TerminalCommander ERROR: Terminal could not be found.");
}
if (UnityInput.Current.GetKeyDown(commanderSource.Configs.SwitchKey))
{
SwitchPlayer(val);
}
else if (UnityInput.Current.GetKeyDown(commanderSource.Configs.TransmitKey))
{
Transmission(val, ___screenText);
}
else if (UnityInput.Current.GetKeyDown(commanderSource.Configs.DoorKey))
{
OperateBigDoors(val);
}
else if (UnityInput.Current.GetKeyDown(commanderSource.Configs.JammingKey))
{
JamTurrentMines(val);
}
else if (UnityInput.Current.GetKeyDown(commanderSource.Configs.MonitorKey))
{
ViewMonitor(val);
}
else if (UnityInput.Current.GetKeyDown(commanderSource.Configs.TeleportKey))
{
SetTerminalText(val, TerminalCommands.TeleportCommand());
}
else if (UnityInput.Current.GetKeyDown(commanderSource.Configs.InverseTeleportKey))
{
SetTerminalText(val, TerminalCommands.InverseTeleportCommand());
}
}
}
catch (Exception ex)
{
logSource.LogError((object)(ex.Message ?? ""));
}
}
private static void SwitchPlayer(Terminal t)
{
string text = "switch";
TMP_InputField screenText = t.screenText;
screenText.text += text;
t.textAdded = text.Length;
t.OnSubmit();
}
private static void Transmission(Terminal t, TMP_InputField ___screenText)
{
___screenText.text += "transmit ";
}
private static void OperateBigDoors(Terminal t)
{
DateTime dateTime = DateTime.Now.AddSeconds(-commanderSource.Configs.BigDoorsCoolDown);
if (!commanderSource.Configs.AllowBigDoors)
{
SetTerminalText(t, "This command has been disabled by the company.\n\n");
return;
}
if (dateTime < commanderSource.LastDoorEvent)
{
SetTerminalText(t, $"Door signal cool down time remaining: {Math.Round((commanderSource.LastDoorEvent - dateTime).TotalSeconds)} seconds.\n\n");
return;
}
TerminalAccessibleObject[] source = (from x in Object.FindObjectsOfType<TerminalAccessibleObject>()
select (x)).ToArray();
List<string> list = new List<string>();
foreach (TerminalAccessibleObject item in source.Where((TerminalAccessibleObject x) => ((Object)x).name.ToLower().Contains(doorName)))
{
if (!item.isBigDoor)
{
return;
}
list.Add(item.objectCode);
item.SetDoorLocalClient(openDoors);
}
if (openDoors || commanderSource.StartOfRound)
{
SetTerminalText(t, "Opening all doors\n\n");
openDoors = false;
commanderSource.StartOfRound = false;
}
else
{
SetTerminalText(t, "Closing all doors\n\n");
openDoors = true;
}
t.terminalAudio.PlayOneShot(t.codeBroadcastSFX, 1f);
t.codeBroadcastAnimator.SetTrigger("display");
commanderSource.LastDoorEvent = DateTime.Now;
logSource.LogInfo((object)string.Format("{0} TerminalAccessibleObjects Called: Count{1} - ({2})", "TerminalCommander", source.Count(), string.Join(", ", list)));
}
private static void JamTurrentMines(Terminal t)
{
DateTime dateTime = DateTime.Now.AddSeconds(-commanderSource.Configs.JammingCoolDown);
if (!commanderSource.Configs.AllowJamming)
{
SetTerminalText(t, "This command has been disabled by the company.\n\n");
return;
}
if (dateTime < commanderSource.LastJamEvent)
{
SetTerminalText(t, $"Jammer cool down time remaining: {Math.Round((commanderSource.LastJamEvent - dateTime).TotalSeconds)} seconds.\n\n");
return;
}
TerminalAccessibleObject[] source = (from x in Object.FindObjectsOfType<TerminalAccessibleObject>()
select (x)).ToArray();
List<string> list = new List<string>();
foreach (TerminalAccessibleObject item in source.Where((TerminalAccessibleObject x) => ((Object)x).name.ToLower() == turretName || ((Object)x).name.ToLower() == landmineName))
{
list.Add(item.objectCode);
item.CallFunctionFromTerminal();
}
SetTerminalText(t, "Jamming turrets and land mines\n\n");
t.terminalAudio.PlayOneShot(t.codeBroadcastSFX, 1f);
t.codeBroadcastAnimator.SetTrigger("display");
commanderSource.LastJamEvent = DateTime.Now;
logSource.LogInfo((object)string.Format("{0} TerminalAccessibleObjects Called: Count{1} - ({2})", "TerminalCommander", source.Count(), string.Join(", ", list)));
}
private static void ViewMonitor(Terminal t)
{
string text = "view monitor";
TMP_InputField screenText = t.screenText;
screenText.text += text;
t.textAdded = text.Length;
t.OnSubmit();
}
private static void SetTerminalText(Terminal t, string s)
{
TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
val.clearPreviousText = true;
val.acceptAnything = false;
val.displayText = s;
t.LoadNewNode(val);
t.screenText.ActivateInputField();
((Selectable)t.screenText).Select();
}
private static T FindActiveObject<T>() where T : Object
{
T[] array = Object.FindObjectsOfType<T>();
if (array.Length != 0)
{
return array[0];
}
return default(T);
}
}
}