Decompiled source of BetterTerminal v1.1.1

BetterTerminal.dll

Decompiled 6 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalAPI.LibTerminal;
using LethalAPI.LibTerminal.Attributes;
using LethalAPI.LibTerminal.Models;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("BetterTerminal")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BetterTerminal")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e8857ce3-5d85-4646-b810-d07713a6c929")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
public class TerminalNetworkHandler : NetworkBehaviour
{
	public static TerminalNetworkHandler Instance;

	private void Awake()
	{
		Instance = this;
	}

	public void SyncOrderedItems(List<int> orderedItems)
	{
		if (((NetworkBehaviour)this).IsServer)
		{
			SyncOrderedItemsClientRpc(orderedItems);
		}
		else
		{
			SyncOrderedItemsServerRpc(orderedItems);
		}
	}

	[ClientRpc]
	private void SyncOrderedItemsClientRpc(List<int> orderedItems)
	{
		Terminal val = Object.FindObjectOfType<Terminal>();
		if ((Object)(object)val != (Object)null)
		{
			val.orderedItemsFromTerminal = orderedItems;
		}
	}

	[ServerRpc(RequireOwnership = false)]
	private void SyncOrderedItemsServerRpc(List<int> orderedItems)
	{
		SyncOrderedItemsClientRpc(orderedItems);
	}
}
namespace BetterTerminal;

internal class Alias
{
	private MainBetterTerminal instance = new MainBetterTerminal();

	[TerminalCommand("scan", true)]
	public string ScanAlias(string scanspot)
	{
		if (scanspot == "inside")
		{
			return instance.ScanInsideCommand();
		}
		if (scanspot == "ship")
		{
			return instance.ItemsCommand();
		}
		return "[There was no scan type supplied with that word.]";
	}

	[TerminalCommand("light", true)]
	public string LightAlias()
	{
		return instance.LightsCommand();
	}

	[TerminalCommand("teleport", true)]
	public string TpAlias()
	{
		return instance.TpCommand();
	}

	[TerminalCommand("doors", true)]
	public string DoorAlias()
	{
		return instance.ToggleDoorCommand();
	}

	[TerminalCommand("Land", true)]
	public string LaunchAlias()
	{
		return instance.LaunchCommand();
	}

	[TerminalCommand("Go", true)]
	public string LaunchAlias2()
	{
		return instance.LaunchCommand();
	}

	[TerminalCommand("InverseTp", true)]
	public string InverseAlias()
	{
		return instance.InverseCommand();
	}
}
[Serializable]
public class BetterTerminalConfig : SyncedInstance<BetterTerminalConfig>
{
	public ConfigEntry<bool> restartCommandDisable;

	public ConfigEntry<bool> cancelDeliveryDisable;

	public ConfigEntry<bool> itpDisable;

	public ConfigEntry<bool> itpHost;

	public ConfigEntry<bool> launchDisable;

	public ConfigEntry<bool> launchHost;

	public ConfigEntry<bool> doorDisable;

	public ConfigEntry<bool> doorHost;

	public ConfigEntry<bool> teleportDisable;

	public ConfigEntry<bool> teleportHost;

	public ConfigEntry<bool> lightsDisable;

	public ConfigEntry<bool> lightsHost;

	public ConfigEntry<bool> itemsDisable;

	public ConfigEntry<bool> itemsHost;

	public ConfigEntry<bool> scanInsideDisable;

	public ConfigEntry<bool> scanInsideHost;

	public BetterTerminalConfig(ConfigFile cfg)
	{
		InitInstance(this);
		restartCommandDisable = cfg.Bind<bool>("Commands.Restart", "Disable", false, "Disables the restart command");
		itpDisable = cfg.Bind<bool>("Commands.itp", "Disable", false, "Disables the ITP (Inverse Teleporter) command");
		itpHost = cfg.Bind<bool>("Commands.itp", "Host Only", false, "Makes the ITP (Inverse Teleporter) command for hosts only");
		launchDisable = cfg.Bind<bool>("Commands.Launch", "Disable", false, "Disables the Launch command");
		launchHost = cfg.Bind<bool>("Commands.Launch", "Host Only", false, "Makes the Launch command for hosts only");
		doorDisable = cfg.Bind<bool>("Commands.Door", "Disable", false, "Disables the Door command");
		doorHost = cfg.Bind<bool>("Commands.Door", "Host Only", false, "Makes the Door command for hosts only");
		teleportDisable = cfg.Bind<bool>("Commands.Teleport", "Disable", false, "Disables the Door command");
		teleportHost = cfg.Bind<bool>("Commands.Teleport", "Host Only", false, "Makes the Door command for hosts only");
		lightsDisable = cfg.Bind<bool>("Commands.Lights", "Disable", false, "Disables the Lights command");
		lightsHost = cfg.Bind<bool>("Commands.Lights", "Host Only", false, "Makes the Lights command for hosts only");
		cancelDeliveryDisable = cfg.Bind<bool>("Commands.CancelDelivery", "Disable", false, "Disables the Cancel Delivery command");
		itemsDisable = cfg.Bind<bool>("Commands.Items", "Disable", false, "Disables the Items command");
		itemsHost = cfg.Bind<bool>("Commands.Items", "Host Only", false, "Makes the Items command for hosts only");
		scanInsideDisable = cfg.Bind<bool>("Commands.ScanInside", "Disable", false, "Disables the Scan Inside command");
		scanInsideHost = cfg.Bind<bool>("Commands.ScanInside", "Host Only", false, "Makes the Scan Inside command for hosts only");
	}
}
[BepInPlugin("zg.BetterTerminal", "BetterTerminal", "1.1.1")]
[HarmonyPatch(typeof(Terminal))]
public class MainBetterTerminal : BaseUnityPlugin
{
	private const string modVersion = "1.1.1";

	private const string modGUID = "zg.BetterTerminal";

	private const string modName = "BetterTerminal";

	private readonly Harmony harmony = new Harmony("zg.BetterTerminal");

	private TerminalModRegistry Commands;

	internal ManualLogSource pnt;

	public static BetterTerminalConfig Config { get; internal set; }

	public static MainBetterTerminal instance { get; internal set; }

	public ManualLogSource getLogger()
	{
		return ((BaseUnityPlugin)this).Logger;
	}

	private void Awake()
	{
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Expected O, but got Unknown
		if ((Object)(object)instance == (Object)null)
		{
			instance = this;
		}
		Config = new BetterTerminalConfig(((BaseUnityPlugin)this).Config);
		Commands = TerminalRegistry.CreateTerminalRegistry();
		Commands.RegisterFrom<MainBetterTerminal>(this);
		Commands.RegisterFrom<Alias>();
		GameObject val = new GameObject("TerminalNetworkHandler");
		TerminalNetworkHandler terminalNetworkHandler = val.AddComponent<TerminalNetworkHandler>();
		TerminalNetworkHandler.Instance = terminalNetworkHandler;
		pnt = Logger.CreateLogSource("zg.BetterTerminal");
		pnt.LogInfo((object)"BetterTerminal Enabled");
		pnt.LogInfo((object)"Make sure to review BetterTerminal");
		harmony.PatchAll(typeof(MainBetterTerminal));
		harmony.PatchAll(typeof(TerminalNetworkHandler));
	}

	[TerminalCommand("ScanInside", true)]
	[CommandInfo("See how many items are INSIDE the facility", "")]
	public string ScanInsideCommand()
	{
		if (Config.scanInsideDisable.Value)
		{
			return "This command is Disabled";
		}
		if (Config.scanInsideHost.Value && !isHost())
		{
			return "This command is Host Only";
		}
		Debug.Log((object)"Got to debug 1");
		Random random = new Random(StartOfRound.Instance.randomMapSeed + 91);
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
		for (int i = 0; i < array.Length; i++)
		{
			Debug.Log((object)"Got to debug 2");
			if (array[i].itemProperties.isScrap && array[i].isInFactory)
			{
				Debug.Log((object)"Got to debug 3");
				num3 += array[i].itemProperties.maxValue - array[i].itemProperties.minValue;
				num2 += Mathf.Clamp(random.Next(array[i].itemProperties.minValue, array[i].itemProperties.maxValue), array[i].scrapValue - 6 * i, array[i].scrapValue + 9 * i);
				num++;
			}
			Debug.Log((object)"Got to debug 4");
		}
		Debug.Log((object)"Got to debug 5");
		return "There are currently " + num + " items inside the facility";
	}

	[TerminalCommand("Items", true)]
	[CommandInfo("See the value of items inside of the ship", "")]
	public string ItemsCommand()
	{
		if (Config.itemsDisable.Value)
		{
			return "This command is Disabled";
		}
		if (Config.itemsHost.Value && !isHost())
		{
			return "This command is Host Only";
		}
		GameObject val = GameObject.Find("/Environment/HangarShip");
		if ((Object)(object)val == (Object)null)
		{
			return "0";
		}
		List<GrabbableObject> source = (from obj in val.GetComponentsInChildren<GrabbableObject>()
			where ((Object)obj).name != "ClipboardManual" && ((Object)obj).name != "StickyNoteItem" && ((Object)obj).name != "KeyItem"
			select obj).ToList();
		float num = source.Sum((GrabbableObject scrap) => scrap.scrapValue);
		Debug.Log((object)$"There is currently ${num} value of scrap inside the ship");
		return $"There is currently ${num} value of scrap inside of the ship";
	}

	[TerminalCommand("CancelDelivery", true)]
	[AllowedCaller(/*Could not decode attribute arguments.*/)]
	[CommandInfo("Cancel purchased items for a refund before delivery", "")]
	public string CancelDeliveryCommand()
	{
		if (Config.cancelDeliveryDisable.Value)
		{
			return "This command is Disabled";
		}
		Terminal val = Object.FindObjectOfType<Terminal>();
		if (val.numberOfItemsInDropship > 0)
		{
			TerminalNetworkHandler.Instance.SyncOrderedItems(val.orderedItemsFromTerminal);
			int num = 0;
			foreach (int item in val.orderedItemsFromTerminal)
			{
				if (item >= 0 && item < val.buyableItemsList.Count())
				{
					num += val.buyableItemsList[item].creditsWorth;
				}
				else
				{
					Debug.LogError((object)"Why is this happening?!?");
				}
			}
			int num2 = (val.groupCredits += num);
			Debug.Log((object)num);
			num = 0;
			val.orderedItemsFromTerminal.Clear();
			val.numberOfItemsInDropship = 0;
			val.SyncGroupCreditsClientRpc(num2, val.numberOfItemsInDropship);
			val.SyncGroupCreditsServerRpc(num2, val.numberOfItemsInDropship);
			return "Purchase cancelled and items refunded";
		}
		return "No items in delivery to cancel.";
	}

	[TerminalCommand("bettermods", true)]
	[CommandInfo("Info about BetterMods", "")]
	public string BetterModsCommand()
	{
		return "BetterSpec and BetterTerminal were made by Higgins, You can get them both on Thunderstore";
	}

	[TerminalCommand("lights", true)]
	[CommandInfo("Use this to toggle ship lights remotely", "")]
	public string LightsCommand()
	{
		if (Config.lightsDisable.Value)
		{
			return "This command is Disabled";
		}
		if (Config.lightsHost.Value && !isHost())
		{
			return "This command is Host Only";
		}
		StartOfRound.Instance.shipRoomLights.ToggleShipLights();
		return "You've toggled the lights inside of the ship";
	}

	[TerminalCommand("tp", true)]
	[CommandInfo("Teleport the player currently on the monitor", "")]
	public string TpCommand()
	{
		if (Config.teleportDisable.Value)
		{
			return "This command is Disabled";
		}
		if (Config.teleportHost.Value && !isHost())
		{
			return "This command is Host Only";
		}
		ShipTeleporter component = GameObject.Find("Teleporter(Clone)").GetComponent<ShipTeleporter>();
		FieldInfo field = ((object)component).GetType().GetField("cooldownTime", BindingFlags.Instance | BindingFlags.NonPublic);
		float num = (float)field.GetValue(component);
		if (num > 0f)
		{
			return "The teleporter is currently on cooldown";
		}
		if ((Object)(object)component == (Object)null)
		{
			return "You must purchase a Teleporter to teleport";
		}
		((UnityEvent<PlayerControllerB>)(object)component.buttonTrigger.onInteract).Invoke(GameNetworkManager.Instance.localPlayerController);
		return "Teleporting";
	}

	[TerminalCommand("door", true)]
	[CommandInfo("Safely toggle the Ship Door", "")]
	public string ToggleDoorCommand()
	{
		if (Config.doorDisable.Value)
		{
			return "This command is Disabled";
		}
		if (Config.doorHost.Value && !isHost())
		{
			return "This command is Host Only";
		}
		InteractTrigger componentInChildren = GameObject.Find(StartOfRound.Instance.hangarDoorsClosed ? "StartButton" : "StopButton").GetComponentInChildren<InteractTrigger>();
		((UnityEvent<PlayerControllerB>)(object)componentInChildren.onInteract).Invoke(GameNetworkManager.Instance.localPlayerController);
		if (StartOfRound.Instance.hangarDoorsClosed)
		{
			return "Opened the doors";
		}
		return "Closed the doors, stay safe";
	}

	[TerminalCommand("Launch", true)]
	[CommandInfo("Use this to land or launch the ship", "")]
	public string LaunchCommand()
	{
		if (Config.launchDisable.Value)
		{
			return "This command is Disabled";
		}
		if (Config.launchHost.Value && !isHost())
		{
			return "This command is Host Only";
		}
		if ((Object)(object)GameObject.Find("StartGameLever") == (Object)null)
		{
			return "Error finding the Lever";
		}
		StartMatchLever component = GameObject.Find("StartGameLever").GetComponent<StartMatchLever>();
		if (StartOfRound.Instance.shipDoorsEnabled && !StartOfRound.Instance.shipHasLanded && !StartOfRound.Instance.shipIsLeaving)
		{
			return "Contact the Pilot someone's already done this!";
		}
		if (!StartOfRound.Instance.shipDoorsEnabled && StartOfRound.Instance.travellingToNewLevel)
		{
			return "Contact the Pilot someone's already done this!";
		}
		component.PullLever();
		component.LeverAnimation();
		if (component.leverHasBeenPulled)
		{
			component.StartGame();
			return "Copy that Pilot ship is heading there now";
		}
		if (!component.leverHasBeenPulled)
		{
			component.EndGame();
			return "Copy that Pilot, Leaving the moon now";
		}
		return "If you see this run the command again";
	}

	[TerminalCommand("itp", true)]
	[CommandInfo("Uses the inverse teleporter", "")]
	public string InverseCommand()
	{
		if (Config.itpDisable.Value)
		{
			return "This command is Disabled";
		}
		if (Config.itpHost.Value && !isHost())
		{
			return "This command is Host Only";
		}
		if (!StartOfRound.Instance.shipHasLanded)
		{
			return "You can't teleport in space you'll die!";
		}
		if ((Object)(object)GameObject.Find("InverseTeleporter(Clone)") == (Object)null)
		{
			return "You need to purchase a inverse teleporter";
		}
		ShipTeleporter component = GameObject.Find("InverseTeleporter(Clone)").GetComponent<ShipTeleporter>();
		FieldInfo field = ((object)component).GetType().GetField("cooldownTime", BindingFlags.Instance | BindingFlags.NonPublic);
		float num = (float)field.GetValue(component);
		if (num > 0f)
		{
			return "The inverse teleporter is currently on cooldown";
		}
		if ((Object)(object)component == (Object)null)
		{
			return "You need to purchase a inverse teleporter";
		}
		((UnityEvent<PlayerControllerB>)(object)component.buttonTrigger.onInteract).Invoke(GameNetworkManager.Instance.localPlayerController);
		return "You sent him to die, Goodluck!";
	}

	[TerminalCommand("Restart", true)]
	[AllowedCaller(/*Could not decode attribute arguments.*/)]
	[CommandInfo("Resets all the ships furniture", "")]
	public string RestartCommand()
	{
		if (Config.restartCommandDisable.Value)
		{
			return "This command is Disabled";
		}
		if (!StartOfRound.Instance.shipDoorsEnabled)
		{
			StartOfRound.Instance.ResetShip();
			return "The company has shunned you, Go back to square 1";
		}
		return "You must be in space to restart, the company wants you working on the moon";
	}

	private bool isHost()
	{
		return ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost;
	}
}
[Serializable]
public class SyncedInstance<T>
{
	[NonSerialized]
	protected static int IntSize = 4;

	internal static CustomMessagingManager MessageManager => NetworkManager.Singleton.CustomMessagingManager;

	internal static bool IsClient => NetworkManager.Singleton.IsClient;

	internal static bool IsHost => NetworkManager.Singleton.IsHost;

	public static T Default { get; private set; }

	public static T Instance { get; private set; }

	public static bool Synced { get; internal set; }

	protected void InitInstance(T instance)
	{
		Default = instance;
		Instance = instance;
		IntSize = 4;
	}

	internal static void SyncInstance(byte[] data)
	{
		Instance = DeserializeFromBytes(data);
		Synced = true;
	}

	internal static void RevertSync()
	{
		Instance = Default;
		Synced = false;
	}

	public static byte[] SerializeToBytes(T val)
	{
		BinaryFormatter binaryFormatter = new BinaryFormatter();
		using MemoryStream memoryStream = new MemoryStream();
		try
		{
			binaryFormatter.Serialize(memoryStream, val);
			return memoryStream.ToArray();
		}
		catch (Exception arg)
		{
			MainBetterTerminal.instance.getLogger().LogError((object)$"Error serializing instance: {arg}");
			return null;
		}
	}

	public static T DeserializeFromBytes(byte[] data)
	{
		BinaryFormatter binaryFormatter = new BinaryFormatter();
		using MemoryStream serializationStream = new MemoryStream(data);
		try
		{
			return (T)binaryFormatter.Deserialize(serializationStream);
		}
		catch (Exception arg)
		{
			MainBetterTerminal.instance.getLogger().LogError((object)$"Error deserializing instance: {arg}");
			return default(T);
		}
	}

	public static void RequestSync()
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		if (!IsClient)
		{
			return;
		}
		FastBufferWriter val = default(FastBufferWriter);
		((FastBufferWriter)(ref val))..ctor(IntSize, (Allocator)2, -1);
		try
		{
			MessageManager.SendNamedMessage("BetterTerminal_OnRequestConfigSync", 0uL, val, (NetworkDelivery)3);
		}
		finally
		{
			((IDisposable)(FastBufferWriter)(ref val)).Dispose();
		}
	}

	public static void OnRequestSync(ulong clientId, FastBufferReader _)
	{
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		if (!IsHost)
		{
			return;
		}
		MainBetterTerminal.instance.getLogger().LogInfo((object)$"Config sync request received from client: {clientId}");
		byte[] array = SerializeToBytes(Instance);
		int num = array.Length;
		FastBufferWriter val = default(FastBufferWriter);
		((FastBufferWriter)(ref val))..ctor(num + IntSize, (Allocator)2, -1);
		try
		{
			((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives));
			((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0);
			MessageManager.SendNamedMessage("BetterTerminal_OnReceiveConfigSync", clientId, val, (NetworkDelivery)3);
		}
		catch (Exception arg)
		{
			MainBetterTerminal.instance.getLogger().LogInfo((object)$"Error occurred syncing config with client: {clientId}\n{arg}");
		}
		finally
		{
			((IDisposable)(FastBufferWriter)(ref val)).Dispose();
		}
	}

	public static void OnReceiveSync(ulong _, FastBufferReader reader)
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		if (!((FastBufferReader)(ref reader)).TryBeginRead(IntSize))
		{
			MainBetterTerminal.instance.getLogger().LogError((object)"Config sync error: Could not begin reading buffer.");
			return;
		}
		int num = default(int);
		((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
		if (!((FastBufferReader)(ref reader)).TryBeginRead(num))
		{
			MainBetterTerminal.instance.getLogger().LogError((object)"Config sync error: Host could not sync.");
			return;
		}
		byte[] data = new byte[num];
		((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0);
		SyncInstance(data);
		MainBetterTerminal.instance.getLogger().LogInfo((object)"Successfully synced config with host.");
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
	public static void InitializeLocalPlayer()
	{
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Expected O, but got Unknown
		if (IsHost)
		{
			MessageManager.RegisterNamedMessageHandler("BetterTerminal_OnRequestConfigSync", new HandleNamedMessageDelegate(OnRequestSync));
			Synced = true;
		}
		else
		{
			Synced = false;
			MessageManager.RegisterNamedMessageHandler("BetterTerminal_OnReceiveConfigSync", new HandleNamedMessageDelegate(OnReceiveSync));
			RequestSync();
		}
	}
}
public static class MyPluginInfo
{
	public const string PLUGIN_GUID = "BetterTerminal";

	public const string PLUGIN_NAME = "";

	public const string PLUGIN_VERSION = "1.0.0.0";
}