Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ShipDoorTerminal v1.0.10
ShipDoorTerminal.dll
Decompiled 7 hours agousing 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"; } }