Decompiled source of darmuhsTerminalStuff v3.6.8

darmuhsTerminalStuff.dll

Decompiled 2 weeks ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CruiserTerminal;
using FovAdjust;
using GameNetcodeStuff;
using HarmonyLib;
using LethalConstellations.PluginCore;
using LobbyCompatibility.Enums;
using LobbyCompatibility.Features;
using Microsoft.CodeAnalysis;
using OpenBodyCams;
using OpenLib;
using OpenLib.Common;
using OpenLib.Compat;
using OpenLib.ConfigManager;
using OpenLib.CoreMethods;
using OpenLib.Events;
using OpenLib.Menus;
using ShipInventory.Helpers;
using ShipInventory.Objects;
using TMPro;
using TerminalStuff;
using TerminalStuff.Compatibility;
using TerminalStuff.EventSub;
using TerminalStuff.PluginCore;
using TerminalStuff.SpecialStuff;
using TerminalStuff.VisualCore;
using TwoRadarMaps;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.TextCore.LowLevel;
using UnityEngine.UI;
using UnityEngine.Video;
using darmuhsTerminalStuff.NetcodePatcher;
using suitsTerminal;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("darmuhsTerminalStuff")]
[assembly: AssemblyDescription("https://github.com/darmuh/TerminalStuff")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("darmuhsTerminalStuff")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e2700abc-7bc7-4bd0-b787-effe68445b6a")]
[assembly: AssemblyFileVersion("3.6.8")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("3.6.8.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
	}
}
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;
		}
	}
}
[HarmonyPatch]
public class NetObject
{
	private static GameObject networkPrefab;

	[HarmonyPostfix]
	[HarmonyPatch(typeof(GameNetworkManager), "Start")]
	public static void Init()
	{
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Expected O, but got Unknown
		if (ConfigSettings.ModNetworking.Value && !((Object)(object)networkPrefab != (Object)null))
		{
			AssetBundle val = AssetBundle.LoadFromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("TerminalStuff.darmuhngo"));
			networkPrefab = (GameObject)val.LoadAsset("darmuhNGO");
			networkPrefab.AddComponent<NetHandler>();
			NetworkManager.Singleton.AddNetworkPrefab(networkPrefab);
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(StartOfRound), "Awake")]
	private static void SpawnNetworkHandler()
	{
		//IL_0033: 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 (ConfigSettings.ModNetworking.Value && (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer))
		{
			GameObject val = Object.Instantiate<GameObject>(networkPrefab, Vector3.zero, Quaternion.identity);
			val.GetComponent<NetworkObject>().Spawn(false);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace TutorialNameSpace
{
	internal class Tutorial
	{
		internal static void AddMyCommands()
		{
			AddingThings.AddBasicCommand("command1", "command1", "command 1 text", false, true, "", "");
		}

		internal static void OnTerminalAwake(Terminal instance)
		{
			AddMyCommands();
		}

		internal static void Subscribers()
		{
			EventManager.TerminalAwake.AddListener((ParameterEvent<Terminal>)OnTerminalAwake);
		}
	}
}
namespace TerminalStuff
{
	internal class AdminCommands
	{
		internal static PlayerControllerB playerToKick;

		internal static bool kickEnum;

		internal static string KickPlayersAsk()
		{
			playerToKick = null;
			string afterKeyword = StringStuff.GetAfterKeyword(StringStuff.GetKeywordsPerConfigItem(ConfigSettings.KickKeywords.Value));
			if (!AmIHost(out var displayText))
			{
				return displayText;
			}
			if (afterKeyword.Length < 1)
			{
				string text = PlayerNameAndIDList();
				return "You must specify a player name or ID to kick them!\r\n\tKickable Players:\r\n(id) PlayerName" + text + "\r\n\r\n";
			}
			if (ulong.TryParse(afterKeyword, out var result))
			{
				PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
				foreach (PlayerControllerB val in allPlayerScripts)
				{
					if (val.playerClientId == result && (Object)(object)StartOfRound.Instance.localPlayerController != (Object)(object)val && val.isPlayerControlled)
					{
						playerToKick = val;
						displayText = "Kick " + val.playerUsername + " from the lobby?\n\n\n\n\n\n\n\n\n\n\nPlease CONFIRM or DENY.\r\n\r\n";
						Plugin.MoreLogs("valid player to kick from id");
						return displayText;
					}
				}
			}
			else
			{
				Plugin.Spam("ulong failed parse");
				string text2 = afterKeyword.ToLower();
				PlayerControllerB[] allPlayerScripts2 = StartOfRound.Instance.allPlayerScripts;
				foreach (PlayerControllerB val2 in allPlayerScripts2)
				{
					if (val2.playerUsername.ToLower() == text2)
					{
						playerToKick = val2;
						return "Kick " + val2.playerUsername + " from the lobby?\n\n\n\n\n\n\n\n\n\n\nPlease CONFIRM or DENY.\r\n\r\n";
					}
				}
			}
			return "Unable to find player to kick by name or id - " + afterKeyword + "\r\n\r\n";
		}

		private static string PlayerNameAndIDList()
		{
			StringBuilder stringBuilder = new StringBuilder();
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if ((Object)(object)StartOfRound.Instance.localPlayerController != (Object)(object)val && val.isPlayerControlled)
				{
					stringBuilder.Append($"\r\n({val.playerClientId}) {val.playerUsername}\r\n");
				}
			}
			return stringBuilder.ToString();
		}

		internal static bool AmIHost(out string displayText)
		{
			displayText = "";
			if (((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsHost)
			{
				return true;
			}
			displayText = "You do not have permission to kick players from this lobby, you are NOT the host.\r\n\r\n";
			Plugin.Log.LogWarning((object)"Somehow non-host player could try to kick others, error handled.");
			return false;
		}

		internal static string KickPlayerConfirm()
		{
			int playerToKickID = GetPlayerToKickID(playerToKick);
			((MonoBehaviour)Plugin.instance.Terminal).StartCoroutine(KickYes(playerToKickID));
			return "Kick Player Action Confirmed.\r\n\r\n\tKicking player: " + playerToKick.playerUsername + "\r\n\r\n";
		}

		internal static string KickPlayerDeny()
		{
			string result = "Cancelling kick player action for player:" + playerToKick.playerUsername + "\r\n\r\n";
			playerToKick = null;
			return result;
		}

		internal static int GetPlayerToKickID(PlayerControllerB matchingPlayer)
		{
			int result = -1;
			for (int i = 0; i < StartOfRound.Instance.allPlayerScripts.Count(); i++)
			{
				if (StartOfRound.Instance.allPlayerScripts[i].playerUsername == matchingPlayer.playerUsername)
				{
					result = i;
					break;
				}
			}
			return result;
		}

		internal static IEnumerator KickYes(int playerNum)
		{
			if (!kickEnum)
			{
				kickEnum = true;
				Plugin.Spam("We made it to the kick event!!");
				Plugin.Spam("playerObjIdForTerminal = " + playerNum);
				Plugin.instance.Terminal.QuitTerminal(true);
				yield return (object)new WaitForSeconds(0.1f);
				StartOfRound.Instance.KickPlayer(playerNum);
				Plugin.Spam("kicked");
				kickEnum = false;
			}
		}
	}
	internal class LevelCommands
	{
		internal static List<string> bannedWeather = new List<string>();

		internal static List<string> bannedWeatherConfig = new List<string>();

		internal static string RouteRandomCommand()
		{
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.instance.Terminal.groupCredits < ConfigSettings.RouteRandomCost.Value)
			{
				return $"You cannot afford to run the 'route random' command.\r\n\r\n\tRoute Random Cost: [{ConfigSettings.RouteRandomCost.Value}]\r\n\tYour credits: <color=#BD3131>[{Plugin.instance.Terminal.groupCredits}]</color>\r\n\r\n\r\n";
			}
			bannedWeatherConfig = StringStuff.GetKeywordsPerConfigItem(ConfigSettings.RouteRandomBannedWeather.Value);
			bannedWeather = StringStuff.GetListToLower(bannedWeatherConfig);
			List<SelectableLevel> list = new List<SelectableLevel>();
			SelectableLevel[] moonsCatalogueList = Plugin.instance.Terminal.moonsCatalogueList;
			foreach (SelectableLevel val in moonsCatalogueList)
			{
				if (bannedWeather.Contains(((object)(LevelWeatherType)(ref val.currentWeather)).ToString().ToLower()))
				{
					Plugin.MoreLogs($"{val.PlanetName} has banned weather: {val.currentWeather}");
				}
				else if (ConfigSettings.RouteOnlyInCurrentConstellation.Value && Plugin.instance.Constellations)
				{
					if (ConstellationsCompat.IsLevelInConstellation(val))
					{
						list.Add(val);
						Plugin.MoreLogs("Added " + val.PlanetName + " to valid random planets within the current constellation!");
					}
				}
				else
				{
					list.Add(val);
					Plugin.MoreLogs("Added " + val.PlanetName + " to valid random planets");
				}
			}
			if (list.Count < 1)
			{
				return "Route Random was unable to select a valid moon and you have not been charged.\r\n\r\nThis may be due to all moons have banned weather attributes...\r\n\r\n\r\n";
			}
			Random random = new Random();
			int index = random.Next(0, list.Count);
			Plugin.MoreLogs(list[index].PlanetName + " has been chosen!");
			StartOfRound.Instance.ChangeLevelServerRpc(list[index].levelID, Plugin.instance.Terminal.groupCredits);
			StartOfRound.Instance.SetMapScreenInfoToCurrentLevel();
			int num = CostCommands.CalculateNewCredits(Plugin.instance.Terminal.groupCredits, ConfigSettings.RouteRandomCost.Value, Plugin.instance.Terminal);
			return $"Your new balance is ■{num} Credits.\r\n\r\nRoute Random has chosen {list[index].PlanetName}!\r\n\r\n\tEnjoy!\r\n\r\n";
		}
	}
	internal class AllTheLootStuff
	{
		internal static string GetLootSimple()
		{
			Plugin.Spam("calculating loot value next");
			float num = CalculateLootValue();
			string text;
			if (Plugin.instance.ShipInventory)
			{
				int inventoryValue = ShipInventoryCompat.GetInventoryValue();
				text = $"Total Value on Ship: ${num}\n\nTotal Value in Ship Inventory: ${inventoryValue}";
			}
			else
			{
				text = $"Total Value on Ship: ${num}";
			}
			Plugin.Spam("loot calculated");
			return text + "\n\n";
		}

		internal static string DetailedLootCommand()
		{
			LoadGrabbablesOnShip.LoadAllItems();
			StringBuilder stringBuilder = new StringBuilder();
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			int totalCredsWorth = 0;
			foreach (GrabbableObject item in LoadGrabbablesOnShip.ItemsOnShip)
			{
				string itemName = item.itemProperties.itemName;
				int scrapValue = item.scrapValue;
				if (item.itemProperties.isScrap)
				{
					string text = $"{itemName} ({scrapValue} credits)";
					Plugin.Spam(text + "added to output");
					totalCredsWorth += scrapValue;
					dictionary[text] = ((!dictionary.TryGetValue(text, out var value)) ? 1 : (value + 1));
				}
			}
			foreach (KeyValuePair<string, int> item2 in dictionary)
			{
				if (item2.Value > 1)
				{
					stringBuilder.AppendLine($"{item2.Key} [x{item2.Value}]");
				}
				else
				{
					stringBuilder.AppendLine(item2.Key ?? "");
				}
			}
			if (Plugin.instance.ShipInventory)
			{
				ShipInventoryCompat.GetInventoryItems(out var itemsInventory);
				StringBuilder arg = ShipInventoryItems(itemsInventory, ref totalCredsWorth);
				return $"Scrap on ship (not stored):\n\n{stringBuilder}Scrap stored in Ship Inventory:\n\n{arg}\n\n\tTotal Value: {totalCredsWorth}\n\n";
			}
			return $"Scrap on ship:\n\n{stringBuilder}\n\n\tTotal Value: {totalCredsWorth}\n\n";
		}

		private static StringBuilder ShipInventoryItems(List<Item> inventory, ref int totalCredsWorth)
		{
			StringBuilder stringBuilder = new StringBuilder();
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			foreach (Item item in inventory)
			{
				if (item.isScrap)
				{
					string itemName = item.itemName;
					int creditsWorth = item.creditsWorth;
					string text = $"{itemName} ({creditsWorth} credits)";
					Plugin.Spam(text + "added to output");
					totalCredsWorth += creditsWorth;
					dictionary[text] = ((!dictionary.TryGetValue(text, out var value)) ? 1 : (value + 1));
				}
			}
			foreach (KeyValuePair<string, int> item2 in dictionary)
			{
				if (item2.Value > 1)
				{
					stringBuilder.AppendLine($"{item2.Key} [x{item2.Value}]");
				}
				else
				{
					stringBuilder.AppendLine(item2.Key ?? "");
				}
			}
			return stringBuilder;
		}

		private static float CalculateLootValue()
		{
			List<GrabbableObject> list = (from obj in GameObject.Find("/Environment/HangarShip").GetComponentsInChildren<GrabbableObject>()
				where ((Object)obj).name != "ClipboardManual" && ((Object)obj).name != "StickyNoteItem" && ((Object)obj).name != "Key(Clone)"
				select obj).ToList();
			Plugin.Log.LogDebug((object)"Calculating total ship scrap value.");
			CollectionExtensions.Do<GrabbableObject>((IEnumerable<GrabbableObject>)list, (Action<GrabbableObject>)delegate(GrabbableObject scrap)
			{
				Plugin.Log.LogDebug((object)$"{((Object)scrap).name} - ${scrap.scrapValue}");
			});
			return list.Sum((GrabbableObject scrap) => scrap.scrapValue);
		}
	}
	internal class ColorCommands
	{
		internal static Color? CustomFlashColor;

		internal static string flashLightColor;

		internal static bool usingHexCode;

		internal static bool RainbowFlash;

		internal static void FlashLightCommandAction(out string displayText)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			RainbowFlash = false;
			Color val = (Color)(((??)CustomFlashColor) ?? Color.white);
			Plugin.MoreLogs($"got {flashLightColor} - {val}");
			displayText = "The next time you turn on your flashlight, the color will be set to " + flashLightColor + "!\r\n\r\n";
		}

		internal static void SetCustomColor(string colorKeyword, out Color? customColor)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_038e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0393: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			if (IsHexColorCode(colorKeyword))
			{
				usingHexCode = true;
				customColor = HexToColor("#" + colorKeyword);
				return;
			}
			string text = colorKeyword.ToLower();
			if (1 == 0)
			{
			}
			Color? val = text switch
			{
				"white" => Color.white, 
				"red" => Color.red, 
				"blue" => Color.blue, 
				"yellow" => Color.yellow, 
				"cyan" => Color.cyan, 
				"magenta" => Color.magenta, 
				"green" => Color.green, 
				"purple" => Color32.op_Implicit(new Color32((byte)144, (byte)100, (byte)254, (byte)1)), 
				"lime" => Color32.op_Implicit(new Color32((byte)166, (byte)254, (byte)0, (byte)1)), 
				"pink" => Color32.op_Implicit(new Color32((byte)242, (byte)0, (byte)254, (byte)1)), 
				"maroon" => Color32.op_Implicit(new Color32((byte)114, (byte)3, (byte)3, (byte)1)), 
				"orange" => Color32.op_Implicit(new Color32(byte.MaxValue, (byte)117, (byte)24, (byte)1)), 
				"sasstro" => Color32.op_Implicit(new Color32((byte)212, (byte)148, (byte)180, (byte)1)), 
				"samstro" => Color32.op_Implicit(new Color32((byte)180, (byte)203, (byte)240, (byte)1)), 
				_ => null, 
			};
			if (1 == 0)
			{
			}
			customColor = val;
		}

		internal static bool IsHexColorCode(string input)
		{
			return Regex.IsMatch(input, "^(?:[0-9a-fA-F]{3}){1,2}$");
		}

		internal static Color HexToColor(string hex)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			Color result = default(Color);
			ColorUtility.TryParseHtmlString(hex, ref result);
			return result;
		}

		internal static string ShipColorBase()
		{
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			string afterKeyword = StringStuff.GetAfterKeyword(StringStuff.GetKeywordsPerConfigItem(ConfigSettings.ScolorKeywords.Value));
			if (afterKeyword.Length < 1)
			{
				string result = ShipColorList();
				Plugin.WARNING("not enough words for the command!");
				return result;
			}
			if (afterKeyword.ToLower().Contains("list"))
			{
				string result2 = ShipColorList();
				Plugin.MoreLogs("list requested");
				return result2;
			}
			string[] words = afterKeyword.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			if (!ShipColorCommon(words, out var displayText, out var targetColor, out var newColor))
			{
				return displayText;
			}
			if (afterKeyword.ToLower().Contains("all"))
			{
				NetHandler.Instance.ShipColorALLServerRpc(newColor, targetColor);
				return displayText;
			}
			if (afterKeyword.ToLower().Contains("front"))
			{
				NetHandler.Instance.ShipColorFRONTServerRpc(newColor, targetColor);
				return displayText;
			}
			if (afterKeyword.ToLower().Contains("mid"))
			{
				NetHandler.Instance.ShipColorMIDServerRpc(newColor, targetColor);
				return displayText;
			}
			if (afterKeyword.ToLower().Contains("back"))
			{
				NetHandler.Instance.ShipColorBACKServerRpc(newColor, targetColor);
				return displayText;
			}
			Plugin.WARNING("failed to grab specific part of ship lights to change");
			return ShipColorList();
		}

		internal static bool ShipColorCommon(string[] words, out string displayText, out string targetColor, out Color newColor)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			if (words.Length < 2)
			{
				displayText = ShipColorList();
				Plugin.MoreLogs("not enough words for the command, returning list!");
				targetColor = string.Empty;
				newColor = Color.white;
				return false;
			}
			targetColor = words[1];
			Plugin.MoreLogs("Attempting to set " + words[0] + " ship light colors to " + targetColor);
			SetCustomColor(targetColor, out var customColor);
			if (customColor.HasValue && targetColor != null)
			{
				newColor = customColor.Value;
				displayText = "Color of " + words[0] + " ship lights set to " + targetColor + "!\r\n\r\n";
				return true;
			}
			targetColor = "";
			newColor = Color.white;
			displayText = "Unable to set " + words[0] + " ship light color...\r\n\tInvalid color [" + targetColor + "] detected!\r\n\r\n";
			Plugin.WARNING("invalid color for the color command!");
			return false;
		}

		internal static string ShipColorList()
		{
			string text = StringStuff.GetKeywordsPerConfigItem(ConfigSettings.ScolorKeywords.Value)[0];
			return "========= Ship Lights Color Options List =========\r\nColor Name: \"command used\"\r\n\r\nDefault: \"" + text + " all normal\" or \"" + text + " all default\"\r\nRed: \"" + text + " back red\"\r\nGreen: \"" + text + " mid green\"\r\nBlue: \"" + text + " front blue\"\r\nYellow: \"" + text + " middle yellow\"\r\nCyan: \"" + text + " all cyan\"\r\nMagenta: \"" + text + " back magenta\"\r\nPurple: \"" + text + " mid purple\"\r\nLime: \"" + text + " all lime\"\r\nPink: \"" + text + " front pink\"\r\nMaroon: \"" + text + " middle maroon\"\r\nOrange: \"" + text + " back orange\"\r\nSasstro's Color: \"" + text + " all sasstro\"\r\nSamstro's Color: \"" + text + " all samstro\"\r\nANY HEXCODE: \"" + text + " all FF00FF\"\r\n\r\n\r\n";
		}

		internal static string FlashColorBase()
		{
			string afterKeyword = StringStuff.GetAfterKeyword(StringStuff.GetKeywordsPerConfigItem(ConfigSettings.FcolorKeywords.Value));
			if (afterKeyword.Length < 1)
			{
				string result = FlashColorList();
				Plugin.WARNING("getting list, not enough words for color command!");
				return result;
			}
			if (afterKeyword.ToLower().Contains("list"))
			{
				string result = FlashColorList();
				Plugin.MoreLogs("displaying flashcolor list");
				return result;
			}
			if (afterKeyword.ToLower().Contains("rainbow"))
			{
				string result = FlashColorRainbow();
				Plugin.MoreLogs("running rainbow command");
				return result;
			}
			if (afterKeyword.ToLower().Contains("normal") || afterKeyword.ToLower().Contains("default"))
			{
				Plugin.MoreLogs("Player no longer wants a custom flashlight color!");
				CustomFlashColor = null;
				RainbowFlash = false;
				return "Flashlight color preference set back to default!\n\nFlashlight's with the default color will no longer be updated!\r\n\r\n";
			}
			string text = afterKeyword.TrimStart(Array.Empty<char>());
			Plugin.MoreLogs("Attempting to set flashlight color to " + text);
			SetCustomColor(text, out CustomFlashColor);
			flashLightColor = text;
			if (CustomFlashColor.HasValue)
			{
				Plugin.MoreLogs("Using flashlight color: " + text);
				NetHandler.Instance.endFlashRainbow = true;
				FlashLightCommandAction(out var displayText);
				return displayText;
			}
			string result2 = "Unable to set flashlight color...\r\n\tInvalid color: [" + text + "] detected!\r\n\r\n";
			Plugin.WARNING("invalid color for the color command!");
			return result2;
		}

		internal static string FlashColorList()
		{
			string text = StringStuff.GetKeywordsPerConfigItem(ConfigSettings.FcolorKeywords.Value)[0];
			return "========= Flashlight Color Options List =========\r\nColor Name: \"command used\"\r\n\r\nDefault: \"" + text + " normal\" or \"" + text + " default\"\r\nRed: \"" + text + " red\"\r\nGreen: \"" + text + " green\"\r\nBlue: \"" + text + " blue\"\r\nYellow: \"" + text + " yellow\"\r\nCyan: \"" + text + " cyan\"\r\nMagenta: \"" + text + " magenta\"\r\nPurple: \"" + text + " purple\"\r\nLime: \"" + text + " lime\"\r\nPink: \"" + text + " pink\"\r\nMaroon: \"" + text + " maroon\"\r\nOrange: \"" + text + " orange\"\r\nSasstro's Color: \"" + text + " sasstro\"\r\nSamstro's Color: \"" + text + " samstro\"\r\n\r\nRainbow Color (animated): \"" + text + " rainbow\"\r\nANY HEXCODE: \"" + text + " FF00FF\"\r\n\r\n";
		}

		internal static string FlashColorRainbow()
		{
			if (DoIhaveFlash(StartOfRound.Instance.localPlayerController))
			{
				NetHandler.Instance.CycleThroughRainbowFlash();
				return "Flashlight color set to Rainbow Mode! (performance may vary)\r\n\r\n";
			}
			RainbowFlash = true;
			return "The next flashlight you hold will be set to rainbow mode! (performance may vary)\r\n\r\n";
		}

		private static bool DoIhaveFlash(PlayerControllerB player)
		{
			GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
			GrabbableObject[] array2 = array;
			foreach (GrabbableObject val in array2)
			{
				if ((Object)(object)val.playerHeldBy != (Object)null && val.playerHeldBy.playerUsername == player.playerUsername && ((Object)((Component)val).gameObject).name.Contains("Flashlight"))
				{
					return true;
				}
			}
			return false;
		}
	}
	internal class CostCommands
	{
		internal static bool vitalsUpgradeEnabled = false;

		internal static bool enemyScanUpgradeEnabled = false;

		internal static List<int> storeCart = new List<int>();

		internal static string currentPackList;

		internal static string currentPackName;

		internal static string buyPackName;

		internal static Dictionary<Item, int> itemsIndexed = new Dictionary<Item, int>();

		internal static bool CheckUnlockableStatus(string itemName)
		{
			foreach (UnlockableItem unlockable in StartOfRound.Instance.unlockablesList.unlockables)
			{
				if (unlockable.unlockableName == itemName && (unlockable.alreadyUnlocked || unlockable.hasBeenUnlockedByPlayer))
				{
					Plugin.Spam("Upgrade: " + itemName + " already unlocked. Setting variable to true");
					return true;
				}
			}
			Plugin.Spam("Upgrade: " + itemName + " is NOT unlocked already");
			return false;
		}

		internal static bool CheckUnlockableStatus(int itemID)
		{
			if (itemID >= StartOfRound.Instance.unlockablesList.unlockables.Count)
			{
				return false;
			}
			UnlockableItem val = StartOfRound.Instance.unlockablesList.unlockables[itemID];
			if (!val.alreadyUnlocked && !val.hasBeenUnlockedByPlayer)
			{
				Plugin.Spam($"Upgrade ID: {itemID} has not been unlocked. Setting variable to true");
				return true;
			}
			return false;
		}

		internal static void UpdateUnlockStatus()
		{
			enemyScanUpgradeEnabled = false;
			vitalsUpgradeEnabled = false;
			foreach (string item in SaveManager.AllUpgradesUnlocked)
			{
				Plugin.Spam("Updating upgrade status for " + item);
				if (item == "BioscanPatch")
				{
					enemyScanUpgradeEnabled = true;
				}
				else if (item == "VitalsPatch")
				{
					vitalsUpgradeEnabled = true;
				}
				else
				{
					Plugin.WARNING("Unexpected upgrade unlock name [ " + item + " ]");
				}
			}
		}

		internal static string BioscanCommand()
		{
			if ((Object)(object)RoundManager.Instance != (Object)null)
			{
				int count = RoundManager.Instance.SpawnedEnemies.Count;
				int groupCredits = Plugin.instance.Terminal.groupCredits;
				int value = ConfigSettings.BioScanCost.Value;
				string result;
				if (ShouldRunBioscan2(groupCredits, value))
				{
					int newCreds = CalculateNewCredits(groupCredits, value, Plugin.instance.Terminal);
					List<EnemyAI> livingEnemiesList = GetLivingEnemiesList();
					string text = FilterLivingEnemies(livingEnemiesList);
					string bioscanResult = GetBioscanResult(count, value, newCreds, text);
					result = bioscanResult;
					Plugin.MoreLogs("Living Enemies(filtered): " + text);
					return result;
				}
				if (groupCredits >= value)
				{
					int newCreds2 = CalculateNewCredits(groupCredits, value, Plugin.instance.Terminal);
					string basicBioscanResult = GetBasicBioscanResult(count, value, newCreds2);
					result = basicBioscanResult;
					Plugin.MoreLogs("v1 scanner utilized, only numbers shown");
					return result;
				}
				result = "Not enough credits to run Biomatter Scanner.\r\n";
				Plugin.MoreLogs("brokeboy detected");
				return result;
			}
			return "Cannot scan for Biomatter at this time.\r\n";
		}

		private static bool ShouldRunBioscan2(int getCreds, int costCreds)
		{
			return enemyScanUpgradeEnabled && getCreds >= costCreds;
		}

		private static string GetBasicBioscanResult(int scannedEnemies, int costCreds, int newCreds)
		{
			return $"Biomatter scanner charged {costCreds} credits and has detected [{scannedEnemies}] non-employee organic objects.\r\n\r\nYour new balance is ■{newCreds} Credits.\r\n";
		}

		private static List<EnemyAI> GetLivingEnemiesList()
		{
			return RoundManager.Instance.SpawnedEnemies.Where((EnemyAI enemy) => !enemy.isEnemyDead).ToList();
		}

		private static string FilterLivingEnemies(List<EnemyAI> livingEnemies)
		{
			string input = string.Join(Environment.NewLine, livingEnemies.Select((EnemyAI enemy) => ((object)enemy).ToString()));
			string pattern = "\\([^)]*\\)";
			return Regex.Replace(input, pattern, string.Empty);
		}

		private static string GetBioscanResult(int scannedEnemies, int costCreds, int newCreds, string filteredLivingEnemiesString)
		{
			string text = $"Biomatter scanner charged {costCreds} credits and has detected [{scannedEnemies}] non-employee organic objects.\r\n\r\n";
			if (!string.IsNullOrEmpty(filteredLivingEnemiesString))
			{
				text += $"Your new balance is ■{newCreds} Credits.\r\n\r\nDetailed scan has defined these objects as the following in the registry: \r\n{filteredLivingEnemiesString}\r\n";
			}
			else
			{
				text += $"Your new balance is ■{newCreds} Credits.\r\n";
				Plugin.MoreLogs("v1 scanner utilized, only numbers shown");
			}
			return text;
		}

		internal static string VitalsCommand()
		{
			PlayerControllerB targetedPlayer = StartOfRound.Instance.mapScreen.targetedPlayer;
			if ((Object)(object)targetedPlayer == (Object)null)
			{
				return "Vitals command malfunctioning...\n\n";
			}
			int groupCredits = Plugin.instance.Terminal.groupCredits;
			int costCreds = GetCostCreds(vitalsUpgradeEnabled);
			string playerUsername = targetedPlayer.playerUsername;
			Plugin.MoreLogs("playername: " + playerUsername);
			if (ShouldDisplayVitals(targetedPlayer, groupCredits, costCreds))
			{
				int newCreds = CalculateNewCredits(groupCredits, costCreds, Plugin.instance.Terminal);
				string vitalsInfo = GetVitalsInfo(targetedPlayer);
				string creditsInfo = GetCreditsInfo(newCreds);
				if (!vitalsUpgradeEnabled)
				{
					return $"Charged ■{costCreds} Credits. \n{vitalsInfo}\n{creditsInfo}";
				}
				return vitalsInfo + "\n" + creditsInfo;
			}
			return ConfigSettings.VitalsPoorString.Value + "\n";
		}

		internal static int GetCostCreds(bool upgradeStatus)
		{
			if (!upgradeStatus)
			{
				return ConfigSettings.VitalsCost.Value;
			}
			return 0;
		}

		internal static string AskBioscanUpgrade()
		{
			if (!enemyScanUpgradeEnabled)
			{
				return $"Purchase the BioScanner 2.0 Upgrade Patch?\nThis software update is available for {ConfigSettings.BioScanUpgradeCost.Value} Credits.\n\n\n\n\n\n\n\n\n\n\nPlease CONFIRM or DENY.\n";
			}
			TerminalGeneral.CancelConfirmation = true;
			return "BioScanner software has already been updated to the latest patch (2.0).\r\n\r\n";
		}

		internal static string AskVitalsUpgrade()
		{
			if (!vitalsUpgradeEnabled)
			{
				return $"Purchase the Vitals Scanner 2.0 Patch?\nThis software update is available for {ConfigSettings.VitalsUpgradeCost.Value} Credits.\n\n\n\n\n\n\n\n\n\n\nPlease CONFIRM or DENY.\n";
			}
			TerminalGeneral.CancelConfirmation = true;
			return "Vitals Scanner software has already been updated to the latest patch (2.0).\r\n\r\n";
		}

		private static int GetIndexNum(Item givenItem)
		{
			int num = 0;
			Item[] buyableItemsList = Plugin.instance.Terminal.buyableItemsList;
			foreach (Item val in buyableItemsList)
			{
				if ((Object)(object)givenItem == (Object)(object)val)
				{
					return num;
				}
				num++;
			}
			return -1;
		}

		private static bool TryGetItemToBuy(string itemName, out Item itemValue)
		{
			int num = 0;
			Item[] buyableItemsList = Plugin.instance.Terminal.buyableItemsList;
			foreach (Item val in buyableItemsList)
			{
				if (val.itemName.ToLower().Contains(itemName))
				{
					Plugin.Spam($"{val.itemName} found matching to {itemName} at index: [{num}]");
					if (itemsIndexed.ContainsKey(val))
					{
						Plugin.Spam(itemName + " already indexed");
					}
					else
					{
						itemsIndexed.Add(val, num);
						Plugin.Spam("indexed item: " + itemName);
					}
					itemValue = val;
					return true;
				}
				Plugin.Spam($"{val.itemName} at index [{num}] does not match config item {itemName}");
				num++;
			}
			itemValue = null;
			return false;
		}

		private static int GetTotalCost(Dictionary<Item, int> itemsToPurchase, Dictionary<Item, int> itemsIndexed, out int itemCount)
		{
			int num = 0;
			itemCount = 0;
			if (itemsIndexed.Count == 0 || itemsToPurchase.Count == 0)
			{
				return num;
			}
			foreach (KeyValuePair<Item, int> item in itemsToPurchase)
			{
				int num2 = itemsToPurchase[item.Key];
				int num3 = item.Key.creditsWorth * (Plugin.instance.Terminal.itemSalesPercentages[itemsIndexed[item.Key]] / 100);
				num3 *= num2;
				num += num3;
				itemCount += num2;
				Plugin.Spam($"Added {num3} to total: {num} (total item count: {itemCount})");
			}
			Plugin.MoreLogs($"Total Cost: [{num}]");
			return num;
		}

		private static int GetUpgradesTotalCost(List<TerminalNode> upgradeList, out int itemCount)
		{
			int num = 0;
			itemCount = 0;
			foreach (TerminalNode upgrade in upgradeList)
			{
				num += upgrade.itemCost;
				itemCount++;
				Plugin.Spam($"Adding {upgrade.itemCost} to total: {num}");
			}
			Plugin.Spam($"totalCost: {num}");
			return num;
		}

		internal static string AskPurchasePack()
		{
			itemsIndexed.Clear();
			List<string> itemList = StringStuff.GetItemList(currentPackList);
			Dictionary<Item, int> itemsToPurchase = new Dictionary<Item, int>();
			StringBuilder packAsk = new StringBuilder();
			packAsk.AppendLine("Would you like to purchase the [" + currentPackName + "] PurchasePack?\r\n\r\n\tContents:\r\n");
			PurchasePackContents(itemList, ref itemsToPurchase, ref packAsk, out var upgradeItems);
			int itemCount;
			int num = GetTotalCost(itemsToPurchase, itemsIndexed, out itemCount);
			if (upgradeItems.Count > 0)
			{
				int itemCount2;
				int upgradesTotalCost = GetUpgradesTotalCost(upgradeItems, out itemCount2);
				Plugin.Spam($"Adding {upgradesTotalCost} to {num}");
				num += upgradesTotalCost;
				itemCount += itemCount2;
			}
			if (num <= Plugin.instance.Terminal.groupCredits)
			{
				packAsk.AppendLine($"\r\n\tTotal Cost: ■{num}({itemCount} items)\r\n\r\nPlease CONFIRM or DENY.\n");
				buyPackName = currentPackName;
				return packAsk.ToString();
			}
			Plugin.MoreLogs("not enough credits to purchase, sending to cannot afford display");
			TerminalGeneral.CancelConfirmation = true;
			return $"You cannot afford the {currentPackName} PurchasePack ({itemCount} items).\r\n\r\n\tTotal Cost: ■<color=#BD3131>{num}</color>\r\n\r\n";
		}

		private static int GetNameCount(List<string> itemList, string itemName)
		{
			int num = 0;
			foreach (string item in itemList)
			{
				if (item == itemName)
				{
					num++;
					Plugin.Spam($"Count for {item} - {num}");
				}
			}
			Plugin.MoreLogs($"Final Count: {itemName} - {num}");
			return num;
		}

		internal static int GetCostFromList(List<string> itemList)
		{
			int num = 0;
			foreach (string item in itemList)
			{
				TerminalNode UpgradeNode;
				if (TryGetItem(item, out var itemValue))
				{
					Plugin.Spam(item + " is a valid item, getting cost");
					int indexNum = GetIndexNum(itemValue);
					int num2 = itemValue.creditsWorth * (Plugin.instance.Terminal.itemSalesPercentages[indexNum] / 100);
					Plugin.Spam($"Adding {num2} to {num}");
					num += num2;
				}
				else if (TryGetUpgrade(item, out UpgradeNode))
				{
					Plugin.Spam("Upgrade detected");
					if ((Object)(object)UpgradeNode == (Object)null)
					{
						Plugin.Spam("returned upgradeItem terminalNode is null for some reason");
					}
					else if (CheckUnlockableStatus(UpgradeNode.shipUnlockableID))
					{
						Plugin.Spam($"list contains ship upgrade {UpgradeNode.creatureName}, adding value {UpgradeNode.itemCost} to {num}");
						num += UpgradeNode.itemCost;
					}
				}
			}
			Plugin.MoreLogs($"total cost of list: {num}");
			return num;
		}

		private static bool TryGetItem(string itemName, out Item itemValue)
		{
			Item[] buyableItemsList = Plugin.instance.Terminal.buyableItemsList;
			foreach (Item val in buyableItemsList)
			{
				if (val.itemName.ToLower().Contains(itemName))
				{
					itemValue = val;
					return true;
				}
			}
			itemValue = null;
			return false;
		}

		private static bool TryGetUpgrade(string upgradeName, out TerminalNode UpgradeNode)
		{
			UpgradeNode = null;
			Plugin.Spam("TryGetUpgrade from " + upgradeName);
			Plugin.Spam("iterating through Plugin.Allnodes");
			foreach (TerminalNode allnode in Plugin.Allnodes)
			{
				if ((Object)(object)allnode != (Object)null && allnode.creatureName != null && allnode.creatureName.ToLower().StartsWith(upgradeName.ToLower()) && allnode.shipUnlockableID > 0 && CheckUnlockableStatus(allnode.shipUnlockableID))
				{
					Plugin.Spam($"unlockableID: {allnode.shipUnlockableID}");
					Plugin.Spam("creatureName: " + allnode.creatureName + " matching " + upgradeName);
					UpgradeNode = allnode;
					return true;
				}
			}
			return false;
		}

		private static void PurchasePackContents(List<string> itemList, ref Dictionary<Item, int> itemsToPurchase, ref StringBuilder packAsk, out List<TerminalNode> upgradeItems)
		{
			List<string> list = new List<string>();
			upgradeItems = new List<TerminalNode>();
			foreach (string item in itemList)
			{
				TerminalNode UpgradeNode;
				if (TryGetItemToBuy(item, out var itemValue))
				{
					Plugin.Spam(item + " is a valid item, adding to pack purchase");
					int nameCount = GetNameCount(itemList, item);
					if (nameCount > 1 && !list.Contains(itemValue.itemName))
					{
						packAsk.AppendLine($"{itemValue.itemName} x{nameCount}");
					}
					else if (nameCount <= 1)
					{
						packAsk.AppendLine(itemValue.itemName ?? "");
					}
					if (!list.Contains(itemValue.itemName))
					{
						list.Add(itemValue.itemName);
					}
					if (!itemsToPurchase.ContainsKey(itemValue))
					{
						itemsToPurchase.Add(itemValue, nameCount);
					}
				}
				else if (TryGetUpgrade(item, out UpgradeNode) && !upgradeItems.Contains(UpgradeNode) && CheckUnlockableStatus(UpgradeNode.shipUnlockableID))
				{
					packAsk.AppendLine(UpgradeNode.creatureName ?? "");
					upgradeItems.Add(UpgradeNode);
					Plugin.Spam("list contains ship upgrades, adding to custom list and returning containsUpgrades true");
				}
			}
		}

		internal static int GetItemListCost(string rawList)
		{
			List<string> itemList = StringStuff.GetItemList(rawList);
			return GetCostFromList(itemList);
		}

		internal static string CompletePurchasePack()
		{
			itemsIndexed.Clear();
			bool costDeducted = false;
			List<string> itemList = StringStuff.GetItemList(currentPackList);
			Dictionary<Item, int> itemsToPurchase = new Dictionary<Item, int>();
			StringBuilder packAsk = new StringBuilder();
			packAsk.AppendLine("You have purchased the " + buyPackName + " PurchasePack!\r\n\r\n\tContents:\r\n");
			PurchasePackContents(itemList, ref itemsToPurchase, ref packAsk, out var upgradeItems);
			int itemCount;
			int num = GetTotalCost(itemsToPurchase, itemsIndexed, out itemCount);
			if (upgradeItems.Count > 0)
			{
				int itemCount2;
				int upgradesTotalCost = GetUpgradesTotalCost(upgradeItems, out itemCount2);
				Plugin.Spam($"Adding {upgradesTotalCost} to {num}");
				num += upgradesTotalCost;
				itemCount += itemCount2;
			}
			if (num > Plugin.instance.Terminal.groupCredits)
			{
				Plugin.MoreLogs("not enough credits to purchase, sending to error message");
				return Plugin.instance.Terminal.terminalNodes.specialNodes[5].displayText;
			}
			int[] array = BuyItems(itemsIndexed, itemsToPurchase);
			if (array.Length > 9)
			{
				MegaPurchase(array, num, out costDeducted);
			}
			else
			{
				Terminal terminal = Plugin.instance.Terminal;
				int[] array2 = array;
				int num2 = 0;
				int[] array3 = new int[array2.Length];
				int[] array4 = array2;
				foreach (int num3 in array4)
				{
					array3[num2] = num3;
					num2++;
				}
				terminal.BuyItemsServerRpc(array3, Plugin.instance.Terminal.groupCredits - num, Plugin.instance.Terminal.numberOfItemsInDropship + itemCount);
				costDeducted = true;
			}
			if (upgradeItems.Count > 0)
			{
				foreach (TerminalNode item in upgradeItems)
				{
					StartOfRound.Instance.BuyShipUnlockableServerRpc(item.shipUnlockableID, Plugin.instance.Terminal.groupCredits);
					Plugin.MoreLogs("Unlocking " + item.creatureName);
				}
				if (!costDeducted)
				{
					int[] array5 = Array.Empty<int>();
					Terminal terminal2 = Plugin.instance.Terminal;
					int[] array6 = array5;
					int num4 = 0;
					int[] array7 = new int[array6.Length];
					int[] array8 = array6;
					foreach (int num3 in array8)
					{
						array7[num4] = num3;
						num4++;
					}
					terminal2.BuyItemsServerRpc(array7, Plugin.instance.Terminal.groupCredits - num, Plugin.instance.Terminal.numberOfItemsInDropship);
				}
			}
			packAsk.AppendLine($"\r\n\r\nYour new balance is ■{Plugin.instance.Terminal.groupCredits} credits\r\n\r\n\tEnjoy!\r\n");
			Plugin.instance.Terminal.PlayTerminalAudioServerRpc(0);
			return packAsk.ToString();
		}

		private static void MegaPurchase(int[] fullItemList, int totalCost, out bool costDeducted)
		{
			int num = 0;
			List<int> list = new List<int>();
			foreach (int item in fullItemList)
			{
				if (num < 9)
				{
					list.Add(item);
					num++;
					Plugin.Spam($"count: {num}");
					continue;
				}
				Plugin.instance.Terminal.BuyItemsServerRpc(list.ToArray(), Plugin.instance.Terminal.groupCredits, Plugin.instance.Terminal.numberOfItemsInDropship + 9);
				Plugin.Spam($"purchased {num} items");
				num = 0;
				list.Clear();
				list.Add(item);
				num++;
			}
			if (list.Count > 0)
			{
				Plugin.instance.Terminal.BuyItemsServerRpc(list.ToArray(), Plugin.instance.Terminal.groupCredits, Plugin.instance.Terminal.numberOfItemsInDropship + list.Count);
				Plugin.Spam($"purchased another {list.Count} items");
			}
			int[] array = Array.Empty<int>();
			Terminal terminal = Plugin.instance.Terminal;
			int[] array2 = array;
			int num2 = 0;
			int[] array3 = new int[array2.Length];
			int[] array4 = array2;
			foreach (int num3 in array4)
			{
				array3[num2] = num3;
				num2++;
			}
			terminal.BuyItemsServerRpc(array3, Plugin.instance.Terminal.groupCredits - totalCost, Plugin.instance.Terminal.numberOfItemsInDropship);
			costDeducted = true;
			Plugin.Spam("end of megapurchase");
		}

		private static int[] BuyItems(Dictionary<Item, int> itemsIndexed, Dictionary<Item, int> itemCounts)
		{
			List<int> list = new List<int>();
			foreach (KeyValuePair<Item, int> item in itemsIndexed)
			{
				int num = itemCounts[item.Key];
				for (int i = 0; i < num; i++)
				{
					list.Add(item.Value);
					Plugin.Spam($"Adding {item.Key} to order list ({i})");
				}
			}
			return list.ToArray();
		}

		internal static string PerformBioscanUpgrade()
		{
			if (!enemyScanUpgradeEnabled)
			{
				int num = Plugin.instance.Terminal.groupCredits - ConfigSettings.BioScanUpgradeCost.Value;
				string result = $"Biomatter Scanner software has been updated to the latest patch (2.0) and now provides more detailed information!\r\n\r\nYour new balance is ■{num} Credits\r\n";
				SaveManager.NewUnlock("BioscanPatch");
				Plugin.instance.Terminal.SyncGroupCreditsServerRpc(num, Plugin.instance.Terminal.numberOfItemsInDropship);
				Plugin.instance.Terminal.PlayTerminalAudioServerRpc(0);
				return result;
			}
			return "BioScanner software has already been updated to the latest patch (2.0).\r\n\r\n";
		}

		internal static string GetRefund()
		{
			int numberOfItemsInDropship = Plugin.instance.Terminal.numberOfItemsInDropship;
			Item[] buyableItemsList = Plugin.instance.Terminal.buyableItemsList;
			List<string> list = new List<string>();
			int num = 0;
			Plugin.MoreLogs($"buyables: {buyableItemsList.Length}, deliverables: {numberOfItemsInDropship}, items: {storeCart.Count}");
			if (numberOfItemsInDropship > 0)
			{
				foreach (int item in storeCart)
				{
					if (item <= buyableItemsList.Length)
					{
						int indexNum = GetIndexNum(buyableItemsList[item]);
						int num2 = buyableItemsList[item].creditsWorth * (Plugin.instance.Terminal.itemSalesPercentages[indexNum] / 100);
						num += num2;
						string itemName = buyableItemsList[item].itemName;
						list.Add(itemName + "\n");
						Plugin.Spam($"Adding {itemName} ${num2} to refund list");
					}
					else
					{
						Plugin.Spam("Unable to add item to refund list");
					}
				}
				Plugin.Spam($"old creds: {Plugin.instance.Terminal.groupCredits}");
				int num3 = Plugin.instance.Terminal.groupCredits + num;
				Plugin.instance.Terminal.groupCredits = num3;
				Plugin.Spam($"new creds: {num3}");
				Plugin.instance.Terminal.orderedItemsFromTerminal.Clear();
				storeCart.Clear();
				NetHandler.Instance.SyncDropShipServerRpc(isRefund: true);
				NetHandler.Instance.SyncCreditsServerRpc(num3, 0);
				string arg = ListToStringBuild(list);
				Plugin.MoreLogs($"Refund total: ${num}");
				string result = $"Cancelling order for:\n{arg}\nYou have been refunded ■{num} Credits!\r\n";
				Plugin.instance.Terminal.PlayTerminalAudioServerRpc(0);
				return result;
			}
			return "No ordered items detected on the dropship.\n\n";
		}

		private static string ListToStringBuild(List<string> list)
		{
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < list.Count; i++)
			{
				stringBuilder.Append(list[i]);
			}
			return stringBuilder.ToString();
		}

		internal static string PerformVitalsUpgrade()
		{
			if (!vitalsUpgradeEnabled)
			{
				int num = Plugin.instance.Terminal.groupCredits - ConfigSettings.VitalsUpgradeCost.Value;
				SaveManager.NewUnlock("VitalsPatch");
				string result = $"Vitals Scanner software has been updated to the latest patch (2.0) and no longer requires credits to scan.\r\n\r\nYour new balance is ■{num} credits\r\n";
				Plugin.instance.Terminal.SyncGroupCreditsServerRpc(num, Plugin.instance.Terminal.numberOfItemsInDropship);
				Plugin.instance.Terminal.PlayTerminalAudioServerRpc(0);
				return result;
			}
			return "Update already purchased.\n";
		}

		private static bool ShouldDisplayVitals(PlayerControllerB playerInfo, int getCreds, int costCreds)
		{
			return !playerInfo.isPlayerDead && (getCreds >= costCreds || vitalsUpgradeEnabled);
		}

		internal static int CalculateNewCredits(int getCreds, int costCreds, Terminal frompatch)
		{
			int num = (frompatch.groupCredits = getCreds - costCreds);
			NetHandler.Instance.SyncCreditsServerRpc(num, frompatch.numberOfItemsInDropship);
			return num;
		}

		private static string GetVitalsInfo(PlayerControllerB playerInfo)
		{
			int health = playerInfo.health;
			float carryWeight = playerInfo.carryWeight;
			float insanityLevel = playerInfo.insanityLevel;
			bool flag = playerInfo.ItemSlots.Any((GrabbableObject item) => item is FlashlightItem);
			float num = Mathf.RoundToInt(Mathf.Clamp(carryWeight - 1f, 0f, 100f) * 105f);
			string text = $"{playerInfo.playerUsername} Vitals:\n\n Health: {health}\n Weight: {num}\n Sanity: {insanityLevel}";
			if (flag)
			{
				float num2 = Mathf.RoundToInt(playerInfo.pocketedFlashlight.insertedBattery.charge * 100f);
				text += $"\n Flashlight Battery Percentage: {num2}%";
			}
			return text;
		}

		private static string GetCreditsInfo(int newCreds)
		{
			return $"Your new balance is ■{newCreds} Credits.\r\n";
		}
	}
	internal class DynamicCommands
	{
		internal static bool newParsedValue;

		internal static bool validFovNum;

		internal static bool fovEnum;

		public static int ParsedValue { get; internal set; }

		public static string Linktext { get; internal set; }

		internal static string BindKeyToCommand()
		{
			string[] words = StringStuff.GetWords();
			ShortcutBindings.BindToCommand(words, words.Length, out var displayText);
			return displayText;
		}

		internal static string UnBindKeyToCommand()
		{
			string[] words = StringStuff.GetWords();
			ShortcutBindings.UnbindKey(words, words.Length, out var displayText);
			return displayText;
		}

		internal static string FovPrompt()
		{
			if (!Plugin.instance.FovAdjust)
			{
				validFovNum = false;
				string result = "Unable to change your fov at this time...\r\n\tRequired mod [FOVAdjust] is not loaded!\r\n\r\n";
				Plugin.WARNING("not enough words for the fov command!");
				return result;
			}
			string afterKeyword = StringStuff.GetAfterKeyword(StringStuff.GetKeywordsPerConfigItem(ConfigSettings.FovKeywords.Value));
			if (afterKeyword.Length < 1)
			{
				validFovNum = false;
				string result2 = "Unable to change your fov at this time...\r\n\tInvalid input detected, no digits were provided!\r\n\r\n";
				Plugin.WARNING("not enough words for the fov command!");
				return result2;
			}
			if (int.TryParse(afterKeyword, out var result3))
			{
				newParsedValue = true;
				validFovNum = true;
				Plugin.Spam("))))))))))))))))))Integer Established");
				ParsedValue = result3;
				return $"Set your FOV to {ParsedValue}?\n\n\n\n\n\n\n\n\n\n\n\nPlease CONFIRM or DENY.\n";
			}
			validFovNum = false;
			string result4 = "Unable to change your fov at this time...\r\n\tInvalid input detected!\n\tInput: " + afterKeyword + "\r\n\r\n";
			Plugin.WARNING("there are no digits for the fov command!");
			return result4;
		}

		internal static string FovConfirm()
		{
			if (validFovNum)
			{
				Plugin.MoreLogs("Valid fov value detected, returning fov command action");
				FovNodeText(out var displayText);
				return displayText;
			}
			Plugin.MoreLogs("attempting to confirm invalid fov. Returning error");
			return Plugin.instance.Terminal.terminalNodes.specialNodes[5].displayText;
		}

		internal static string FovDeny()
		{
			if (validFovNum)
			{
				Plugin.MoreLogs("Valid fov value detected, but fov has been canceled");
				return $"Fov change to {ParsedValue} has been canceled.\r\n\r\n\r\n";
			}
			Plugin.MoreLogs("attempting to confirm invalid fov. Returning error");
			return Plugin.instance.Terminal.terminalNodes.specialNodes[5].displayText;
		}

		private static void FovNodeText(out string displayText)
		{
			TerminalNode currentNode = Plugin.instance.Terminal.currentNode;
			if (!Plugin.instance.FovAdjust)
			{
				displayText = "FovAdjust mod is not installed, command can not be run.\r\n";
				return;
			}
			int parsedValue = ParsedValue;
			float num = parsedValue;
			if (num != 0f && num >= 66f && num <= 130f && newParsedValue)
			{
				currentNode.clearPreviousText = true;
				displayText = "Setting FOV to - " + parsedValue + "\n\n";
				((MonoBehaviour)Plugin.instance.Terminal).StartCoroutine(FovEnum(Plugin.instance.Terminal, num));
			}
			else
			{
				displayText = "Fov can only be set between 66 and 130\n";
			}
		}

		private static IEnumerator FovEnum(Terminal term, float number)
		{
			if (!fovEnum)
			{
				fovEnum = true;
				yield return (object)new WaitForSeconds(0.5f);
				FovAdjustStuff.FovAdjustFunc(term, number);
				fovEnum = false;
			}
		}
	}
	internal class BMX_LobbyCompat
	{
		public static void SetCompat(bool isNetworked)
		{
			Version version = Assembly.GetExecutingAssembly().GetName().Version;
			if (isNetworked)
			{
				PluginHelper.RegisterPlugin("darmuh.TerminalStuff", version, (CompatibilityLevel)2, (VersionStrictness)3);
			}
			else
			{
				PluginHelper.RegisterPlugin("darmuh.TerminalStuff", version, (CompatibilityLevel)0, (VersionStrictness)3);
			}
		}
	}
	internal class FovAdjustStuff
	{
		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void FovAdjustFunc(Terminal instance, float number)
		{
			instance.QuitTerminal(true);
			number = Mathf.Clamp(number, 66f, 130f);
			PlayerControllerBPatches.newTargetFovBase = number;
			PlayerControllerBPatches.calculateVisorStuff();
			DynamicCommands.newParsedValue = false;
		}
	}
	internal class GambaCommands
	{
		internal static bool validGambleValue;

		internal static string Ask2Gamble()
		{
			Plugin.MoreLogs("Ask2Gamble");
			string afterKeyword = StringStuff.GetAfterKeyword(StringStuff.GetKeywordsPerConfigItem(ConfigSettings.GambleKeywords.Value));
			if (afterKeyword.Length < 1)
			{
				TerminalGeneral.CancelConfirmation = true;
				validGambleValue = false;
				string result = "Unable to gamble at this time...\r\n\tInvalid input detected, no digits were provided!\r\n\r\n";
				Plugin.WARNING("not enough words for the gamble command!");
				return result;
			}
			if (int.TryParse(afterKeyword, out var result2))
			{
				if (result2 < 0 || result2 > 100)
				{
					return BadInputGamble(afterKeyword);
				}
				DynamicCommands.newParsedValue = true;
				validGambleValue = true;
				Plugin.MoreLogs("))))))))))))))))))Integer Established");
				DynamicCommands.ParsedValue = result2;
				return $"Gamble {DynamicCommands.ParsedValue}% of your credits?\n\n\n\n\n\n\n\n\n\n\n\nPlease CONFIRM or DENY.\n";
			}
			return BadInputGamble(afterKeyword);
		}

		internal static string BadInputGamble(string val)
		{
			TerminalGeneral.CancelConfirmation = true;
			validGambleValue = false;
			string result = "Unable to gamble at this time...\r\n\tInvalid input detected!\r\n\tInput: " + val + "\r\n\r\n";
			Plugin.WARNING("there are no digits for the gamble command!");
			return result;
		}

		internal static string GambleConfirm()
		{
			if (validGambleValue)
			{
				Plugin.MoreLogs("Valid gamble value detected, returning gamble command action");
				BasicGambleCommand(out var displayText);
				return displayText;
			}
			Plugin.MoreLogs("attempting to confirm invalid gamble. Returning error");
			return Plugin.instance.Terminal.terminalNodes.specialNodes[5].displayText;
		}

		internal static string GambleDeny()
		{
			if (validGambleValue)
			{
				Plugin.MoreLogs("Valid gamble value detected, but gamble has been canceled");
				return $"Gamble for {DynamicCommands.ParsedValue}% of your credits has been canceled.\r\n\r\n\r\n";
			}
			Plugin.MoreLogs("attempting to confirm invalid gamble. Returning error");
			return Plugin.instance.Terminal.terminalNodes.specialNodes[5].displayText;
		}

		internal static void BasicGambleCommand(out string displayText)
		{
			float num = DynamicCommands.ParsedValue;
			if (!DynamicCommands.newParsedValue || num < 0f || num > 100f)
			{
				Plugin.MoreLogs("Invalid percentage value. Telling user.");
				displayText = "Invalid gamble percentage, please input a value between 0 and 100.\n\n";
				return;
			}
			if (Plugin.instance.Terminal.groupCredits <= ConfigSettings.GambleMinimum.Value)
			{
				Plugin.MoreLogs("Invalid percentage value. Telling user.");
				displayText = ConfigSettings.GamblePoorString.Value + "\n\n";
				return;
			}
			(int, string) tuple = Gamble(Plugin.instance.Terminal.groupCredits, num);
			Plugin.instance.Terminal.groupCredits = tuple.Item1;
			NetHandler.Instance.SyncCreditsServerRpc(tuple.Item1, Plugin.instance.Terminal.numberOfItemsInDropship);
			DynamicCommands.newParsedValue = false;
			displayText = tuple.Item2;
		}

		private static (int newGroupCredits, string displayText) Gamble(int currentGroupCredits, float percentage)
		{
			percentage = Mathf.Clamp(percentage, 0f, 100f);
			int num = (int)((float)currentGroupCredits * (percentage / 100f));
			float value = Random.value;
			float value2 = Random.value;
			if (value < value2)
			{
				string item = $"Congratulations! You won ■{num} credits!\r\n\r\nYour new balance is ■{currentGroupCredits + num} Credits.\r\n";
				return (currentGroupCredits + num, item);
			}
			int num2 = currentGroupCredits - num;
			if (ConfigSettings.GamblePityMode.Value && num2 == 0)
			{
				if (ConfigSettings.GamblePityCredits.Value <= 60)
				{
					string item2 = $"Sorry, you lost ■{num} credits.\n\nHowever, you've received {ConfigSettings.GamblePityCredits.Value} Pity Credits.\r\n\r\nYour new balance is ■{ConfigSettings.GamblePityCredits.Value} Credits.\r\n";
					return (ConfigSettings.GamblePityCredits.Value, item2);
				}
				string item3 = $"Sorry, you lost ■{num} credits.\n\nUnfortunately we're also fresh out of Pity Credits due to malicious actors.\r\n\r\nYour new balance is ■{num2} Credits.\r\n";
				return (currentGroupCredits - num, item3);
			}
			string item4 = $"Sorry, you lost ■{num} credits.\r\n\r\nYour new balance is ■{num2} Credits.\r\n";
			return (currentGroupCredits - num, item4);
		}
	}
	internal class BoolStuff
	{
		internal static bool ListenForShortCuts()
		{
			if (Plugin.instance.suitsTerminal && SuitsTerminalCompatibility.CheckForSuitsMenu())
			{
				return false;
			}
			if (!Plugin.instance.Terminal.terminalInUse)
			{
				return false;
			}
			return true;
		}

		internal static void ResetEnumBools()
		{
			TerminalStart.delayStartEnum = false;
			AlwaysOnStuff.dynamicStatus = false;
			TerminalQuit.videoQuitEnum = false;
			TerminalEvents.quitTerminalEnum = false;
			ShipControls.leverEnum = false;
			DynamicCommands.fovEnum = false;
			ShortcutBindings.shortcutListenEnum = false;
			TerminalClockStuff.terminalClockEnum = false;
			NetHandler.rainbowFlashEnum = false;
			AdminCommands.kickEnum = false;
			WalkieTerm.walkieEnum = false;
			StartofHandling.textUpdater = false;
		}

		internal static bool ShouldAddCamsLogic()
		{
			if (ConfigSettings.TerminalCams.Value)
			{
				return true;
			}
			if (ConfigSettings.TerminalMap.Value)
			{
				return true;
			}
			if (ConfigSettings.TerminalMinicams.Value)
			{
				return true;
			}
			if (ConfigSettings.TerminalMinimap.Value)
			{
				return true;
			}
			if (ConfigSettings.TerminalOverlay.Value)
			{
				return true;
			}
			return false;
		}

		internal static bool ShouldEnableImage()
		{
			if (Plugin.instance.suitsTerminal && SuitsTerminalCompatibility.CheckForSuitsMenu())
			{
				SplitViewChecks.ResetPluginInstanceBools();
				SplitViewChecks.DisableSplitView("neither");
				return false;
			}
			if (ViewCommands.AnyActiveMonitoring())
			{
				return true;
			}
			if (Plugin.instance.isOnMirror)
			{
				return true;
			}
			if (!Plugin.instance.splitViewCreated && Object.op_Implicit((Object)(object)Plugin.instance.Terminal.displayingPersistentImage))
			{
				return true;
			}
			return false;
		}
	}
	internal class Misc
	{
		internal static PlayerControllerB GetPlayerFromName(string playerName)
		{
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (val.playerUsername.ToLower() == playerName.ToLower())
				{
					return val;
				}
			}
			return null;
		}

		internal static PlayerControllerB GetPlayerUsingTerminal()
		{
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (!val.isPlayerDead && (Object)(object)val.currentTriggerInAnimationWith == (Object)(object)Plugin.instance.Terminal.terminalTrigger)
				{
					Plugin.MoreLogs("Player: " + val.playerUsername + " detected using terminal.");
					return val;
				}
			}
			return null;
		}

		internal static int HostClientID()
		{
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (val.isHostPlayerObject)
				{
					Plugin.MoreLogs($"Player: {val.playerUsername} is the host, client ID: {val.playerClientId}.");
					return (int)val.playerClientId;
				}
			}
			return -1;
		}
	}
	internal class StringStuff
	{
		internal static string[] GetWords()
		{
			string text = Plugin.instance.Terminal.screenText.text.Substring(Plugin.instance.Terminal.screenText.text.Length - Plugin.instance.Terminal.textAdded);
			return text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
		}

		internal static string GetAfterKeyword(List<string> keywords)
		{
			string text = Plugin.instance.Terminal.screenText.text.Substring(Plugin.instance.Terminal.screenText.text.Length - Plugin.instance.Terminal.textAdded);
			foreach (string keyword in keywords)
			{
				if (text.StartsWith(keyword, ignoreCase: true, null))
				{
					return text.Replace(keyword, "");
				}
			}
			return "";
		}

		internal static List<string> GetKeywordsPerConfigItem(string configItem)
		{
			List<string> result = new List<string>();
			if (configItem.Length > 0)
			{
				result = (from item in configItem.Split(new char[1] { ';' })
					select item.TrimStart(Array.Empty<char>())).ToList();
			}
			return result;
		}

		internal static List<int> GetNumberListFromStringList(List<string> stringList)
		{
			List<int> list = new List<int>();
			foreach (string @string in stringList)
			{
				if (int.TryParse(@string, out var result))
				{
					list.Add(result);
				}
				else
				{
					Plugin.WARNING("Could not parse " + @string + " to integer");
				}
			}
			return list;
		}

		internal static List<string> GetItemList(string rawList)
		{
			List<string> result = new List<string>();
			if (rawList.Length > 0)
			{
				result = (from item in rawList.Split(new char[1] { ',' })
					select item.TrimStart(Array.Empty<char>())).ToList();
			}
			return result;
		}

		internal static Dictionary<string, string> GetKeywordAndItemNames(string configItem)
		{
			Dictionary<string, string> result = new Dictionary<string, string>();
			if (configItem.Length > 0)
			{
				result = (from item in configItem.Split(new char[1] { ';' })
					select item.Trim() into item
					select item.Split(new char[1] { ':' })).ToDictionary((string[] pair) => pair[0].Trim(), (string[] pair) => pair[1].Trim());
			}
			return result;
		}

		internal static List<string> GetListToLower(List<string> stringList)
		{
			List<string> list = new List<string>();
			foreach (string @string in stringList)
			{
				list.Add(@string.ToLower());
			}
			return list;
		}
	}
	internal class AutoComplete
	{
		internal static int AutoCompleteIndex = -1;

		internal static List<string> AutoCompleteResults = new List<string>();

		internal static List<string> GetMatchingKeywords(string input)
		{
			List<string> list = new List<string>();
			list.Add(input);
			Plugin.Spam("added " + input + " to automcomplete list");
			TerminalKeyword[] allKeywords = Plugin.instance.Terminal.terminalNodes.allKeywords;
			foreach (TerminalKeyword val in allKeywords)
			{
				if (val.word.ToLower().Contains(input))
				{
					list.Add(val.word);
					Plugin.Spam("adding matching word: " + val.word + " to autocomplete list");
				}
			}
			return list;
		}

		internal static bool CheckCurrentInput(List<string> matchList, string input)
		{
			if (!matchList.Contains(input))
			{
				AutoCompleteIndex = -1;
				return false;
			}
			return true;
		}

		internal static string ShowMatchingKeywords(List<string> matchList, ref int currentIndex)
		{
			Plugin.Spam($"Matching Words: {matchList.Count}");
			if (matchList.Count < 1)
			{
				Plugin.Spam("matchList count is 0");
				currentIndex = 0;
				return string.Empty;
			}
			if (matchList.Count > ConfigSettings.TerminalAutoCompleteMaxCount.Value)
			{
				Plugin.Spam("matchList count is too high");
				currentIndex = -1;
				return matchList[0].ToString();
			}
			if (currentIndex == -1)
			{
				currentIndex = 1;
			}
			if (currentIndex > matchList.Count - 1)
			{
				Plugin.Spam("setting autocompleteindex to 0");
				currentIndex = -1;
				return matchList[0].ToString();
			}
			string result = matchList[currentIndex].ToString();
			currentIndex++;
			return result;
		}
	}
	internal class TerminalHistory
	{
		internal static List<string> CommandHistory = new List<string>();

		internal static int historyIndex = 0;

		internal static void AddToCommandHistory(string command)
		{
			if (ConfigSettings.TerminalHistory.Value)
			{
				if (CommandHistory.Count < ConfigSettings.TerminalHistoryMaxCount.Value)
				{
					CommandHistory.Add(command);
				}
				else
				{
					CommandHistory.RemoveAt(0);
					CommandHistory.Add(command);
				}
				Plugin.Spam("Added " + command + " to CommandHistory List");
			}
		}

		internal static int PreviousIndex()
		{
			if (CommandHistory.Count < 1)
			{
				Plugin.Spam("CommandHistory.Count < 1");
				historyIndex = 0;
				return historyIndex;
			}
			if (historyIndex == 0)
			{
				historyIndex = CommandHistory.Count - 1;
			}
			else
			{
				historyIndex--;
			}
			return historyIndex;
		}

		internal static int NextIndex()
		{
			if (CommandHistory.Count < 1)
			{
				Plugin.Spam("CommandHistory.Count < 1");
				historyIndex = 0;
				return historyIndex;
			}
			if (historyIndex == CommandHistory.Count - 1)
			{
				historyIndex = 0;
			}
			else
			{
				historyIndex++;
			}
			return historyIndex;
		}

		internal static string GetFromCommandHistory(ref int currentIndex)
		{
			string empty = string.Empty;
			if (CommandHistory.Count < 1)
			{
				return empty;
			}
			if (CommandHistory.Count > currentIndex)
			{
				empty = CommandHistory[currentIndex];
			}
			else
			{
				empty = CommandHistory[0];
				currentIndex = 0;
			}
			return empty;
		}
	}
	internal class throwawaycode
	{
	}
	internal class AlwaysOnStuff
	{
		internal static bool dynamicStatus;

		internal static bool delayOff;

		internal static ScreenSettings screenSettings;

		internal static void IsPlayerDead()
		{
			if (StartOfRound.Instance.localPlayerController.isPlayerDead && DisableScreenOnDeath() && ((Component)Plugin.instance.Terminal.terminalUIScreen).gameObject.activeSelf)
			{
				((Component)Plugin.instance.Terminal.terminalUIScreen).gameObject.SetActive(false);
			}
		}

		internal static void OnSpecateShipCheck()
		{
			if (!DisableScreenOnDeath() && screenSettings.Dynamic)
			{
				Plugin.Spam($"Spectated Player detected in ship [ {StartOfRound.Instance.localPlayerController.spectatedPlayerScript.isInHangarShipRoom} ]");
				if (screenSettings.inUse && !((Component)Plugin.instance.Terminal.terminalUIScreen).gameObject.activeSelf && !((Component)Plugin.instance.Terminal.terminalUIScreen).gameObject.activeSelf && StartOfRound.Instance.localPlayerController.spectatedPlayerScript.isInHangarShipRoom && Plugin.instance.Terminal.placeableObject.inUse)
				{
					((Component)Plugin.instance.Terminal.terminalUIScreen).gameObject.SetActive(true);
				}
				if (!((Component)Plugin.instance.Terminal.terminalUIScreen).gameObject.activeSelf && StartOfRound.Instance.localPlayerController.spectatedPlayerScript.isInHangarShipRoom)
				{
					((Component)Plugin.instance.Terminal.terminalUIScreen).gameObject.SetActive(true);
				}
				else if (((Component)Plugin.instance.Terminal.terminalUIScreen).gameObject.activeSelf && !StartOfRound.Instance.localPlayerController.spectatedPlayerScript.isInHangarShipRoom)
				{
					((Component)Plugin.instance.Terminal.terminalUIScreen).gameObject.SetActive(false);
				}
			}
		}

		internal static void PlayerShipChanged()
		{
			if ((Object)(object)StartOfRound.Instance.localPlayerController == (Object)null || screenSettings == null)
			{
				return;
			}
			Plugin.Spam($"Player detected in ship change - {StartOfRound.Instance.localPlayerController.isInHangarShipRoom}");
			if (StartOfRound.Instance.localPlayerController.isPlayerDead && DisableScreenOnDeath() && ((Component)Plugin.instance.Terminal.terminalUIScreen).gameObject.activeSelf)
			{
				((Component)Plugin.instance.Terminal.terminalUIScreen).gameObject.SetActive(false);
			}
			if (StartOfRound.Instance.localPlayerController.isInHangarShipRoom)
			{
				if (screenSettings.Dynamic && !screenSettings.inUse)
				{
					if (!((Component)Plugin.instance.Terminal.terminalUIScreen).gameObject.activeSelf)
					{
						((Component)Plugin.instance.Terminal.terminalUIScreen).gameObject.SetActive(true);
					}
				}
				else if (screenSettings.inUse && TerminalUpdatePatch.inUse && !((Component)Plugin.instance.Terminal.terminalUIScreen).gameObject.activeSelf)
				{
					((Component)Plugin.instance.Terminal.terminalUIScreen).gameObject.SetActive(true);
				}
			}
			else
			{
				if (!screenSettings.Dynamic)
				{
					return;
				}
				Plugin.Spam($"disabling screen - screenSetting Dynamic {screenSettings.Dynamic}");
				if (((Component)Plugin.instance.Terminal.terminalUIScreen).gameObject.activeSelf)
				{
					if (ConfigSettings.ScreenOffDelay.Value < 1)
					{
						((Component)Plugin.instance.Terminal.terminalUIScreen).gameObject.SetActive(false);
					}
					else
					{
						((MonoBehaviour)Plugin.instance).StartCoroutine(DelayScreenOff(ConfigSettings.ScreenOffDelay.Value));
					}
				}
			}
		}

		internal static IEnumerator DelayScreenOff(int delay)
		{
			if (!delayOff)
			{
				delayOff = true;
				yield return (object)new WaitForSeconds((float)delay);
				if (!StartOfRound.Instance.localPlayerController.isInHangarShipRoom)
				{
					((Component)Plugin.instance.Terminal.terminalUIScreen).gameObject.SetActive(false);
				}
				delayOff = false;
			}
		}

		internal static bool DisableScreenOnDeath()
		{
			if (ConfigSettings.ScreenOnWhileDead.Value)
			{
				return false;
			}
			return StartOfRound.Instance.localPlayerController.isPlayerDead;
		}
	}
	internal class ScreenSettings
	{
		internal bool AlwaysOn;

		internal bool Dynamic;

		internal bool inUse;

		internal void Update(string setting)
		{
			if (setting.ToLower() == "alwayson")
			{
				AlwaysOn = true;
				Dynamic = false;
				inUse = false;
			}
			else if (setting.ToLower() == "inship")
			{
				AlwaysOn = true;
				Dynamic = true;
				inUse = false;
			}
			else if (setting.ToLower() == "inuse")
			{
				AlwaysOn = true;
				Dynamic = true;
				inUse = true;
			}
			else
			{
				AlwaysOn = false;
				Dynamic = false;
				inUse = false;
			}
			Plugin.Spam("ScreenSettings set to: " + setting);
		}

		internal ScreenSettings(string setting)
		{
			Update(setting);
		}
	}
	internal class PlayerCamsCompatibility
	{
		internal static Texture PlayerCamTexture()
		{
			Plugin.MoreLogs("Setting camstexture to monitor, both Solo's body cam and Rick Arg's Helmet cam use the same texture");
			return ((Renderer)GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/Cube.001").GetComponent<MeshRenderer>()).materials[2].mainTexture;
		}
	}
	internal class MenuBuild
	{
		internal static List<TerminalMenuCategory> myMenuCategories = new List<TerminalMenuCategory>();

		internal static List<TerminalMenuItem> myMenuItems = new List<TerminalMenuItem>();

		internal static TerminalMenu myMenu;

		internal static void CategoryList()
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			myMenuItems.Clear();
			myMenuItems = MenuBuild.TerminalMenuItems(ConfigSetup.defaultManaged);
			AddMenuItems(ConfigSettings.TerminalStuffBools, myMenuItems);
			if (MenuBuild.ShouldAddCategoryNameToMainMenu(myMenuItems, "COMFORT"))
			{
				dictionary.Add("COMFORT", "Improves the terminal user experience.");
			}
			if (MenuBuild.ShouldAddCategoryNameToMainMenu(myMenuItems, "EXTRAS"))
			{
				dictionary.Add("EXTRAS", "Adds extra functionality to the ship terminal.");
			}
			if (MenuBuild.ShouldAddCategoryNameToMainMenu(myMenuItems, "CONTROLS"))
			{
				dictionary.Add("CONTROLS", "Gives terminal more control of the ship's systems.");
			}
			if (MenuBuild.ShouldAddCategoryNameToMainMenu(myMenuItems, "FUN"))
			{
				dictionary.Add("FUN", "Type \"fun\" for a list of these [FUN]ctional commands.");
			}
			if (dictionary.Count == 0)
			{
				Plugin.WARNING("No enabled commands? ending menu creation");
			}
			myMenuCategories = MenuBuild.InitCategories(dictionary);
			CreateDarmuhsTerminalStuffMenus();
		}

		internal static void CreateDarmuhsTerminalStuffMenus()
		{
			Plugin.Spam("START CreateDarmuhsTerminalStuffMenus");
			if (!ConfigSettings.CreateMoreMenus.Value)
			{
				TerminalKeyword val = default(TerminalKeyword);
				if (!DynamicBools.TryGetKeyword("other", ref val))
				{
					return;
				}
				{
					foreach (TerminalMenuItem myMenuItem in myMenuItems)
					{
						if (myMenuItem.itemKeywords.Count == 0)
						{
							Plugin.WARNING(myMenuItem.ItemName + " has no keywords!!");
							continue;
						}
						if (myMenuItem == null)
						{
							Plugin.WARNING("NULL ITEM IN myMenuItems!!!");
							continue;
						}
						AddingThings.AddToExistingNodeText("\n>" + CommonStringStuff.GetKeywordsForMenuItem(myMenuItem.itemKeywords).ToUpper() + "\n" + myMenuItem.itemDescription, ref val.specialKeywordResult);
						Plugin.Spam(myMenuItem.ItemName + " keywords added to other menu");
					}
					return;
				}
			}
			myMenu = MenuBuild.AssembleMainMenu("darmuhsTerminalStuff", "more", ConfigSettings.MoreMenuText.Value, myMenuCategories, myMenuItems, false, "");
			AddingThings.AddToHelpCommand(ConfigSettings.MoreHintText.Value);
			TerminalNode val2 = default(TerminalNode);
			if (LogicHandling.TryGetFromAllNodes("OtherCommands", ref val2))
			{
				AddingThings.AddToExistingNodeText("\n" + ConfigSettings.MoreHintText.Value, ref val2);
			}
			Plugin.Spam($"myMenu info:\nMenuName: {myMenu.MenuName}\nmyMenu.Categories.Count: {myMenu.Categories.Count}\n");
			MenuBuild.CreateCategoryCommands(myMenu, ConfigSettings.TerminalStuffMain);
			Plugin.Spam("END CreateDarmuhsTerminalStuffMenus");
			TerminalStart.InitiateTerminalStuff();
		}

		internal static void AddMenuItems(List<ManagedConfig> managedItems, TerminalMenu myMenu)
		{
			if (myMenu.menuItems.Count == 0)
			{
				return;
			}
			foreach (ManagedConfig managedItem in managedItems)
			{
				if (managedItem.menuItem != null && !myMenu.menuItems.Contains(managedItem.menuItem))
				{
					myMenu.menuItems.Add(managedItem.menuItem);
				}
			}
		}

		internal static void AddMenuItems(List<ManagedConfig> managedItems, List<TerminalMenuItem> myMenuItems)
		{
			if (myMenuItems.Count == 0)
			{
				return;
			}
			foreach (ManagedConfig managedItem in managedItems)
			{
				if (managedItem.menuItem != null && !myMenuItems.Contains(managedItem.menuItem))
				{
					myMenuItems.Add(managedItem.menuItem);
				}
			}
		}

		internal static void RefreshMyMenu()
		{
			if (myMenu != null)
			{
				myMenu.menuItems.Clear();
				myMenuItems.Clear();
				myMenuItems = MenuBuild.TerminalMenuItems(ConfigSetup.defaultManaged);
				myMenu.menuItems = myMenuItems;
				AddMenuItems(ConfigSettings.TerminalStuffBools, myMenu);
				MenuBuild.UpdateCategories(myMenu);
			}
		}

		internal static void ClearMyMenustuff()
		{
			TerminalMenu obj = myMenu;
			if (obj != null)
			{
				obj.Delete();
			}
			myMenuItems.Clear();
			myMenuCategories.Clear();
		}
	}
	internal class MoreCommands
	{
		private static Dictionary<string, PluginInfo> PluginsLoaded = new Dictionary<string, PluginInfo>();

		internal static bool keepAlwaysOnDisabled = false;

		internal static string CurrentLobbyName { get; private set; }

		internal static string GetItemsOnShip()
		{
			LoadGrabbablesOnShip.LoadAllItems();
			StringBuilder stringBuilder = new StringBuilder();
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			foreach (GrabbableObject item in LoadGrabbablesOnShip.ItemsOnShip)
			{
				string itemName = item.itemProperties.itemName;
				if (!item.itemProperties.isScrap && !item.isHeld)
				{
					dictionary[itemName] = ((!dictionary.TryGetValue(itemName, out var value)) ? 1 : (value + 1));
				}
			}
			foreach (KeyValuePair<string, int> item2 in dictionary)
			{
				if (item2.Value > 1)
				{
					stringBuilder.AppendLine($"{item2.Key} x{item2.Value}");
				}
				else
				{
					stringBuilder.AppendLine(item2.Key ?? "");
				}
			}
			return $"Items on ship:\n\n{stringBuilder}\n\n";
		}

		private static string ReturnLobbyName()
		{
			if (GameNetworkManager.Instance.steamLobbyName != null && GameNetworkManager.Instance.steamLobbyName != string.Empty)
			{
				CurrentLobbyName = GameNetworkManager.Instance.steamLobbyName;
				return "Lobby Name: " + CurrentLobbyName + "\n";
			}
			return "Unable to determine Lobby Name. \n";
		}

		internal static string GetLobbyName()
		{
			return ReturnLobbyName();
		}

		internal static string ModListCommand()
		{
			PluginsLoaded = Chainloader.PluginInfos;
			string text = string.Join("\n", PluginsLoaded.Select((KeyValuePair<string, PluginInfo> kvp) => $"{kvp.Value.Metadata.Name}, Version: {kvp.Value.Metadata.Version}"));
			return "Mod List:\n\n" + text + "\n\n";
		}

		internal static string HealCommand()
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			int health = GameNetworkManager.Instance.localPlayerController.health;
			if (health >= 100)
			{
				Plugin.MoreLogs($"Health = {health}");
				return ConfigSettings.HealIsFullString.Value + "\n";
			}
			Plugin.MoreLogs($"Health before = {health}");
			GameNetworkManager.Instance.localPlayerController.DamagePlayer(-100, false, true, (CauseOfDeath)0, 0, false, default(Vector3));
			GameNetworkManager.Instance.localPlayerController.MakeCriticallyInjured(false);
			int health2 = GameNetworkManager.Instance.localPlayerController.health;
			string result = $"{ConfigSettings.HealString.Value}\nHealth: {GameNetworkManager.Instance.localPlayerController.health}\r\n";
			Plugin.MoreLogs($"Health now = {health2}");
			return result;
		}

		internal static string DangerCommand()
		{
			if (StartOfRound.Instance.shipDoorsEnabled)
			{
				string riskLevel = StartOfRound.Instance.currentLevel.riskLevel;
				return "Current Danger Level: " + riskLevel + "\n\n";
			}
			return "Still in orbit.\n\n";
		}

		internal static string FirstLinkDo()
		{
			int linkID = 0;
			return ExternalLink(linkID);
		}

		internal static string SecondLinkDo()
		{
			int linkID = 1;
			return ExternalLink(linkID);
		}

		internal static string FirstLinkAsk()
		{
			int linkID = 0;
			return LinksAsk(linkID);
		}

		internal static string SecondLinkAsk()
		{
			int linkID = 1;
			return LinksAsk(linkID);
		}

		internal static string FirstLinkDeny()
		{
			int linkID = 0;
			return LinksDeny(linkID);
		}

		internal static string SecondLinkDeny()
		{
			int linkID = 1;
			return LinksDeny(linkID);
		}

		internal static void GetLinkText(int linkID)
		{
			if (linkID == 0)
			{
				DynamicCommands.Linktext = ConfigSettings.CustomLink.Value;
			}
			else
			{
				DynamicCommands.Linktext = ConfigSettings.CustomLink2.Value;
			}
		}

		internal static string ExternalLink(int linkID)
		{
			GetLinkText(linkID);
			string result = "Taking you to " + DynamicCommands.Linktext + " now...\n";
			Application.OpenURL(DynamicCommands.Linktext);
			((MonoBehaviour)Plugin.instance.Terminal).StartCoroutine(TerminalEvents.TerminalQuitter(Plugin.instance.Terminal));
			return result;
		}

		internal static string LinksAsk(int linkID)
		{
			GetLinkText(linkID);
			return "Would you like to be taken to the following link?\n\n\t" + DynamicCommands.Linktext + "\n\n\n\n\n\n\n\n\n\nPlease CONFIRM or DENY.\n\n";
		}

		internal static string LinksDeny(int linkID)
		{
			GetLinkText(linkID);
			return "You have cancelled visiting the site:\n\n\t" + DynamicCommands.Linktext + "\n\n";
		}

		internal static string AlwaysOnDisplay()
		{
			if (!TerminalStart.alwaysOnDisplay && ConfigSettings.NetworkedNodes.Value && ConfigSettings.ModNetworking.Value)
			{
				keepAlwaysOnDisabled = false;
				NetHandler.Instance.AoDServerRpc(aod: true);
				return "Terminal Always-on Display [ENABLED]\r\n";
			}
			if (TerminalStart.alwaysOnDisplay && ConfigSettings.NetworkedNodes.Value && ConfigSettings.ModNetworking.Value)
			{
				keepAlwaysOnDisabled = true;
				NetHandler.Instance.AoDServerRpc(aod: false);
				return "Terminal Always-on Display [DISABLED]\r\n";
			}
			if (!TerminalStart.alwaysOnDisplay && !ConfigSettings.NetworkedNodes.Value)
			{
				keepAlwaysOnDisabled = false;
				TerminalStart.alwaysOnDisplay = true;
				return "Terminal Always-on Display [ENABLED]\r\n";
			}
			if (TerminalStart.alwaysOnDisplay && !ConfigSettings.NetworkedNodes.Value)
			{
				keepAlwaysOnDisabled = true;
				TerminalStart.alwaysOnDisplay = false;
				return "Terminal Always-on Display [DISABLED]\r\n";
			}
			Plugin.Log.LogError((object)"report this as a bug with alwayson please");
			return "alwayson failed to initiate, report this as a bug please.";
		}
	}
	public class NetHandler : NetworkBehaviour
	{
		public static CustomEvent ShipReset = new CustomEvent();

		internal static Terminal patchTerminal = null;

		internal static bool netNodeSet = false;

		internal bool endFlashRainbow = false;

		internal static TerminalNode netNode = AddingThings.CreateDummyNode("", true, "");

		internal static bool rainbowFlashEnum = false;

		internal static NetHandler Instance { get; private set; }

		[ServerRpc(RequireOwnership = false)]
		internal void NodeLoadServerRpc(string topRightText, string nodeName, string nodeText, int nodeNumber = -1)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				ServerRpcParams val = default(ServerRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(3041900586u, val, (RpcDelivery)0);
				bool flag = topRightText != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(topRightText, false);
				}
				bool flag2 = nodeName != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives));
				if (flag2)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(nodeName, false);
				}
				bool flag3 = nodeText != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag3, default(ForPrimitives));
				if (flag3)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(nodeText, false);
				}
				BytePacker.WriteValueBitPacked(val2, nodeNumber);
				((NetworkBehaviour)this).__endSendServerRpc(ref val2, 3041900586u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage != 1 || (!networkManager.IsServer && !networkManager.IsHost))
			{
				return;
			}
			NetworkManager networkManager2 = ((NetworkBehaviour)this).NetworkManager;
			if (netNodeSet && (networkManager2.IsHost || networkManager2.IsServer))
			{
				Plugin.MoreLogs("RPC called from host, sending to client RPC ");
				NodeLoadClientRpc(topRightText, nodeName, nodeText, fromHost: true, nodeNumber);
				return;
			}
			if ((!netNodeSet && networkManager2.IsHost) || networkManager2.IsServer)
			{
				Plugin.MoreLogs($"Host: attempting to sync node {nodeName}/{nodeNumber}");
				SyncNodes(topRightText, nodeName, nodeText, nodeNumber);
			}
			else
			{
				Plugin.MoreLogs("Server: This should only be coming from clients");
				NodeLoadClientRpc(topRightText, nodeName, nodeText, fromHost: true, nodeNumber);
			}
			Plugin.MoreLogs("Server: Attempting to sync nodes between clients.");
		}

		[ClientRpc]
		internal void NodeLoadClientRpc(string topRightText, string nodeName, string nodeText, bool fromHost, int nodeNumber = -1)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: 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_015e: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(2216011817u, val, (RpcDelivery)0);
				bool flag = topRightText != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(topRightText, false);
				}
				bool flag2 = nodeName != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives));
				if (flag2)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(nodeName, false);
				}
				bool flag3 = nodeText != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag3, default(ForPrimitives));
				if (flag3)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(nodeText, false);
				}
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref fromHost, default(ForPrimitives));
				BytePacker.WriteValueBitPacked(val2, nodeNumber);
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2216011817u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
			{
				NetworkManager networkManager2 = ((NetworkBehaviour)this).NetworkManager;
				if (fromHost && (networkManager2.IsHost || networkManager2.IsServer))
				{
					NetNodeReset(set: false);
					Plugin.MoreLogs("Node detected coming from host, resetting nNS and ending RPC");
				}
				else if (!netNodeSet)
				{
					Plugin.MoreLogs($"Client: attempting to sync node, {nodeName}/{nodeNumber}");
					SyncNodes(topRightText, nodeName, nodeText, nodeNumber);
				}
				else
				{
					Plugin.MoreLogs("Client: netNodeSet is true, no sync required.");
					NetNodeReset(set: false);
				}
			}
		}

		internal static bool NetNodeReset(bool set)
		{
			netNodeSet = set;
			return netNodeSet;
		}

		private static void SyncViewNodeWithNum(ref TerminalNode node, int nodeNumber, string nodeText)
		{
			Plugin.MoreLogs("---------------- Loading view node triggered by another player ----------------");
			switch (nodeNumber)
			{
			case 0:
				if (ConfigSettings.VideoSync.Value)
				{
					node.displayText = nodeText;
					VideoManager.PlaySyncedVideo();
				}
				else
				{
					node.displayText = ViewCommands.LolVideoPlayerEvent();
				}
				break;
			case 1:
				node.displayText = ViewCommands.TermCamsEvent();
				break;
			case 2:
				node.displayText = ViewCommands.OverlayTermEvent();
				break;
			case 3:
				node.displayText = ViewCommands.MiniMapTermEvent();
				break;
			case 4:
				node.displayText = ViewCommands.MiniCamsTermEvent();
				break;
			case 5:
				node.displayText = ViewCommands.TermMapEvent();
				break;
			case 6:
				node.displayText = ViewCommands.MirrorEvent();
				break;
			default:
				Plugin.MoreLogs("No matching views detected");
				break;
			}
		}

		private void SyncNodes(string topRightText, string nodeName, string nodeText, int nodeNumber = -1)
		{
			TerminalNode newNode = default(TerminalNode);
			if (!LogicHandling.TryGetFromAllNodes(nodeName, ref newNode))
			{
				DefaultSync(nodeName, nodeText);
				Plugin.MoreLogs(nodeName + " not matching known nodes. Only displaying text:\n" + nodeText);
				return;
			}
			NetNodeReset(set: true);
			if (nodeNumber != -1 && nodeNumber <= ConfigSettings.TerminalStuffMain.ListNumToString.Count)
			{
				TerminalNode node = StartofHandling.FindViewNode(nodeNumber);
				if ((Object)(object)node == (Object)null)
				{
					return;
				}
				SyncViewNodeWithNum(ref node, nodeNumber, nodeText);
				Plugin.instance.Terminal.LoadNewNode(node);
				Plugin.MoreLogs($"Non terminal user: Attempting to load {nodeName}, ViewNode: {nodeNumber}\n {node.displayText}");
			}
			else
			{
				DefaultSync(nodeName, nodeText, newNode);
				Plugin.MoreLogs("Non terminal user: Attempting to load " + nodeName + "'s displayText:\n " + nodeText);
			}
			((TMP_Text)Plugin.instance.Terminal.topRightText).text = topRightText;
			NetNodeReset(set: false);
		}

		private void DefaultSync(string nodeName, string nodeText, TerminalNode newNode = null)
		{
			if ((Object)(object)newNode != (Object)null && TerminalStart.vanillaNodes.Contains(newNode))
			{
				MoreCamStuff.CamPersistance(nodeName);
				MoreCamStuff.VideoPersist(nodeName);
				Plugin.instance.Terminal.LoadNewNode(newNode);
			}
			else
			{
				MoreCamStuff.CamPersistance(nodeName);
				MoreCamStuff.VideoPersist(nodeName);
				netNode.displayText = nodeText;
				Plugin.instance.Terminal.LoadNewNode(netNode);
				Plugin.MoreLogs("Only displaying " + nodeName + " text.");
			}
		}

		[ServerRpc(RequireOwnership = false)]
		internal void SyncDropShipServerRpc(bool isRefund = false)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
				{
					ServerRpcParams val = default(ServerRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(1971978312u, val, (RpcDelivery)0);
					((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref isRefund, default(ForPrimitives));
					((NetworkBehaviour)this).__endSendServerRpc(ref val2, 1971978312u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
				{
					Plugin.MoreLogs("Server: Attempting to sync dropship between players...");
					SyncDropShipClientRpc(isRefund);
				}
			}
		}

		[ClientRpc]
		internal void SyncDropShipClientRpc(bool isRefund)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(946025536u, val, (RpcDelivery)0);
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref isRefund, default(ForPrimitives));
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 946025536u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage != 2 || (!networkManager.IsClient && !networkManager.IsHost))
			{
				return;
			}
			NetworkManager networkManager2 = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager2.IsHost || networkManager2.IsServer)
			{
				if (isRefund)
				{
					Plugin.MoreLogs("Host received refund command, clearing orderedItems list");
					Plugin.instance.Terminal.orderedItemsFromTerminal.Clear();
					CostCommands.storeCart.Clear();
				}
				else
				{
					Plugin.MoreLogs("Host syncing dropship to storeCart after purchase");
					int[] itemsOrdered = Plugin.instance.Terminal.orderedItemsFromTerminal.ToArray();
					CostCommands.storeCart = Plugin.instance.Terminal.orderedItemsFromTerminal;
					SendItemsToAllServerRpc(itemsOrdered);
				}
			}
		}

		internal static void SyncMyVideoChoiceToEveryone(string videoPlaying)
		{
			if (ConfigSettings.NetworkedNodes.Value && ConfigSettings.ModNetworking.Value && ConfigSettings.VideoSync.Value && !((Object)(object)Instance == (Object)null) && !((Object)(object)StartOfRound.Instance == (Object)null) && !((Object)(object)StartOfRound.Instance.localPlayerController == (Object)null))
			{
				Plugin.MoreLogs("Sending " + videoPlaying + " as videoPlaying to other clients with active screens");
				Instance.SyncVideoChoiceServerRpc((int)StartOfRound.Instance.localPlayerController.playerClientId, videoPlaying);
			}
		}

		[ServerRpc(RequireOwnership = false)]
		internal void SyncTwoRadarMapsServerRpc(int fromClient, int playerNum)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
				{
					ServerRpcParams val = default(ServerRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(1505932234u, val, (RpcDelivery)0);
					BytePacker.WriteValueBitPacked(val2, fromClient);
					BytePacker.WriteValueBitPacked(val2, playerNum);
					((NetworkBehaviour)this).__endSendServerRpc(ref val2, 1505932234u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
				{
					Plugin.Spam($"Server: Client ({fromClient}) attempting to sync tworadarmaps target to {playerNum}");
					SyncTwoRadarMapsClientRpc(fromClient, playerNum);
				}
			}
		}

		[ClientRpc]
		internal void SyncTwoRadarMapsClientRpc(int fromClient, int playerNum)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1495934517u, val, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val2, fromClient);
				BytePacker.WriteValueBitPacked(val2, playerNum);
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1495934517u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
			{
				if ((int)StartOfRound.Instance.localPlayerController.playerClientId == fromClient)
				{
					Plugin.Spam($"This is the client updating target to {playerNum}");
					return;
				}
				Plugin.Spam("SyncTwoRadarMapsClientRpc called from another client");
				TwoRadarMapsCompatibility.SyncTarget(playerNum);
			}
		}

		[ServerRpc(RequireOwnership = false)]
		internal void SyncVideoChoiceServerRpc(int fromClient, string videoPlaying)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or miss