Decompiled source of OpenLib v0.4.0
OpenLib.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using InteractiveTerminalAPI.UI; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using LobbyCompatibility.Enums; using LobbyCompatibility.Features; using Microsoft.CodeAnalysis; using ModelReplacement; using OpenBodyCams; using OpenBodyCams.API; using OpenLib.Common; using OpenLib.Compat; using OpenLib.ConfigManager; using OpenLib.CoreMethods; using OpenLib.Events; using OpenLib.InteractiveMenus; using OpenLib.Menus; using TMPro; using TerminalStuff; using TerminalStuff.EventSub; using TerminalStuff.SpecialStuff; using TwoRadarMaps; using Unity.Netcode; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Rendering.HighDefinition; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("darmuhsTerminalStuff")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("darmuh")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.4.0")] [assembly: AssemblyInformationalVersion("0.4.0+5f6d109a8b261753d1ec15b919a3c4d338c163af")] [assembly: AssemblyProduct("OpenLib")] [assembly: AssemblyTitle("OpenLib")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.4.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace OpenLib { public class Loggers { public enum LoggingLevel { WarningsPlus = 4, Message = 8, Info = 0x10, Debug = 0x20 } private static void Log(LogLevel bepLevel, object data) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected I4, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) int value = (int)ConfigSetup.LogLevel.Value; int num = (int)bepLevel; if (num <= value) { Plugin.Log.Log(bepLevel, data); } } internal static void LogDebug(object data) { Log((LogLevel)32, data); } internal static void LogInfo(object data) { Log((LogLevel)16, data); } internal static void LogMessage(object data) { Log((LogLevel)8, data); } internal static void WARNING(object data) { Log((LogLevel)4, data); } internal static void ERROR(object data) { Log((LogLevel)2, data); } internal static void FATAL(object data) { Log((LogLevel)1, data); } } public class PageBuilder { public StringBuilder? Content { get; set; } public int PageNumber { get; set; } } public class PageSplitter { public static List<PageBuilder> SplitTextIntoPages(string inputText, int maxLinesPerPage, string nextPageBlurb) { string[] array = inputText.Split(new string[1] { Environment.NewLine }, StringSplitOptions.None); List<PageBuilder> list = new List<PageBuilder>(); int i = 0; int num = 1; while (i < array.Length) { PageBuilder pageBuilder = new PageBuilder { Content = new StringBuilder(), PageNumber = num }; for (; i < array.Length && string.IsNullOrWhiteSpace(array[i]); i++) { } for (int j = 0; j < maxLinesPerPage; j++) { if (i >= array.Length) { break; } pageBuilder.Content.AppendLine(array[i]); i++; } if (i < array.Length - 2) { pageBuilder.Content.AppendLine(nextPageBlurb ?? ""); } else { pageBuilder.Content.AppendLine("\r\n"); } list.Add(pageBuilder); num++; } return list; } } [HarmonyPatch(typeof(GameNetworkManager), "Start")] public class GameStartPatch { public static void Postfix() { EventManager.GameNetworkManagerStart.Invoke(); NetworkClassBase.RegisterNetworkPrefabs(); } } [HarmonyPatch(typeof(StartOfRound), "Awake")] public class StartRoundAwake { public static void Postfix() { EventManager.StartOfRoundAwake.Invoke(); NetworkClassBase.SpawnNetworkPrefab(); } } [HarmonyPatch(typeof(StartOfRound), "Start")] public class StartRoundPatch { public static void Postfix() { EventManager.StartOfRoundStart.Invoke(); } } [HarmonyPatch(typeof(StartOfRound), "StartGame")] public class LandingPatch { public static void Postfix() { EventManager.StartOfRoundStartGame.Invoke(); } } [HarmonyPatch(typeof(StartOfRound), "ResetShip")] public class ShipResetPatch { public static void Postfix() { EventManager.ShipReset.Invoke(); } } [HarmonyPatch(typeof(StartOfRound), "PassTimeToNextDay")] public class NextDayPatch { public static void Postfix() { EventManager.NextDayEvent.Invoke(); } } [HarmonyPatch(typeof(StartOfRound), "OnShipLandedMiscEvents")] public class OnShipLandedMiscPatch { public static void Postfix() { EventManager.OnShipLandedMiscPatch.Invoke(); } } [HarmonyPatch(typeof(StartOfRound), "ShipHasLeft")] public class ShipLeftPatch { public static void Postfix() { EventManager.ShipLeft.Invoke(); } } [HarmonyPatch(typeof(StartOfRound), "OnClientConnect")] public class OnClientConnectPatch { public static void Postfix() { EventManager.OnClientConnect.Invoke(); } } [HarmonyPatch(typeof(StartOfRound), "ChangeLevel")] public class RouteEvent { public static void Postfix() { EventManager.StartOfRoundChangeLevel.Invoke(); } } [HarmonyPatch(typeof(RoundManager), "SetBigDoorCodes")] public class SetBigDoorCodes { public static void Postfix() { EventManager.SetBigDoorCodes.Invoke(); } } [HarmonyPatch(typeof(RoundManager), "SpawnMapObjects")] public class SpawnMapObjects { public static void Postfix() { EventManager.SpawnMapObjects.Invoke(); } } [HarmonyPatch(typeof(TimeOfDay), "SetNewProfitQuota")] public class NewQuotaPatch { public static void Postfix() { EventManager.NewQuota.Invoke(); } } [HarmonyPatch(typeof(AutoParentToShip), "Awake")] public class AutoParentGameObjectPatch { public static void Postfix(AutoParentToShip __instance) { if (!((Object)(object)((Component)__instance).gameObject == (Object)null)) { EventManager.AutoParentEvent.Invoke(((Component)__instance).gameObject); } } } [HarmonyPatch(typeof(NetworkObject), "Spawn")] public class ObjectSpawnPatch { public static void Postfix(NetworkObject __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)((Component)__instance).gameObject == (Object)null)) { EventManager.NetworkObjectSpawn.Invoke(((Component)__instance).gameObject); } } } [HarmonyPatch(typeof(PlayerControllerB), "StartPerformingEmoteServerRpc")] public class EmotePatch { public static void Postfix() { EventManager.PlayerEmote.Invoke(); } } [HarmonyPatch(typeof(PlayerControllerB), "Update")] public class PlayerUpdatePatch { public static bool usePatch; public static bool inShip; public static bool spectate_inShip; public static bool isDead; public static void Postfix(PlayerControllerB __instance) { if (usePatch && !((Object)(object)StartOfRound.Instance == (Object)null) && !((Object)(object)StartOfRound.Instance.localPlayerController == (Object)null) && !((Object)(object)StartOfRound.Instance.localPlayerController != (Object)(object)__instance)) { if (__instance.isInHangarShipRoom != inShip) { inShip = __instance.isInHangarShipRoom; EventManager.PlayerIsInShip.Invoke(); } if (__instance.isPlayerDead != isDead) { isDead = __instance.isPlayerDead; EventManager.PlayerIsDead.Invoke(); } if (__instance.isPlayerDead && (Object)(object)__instance.spectatedPlayerScript != (Object)null && __instance.spectatedPlayerScript.isInHangarShipRoom != spectate_inShip) { spectate_inShip = __instance.spectatedPlayerScript.isInHangarShipRoom; EventManager.SpecatingPlayerIsInShip.Invoke(); } } } } public class SpectateNextPatch { [HarmonyPatch(typeof(PlayerControllerB), "SpectateNextPlayer")] public class PlayerSpawnPatch : MonoBehaviour { private static void Postfix() { EventManager.SpecateNextPlayer.Invoke(); } } } public class SpawnPatch { [HarmonyPatch(typeof(PlayerControllerB), "SpawnPlayerAnimation")] public class PlayerSpawnPatch { private static void Postfix() { EventManager.PlayerSpawn.Invoke(); } } } [HarmonyPatch(typeof(ShipTeleporter), "Awake")] public class TeleporterInit { private static void Postfix(ShipTeleporter __instance) { EventManager.TeleporterAwake.Invoke(__instance); } } [HarmonyPatch(typeof(Terminal), "Awake")] public class AwakeTermPatch { private static void Postfix(Terminal __instance) { EventManager.TerminalAwake.Invoke(__instance); } } [HarmonyPatch(typeof(Terminal), "Start")] public class TerminalStartPatch { private static void Postfix() { EventManager.TerminalStart.Invoke(); } } [HarmonyPatch(typeof(Terminal), "OnDisable")] public class DisableTermPatch { private static void Postfix() { EventManager.TerminalDisable.Invoke(); } } [HarmonyPatch(typeof(Terminal), "QuitTerminal")] public class QuitTerminalPatch { private static void Postfix() { EventManager.TerminalQuit.Invoke(); } } [HarmonyPatch(typeof(Terminal), "LoadNewNode")] public class LoadNewNodePatch { private static void Postfix(TerminalNode node) { EventManager.TerminalLoadNewNode.Invoke(node); } } [HarmonyPatch(typeof(Terminal), "LoadNewNodeIfAffordable")] public class AffordableNodePatch { private static void Postfix(TerminalNode node) { EventManager.TerminalLoadIfAffordable.Invoke(node); } } [HarmonyPatch(typeof(Terminal), "BeginUsingTerminal")] public class Terminal_Begin_Patch { private static void Postfix() { EventManager.TerminalBeginUsing.Invoke(); } } [HarmonyPatch(typeof(Terminal), "ParsePlayerSentence")] public class Terminal_ParsePlayerSentence_Patch { private static void Postfix(ref TerminalNode __result) { if (!((Object)(object)__result == (Object)null)) { TerminalNode val = EventManager.TerminalParseSent.NodeInvoke(ref __result); __result = val; } } } [HarmonyPatch(typeof(Terminal), "Update")] public class TerminalUpdatePatch { public static bool inUse; public static bool usePatch; public static int menuIndex; private static void Postfix(Terminal __instance) { if (usePatch && __instance.placeableObject.inUse != inUse) { inUse = __instance.placeableObject.inUse; EventManager.SetTerminalInUse.Invoke(); } } [HarmonyPrefix] private static bool Prefix(Terminal __instance) { if (!usePatch || !__instance.terminalInUse) { return true; } if (MenusContainer.AnyOpenLibMenuActive()) { __instance.scrollBarCanvasGroup.alpha = 0f; ((TMP_Text)__instance.topRightText).text = $"${__instance.groupCredits}"; if (__instance.placeableObject.inUse != inUse) { inUse = __instance.placeableObject.inUse; EventManager.SetTerminalInUse.Invoke(); } if (((ButtonControl)Keyboard.current.anyKey).wasPressedThisFrame) { EventManager.TerminalMenuKeyPressed.Invoke(); } return false; } if (((ButtonControl)Keyboard.current.anyKey).wasPressedThisFrame) { EventManager.TerminalKeyPressed.Invoke(); } return true; } } [BepInPlugin("darmuh.OpenLib", "OpenLib", "0.4.0")] public class Plugin : BaseUnityPlugin { public static Plugin instance = null; internal static ManualLogSource Log = null; public bool TerminalStuff; public bool LobbyCompat; public bool TerminalFormatter; public bool ITAPI; public bool LethalConfig; public bool OpenBodyCamsMod; public bool TwoRadarMapsMod; public bool ModelReplacement; public bool TooManyEmotes; public bool MirrorDecor; public static List<CommandManager> AllCommands = new List<CommandManager>(); public static List<TerminalKeyword> KeywordsAdded = new List<TerminalKeyword>(); public static List<TerminalNode> NodesAdded = new List<TerminalNode>(); public static List<CompatibleNoun> NounsAdded = new List<CompatibleNoun>(); public static List<TerminalAccessibleObject> AllTerminalCodes = new List<TerminalAccessibleObject>(); public Terminal Terminal; public static List<TerminalNode> ShopNodes = new List<TerminalNode>(); public const string Id = "darmuh.OpenLib"; public static string Name => "OpenLib"; public static string Version => "0.4.0"; public static List<CommandManager> GetActiveCommands() { if (AllCommands.Count == 0) { return new List<CommandManager>(); } return AllCommands.FindAll((CommandManager x) => x.IsCreated); } private void Awake() { instance = this; Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)"OpenLib is loading with version 0.4.0!\nThis mod has been compiled for v73 of Lethal Company and may not work with earlier versions"); ConfigSetup.defaultManaged = new List<ManagedConfig>(); CommandRegistry.InitListing(ref ConfigSetup.defaultListing); ConfigSetup.BindConfigSettings(); ((BaseUnityPlugin)this).Config.ConfigReloaded += OnConfigReloaded; Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null); EventUsage.Subscribers(); AllInteractiveMenus.AllMenus = new List<InteractiveMenu>(); string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "openlib.bundle"); if (File.Exists(text)) { AssetBundle val = AssetBundle.LoadFromFile(text); NetworkClassBase.Prefab = val.LoadAsset<GameObject>("Openlib Networker"); } else { Log.LogError((object)("Openlib Networker asset cannot be found! Expected path: " + text)); } Log.LogInfo((object)"OpenLib load complete!"); } internal void OnConfigReloaded(object sender, EventArgs e) { Log.LogInfo((object)"Config has been reloaded!"); ConfigSetup.ReadConfigAndAssignValues(((BaseUnityPlugin)instance).Config, ConfigSetup.defaultManaged); } } public class NodeInfo { [CompilerGenerated] private CommandManager <command>P; public string Name; public string InfoText; public Func<string> InfoAction; public TerminalNode terminalNode; public NodeInfo(CommandManager command) { <command>P = command; Name = <command>P.Name; InfoText = string.Empty; base..ctor(); } public void GetDefaultInfo(CommandManager command) { string text = "[ " + CommonStringStuff.GetKeywordsForMenuItem(command.KeywordList) + " ]\r\n"; text = ((command.IsEnabled == null) ? (text + "No further information on this command!\r\n\r\n") : (text + ((ConfigEntryBase)command.IsEnabled.ConfigItem).Description.Description + "\r\n\r\n")); InfoText = text; } public void CreateInfoNode() { if (!((Object)(object)CommonTerminal.InfoKeyword == (Object)null)) { TerminalKeyword info = CommonTerminal.InfoKeyword; terminalNode = BasicTerminal.CreateNewTerminalNode(); ((Object)terminalNode).name = "info_" + Name; terminalNode.displayText = InfoText; terminalNode.clearPreviousText = true; CollectionExtensions.Do<string>((IEnumerable<string>)<command>P.KeywordList, (Action<string>)delegate(string Keyword) { AddingThings.AddCompatibleNoun(ref info, Keyword, terminalNode); }); Loggers.LogDebug("info node created and assigned to command!"); } } } public static class MyPluginInfo { public const string PLUGIN_GUID = "OpenLib"; public const string PLUGIN_NAME = "OpenLib"; public const string PLUGIN_VERSION = "0.4.0"; } } namespace OpenLib.Menus { public class CommandsMenu { internal static CommandsMenuBase CommandMenu = null; internal static CommandMenuItem<CommandsMenuBase> MainMenuItem = null; internal static List<CommandMenuItem<CommandsMenuBase>> AllCommandMenuItems = new List<CommandMenuItem<CommandsMenuBase>>(); internal static void Init() { CommandMenu = new CommandsMenuBase("Commands Menu") { MainMenu = MainMenuItem, PageSize = 10, AdjustScrollInMenu = false }; MainMenuItem = CreateMainMenu(CommandMenu, "My Commands Menu", () => "=== My Commands Main Menu ===\n\n", () => "Created by darmuh"); } internal static void RuntimeSetup() { List<CommandManager> activeCommands = Plugin.GetActiveCommands(); UpdateMenuListing(CommandMenu, MainMenuItem, activeCommands); CreateAndSetControlsFooter(CommandMenu, AllCommandMenuItems); } public static void UpdateMenuListing(CommandsMenuBase menuBase, CommandMenuItem<CommandsMenuBase> mainMenuItem, List<CommandManager> CommandList, string defaultCategory = "Other") { if (mainMenuItem.NestedMenus.Count == 0) { MakeCommandMenuItems(menuBase, CommandList, defaultCategory, mainMenuItem); return; } List<CommandMenuItem<CommandsMenuBase>> list = mainMenuItem.NestedMenus.ConvertAll((MenuItem x) => x as CommandMenuItem<CommandsMenuBase>); foreach (CommandMenuItem<CommandsMenuBase> item in list) { item.isEnabled = CommandList.Contains(item.Command); CommandList.Remove(item.Command); UpdateMenuVisibility(item); } if (CommandList.Count > 0) { MakeCommandMenuItems(menuBase, CommandList, defaultCategory, mainMenuItem); } } private static void UpdateMenuVisibility(CommandMenuItem<CommandsMenuBase> item) { if (item.isEnabled) { if (item.Parent == null) { if (item.CachedParent == null) { Loggers.WARNING("Unable to update " + item.Name + "'s parent. CachedParent is null!"); } else { item.SetParentMenu(item.CachedParent); } } } else if (item.Parent != null) { item.CachedParent = item.Parent; item.SetParentMenu(null); } } internal static string EnterCommandMenu() { if (MainMenuItem == null) { return "This menu has not been created correctly"; } CommandMenu.EnterAtPage(MainMenuItem); return ""; } public static CommandMenuItem<CommandsMenuBase> CreateMainMenu(CommandsMenuBase menuBase, string menuName, Func<string> header = null, Func<string> footer = null) { if (header == null) { header = () => string.Empty; } if (footer == null) { footer = () => string.Empty; } CommandMenuItem<CommandsMenuBase> commandMenuItem = new CommandMenuItem<CommandsMenuBase>(menuBase, menuName) { Header = header, Footer = footer }; AllCommandMenuItems.Add(commandMenuItem); return commandMenuItem; } public static List<CommandMenuItem<CommandsMenuBase>> MakeCommandMenuItems(CommandsMenuBase menuBase, List<CommandManager> commands, string DefaultCategory, CommandMenuItem<CommandsMenuBase> MainMenu) { CommandsMenuBase menuBase2 = menuBase; List<CommandMenuItem<CommandsMenuBase>> commandMenuItems = new List<CommandMenuItem<CommandsMenuBase>>(); Dictionary<CommandManager, string> dictionary = new Dictionary<CommandManager, string>(); if (commands.Count < 1) { return commandMenuItems; } foreach (CommandManager command in commands) { if (string.IsNullOrEmpty(command.Category)) { dictionary.Add(command, DefaultCategory); } else { dictionary.Add(command, command.Category); } } foreach (KeyValuePair<CommandManager, string> category in dictionary) { MenuItem menuItem = MainMenu.NestedMenus.FirstOrDefault((MenuItem c) => Misc.CompareStringsInvariant(c.Name, category.Value)); CommandMenuItem<CommandsMenuBase> cat = menuItem as CommandMenuItem<CommandsMenuBase>; if (cat == null) { cat = new CommandMenuItem<CommandsMenuBase>(menuBase2, category.Value.ToUpperInvariant()); commandMenuItems.Add(cat); cat.SetParentMenu(MainMenu); cat.Header = () => CommandsMenuBase.ConvertHeader(menuBase2.CategoryHeader, cat.Name); } CreateCommandMenuItems(menuBase2, cat, category.Key, ref commandMenuItems); } foreach (CommandMenuItem<CommandsMenuBase> item in commandMenuItems) { if (item.Command == null && item.Parent == null) { item.SetParentMenu(MainMenu); } } AllCommandMenuItems.AddRange(commandMenuItems); return commandMenuItems; } public static void CreateAndSetControlsFooter(CommandsMenuBase menuBase, List<CommandMenuItem<CommandsMenuBase>> MenuItems) { SetMenuItemsFooter(MenuItems, menuBase.Controls); } public static void SetMenuItemsFooter(List<CommandMenuItem<CommandsMenuBase>> MenuItems, Func<string> footer) { foreach (CommandMenuItem<CommandsMenuBase> MenuItem in MenuItems) { MenuItem.Footer = footer; } } public static void CreateCommandMenuItems(CommandsMenuBase menuBase, CommandMenuItem<CommandsMenuBase> parent, CommandManager command, ref List<CommandMenuItem<CommandsMenuBase>> commandMenuItems) { CommandsMenuBase menuBase2 = menuBase; CommandMenuItem<CommandsMenuBase> parent2 = parent; CommandManager command2 = command; CommandMenuItem<CommandsMenuBase> CommandName = TryCreate(menuBase2, command2); commandMenuItems.Add(CommandName); CommandName.Header = () => CommandsMenuBase.ConvertHeader(menuBase2.CommandHeader, parent2.Name, CommandName.Name); CommandName.SetParentMenu(parent2); if (menuBase2.AddKeywordsMenu) { if (!TryGetChild(CommandName, command2.Name + " Keywords", out CommandMenuItem<CommandsMenuBase> item)) { item = new CommandMenuItem<CommandsMenuBase>(menuBase2, command2.Name + " Keywords"); commandMenuItems.Add(item); item.SetParentMenu(CommandName); } item.Header = () => CommandsMenuBase.ConvertHeader(menuBase2.KeywordsHeader, parent2.Name, CommandName.Name); foreach (string keyword in command2.KeywordList) { if (!TryGetChild(item, keyword, out CommandMenuItem<CommandsMenuBase> item2)) { item2 = new CommandMenuItem<CommandsMenuBase>(menuBase2, keyword); commandMenuItems.Add(item2); item2.SetParentMenu(item); item2.Header = () => CommandsMenuBase.ConvertHeader(menuBase2.KeywordsHeader, parent2.Name, CommandName.Name); } } } if (command2.IsEnabled != null && menuBase2.AddInfoMenu) { if (!TryGetChild(CommandName, command2.Name + " Information", out CommandMenuItem<CommandsMenuBase> item3)) { item3 = new CommandMenuItem<CommandsMenuBase>(menuBase2, command2.Name + " Information"); commandMenuItems.Add(item3); item3.SetParentMenu(CommandName); } item3.Header = () => CommandsMenuBase.ConvertHeader(menuBase2.InfoHeader, parent2.Name, CommandName.Name); if (!TryGetChild(item3, ((ConfigEntryBase)command2.IsEnabled.ConfigItem).Description.Description, out CommandMenuItem<CommandsMenuBase> item4)) { item4 = new CommandMenuItem<CommandsMenuBase>(menuBase2, ((ConfigEntryBase)command2.IsEnabled.ConfigItem).Description.Description); commandMenuItems.Add(item4); item4.SetParentMenu(item3); } item4.Header = () => CommandsMenuBase.ConvertHeader(menuBase2.InfoHeader, parent2.Name, CommandName.Name); } if ((!command2.AcceptAdditionalText || !menuBase2.AddRunCommand) && !TryGetChild(CommandName, "Run " + command2.Name, out CommandMenuItem<CommandsMenuBase> item5)) { item5 = new CommandMenuItem<CommandsMenuBase>(menuBase2, "Run " + command2.Name) { LoadPageOnSelect = false }; commandMenuItems.Add(item5); item5.SetParentMenu(CommandName); OpenLib.Events.Events.CustomEvent customEvent = new OpenLib.Events.Events.CustomEvent(); customEvent.AddListener(delegate { menuBase2.ExitPage = command2; menuBase2.ExitMenu(enableInput: true); }); item5.SelectionEvent = customEvent; } } public static CommandMenuItem<CommandsMenuBase> TryCreate(CommandsMenuBase menuBase, CommandManager command) { CommandManager command2 = command; CommandMenuItem<CommandsMenuBase> commandMenuItem = AllCommandMenuItems.FirstOrDefault((CommandMenuItem<CommandsMenuBase> c) => c.Command == command2); if (commandMenuItem != null) { return commandMenuItem; } return new CommandMenuItem<CommandsMenuBase>(menuBase, command2.Name) { Command = command2 }; } public static bool TryGetChild(CommandMenuItem<CommandsMenuBase> Parent, string expectedName, out CommandMenuItem<CommandsMenuBase> item) { CommandMenuItem<CommandsMenuBase> Parent2 = Parent; string expectedName2 = expectedName; item = AllCommandMenuItems.FirstOrDefault((CommandMenuItem<CommandsMenuBase> c) => c.Parent == Parent2 && c.Name == expectedName2); return item != null; } public static bool TryGetCategoryMenuItem(string categoryName, out CommandMenuItem<CommandsMenuBase> match) { string categoryName2 = categoryName; List<CommandMenuItem<CommandsMenuBase>> source = AllCommandMenuItems.FindAll((CommandMenuItem<CommandsMenuBase> x) => x.Parent == MainMenuItem && x.Command == null); match = source.FirstOrDefault((CommandMenuItem<CommandsMenuBase> x) => x.Name == categoryName2); return match != null; } public static void SetCategoryHeader(string categoryName, Func<string> header) { if (TryGetCategoryMenuItem(categoryName, out CommandMenuItem<CommandsMenuBase> match)) { match.Header = header; } } public static void SetCategoryFooter(string categoryName, Func<string> footer) { if (TryGetCategoryMenuItem(categoryName, out CommandMenuItem<CommandsMenuBase> match)) { match.Footer = footer; } } } public class CommandsMenuBase : BetterMenu<CommandsMenuBase> { public bool AddKeywordsMenu = true; public bool AddInfoMenu = true; public bool AddRunCommand = true; public string CommandHeader = "======== {commandName} ========\n\n"; public string KeywordsHeader = "======== {commandName} Keywords ========\n\n"; public string CategoryHeader = "======== {catName>>} COMMANDS ========\n\n"; public string InfoHeader = "====== {commandName} Information ======\n\n"; public const string CategoryName = "catName"; public const string CommandName = "commandName"; public const string ToUpper = ">>"; public const string ToLower = "<<"; public static readonly List<string> AcceptableVariables = new List<string>(4) { "catName", "commandName", ">>", "<<" }; public CommandManager ExitPage; public CommandsMenuBase(string name, Dictionary<Key, Action> MoreMenuActions = null) : base(name, MoreMenuActions) { ExitAction = CustomExitAction; OnEnter.AddListener(delegate { ExitPage = null; }); } public void CustomExitAction() { if (ExitPage != null) { if (LogicHandling.GetDisplayTextFromCommand(ref ExitPage.terminalNode)) { CommonTerminal.LoadNewNode(ExitPage.terminalNode); } else { CommonTerminal.LoadNewNode(CommonTerminal.HomePage); } } else { CommonTerminal.LoadNewNode(CommonTerminal.HomePage); } } public static string ConvertHeader(string query, string catName, string commandName = "") { if (string.IsNullOrEmpty(query)) { return query; } List<string> substrings = Misc.GetSubstrings('{', '}', query); if (substrings.Count == 0) { return query; } foreach (string item in substrings) { string text = item.Replace("{", "").Replace("}", ""); if (Misc.StringContainsInvariant(item, "catName")) { text = text.Replace("catName", catName); } if (Misc.StringContainsInvariant(item, "commandName")) { text = text.Replace("commandName", commandName); } if (Misc.StringContainsInvariant(item, ">>")) { text = text.Replace(">>", "").ToUpperInvariant(); } if (Misc.StringContainsInvariant(item, "<<")) { text = text.Replace("<<", "").ToLowerInvariant(); } query = query.Replace(item, text); } return query; } public string Controls() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append($"\r\n\r\nPage [{leftMenu}] < {CurrentPage}/{Mathf.CeilToInt((float)DisplayMenuItemsOfType.Count / (float)PageSize)} > [{rightMenu}]\r\n"); stringBuilder.Append($"Back: [{leaveMenu}] Select: [{selectMenu}]\r\n"); return stringBuilder.ToString(); } } public class CommandMenuItem<TMenu> : MenuItem<TMenu> where TMenu : BetterMenuBase { private string _name; private bool _showEmpty; private OpenLib.Events.Events.CustomEvent _selection; private List<MenuItem> _nested; public bool isEnabled; public CommandManager Command; public MenuItem CachedParent; public TMenu MenuBase; public override string Name { get { return _name; } set { _name = value; } } public override bool ShowIfEmptyNest { get { return _showEmpty; } set { _showEmpty = value; } } public override OpenLib.Events.Events.CustomEvent SelectionEvent { get { return _selection; } set { _selection = value; } } public override List<MenuItem> NestedMenus { get { return _nested; } set { _nested = value; } } public CommandMenuItem(TMenu betterMenu, string name) { _name = name; _showEmpty = true; _selection = new OpenLib.Events.Events.CustomEvent(); _nested = new List<MenuItem>(); isEnabled = true; MenuBase = betterMenu; base..ctor(betterMenu); } } [Obsolete("Doing away with this style of Menu...")] public class MenuBuild { public static bool isNextEnabled = false; public static int nextCount = 1; public static string currentCategory = ""; public static TerminalMenu currentMenu = null; public static List<TerminalMenu> allMenus = new List<TerminalMenu>(); public static List<TerminalMenuCategory> InitCategories(Dictionary<string, string> CategoryItems) { Loggers.LogDebug("InitCategories START"); List<TerminalMenuCategory> list = new List<TerminalMenuCategory>(); if (CategoryItems.Count < 1) { return list; } foreach (KeyValuePair<string, string> CategoryItem in CategoryItems) { TerminalMenuCategory item = new TerminalMenuCategory { CatName = CategoryItem.Key, CatDescription = CategoryItem.Value }; list.Add(item); } Loggers.LogDebug("InitCategories SUCCESS"); return list; } public static bool ShouldAddCategoryNameToMainMenu(List<TerminalMenuItem> menuItems, string categoryName) { foreach (TerminalMenuItem menuItem in menuItems) { if (menuItem.Category == categoryName) { return true; } } return false; } public static List<TerminalMenuItem> TerminalMenuItems(List<ManagedConfig> managedBools) { List<TerminalMenuItem> list = new List<TerminalMenuItem>(); managedBools.RemoveAll((ManagedConfig m) => m == null); foreach (ManagedConfig managedBool in managedBools) { if (managedBool.menuItem != null && managedBool.KeywordList != null && managedBool.KeywordList.Count > 0) { list.Add(managedBool.menuItem); } } Loggers.LogDebug("\n\n\n"); Loggers.LogDebug($"myMenuItems count: {list.Count}"); Loggers.LogDebug("\n\n\n"); return list; } public static TerminalMenu AssembleMainMenu(string menuName, string keyword, string mainMenuText, List<TerminalMenuCategory> categoryList, List<TerminalMenuItem> menuItems, bool addToOther = false, string menuDescription = "") { TerminalMenu terminalMenu = new TerminalMenu { MenuName = menuName, setKeyword = keyword, Categories = categoryList, MainMenuText = mainMenuText, menuItems = menuItems, currentCategory = "", nextCount = 1, isNextEnabled = false }; string displayText = AssembleMainMenuText(terminalMenu); if (addToOther) { AddingThings.AddBasicCommand(terminalMenu.MenuName + "_main", terminalMenu.setKeyword, displayText, isVerb: false, clearText: true, "other", menuDescription); } else { AddingThings.AddBasicCommand(terminalMenu.MenuName + "_main", terminalMenu.setKeyword, displayText, isVerb: false, clearText: true); } allMenus.Add(terminalMenu); return terminalMenu; } public static bool InMainMenu(TerminalNode terminalNode, TerminalMenu terminalMenu) { if (terminalMenu == null) { Loggers.ERROR("ERROR: OpenLib menu is NULL, most likely failed to create!"); return false; } if (((Object)terminalNode).name.Contains(terminalMenu.MenuName)) { terminalMenu.isActive = true; terminalMenu.nextCount = 1; terminalMenu.currentCategory = ""; Loggers.LogDebug("In main menu of " + terminalMenu.MenuName); return true; } if (terminalMenu.isNextEnabled && terminalMenu.terminalNodes.Contains(terminalNode)) { Loggers.LogDebug("Still in menus but not main, next is enabled"); return false; } terminalMenu.isActive = false; return false; } public static string AssembleMainMenuText(TerminalMenu terminalMenu) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(terminalMenu.MainMenuText + "\r\n\r\n"); if (terminalMenu.Categories.Count > 0) { foreach (TerminalMenuCategory category in terminalMenu.Categories) { stringBuilder.Append("[" + category.CatName.ToUpper() + "]\r\n" + category.CatDescription + "\r\n\r\n"); } } return stringBuilder.ToString(); } public static string AssembleMainMenuText(string MainMenuText, Dictionary<string, string> Categories) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(MainMenuText + "\r\n\r\n"); if (Categories.Count > 0) { foreach (KeyValuePair<string, string> Category in Categories) { stringBuilder.Append("[" + Category.Key.ToUpper() + "]\r\n" + Category.Value + "\r\n\r\n"); } } return stringBuilder.ToString(); } public static void CreateCategoryCommands(TerminalMenu terminalMenu, MainListing yourModListing) { List<Dictionary<string, List<string>>> list = new List<Dictionary<string, List<string>>>(); foreach (TerminalMenuCategory category in terminalMenu.Categories) { Loggers.LogDebug("checking category in terminalMenu.categories"); Dictionary<string, List<string>> item = MakeCategoryList(category, terminalMenu.menuItems); if (!list.Contains(item)) { list.Add(item); } TerminalNode item2 = AddingThings.CreateNode(terminalMenu, category.CatName ?? "", category.CatName.ToLower(), GetFirstInList, yourModListing); terminalMenu.terminalNodes.Add(item2); } terminalMenu.categoryLists = list; TerminalNode item3 = AddingThings.CreateNode(terminalMenu, "nextInMenu", "next", NextInList, yourModListing, isNextPageCommand: true); terminalMenu.terminalNodes.Add(item3); } public static void CreateCategoryFauxCommands(TerminalMenu terminalMenu, MainListing yourModListing) { CreateCategoryFauxCommands(terminalMenu, yourModListing, "more"); } public static void CreateCategoryFauxCommands(TerminalMenu terminalMenu, MainListing yourModListing, string mainWord) { List<Dictionary<string, List<string>>> list = new List<Dictionary<string, List<string>>>(); foreach (TerminalMenuCategory category in terminalMenu.Categories) { Loggers.LogDebug("checking category in terminalMenu.categories"); Dictionary<string, List<string>> item = MakeCategoryList(category, terminalMenu.menuItems); if (!list.Contains(item)) { list.Add(item); } FauxKeyword fauxWord = new FauxKeyword(mainWord, category.CatName, GetFirstInList) { AllowOtherFauxWords = true, requireExact = true }; AddingThings.AddToFauxListing(fauxWord, yourModListing); } terminalMenu.categoryLists = list; FauxKeyword fauxWord2 = new FauxKeyword(mainWord, "next", NextInList) { AllowOtherFauxWords = true }; AddingThings.AddToFauxListing(fauxWord2, yourModListing); } public static void UpdateCategories(TerminalMenu myMenu) { List<Dictionary<string, List<string>>> list = new List<Dictionary<string, List<string>>>(); foreach (TerminalMenuCategory category in myMenu.Categories) { Loggers.LogDebug("checking category in myMenu.categories"); Dictionary<string, List<string>> item = MakeCategoryList(category, myMenu.menuItems); if (!list.Contains(item)) { list.Add(item); } } myMenu.categoryLists = list; } public static List<string> GetCategoryList(string catName, out TerminalMenu menuName) { Loggers.LogDebug("2.1"); List<string> result = new List<string>(); foreach (TerminalMenu allMenu in allMenus) { Loggers.LogDebug("2.2"); if (!allMenu.isActive) { continue; } for (int i = 0; i < allMenu.Categories.Count; i++) { Loggers.LogDebug("2.3"); foreach (KeyValuePair<string, List<string>> item in allMenu.categoryLists[i]) { if (Misc.CompareStringsInvariant(item.Key, catName)) { Loggers.LogDebug("categorylist found!!!"); menuName = allMenu; return item.Value; } } } } Loggers.LogDebug("2.1 FAIL"); menuName = null; return result; } public static Dictionary<string, List<string>> MakeCategoryList(TerminalMenuCategory category, List<TerminalMenuItem> terminalMenuItems) { Loggers.LogDebug("MakeCategoryList START"); string catName = category.CatName; Loggers.LogDebug(catName); List<string> list = new List<string>(); Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>(); Loggers.LogDebug($"count: {terminalMenuItems.Count}"); foreach (TerminalMenuItem terminalMenuItem in terminalMenuItems) { Loggers.LogDebug("checking " + terminalMenuItem.ItemName); if (Misc.CompareStringsInvariant(terminalMenuItem.Category, catName)) { list.Add("> " + CommonStringStuff.GetKeywordsForMenuItem(terminalMenuItem.itemKeywords) + "\r\n" + terminalMenuItem.itemDescription + "\r\n"); Loggers.LogDebug(CommonStringStuff.GetKeywordsForMenuItem(terminalMenuItem.itemKeywords) + " added"); Loggers.LogDebug(terminalMenuItem.itemDescription + " added too!"); } } Loggers.LogDebug("setting catName list"); dictionary.Add(catName, list); Loggers.LogDebug("MakeCategoryList END"); return dictionary; } public static string NextInList() { if (!isNextEnabled) { return "Not currently in any menus...\r\n\r\n"; } Loggers.LogDebug("currentCategory = " + currentCategory); nextCount++; GetCategoryFromString(currentCategory); TerminalMenu menuName; List<string> categoryList = GetCategoryList(currentCategory, out menuName); if (menuName == null) { return "ERROR: Unable to get current category!\r\n\r\n"; } menuName.isActive = true; menuName.nextCount = nextCount; menuName.currentCategory = currentCategory; string nextPage = CommonStringStuff.GetNextPage(categoryList, currentCategory, 4, nextCount, out isNextEnabled); Loggers.LogDebug($"currentCategory:{currentCategory} nextCount: {nextCount} isNextEnabled: {isNextEnabled}"); menuName.isNextEnabled = isNextEnabled; return nextPage; } public static string GetFirstInList() { Loggers.LogDebug("1"); nextCount = 1; string text = Plugin.instance.Terminal.screenText.text; int textAdded = Plugin.instance.Terminal.textAdded; int length = text.Length; int num = length - textAdded; string input = text.Substring(num, length - num); currentCategory = GetCategoryFromString(input); Loggers.LogDebug("currentCategory detected as: [" + currentCategory + "]"); Loggers.LogDebug("2"); TerminalMenu menuName; List<string> categoryList = GetCategoryList(currentCategory, out menuName); menuName.isActive = true; menuName.nextCount = nextCount; menuName.currentCategory = currentCategory; Loggers.LogDebug("3"); string nextPage = CommonStringStuff.GetNextPage(categoryList, currentCategory, 4, 1, out isNextEnabled); menuName.isNextEnabled = isNextEnabled; Loggers.LogDebug("4"); return nextPage; } public static string GetCategoryFromString(string input) { string input2 = input; Loggers.LogDebug("Getting Category from string: [" + input2 + "]"); foreach (TerminalMenu allMenu in allMenus) { if (allMenu.categoryLists.Any((Dictionary<string, List<string>> c) => c.Any((KeyValuePair<string, List<string>> d) => Misc.CompareStringsInvariant(d.Key, input2)))) { Loggers.LogDebug("detected menu with categoryList containing string " + input2 + "!!"); allMenu.isActive = true; int index = allMenu.categoryLists.FindIndex((Dictionary<string, List<string>> c) => c.Any<KeyValuePair<string, List<string>>>((KeyValuePair<string, List<string>> d) => Misc.CompareStringsInvariant(d.Key, input2))); return allMenu.categoryLists[index].First<KeyValuePair<string, List<string>>>((KeyValuePair<string, List<string>> d) => Misc.CompareStringsInvariant(d.Key, input2)).Key; } Loggers.LogDebug("menu does not contain string " + input2); allMenu.isActive = false; } return "CategoryNameFailure"; } public static string GetCategoryFromNode(TerminalNode givenNode) { Loggers.LogDebug("1.1"); if ((Object)(object)givenNode == (Object)null) { Loggers.ERROR("GetCategoryFromNode: givenNode is null!!!!"); return ""; } foreach (TerminalMenu allMenu in allMenus) { if (!allMenu.terminalNodePerCategory.ContainsValue(givenNode)) { Loggers.LogDebug("menu does not contain node " + ((Object)givenNode).name); allMenu.isActive = false; continue; } foreach (KeyValuePair<string, TerminalNode> item in allMenu.terminalNodePerCategory) { if ((Object)(object)item.Value == (Object)(object)givenNode) { Loggers.LogDebug("FOUND NODE AND PAIR " + item.Key); allMenu.isActive = true; return item.Key; } } } Loggers.ERROR("GetCategoryFromNode FAILURE: COULD NOT FIND NODE???"); return ""; } public static TerminalMenuItem MakeMenuItem(ManagedConfig managedBool) { if (managedBool.categoryText != "") { return new TerminalMenuItem { itemKeywords = managedBool.KeywordList, itemDescription = managedBool.configDescription, ItemName = managedBool.ConfigItemName, Category = managedBool.categoryText }; } return null; } public static TerminalMenuItem MakeMenuItem(string categoryText, List<string> keywordList, string configDescription, string itemName) { if (categoryText != "") { return new TerminalMenuItem { itemKeywords = keywordList, itemDescription = configDescription, ItemName = itemName, Category = categoryText }; } Loggers.WARNING("Empty categoryText, Unable to create TerminalMenuItem! (null return)"); return null; } } [Obsolete("This style of menu will be deleted in next major update to library, once all mods are confirmed not using this")] public class TerminalMenu { public string MenuName = string.Empty; public string MainMenuText = string.Empty; public string setKeyword = string.Empty; public List<TerminalMenuCategory> Categories = new List<TerminalMenuCategory>(); public List<TerminalMenuItem> menuItems = new List<TerminalMenuItem>(); public Dictionary<string, TerminalNode> terminalNodePerCategory = new Dictionary<string, TerminalNode>(); public List<Dictionary<string, List<string>>> categoryLists = new List<Dictionary<string, List<string>>>(); public List<TerminalNode> terminalNodes = new List<TerminalNode>(); public string currentCategory { get; internal set; } = string.Empty; public bool isActive { get; internal set; } public bool isNextEnabled { get; internal set; } public int nextCount { get; internal set; } = 1; public void Delete() { MenuBuild.allMenus.Remove(this); menuItems.Clear(); categoryLists.Clear(); Categories.Clear(); terminalNodePerCategory.Clear(); terminalNodes.Clear(); } } public class TerminalMenuItem { public string ItemName = string.Empty; public string Category = string.Empty; public List<string> itemKeywords; public string itemDescription = string.Empty; public void Delete() { itemDescription = ""; Category = ""; ItemName = ""; if (itemKeywords.Count > 0) { itemKeywords.Clear(); } } } public class TerminalMenuCategory { public string CatName { get; set; } public string CatDescription { get; set; } } } namespace OpenLib.InteractiveMenus { public abstract class BetterMenuBase { public List<MenuItem> AllMenuItemsOfType = new List<MenuItem>(); public abstract string Name { get; set; } public abstract Type MenuType { get; } public abstract object BoxedValue { get; } public abstract bool InMenu { get; set; } public abstract OpenLib.Events.Events.CustomEvent InputEvent { get; set; } public abstract OpenLib.Events.Events.CustomEvent ExitTerminal { get; set; } public abstract MenuItem MainMenu { get; set; } public List<T> GetMenuItemsOfType<T>() where T : MenuItem { return AllMenuItemsOfType.OfType<T>().ToList(); } public override string ToString() { return Name; } } public class BetterMenu<T> : BetterMenuBase { [CompilerGenerated] private sealed class <DelayUpdateText>d__68 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public BetterMenu<T> <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayUpdateText>d__68(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown int num = <>1__state; BetterMenu<T> betterMenu = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; if (!betterMenu.AcceptAnything) { betterMenu.MenuNode.displayText = betterMenu.GetPageText(); } if (string.IsNullOrEmpty(betterMenu.MenuNode.displayText)) { betterMenu.ExitInTerminal(); } <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 2; return true; case 2: <>1__state = -1; CommonTerminal.LoadNewNode(betterMenu.MenuNode); <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 3; return true; case 3: <>1__state = -1; if (betterMenu.AdjustScrollInMenu) { betterMenu.ScrollAdjust(); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <MenuClose>d__78 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public BetterMenu<T> <>4__this; public bool enableInput; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <MenuClose>d__78(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown int num = <>1__state; BetterMenu<T> betterMenu = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; betterMenu.OnExit.Invoke(); <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; betterMenu.InMenu = false; betterMenu.AcceptAnything = false; CollectionExtensions.Do<MenuItem>((IEnumerable<MenuItem>)betterMenu.AllMenuItemsOfType, (Action<MenuItem>)delegate(MenuItem x) { x.IsActive = false; }); CommonTerminal.ChangeCaretColor(CommonTerminal.CaretOriginal, saveOriginal: false); <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 2; return true; case 2: <>1__state = -1; if (betterMenu.ExitAction == null) { CommonTerminal.LoadNewNode(CommonTerminal.HomePage); } else { betterMenu.ExitAction(); } if (enableInput) { Plugin.instance.Terminal.screenText.ActivateInputField(); ((Selectable)Plugin.instance.Terminal.screenText).interactable = true; } betterMenu.OnExitComplete.Invoke(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <MenuStart>d__79 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public BetterMenu<T> <>4__this; public MenuItem Start; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <MenuStart>d__79(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown int num = <>1__state; BetterMenu<T> betterMenu = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; if (betterMenu.InMenu) { return false; } if (Start == null) { Start = betterMenu.MainMenu; } Start.IsActive = true; betterMenu.AcceptAnything = false; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; betterMenu.InMenu = true; CommonTerminal.ChangeCaretColor(CommonTerminal.transparent, saveOriginal: true); betterMenu.ActiveSelection = 0; betterMenu.CurrentPage = 1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 2; return true; case 2: <>1__state = -1; Plugin.instance.Terminal.screenText.DeactivateInputField(false); ((Selectable)Plugin.instance.Terminal.screenText).interactable = false; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 3; return true; case 3: <>1__state = -1; Start.SelectionEvent?.Invoke(); if (Start.LoadPageOnSelect) { betterMenu.LoadPage.Invoke(); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private string _name = ""; private bool _inMenu; private MenuItem _mainMenu; private OpenLib.Events.Events.CustomEvent _inputEvent = new OpenLib.Events.Events.CustomEvent(); private OpenLib.Events.Events.CustomEvent _exitEvent = new OpenLib.Events.Events.CustomEvent(); public MenuItem CurrentMenuItem; public TerminalNode MenuNode; public Action ExitAction; public OpenLib.Events.Events.CustomEvent OnExit = new OpenLib.Events.Events.CustomEvent(); public OpenLib.Events.Events.CustomEvent OnExitComplete = new OpenLib.Events.Events.CustomEvent(); public OpenLib.Events.Events.CustomEvent OnEnter = new OpenLib.Events.Events.CustomEvent(); public OpenLib.Events.Events.CustomEvent OnLoad = new OpenLib.Events.Events.CustomEvent(); public OpenLib.Events.Events.CustomEvent LoadPage = new OpenLib.Events.Events.CustomEvent(); public OpenLib.Events.Events.CustomEvent UpMenuEvent = new OpenLib.Events.Events.CustomEvent(); public OpenLib.Events.Events.CustomEvent DownMenuEvent = new OpenLib.Events.Events.CustomEvent(); public OpenLib.Events.Events.CustomEvent LeftMenuEvent = new OpenLib.Events.Events.CustomEvent(); public OpenLib.Events.Events.CustomEvent RightMenuEvent = new OpenLib.Events.Events.CustomEvent(); public OpenLib.Events.Events.CustomEvent AcceptAnyKeyEvent = new OpenLib.Events.Events.CustomEvent(); public OpenLib.Events.Events.CustomEventRef<List<MenuItem>> MenuItemList = new OpenLib.Events.Events.CustomEventRef<List<MenuItem>>(); public Key upMenu = (Key)63; public Key downMenu = (Key)64; public Key leftMenu = (Key)61; public Key rightMenu = (Key)62; public Key selectMenu = (Key)2; public Key leaveMenu = (Key)65; public Dictionary<Key, Action> MainActions = new Dictionary<Key, Action>(); public Dictionary<Key, Action> OtherActions = new Dictionary<Key, Action>(); public bool IsMenuEnabled; public bool AcceptAnything; public bool AdjustScrollInMenu; private int _activeIndex; private int _endIndex; public int CurrentPage = 1; public int PageSize = 8; public List<MenuItem> DisplayMenuItemsOfType = new List<MenuItem>(); public override string Name { get { return _name; } set { _name = value; } } public override Type MenuType => typeof(T); public override object BoxedValue => this; public override bool InMenu { get { return _inMenu; } set { _inMenu = value; } } public override MenuItem MainMenu { get { return _mainMenu; } set { _mainMenu = value; } } public override OpenLib.Events.Events.CustomEvent InputEvent { get { return _inputEvent; } set { _inputEvent = value; } } public override OpenLib.Events.Events.CustomEvent ExitTerminal { get { return _exitEvent; } set { _exitEvent = value; } } public int ActiveSelection { get { return _activeIndex; } set { _activeIndex = value; } } public int EndIndex { get { return _endIndex; } set { _endIndex = value; } } public override string ToString() { return Name; } public BetterMenu(string name, Dictionary<Key, Action> MoreMenuActions = null) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) if (!TerminalUpdatePatch.usePatch) { TerminalUpdatePatch.usePatch = true; } Name = name; LoadPage.AddListener(Load); InputEvent.AddListener(HandleInput); ExitTerminal.AddListener(ExitTerminalLeave); AcceptAnyKeyEvent.AddListener(DefaultAcceptAnything); UpdateMainActions(); if (MoreMenuActions != null) { OtherActions = MoreMenuActions; } MenusContainer.AllMenus.Add(this); } public void ReplaceEventAction(OpenLib.Events.Events.CustomEvent eventName, OpenLib.Events.Events.CustomEvent.Event newMethod) { if (eventName.Listeners > 0) { eventName.RemoveAllListeners(); } eventName.AddListener(newMethod); } public void AddToOtherActions(Key key, Action action) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (OtherActions.ContainsKey(key)) { OtherActions.Remove(key); } OtherActions.Add(key, action); } public void UpdateMainActions() { //IL_0012: 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) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) MainActions.Clear(); MainActions.Add(upMenu, UpMenu); MainActions.Add(downMenu, DownMenu); MainActions.Add(leftMenu, LeftMenu); MainActions.Add(rightMenu, RightMenu); MainActions.Add(selectMenu, SelectInMenu); MainActions.Add(leaveMenu, ExitInTerminal); } internal void HandleInput() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) if (!InMenu || (Object)(object)MenuNode == (Object)null) { return; } if (AcceptAnything && AcceptAnyKeyEvent.HasListeners) { AcceptAnyKeyEvent.Invoke(); return; } Key? main = MainActions.FirstOrDefault<KeyValuePair<Key, Action>>((KeyValuePair<Key, Action> x) => ((ButtonControl)Keyboard.current[x.Key]).isPressed).Key; if (main.HasValue) { MainActions.FirstOrDefault<KeyValuePair<Key, Action>>((KeyValuePair<Key, Action> x) => (Key?)x.Key == main).Value?.Invoke(); } if (OtherActions.Count == 0) { return; } Key? other = OtherActions.FirstOrDefault<KeyValuePair<Key, Action>>((KeyValuePair<Key, Action> x) => ((ButtonControl)Keyboard.current[x.Key]).isPressed).Key; if (other.HasValue) { OtherActions.FirstOrDefault<KeyValuePair<Key, Action>>((KeyValuePair<Key, Action> x) => (Key?)x.Key == other).Value?.Invoke(); } } public void Load() { MenuItem menuItem = AllMenuItemsOfType.FirstOrDefault((MenuItem x) => x.IsActive); if (menuItem == null) { Loggers.ERROR("Unable to load current page! Nothing is active!"); return; } if ((Object)(object)MenuNode == (Object)null) { Loggers.ERROR("NRE detected at MenuNode! This menu did not set it's terminal node correctly!"); return; } menuItem.OnPageLoad?.Invoke(); OnLoad.Invoke(); ((MonoBehaviour)Plugin.instance.Terminal).StartCoroutine(DelayUpdateText()); } public void DefaultAcceptAnything() { AcceptAnything = false; MenuItem menuItem = AllMenuItemsOfType.FirstOrDefault((MenuItem x) => x.IsActive); if (menuItem.NestedMenus.Count == 0) { ExitInTerminal(); } else { LoadPage.Invoke(); } } [IteratorStateMachine(typeof(BetterMenu<>.<DelayUpdateText>d__68))] private IEnumerator DelayUpdateText() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayUpdateText>d__68(0) { <>4__this = this }; } private void ScrollAdjust() { float num = ((float)EndIndex - (float)ActiveSelection) / (float)EndIndex; if (num >= 1f) { ((MonoBehaviour)Plugin.instance.Terminal).StartCoroutine(Plugin.instance.Terminal.forceScrollbarUp()); } else if (num == 0f) { ((MonoBehaviour)Plugin.instance.Terminal).StartCoroutine(Plugin.instance.Terminal.forceScrollbarDown()); } else { Plugin.instance.Terminal.scrollBarVertical.value = num; } } public string GetPageText() { StringBuilder stringBuilder = new StringBuilder(); CurrentMenuItem = AllMenuItemsOfType.FirstOrDefault((MenuItem x) => x.IsActive); if (CurrentMenuItem == null) { Loggers.WARNING("Unable to get current menu page!!"); return ""; } stringBuilder.Append(CurrentMenuItem.Header() ?? ""); DisplayMenuItemsOfType = AllMenuItemsOfType.FindAll((MenuItem x) => CurrentMenuItem.NestedMenus.Contains(x)); DisplayMenuItemsOfType.RemoveAll((MenuItem x) => !x.ShowIfEmptyNest && x.NestedMenus.Count == 0); if (DisplayMenuItemsOfType.Count == 0) { stringBuilder.Append("\r\n\r\nThis menu listing is currently empty :(\r\n"); if (CurrentMenuItem != null) { stringBuilder.Append(CurrentMenuItem.Footer() ?? ""); } return stringBuilder.ToString(); } CurrentMenuItem.AdjustNestedMenuList.Invoke(ref DisplayMenuItemsOfType); CurrentPage = Misc.CycleIndex(CurrentPage, 1, Mathf.CeilToInt((float)DisplayMenuItemsOfType.Count / (float)PageSize)); int num = (CurrentPage - 1) * PageSize; int num3 = (EndIndex = Mathf.Min(num + PageSize, DisplayMenuItemsOfType.Count)); ActiveSelection = Misc.CycleIndex(ActiveSelection, num, num3 - 1); Loggers.LogDebug($"{Name} menu activeselection: {ActiveSelection}"); CollectionExtensions.DoIf<MenuItem>((IEnumerable<MenuItem>)DisplayMenuItemsOfType, (Func<MenuItem, bool>)((MenuItem x) => x.OnPageLoad != null), (Action<MenuItem>)delegate(MenuItem x) { x.OnPageLoad(); }); for (int i = num; i < num3; i++) { string text = string.Empty; if (ActiveSelection == i) { text = ">>> "; } text += DisplayMenuItemsOfType[i].Prefix; text += DisplayMenuItemsOfType[i].Name; text += DisplayMenuItemsOfType[i].Suffix; stringBuilder.Append(text + "\n"); } int num4 = num3 - num - PageSize; if (num4 < 0) { for (int j = num4; j < 0; j++) { stringBuilder.Append('\n'); } } if (CurrentMenuItem == null) { Loggers.WARNING("Unable to select current menu item!!"); } else { stringBuilder.Append(CurrentMenuItem.Footer() ?? ""); } return stringBuilder.ToString(); } public void SelectInMenu() { if (DisplayMenuItemsOfType.Count == 0) { return; } MenuItem menuItem = AllMenuItemsOfType.FirstOrDefault((MenuItem x) => x.IsActive); if (menuItem == null) { Loggers.WARNING("Unable to select current menu item!!"); return; } Loggers.LogDebug("Selecting Nested Menu Item!"); MenuItem menuItem2 = DisplayMenuItemsOfType[ActiveSelection]; menuItem2.SelectionEvent?.Invoke(); if (menuItem2.NestedMenus.Count > 0) { Loggers.LogDebug("Setting to nested menu item!"); CurrentPage = 1; ActiveSelection = 0; CollectionExtensions.Do<MenuItem>((IEnumerable<MenuItem>)AllMenuItemsOfType, (Action<MenuItem>)delegate(MenuItem x) { x.IsActive = false; }); menuItem2.IsActive = true; } if (menuItem2.LoadPageOnSelect) { LoadPage.Invoke(); } } public void AddMenuItem(MenuItem menuItem) { if (!AllMenuItemsOfType.Contains(menuItem)) { AllMenuItemsOfType.Add(menuItem); } } public void ExitInTerminal() { MenuItem menuItem = AllMenuItemsOfType.FirstOrDefault((MenuItem x) => x.IsActive); if (menuItem == null) { Loggers.WARNING("Unable to get current menu page!!"); } if (menuItem == null) { ExitMenu(enableInput: true); } else if (menuItem.Parent != null) { Loggers.LogDebug("Setting to ParentMenu!"); ActiveSelection = 0; CurrentPage = 1; menuItem.IsActive = false; menuItem.Parent.IsActive = true; LoadPage.Invoke(); } else { ExitMenu(enableInput: true); } } public void ExitTerminalLeave() { ExitMenu(enableInput: false); } public void ExitMenu(bool enableInput) { ((MonoBehaviour)Plugin.instance.Terminal).StartCoroutine(MenuClose(enableInput)); } public void EnterAtPage(MenuItem menuItem) { OnEnter.Invoke(); ((MonoBehaviour)Plugin.instance.Terminal).StartCoroutine(MenuStart(menuItem)); } public void EnterMenu() { OnEnter.Invoke(); ((MonoBehaviour)Plugin.instance.Terminal).StartCoroutine(MenuStart()); } [IteratorStateMachine(typeof(BetterMenu<>.<MenuClose>d__78))] internal IEnumerator MenuClose(bool enableInput) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <MenuClose>d__78(0) { <>4__this = this, enableInput = enableInput }; } [IteratorStateMachine(typeof(BetterMenu<>.<MenuStart>d__79))] internal IEnumerator MenuStart(MenuItem Start = null) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <MenuStart>d__79(0) { <>4__this = this, Start = Start }; } public void UpMenu() { if (InMenu) { ActiveSelection--; UpMenuEvent.Invoke(); LoadPage.Invoke(); } } public void DownMenu() { if (InMenu) { ActiveSelection++; DownMenuEvent.Invoke(); LoadPage.Invoke(); } } public void LeftMenu() { if (InMenu) { CurrentPage--; LeftMenuEvent.Invoke(); LoadPage.Invoke(); } } public void RightMenu() { if (InMenu) { CurrentPage++; RightMenuEvent.Invoke(); LoadPage.Invoke(); } } } public abstract class MenuItem<TMenu> : MenuItem where TMenu : BetterMenuBase { public new TMenu BetterMenu => (TMenu)base.BetterMenu; protected MenuItem(TMenu betterMenu) : base(betterMenu) { } } public abstract class MenuItem { private string _prefix = string.Empty; private string _suffix = string.Empty; private bool _isActive; private bool _LoadOnSelect = true; private MenuItem _parent; private Func<string> _header = () => string.Empty; private Func<string> _footer = () => string.Empty; protected BetterMenuBase? BetterMenu { get; } public abstract string Name { get; set; } public abstract bool ShowIfEmptyNest { get; set; } public virtual string Prefix { get { return _prefix; } set { _prefix = value; } } public virtual string Suffix { get { return _suffix; } set { _suffix = value; } } public virtual bool IsActive { get { return _isActive; } set { _isActive = value; } } public virtual bool LoadPageOnSelect { get { return _LoadOnSelect; } set { _LoadOnSelect = value; } } public virtual Action OnPageLoad { get; set; } public abstract OpenLib.Events.Events.CustomEvent SelectionEvent { get; set; } public virtual OpenLib.Events.Events.CustomEventRef<List<MenuItem>> AdjustNestedMenuList { get; set; } = new OpenLib.Events.Events.CustomEventRef<List<MenuItem>>(); public abstract List<MenuItem> NestedMenus { get; set; } public virtual MenuItem Parent { get { return _parent; } set { _parent = value; } } public virtual Func<string> Header { get { return _header; } set { _header = value; } } public virtual Func<string> Footer { get { return _footer; } set { _footer = value; } } [Obsolete("Added for compatibility with older versions, please use the constructor with the bettermenubase")] protected MenuItem() { Loggers.LogInfo("MenuItem created from obsolete constructor! Please use constructor with BetterMenuBase!"); } protected MenuItem(BetterMenuBase betterMenu) { if (betterMenu == null) { Loggers.ERROR("Unable to assign menu item to NULL betterMenu!"); return; } BetterMenu = betterMenu; betterMenu.AllMenuItemsOfType.Add(this); } public override string ToString() { return Name; } public virtual void SetParentMenu(MenuItem parent) { Parent?.NestedMenus.RemoveAll((MenuItem m) => m == this); Parent = parent; if (parent != null && !parent.NestedMenus.Contains(this)) { parent.NestedMenus.Add(this); } } public virtual void AddNestedItem(MenuItem child) { if (child != null) { child.Parent = this; if (!NestedMenus.Contains(child)) { NestedMenus.Add(child); } } } public virtual void RemoveFromParent() { if (Parent != null) { Parent.NestedMenus.RemoveAll((MenuItem m) => m == this); Parent = null; } } public virtual void RemoveChild(MenuItem child) { if (child != null) { if (child.Parent != null) { child.Parent = null; } NestedMenus.Remove(child); } } } public class MenusContainer { public static List<BetterMenuBase> AllMenus = new List<BetterMenuBase>(); private static int _activeIndex = 0; public static int StaticIndex { get { return _activeIndex; } set { _activeIndex = value; } } public static bool TryGetMenu(string menuName, out BetterMenuBase item) { string menuName2 = menuName; item = AllMenus.FirstOrDefault((BetterMenuBase x) => x.Name == menuName2); if (item == null) { return false; } return true; } public static bool AnyMenuActive() { if (AllInteractiveMenus.AnyInteractiveMenuActive()) { return true; } bool flag = false; if (Plugin.instance.ITAPI) { flag = InteractiveTermAPI.ApplicationInUse(); } if (flag) { return true; } if (AllMenus.Count == 0) { return false; } if (AllMenus.Any((BetterMenuBase x) => x.InMenu)) { return true; } return false; } public static bool AnyBetterMenuActive() { if (AllMenus.Count == 0) { return false; } if (AllMenus.Any((BetterMenuBase x) => x.InMenu)) { return true; } return false; } public static bool AnyOpenLibMenuActive() { if (AllInteractiveMenus.AnyInteractiveMenuActive()) { return true; } if (AllMenus.Count == 0) { return false; } if (AllMenus.Any((BetterMenuBase x) => x.InMenu)) { return true; } return false; } } } namespace OpenLib.Examples { internal class Examples { public static void TestMyTAO() { TerminalCodeObject<PlayerControllerB> terminalCodeObject = new TerminalCodeObject<PlayerControllerB>(StartOfRound.Instance.localPlayerController, ((Component)StartOfRound.Instance.localPlayerController).gameObject, dynamicMapIcon: true); terminalCodeObject.OnCodeUsed.AddListener((UnityAction<TerminalAccessibleObject, PlayerControllerB>)TestCodeEvent); terminalCodeObject.OnCooldownComplete.AddListener((UnityAction<TerminalAccessibleObject, PlayerControllerB>)TestCoolDownEvent); terminalCodeObject.SetTimers(10f, 0f); } public static void TestCodeEvent(TerminalAccessibleObject Code, PlayerControllerB playerOfCode) { if ((Object)(object)Code == (Object)null) { Loggers.WARNING("Code is NULL!"); return; } Plugin.Log.LogDebug((object)$"{Code.objectCode} activated! Status: isPoweredOn - {Code.isPoweredOn}, Cooldown: {Code.inCooldown}, Cooldown Timer: {Code.currentCooldownTimer}"); playerOfCode.drunkness = 20f; } public static void TestCoolDownEvent(TerminalAccessibleObject Code, PlayerControllerB playerOfCode) { if ((Object)(object)Code == (Object)null) { Loggers.WARNING("Code is NULL!"); return; } Plugin.Log.LogDebug((object)$"{Code.objectCode} cooldown reached! Status: isPoweredOn - {Code.isPoweredOn}, Cooldown: {Code.inCooldown}, Cooldown Timer: {Code.currentCooldownTimer}"); playerOfCode.drunkness = 0f; } } } namespace OpenLib.Events { public static class EventManager { public static Events.CustomEvent TerminalDisable = new Events.CustomEvent(); public static Events.CustomEvent TerminalStart = new Events.CustomEvent(); public static Events.CustomEvent TerminalBeginUsing = new Events.CustomEvent(); public static Events.CustomEvent TerminalQuit = new Events.CustomEvent(); public static Events.CustomEvent<Terminal> TerminalAwake = new Events.CustomEvent<Terminal>(); public static Events.CustomEvent<TerminalNode> TerminalLoadIfAffordable = new Events.CustomEvent<TerminalNode>(); public static Events.TerminalNodeEvent TerminalParseSent = new Events.TerminalNodeEvent(); public static Events.CustomEvent<TerminalNode> TerminalLoadNewNode = new Events.CustomEvent<TerminalNode>(); public static Events.TerminalNodeEvent GetNewDisplayText = new Events.TerminalNodeEvent(); public static Events.CustomEvent StartOfRoundAwake = new Events.CustomEvent(); public static Events.CustomEvent StartOfRoundStart = new Events.CustomEvent(); public static Events.CustomEvent StartOfRoundStartGame = new Events.CustomEvent(); public static Events.CustomEvent StartOfRoundChangeLevel = new Events.CustomEvent(); public static Events.CustomEvent ShipReset = new Events.CustomEvent(); public static Events.CustomEvent SetBigDoorCodes = new Events.CustomEvent(); public static Events.CustomEvent SpawnMapObjects = new Events.CustomEvent(); public static Events.CustomEvent NextDayEvent = new Events.CustomEvent(); public static Events.CustomEvent OnShipLandedMiscPatch = new Events.CustomEvent(); public static Events.CustomEvent ShipLeft = new Events.CustomEvent(); public static Events.CustomEvent NewQuota = new Events.CustomEvent(); public static Events.CustomEvent PlayerSpawn = new Events.CustomEvent(); public static Events.CustomEvent PlayerEmote = new Events.CustomEvent(); public static Events.CustomEvent<ShipTeleporter> TeleporterAwake = new Events.CustomEvent<ShipTeleporter>(); public static Events.CustomEvent NormalTPFound = new Events.CustomEvent(); public static Events.CustomEvent InverseTPFound = new Events.CustomEvent(); public static Events.CustomEvent GameNetworkManagerStart = new Events.CustomEvent(); public static Events.CustomEvent OnClientConnect = new Events.CustomEvent(); public static Events.CustomEvent SpecateNextPlayer = new Events.CustomEvent(); public static Events.CustomEvent TerminalDelayStart = new Events.CustomEvent(); public static Events.CustomEvent SetTerminalInUse = new Events.CustomEvent(); public static Events.CustomEvent TerminalKeyPressed = new Events.CustomEvent(); public static Events.CustomEvent TerminalMenuKeyPressed = new Events.CustomEvent(); public static Events.CustomEvent PlayerIsInShip = new Events.CustomEvent(); public static Events.CustomEvent PlayerIsDead = new Events.CustomEvent(); public static Events.CustomEvent SpecatingPlayerIsInShip = new Events.CustomEvent(); public static Events.CustomEvent<GameObject> AutoParentEvent = new Events.CustomEvent<GameObject>(); public static Events.CustomEvent<GameObject> NetworkObjectSpawn = new Events.CustomEvent<GameObject>(); } public class Events { public class CustomEvent<T> { public delegate void ParameterEvent(T param); public bool HasListeners => Listeners != 0; public int Listeners { get; internal set; } private event ParameterEvent OnParameterEvent; public void Invoke(T param) { this.OnParameterEvent?.Invoke(param); } public void AddListener(ParameterEvent listener) { OnParameterEvent += listener; Listeners++; } public void RemoveListener(ParameterEvent listener) { OnParameterEvent -= listener; Listeners--; } } public class CustomEventRef<T> { public delegate void ParameterEvent(ref T param); public bool HasListeners => Listeners != 0; public int Listeners { get; internal set; } private event ParameterEvent OnParameterEvent; public void Invoke(ref T param) { this.OnParameterEvent?.Invoke(ref param); } public void AddListener(ParameterEvent listener) { OnParameterEvent += listener; Listeners++; } public void RemoveListener(ParameterEvent listener) { OnParameterEvent -= listener; Listeners--; } } public class TerminalNodeEvent { public delegate TerminalNode Event(ref TerminalNode original); public bool HasListeners => Listeners != 0; public int Listeners { get; internal set; } private event Event OnEvent; public TerminalNode NodeInvoke(ref TerminalNode original) { return this.OnEvent?.Invoke(ref original); } public void AddListener(Event listener) { OnEvent += listener; Listeners++; } public void RemoveListener(Event listener) { OnEvent -= listener; Listeners--; } } public class TerminalKeywordEvent { public delegate TerminalKeyword Event(ref TerminalKeyword original); public bool HasListeners => Listeners != 0; public int Listeners { get; internal set; } private event Event OnEvent; public TerminalKeyword WordInvoke(ref TerminalKeyword original) { return this.OnEvent?.Invoke(ref original); } public void AddListener(Event listener) { OnEvent += listener; Listeners++; } public void RemoveListener(Event listener) { OnEvent -= listener; Listeners--; } } public class CustomEvent { public delegate void Event(); public bool HasListeners => Listeners != 0; public int Listeners { get; internal set; } private event Event OnEvent; public void Invoke() { if (HasListeners) { this.OnEvent?.Invoke(); } } public void AddListener(Event listener) { OnEvent += listener; Listeners++; } public void RemoveListener(Event listener) { OnEvent -= listener; Listeners--; } public void RemoveAllListeners() { if (Listeners != 0) { List<Delegate> list = this.OnEvent.GetInvocationList().ToList(); CollectionExtensions.Do<Delegate>((IEnumerable<Delegate>)list, (Action<Delegate>)delegate(Delegate x) { OnEvent -= (Event)x; }); Listeners = 0; } } } } public class EventUsage { public static List<ConfigFile> configsToReload = new List<ConfigFile>(); internal static void Subscribers() { EventManager.TerminalAwake.AddListener(OnTerminalAwake); EventManager.TerminalStart.AddListener(OnTerminalStart); EventManager.TerminalQuit.AddListener(OnTerminalQuit); EventManager.TerminalDisable.AddListener(OnTerminalDisable); EventManager.TerminalLoadNewNode.AddListener(OnLoadNewNode); EventManager.TerminalParseSent.AddListener(OnParseSent); EventManager.TerminalBeginUsing.AddListener(OnUsingTerminal); EventManager.GameNetworkManagerStart.AddListener(StartGame.OnGameStart); EventManager.TeleporterAwake.AddListener(Teleporter.CheckTeleporterTypeAndAssign); EventManager.TerminalMenuKeyPressed.AddListener(OnMenuKeyPress); } private static void OnTerminalAwake(Terminal instance) { Plugin.instance.Terminal = instance; Loggers.LogInfo("Setting Plugin.instance.Terminal"); CommandRegistry.GetCommandsToAdd(ConfigSetup.defaultManaged, ConfigSetup.defaultListing); CommandManager.AddAllCommandsToTerminal(); } private static void OnTerminalDisable() { if (Plugin.instance.OpenBodyCamsMod) { OpenBodyCamFuncs.ResidualCamsCheck(); } RemoveThings.OnTerminalDisable(); TerminalStart.delayStartEnum = false; ListManagement.ClearLists(); CollectionExtensions.Do<CommandManager>((IEnumerable<CommandManager>)Plugin.AllCommands, (Action<CommandManager>)delegate(CommandManager x) { x.TerminalDisabled(); }); foreach (ConfigFile item in configsToReload) { Loggers.LogDebug("reloading config from list"); item.Save(); item.Reload(); } configsToReload.Clear(); } private static void OnTerminalStart() { TerminalStart.TerminalStartGroupDelay(); } private static void OnTerminalQuit() { if (MenusContainer.AllMenus.Count != 0) { MenusContainer.AllMenus.FirstOrDefault((BetterMenuBase x) => x.InMenu)?.ExitTerminal.Invoke(); } } internal static void OnMenuKeyPress() { if (AllInteractiveMenus.AllMenus.Count != 0) { AllInteractiveMenus.AllMenus.FirstOrDefault((InteractiveMenu x) => x.inMenu && x.isMenuEnabled)?.HandleInput(); } if (MenusContainer.AllMenus.Count != 0) { MenusContainer.AllMenus.FirstOrDefault((BetterMenuBase x) => x.InMenu)?.InputEvent.Invoke(); } CommonTerminal.TrySyncNodeOnly(Plugin.instance.Terminal.currentNode); } public static void OnUsingTerminal() { Loggers.LogInfo("Start Using Terminal Postfix"); } public static TerminalNode OnParseSent(ref TerminalNode node) { Loggers.LogDebug("parsing sentence"); if ((Object)(object)node == (Object)null) { Loggers.WARNING("node detected as NULL, returning..."); return node; } string text = Plugin.instance.Terminal.screenText.text; int textAdded = Plugin.instance.Terminal.textAdded; int length = text.Length; int num = length - textAdded; string text2 = text.Substring(num, length - num); if (text2.Length > 0) { if (LogicHandling.GetDisplayFromFaux(ConfigSetup.defaultListing.fauxKeywords, text2, ref node)) { Loggers.LogInfo("faux word detected on current node!"); } if (CommonTerminal.TryGetNodeFromList(text2, ConfigSetup.defaultListing.specialListString, out TerminalNode returnNode)) { node = returnNode; Loggers.LogDebug("node found matching specialListString in text - " + text2); } if (CommonTerminal.TryGetCommand(text2, out TerminalNode returnNode2)) { node = returnNode2; Loggers.LogDebug("node found matching CommandManager listing in text - " + text2); } } if (LogicHandling.GetNewDisplayText(ConfigSetup.defaultListing, ref node)) { Loggers.LogInfo("node found: " + ((Object)node).name); } if (LogicHandling.GetDisplayTextFromCommand(ref node)) { Loggers.LogInfo("command found: " + ((Object)node).name); } return node; } public static void OnLoadNewNode(TerminalNode node) { if (!((Object)(object)node == (Object)null)) { Loggers.LogDebug(((Object)node).name + " has been loaded"); if (node.acceptAnything && node.terminalOptions.Length < 1) { node.acceptAnything = false; Loggers.LogDebug("fixing node property to avoid errors! (eg. LLL route locked)"); } } } } } namespace OpenLib.CoreMethods { public class AddingThings { private static readonly char[] NewLineChars = Environment.NewLine.ToCharArray(); public static void AddKeywordToExistingNode(string keyWord, TerminalNode existingNode, bool addToList = true) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown List<TerminalKeyword> list = Plugin.instance.Terminal.terminalNodes.allKeywords.ToList(); List<CompatibleNoun> list2 = new List<CompatibleNoun>(); TerminalKeyword val = BasicTerminal.CreateNewTerminalKeyword(keyWord + "_keyword", keyWord.ToLower()); val.isVerb = false; val.specialKeywordResult = existingNode; if (existingNode.terminalOptions != null) { list2 = existingNode.terminalOptions.ToList(); Loggers.LogDebug(((Object)existingNode).name + " has existing terminalOptions"); } CompatibleNoun item = new CompatibleNoun { noun = val, result = existingNode }; list2.Add(item); existingNode.terminalOptions = list2.ToArray(); list.Add(val); if (addToList) { Plugin.KeywordsAdded.Add(val); } Loggers.LogDebug("Adding " + keyWord + " to existing node " + ((Object)existingNode).name); Plugin.instance.Terminal.terminalNodes.allKeywords = list.ToArray(); } public static TerminalKeyword AddKeywordToNode(string keyWord, TerminalNode existingNode, bool addToList = true) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown List<TerminalKeyword> list = Plugin.instance.Terminal.terminalNodes.allKeywords.ToList(); List<CompatibleNoun> list2 = new List<CompatibleNoun>(); TerminalKeyword val = BasicTerminal.CreateNewTerminalKeyword(keyWord + "_keyword", keyWord.ToLower()); val.isVerb = false; val.specialKeywordResult = existingNode; if (existingNode.terminalOptions != null) { list2 = existingNode.terminalOptions.ToList(); Loggers.LogDebug(((Object)existingNode).name + " has existing terminalOptions"); } CompatibleNoun item = new CompatibleNoun { noun = val, result = existingNode }; list2.Add(item); existingNode.terminalOptions = list2.ToArray(); list.Add(val); if (addToList) { Plugin.KeywordsAdded.Add(val); } Loggers.LogDebug("Adding " + keyWord + " to existing node " + ((Object)existingNode).name); Plugin.instance.Terminal.terminalNodes.allKeywords = list.ToArray(); return val; } public static void AddToHelpCommand(string textToAdd) { TerminalNode val = Plugin.instance.Terminal.terminalNodes.specialNodes[13]; if (val.displayText.Contains(textToAdd)) { Loggers.WARNING("Help command already contains this text: " + textToAdd); return; } int startIndex = val.displayText.LastIndexOf('['); val.displayText = val.displayText.Insert(startIndex, textToAdd + "\r\n\r\n"); } public static void AddToExistingNodeText(string textToAdd, ref TerminalNode existingNode) { if (existingNode.displayText.Contains(textToAdd)) { Plugin.Log.LogWarning((object)("Unable to add below text to " + ((Object)existingNode).name + ", it already has this text in it")); return; } Loggers.LogDebug($"oldtext length {existingNode.displayText.Length}"); Loggers.LogDebug(existingNode.displayText); string text = existingNode.displayText.TrimEnd(NewLineChars); text = text + "\n" + textToAdd + "\r\n\r\n"; existingNode.displayText = text; Loggers.LogDebug(((Object)existingNode).name + " text updated!!!"); } public static TerminalNode CreateDummyNode(string nodeName, bool clearPrevious, string displayText) { if (DynamicBools.UseMatchingNode(nodeName, out TerminalNode returnNode)) { returnNode.displayText = displayText; returnNode.clearPreviousText = clearPrevious; } else { returnNode = BasicTerminal.CreateNewTerminalNode(); ((Object)returnNode).name = nodeName; returnNode.displayText = displayText; returnNode.clearPreviousText = clearPrevious; } return returnNode; } public static void AddBasicCommand(string nodeName, string keyWord, string displayText, bool isVerb, bool clearText, string category = "", string keywordDescription = "") { //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) if (!LogicHandling.TryGetFromAllNodes("OtherCommands", out TerminalNode outNode) && Misc.CompareStringsInvariant(category, "other")) { Loggers.WARNING("Unable to add " + keyWord + " to " + category + "\n" + category + " TerminalNode could not be found!"); return; } List<TerminalKeyword> list = Plugin.instance.Terminal.terminalNodes.allKeywords.ToList(); if (!DynamicBools.IsCommandCreatedAlready(keyWord, displayText, list)) { CommonThings.CheckForAndDeleteKeyWord(keyWord.ToLower()); TerminalNode val = BasicTerminal.CreateNewTerminalNode(); ((Object)val).name = nodeName; val.displayText = displayText; val.clearPreviousText = clearText; TerminalKeyword val2 = BasicTerminal.CreateNewTerminalKeyword(nodeName + "_keyword", keyWord.ToLower()); ((Object)val2).name = nodeName + "_keyword"; val2.word = keyWord.ToLower(); val2.isVerb = isVerb; val2.specialKeywordResult = val; new CompatibleNoun { noun = val2, result = val }; list.Add(val2); Plugin.instance.Terminal.terminalNodes.allKeywords = list.ToArray(); if (!Plugin.NodesAdded.Contains(val)) { Plugin.NodesAdded.Add(val); } if (!Plugin.KeywordsAdded.Contains(val2)) { Plugin.KeywordsAdded.Add(val2); } if (Misc.CompareStringsInvariant(category, "other") && (Object)(object)outNode != (Object)null) { AddToExistingNodeText(keywordDescription ?? "", ref outNode); Loggers.LogDebug("adding node to other listing"); } } } [Obsolete("use CommandManager class, if equivalent method does not exist will exist in the future")] public static TerminalNode AddNodeManual(string nodeName, string stringValue, Func<string> commandAction, bool clearText, int CommandType, MainListing yourModListing, int price = 0, Func<string> ConfirmAction = null, Func<string> DenyAction = null, string confirmText = "", string denyText = "", bool alwaysInStock = false, int maxStock = 1, string storeName = "", bool reuseFunc = false, string itemList = "") { TerminalNode val = null; List<string> list = new List<string>(); if (stringValue != null) { list = CommonStringStuff.GetKeywordsPerConfigItem(stringValue); } foreach (string item in list) { val = BaseCommandCreation(nodeName, item, commandAction, clearText, CommandType, yourModListing, price, ConfirmAction, DenyAction, confirmText, denyText, alwaysInStock, maxStock, storeName, reuseFunc, itemList); } if ((Object)(object)val == (Object)null) { Loggers.WARNING("Returning NULL terminal node @AddNodeManual!!!"); } return val; } [Obsolete("use CommandManager class, if equivalent method does not exist will exist in the future")] public static TerminalNode AddNodeManual(string nodeName, ConfigEntry<string> stringValue, Func<string> commandAction, bool clearText, int CommandType, MainListing yourModListing, List<ManagedConfig> managedBools, string category = "", string description = "", int price = 0, Func<string> ConfirmAction = null, Func<string> DenyAction = null, string confirmText = "", string denyText = "", bool alwaysInStock = false, int maxStock = 1, string storeName = "", bool reuseFunc = false, string itemList = "") { TerminalNode val = null; List<string> list = new List<string>(); bool flag = true; if (stringValue != null) { flag = false; list = CommonStringStuff.GetKeywordsPerConfigItem(stringValue.Value); } foreach (string item in list) { val = BaseCommandCreation(nodeName, item, commandAction, clearText, CommandType, yourModListing, price, ConfirmAction, DenyAction, confirmText, denyText, alwaysInStock, maxStock, storeName, reuseFunc, itemList); } if ((Object)(object)val == (Object)null) { Loggers.WARNING("Returning NULL terminal node @AddNodeManual!!!"); } if (ManagedBoolGet.CanAddToManagedBoolList(managedBools, nodeName)) { TerminalMenuItem menuItem = new TerminalMenuItem { Category = category, itemDescription = description, ItemName = nodeName, itemKeywords = list }; ManagedConfig managedConfig = new ManagedConfig { TerminalNode = val, menuItem = menuItem, ConfigItemName = nodeName }; managedBools.Add(managedConfig); if (!flag) { ConfigSetup.AddManagedString(stringValue, ref managedBools, managedConfig); } } return val; } [Obsolete("use CommandManager class, if equivalent method does not exist will exist in the future")] public static TerminalNode CreateNode(TerminalMenu terminalMenu, string nodeName, string keyWord, Func<string> commandAction, MainListing yourModListing, bool isNextPageCommand = false) { List<TerminalKeyword> list = Plugin.instance.Terminal.terminalNodes.allKeywords.ToList(); Loggers.LogDebug(nodeName ?? ""); Loggers.LogDebug(keyWord); bool clearPreviousText = true; CommonThings.CheckForAndDeleteKeyWord(keyWord.ToLower()); TerminalNode val = BasicTerminal.CreateNewTerminalNode(); ((Object)val).name = nodeName; val.displayText = nodeName; val.clearPreviousText = clearPreviousText; val.buyUnlockable = false; Loggers.LogDebug("node created"); TerminalKeyword val2 = BasicTerminal.CreateNewTerminalKeyword(nodeName + "_keyword", keyWord.ToLower()); val2.isVerb = false; val2.specialKeywordResult = val; Loggers.LogDebug("keyword created"); yourModListing.Listing.Add(val, commandAction); Loggers.LogDebug("func added to listing"); if (!isNextPageCommand) { terminalMenu.terminalNodePerCategory.Add(keyWord, val); Loggers.LogDebug("added terminalNode to menus nodelisting"); } list.Add(val2); Plugin.KeywordsAdded.Add(val2); Plugin.instance.Terminal.terminalNodes.allKeywords = list.ToArray(); Loggers.LogDebug("added to all keyword lists"); return val; } [Obsolete("use CommandManager class, if equivalent method does not exist will exist in the future")] public static void InfoText(ManagedConfig managedBool, string keyWord, TerminalKeyword infoWord, MainListing yourModListing) { if (managedBool.InfoAction != null) { TerminalNode val = BasicTerminal.CreateNewTerminalNode(); ((Object)val).name = "info_" + keyWord; val.displayText = "infoAction should replace this"; yourModListing.Listing.Add(val, managedBool.InfoAction); val.clearPreviousText = true; AddCompatibleNoun(ref infoWord, keyWord, val); Loggers.LogDebug("info node created with infoAction!"); } else if (managedBool.InfoText.Length > 1) { TerminalNode val2 = BasicTerminal.CreateNewTerminalNode(); ((Object)val2).name = "info_" + keyWord; val2.displayText = managedBool.InfoText; val2.clearPreviousText = true; AddCompatibleNoun(ref infoWord, keyWord, val2); Loggers.LogDebug("info node created"); } } public static void AddToFauxListing(FauxKeyword fauxWord, MainListing yourListing) { if (fauxWord != null && fauxWord.Keyword != null && (Object)(object)fauxWord.MainPage != (Object)null) { yourListing.fauxKeywords.Add(fauxWord); } } [Obsolete("use CommandManager class, if equivalent method does not exist will exist in the future")] public static TerminalNode CreateNode(ManagedConfig managedBool, string keyWord, MainListing yourModListing) { List<TerminalKeyword> list = Plugin.instance.Terminal.terminalNodes.allKeywords.ToList(); Func<string> mainAction = managedBool.MainAction; string text; if (managedBool.nodeName.Length < 2) { text = managedBool.ConfigItemName; Loggers.LogDebug("managedBool nodename is blank, using configitemname"); } else { text = managedBool.nodeName; Loggers.LogDebug("using nodeName: " + text); } bool clearText = managedBool.clearText; TerminalNode val = BaseCommandCreation(text, keyWord, mainAction, managedBool.clearText, managedBool.CommandType, yourModListing, managedBool.price, managedBool.ConfirmAction, managedBool.DenyAction, managedBool.confirmText, managedBool.denyText, managedBool.alwaysInStock, managedBool.maxStock, managedBool.storeName, managedBool.reuseFunc, managedBool.itemList); if ((Object)(object)val == (Object)null) { Loggers.WARNING("terminalNode is NULL at CreateNode!!!"); } return val; } [Obsolete("use CommandManager class, if equivalent method does not exist will exist in the future")] public static void AddConfirm(string nodeName, ManagedConfig managedBool, Dictionary<TerminalNode, Func<string>> nodeListing, out CompatibleNoun confirm, out CompatibleNoun deny) { confirm = BasicTerminal.CreateCompatibleNoun(nodeName, "confirm", managedBool.confirmText, managedBool.price, managedBool.ConfirmAction, nodeListing); deny = BasicTerminal.CreateCompatibleNoun(nodeName, "deny", managedBool.denyText, managedBool.price, managedBool.DenyAction, nodeListing); } [Obsolete("use CommandManager class, if equivalent method does not exist will exist in the future")] public static void AddConfirm(string nodeName, int price, Func<string> ConfirmAction, Func<string> DenyAction, string confirmText, string denyText, Dictionary<TerminalNode, Func<string>> nodeListing, out CompatibleNoun confirm, out CompatibleNoun deny) { confirm = BasicTerminal.CreateCompatibleNoun(nodeName, "confirm", confirmText, price, ConfirmAction, nodeListing); deny = BasicTerminal.CreateCompatibleNoun(nodeName, "deny", denyText, price, DenyAction, nodeListing); } [Obsolete("use CommandManager class, if equivalent method does not exist will exist in the future")] public static void AddStoreCommand(string nodeName, ref TerminalKeyword keyword, ManagedConfig managedBool, MainListing mainListing, out CompatibleNoun confirm, out CompatibleNoun deny) { if ((Object)(object)managedBool.TerminalNode == (Object)null) { Loggers.ERROR("node is null when adding store command!!!"); confirm = null; deny = null; } else if (managedBool.ConfirmAction != null) { AddConfirm(nodeName, managedBool, mainListing.Listing, out confirm, out deny); StoreStuff(nodeName, managedBool.storeName, ref keyword, ref managedBool.TerminalNode, managedBool.price, managedBool.alwaysInStock, managedBool.maxStock, ref confirm, ref deny); } else { Loggers.ERROR("Shop nodes NEED confirmation, but confirmAction is null for " + nodeName + "!"); confirm = null; deny = null; } } [Obsolete("use CommandManager class, if equivalent method does not exist will exist in the future")] public static void AddStoreCommand(string nodeName, string storeName, ref TerminalKeyword keyword, ref TerminalNode node, int price, Func<string> ConfirmAction, Func<string> DenyAction, string confirmText, string denyText, MainListing mainListing, bool alwaysInStock, int maxStock, out CompatibleNoun confirm, out CompatibleNoun deny) { if ((Object)(object)node == (Object)null) { Loggers.ERROR("node is null when adding store command!!!"); confirm = null; deny = null; } else if (ConfirmAction != null) { AddConfir