Decompiled source of PersistentTerminal v1.2.2

BepInEx/plugins/PersistentTerminal.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("PersistentTerminal")]
[assembly: AssemblyConfiguration("release")]
[assembly: AssemblyDescription("Terminal remembers your last screen")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0")]
[assembly: AssemblyProduct("PersistentTerminal")]
[assembly: AssemblyTitle("PersistentTerminal")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PersistentTerminal
{
	[BepInPlugin("mrbub.persistentterminal", "PersistentTerminal", "1.2.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		public static ConfigEntry<string> TerminalTheme;

		public static ConfigEntry<string> CustomTextColor;

		public static ConfigEntry<string> CustomBackgroundColor;

		public static ConfigEntry<string> CustomScreenLightColor;

		public static ConfigEntry<bool> AlwaysOnScreen;

		public static ConfigEntry<bool> AlwaysOnLight;

		private void Awake()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			Logger = ((BaseUnityPlugin)this).Logger;
			TerminalTheme = ((BaseUnityPlugin)this).Config.Bind<string>("Theme", "Preset", "Default", new ConfigDescription("Terminal color theme preset.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[7] { "Default", "Green", "Amber", "Blue", "Red", "Purple", "Cyan" }), Array.Empty<object>()));
			CustomTextColor = ((BaseUnityPlugin)this).Config.Bind<string>("Custom Colors", "TextColor", "", "Custom text color in RGB format (0-255). Overrides the theme preset if set.\nExample: 0,255,0 for green\nLeave empty to use theme preset.");
			CustomBackgroundColor = ((BaseUnityPlugin)this).Config.Bind<string>("Custom Colors", "BackgroundColor", "", "Custom background color in RGB format (0-255). Overrides the theme preset if set.\nExample: 0,20,0 for dark green\nLeave empty to use theme preset.");
			CustomScreenLightColor = ((BaseUnityPlugin)this).Config.Bind<string>("Custom Colors", "ScreenLightColor", "", "Custom screen light color in RGB format (0-255). Overrides the theme preset if set.\nExample: 0,255,0 for green\nLeave empty to use theme preset.");
			AlwaysOnScreen = ((BaseUnityPlugin)this).Config.Bind<bool>("Behavior", "AlwaysOnScreen", false, "Keep the terminal screen always on, even when not in use.");
			AlwaysOnLight = ((BaseUnityPlugin)this).Config.Bind<bool>("Behavior", "AlwaysOnLight", false, "Keep the terminal light always on.");
			new Harmony("mrbub.persistentterminal").PatchAll();
			Logger.LogInfo((object)"PersistentTerminal v1.2.0 loaded!");
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "mrbub.persistentterminal";

		public const string PLUGIN_NAME = "PersistentTerminal";

		public const string PLUGIN_VERSION = "1.2.0";
	}
}
namespace PersistentTerminal.Patches
{
	[HarmonyPatch(typeof(Terminal))]
	internal class TerminalPatches
	{
		private static TerminalNode lastNode = null;

		private static string lastScreenText = "";

		private static int lastTextPosition = 0;

		private static int lastSaveFileNum = -1;

		private static bool isRestoring = false;

		private static bool hasRestoredThisSession = false;

		private static bool skipSoundPlayback = false;

		private static List<string> commandHistory = new List<string>();

		private static int historyIndex = -1;

		private static string currentInput = "";

		private static string savedInput = "";

		private static bool themeApplied = false;

		private static Light terminalLight = null;

		private static Image terminalBackground = null;

		[HarmonyPatch("BeginUsingTerminal")]
		[HarmonyPrefix]
		private static void BeginUsingTerminalPrefix(Terminal __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)GameNetworkManager.Instance == (Object)null) && !hasRestoredThisSession)
			{
				int saveFileNum = GameNetworkManager.Instance.saveFileNum;
				if (saveFileNum != lastSaveFileNum)
				{
					ClearSavedState();
					lastSaveFileNum = saveFileNum;
				}
				else if ((Object)(object)lastNode != (Object)null && !string.IsNullOrEmpty(lastScreenText))
				{
					isRestoring = true;
				}
			}
		}

		[HarmonyPatch("BeginUsingTerminal")]
		[HarmonyPostfix]
		private static void BeginUsingTerminalPostfix(Terminal __instance)
		{
			if (!themeApplied)
			{
				ApplyTheme(__instance);
				themeApplied = true;
			}
			if (!isRestoring)
			{
				if (!string.IsNullOrEmpty(savedInput) && (Object)(object)__instance.screenText != (Object)null)
				{
					Plugin.Logger.LogInfo((object)("[INPUT] Restoring saved input: '" + savedInput + "'"));
					TMP_InputField screenText = __instance.screenText;
					screenText.text += savedInput;
					__instance.textAdded = savedInput.Length;
					__instance.currentText = __instance.screenText.text;
					Plugin.Logger.LogInfo((object)$"[INPUT] Input restored, textAdded: {__instance.textAdded}");
					savedInput = "";
				}
				return;
			}
			try
			{
				if (!((Object)(object)lastNode == (Object)null))
				{
					Plugin.Logger.LogInfo((object)("[RESTORE] Starting restoration of node: " + ((Object)lastNode).name));
					skipSoundPlayback = true;
					__instance.LoadNewNode(lastNode);
					skipSoundPlayback = false;
					if (lastTextPosition > 0 && (Object)(object)__instance.screenText != (Object)null)
					{
						__instance.textAdded = lastTextPosition;
						Plugin.Logger.LogInfo((object)$"[RESTORE] Restored scroll position: {lastTextPosition}");
					}
					if (!string.IsNullOrEmpty(savedInput) && (Object)(object)__instance.screenText != (Object)null)
					{
						Plugin.Logger.LogInfo((object)("[INPUT] Restoring saved input after node restore: '" + savedInput + "'"));
						TMP_InputField screenText2 = __instance.screenText;
						screenText2.text += savedInput;
						__instance.textAdded = savedInput.Length;
						__instance.currentText = __instance.screenText.text;
						Plugin.Logger.LogInfo((object)$"[INPUT] Input restored, textAdded: {__instance.textAdded}");
						savedInput = "";
					}
					Plugin.Logger.LogInfo((object)("[RESTORE] Successfully restored to: " + ((Object)lastNode).name));
					hasRestoredThisSession = true;
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogError((object)("Error restoring terminal state: " + ex.Message));
				skipSoundPlayback = false;
			}
			finally
			{
				isRestoring = false;
			}
		}

		[HarmonyPatch("LoadNewNode")]
		[HarmonyPrefix]
		private static bool LoadNewNodePrefix(Terminal __instance, TerminalNode node)
		{
			if (isRestoring && (Object)(object)node != (Object)null && ((Object)node).name == "Start")
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch("LoadNewNode")]
		[HarmonyPostfix]
		private static void LoadNewNodePostfix(Terminal __instance, TerminalNode node)
		{
			if (!isRestoring && !skipSoundPlayback && __instance.terminalInUse && (Object)(object)node != (Object)null && (Object)(object)__instance.currentNode == (Object)(object)node)
			{
				lastNode = node;
				if ((Object)(object)__instance.screenText != (Object)null)
				{
					lastScreenText = __instance.screenText.text;
					lastTextPosition = __instance.textAdded;
				}
			}
		}

		[HarmonyPatch("PlayTerminalAudioServerRpc")]
		[HarmonyPrefix]
		private static bool PlayTerminalAudioServerRpcPrefix(int clipIndex)
		{
			if (skipSoundPlayback)
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void UpdatePostfix(Terminal __instance)
		{
			if (!__instance.terminalInUse || (Object)(object)__instance.screenText == (Object)null)
			{
				return;
			}
			Keyboard current = Keyboard.current;
			if (current == null)
			{
				return;
			}
			if (((ButtonControl)current.upArrowKey).wasPressedThisFrame && commandHistory.Count > 0)
			{
				if (historyIndex == -1)
				{
					currentInput = GetCurrentInput(__instance);
					Plugin.Logger.LogInfo((object)("[HISTORY] Saved current input: '" + currentInput + "'"));
				}
				if (historyIndex < commandHistory.Count - 1)
				{
					historyIndex++;
					string text = commandHistory[commandHistory.Count - 1 - historyIndex];
					Plugin.Logger.LogInfo((object)$"[HISTORY] Up arrow - showing command {historyIndex + 1}/{commandHistory.Count}: '{text}'");
					SetCurrentInput(__instance, text);
				}
				else
				{
					Plugin.Logger.LogInfo((object)"[HISTORY] Already at oldest command");
				}
			}
			else if (((ButtonControl)current.downArrowKey).wasPressedThisFrame && commandHistory.Count > 0)
			{
				if (historyIndex > 0)
				{
					historyIndex--;
					string text2 = commandHistory[commandHistory.Count - 1 - historyIndex];
					Plugin.Logger.LogInfo((object)$"[HISTORY] Down arrow - showing command {historyIndex + 1}/{commandHistory.Count}: '{text2}'");
					SetCurrentInput(__instance, text2);
				}
				else if (historyIndex == 0)
				{
					Plugin.Logger.LogInfo((object)("[HISTORY] Down arrow - restoring current input: '" + currentInput + "'"));
					historyIndex = -1;
					SetCurrentInput(__instance, currentInput);
				}
				else
				{
					Plugin.Logger.LogInfo((object)"[HISTORY] Already at newest input");
				}
			}
		}

		[HarmonyPatch("OnSubmit")]
		[HarmonyPrefix]
		private static void OnSubmitPrefix(Terminal __instance)
		{
			if ((Object)(object)__instance.screenText == (Object)null || __instance.textAdded <= 0)
			{
				return;
			}
			string text = GetCurrentInput(__instance);
			if (!string.IsNullOrWhiteSpace(text))
			{
				if (commandHistory.Count == 0 || commandHistory[commandHistory.Count - 1] != text)
				{
					commandHistory.Add(text);
					Plugin.Logger.LogInfo((object)$"[HISTORY] Added command to history: '{text}' (total: {commandHistory.Count})");
					if (commandHistory.Count > 50)
					{
						string text2 = commandHistory[0];
						commandHistory.RemoveAt(0);
						Plugin.Logger.LogInfo((object)("[HISTORY] Removed oldest command: '" + text2 + "'"));
					}
				}
				else
				{
					Plugin.Logger.LogInfo((object)("[HISTORY] Skipped duplicate command: '" + text + "'"));
				}
			}
			historyIndex = -1;
			currentInput = "";
		}

		private static string GetCurrentInput(Terminal terminal)
		{
			if ((Object)(object)terminal.screenText == (Object)null || terminal.textAdded <= 0)
			{
				return "";
			}
			int num = terminal.screenText.text.Length - terminal.textAdded;
			if (num < 0 || num >= terminal.screenText.text.Length)
			{
				return "";
			}
			return terminal.screenText.text.Substring(num);
		}

		private static void SetCurrentInput(Terminal terminal, string input)
		{
			if (!((Object)(object)terminal.screenText == (Object)null))
			{
				if (terminal.textAdded > 0)
				{
					terminal.screenText.text = terminal.screenText.text.Substring(0, terminal.screenText.text.Length - terminal.textAdded);
				}
				TMP_InputField screenText = terminal.screenText;
				screenText.text += input;
				terminal.textAdded = input.Length;
				terminal.currentText = terminal.screenText.text;
			}
		}

		[HarmonyPatch("QuitTerminal")]
		[HarmonyPrefix]
		private static void QuitTerminalPrefix(Terminal __instance)
		{
			if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.currentNode == (Object)null)
			{
				return;
			}
			try
			{
				lastNode = __instance.currentNode;
				if ((Object)(object)__instance.screenText != (Object)null)
				{
					lastScreenText = __instance.screenText.text;
					lastTextPosition = __instance.textAdded;
					savedInput = GetCurrentInput(__instance);
					if (!string.IsNullOrEmpty(savedInput))
					{
						Plugin.Logger.LogInfo((object)("[INPUT] Saved player input: '" + savedInput + "'"));
					}
				}
				if ((Object)(object)GameNetworkManager.Instance != (Object)null)
				{
					lastSaveFileNum = GameNetworkManager.Instance.saveFileNum;
				}
				Plugin.Logger.LogInfo((object)$"[HISTORY] Command history size: {commandHistory.Count}");
				hasRestoredThisSession = false;
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogError((object)("Error saving terminal state: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "ResetShip")]
		[HarmonyPostfix]
		private static void ResetShipPostfix()
		{
			ClearSavedState();
		}

		[HarmonyPatch(typeof(StartOfRound), "EndOfGame")]
		[HarmonyPostfix]
		private static void EndOfGamePostfix()
		{
			ClearSavedState();
		}

		[HarmonyPatch(typeof(GameNetworkManager), "Disconnect")]
		[HarmonyPostfix]
		private static void DisconnectPostfix()
		{
			Plugin.Logger.LogInfo((object)"[STATE] Disconnected - clearing terminal state");
			ClearSavedState();
		}

		private static void ClearSavedState()
		{
			Plugin.Logger.LogInfo((object)"[STATE] Clearing all saved state");
			lastNode = null;
			lastScreenText = "";
			lastTextPosition = 0;
			isRestoring = false;
			hasRestoredThisSession = false;
			skipSoundPlayback = false;
			commandHistory.Clear();
			historyIndex = -1;
			currentInput = "";
			savedInput = "";
			themeApplied = false;
			Plugin.Logger.LogInfo((object)"[STATE] State cleared");
		}

		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPostfix(Terminal __instance)
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_040a: Unknown result type (might be due to invalid IL or missing references)
			//IL_041e: Unknown result type (might be due to invalid IL or missing references)
			Plugin.Logger.LogInfo((object)"[INIT] ========== Terminal.Start - Full Object Discovery ==========");
			Plugin.Logger.LogInfo((object)("[INIT] Terminal GameObject: " + ((Object)((Component)__instance).gameObject).name));
			Plugin.Logger.LogInfo((object)("[INIT] Terminal transform: " + ((Object)((Component)__instance).transform).name));
			if ((Object)(object)__instance.terminalLight != (Object)null)
			{
				terminalLight = __instance.terminalLight;
				Plugin.Logger.LogInfo((object)$"[INIT] terminalLight: {((Object)((Component)__instance.terminalLight).gameObject).name} (enabled: {((Behaviour)__instance.terminalLight).enabled})");
				Plugin.Logger.LogInfo((object)$"[INIT] terminalLight color: R:{__instance.terminalLight.color.r} G:{__instance.terminalLight.color.g} B:{__instance.terminalLight.color.b}");
				if (Plugin.AlwaysOnLight.Value)
				{
					((Behaviour)terminalLight).enabled = true;
					Plugin.Logger.LogInfo((object)"[ALWAYS-ON] Terminal light enabled");
				}
			}
			else
			{
				Plugin.Logger.LogWarning((object)"[INIT] terminalLight is null");
			}
			if ((Object)(object)__instance.terminalUIScreen != (Object)null)
			{
				Plugin.Logger.LogInfo((object)("[INIT] terminalUIScreen: " + ((Object)__instance.terminalUIScreen).name));
				LogGameObjectHierarchy(((Component)__instance.terminalUIScreen).gameObject, 0, 3);
			}
			else
			{
				Plugin.Logger.LogWarning((object)"[INIT] terminalUIScreen is null");
			}
			if ((Object)(object)__instance.screenText != (Object)null)
			{
				Plugin.Logger.LogInfo((object)("[INIT] screenText GameObject: " + ((Object)((Component)__instance.screenText).gameObject).name));
				if ((Object)(object)__instance.screenText.textComponent != (Object)null)
				{
					Plugin.Logger.LogInfo((object)("[INIT] screenText.textComponent: " + ((object)__instance.screenText.textComponent).GetType().Name));
					Plugin.Logger.LogInfo((object)$"[INIT] screenText color: R:{((Graphic)__instance.screenText.textComponent).color.r} G:{((Graphic)__instance.screenText.textComponent).color.g} B:{((Graphic)__instance.screenText.textComponent).color.b}");
				}
			}
			else
			{
				Plugin.Logger.LogWarning((object)"[INIT] screenText is null");
			}
			Plugin.Logger.LogInfo((object)"[INIT] === Terminal GameObject Children ===");
			LogGameObjectHierarchy(((Component)__instance).gameObject, 0, 3);
			Plugin.Logger.LogInfo((object)"[INIT] === Searching for UI Image components ===");
			Image[] componentsInChildren = ((Component)__instance.terminalUIScreen).GetComponentsInChildren<Image>(true);
			Plugin.Logger.LogInfo((object)$"[INIT] Found {componentsInChildren.Length} Image components in Canvas");
			Image[] array = componentsInChildren;
			foreach (Image val in array)
			{
				Plugin.Logger.LogInfo((object)$"[INIT] Image: {((Object)((Component)val).gameObject).name} - Color: R:{((Graphic)val).color.r:F2} G:{((Graphic)val).color.g:F2} B:{((Graphic)val).color.b:F2} A:{((Graphic)val).color.a:F2}");
				if (((Object)((Component)val).gameObject).name == "MainContainer" && (Object)(object)terminalBackground == (Object)null)
				{
					terminalBackground = val;
					Plugin.Logger.LogInfo((object)"[INIT] *** Cached MainContainer as terminal background ***");
				}
			}
			Plugin.Logger.LogInfo((object)"[INIT] === Searching for Light components ===");
			Light[] componentsInChildren2 = ((Component)__instance).GetComponentsInChildren<Light>(true);
			Plugin.Logger.LogInfo((object)$"[INIT] Found {componentsInChildren2.Length} Light components in Terminal");
			Light[] array2 = componentsInChildren2;
			foreach (Light val2 in array2)
			{
				Plugin.Logger.LogInfo((object)$"[INIT] Light: {((Object)((Component)val2).gameObject).name} - Type: {val2.type} - Color: R:{val2.color.r:F2} G:{val2.color.g:F2} B:{val2.color.b:F2} - Enabled: {((Behaviour)val2).enabled}");
			}
			Plugin.Logger.LogInfo((object)"[INIT] ========== End Terminal Object Discovery ==========");
			if (Plugin.AlwaysOnScreen.Value)
			{
				Plugin.Logger.LogInfo((object)"[INIT] Always-on enabled, applying theme immediately");
				ApplyTheme(__instance);
				themeApplied = true;
			}
			if (Plugin.AlwaysOnScreen.Value && (Object)(object)__instance.terminalNodes != (Object)null && __instance.terminalNodes.specialNodes != null && __instance.terminalNodes.specialNodes.Count > 1)
			{
				Plugin.Logger.LogInfo((object)"[ALWAYS-ON] Loading store node for always-on screen");
				__instance.LoadNewNode(__instance.terminalNodes.specialNodes[1]);
			}
		}

		private static void LogGameObjectHierarchy(GameObject obj, int depth, int maxDepth)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)obj == (Object)null || depth > maxDepth)
			{
				return;
			}
			string text = new string(' ', depth * 2);
			Plugin.Logger.LogInfo((object)("[HIERARCHY] " + text + "└─ " + ((Object)obj).name));
			Component[] components = obj.GetComponents<Component>();
			foreach (Component val in components)
			{
				if ((Object)(object)val != (Object)null && !(val is Transform))
				{
					Plugin.Logger.LogInfo((object)("[HIERARCHY] " + text + "   ├─ Component: " + ((object)val).GetType().Name));
				}
			}
			foreach (Transform item in obj.transform)
			{
				LogGameObjectHierarchy(((Component)item).gameObject, depth + 1, maxDepth);
			}
		}

		[HarmonyPatch("waitUntilFrameEndToSetActive")]
		[HarmonyPrefix]
		private static void WaitUntilFrameEndToSetActivePrefix(Terminal __instance, ref bool active)
		{
			if (Plugin.AlwaysOnScreen.Value)
			{
				Plugin.Logger.LogInfo((object)$"[ALWAYS-ON] Forcing terminal canvas to stay active (was: {active})");
				active = true;
			}
		}

		[HarmonyPatch("SetTerminalInUseClientRpc")]
		[HarmonyPostfix]
		private static void SetTerminalInUseClientRpcPostfix(Terminal __instance, bool inUse)
		{
			if (Plugin.AlwaysOnLight.Value && (Object)(object)terminalLight != (Object)null)
			{
				((Behaviour)terminalLight).enabled = true;
				Plugin.Logger.LogInfo((object)$"[ALWAYS-ON] Terminal light kept enabled (inUse: {inUse})");
			}
		}

		private static void ApplyTheme(Terminal terminal)
		{
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03db: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0401: Unknown result type (might be due to invalid IL or missing references)
			//IL_0406: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0414: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_052f: Unknown result type (might be due to invalid IL or missing references)
			//IL_053f: Unknown result type (might be due to invalid IL or missing references)
			//IL_054a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0555: Unknown result type (might be due to invalid IL or missing references)
			//IL_048b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)terminal.screenText == (Object)null || (Object)(object)terminal.screenText.textComponent == (Object)null)
			{
				Plugin.Logger.LogWarning((object)"[THEME] Cannot apply theme - screenText or textComponent is null");
				return;
			}
			bool flag = !string.IsNullOrWhiteSpace(Plugin.CustomTextColor.Value);
			bool flag2 = !string.IsNullOrWhiteSpace(Plugin.CustomScreenLightColor.Value);
			bool flag3 = !string.IsNullOrWhiteSpace(Plugin.CustomBackgroundColor.Value);
			Color val = default(Color);
			Color val2 = default(Color);
			Color val3 = default(Color);
			if (flag || flag2 || flag3)
			{
				Plugin.Logger.LogInfo((object)"[THEME] Using custom colors (overriding theme)");
				val = (Color)(flag ? ParseCustomColor(Plugin.CustomTextColor.Value) : new Color(0f, 1f, 0f, 1f));
				val2 = (Color)(flag2 ? ParseCustomColor(Plugin.CustomScreenLightColor.Value) : new Color(0f, 1f, 0f, 1f));
				val3 = (Color)(flag3 ? ParseCustomColor(Plugin.CustomBackgroundColor.Value) : new Color(0f, 0.08f, 0f, 1f));
			}
			else
			{
				string text = Plugin.TerminalTheme.Value.ToLower();
				switch (text)
				{
				case "green":
					((Color)(ref val))..ctor(0f, 1f, 0f, 1f);
					((Color)(ref val2))..ctor(0f, 1f, 0f, 1f);
					((Color)(ref val3))..ctor(0f, 0.08f, 0f, 1f);
					break;
				case "amber":
					((Color)(ref val))..ctor(1f, 0.75f, 0f, 1f);
					((Color)(ref val2))..ctor(1f, 0.75f, 0f, 1f);
					((Color)(ref val3))..ctor(0.08f, 0.06f, 0f, 1f);
					break;
				case "blue":
					((Color)(ref val))..ctor(0.3f, 0.7f, 1f, 1f);
					((Color)(ref val2))..ctor(0.3f, 0.7f, 1f, 1f);
					((Color)(ref val3))..ctor(0f, 0.03f, 0.08f, 1f);
					break;
				case "red":
					((Color)(ref val))..ctor(1f, 0.2f, 0.2f, 1f);
					((Color)(ref val2))..ctor(1f, 0.2f, 0.2f, 1f);
					((Color)(ref val3))..ctor(0.08f, 0f, 0f, 1f);
					break;
				case "purple":
					((Color)(ref val))..ctor(0.8f, 0.4f, 1f, 1f);
					((Color)(ref val2))..ctor(0.8f, 0.4f, 1f, 1f);
					((Color)(ref val3))..ctor(0.06f, 0f, 0.08f, 1f);
					break;
				case "cyan":
					((Color)(ref val))..ctor(0f, 1f, 1f, 1f);
					((Color)(ref val2))..ctor(0f, 1f, 1f, 1f);
					((Color)(ref val3))..ctor(0f, 0.08f, 0.08f, 1f);
					break;
				default:
					Plugin.Logger.LogInfo((object)"[THEME] Using default terminal colors");
					return;
				}
				Plugin.Logger.LogInfo((object)("[THEME] Using theme preset: " + text));
			}
			((Graphic)terminal.screenText.textComponent).color = val;
			Plugin.Logger.LogInfo((object)$"[THEME] Applied text color: R:{val.r:F2} G:{val.g:F2} B:{val.b:F2}");
			if (terminal.screenText.caretColor != val)
			{
				terminal.screenText.caretColor = val;
				Plugin.Logger.LogInfo((object)"[THEME] Applied caret color");
			}
			if ((Object)(object)terminal.terminalUIScreen != (Object)null)
			{
				TextMeshProUGUI[] componentsInChildren = ((Component)terminal.terminalUIScreen).GetComponentsInChildren<TextMeshProUGUI>(true);
				Plugin.Logger.LogInfo((object)$"[THEME] Found {componentsInChildren.Length} TextMeshProUGUI components");
				TextMeshProUGUI[] array = componentsInChildren;
				foreach (TextMeshProUGUI val4 in array)
				{
					if (!((Object)(object)val4 == (Object)(object)terminal.screenText.textComponent))
					{
						((Graphic)val4).color = val;
						Plugin.Logger.LogInfo((object)("[THEME] Colored text component: " + ((Object)((Component)val4).gameObject).name));
					}
				}
			}
			if ((Object)(object)terminalLight != (Object)null)
			{
				terminalLight.color = val2;
				Plugin.Logger.LogInfo((object)$"[THEME] Applied light color: R:{val2.r:F2} G:{val2.g:F2} B:{val2.b:F2}");
			}
			else
			{
				Plugin.Logger.LogInfo((object)"[THEME] No terminal light found to color");
			}
			if ((Object)(object)terminalBackground != (Object)null)
			{
				((Graphic)terminalBackground).color = val3;
				Plugin.Logger.LogInfo((object)$"[THEME] Applied background color: R:{val3.r:F2} G:{val3.g:F2} B:{val3.b:F2}");
			}
			else
			{
				Plugin.Logger.LogInfo((object)"[THEME] No terminal background found to color");
			}
		}

		private static Color ParseCustomColor(string colorString)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string[] array = colorString.Split(',');
				if (array.Length == 3)
				{
					float num = float.Parse(array[0].Trim()) / 255f;
					float num2 = float.Parse(array[1].Trim()) / 255f;
					float num3 = float.Parse(array[2].Trim()) / 255f;
					return new Color(num, num2, num3, 1f);
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogError((object)("[THEME] Failed to parse custom color '" + colorString + "': " + ex.Message));
			}
			Plugin.Logger.LogWarning((object)"[THEME] Using default green color due to parse error");
			return new Color(0f, 1f, 0f, 1f);
		}
	}
}