Decompiled source of MatrixTermExtensions v1.1.2

MatrixTermExtensions.dll

Decompiled 6 months ago
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalAPI.LibTerminal;
using LethalAPI.LibTerminal.Attributes;
using LethalAPI.LibTerminal.Models;
using Matrix.TerminalExtensions.Commands;
using Matrix.TerminalExtensions.Configs;
using Matrix.TerminalExtensions.Extensions;
using Microsoft.CodeAnalysis;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MatrixTermExtensions")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A customized variant of Terminal Extensions for use in sessions with my friends.")]
[assembly: AssemblyFileVersion("1.1.2.0")]
[assembly: AssemblyInformationalVersion("1.1.2+291ddd33c0b90956ef8deba1c0236128b964ab05")]
[assembly: AssemblyProduct("MatrixTermExtensions")]
[assembly: AssemblyTitle("MatrixTermExtensions")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/D0t-Matrix/LC-TermExtensions")]
[assembly: AssemblyVersion("1.1.2.0")]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 System.Runtime.Versioning
{
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresPreviewFeaturesAttribute : Attribute
	{
		public string? Message { get; }

		public string? Url { get; set; }

		public RequiresPreviewFeaturesAttribute()
		{
		}

		public RequiresPreviewFeaturesAttribute(string? message)
		{
			Message = message;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CallerArgumentExpressionAttribute : Attribute
	{
		public string ParameterName { get; }

		public CallerArgumentExpressionAttribute(string parameterName)
		{
			ParameterName = parameterName;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CollectionBuilderAttribute : Attribute
	{
		public Type BuilderType { get; }

		public string MethodName { get; }

		public CollectionBuilderAttribute(Type builderType, string methodName)
		{
			BuilderType = builderType;
			MethodName = methodName;
		}
	}
	[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CompilerFeatureRequiredAttribute : Attribute
	{
		public const string RefStructs = "RefStructs";

		public const string RequiredMembers = "RequiredMembers";

		public string FeatureName { get; }

		public bool IsOptional { get; set; }

		public CompilerFeatureRequiredAttribute(string featureName)
		{
			FeatureName = featureName;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute
	{
		public string[] Arguments { get; }

		public InterpolatedStringHandlerArgumentAttribute(string argument)
		{
			Arguments = new string[1] { argument };
		}

		public InterpolatedStringHandlerArgumentAttribute(params string[] arguments)
		{
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerAttribute : Attribute
	{
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal static class IsExternalInit
	{
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ModuleInitializerAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiredMemberAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresLocationAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SkipLocalsInitAttribute : Attribute
	{
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ExperimentalAttribute : Attribute
	{
		public string DiagnosticId { get; }

		public string? UrlFormat { get; set; }

		public ExperimentalAttribute(string diagnosticId)
		{
			DiagnosticId = diagnosticId;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullAttribute : Attribute
	{
		public string[] Members { get; }

		public MemberNotNullAttribute(string member)
		{
			Members = new string[1] { member };
		}

		public MemberNotNullAttribute(params string[] members)
		{
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public string[] Members { get; }

		public MemberNotNullWhenAttribute(bool returnValue, string member)
		{
			ReturnValue = returnValue;
			Members = new string[1] { member };
		}

		public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
		{
			ReturnValue = returnValue;
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SetsRequiredMembersAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class StringSyntaxAttribute : Attribute
	{
		public const string CompositeFormat = "CompositeFormat";

		public const string DateOnlyFormat = "DateOnlyFormat";

		public const string DateTimeFormat = "DateTimeFormat";

		public const string EnumFormat = "EnumFormat";

		public const string GuidFormat = "GuidFormat";

		public const string Json = "Json";

		public const string NumericFormat = "NumericFormat";

		public const string Regex = "Regex";

		public const string TimeOnlyFormat = "TimeOnlyFormat";

		public const string TimeSpanFormat = "TimeSpanFormat";

		public const string Uri = "Uri";

		public const string Xml = "Xml";

		public string Syntax { get; }

		public object?[] Arguments { get; }

		public StringSyntaxAttribute(string syntax)
		{
			Syntax = syntax;
			Arguments = new object[0];
		}

		public StringSyntaxAttribute(string syntax, params object?[] arguments)
		{
			Syntax = syntax;
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class UnscopedRefAttribute : Attribute
	{
	}
}
namespace Matrix.TerminalExtensions
{
	[BepInPlugin("matrix.lethalcompany.termextensions", "MatrixTermExtensions", "1.1.2")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		internal static Config Config;

		private readonly Harmony _harmony = new Harmony("matrix.lethalcompany.termextensions");

		private readonly TerminalModRegistry _commands = TerminalRegistry.CreateTerminalRegistry();

		public void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Config = new Config(((BaseUnityPlugin)this).Config);
			try
			{
				_harmony.PatchAll(typeof(Plugin).Assembly);
				Logger.LogInfo((object)"<!!!> MatrixTermExtensions Plugin has loaded. <!!!>");
				_commands.RegisterFrom<DoorCommands>();
				_commands.RegisterFrom<TeleporterCommands>();
				_commands.RegisterFrom<LightsCommands>();
				_commands.RegisterFrom<LaunchCommands>();
				if (Config.EnableCheatCommands)
				{
					Logger.LogInfo((object)"Enabling Cheat Commands.");
					_commands.RegisterFrom<CheatCommands>();
				}
				Logger.LogInfo((object)"<!!!> MatrixTermExtensions Custom Terminal Commands loaded. <!!!>");
			}
			catch (Exception ex)
			{
				Logger.LogError((object)ex);
			}
		}
	}
	internal static class Utils
	{
		internal static T GetInstancedStructField<T>(object instance, string fieldName) where T : struct
		{
			object value = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic).GetValue(instance);
			if (value is T)
			{
				return (T)value;
			}
			return default(T);
		}

		internal static void SetInstancedStructField<T>(object instance, string fieldName, T value) where T : struct
		{
			instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic).SetValue(instance, value);
		}

		internal static T? GetInstancedClassField<T>(object instance, string fieldName) where T : class
		{
			if (!(instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic).GetValue(instance) is T result))
			{
				return null;
			}
			return result;
		}

		internal static T GetInstanceMethod<T>(Type type, object instance, string methodName)
		{
			MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
			return (T)(object)Delegate.CreateDelegate(typeof(T), instance, method);
		}
	}
	[CompilerGenerated]
	internal static class GeneratedPluginInfo
	{
		public const string Identifier = "matrix.lethalcompany.termextensions";

		public const string Name = "MatrixTermExtensions";

		public const string Version = "1.1.2";
	}
}
namespace Matrix.TerminalExtensions.Patches
{
	[HarmonyPatch(typeof(RoundManager))]
	internal sealed class LevelPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("LoadNewLevel")]
		private static void LoadNewLevel()
		{
			Plugin.Logger.LogInfo((object)"Resetting the Inverse Teleporter Cooldown");
			TeleporterCommands.TryResetInverseTeleporter();
		}
	}
}
namespace Matrix.TerminalExtensions.Extensions
{
	internal static class StringExtensions
	{
		internal static bool IsNullOrEmpty([NotNullWhen(false)] this string? str)
		{
			return string.IsNullOrEmpty(str);
		}

		internal static bool IsNullOrWhitespace([NotNullWhen(false)] this string? str)
		{
			return string.IsNullOrWhiteSpace(str);
		}
	}
}
namespace Matrix.TerminalExtensions.Configs
{
	[DataContract]
	public class Config : SyncedInstance<Config>
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__OnRequestSync;

			public static HandleNamedMessageDelegate <1>__OnReceiveSync;
		}

		[DataMember]
		public bool EnablePlugin { get; private set; }

		[DataMember]
		public bool EnableCheatCommands { get; private set; }

		public Config(ConfigFile cfg)
		{
			InitInstance(this);
			EnablePlugin = cfg.Bind<bool>("MatrixTermExtensions", "enabled", true, "Enable or disable the plugin globally.").Value;
			EnableCheatCommands = cfg.Bind<bool>("MatrixTermExtensions", "cheat commands enabled", false, "Enable or disable the cheat commands.").Value;
		}

		public static void RequestSync()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (!SyncedInstance<Config>.IsClient)
			{
				return;
			}
			FastBufferWriter stream = default(FastBufferWriter);
			((FastBufferWriter)(ref stream))..ctor(SyncedInstance<Config>.IntSize, (Allocator)2, -1);
			try
			{
				SyncedInstance<Config>.SendMessage("MatrixTermExtensions_OnRequestConfigSync", 0uL, stream);
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref stream)).Dispose();
			}
		}

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

		public static void OnReceiveSync(ulong _, FastBufferReader reader)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (!((FastBufferReader)(ref reader)).TryBeginRead(SyncedInstance<Config>.IntSize))
			{
				Plugin.Logger.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))
			{
				Plugin.Logger.LogError((object)"Config sync error: Host could not sync.");
				return;
			}
			byte[] data = new byte[num];
			((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0);
			SyncedInstance<Config>.SyncInstance(data);
			Plugin.Logger.LogInfo((object)"Successfully synced config with host.");
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameNetworkManager), "JoinLobby")]
		public static void InitializeLocalPlayer()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			if (SyncedInstance<Config>.IsHost)
			{
				CustomMessagingManager messageManager = SyncedInstance<Config>.MessageManager;
				object obj = <>O.<0>__OnRequestSync;
				if (obj == null)
				{
					HandleNamedMessageDelegate val = OnRequestSync;
					<>O.<0>__OnRequestSync = val;
					obj = (object)val;
				}
				messageManager.RegisterNamedMessageHandler("MatrixTermExtensions_OnRequestConfigSync", (HandleNamedMessageDelegate)obj);
				SyncedInstance<Config>.IsSynced = true;
				return;
			}
			SyncedInstance<Config>.IsSynced = false;
			CustomMessagingManager messageManager2 = SyncedInstance<Config>.MessageManager;
			object obj2 = <>O.<1>__OnReceiveSync;
			if (obj2 == null)
			{
				HandleNamedMessageDelegate val2 = OnReceiveSync;
				<>O.<1>__OnReceiveSync = val2;
				obj2 = (object)val2;
			}
			messageManager2.RegisterNamedMessageHandler("MatrixTermExtensions_OnReceiveConfigSync", (HandleNamedMessageDelegate)obj2);
			RequestSync();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")]
		public static void PlayerLeave()
		{
			SyncedInstance<Config>.RevertSync();
		}
	}
	[Serializable]
	public class SyncedInstance<T>
	{
		[NonSerialized]
		protected static int IntSize = 4;

		[NonSerialized]
		private static readonly DataContractSerializer serializer = new DataContractSerializer(typeof(T));

		internal static bool IsSynced;

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

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

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

		internal static T? Default { get; private set; }

		internal static T? Instance { get; private set; }

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

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

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

		public static byte[]? SerializeToBytes(T? val)
		{
			if (val == null)
			{
				return null;
			}
			using MemoryStream memoryStream = new MemoryStream();
			try
			{
				serializer.WriteObject(memoryStream, val);
				return memoryStream.ToArray();
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error serializing instance: {arg}");
				return null;
			}
		}

		public static T? DeserializeFromBytes(byte[] data)
		{
			using MemoryStream stream = new MemoryStream(data);
			try
			{
				return (T)serializer.ReadObject(stream);
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogDebug((object)$"Error deserializing instance: {arg}");
				return default(T);
			}
		}

		internal static void SendMessage(string label, ulong clientId, FastBufferWriter stream)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			bool num = ((FastBufferWriter)(ref stream)).Capacity >= ((FastBufferWriter)(ref stream)).MaxCapacity;
			NetworkDelivery val = (NetworkDelivery)(num ? 4 : 2);
			if (num)
			{
				Plugin.Logger.LogDebug((object)($"Size of stream ({((FastBufferWriter)(ref stream)).Capacity}) was past the max buffer size.\n" + "Config instance will be sent in fragments to avoid overflowing the buffer."));
			}
			MessageManager.SendNamedMessage(label, clientId, stream, val);
		}
	}
}
namespace Matrix.TerminalExtensions.Commands
{
	public class CheatCommands
	{
		private const string AmountAdded = "{0} has been added, ye dirty cheater!";

		private const string ItemSpawned = "Item Spawned";

		private const string ItemsSpawned = "Items Spawned";

		private const string ResetCooldown = "Cooldown Reset";

		private const string FailedReset = "Failed to reset cooldown";

		[TerminalCommand("GiveMoney", true)]
		public string GiveMoneyCommand(Terminal terminal, int amount)
		{
			terminal.groupCredits += amount;
			return $"{amount} has been added, ye dirty cheater!";
		}

		[TerminalCommand("SpawnLoot", true)]
		public string SpawnLootCommand(int amount, int value)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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)
			int index = RoundManager.Instance.LevelRandom.Next(RoundManager.Instance.currentLevel.spawnableScrap.Count);
			GameObject spawnPrefab = RoundManager.Instance.currentLevel.spawnableScrap[index].spawnableItem.spawnPrefab;
			Vector3 position = ((Component)GameNetworkManager.Instance.localPlayerController).transform.position;
			for (int i = 0; i < amount; i++)
			{
				GrabbableObject component = Object.Instantiate<GameObject>(spawnPrefab, position, Quaternion.identity).GetComponent<GrabbableObject>();
				component.startFallingPosition = position;
				component.targetFloorPosition = component.GetItemFloorPosition(position);
				component.SetScrapValue(value);
				((NetworkBehaviour)component).NetworkObject.Spawn(false);
			}
			if (amount != 1)
			{
				return "Items Spawned";
			}
			return "Item Spawned";
		}

		[TerminalCommand("ResetInverse", false)]
		public string ResetInverseTeleporterCooldownCommand()
		{
			if (TeleporterCommands.TryResetInverseTeleporter())
			{
				return "Cooldown Reset";
			}
			return "Failed to reset cooldown";
		}
	}
	public class DoorCommands
	{
		private const string StartButton = "StartButton";

		private const string StopButton = "StopButton";

		private const string OpenParameter = "open";

		private const string CloseParameter = "close";

		private const string ToggleParameter = "toggle";

		private const string InvalidParameter = "Invalid Parameter!";

		private const string DoorsOpened = "Doors Opened.";

		private const string DoorsClosed = "Doors Closed.";

		private const string DoorsAlreadyOpen = "Doors already open!";

		private const string DoorsAlreadyClosed = "Doors already closed!";

		private const string InSpaceError = "Can't open doors in space!";

		[TerminalCommand("Doors", false)]
		public string DoorCommand([RemainingText] string? subcommand)
		{
			return subcommand?.ToLowerInvariant() switch
			{
				"open" => OpenCommand(), 
				"close" => CloseCommand(), 
				"toggle" => ToggleDoors(), 
				_ => "Invalid Parameter!", 
			};
		}

		[TerminalCommand("Door", false)]
		[CommandInfo("Opens or closes the door", "[open/close]")]
		public string DoorsCommand([RemainingText] string? subcommand)
		{
			string text = subcommand?.ToLowerInvariant();
			if (!(text == "open"))
			{
				if (text == "close")
				{
					return CloseCommand();
				}
				return "Invalid Parameter!";
			}
			return OpenCommand();
		}

		[TerminalCommand("Open", false)]
		[CommandInfo("Opens doors, if not already open.", "")]
		public string OpenCommand()
		{
			if (!StartOfRound.Instance.shipDoorsEnabled)
			{
				return "Can't open doors in space!";
			}
			if (TryOpenDoors())
			{
				return "Doors Opened.";
			}
			return "Doors already open!";
		}

		[TerminalCommand("Close", false)]
		[CommandInfo("Closes doors, if not already closed.", "")]
		public string CloseCommand()
		{
			if (!StartOfRound.Instance.shipDoorsEnabled)
			{
				return "Can't open doors in space!";
			}
			if (TryCloseDoors())
			{
				return "Doors Closed.";
			}
			return "Doors already closed!";
		}

		private static bool TryOpenDoors()
		{
			if (StartOfRound.Instance.hangarDoorsClosed)
			{
				((UnityEvent<PlayerControllerB>)(object)GameObject.Find("StartButton").GetComponentInChildren<InteractTrigger>().onInteract).Invoke(GameNetworkManager.Instance.localPlayerController);
				return true;
			}
			return false;
		}

		private static bool TryCloseDoors()
		{
			if (!StartOfRound.Instance.hangarDoorsClosed)
			{
				((UnityEvent<PlayerControllerB>)(object)GameObject.Find("StopButton").GetComponentInChildren<InteractTrigger>().onInteract).Invoke(GameNetworkManager.Instance.localPlayerController);
				return true;
			}
			return false;
		}

		private string ToggleDoors()
		{
			if (StartOfRound.Instance.hangarDoorsClosed)
			{
				return OpenCommand();
			}
			return CloseCommand();
		}
	}
	public class LaunchCommands
	{
		private const string StartGameLever = "StartGameLever";

		private const string alreadyInTransitMsg = "Unable to comply. Ship is alredy in tranist.";

		private const string CantFindStartComponent = "<!!!> Can't find StartMatchLever Component <!!!>";

		private const string InitiatingLaunch = "Initiating launch sequence.";

		private const string InitiatingLanding = "Initiating landing sequence.";

		private const string AlreadyInSpace = "Already in space!";

		private const string AlreadyLanded = "Already landed on moon!";

		[TerminalCommand("Launch", false)]
		public string LaunchCommand()
		{
			if (!TryGetShipLever(out StartMatchLever startMatchLever))
			{
				return "<!!!> Can't find StartMatchLever Component <!!!>";
			}
			if (StartOfRound.Instance.shipDoorsEnabled && !StartOfRound.Instance.shipHasLanded && !StartOfRound.Instance.shipIsLeaving)
			{
				return "Unable to comply. Ship is alredy in tranist.";
			}
			if (!StartOfRound.Instance.shipDoorsEnabled && StartOfRound.Instance.travellingToNewLevel)
			{
				return "Unable to comply. Ship is alredy in tranist.";
			}
			return PullLever(startMatchLever);
		}

		[TerminalCommand("Go", false)]
		[CommandInfo("Pull the lever, Kronk!", "")]
		public string GoCommand()
		{
			return LaunchCommand();
		}

		[TerminalCommand("TakeOff", false)]
		[CommandInfo("Takes off from moon.", "")]
		public string TakeOffCommand()
		{
			if (!TryGetShipLever(out StartMatchLever startMatchLever))
			{
				return "<!!!> Can't find StartMatchLever Component <!!!>";
			}
			if (!StartOfRound.Instance.shipDoorsEnabled)
			{
				return "Already in space!";
			}
			if (StartOfRound.Instance.shipDoorsEnabled && !StartOfRound.Instance.shipHasLanded && !StartOfRound.Instance.shipIsLeaving)
			{
				return "Unable to comply. Ship is alredy in tranist.";
			}
			return PullLever(startMatchLever);
		}

		[TerminalCommand("Land", false)]
		[CommandInfo("Lands ship on routed moon.", "")]
		public string LandCommand()
		{
			if (!TryGetShipLever(out StartMatchLever startMatchLever))
			{
				return "<!!!> Can't find StartMatchLever Component <!!!>";
			}
			if (StartOfRound.Instance.shipDoorsEnabled)
			{
				return "Already landed on moon!";
			}
			if (!StartOfRound.Instance.shipDoorsEnabled && StartOfRound.Instance.travellingToNewLevel)
			{
				return "Unable to comply. Ship is alredy in tranist.";
			}
			return PullLever(startMatchLever);
		}

		private static bool TryGetShipLever([NotNullWhen(true)] out StartMatchLever? startMatchLever)
		{
			startMatchLever = null;
			GameObject val = GameObject.Find("StartGameLever");
			if (val == null)
			{
				return false;
			}
			startMatchLever = val.GetComponent<StartMatchLever>();
			return startMatchLever != null;
		}

		private static string PullLever(StartMatchLever lever)
		{
			bool num = !lever.leverHasBeenPulled;
			lever.PullLever();
			lever.LeverAnimation();
			if (num)
			{
				lever.StartGame();
			}
			else
			{
				lever.EndGame();
			}
			if (!lever.leverHasBeenPulled)
			{
				return "Initiating launch sequence.";
			}
			return "Initiating landing sequence.";
		}
	}
	public class LightsCommands
	{
		private enum LightState
		{
			On,
			Off,
			Toggle
		}

		private const string LightsTurnedOn = "Turning lights on.";

		private const string LightsTurnedOff = "Turning lights off.";

		private const string LightsDisabled = "Unable to switch lights, as they are disabled.";

		private const string LightsAlreadyOn = "Lights are already on!";

		private const string LightsAlreadyOff = "Lights are already off!";

		private const string ParameterError = "Invalid Parameter.";

		[TerminalCommand("Lights", false)]
		[CommandInfo("Toggles the lights on or off", "")]
		public string SwitchLightsCommand()
		{
			return TrySwitchLights(LightState.Toggle);
		}

		[TerminalCommand("Lightup", false)]
		public string LightsOnCommand()
		{
			return TrySwitchLights(LightState.On);
		}

		[TerminalCommand("lightout", false)]
		[CommandInfo("Turns the lights off, if not already off", "")]
		public string LightsOffCommand()
		{
			return TrySwitchLights(LightState.Off);
		}

		[TerminalCommand("nox", false)]
		public string NoxCommand()
		{
			return LightsOffCommand();
		}

		[TerminalCommand("lumos", false)]
		[CommandInfo("Turns the lights off, if not already off", "")]
		public string LumosCommand()
		{
			return LightsOnCommand();
		}

		private static string TrySwitchLights(LightState switchState)
		{
			if (!((Behaviour)StartOfRound.Instance.shipRoomLights).enabled)
			{
				return "Unable to switch lights, as they are disabled.";
			}
			InteractTrigger component = GameObject.Find("LightSwitch").GetComponent<InteractTrigger>();
			switch (switchState)
			{
			case LightState.Off:
				if (StartOfRound.Instance.shipRoomLights.areLightsOn)
				{
					((UnityEvent<PlayerControllerB>)(object)component.onInteract).Invoke(GameNetworkManager.Instance.localPlayerController);
					return "Turning lights off.";
				}
				return "Lights are already off!";
			case LightState.On:
				if (!StartOfRound.Instance.shipRoomLights.areLightsOn)
				{
					((UnityEvent<PlayerControllerB>)(object)component.onInteract).Invoke(GameNetworkManager.Instance.localPlayerController);
					return "Turning lights on.";
				}
				return "Lights are already on!";
			case LightState.Toggle:
				((UnityEvent<PlayerControllerB>)(object)component.onInteract).Invoke(GameNetworkManager.Instance.localPlayerController);
				if (!StartOfRound.Instance.shipRoomLights.areLightsOn)
				{
					return "Turning lights off.";
				}
				return "Turning lights on.";
			default:
				return "Invalid Parameter.";
			}
		}
	}
	public class TeleporterCommands
	{
		private const string TeleporterObjectName = "Teleporter(Clone)";

		private const string InverseTeleporterObjectName = "InverseTeleporter(Clone)";

		private const string TeleporterCooldown = "Teleporter is on cooldown, {0:D} seconds left!";

		private const string InverseTeleporterCooldown = "Inverse Teleporter is on cooldown, {0:D} seconds left!";

		private const string TeleportingPlayer = "Teleporting Player..";

		private const string InverseTeleporting = "Tally ho, lads!";

		private const string NoTeleporterInShip = "No Teleporter in ship!";

		private const string ShipTeleporterComponentNotFound = "<!!!> Cannot locate ShipTeleporter Component! <!!!>";

		private const string UnableToResetInverted = "Unable to reset inverse teleporter.";

		private const string InSpaceError = "Can't use the Inverse Teleporter in space!";

		[TerminalCommand("Teleport", false)]
		public string TeleportCommand()
		{
			if (!TryGetTeleporter(out ShipTeleporter teleporter, out string errorMessage))
			{
				return errorMessage;
			}
			if (!teleporter.buttonTrigger.interactable)
			{
				int num = (int)Utils.GetInstancedStructField<float>(teleporter, "cooldownTime");
				return $"Teleporter is on cooldown, {num:D} seconds left!";
			}
			((UnityEvent<PlayerControllerB>)(object)teleporter.buttonTrigger.onInteract).Invoke(GameNetworkManager.Instance.localPlayerController);
			return "Teleporting Player..";
		}

		[TerminalCommand("iTeleport", false)]
		public string InverseTeleportCommand()
		{
			if (!StartOfRound.Instance.shipDoorsEnabled)
			{
				return "Can't use the Inverse Teleporter in space!";
			}
			if (!TryGetTeleporter(out ShipTeleporter teleporter, out string errorMessage, isInverted: true))
			{
				return errorMessage;
			}
			if (!teleporter.buttonTrigger.interactable)
			{
				int num = (int)Utils.GetInstancedStructField<float>(teleporter, "cooldownTime");
				return $"Inverse Teleporter is on cooldown, {num:D} seconds left!";
			}
			((UnityEvent<PlayerControllerB>)(object)teleporter.buttonTrigger.onInteract).Invoke(GameNetworkManager.Instance.localPlayerController);
			return "Tally ho, lads!";
		}

		[TerminalCommand("tp", false)]
		[CommandInfo("Activates teleporter.", "")]
		public string TpCommand()
		{
			return TeleportCommand();
		}

		[TerminalCommand("itp", false)]
		[CommandInfo("Activates the Inverse Teleporter.", "")]
		public string ItpCommand()
		{
			return InverseTeleportCommand();
		}

		internal static bool TryGetTeleporter([NotNullWhen(true)] out ShipTeleporter? teleporter, out string errorMessage, bool isInverted = false)
		{
			errorMessage = string.Empty;
			GameObject val = GameObject.Find(isInverted ? "InverseTeleporter(Clone)" : "Teleporter(Clone)");
			if (val == null)
			{
				teleporter = null;
				errorMessage = "No Teleporter in ship!";
				return false;
			}
			teleporter = val.GetComponent<ShipTeleporter>();
			if (teleporter == null)
			{
				teleporter = null;
				errorMessage = "<!!!> Cannot locate ShipTeleporter Component! <!!!>";
				return false;
			}
			return errorMessage.IsNullOrWhitespace();
		}

		internal static bool TryResetInverseTeleporter()
		{
			if (!TryGetTeleporter(out ShipTeleporter teleporter, out string errorMessage, isInverted: true))
			{
				Plugin.Logger.LogDebug((object)"Unable to reset inverse teleporter.");
				Plugin.Logger.LogDebug((object)errorMessage);
				return false;
			}
			Plugin.Logger.LogInfo((object)"Inverse Teleporter loaded. Resetting cooldown");
			Utils.SetInstancedStructField(teleporter, "cooldownTime", 0f);
			((Behaviour)teleporter).enabled = true;
			teleporter.buttonTrigger.cooldownTime = 0f;
			teleporter.buttonTrigger.interactable = true;
			int num = (int)Utils.GetInstancedStructField<float>(teleporter, "cooldownTime");
			Plugin.Logger.LogInfo((object)$"Inverse Teleporter is on cooldown, {num:D} seconds left!");
			return true;
		}
	}
}