Decompiled source of OpenLib v0.2.12
OpenLib.dll
Decompiled 15 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; 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.Menus; using TerminalStuff; using TerminalStuff.EventSub; using TwoRadarMaps; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Rendering.HighDefinition; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("OpenLib")] [assembly: AssemblyDescription("https://github.com/darmuh/OpenLib")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("OpenLib")] [assembly: AssemblyCopyright("")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e2700abc-7bc7-4bd0-b787-effe68445b6a")] [assembly: AssemblyFileVersion("0.2.12")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.2.12.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; } } [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } } namespace OpenLib { [HarmonyPatch(typeof(StartOfRound), "Awake")] public class StartRoundAwake { public static void Postfix() { EventManager.StartOfRoundAwake.Invoke(); } } [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), "ShipHasLeft")] public class ShipLeftPatch { public static void Postfix() { EventManager.ShipLeft.Invoke(); } } [HarmonyPatch(typeof(TimeOfDay), "SetNewProfitQuota")] public class NewQuotaPatch { public static void Postfix() { EventManager.NewQuota.Invoke(); } } [HarmonyPatch(typeof(StartOfRound), "ChangeLevel")] public class RouteEvent { public static void Postfix() { EventManager.StartOfRoundChangeLevel.Invoke(); } } [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 : MonoBehaviour { private static void Postfix() { EventManager.PlayerSpawn.Invoke(); } } } [HarmonyPatch(typeof(ShipTeleporter), "Awake")] public class TeleporterInit : ShipTeleporter { private static void Postfix(ShipTeleporter __instance) { EventManager.TeleporterAwake.Invoke(__instance); } } [HarmonyPatch(typeof(GameNetworkManager), "Start")] public class GameStartPatch { public static void Postfix() { EventManager.GameNetworkManagerStart.Invoke(); } } [HarmonyPatch(typeof(StartOfRound), "OnClientConnect")] public class OnClientConnectPatch { public static void Postfix() { EventManager.OnClientConnect.Invoke(); } } 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(Terminal), "Awake")] public class AwakeTermPatch : Terminal { private static void Postfix(Terminal __instance) { EventManager.TerminalAwake.Invoke(__instance); } } [HarmonyPatch(typeof(Terminal), "OnDisable")] public class DisableTermPatch : Terminal { private static void Postfix() { EventManager.TerminalDisable.Invoke(); } } [HarmonyPatch(typeof(Terminal), "QuitTerminal")] public class QuitTerminalPatch : Terminal { private static void Postfix() { EventManager.TerminalQuit.Invoke(); } } [HarmonyPatch(typeof(Terminal), "LoadNewNode")] public class LoadNewNodePatch : Terminal { private static void Postfix(TerminalNode node) { EventManager.TerminalLoadNewNode.Invoke(node); } } [HarmonyPatch(typeof(Terminal), "Start")] public class TerminalStartPatch : Terminal { private static void Postfix() { EventManager.TerminalStart.Invoke(); } } [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; private static void Postfix(Terminal __instance) { if (usePatch) { if (__instance.placeableObject.inUse != inUse) { inUse = __instance.placeableObject.inUse; EventManager.SetTerminalInUse.Invoke(); } if (((ButtonControl)Keyboard.current.anyKey).wasPressedThisFrame && __instance.terminalInUse) { EventManager.TerminalKeyPressed.Invoke(); } } } } [HarmonyPatch(typeof(Terminal), "LoadNewNodeIfAffordable")] public class AffordableNodePatch { private static void Postfix(TerminalNode node) { EventManager.TerminalLoadIfAffordable.Invoke(node); } } [BepInPlugin("darmuh.OpenLib", "OpenLib", "0.2.12")] public class Plugin : BaseUnityPlugin { public static class PluginInfo { public const string PLUGIN_GUID = "darmuh.OpenLib"; public const string PLUGIN_NAME = "OpenLib"; public const string PLUGIN_VERSION = "0.2.12"; } public static Plugin instance; internal static ManualLogSource Log; public bool TerminalStuff = false; public bool LobbyCompat = false; public bool TerminalFormatter = false; public bool LethalConfig = false; public bool OpenBodyCamsMod = false; public bool TwoRadarMapsMod = false; public bool ModelReplacement = false; public bool TooManyEmotes = false; public bool MirrorDecor = false; 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 Terminal Terminal; public static List<TerminalNode> ShopNodes = new List<TerminalNode>(); private void Awake() { instance = this; Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)"OpenLib is loading with version 0.2.12!"); ConfigSetup.defaultManaged = new List<ManagedConfig>(); ConfigSetup.defaultListing = new MainListing(); 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>(); 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); } internal static void MoreLogs(string message) { if (ConfigSetup.ExtensiveLogging.Value) { Log.LogInfo((object)message); } } internal static void Spam(string message) { if (ConfigSetup.DeveloperLogging.Value) { Log.LogDebug((object)message); } } internal static void ERROR(string message) { Log.LogError((object)message); } internal static void WARNING(string message) { Log.LogWarning((object)message); } } } namespace OpenLib.Properties { [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [DebuggerNonUserCode] [CompilerGenerated] internal class Resources { private static ResourceManager resourceMan; private static CultureInfo resourceCulture; [EditorBrowsable(EditorBrowsableState.Advanced)] internal static ResourceManager ResourceManager { get { if (resourceMan == null) { ResourceManager resourceManager = new ResourceManager("OpenLib.Properties.Resources", typeof(Resources).Assembly); resourceMan = resourceManager; } return resourceMan; } } [EditorBrowsable(EditorBrowsableState.Advanced)] internal static CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } internal Resources() { } } } namespace OpenLib.Menus { public class TerminalMenu { public string MenuName; public string MainMenuText; public string setKeyword; public List<TerminalMenuCategory> Categories = new List<TerminalMenuCategory>(); public string currentCategory; public bool isActive; public bool isNextEnabled; public int nextCount = 1; public List<TerminalMenuItem> menuItems; 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 void Delete() { MenuBuild.allMenus.Remove(this); menuItems.Clear(); categoryLists.Clear(); Categories.Clear(); terminalNodePerCategory.Clear(); terminalNodes.Clear(); } } public class TerminalMenuItem { public string ItemName; public string Category; public List<string> itemKeywords; public string itemDescription; public void Delete() { itemDescription = ""; Category = ""; ItemName = ""; if (itemKeywords.Count > 0) { itemKeywords.Clear(); } } } public class TerminalMenuCategory { public string CatName; public string CatDescription; } public class MenuBuild { public static bool isNextEnabled = false; public static int nextCount = 1; public static string currentCategory = ""; public static TerminalMenu currentMenu; public static List<TerminalMenu> allMenus = new List<TerminalMenu>(); public static List<TerminalMenuCategory> InitCategories(Dictionary<string, string> CategoryItems) { Plugin.Spam("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); } Plugin.Spam("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); } } Plugin.Spam("\n\n\n"); Plugin.Spam($"myMenuItems count: {list.Count}"); Plugin.Spam("\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) { Plugin.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 = ""; Plugin.Spam("In main menu of " + terminalMenu.MenuName); return true; } if (terminalMenu.isNextEnabled && terminalMenu.terminalNodes.Contains(terminalNode)) { Plugin.Spam("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) { Plugin.Spam("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) { List<Dictionary<string, List<string>>> list = new List<Dictionary<string, List<string>>>(); foreach (TerminalMenuCategory category in terminalMenu.Categories) { Plugin.Spam("checking category in terminalMenu.categories"); Dictionary<string, List<string>> item = MakeCategoryList(category, terminalMenu.menuItems); if (!list.Contains(item)) { list.Add(item); } FauxKeyword fauxKeyword = new FauxKeyword("more", category.CatName, GetFirstInList); fauxKeyword.AllowOtherFauxWords = true; fauxKeyword.requireExact = true; AddingThings.AddToFauxListing(fauxKeyword, yourModListing); } terminalMenu.categoryLists = list; FauxKeyword fauxKeyword2 = new FauxKeyword("more", "next", NextInList); fauxKeyword2.AllowOtherFauxWords = true; AddingThings.AddToFauxListing(fauxKeyword2, 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) { Plugin.Spam("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) { Plugin.Spam("2.1"); List<string> result = new List<string>(); foreach (TerminalMenu allMenu in allMenus) { Plugin.Spam("2.2"); if (!allMenu.isActive) { continue; } for (int i = 0; i < allMenu.Categories.Count; i++) { Plugin.Spam("2.3"); foreach (KeyValuePair<string, List<string>> item in allMenu.categoryLists[i]) { if (item.Key.ToLower() == catName.ToLower()) { Plugin.Spam("categorylist found!!!"); menuName = allMenu; return item.Value; } } } } Plugin.Spam("2.1 FAIL"); menuName = null; return result; } public static Dictionary<string, List<string>> MakeCategoryList(TerminalMenuCategory category, List<TerminalMenuItem> terminalMenuItems) { Plugin.Spam("MakeCategoryList START"); string catName = category.CatName; Plugin.Spam(catName); List<string> list = new List<string>(); Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>(); Plugin.Spam($"count: {terminalMenuItems.Count}"); foreach (TerminalMenuItem terminalMenuItem in terminalMenuItems) { Plugin.Spam("checking " + terminalMenuItem.ItemName); if (terminalMenuItem.Category.ToLower() == catName.ToLower()) { list.Add("> " + CommonStringStuff.GetKeywordsForMenuItem(terminalMenuItem.itemKeywords) + "\r\n" + terminalMenuItem.itemDescription + "\r\n"); Plugin.Spam(CommonStringStuff.GetKeywordsForMenuItem(terminalMenuItem.itemKeywords) + " added"); Plugin.Spam(terminalMenuItem.itemDescription + " added too!"); } } Plugin.Spam("setting catName list"); dictionary.Add(catName, list); Plugin.Spam("MakeCategoryList END"); return dictionary; } public static string NextInList() { if (!isNextEnabled) { return "Not currently in any menus...\r\n\r\n"; } Plugin.Spam("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); Plugin.Spam($"currentCategory:{currentCategory} nextCount: {nextCount} isNextEnabled: {isNextEnabled}"); menuName.isNextEnabled = isNextEnabled; return nextPage; } public static string GetFirstInList() { Plugin.Spam("1"); nextCount = 1; string input = Plugin.instance.Terminal.screenText.text.Substring(Plugin.instance.Terminal.screenText.text.Length - Plugin.instance.Terminal.textAdded); currentCategory = GetCategoryFromString(input); Plugin.Spam("currentCategory detected as: [" + currentCategory + "]"); Plugin.Spam("2"); TerminalMenu menuName; List<string> categoryList = GetCategoryList(currentCategory, out menuName); menuName.isActive = true; menuName.nextCount = nextCount; menuName.currentCategory = currentCategory; Plugin.Spam("3"); string nextPage = CommonStringStuff.GetNextPage(categoryList, currentCategory, 4, 1, out isNextEnabled); menuName.isNextEnabled = isNextEnabled; Plugin.Spam("4"); return nextPage; } public static string GetCategoryFromString(string input) { string input2 = input; Plugin.Spam("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) => d.Key.ToLower() == input2.ToLower()))) { Plugin.Spam("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) => d.Key.ToLower() == input2.ToLower())); return allMenu.categoryLists[index].First<KeyValuePair<string, List<string>>>((KeyValuePair<string, List<string>> d) => d.Key.ToLower() == input2.ToLower()).Key; } Plugin.Spam("menu does not contain string " + input2); allMenu.isActive = false; } return "CategoryNameFailure"; } public static string GetCategoryFromNode(TerminalNode givenNode) { Plugin.Spam("1.1"); if ((Object)(object)givenNode == (Object)null) { Plugin.ERROR("givenNode is null!!!!"); return ""; } foreach (TerminalMenu allMenu in allMenus) { if (!allMenu.terminalNodePerCategory.ContainsValue(givenNode)) { Plugin.Spam("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) { Plugin.Spam("FOUND NODE AND PAIR " + item.Key); allMenu.isActive = true; return item.Key; } } } Plugin.ERROR("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 }; } Plugin.WARNING("Empty categoryText, Unable to create TerminalMenuItem! (null return)"); return null; } } } 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 NextDayEvent = 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 PlayerIsInShip = new Events.CustomEvent(); public static Events.CustomEvent PlayerIsDead = new Events.CustomEvent(); public static Events.CustomEvent SpecatingPlayerIsInShip = new Events.CustomEvent(); } 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 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 class EventUsage { public static List<ConfigFile> configsToReload = new List<ConfigFile>(); public static void Subscribers() { EventManager.TerminalAwake.AddListener(OnTerminalAwake); EventManager.TerminalStart.AddListener(OnTerminalStart); 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.TerminalKeyPressed.AddListener(OnKeyPress); } public static void OnTerminalAwake(Terminal instance) { Plugin.instance.Terminal = instance; Plugin.MoreLogs("Setting Plugin.instance.Terminal"); CommandRegistry.GetCommandsToAdd(ConfigSetup.defaultManaged, ConfigSetup.defaultListing); } public static void OnTerminalDisable() { if (Plugin.instance.OpenBodyCamsMod) { OpenBodyCamFuncs.ResidualCamsCheck(); } RemoveThings.OnTerminalDisable(); TerminalStart.delayStartEnum = false; ListManagement.ClearLists(); foreach (ConfigFile item in configsToReload) { Plugin.Spam("reloading config from list"); item.Save(); item.Reload(); } configsToReload.Clear(); } public static void OnTerminalStart() { TerminalStart.TerminalStartGroupDelay(); } public static void OnKeyPress() { if (AllInteractiveMenus.AllMenus.Count != 0) { AllInteractiveMenus.AllMenus.FirstOrDefault((InteractiveMenu x) => x.inMenu && x.isMenuEnabled)?.HandleInput(); } } public static void OnUsingTerminal() { Plugin.MoreLogs("Start Using Terminal Postfix"); } public static TerminalNode OnParseSent(ref TerminalNode node) { Plugin.Spam("parsing sentence"); if ((Object)(object)node == (Object)null) { Plugin.WARNING("node detected as NULL, returning..."); return node; } string text = Plugin.instance.Terminal.screenText.text.Substring(Plugin.instance.Terminal.screenText.text.Length - Plugin.instance.Terminal.textAdded); if (text.Length > 0) { if (LogicHandling.GetDisplayFromFaux(ConfigSetup.defaultListing.fauxKeywords, text, ref node)) { Plugin.MoreLogs("faux word detected on current node!"); } if (CommonTerminal.TryGetNodeFromList(text, ConfigSetup.defaultListing.specialListString, out TerminalNode returnNode)) { node = returnNode; Plugin.Spam("node found matching specialListString in text - " + text); } } if (LogicHandling.GetNewDisplayText(ConfigSetup.defaultListing, ref node)) { Plugin.MoreLogs("node found: " + ((Object)node).name); } return node; } public static void OnLoadNewNode(TerminalNode node) { Plugin.Spam($"listing count: {ConfigSetup.defaultListing.Listing.Count}"); if (!((Object)(object)node == (Object)null)) { Plugin.Spam(((Object)node).name + " has been loaded"); if (node.acceptAnything && node.terminalOptions.Length < 1) { node.acceptAnything = false; Plugin.Spam("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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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(); Plugin.Spam(((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); } Plugin.Spam("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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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(); Plugin.Spam(((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); } Plugin.Spam("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)) { Plugin.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; } Plugin.Spam($"oldtext length {existingNode.displayText.Length}"); Plugin.Spam(existingNode.displayText); string text = existingNode.displayText.TrimEnd(NewLineChars); text = text + "\n" + textToAdd + "\r\n\r\n"; existingNode.displayText = text; Plugin.Spam(((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_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) if (!LogicHandling.TryGetFromAllNodes("OtherCommands", out TerminalNode outNode) && category.ToLower() == "other") { Plugin.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 (category.ToLower() == "other" && (Object)(object)outNode != (Object)null) { AddToExistingNodeText(keywordDescription ?? "", ref outNode); Plugin.Spam("adding node to other listing"); } } } 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) { Plugin.WARNING("Returning NULL terminal node @AddNodeManual!!!"); } return val; } 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) { Plugin.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; } 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(); Plugin.Spam(nodeName ?? ""); Plugin.Spam(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; Plugin.Spam("node created"); TerminalKeyword val2 = BasicTerminal.CreateNewTerminalKeyword(nodeName + "_keyword", keyWord.ToLower()); val2.isVerb = false; val2.specialKeywordResult = val; Plugin.Spam("keyword created"); yourModListing.Listing.Add(val, commandAction); Plugin.Spam("func added to listing"); if (!isNextPageCommand) { terminalMenu.terminalNodePerCategory.Add(keyWord, val); Plugin.Spam("added terminalNode to menus nodelisting"); } list.Add(val2); Plugin.keywordsAdded.Add(val2); Plugin.instance.Terminal.terminalNodes.allKeywords = list.ToArray(); Plugin.Spam("added to all keyword lists"); return val; } 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); Plugin.Spam("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); Plugin.Spam("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); } } 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; Plugin.Spam("managedBool nodename is blank, using configitemname"); } else { text = managedBool.nodeName; Plugin.Spam("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) { Plugin.WARNING("terminalNode is NULL at CreateNode!!!"); } return val; } 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); } 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); } 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) { Plugin.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 { Plugin.ERROR("Shop nodes NEED confirmation, but confirmAction is null for " + nodeName + "!"); confirm = null; deny = null; } } 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) { Plugin.ERROR("node is null when adding store command!!!"); confirm = null; deny = null; } else if (ConfirmAction != null) { AddConfirm(nodeName, price, ConfirmAction, DenyAction, confirmText, denyText, mainListing.Listing, out confirm, out deny); StoreStuff(nodeName, storeName, ref keyword, ref node, price, alwaysInStock, maxStock, ref confirm, ref deny); } else { Plugin.ERROR("Shop nodes NEED confirmation, but confirmAction is null for " + nodeName + "!"); confirm = null; deny = null; } } public static void StoreStuff(string nodeName, string storeName, ref TerminalKeyword keyword, ref TerminalNode node, int price, bool alwaysInStock, int maxStock, ref CompatibleNoun confirm, ref CompatibleNoun deny) { node.terminalOptions = (CompatibleNoun[])(object)new CompatibleNoun[2] { confirm, deny }; UnlockableItem item = AddUnlockable(nodeName, node, alwaysInStock, maxStock); if (!StartOfRound.Instance.unlockablesList.unlockables.Contains(item)) { StartOfRound.Instance.unlockablesList.unlockables.Add(item); } int shipUnlockableID = StartOfRound.Instance.unlockablesList.unlockables.IndexOf(item); node.creatureName = storeName; node.shipUnlockableID = shipUnlockableID; confirm.result.shipUnlockableID = shipUnlockableID; confirm.result.buyUnlockable = false; confirm.result.itemCost = price; if (DynamicBools.TryGetKeyword("buy", out TerminalKeyword terminalKeyword)) { AddToBuyWord(ref terminalKeyword, ref keyword, item); } Plugin.ShopNodes.Add(node); Plugin.Spam("Store nodes created for " + nodeName); } public static UnlockableItem AddUnlockable(string storeName, TerminalNode node, bool alwaysInStock, int maxStock) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown if (DynamicBools.TryGetAndReturnUnlockable(storeName, out UnlockableItem itemOut)) { Plugin.Spam("found matching item for " + storeName); itemOut.unlockableType = 1; itemOut.shopSelectionNode = node; itemOut.alwaysInStock = alwaysInStock; itemOut.IsPlaceable = false; itemOut.spawnPrefab = false; itemOut.maxNumber = maxStock; return itemOut; } Plugin.Spam("Creating unlockable item manually for item: " + storeName); return new UnlockableItem { unlockableType = 1, unlockableName = storeName, shopSelectionNode = node, alwaysInStock = alwaysInStock, IsPlaceable = false, spawnPrefab = false, maxNumber = maxStock }; } public static void AddToBuyWord(ref TerminalKeyword buyKeyword, ref TerminalKeyword terminalKeyword, UnlockableItem item) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown terminalKeyword.defaultVerb = buyKeyword; Plugin.Spam("Added buy verb to " + buyKeyword.word); CompatibleNoun item2 = new CompatibleNoun { noun = terminalKeyword, result = item.shopSelectionNode }; List<CompatibleNoun> list = buyKeyword.compatibleNouns.ToList(); list.Add(item2); Plugin.nounsAdded.Add(item2); buyKeyword.compatibleNouns = list.ToArray(); } [Obsolete("Use AddCompatibleNoun instead")] public static void AddToKeyword(ref TerminalKeyword originalKeyword, ref TerminalKeyword newWord) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown if (!originalKeyword.isVerb) { Plugin.Log.LogWarning((object)"AddToKeyword called on non-verb"); return; } newWord.defaultVerb = originalKeyword; Plugin.Spam("Added verb " + originalKeyword.word + " to " + newWord.word); CompatibleNoun item = new CompatibleNoun { noun = newWord, result = newWord.specialKeywordResult }; List<CompatibleNoun> list = originalKeyword.compatibleNouns.ToList(); list.Add(item); Plugin.nounsAdded.Add(item); originalKeyword.compatibleNouns = list.ToArray(); } public static void AddCompatibleNoun(ref TerminalKeyword originalWord, string word, TerminalNode resultNode) { //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown if (!originalWord.isVerb) { Plugin.WARNING(originalWord.word + " is NOT a verb"); return; } List<CompatibleNoun> list = originalWord.compatibleNouns.ToList(); foreach (CompatibleNoun item in list) { if (item.noun.word.ToLower() == word.ToLower()) { Plugin.WARNING("NOUN: " + item.noun.word + " already exists for WORD: " + originalWord.word); return; } } if (DynamicBools.TryGetKeyword(word, out TerminalKeyword terminalKeyword)) { CompatibleNoun val = new CompatibleNoun(); val.noun = terminalKeyword; val.result = resultNode; list.Add(val); originalWord.compatibleNouns = list.ToArray(); Plugin.Spam("Added NOUN: " + val.noun.word + " to WORD: " + originalWord.word + " compatible nouns"); Plugin.nounsAdded.Add(val); } else { Plugin.WARNING("word: " + word + " does not exist, unable to add as compatible noun"); } } public static TerminalNode BaseCommandCreation(string nodeName, string keyWord, Func<string> commandAction, bool clearText, int CommandType, MainListing yourModListing, int price, Func<string> ConfirmAction, Func<string> DenyAction, string confirmText, string denyText, bool alwaysInStock, int maxStock, string storeName, bool reuseFunc, string itemList) { List<TerminalKeyword> list = Plugin.instance.Terminal.terminalNodes.allKeywords.ToList(); if (DynamicBools.IsCommandCreatedAlready(yourModListing.Listing, keyWord, commandAction, list, out TerminalKeyword outKeyword) && !reuseFunc) { return outKeyword.specialKeywordResult; } CommonThings.CheckForAndDeleteKeyWord(keyWord.ToLower()); if (DynamicBools.DoesNodeExist(yourModListing.Listing, commandAction, out TerminalNode node) && !reuseFunc) { AddKeywordToExistingNode(keyWord, node); Plugin.Spam("existing node found " + ((Object)node).name + ", reusing associated func and adding additional keyword " + keyWord); return node; } TerminalNode node2 = BasicTerminal.CreateNewTerminalNode(); ((Object)node2).name = nodeName; node2.displayText = nodeName; node2.clearPreviousText = clearText; node2.buyUnlockable = false; TerminalKeyword keyword = BasicTerminal.CreateNewTerminalKeyword(nodeName + "_keyword", keyWord.ToLower()); keyword.isVerb = false; keyword.specialKeywordResult = node2; CompatibleNoun confirm = null; CompatibleNoun deny = null; switch (CommandType) { case 1: AddConfirm(nodeName, price, ConfirmAction, DenyAction, confirmText, denyText, yourModListing.Listing, out confirm, out deny); node2.acceptAnything = false; Plugin.Spam("command type 1 detected, adding basic confirmation"); break; case 2: AddStoreCommand(nodeName, storeName, ref keyword, ref node2, price, ConfirmAction, DenyAction, confirmText, denyText, yourModListing, alwaysInStock, maxStock, out confirm, out deny); Plugin.Spam("command type 2 detected, adding store logic"); node2.acceptAnything = false; yourModListing.shopNodes.Add(confirm.result); yourModListing.shopNodes.Add(node2); yourModListing.shopNodes.Add(deny.result); if (itemList.Length > 1) { confirm.result.buyUnlockable = false; yourModListing.storePacks.Add(node2, itemList); Plugin.Spam("storepack detected, adding itemlist"); } break; } if (confirm != null && deny != null) { list.Add(confirm.noun); Plugin.keywordsAdded.Add(confirm.noun); list.Add(deny.noun); Plugin.keywordsAdded.Add(deny.noun); node2.terminalOptions = (CompatibleNoun[])(object)new CompatibleNoun[2] { confirm, deny }; node2.overrideOptions = true; } else { Plugin.Spam("no confirmation logic added for " + keyWord); } yourModListing.Listing.Add(node2, commandAction); list.Add(keyword); if (!Plugin.nodesAdded.Contains(node2)) { Plugin.nodesAdded.Add(node2); } if (!Plugin.keywordsAdded.Contains(keyword)) { Plugin.keywordsAdded.Add(keyword); } Plugin.instance.Terminal.terminalNodes.allKeywords = list.ToArray(); return node2; } [Obsolete("use AddCompatibleNoun")] public static void AddNounWordSimple(string originalVerb, string nodeName, string keyWord, string displayText, bool clearText) { } } public class BasicTerminal { public static TerminalKeyword CreateNewTerminalKeyword(string name, string keyword) { List<TerminalKeyword> list = Plugin.instance.Terminal.terminalNodes.allKeywords.ToList(); TerminalKeyword val = ScriptableObject.CreateInstance<TerminalKeyword>(); ((Object)val).name = name; val.word = keyword; val.compatibleNouns = Array.Empty<CompatibleNoun>(); val.defaultVerb = null; list.Add(val); Plugin.instance.Terminal.terminalNodes.allKeywords = list.ToArray(); return val; } public static TerminalNode CreateNewTerminalNode() { TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>(); ((Object)val).name = "OpenLibTerminalNode"; val.displayText = string.Empty; val.terminalEvent = string.Empty; val.maxCharactersToType = 25; val.buyItemIndex = -1; val.buyRerouteToMoon = -1; val.displayPlanetInfo = -1; val.shipUnlockableID = -1; val.creatureFileID = -1; val.storyLogFileID = -1; val.playSyncedClip = -1; val.terminalOptions = Array.Empty<CompatibleNoun>(); return val; } public static CompatibleNoun CreateCompatibleNoun(string nodeName, string word, string displayText = "", int price = 0, Func<string> thisAction = null, Dictionary<TerminalNode, Func<string>> nodeListing = null) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown CompatibleNoun val = new CompatibleNoun(); TerminalKeyword terminalKeyword; if (word.ToLower() == "deny" || word.ToLower() == "confirm") { val.noun = CreateNewTerminalKeyword(nodeName + "_" + word, word); } else if (DynamicBools.TryGetKeyword(word, out terminalKeyword)) { val.noun = terminalKeyword; } else { val.noun = CreateNewTerminalKeyword(nodeName + "_" + word, word); } val.result = CreateNewTerminalNode(); ((Object)val.result).name = nodeName + "_" + word; val.result.displayText = displayText; val.result.clearPreviousText = true; val.result.itemCost = price; val.noun.specialKeywordResult = val.result; if (thisAction != null) { nodeListing?.Add(val.result, thisAction); } return val; } } public class CommonThings { public static void CheckForAndDeleteKeyWord(string keyWord) { Plugin.Spam("Checking for " + keyWord); List<TerminalKeyword> list = Plugin.instance.Terminal.terminalNodes.allKeywords.ToList(); for (int num = list.Count - 1; num >= 0; num--) { if (list[num].word.Equals(keyWord)) { Plugin.Spam("removing " + list[num].word); list.RemoveAt(num); break; } } Plugin.instance.Terminal.terminalNodes.allKeywords = list.ToArray(); } } public class FauxKeyword { public TerminalNode MainPage; public TerminalNode thisNode = BasicTerminal.CreateNewTerminalNode(); public string Keyword; public Func<string> ResultFunc; public Func<string> ConfirmFunc; public Func<string> DenyFunc; public string ConfirmText; public string DenyText; public bool GetConfirm; public bool AllowOtherFauxWords = false; public bool requireExact = false; public FauxKeyword(string mainWord, string keyword, Func<string> resultFunc) { TerminalKeyword terminalKeyword; if (keyword.Length < 3) { Plugin.WARNING("Unable to create FauxKeyword for {keyword}! It's too short!"); } else if (DynamicBools.TryGetKeyword(mainWord, out terminalKeyword)) { MainPage = terminalKeyword.specialKeywordResult; Keyword = keyword; ResultFunc = resultFunc; thisNode.clearPreviousText = true; ((Object)thisNode).name = keyword; Plugin.Spam("FauxKeyword - " + keyword + " created!"); } else { Plugin.WARNING("Could not find main page at word - " + mainWord); MainPage = null; Keyword = keyword; } } public void AddConfirm(Func<string> confirmFunc, Func<string> denyFunc = null) { GetConfirm = false; ConfirmFunc = confirmFunc; if (denyFunc != null) { DenyFunc = denyFunc; } } public void AddText(string denyText, string confirmText = "") { GetConfirm = false; ConfirmText = confirmText; DenyText = denyText; } } public class InteractiveMenu { public string MenuName = ""; public Action LoadPage; public Action EnterMenu; public Action LeaveMenu; 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 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 = false; public bool inMenu = false; public bool acceptAnything = false; public int activeSelection = 0; public int currentPage = 1; public InteractiveMenu(string name, Action pageLoader, Action enter, Action leave, Dictionary<Key, Action> MoreMenuActions = null) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) if (!TerminalUpdatePatch.usePatch) { TerminalUpdatePatch.usePatch = true; } MenuName = name; LoadPage = pageLoader; EnterMenu = enter; LeaveMenu = leave; SetupMainActions(); if (MoreMenuActions != null) { OtherActions = MoreMenuActions; } AllInteractiveMenus.AllMenus.Add(this); } public void AddToOtherActions(Key key, Action action) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (OtherActions.ContainsKey(key)) { OtherActions.Remove(key); } OtherActions.Add(key, action); } internal void SetupMainActions() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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, EnterMenu.Invoke); MainActions.Add(leaveMenu, LeaveMenu.Invoke); } internal void HandleInput() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) if (!inMenu) { 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 UpMenu() { if (inMenu) { if (activeSelection > 0) { activeSelection--; } LoadPage(); UpMenuEvent.Invoke(); } } public void DownMenu() { if (inMenu) { activeSelection++; LoadPage(); DownMenuEvent.Invoke(); } } public void LeftMenu() { if (inMenu) { if (currentPage > 1) { currentPage--; } LoadPage(); LeftMenuEvent.Invoke(); } } public void RightMenu() { if (inMenu) { currentPage++; LoadPage(); RightMenuEvent.Invoke(); } } } public static class AllInteractiveMenus { public static List<InteractiveMenu> AllMenus { get; internal set; } public static bool TryGetMenu(string menuName, out InteractiveMenu menu) { string menuName2 = menuName; menu = AllMenus.FirstOrDefault((InteractiveMenu x) => x.MenuName == menuName2); if (menu == null) { return false; } return true; } public static bool AnyMenuActive() { if (AllMenus.Count == 0) { return false; } if (AllMenus.Any((InteractiveMenu x) => x.inMenu)) { return true; } return false; } } public class ListManagement { public static void ClearLists() { Plugin.ShopNodes.Clear(); } } public class MainListing { public List<TerminalNode> terminalNodes = new List<TerminalNode>(); public List<TerminalKeyword> terminalKeywords = new List<TerminalKeyword>(); public Dictionary<TerminalNode, Func<string>> Listing = new Dictionary<TerminalNode, Func<string>>(); public List<TerminalNode> shopNodes = new List<TerminalNode>(); public List<FauxKeyword> fauxKeywords = new List<FauxKeyword>(); public Dictionary<TerminalNode, int> specialListNum = new Dictionary<TerminalNode, int>(); public Dictionary<string, TerminalNode> specialListString = new Dictionary<string, TerminalNode>(); public Dictionary<int, string> ListNumToString = new Dictionary<int, string>(); public Dictionary<TerminalNode, string> storePacks = new Dictionary<TerminalNode, string>(); public void DeleteAll() { terminalKeywords.Clear(); terminalNodes.Clear(); Listing.Clear(); shopNodes.Clear(); specialListNum.Clear(); specialListString.Clear(); ListNumToString.Clear(); storePacks.Clear(); fauxKeywords.Clear(); } } public class CommandRegistry { public static void InitListing(ref MainListing listingName) { if (listingName == null) { listingName = new MainListing(); } listingName.terminalNodes = new List<TerminalNode>(); listingName.terminalKeywords = new List<TerminalKeyword>(); listingName.Listing = new Dictionary<TerminalNode, Func<string>>(); listingName.shopNodes = new List<TerminalNode>(); listingName.specialListNum = new Dictionary<TerminalNode, int>(); listingName.specialListString = new Dictionary<string, TerminalNode>(); listingName.ListNumToString = new Dictionary<int, string>(); if (listingName == null) { Plugin.ERROR("InitListing still null"); } } public static void GetCommandsToAdd(List<ManagedConfig> managedBools, MainListing listingName) { Plugin.MoreLogs("GetCommandsToAdd"); if (managedBools == null || listingName == null) { Plugin.Spam("params are null"); return; } Plugin.Spam($"listing count: {listingName.Listing.Count}"); foreach (ManagedConfig managedBool in managedBools) { if (managedBool.BoolValue) { Plugin.Spam("configvalue is true"); TerminalMenuItem terminalMenuItem = MenuBuild.MakeMenuItem(managedBool); if (terminalMenuItem != null) { managedBool.menuItem = terminalMenuItem; } Plugin.MoreLogs(managedBool.ConfigItemName + " found in managed bools and is active"); if (managedBool.KeywordList == null) { continue; } AddCommandKeyword(managedBool, listingName); if (managedBool.categoryText.ToLower() == "other") { if (!LogicHandling.TryGetFromAllNodes("OtherCommands", out TerminalNode outNode)) { Plugin.WARNING("Unable to add " + managedBool.configDescription + " to OtherCommands\nOtherCommands TerminalNode could not be found!"); } else { AddingThings.AddToExistingNodeText("\n" + managedBool.configDescription, ref outNode); } } } else { Plugin.Spam("configvalue is false, deleting menuItem if not null"); managedBool.menuItem?.Delete(); } } } public static void AddCommandKeyword(ManagedConfig managedBool, MainListing listingName) { if (managedBool == null) { Plugin.ERROR("managedBool is null @AddCommandKeyword()"); return; } if (managedBool.KeywordList.Count == 0) { Plugin.Spam("KeywordList Count = 0 for " + managedBool.ConfigItemName); return; } Plugin.Spam("AddCommandKeyword starting:"); foreach (string keyword in managedBool.KeywordList) { Plugin.Spam("adding " + keyword); GenerateInfoText(managedBool); managedBool.TerminalNode = AddingThings.CreateNode(managedBool, keyword, listingName); if (DynamicBools.TryGetKeyword("info", out TerminalKeyword terminalKeyword)) { AddingThings.InfoText(managedBool, keyword, terminalKeyword, listingName); } if (managedBool.specialNum != -1 && !listingName.specialListNum.ContainsKey(managedBool.TerminalNode)) { listingName.specialListNum.Add(managedBool.TerminalNode, managedBool.specialNum); listingName.ListNumToString.Add(managedBool.specialNum, managedBool.specialString); Plugin.MoreLogs($"Added viewnode types to dictionaries, {managedBool.specialNum}"); } else if (managedBool.specialString.Length > 1) { listingName.specialListString.Add(keyword, managedBool.TerminalNode); Plugin.MoreLogs("mapping keyword" + keyword + " for " + managedBool.specialString + " node"); } } } public static void GenerateInfoText(ManagedConfig managedBool) { if (managedBool == null) { Plugin.ERROR("managedBool is null @GenerateInfoText()"); } else if (managedBool.KeywordList.Count == 0) { Plugin.Spam("KeywordList Count = 0 for " + managedBool.ConfigItemName); } else if (managedBool.InfoAction == null && managedBool.InfoText.Length <= 0) { if (managedBool.menuItem == null) { Plugin.Spam("no menu items to grab description from"); } else { managedBool.DefaultInfoText(); } } } public static void AddSpecialListString(ref MainListing listingName, TerminalNode node, string special) { if (listingName.Listing.ContainsKey(node)) { if (listingName.specialListString.ContainsKey(special)) { Plugin.WARNING("Listing already contains special string key " + special); return; } listingName.specialListString.Add(special, node); Plugin.Spam(((Object)node).name + " added to special string listing with key " + special); } } } public class DynamicBools { public static bool UseMatchingNode(string nodeName, out TerminalNode returnNode) { TerminalNode[] array = Object.FindObjectsOfType<TerminalNode>(); TerminalNode[] array2 = array; foreach (TerminalNode val in array2) { if (((Object)val).name.ToLower().Equals(nodeName.ToLower())) { returnNode = val; Plugin.Spam("Existing terminalNode [" + nodeName + "] found, using it rather than making a new one for this command"); return true; } } returnNode = null; return false; } public static bool TryGetKeyword(string keyWord) { List<TerminalKeyword> list = Plugin.instance.Terminal.terminalNodes.allKeywords.ToList(); foreach (TerminalKeyword item in list) { if (item.word.ToLower().Equals(keyWord.ToLower())) { return true; } } return false; } public static bool TryGetKeyword(string keyWord, out TerminalKeyword terminalKeyword) { List<TerminalKeyword> list = Plugin.instance.Terminal.terminalNodes.allKeywords.ToList(); foreach (TerminalKeyword item in list) { if (item.word.ToLower().Equals(keyWord.ToLower())) { Plugin.Spam("Keyword: [" + keyWord + "] found!"); terminalKeyword = item; return true; } } terminalKeyword = null; return false; } public static bool TryGetAndReturnUnlockable(string unlockableName, out UnlockableItem itemOut) { List<UnlockableItem> list = StartOfRound.Instance.unlockablesList.unlockables.ToList(); foreach (UnlockableItem item in list) { if (item.unlockableName.Equals(unlockableName)) { itemOut = item; return true; } } itemOut = null; return false; } public static bool TryGetAndReturnItem(string unlockableName, out Item itemOut) { List<Item> list = Plugin.instance.Terminal.buyableItemsList.ToList(); foreach (Item item in list) { if (item.itemName.ToLower().Equals(unlockableName.ToLower())) { itemOut = item; return true; } } itemOut = null; return false; } public static bool IsCommandCreatedAlready(string keyWord, string displayText, List<TerminalKeyword> terminalKeywords) { foreach (TerminalKeyword terminalKeyword in terminalKeywords) { if (terminalKeyword.word.ToLower() == keyWord.ToLower() && terminalKeyword.specialKeywordResult.displayText == displayText) { Plugin.Spam("word: " + keyWord + " found with valid node: " + ((Object)terminalKeyword.specialKeywordResult).name); return true; } } return false; } public static bool IsCommandCreatedAlready(Dictionary<TerminalNode, Func<string>> MainCommandListing, string keyWord, Func<string> commandAction, List<TerminalKeyword> terminalKeywords) { if (MainCommandListing.Count == 0) { return false; } foreach (KeyValuePair<TerminalNode, Func<string>> item in MainCommandListing) { if (!((Delegate?)item.Value == (Delegate?)commandAction)) { continue; } foreach (TerminalKeyword terminalKeyword in terminalKeywords) { if (terminalKeyword.word.ToLower() == keyWord.ToLower() && (Object)(object)terminalKeyword.specialKeywordResult == (Object)(object)item.Key) { Plugin.Spam("word: " + keyWord + " found with valid node: " + ((Object)terminalKeyword.specialKeywordResult).name); return true; } } } return false; } public static bool IsCommandCreatedAlready(Dictionary<TerminalNode, Func<string>> MainCommandListing, string keyWord, Func<string> commandAction, List<TerminalKeyword> terminalKeywords, out TerminalKeyword outKeyword) { outKeyword = null; if (MainCommandListing.Count == 0) { return false; } foreach (KeyValuePair<TerminalNode, Func<string>> item in MainCommandListing) { if (!((Delegate?)item.Value == (Delegate?)commandAction)) { continue; } foreach (TerminalKeyword terminalKeyword in terminalKeywords) { if (terminalKeyword.word.ToLower() == keyWord.ToLower() && (Object)(object)terminalKeyword.specialKeywordResult == (Object)(object)item.Key) { Plugin.Spam("word: " + keyWord + " found with valid node: " + ((Object)terminalKeyword.specialKeywordResult).name); outKeyword = terminalKeyword; return true; } } } return false; } public static bool DoesNodeExist(Dictionary<TerminalNode, Func<string>> MainCommandListing, Func<string> commandAction, out TerminalNode node) { node = null; if (MainCommandListing.Count == 0) { return false; } foreach (KeyValuePair<TerminalNode, Func<string>> item in MainCommandListing) { if ((Object)(object)item.Key == (Object)null || !((Delegate?)item.Value == (Delegate?)commandAction)) { continue; } node = item.Key; return true; } return false; } } public class RemoveThings { public static void OnTerminalDisable() { Plugin.Spam("OnTerminalDisable called"); DeleteAllNodes(ref Plugin.nodesAdded); DeleteAllNouns(ref Plugin.nounsAdded); DeleteCams(); ConfigSetup.defaultListing.DeleteAll(); } private static void DeleteCams() { if ((Object)(object)CamStuff.CameraData != (Object)null) { Object.Destroy((Object)(object)CamStuff.CameraData); } if ((Object)(object)CamStuff.ObcCameraHolder != (Object)null) { Object.Destroy((Object)(object)CamStuff.ObcCameraHolder); } if ((Object)(object)CamStuff.ObcCameraHolder != (Object)null) { Object.Destroy((Object)(object)CamStuff.ObcCameraHolder); } } [Obsolete("Probably dont need to do this anymore")] public static void DeleteNounWord(ref TerminalKeyword keyWord, string terminalKeyword) { List<CompatibleNoun> list = keyWord.compatibleNouns.ToList(); List<CompatibleNoun> list2 = new List<CompatibleNoun>(); foreach (CompatibleNoun item in list) { if (item.noun.word.ToLower() == terminalKeyword.ToLower()) { list2.Add(item); } } for (int num = list2.Count - 1; num >= 0; num--) { Plugin.Spam("Deleting noun: " + list2[num].noun.word + " from word: " + keyWord.word); Object.Destroy((Object)(object)list2[num].noun); } keyWord.compatibleNouns = list.ToArray(); } [Obsolete("This doesn't really work right at the moment")] public static void RemoveCompatibleNoun(ref TerminalKeyword mainWord, TerminalKeyword wordToRemove) { bool flag = false; if (mainWord.compatibleNouns == null) { return; } List<CompatibleNoun> list = new List<CompatibleNoun>(); CompatibleNoun[] compatibleNouns = mainWord.compatibleNouns; foreach (CompatibleNoun val in compatibleNouns) { if ((Object)(object)val.noun != (Object)(object)wordToRemove) { list.Add(val); continue; } flag = true; Plugin.Spam("Removing " + wordToRemove.word); } mainWord.compatibleNouns = list.ToArray(); Plugin.Spam($"DeleteCompatibleNoun of {wordToRemove.word} from {mainWord.word} complete, word removed: {flag}"); } [Obsolete("This doesn't really work right at the moment")] public static void RemoveCompatibleNoun(ref TerminalKeyword mainWord, string nounToRemove) { bool flag = false; if (mainWord.compatibleNouns == null) { return; } List<CompatibleNoun> list = new List<CompatibleNoun>(); CompatibleNoun[] compatibleNouns = mainWord.compatibleNouns; foreach (CompatibleNoun val in compatibleNouns) { if (val.noun.word.ToLower() != nounToRemove.ToLower()) { list.Add(val); continue; } flag = true; Plugin.Spam("Removing " + nounToRemove); } mainWord.compatibleNouns = list.ToArray(); Plugin.Spam($"DeleteCompatibleNoun of {nounToRemove} from {mainWord.word} complete, word removed: {flag}"); } public static void DeleteAllNouns(ref List<CompatibleNoun> nounsToDelete) { if (nounsToDelete.Count == 0) { Plugin.Spam("no nouns detected to delete"); DeleteAllKeywords(ref Plugin.keywordsAdded); return; } List<TerminalKeyword> list = Plugin.instance.Terminal.terminalNodes.allKeywords.ToList(); foreach (CompatibleNoun noun in nounsToDelete) { if (list.Any((TerminalKeyword k) => k.compatibleNouns != null && k.compatibleNouns.Contains(noun))) { List<TerminalKeyword> list2 = list.FindAll((TerminalKeyword k) => k.compatibleNouns != null && k.compatibleNouns.Contains(noun)); foreach (TerminalKeyword item in list2) { List<CompatibleNoun> list3 = item.compatibleNouns.ToList(); if (list3.Remove(noun)) { item.compatibleNouns = list3.ToArray(); Plugin.Spam(noun.noun.word + " removed from word: " + item.word); } else { Plugin.WARNING("Unable to remove compatible noun: " + noun.noun.word + " from word: " + item.word); } } } else { Plugin.WARNING("Unable to find any words " + noun.noun.word + " is associated to"); } } Plugin.nounsAdded.Clear(); Plugin.Spam("DeleteAllNouns Completed"); DeleteAllKeywords(ref Plugin.keywordsAdded); } public static void DeleteAllKeywords(ref List<TerminalKeyword> keywordList) { if (keywordList.Count == 0) { return; } List<TerminalKeyword> list = keywordList; List<TerminalKeyword> list2 = Plugin.instance.Terminal.terminalNodes.allKeywords.ToList(); foreach (TerminalKeyword keyword in keywordList) { for (int num = list2.Count - 1; num >= 0; num--) { if ((Object)(object)list2[num] == (Object)(object)keyword) { Plugin.Spam("Removing " + keyword.word + " from all keywords list"); list2.RemoveAt(num); break; } } } for (int num2 = list.Count - 1; num2 >= 0; num2--) { Plugin.Spam("Deleting keyword Object: " + list[num2].word); Object.Destroy((Object)(object)list[num2]); } keywordList.Clear(); Plugin.instance.Terminal.terminalNodes.allKeywords = list2.ToArray(); } public static void DeleteAllNodes(ref Dictionary<TerminalNode, int> nodeDictionary) { List<TerminalNode> list = new List<TerminalNode>(); foreach (KeyValuePair<TerminalNode, int> item in nodeDictionary) { list.Add(item.Key); } nodeDictionary.Clear(); for (int num = list.Count - 1; num >= 0; num--) { Plugin.Spam("Deleting node: " + ((Object)list[num]).name); Object.Destroy((Object)(object)list[num]); } } public static void DeleteAllNodes(ref Dictionary<TerminalNode, Func<string>> nodeDictionary) { if (nodeDictionary.Count == 0) { return; } List<TerminalNode> list = new List<TerminalNode>(); foreach (KeyValuePair<TerminalNode, Func<string>> item in nodeDictionary) { list.Add(item.Key); } nodeDictionary.Clear(); for (int num = list.Count - 1; num >= 0; num--) { Plugin.Spam("Deleting node: " + ((Object)list[num]).name); Object.Destroy((Object)(object)list[num]); } } public static void DeleteAllNodes(ref List<TerminalNode> nodeList) { if (nodeList.Count == 0) { return; } List<TerminalNode> list = new List<TerminalNode>(); foreach (TerminalNode node in nodeList) { list.Add(node); } nodeList.Clear(); for (int num = list.Count - 1; num >= 0; num--) { Plugin.Spam("Deleting node: " + ((Object)list[num]).name); Object.Destroy((Object)(object)list[num]); } } public static void DeleteMatchingNode(string nodeName) { List<TerminalNode> allNodes = LogicHandling.GetAllNodes(); for (int num = allNodes.Count - 1; num >= 0; num--) { if (((Object)allNodes[num]).name.Equals(nodeName)) { Object.Destroy((Object)(object)allNodes[num]); Plugin.Spam("Node: [" + nodeName + "] removed"); break; } } } public static bool TryGetAndDeleteUnlockableName(string unlockableName, out int indexPos) { List<UnlockableItem> list = StartOfRound.Instance.unlockablesList.unlockables.ToList(); for (int num = list.Count - 1; num >= 0; num--) { if (list[num].unlockableName.Equals(unlockableName)) { Plugin.Spam("Unlockable: [" + unlockableName + "] found! Removing unlockable and noting index position"); StartOfRound.Instance.unlockablesList.unlockables.Remove(list[num]); indexPos = num; return true; } } indexPos = -1; return false; } } public class LogicHandling { public static bool GetNewDisplayText(MainListing providedListing, ref TerminalNode node) { if (providedListing.Listing.Count == 0) { return false; } Dictionary<TerminalNode, Func<string>> listing = providedListing.Listing; if (listing.Count < 1) { return false; } Plugin.Spam("command dictionary is not null in provided listing"); if ((Object)(object)node == (Object)null) { return false; } if (EventManager.GetNewDisplayText.Listeners > 0) { node = EventManager.GetNewDisplayText.NodeInvoke(ref node); } if (listing.TryGetValue(node, out var value)) { CommonTerminal.parseNode = node; Plugin.Spam("Func<string> found for " + ((Object)node).name); node.displayText = value(); return true; } Plugin.Spam("Not in special nodeListing dictionary"); return false; } public static bool GetNewDisplayText(List<MainListing> providedListing, ref TerminalNode node) { if (providedListing.Count == 0) { return false; } if ((Object)(object)node == (Object)null) { return false; } bool result = false; int num = 0; foreach (MainListing item in providedListing) { if (item.Listing.Count >= 1) { Dictionary<TerminalNode, Func<string>> listing = item.Listing; num++; Plugin.Spam($"command dictionary in this listing is not empty ({num})"); if (EventManager.GetNewDisplayText.Listeners > 0) { node = EventManager.GetNewDisplayText.NodeInvoke(ref node); } if (listing.TryGetValue(node, out var value)) { CommonTerminal.parseNode = node; Plugin.MoreLogs("Func<string> found for " + ((Object)node).name + " in one of provided listings"); node.displayText = value(); result = true; break; } Plugin.Spam("Not in special nodeListing dictionary"); } } Plugin.MoreLogs("provided listings do not contain this node"); return result; } public static bool GetDisplayFromFaux(List<FauxKeyword> fauxWords, string words, ref TerminalNode node) { Plugin.Spam("GetDisplayFromFaux " + words); string text = words.Split(new char[1] { ' ' })[0]; foreach (FauxKeyword fauxWord in fauxWords) { if (fauxWord.ResultFunc == null || fauxWord.Keyword == null || (Object)(object)fauxWord.MainPage == (Object)null) { continue; } fauxWord.thisNode.displayText = ""; if (words.StartsWith(fauxWord.Keyword.Substring(0, 3), ignoreCase: true, CultureInfo.InvariantCulture) && (Object)(object)Plugin.instance.Terminal.currentNode == (Object)(object)fauxWord.MainPage) { if (fauxWord.requireExact && words.ToLower() != fauxWord.Keyword.ToLower()) { return false; } Plugin.Spam("Using faux word associated with MainPage"); if (fauxWord.ConfirmFunc != null && !fauxWord.GetConfirm) { fauxWord.GetConfirm = true; } fauxWord.thisNode.displayText = fauxWord.ResultFunc(); node = fauxWord.thisNode; return true; } if ((Object)(object)Plugin.instance.Terminal.currentNode == (Object)(object)fauxWord.thisNode && fauxWord.GetConfirm) { Plugin.Spam("getting confirmation for this faux word"); if (words.StartsWith("c", ignoreCase: false, null)) { fauxWord.thisNode.displayText = fauxWord.ConfirmFunc(); node = fauxWord.thisNode; fauxWord.GetConfirm = false; } else if (words.StartsWith("d", ignoreCase: false, null)) { fauxWord.thisNode.displayText = fauxWord.DenyFunc(); node = fauxWord.thisNode; fauxWord.GetConfirm = false; } else { if (!words.StartsWith(fauxWord.Keyword, ignoreCase: false, null)) { return false; } fauxWord.thisNode.displayText = fauxWord.ResultFunc(); node = fauxWord.thisNode; } return true; } if (!words.StartsWith(fauxWord.Keyword.Substring(0, 3), ignoreCase: true, CultureInfo.InvariantCulture) || !fauxWords.Any((FauxKeyword f) => (Object)(object)f.thisNode == (Object)(object)Plugin.instance.Terminal.currentNode && f.AllowOtherFauxWords)) { continue; } if (fauxWord.requireExact && words.ToLower() != fauxWord.Keyword.ToLower()) { return false; } Plugin.Spam("Using faux word that can be called from other fauxwords"); if (fauxWord.ConfirmFunc != null && !fauxWord.GetConfirm) { fauxWord.GetConfirm = true; } fauxWord.thisNode.displayText = fauxWord.ResultFunc(); node = fauxWord.thisNode; return true; } return false; } public static bool TryGetFuncFromNode(List<MainListing> providedListing, ref TerminalNode node, out Func<string> returnFunc) { if ((Object)(object)node == (Object)null || providedListing.Count == 0) { Plugin.WARNING("node is null or listings do not exist"); returnFunc = null; return false; } int num = 0; foreach (MainListing item in providedListing) { Dictionary<TerminalNode, Func<string>> listing = item.Listing; if (listing.Count >= 1) { num++; Plugin.Spam($"command dictionary in this listing is not null ({num})"); if (listing.TryGetValue(node, out var value)) { Plugin.MoreLogs("Func<string> found for " + ((Object)node).name + " in one of provided listings"); returnFunc = value; return true; } Plugin.Spam("Not in this special nodeListing dictionary"); } } Plugin.MoreLogs("provided listings do not contain this node"); returnFunc = null; return false; } public static bool TryGetFromAllNodes(string nodeName, out TerminalNode outNode) { List<TerminalNode> allNodes = GetAllNodes(); outNode = null; foreach (TerminalNode item in allNodes) { if ((Object)(object)item == (Object)null || !(((Object)item).name == nodeName)) { continue; } Plugin.Spam(nodeName + " found!"); outNode = item; return true; } Plugin.Spam(nodeName + " could not be found, result set to null."); return false; } public static List<TerminalNode> GetAllNodes() { return Resources.FindObjectsOfTypeAll<TerminalNode>().ToList(); } public static void SetTerminalInput(string terminalInput) { Plugin.instance.Terminal.TextChanged(Plugin.instance.Terminal.currentText.Substring(0, Plugin.instance.Terminal.currentText.Length - Plugin.instance.Terminal.textAdded) + terminalInput); Plugin.instance.Terminal.screenText.text = Plugin.instance.Terminal.currentText; Plugin.instance.Terminal.textAdded = terminalInput.Length; } [Obsolete("Use TryGetFuncFromNode instead to avoid getting NULL funcs")] public static Func<string> GetFuncFromNode(List<MainListing> providedListing, ref TerminalNode node) { if ((Object)(object)node == (Object)null || providedListing.Count == 0) { Plugin.WARNING("node is null or listings do not exist"); return null; } int num = 0; foreach (MainListing item in providedListing) { Dictionary<TerminalNode, Func<string>> listing = item.Listing; if (listing.Count >= 1) { num++; Plugin.Spam($"command dictionary in this listing is not null ({num})"); if (listing.TryGetValue(node, out var value)) { Plugin.MoreLogs("Func<string> found for " + ((Object)node).name + " in one of provided listings"); return value; } Plugin.Spam("Not in this special nodeListing dictionary"); } } Plugin.MoreLogs("provided listings do not contain this node"); return null; } [Obsolete("Use TryGetFromAllNodes instead to avoid getting NULL funcs")] public static TerminalNode GetFromAllNodes(string nodeName) { List<TerminalNode> allNodes = GetAllNodes(); foreach (TerminalNode item in allNodes) { if ((Object)(object)item == (Object)null || !(((Object)item).name == nodeName)) { continue; } Plugin.Spam(nodeName + " found!"); return item; } Plugin.Spam(nodeName + " could not be found, result set to null."); return null; } } } namespace OpenLib.ConfigManager { public class ConfigHelper { public static List<string> GetAcceptableValues(AcceptableValueBase acceptableValueBase) { List<string> result = new List<string>(); if (acceptableValueBase == null) { return result; } string text = acceptableValueBase.ToDescriptionString(); text = text.Replace("# Acceptable values:", "").Replace(" ", ""); return CommonStringStuff.GetKeywordsPerConfigItem(text, ','); } public static List<float> GetAcceptableValueF(AcceptableValueBase acceptableValueBase) { List<float> result = new List<float>(); if (acceptableValueBase == null) { return result; } string text = acceptableValueBase.ToDescriptionString(); Plugin.Spam(text); text = text.Replace("# Acceptable value range: From ", "").Replace("to", "").Replace(" ", ","); return CommonStringStuff.GetFloatListFromStringList(CommonStringStuff.GetKeywordsPerConfigItem(text, ',')); } public static void ChangeBool(ConfigFile ModConfig, ConfigEntryBase configItem, string newValue) { ConfigEntry<bool> val = default(ConfigEntry<bool>); if (newValue.Length != 0 && ModConfig.TryGetEntry<bool>(configItem.Definition, ref val)) { if (newValue == "true") { val.Value = true; } else { val.Value = false; } } } public static void ChangeString(ConfigFile ModConfig, ConfigEntryBase configItem, string newValue) { ConfigEntry<string> val = default(ConfigEntry<string>); if (newValue.Length != 0 && ModConfig.TryGetEntry<string>(configItem.Definition, ref val)) { val.Value = newValue; } } public static void ChangeInt(ConfigFile ModConfig, ConfigEntryBase configItem, string newValue) { ConfigEntry<int> val = default(ConfigEntry<int>); if (newValue.Length != 0 && ModConfig.TryGetEntry<int>(configItem.Definition, ref val)) { val.Value = int.Parse(newValue); } } public static void ChangeFloat(ConfigFile ModConfig, ConfigEntryBase configItem, string newValue) { ConfigEntry<float> val = default(ConfigEntry<float>); if (newValue.Length != 0 && ModConfig.TryGetEntry<float>(configItem.Definition, ref val)) { val.Value = float.Parse(newValue); } } public static bool TryFindConfigItem(string query, ConfigFile ModConfig, out ConfigEntryBase configItem) { Dictionary<ConfigDefinition, ConfigEntryBase> dictionary = new Dictionary<ConfigDefinition, ConfigEntryBase>(); ConfigEntryBase[] configEntries = ModConfig.GetConfigEntries(); foreach (ConfigEntryBase val in configEntries) { dictionary.Add(val.Definition, val); Plugin.Spam($"added {val.Definition} to list of configItems to check"); } foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in dictionary) { if (item.Key.Key == query) { configItem = item.Value; return true; } } configItem = null; return false; } } public class ConfigMisc { public static bool CheckChangedConfigSetting(List<ManagedConfig> managedItems, ConfigEntryBase entryBase) { ConfigEntry<bool> val = default(ConfigEntry<bool>); ConfigEntry<string> val2 = default(ConfigEntry<string>); foreach (ManagedConfig managedItem in managedItems) { if (!(managedItem.configDescription == entryBase.Description.Description)) { continue; } if (entryBase.BoxedValue.GetType() == typeof(bool)) { if (entryBase.ConfigFile.TryGetEntry<bool>(entryBase.Definition, ref val)) { if (managedItem.BoolValue != val.Value) { managedItem.ConfigChange(val.Value); Plugin.Spam("Updating config item: " + ((ConfigEntryBase)val).Definition.Key + " in managedItems"); return true; } Plugin.Spam("item value matches config item: " + ((ConfigEntryBase)val).Definition.Key); } } else if (entryBase.BoxedValue.GetType() == typeof(string) && entryBase.ConfigFile.TryGetEntry<string>(entryBase.Definition, ref val2)) { if (managedItem.StringValue != val2.Value) { managedItem.ConfigChange(val2.Value); Plugin.Spam("Updating config item: " + ((ConfigEntryBase)val2).Definition.Key + " in managedItems"); List<string> keywordsPerConfigItem = CommonStringStuff.GetKeywordsPerConfigItem(val2.Value); managedItem.relatedConfigItem.KeywordList = keywordsPerConfigItem; return true; } Plugin.Spam("item value matches config item: " + ((ConfigEntryBase)val2).Definition.Key); } } Plugin.Spam("could not match changed config setting to any managed config items"); return false; } public static bool ShouldReloadConfigNow(ConfigEntry<string> entry) { if ((Object)(object)Plugin.instance.Terminal != (Object)null) { if (!EventUsage.configsToReload.Contains(((ConfigEntryBase)entry).ConfigFile)) { EventUsage.configsToReload.Add(((ConfigEntryBase)entry).ConfigFile); } return false; } return true; } } public class ConfigSync { public static void UpdateFromHost(string key, bool value, ConfigFile myConfig) { if (ConfigHelper.TryFindConfigItem(key, myConfig, out ConfigEntryBase configItem) && ((object)configItem).GetType() == typeof(bool)) { ConfigEntry<bool> val = configItem as ConfigEntry<bool>; if (val.Value == value) { Plugin.Spam($"Config - {key} verified set to {value}"); return; } val.Value = value; Plugin.WARNING($"Config sync has updated {key} to {value}"); } } public static void UpdateFromH