Decompiled source of ShipDoorTerminal v1.0.10

ShipDoorTerminal.dll

Decompiled 7 hours 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 System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
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("ShipDoorTerminal")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.7.0")]
[assembly: AssemblyInformationalVersion("1.0.7")]
[assembly: AssemblyProduct("ShipDoorTerminal")]
[assembly: AssemblyTitle("ShipDoorTerminal")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.7.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[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 ShipDoorTerminal
{
	internal static class ManualPatches
	{
		internal static void Apply(Harmony harmony)
		{
			try
			{
				Prefix(typeof(Terminal), "OnSubmit", typeof(OnSubmitPatch), "Prefix");
				Prefix(typeof(Terminal), "ParseWord", typeof(ParseWordPatch), "Prefix", new Type[2]
				{
					typeof(string),
					typeof(int)
				});
				Prefix(typeof(Terminal), "ParsePlayerSentence", typeof(ParseSentencePatch), "Prefix");
				Prefix(typeof(Terminal), "LoadNewNode", typeof(LoadNewNodePatch), "Prefix");
				Postfix(typeof(Terminal), "Awake", typeof(TerminalLifecyclePatch), "AwakePostfix");
				Postfix(typeof(Terminal), "Start", typeof(TerminalLifecyclePatch), "StartPostfix");
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"ManualPatches.Apply failed: {arg}");
			}
			void Postfix(Type type, string name, Type patchType, string method)
			{
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				//IL_007f: Expected O, but got Unknown
				MethodInfo methodInfo = AccessTools.Method(type, name, (Type[])null, (Type[])null);
				Plugin.Log.LogInfo((object)("Resolve " + type.Name + "." + name + " => " + ((methodInfo == null) ? "NULL" : "ok")));
				if (!(methodInfo == null))
				{
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(patchType, method, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Plugin.Log.LogInfo((object)("Patched " + type.Name + "." + name + " postfix " + method));
				}
			}
			void Prefix(Type type, string name, Type patchType, string method, Type[]? args = null)
			{
				//IL_0090: Unknown result type (might be due to invalid IL or missing references)
				//IL_009e: Expected O, but got Unknown
				MethodInfo methodInfo = ((args == null) ? AccessTools.Method(type, name, (Type[])null, (Type[])null) : AccessTools.Method(type, name, args, (Type[])null));
				Plugin.Log.LogInfo((object)("Resolve " + type.Name + "." + name + " => " + ((methodInfo == null) ? "NULL" : (methodInfo.IsPublic ? "public" : "nonpublic"))));
				if (!(methodInfo == null))
				{
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(patchType, method, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Plugin.Log.LogInfo((object)("Patched " + type.Name + "." + name + " prefix " + method));
				}
			}
		}
	}
	internal static class TerminalInput
	{
		internal static string? LastSubmitted;

		private static readonly HashSet<string> Commands = new HashSet<string>(StringComparer.Ordinal) { "door", "doors", "opendoor", "open door", "door open", "dooropen", "closedoor", "close door", "door close", "doorclose" };

		internal static string Normalize(string? raw)
		{
			if (string.IsNullOrEmpty(raw))
			{
				return "";
			}
			return Regex.Replace(Regex.Replace(raw.ToLowerInvariant(), "[^a-z0-9\\s]", " "), "\\s+", " ").Trim();
		}

		internal static string Extract(Terminal terminal)
		{
			try
			{
				string text = (((Object)(object)terminal.screenText != (Object)null) ? terminal.screenText.text : null);
				if (string.IsNullOrEmpty(text))
				{
					return "";
				}
				if (terminal.textAdded > 0 && text.Length >= terminal.textAdded)
				{
					return Normalize(text.Substring(text.Length - terminal.textAdded));
				}
				int num = text.LastIndexOf('\n');
				return Normalize(((num >= 0) ? text.Substring(num + 1) : text).Trim().TrimStart('>', ' '));
			}
			catch
			{
				return "";
			}
		}

		internal static bool IsDoorCommand(string input)
		{
			return Commands.Contains(input);
		}
	}
	internal static class OnSubmitPatch
	{
		public static bool Prefix(Terminal __instance)
		{
			try
			{
				string text = (TerminalInput.LastSubmitted = TerminalInput.Extract(__instance));
				Plugin.Log.LogInfo((object)$"[OnSubmit] captured='{text}' enabled={Plugin.Enabled?.Value}");
				if (Plugin.Enabled == null || !Plugin.Enabled.Value)
				{
					return true;
				}
				if (!TerminalInput.IsDoorCommand(text))
				{
					return true;
				}
				string text2 = DoorActions.Run(text);
				Plugin.Log.LogInfo((object)("[OnSubmit] handled '" + text + "'"));
				__instance.LoadNewNode(DoorActions.CreateDisplayNode(text2));
				DoorActions.ReadyForNextCommand(__instance);
				return false;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogWarning((object)$"[OnSubmit] {arg}");
				return true;
			}
		}
	}
	internal static class ParseWordPatch
	{
		public static bool Prefix(string playerWord, int specificityRequired, ref TerminalKeyword __result)
		{
			if (Plugin.Enabled == null || !Plugin.Enabled.Value)
			{
				return true;
			}
			try
			{
				string text = TerminalInput.Normalize(playerWord);
				Plugin.V($"[ParseWord] '{playerWord}' -> '{text}' spec={specificityRequired}");
				if (!TerminalInput.IsDoorCommand(text))
				{
					return true;
				}
				__result = DoorActions.GetKeyword(text);
				Plugin.Log.LogInfo((object)("[ParseWord] returning door keyword for '" + text + "'"));
				return false;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogWarning((object)$"[ParseWord] {arg}");
				return true;
			}
		}
	}
	internal static class ParseSentencePatch
	{
		public static bool Prefix(Terminal __instance, ref TerminalNode __result)
		{
			if (Plugin.Enabled == null || !Plugin.Enabled.Value)
			{
				return true;
			}
			try
			{
				string text = TerminalInput.LastSubmitted;
				if (string.IsNullOrEmpty(text))
				{
					text = TerminalInput.Extract(__instance);
				}
				Plugin.V("[ParseSentence] input='" + text + "'");
				if (string.IsNullOrEmpty(text) || !TerminalInput.IsDoorCommand(text))
				{
					return true;
				}
				string text2 = DoorActions.Run(text);
				__result = DoorActions.CreateDisplayNode(text2);
				TerminalInput.LastSubmitted = null;
				Plugin.Log.LogInfo((object)("[ParseSentence] handled '" + text + "'"));
				return false;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogWarning((object)$"[ParseSentence] {arg}");
				return true;
			}
		}
	}
	internal static class LoadNewNodePatch
	{
		private static int _reentry;

		public static void Prefix(TerminalNode node)
		{
			if ((Object)(object)node == (Object)null || _reentry > 0)
			{
				return;
			}
			try
			{
				if (Plugin.Enabled == null || !Plugin.Enabled.Value)
				{
					return;
				}
				if (!DoorActions.TryGetCommandForNode(node, out string cmd))
				{
					Plugin.V("[LoadNewNode] unrelated");
					return;
				}
				Plugin.Log.LogInfo((object)("[LoadNewNode] door keyword node for '" + cmd + "' — running action"));
				_reentry++;
				try
				{
					string text = DoorActions.Run(cmd);
					string text2 = (text.EndsWith("\n") ? text : (text + "\n"));
					if (!text2.EndsWith("\n\n"))
					{
						text2 += "\n";
					}
					node.displayText = text2;
					node.clearPreviousText = true;
					node.acceptAnything = false;
					node.overrideOptions = false;
				}
				finally
				{
					_reentry--;
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogWarning((object)$"[LoadNewNode] {arg}");
			}
		}
	}
	internal static class TerminalLifecyclePatch
	{
		public static void AwakePostfix(Terminal __instance)
		{
			Plugin.Log.LogInfo((object)"[Terminal.Awake] postfix hit");
			DoorActions.EnsureKeywordsRegistered(__instance);
			DoorActions.EnsureHelpText(__instance);
		}

		public static void StartPostfix(Terminal __instance)
		{
			Plugin.Log.LogInfo((object)"[Terminal.Start] postfix hit");
			DoorActions.EnsureKeywordsRegistered(__instance);
			DoorActions.EnsureHelpText(__instance);
		}
	}
	internal static class DoorActions
	{
		private static readonly Dictionary<string, TerminalKeyword> Keywords = new Dictionary<string, TerminalKeyword>();

		private static readonly Dictionary<TerminalNode, string> NodeCommands = new Dictionary<TerminalNode, string>();

		private static bool _registered;

		private static bool _helpInjected;

		private const string HelpMarker = "[ShipDoorTerminal]";

		private const string HelpFingerprint = ">DOOR";

		private const string HelpBlock = ">DOOR\nToggle the ship hangar doors.\nAlso: OPENDOOR / CLOSEDOOR\n\n";

		internal static TerminalNode CreateDisplayNode(string text)
		{
			TerminalNode obj = ScriptableObject.CreateInstance<TerminalNode>();
			string text2 = text ?? "";
			if (!text2.EndsWith("\n"))
			{
				text2 += "\n";
			}
			if (!text2.EndsWith("\n\n"))
			{
				text2 += "\n";
			}
			obj.displayText = text2;
			obj.clearPreviousText = true;
			obj.maxCharactersToType = 80;
			obj.acceptAnything = false;
			obj.overrideOptions = false;
			return obj;
		}

		internal static void ReadyForNextCommand(Terminal terminal)
		{
			try
			{
				if (!((Object)(object)terminal?.screenText == (Object)null))
				{
					terminal.screenText.ActivateInputField();
					((Selectable)terminal.screenText).Select();
					int num = ((terminal.screenText.text != null) ? terminal.screenText.text.Length : 0);
					terminal.screenText.caretPosition = num;
					terminal.screenText.selectionAnchorPosition = num;
					terminal.screenText.selectionFocusPosition = num;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[ReadyForNextCommand] " + ex.Message));
			}
		}

		internal static bool TryGetCommandForNode(TerminalNode node, out string cmd)
		{
			if (NodeCommands.TryGetValue(node, out cmd))
			{
				return true;
			}
			string text = node.displayText ?? "";
			if (text.StartsWith("Ship door command:", StringComparison.OrdinalIgnoreCase))
			{
				cmd = TerminalInput.Normalize(text.Substring("Ship door command:".Length));
				return TerminalInput.IsDoorCommand(cmd);
			}
			cmd = "";
			return false;
		}

		internal static TerminalKeyword GetKeyword(string word)
		{
			string text = (word.Contains(" ") ? word.Split(' ')[0] : word);
			if (Keywords.TryGetValue(text, out TerminalKeyword value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			EnsureKeyword(text);
			return Keywords[text];
		}

		private static void EnsureKeyword(string word)
		{
			if (!Keywords.ContainsKey(word))
			{
				TerminalNode val = CreateDisplayNode("Ship door command: " + word + "\n");
				NodeCommands[val] = word;
				TerminalKeyword val2 = ScriptableObject.CreateInstance<TerminalKeyword>();
				val2.word = word;
				val2.isVerb = false;
				val2.specialKeywordResult = val;
				Keywords[word] = val2;
			}
		}

		internal static void EnsureKeywordsRegistered(Terminal terminal)
		{
			try
			{
				if (terminal?.terminalNodes?.allKeywords == null)
				{
					Plugin.Log.LogInfo((object)"Keyword register skipped: allKeywords null");
					return;
				}
				EnsureKeyword("door");
				EnsureKeyword("doors");
				EnsureKeyword("opendoor");
				EnsureKeyword("closedoor");
				EnsureKeyword("dooropen");
				EnsureKeyword("doorclose");
				if (_registered)
				{
					Plugin.V("Keywords already registered");
					return;
				}
				List<TerminalKeyword> list = new List<TerminalKeyword>(terminal.terminalNodes.allKeywords);
				foreach (KeyValuePair<string, TerminalKeyword> kv in Keywords)
				{
					if (!list.Exists((TerminalKeyword k) => (Object)(object)k != (Object)null && k.word == kv.Key))
					{
						list.Add(kv.Value);
					}
				}
				terminal.terminalNodes.allKeywords = list.ToArray();
				_registered = true;
				Plugin.Log.LogInfo((object)$"Registered door keywords (allKeywords={list.Count}, trackedNodes={NodeCommands.Count})");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("EnsureKeywordsRegistered failed: " + ex.Message));
			}
		}

		internal static void EnsureHelpText(Terminal terminal)
		{
			try
			{
				if (terminal?.terminalNodes?.specialNodes == null)
				{
					return;
				}
				int num = 0;
				for (int i = 0; i < terminal.terminalNodes.specialNodes.Count; i++)
				{
					if (TryApplyHelpToNode(terminal.terminalNodes.specialNodes[i], $"specialNodes[{i}]"))
					{
						num++;
					}
				}
				TerminalKeyword[] allKeywords = terminal.terminalNodes.allKeywords;
				if (allKeywords != null)
				{
					TerminalKeyword[] array = allKeywords;
					foreach (TerminalKeyword val in array)
					{
						if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(val.word))
						{
							string word = val.word;
							if ((string.Equals(word, "help", StringComparison.OrdinalIgnoreCase) || string.Equals(word, "other", StringComparison.OrdinalIgnoreCase) || string.Equals(word, "others", StringComparison.OrdinalIgnoreCase)) && TryApplyHelpToNode(val.specialKeywordResult, "keyword:" + word))
							{
								num++;
							}
						}
					}
				}
				if (num > 0)
				{
					_helpInjected = true;
				}
				else if (!_helpInjected)
				{
					Plugin.Log.LogInfo((object)"[Help] no command-list page found yet");
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[Help] " + ex.Message));
			}
		}

		private static bool IsCommandListPage(string page)
		{
			if (string.IsNullOrEmpty(page))
			{
				return false;
			}
			bool num = page.IndexOf(">STORE", StringComparison.OrdinalIgnoreCase) >= 0;
			bool flag = page.IndexOf(">BESTIARY", StringComparison.OrdinalIgnoreCase) >= 0;
			bool flag2 = page.IndexOf(">STORAGE", StringComparison.OrdinalIgnoreCase) >= 0;
			bool flag3 = page.IndexOf(">OTHER", StringComparison.OrdinalIgnoreCase) >= 0;
			if (!num || !(flag || flag2 || flag3))
			{
				return false;
			}
			return true;
		}

		private static bool TryApplyHelpToNode(TerminalNode? node, string label)
		{
			if ((Object)(object)node == (Object)null || string.IsNullOrEmpty(node.displayText))
			{
				return false;
			}
			string text = StripLegacyHelpHeader(node.displayText);
			if (!IsCommandListPage(text))
			{
				string text2 = StripDoorHelp(text);
				if (text2 != node.displayText)
				{
					node.displayText = text2;
					Plugin.Log.LogInfo((object)("[Help] stripped door docs from non-list " + label));
				}
				return false;
			}
			if (text.IndexOf(">DOOR", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				if (text != node.displayText)
				{
					node.displayText = text;
				}
				return false;
			}
			node.displayText = InjectHelp(text);
			Plugin.Log.LogInfo((object)("[Help] injected door docs into " + label));
			return true;
		}

		private static string StripLegacyHelpHeader(string page)
		{
			if (string.IsNullOrEmpty(page) || page.IndexOf("[ShipDoorTerminal]", StringComparison.Ordinal) < 0)
			{
				return page;
			}
			return page.Replace("[ShipDoorTerminal]\n\n", "").Replace("[ShipDoorTerminal]\n", "").Replace("[ShipDoorTerminal]", "");
		}

		private static string StripDoorHelp(string page)
		{
			if (string.IsNullOrEmpty(page) || page.IndexOf(">DOOR", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return page;
			}
			if (page.Contains(">DOOR\nToggle the ship hangar doors.\nAlso: OPENDOOR / CLOSEDOOR\n\n"))
			{
				return page.Replace(">DOOR\nToggle the ship hangar doors.\nAlso: OPENDOOR / CLOSEDOOR\n\n", "");
			}
			int num = page.IndexOf(">DOOR", StringComparison.OrdinalIgnoreCase);
			if (num < 0)
			{
				return page;
			}
			int num2 = page.IndexOf("\n\n", num);
			num2 = ((num2 >= 0) ? (num2 + 2) : page.Length);
			int num3 = num;
			if (num3 >= 2 && page[num3 - 2] == '\n' && page[num3 - 1] == '\n')
			{
				num3 -= 2;
			}
			else if (num3 >= 1 && page[num3 - 1] == '\n')
			{
				num3--;
			}
			return page.Substring(0, num3) + page.Substring(num2);
		}

		private static string InjectHelp(string page)
		{
			page = StripLegacyHelpHeader(page);
			int num = page.IndexOf(">OTHER", StringComparison.OrdinalIgnoreCase);
			if (num < 0)
			{
				num = page.IndexOf("OTHER", StringComparison.OrdinalIgnoreCase);
			}
			if (num >= 0)
			{
				int num2 = page.IndexOf("\n\n", num);
				if (num2 > num)
				{
					int num3 = num2 + 2;
					return page.Substring(0, num3) + ">DOOR\nToggle the ship hangar doors.\nAlso: OPENDOOR / CLOSEDOOR\n\n" + page.Substring(num3);
				}
			}
			if (!page.EndsWith("\n"))
			{
				page += "\n";
			}
			if (!page.EndsWith("\n\n"))
			{
				page += "\n";
			}
			return page + ">DOOR\nToggle the ship hangar doors.\nAlso: OPENDOOR / CLOSEDOOR\n\n";
		}

		internal static string Run(string input)
		{
			switch (input)
			{
			case "door":
			case "doors":
				return Toggle();
			case "dooropen":
			case "opendoor":
			case "door open":
			case "open door":
				return Set(wantClosed: false);
			case "closedoor":
			case "doorclose":
			case "close door":
			case "door close":
				return Set(wantClosed: true);
			default:
				return "Unknown door command.\n";
			}
		}

		private static string Toggle()
		{
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return "Ship doors unavailable.\n";
			}
			return Set(!instance.hangarDoorsClosed);
		}

		private static string Set(bool wantClosed)
		{
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return "Ship doors unavailable.\n";
			}
			if (instance.inShipPhase)
			{
				return "Ship doors unavailable while in orbit.\n";
			}
			HangarShipDoor val = Object.FindObjectOfType<HangarShipDoor>();
			Plugin.Log.LogInfo((object)($"[Door] wantClosed={wantClosed}, hangarDoorsClosed={instance.hangarDoorsClosed}, " + $"shipDoorsEnabled={instance.shipDoorsEnabled}, doorNull={(Object)(object)val == (Object)null}, " + $"overheated={val?.overheated}, buttonsEnabled={val?.buttonsEnabled}, doorPower={val?.doorPower}"));
			if ((Object)(object)val != (Object)null && val.overheated)
			{
				return "Ship doors are overheated and cannot be toggled.\n";
			}
			if (instance.hangarDoorsClosed == wantClosed)
			{
				if (!wantClosed)
				{
					return "Ship doors are already open.\n";
				}
				return "Ship doors are already closed.\n";
			}
			string text = (wantClosed ? "StopButton" : "StartButton");
			if (TryPressDoorButton(text))
			{
				Plugin.Log.LogInfo((object)$"[Door] pressed {text}; hangarDoorsClosed now={instance.hangarDoorsClosed}");
				if (!wantClosed)
				{
					return "Opening ship doors...\n";
				}
				return "Closing ship doors...\n";
			}
			Plugin.Log.LogWarning((object)("[Door] " + text + " interact failed — trying HangarShipDoor + ServerRpc fallback"));
			try
			{
				if ((Object)(object)val != (Object)null)
				{
					if (wantClosed)
					{
						val.SetDoorClosed();
					}
					else
					{
						val.SetDoorOpen();
					}
					val.PlayDoorAnimation(wantClosed);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[Door] HangarShipDoor fallback: " + ex.Message));
			}
			try
			{
				instance.SetDoorsClosedServerRpc(wantClosed);
				Plugin.Log.LogInfo((object)"[Door] called SetDoorsClosedServerRpc");
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogWarning((object)("[Door] SetDoorsClosedServerRpc: " + ex2.Message));
				try
				{
					instance.SetShipDoorsClosed(wantClosed);
				}
				catch (Exception ex3)
				{
					Plugin.Log.LogWarning((object)("[Door] SetShipDoorsClosed: " + ex3.Message));
				}
			}
			Plugin.Log.LogInfo((object)$"[Door] after fallback: hangarDoorsClosed={instance.hangarDoorsClosed}");
			if (!wantClosed)
			{
				return "Opening ship doors...\n";
			}
			return "Closing ship doors...\n";
		}

		private static bool TryPressDoorButton(string buttonName)
		{
			try
			{
				GameObject val = GameObject.Find(buttonName);
				if ((Object)(object)val == (Object)null)
				{
					val = GameObject.Find("Environment/HangarShip/AnimatedShipDoor/" + buttonName) ?? GameObject.Find("HangarShip/" + buttonName);
				}
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogWarning((object)("[Door] GameObject.Find('" + buttonName + "') returned null"));
					return false;
				}
				InteractTrigger componentInChildren = val.GetComponentInChildren<InteractTrigger>();
				if ((Object)(object)componentInChildren == (Object)null)
				{
					Plugin.Log.LogWarning((object)("[Door] no InteractTrigger on " + buttonName));
					return false;
				}
				PlayerControllerB val2 = GameNetworkManager.Instance?.localPlayerController;
				if ((Object)(object)val2 == (Object)null)
				{
					Plugin.Log.LogWarning((object)"[Door] no local player for button interact");
					return false;
				}
				UnityEvent<PlayerControllerB> onInteract = (UnityEvent<PlayerControllerB>)(object)componentInChildren.onInteract;
				if (onInteract != null)
				{
					onInteract.Invoke(val2);
					Plugin.Log.LogInfo((object)("[Door] invoked onInteract on " + buttonName));
					return true;
				}
				componentInChildren.Interact(((Component)val2).transform);
				Plugin.Log.LogInfo((object)("[Door] called Interact() on " + buttonName));
				return true;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogWarning((object)$"[Door] TryPressDoorButton({buttonName}): {arg}");
				return false;
			}
		}
	}
	[BepInPlugin("com.benhough.lethal.ShipDoorTerminal", "ShipDoorTerminal", "1.0.10")]
	public class Plugin : BaseUnityPlugin
	{
		public const string ModGuid = "com.benhough.lethal.ShipDoorTerminal";

		public const string ModName = "ShipDoorTerminal";

		public const string ModVersion = "1.0.10";

		private readonly Harmony _harmony = new Harmony("com.benhough.lethal.ShipDoorTerminal");

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal static ConfigEntry<bool> Enabled { get; private set; }

		internal static ConfigEntry<bool> Verbose { get; private set; }

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable terminal commands: door / doors / opendoor / closedoor.");
			Verbose = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "VerboseLogging", true, "Log terminal/door traces.");
			ManualPatches.Apply(_harmony);
			Log.LogInfo((object)string.Format("{0} v{1} loaded. Verbose={2}", "ShipDoorTerminal", "1.0.10", Verbose.Value));
		}

		internal static void V(string msg)
		{
			if (Verbose != null && Verbose.Value)
			{
				Log.LogInfo((object)msg);
			}
		}
	}
	internal static class PluginInfo
	{
		public const string PLUGIN_GUID = "com.benhough.lethal.ShipDoorTerminal";

		public const string PLUGIN_NAME = "ShipDoorTerminal";

		public const string PLUGIN_VERSION = "1.0.10";
	}
}