Decompiled source of OpenLib v0.1.8

OpenLib.dll

Decompiled a month ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
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 LobbyCompatibility.Enums;
using LobbyCompatibility.Features;
using Microsoft.CodeAnalysis;
using OpenLib.Common;
using OpenLib.Compat;
using OpenLib.ConfigManager;
using OpenLib.CoreMethods;
using OpenLib.Events;
using OpenLib.Menus;
using UnityEngine;

[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.1.8")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.8.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
	[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), "ChangeLevel")]
	public class RouteEvent
	{
		public static void Postfix()
		{
			EventManager.StartOfRoundChangeLevel.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();
		}
	}
	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)
		{
			TerminalNode val = EventManager.TerminalParseSent.NodeInvoke(ref __result);
			__result = val;
		}
	}
	[HarmonyPatch(typeof(Terminal), "SetTerminalInUseClientRpc")]
	public class TerminalInUseRpcPatch
	{
		private static void Postfix()
		{
			EventManager.SetTerminalInUse.Invoke();
		}
	}
	[HarmonyPatch(typeof(Terminal), "LoadNewNodeIfAffordable")]
	public class AffordableNodePatch
	{
		private static void Postfix(TerminalNode node)
		{
			EventManager.TerminalLoadIfAffordable.Invoke(node);
		}
	}
	[BepInPlugin("darmuh.OpenLib", "OpenLib", "0.1.8")]
	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.1.8";
		}

		public static Plugin instance;

		internal static ManualLogSource Log;

		public bool LobbyCompat = false;

		public bool TerminalFormatter = false;

		public static List<TerminalKeyword> keywordsAdded = new List<TerminalKeyword>();

		public static List<TerminalNode> nodesAdded = new List<TerminalNode>();

		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.1.8!");
			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();
			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 MenuStuff
	{
	}
	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>();
			foreach (ManagedConfig managedBool in managedBools)
			{
				if (managedBool.menuItem != null)
				{
					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 (((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 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++;
			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;
			currentCategory = GetCategoryFromNode(CommonTerminal.parseNode);
			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 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
				};
			}
			return null;
		}
	}
}
namespace OpenLib.Common
{
	public class CommonEnums
	{
		public static bool quitTerminalEnum;

		public static IEnumerator TerminalQuitter(Terminal terminal)
		{
			if (!quitTerminalEnum)
			{
				quitTerminalEnum = true;
				yield return (object)new WaitForSeconds(0.5f);
				terminal.QuitTerminal(true);
				quitTerminalEnum = false;
			}
		}

		public static IEnumerator TerminalQuitter(Terminal terminal, bool syncTerminalInUse)
		{
			if (!quitTerminalEnum)
			{
				quitTerminalEnum = true;
				yield return (object)new WaitForSeconds(0.5f);
				terminal.QuitTerminal(syncTerminalInUse);
				quitTerminalEnum = false;
			}
		}
	}
	public class CommonTerminal
	{
		public static TerminalNode parseNode;

		public static void ToggleScreen(bool status)
		{
			((MonoBehaviour)Plugin.instance.Terminal).StartCoroutine(Plugin.instance.Terminal.waitUntilFrameEndToSetActive(status));
			Plugin.Spam($"Screen set to {status}");
		}

		public static TerminalNode GetNodeFromList(string query, Dictionary<string, TerminalNode> nodeListing)
		{
			foreach (KeyValuePair<string, TerminalNode> item in nodeListing)
			{
				if (item.Key == query)
				{
					return item.Value;
				}
			}
			return null;
		}

		public static void AddShopItemsToFurnitureList(List<TerminalNode> UnlockableNodes)
		{
			foreach (TerminalNode UnlockableNode in UnlockableNodes)
			{
				if (!Plugin.instance.Terminal.ShipDecorSelection.Contains(UnlockableNode))
				{
					Plugin.instance.Terminal.ShipDecorSelection.Add(UnlockableNode);
					Plugin.Spam("adding " + UnlockableNode.creatureName + " to shipdecorselection");
				}
				else
				{
					Plugin.Spam(UnlockableNode.creatureName + " already in shipdecorselection");
				}
			}
			Plugin.Spam("nodes have been added");
		}

		public static string ClearText()
		{
			string result = "\n";
			Plugin.Spam("display text cleared for real this time!!!");
			return result;
		}
	}
	public class Misc
	{
		public static PlayerControllerB GetPlayerFromName(string playerName)
		{
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (val.playerUsername.ToLower() == playerName)
				{
					return val;
				}
			}
			return null;
		}

		public static PlayerControllerB GetPlayerUsingTerminal()
		{
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (!val.isPlayerDead && (Object)(object)val.currentTriggerInAnimationWith == (Object)(object)Plugin.instance.Terminal.terminalTrigger)
				{
					Plugin.MoreLogs("Player: " + val.playerUsername + " detected using terminal.");
					return val;
				}
			}
			return null;
		}

		public static int HostClientID()
		{
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (val.isHostPlayerObject)
				{
					Plugin.MoreLogs($"Player: {val.playerUsername} is the host, client ID: {val.playerClientId}.");
					return (int)val.playerClientId;
				}
			}
			return -1;
		}

		public static Color HexToColor(string hex)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			Color result = default(Color);
			ColorUtility.TryParseHtmlString(hex, ref result);
			return result;
		}

		public static void LogColorBeforeChange(Color color, ConfigEntry<string> entry)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			string text = ColorUtility.ToHtmlStringRGB(color);
			Plugin.Log.LogDebug((object)("Previous Color noted as [" + text + "] for configItem - " + ((ConfigEntryBase)entry).Definition.Key));
		}
	}
	public class CommonStringStuff
	{
		public static string GetNextPage(List<string> categoryItems, string categoryTitle, int pageSize, int currentPage, out bool isNextEnabled)
		{
			currentPage = Mathf.Clamp(currentPage, 1, Mathf.CeilToInt((float)categoryItems.Count / (float)pageSize));
			int num = (currentPage - 1) * pageSize;
			int num2 = Mathf.Min(num + pageSize, categoryItems.Count);
			int num3 = 0;
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("============ All [" + categoryTitle.ToUpper() + "] Commands  ============");
			stringBuilder.Append("\r\n");
			for (int i = num; i < num2; i++)
			{
				string text = categoryItems[i];
				stringBuilder.Append(text + "\r\n");
				num3++;
			}
			int num4 = pageSize - num3;
			for (int j = 0; j < num4; j++)
			{
				stringBuilder.Append("\r\n");
			}
			stringBuilder.Append("\r\n");
			stringBuilder.Append($"Page {currentPage}/{Mathf.CeilToInt((float)categoryItems.Count / (float)pageSize)}\r\n");
			if (num2 < categoryItems.Count)
			{
				stringBuilder.Append("Type next to see the next page of [" + categoryTitle + "] commands!\r\n");
				isNextEnabled = true;
			}
			else
			{
				isNextEnabled = false;
			}
			return stringBuilder.ToString();
		}

		public static string[] GetWords()
		{
			string text = Plugin.instance.Terminal.screenText.text.Substring(Plugin.instance.Terminal.screenText.text.Length - Plugin.instance.Terminal.textAdded);
			return text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
		}

		public static string[] GetWordsAndKeyword(List<string> configItemWords, string[] words)
		{
			List<string> list = new List<string>();
			bool flag = false;
			foreach (string text in words)
			{
				Plugin.MoreLogs("checking " + text);
				foreach (string configItemWord in configItemWords)
				{
					if (configItemWord.Contains(text))
					{
						list.Add(configItemWord);
						flag = true;
						Plugin.MoreLogs("adding " + configItemWord + " to list");
						break;
					}
				}
				if (!flag)
				{
					list.Add(text);
					Plugin.MoreLogs("adding non-keyword, word: " + text);
				}
			}
			return list.ToArray();
		}

		public static List<string> GetKeywordsPerConfigItem(string configItem)
		{
			List<string> result = new List<string>();
			if (configItem.Length > 0)
			{
				result = (from item in configItem.Split(new char[1] { ';' })
					select item.TrimStart(Array.Empty<char>())).ToList();
			}
			return result;
		}

		public static List<string> GetKeywordsPerConfigItem(string configItem, char separator)
		{
			List<string> result = new List<string>();
			if (configItem.Length > 0)
			{
				result = (from item in configItem.Split(new char[1] { separator })
					select item.TrimStart(Array.Empty<char>())).ToList();
			}
			return result;
		}

		public static List<int> GetNumberListFromStringList(List<string> stringList)
		{
			List<int> list = new List<int>();
			foreach (string @string in stringList)
			{
				if (int.TryParse(@string, out var result))
				{
					list.Add(result);
				}
				else
				{
					Plugin.ERROR("Could not parse " + @string + " to integer");
				}
			}
			return list;
		}

		public static List<string> GetItemList(string rawList)
		{
			List<string> result = new List<string>();
			if (rawList.Length > 0)
			{
				result = (from item in rawList.Split(new char[1] { ',' })
					select item.TrimStart(Array.Empty<char>())).ToList();
			}
			return result;
		}

		public static List<string> GetListToLower(List<string> stringList)
		{
			List<string> list = new List<string>();
			foreach (string @string in stringList)
			{
				list.Add(@string.ToLower());
			}
			return list;
		}

		public static string GetKeywordsForMenuItem(List<string> itemKeywords)
		{
			StringBuilder stringBuilder = new StringBuilder();
			foreach (string itemKeyword in itemKeywords)
			{
				stringBuilder.Append(itemKeyword + ", ");
			}
			string text = stringBuilder.ToString();
			return text.Remove(text.Length - 2);
		}

		public static string GetCleanedScreenText(Terminal __instance)
		{
			string s = __instance.screenText.text.Substring(__instance.screenText.text.Length - __instance.textAdded);
			return RemovePunctuation(s);
		}

		public static string RemovePunctuation(string s)
		{
			StringBuilder stringBuilder = new StringBuilder();
			foreach (char c in s)
			{
				if (!char.IsPunctuation(c))
				{
					stringBuilder.Append(c);
				}
			}
			return stringBuilder.ToString().ToLower();
		}
	}
	public class StartGame
	{
		internal static bool oneTimeOnly;

		internal static void CompatibilityCheck()
		{
			if (SoftCompatibility("BMX.LobbyCompatibility", ref Plugin.instance.LobbyCompat))
			{
				Plugin.Spam("LobbyCompatibility detected, setting appropriate Lobby Compatibility Level depending on networking status");
				BMX_LobbyCompat.SetCompat(isNetworked: false);
			}
			if (SoftCompatibility("TerminalFormatter", ref Plugin.instance.TerminalFormatter))
			{
				Plugin.Spam("Terminal Formatter by mrov detected!");
			}
		}

		internal static void OnGameStart()
		{
			CompatibilityCheck();
			oneTimeOnly = false;
		}

		public static bool SoftCompatibility(string PluginGUID, ref bool isDetected)
		{
			if (Chainloader.PluginInfos.ContainsKey(PluginGUID))
			{
				string name = Assembly.GetCallingAssembly().GetName().Name;
				isDetected = true;
				Plugin.Log.LogInfo((object)$"{PluginGUID} detected! Plugin: {name} has set compatibility bool - {isDetected}");
				return isDetected;
			}
			return isDetected = false;
		}
	}
	public class Teleporter
	{
		public static ShipTeleporter NormalTP;

		public static ShipTeleporter InverseTP;

		public static void CheckTeleporterTypeAndAssign(ShipTeleporter instance)
		{
			if (instance.isInverseTeleporter)
			{
				ITPexists(instance);
			}
			else
			{
				TPexists(instance);
			}
		}

		public static void TPexists(ShipTeleporter instance)
		{
			NormalTP = instance;
			Plugin.MoreLogs("NormalTP instance detected and set.");
			EventManager.NormalTPFound.Invoke();
		}

		public static void ITPexists(ShipTeleporter instance)
		{
			InverseTP = instance;
			Plugin.MoreLogs("InverseTP instance detected and set.");
			EventManager.InverseTPFound.Invoke();
		}
	}
	public class TerminalStart
	{
		public static bool delayStartEnum;

		internal static void TerminalStartGroupDelay()
		{
			Plugin.Spam("Starting TerminalDelayStartEnumerator");
			((MonoBehaviour)Plugin.instance.Terminal).StartCoroutine(TerminalDelayStartEnumerator());
		}

		internal static IEnumerator TerminalDelayStartEnumerator()
		{
			if (!delayStartEnum)
			{
				delayStartEnum = true;
				yield return (object)new WaitForSeconds(1f);
				Plugin.MoreLogs("1 Second delay methods starting.");
				EventManager.TerminalDelayStart.Invoke();
				AddStoreItems();
				delayStartEnum = false;
			}
		}

		public static void AddStoreItems()
		{
			if (!Plugin.instance.TerminalFormatter)
			{
				AddShopItemsToFurnitureList();
			}
		}

		private static void AddShopItemsToFurnitureList()
		{
			foreach (TerminalNode shopNode in Plugin.ShopNodes)
			{
				if (!Plugin.instance.Terminal.ShipDecorSelection.Contains(shopNode))
				{
					Plugin.instance.Terminal.ShipDecorSelection.Add(shopNode);
					Plugin.Spam("adding " + shopNode.creatureName + " to shipdecorselection");
				}
				else
				{
					Plugin.Spam(shopNode.creatureName + " already in shipdecorselection");
				}
			}
			Plugin.Spam("nodes have been added");
		}
	}
}
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 SetTerminalInUse = 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.CustomEvent<TerminalNode> GetNewDisplayText = new Events.CustomEvent<TerminalNode>();

		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 PlayerSpawn = 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 TerminalDelayStart = 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()
			{
				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);
		}

		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()
		{
			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 OnUsingTerminal()
		{
			Plugin.MoreLogs("Start Using Terminal Postfix");
		}

		public static TerminalNode OnParseSent(ref TerminalNode node)
		{
			Plugin.Spam("parse event");
			if ((Object)(object)node == (Object)null)
			{
				Plugin.ERROR("node detected as NULL");
				return node;
			}
			string cleanedScreenText = CommonStringStuff.GetCleanedScreenText(Plugin.instance.Terminal);
			if (cleanedScreenText.Length > 0)
			{
				string[] array = cleanedScreenText.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
				if (ConfigSetup.defaultListing.specialListString.ContainsKey(array[0]))
				{
					TerminalNode nodeFromList = CommonTerminal.GetNodeFromList(array[0], ConfigSetup.defaultListing.specialListString);
					node = nodeFromList;
				}
			}
			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");
			}
		}
	}
}
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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			TerminalKeyword[] allKeywords = Plugin.instance.Terminal.terminalNodes.allKeywords;
			List<TerminalKeyword> list = new List<TerminalKeyword>(allKeywords.Length);
			list.AddRange(allKeywords);
			List<TerminalKeyword> list2 = list;
			List<CompatibleNoun> list3 = new List<CompatibleNoun>();
			TerminalKeyword val = ScriptableObject.CreateInstance<TerminalKeyword>();
			((Object)val).name = keyWord + "_keyword";
			val.word = keyWord.ToLower();
			val.isVerb = false;
			val.specialKeywordResult = existingNode;
			if (existingNode.terminalOptions != null)
			{
				CompatibleNoun[] terminalOptions = existingNode.terminalOptions;
				List<CompatibleNoun> list4 = new List<CompatibleNoun>(terminalOptions.Length);
				list4.AddRange(terminalOptions);
				list3 = list4;
				Plugin.Spam(((Object)existingNode).name + " has existing terminalOptions");
			}
			CompatibleNoun item = new CompatibleNoun
			{
				noun = val,
				result = existingNode
			};
			list3.Add(item);
			existingNode.terminalOptions = list3.ToArray();
			list2.Add(val);
			if (addToList)
			{
				Plugin.keywordsAdded.Add(val);
			}
			Plugin.Spam("Adding " + keyWord + " to existing node " + ((Object)existingNode).name);
			Plugin.instance.Terminal.terminalNodes.allKeywords = list2.ToArray();
		}

		public static TerminalKeyword AddKeywordToNode(string keyWord, TerminalNode existingNode, bool addToList = true)
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			TerminalKeyword[] allKeywords = Plugin.instance.Terminal.terminalNodes.allKeywords;
			List<TerminalKeyword> list = new List<TerminalKeyword>(allKeywords.Length);
			list.AddRange(allKeywords);
			List<TerminalKeyword> list2 = list;
			List<CompatibleNoun> list3 = new List<CompatibleNoun>();
			TerminalKeyword val = ScriptableObject.CreateInstance<TerminalKeyword>();
			((Object)val).name = keyWord + "_keyword";
			val.word = keyWord.ToLower();
			val.isVerb = false;
			val.specialKeywordResult = existingNode;
			if (existingNode.terminalOptions != null)
			{
				CompatibleNoun[] terminalOptions = existingNode.terminalOptions;
				List<CompatibleNoun> list4 = new List<CompatibleNoun>(terminalOptions.Length);
				list4.AddRange(terminalOptions);
				list3 = list4;
				Plugin.Spam(((Object)existingNode).name + " has existing terminalOptions");
			}
			CompatibleNoun item = new CompatibleNoun
			{
				noun = val,
				result = existingNode
			};
			list3.Add(item);
			existingNode.terminalOptions = list3.ToArray();
			list2.Add(val);
			if (addToList)
			{
				Plugin.keywordsAdded.Add(val);
			}
			Plugin.Spam("Adding " + keyWord + " to existing node " + ((Object)existingNode).name);
			Plugin.instance.Terminal.terminalNodes.allKeywords = list2.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 var returnNode))
			{
				returnNode.displayText = displayText;
				returnNode.clearPreviousText = clearPrevious;
			}
			else
			{
				returnNode = ScriptableObject.CreateInstance<TerminalNode>();
				((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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			TerminalNode existingNode = LogicHandling.GetFromAllNodes("OtherCommands");
			TerminalKeyword[] allKeywords = Plugin.instance.Terminal.terminalNodes.allKeywords;
			List<TerminalKeyword> list = new List<TerminalKeyword>(allKeywords.Length);
			list.AddRange(allKeywords);
			List<TerminalKeyword> list2 = list;
			if (!DynamicBools.IsCommandCreatedAlready(keyWord, displayText, list2))
			{
				CommonThings.CheckForAndDeleteKeyWord(keyWord.ToLower());
				TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
				((Object)val).name = nodeName;
				val.displayText = displayText;
				val.clearPreviousText = clearText;
				TerminalKeyword val2 = ScriptableObject.CreateInstance<TerminalKeyword>();
				((Object)val2).name = nodeName + "_keyword";
				val2.word = keyWord.ToLower();
				val2.isVerb = isVerb;
				val2.specialKeywordResult = val;
				new CompatibleNoun
				{
					noun = val2,
					result = val
				};
				list2.Add(val2);
				Plugin.instance.Terminal.terminalNodes.allKeywords = list2.ToArray();
				if (!Plugin.nodesAdded.Contains(val))
				{
					Plugin.nodesAdded.Add(val);
				}
				if (!Plugin.keywordsAdded.Contains(val2))
				{
					Plugin.keywordsAdded.Add(val2);
				}
				if (category.ToLower() == "other")
				{
					AddToExistingNodeText(keywordDescription ?? "", ref existingNode);
					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 result = null;
			List<string> list = new List<string>();
			if (stringValue != null)
			{
				list = CommonStringStuff.GetKeywordsPerConfigItem(stringValue);
			}
			foreach (string item in list)
			{
				TerminalKeyword[] allKeywords = Plugin.instance.Terminal.terminalNodes.allKeywords;
				List<TerminalKeyword> list2 = new List<TerminalKeyword>(allKeywords.Length);
				list2.AddRange(allKeywords);
				List<TerminalKeyword> list3 = list2;
				if (DynamicBools.IsCommandCreatedAlready(yourModListing.Listing, item, commandAction, list3, out var _) && !reuseFunc)
				{
					continue;
				}
				CommonThings.CheckForAndDeleteKeyWord(item.ToLower());
				if (DynamicBools.DoesNodeExist(yourModListing.Listing, commandAction, out var node) && !reuseFunc)
				{
					AddKeywordToExistingNode(item, node);
					Plugin.Spam("existing node found " + ((Object)node).name + ", reusing associated func and adding additional keyword " + item);
					continue;
				}
				TerminalNode node2 = ScriptableObject.CreateInstance<TerminalNode>();
				((Object)node2).name = nodeName;
				node2.displayText = nodeName;
				node2.clearPreviousText = clearText;
				node2.buyUnlockable = false;
				result = node2;
				TerminalKeyword keyword = ScriptableObject.CreateInstance<TerminalKeyword>();
				((Object)keyword).name = nodeName + "_keyword";
				keyword.word = item.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)
				{
					list3.Add(confirm.noun);
					Plugin.keywordsAdded.Add(confirm.noun);
					list3.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 " + item);
				}
				yourModListing.Listing.Add(node2, commandAction);
				list3.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 = list3.ToArray();
			}
			return result;
		}

		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)
			{
				TerminalKeyword[] allKeywords = Plugin.instance.Terminal.terminalNodes.allKeywords;
				List<TerminalKeyword> list2 = new List<TerminalKeyword>(allKeywords.Length);
				list2.AddRange(allKeywords);
				List<TerminalKeyword> list3 = list2;
				if (DynamicBools.IsCommandCreatedAlready(yourModListing.Listing, item, commandAction, list3, out var _) && !reuseFunc)
				{
					continue;
				}
				CommonThings.CheckForAndDeleteKeyWord(item.ToLower());
				if (DynamicBools.DoesNodeExist(yourModListing.Listing, commandAction, out var node) && !reuseFunc)
				{
					AddKeywordToExistingNode(item, node);
					Plugin.Spam("existing node found " + ((Object)node).name + ", reusing associated func and adding additional keyword " + item);
					continue;
				}
				TerminalNode node2 = ScriptableObject.CreateInstance<TerminalNode>();
				((Object)node2).name = nodeName;
				node2.displayText = nodeName;
				node2.clearPreviousText = clearText;
				node2.buyUnlockable = false;
				val = node2;
				TerminalKeyword keyword = ScriptableObject.CreateInstance<TerminalKeyword>();
				((Object)keyword).name = nodeName + "_keyword";
				keyword.word = item.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)
				{
					list3.Add(confirm.noun);
					Plugin.keywordsAdded.Add(confirm.noun);
					list3.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 " + item);
				}
				yourModListing.Listing.Add(node2, commandAction);
				list3.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 = list3.ToArray();
			}
			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)
		{
			TerminalKeyword[] allKeywords = Plugin.instance.Terminal.terminalNodes.allKeywords;
			List<TerminalKeyword> list = new List<TerminalKeyword>(allKeywords.Length);
			list.AddRange(allKeywords);
			List<TerminalKeyword> list2 = list;
			Plugin.Spam(nodeName ?? "");
			Plugin.Spam(keyWord);
			bool clearPreviousText = true;
			CommonThings.CheckForAndDeleteKeyWord(keyWord.ToLower());
			TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
			((Object)val).name = nodeName;
			val.displayText = nodeName;
			val.clearPreviousText = clearPreviousText;
			val.buyUnlockable = false;
			Plugin.Spam("node created");
			TerminalKeyword val2 = ScriptableObject.CreateInstance<TerminalKeyword>();
			((Object)val2).name = nodeName + "_keyword";
			val2.word = 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");
			}
			list2.Add(val2);
			Plugin.keywordsAdded.Add(val2);
			Plugin.instance.Terminal.terminalNodes.allKeywords = list2.ToArray();
			Plugin.Spam("added to all keyword lists");
			return val;
		}

		public static TerminalNode CreateNode(ManagedConfig managedBool, string keyWord, MainListing yourModListing)
		{
			TerminalKeyword[] allKeywords = Plugin.instance.Terminal.terminalNodes.allKeywords;
			List<TerminalKeyword> list = new List<TerminalKeyword>(allKeywords.Length);
			list.AddRange(allKeywords);
			List<TerminalKeyword> list2 = list;
			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;
			if (DynamicBools.IsCommandCreatedAlready(yourModListing.Listing, keyWord, mainAction, list2, out var outKeyword) && !managedBool.reuseFunc)
			{
				return outKeyword.specialKeywordResult;
			}
			CommonThings.CheckForAndDeleteKeyWord(keyWord.ToLower());
			if (DynamicBools.DoesNodeExist(yourModListing.Listing, mainAction, out var node) && !managedBool.reuseFunc)
			{
				AddKeywordToExistingNode(keyWord, node);
				Plugin.Spam("existing node found " + ((Object)node).name + ", re-using func and adding additional keyword " + keyWord);
				return node;
			}
			TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
			((Object)val).name = text;
			val.displayText = text;
			val.clearPreviousText = clearText;
			val.buyUnlockable = false;
			managedBool.TerminalNode = val;
			TerminalKeyword keyword = ScriptableObject.CreateInstance<TerminalKeyword>();
			((Object)keyword).name = text + "_keyword";
			keyword.word = keyWord.ToLower();
			keyword.isVerb = false;
			keyword.specialKeywordResult = val;
			CompatibleNoun confirm = null;
			CompatibleNoun deny = null;
			if (managedBool.CommandType == 1)
			{
				AddConfirm(text, managedBool, out confirm, out deny);
				if (managedBool.ConfirmAction != null)
				{
					yourModListing.Listing.Add(confirm.result, managedBool.ConfirmAction);
					Plugin.Spam("confirmResult FUNC added");
				}
				if (managedBool.DenyAction != null)
				{
					yourModListing.Listing.Add(deny.result, managedBool.DenyAction);
					Plugin.Spam("denyResult FUNC added");
				}
				val.acceptAnything = false;
				Plugin.Spam("command type 1 detected, adding basic confirmation");
			}
			else if (managedBool.CommandType == 2)
			{
				AddStoreCommand(text, ref keyword, managedBool, yourModListing, out confirm, out deny);
				Plugin.Spam("command type 2 detected, adding store logic");
				val.acceptAnything = false;
				yourModListing.shopNodes.Add(confirm.result);
				yourModListing.shopNodes.Add(val);
				yourModListing.shopNodes.Add(deny.result);
				if (managedBool.itemList.Length > 1)
				{
					confirm.result.buyUnlockable = false;
					yourModListing.storePacks.Add(val, managedBool.itemList);
					Plugin.Spam("storepack detected, adding itemlist");
				}
			}
			if (confirm != null && deny != null)
			{
				list2.Add(confirm.noun);
				Plugin.keywordsAdded.Add(confirm.noun);
				list2.Add(deny.noun);
				Plugin.keywordsAdded.Add(deny.noun);
				val.terminalOptions = (CompatibleNoun[])(object)new CompatibleNoun[2] { confirm, deny };
				val.overrideOptions = true;
			}
			else
			{
				Plugin.Spam("no confirmation logic added for " + keyWord);
			}
			yourModListing.Listing.Add(val, mainAction);
			list2.Add(keyword);
			if (!Plugin.nodesAdded.Contains(val))
			{
				Plugin.nodesAdded.Add(val);
			}
			if (!Plugin.keywordsAdded.Contains(keyword))
			{
				Plugin.keywordsAdded.Add(keyword);
			}
			Plugin.instance.Terminal.terminalNodes.allKeywords = list2.ToArray();
			return val;
		}

		public static void AddConfirm(string nodeName, ManagedConfig managedBool, out CompatibleNoun confirm, out CompatibleNoun deny)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected O, but got Unknown
			confirm = new CompatibleNoun
			{
				noun = ScriptableObject.CreateInstance<TerminalKeyword>()
			};
			confirm.noun.word = "confirm";
			confirm.noun.isVerb = true;
			confirm.result = ScriptableObject.CreateInstance<TerminalNode>();
			((Object)confirm.result).name = nodeName + "_confirm";
			confirm.result.displayText = managedBool.confirmText;
			confirm.result.clearPreviousText = true;
			confirm.result.itemCost = managedBool.price;
			confirm.noun.specialKeywordResult = confirm.result;
			deny = new CompatibleNoun
			{
				noun = ScriptableObject.CreateInstance<TerminalKeyword>()
			};
			deny.noun.word = "deny";
			deny.noun.isVerb = true;
			deny.result = ScriptableObject.CreateInstance<TerminalNode>();
			((Object)deny.result).name = nodeName + "_deny";
			deny.result.displayText = managedBool.denyText;
			deny.result.clearPreviousText = true;
			deny.noun.specialKeywordResult = deny.result;
		}

		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)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			confirm = new CompatibleNoun
			{
				noun = ScriptableObject.CreateInstance<TerminalKeyword>()
			};
			confirm.noun.word = "confirm";
			confirm.noun.isVerb = true;
			confirm.result = ScriptableObject.CreateInstance<TerminalNode>();
			((Object)confirm.result).name = nodeName + "_confirm";
			confirm.result.displayText = confirmText;
			confirm.result.clearPreviousText = true;
			confirm.result.itemCost = price;
			confirm.noun.specialKeywordResult = confirm.result;
			if (ConfirmAction != null)
			{
				nodeListing.Add(confirm.result, ConfirmAction);
			}
			deny = new CompatibleNoun
			{
				noun = ScriptableObject.CreateInstance<TerminalKeyword>()
			};
			deny.noun.word = "deny";
			deny.noun.isVerb = true;
			deny.result = ScriptableObject.CreateInstance<TerminalNode>();
			((Object)deny.result).name = nodeName + "_deny";
			deny.result.displayText = denyText;
			deny.result.clearPreviousText = true;
			deny.noun.specialKeywordResult = deny.result;
			if (DenyAction != null)
			{
				nodeListing.Add(deny.result, DenyAction);
			}
		}

		public static void AddStoreCommand(string nodeName, ref TerminalKeyword keyword, ManagedConfig managedBool, MainListing mainListing, out CompatibleNoun confirm, out CompatibleNoun deny)
		{
			TerminalNode terminalNode = managedBool.TerminalNode;
			if ((Object)(object)terminalNode == (Object)null)
			{
				Plugin.ERROR("Unable to retrieve managedBool TerminalNode");
				confirm = null;
				deny = null;
			}
			else if (managedBool.ConfirmAction != null)
			{
				AddConfirm(nodeName, managedBool, out confirm, out deny);
				confirm.result.buyUnlockable = true;
				if (managedBool.ConfirmAction != null)
				{
					mainListing.Listing.Add(confirm.result, managedBool.ConfirmAction);
					Plugin.Spam("confirmResult FUNC added");
				}
				if (managedBool.DenyAction != null)
				{
					mainListing.Listing.Add(deny.result, managedBool.DenyAction);
					Plugin.Spam("denyResult FUNC added");
				}
				terminalNode.terminalOptions = (CompatibleNoun[])(object)new CompatibleNoun[2] { confirm, deny };
				UnlockableItem item = AddUnlockable(managedBool);
				if (!StartOfRound.Instance.unlockablesList.unlockables.Contains(item))
				{
					StartOfRound.Instance.unlockablesList.unlockables.Add(item);
				}
				int num = StartOfRound.Instance.unlockablesList.unlockables.IndexOf(item);
				Plugin.Spam($"new unlockable found at {num} out of count: {StartOfRound.Instance.unlockablesList.unlockables.Count}");
				terminalNode.creatureName = managedBool.storeName;
				terminalNode.shipUnlockableID = num;
				terminalNode.itemCost = managedBool.price;
				terminalNode.overrideOptions = true;
				confirm.result.shipUnlockableID = num;
				confirm.result.buyUnlockable = true;
				confirm.result.itemCost = managedBool.price;
				if (DynamicBools.TryGetKeyword("buy", out var terminalKeyword))
				{
					AddToBuyWord(ref terminalKeyword, ref keyword, item);
				}
				Plugin.ShopNodes.Add(terminalNode);
				Plugin.Spam("Store nodes created for " + managedBool.storeName);
			}
			else
			{
				Plugin.ERROR("Shop nodes NEED confirmation, but confirmAction is null for " + managedBool.storeName + "!");
				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);
				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 var terminalKeyword))
				{
					AddToBuyWord(ref terminalKeyword, ref keyword, item);
				}
				Plugin.ShopNodes.Add(node);
				Plugin.Spam("Store nodes created for " + nodeName);
			}
			else
			{
				Plugin.ERROR("Shop nodes NEED confirmation, but confirmAction is null for " + nodeName + "!");
				confirm = null;
				deny = null;
			}
		}

		public static UnlockableItem AddUnlockable(ManagedConfig managedBool)
		{
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Expected O, but got Unknown
			if (managedBool.UnlockableItem != null)
			{
				Plugin.Spam(managedBool.ConfigItemName + " already contained item: " + managedBool.UnlockableItem.unlockableName);
				return managedBool.UnlockableItem;
			}
			UnlockableItem val;
			if (DynamicBools.TryGetAndReturnUnlockable(managedBool.storeName, out var itemOut))
			{
				Plugin.Spam("found matching item for " + managedBool.storeName);
				itemOut.unlockableType = 1;
				itemOut.shopSelectionNode = managedBool.TerminalNode;
				itemOut.alwaysInStock = managedBool.alwaysInStock;
				itemOut.IsPlaceable = false;
				itemOut.spawnPrefab = false;
				itemOut.maxNumber = managedBool.maxStock;
				val = itemOut;
			}
			else
			{
				Plugin.Spam("Creating unlockable item from managedBool: " + managedBool.ConfigItemName);
				val = new UnlockableItem
				{
					unlockableType = 1,
					alreadyUnlocked = false,
					hasBeenUnlockedByPlayer = false,
					unlockableName = managedBool.storeName,
					shopSelectionNode = managedBool.TerminalNode,
					alwaysInStock = managedBool.alwaysInStock,
					IsPlaceable = false,
					spawnPrefab = false,
					maxNumber = managedBool.maxStock
				};
			}
			managedBool.UnlockableItem = val;
			return val;
		}

		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 var 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
			};
			CompatibleNoun[] compatibleNouns = buyKeyword.compatibleNouns;
			List<CompatibleNoun> list = new List<CompatibleNoun>(compatibleNouns.Length);
			list.AddRange(compatibleNouns);
			List<CompatibleNoun> list2 = list;
			list2.Add(item2);
			buyKeyword.compatibleNouns = list2.ToArray();
		}

		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
			};
			CompatibleNoun[] compatibleNouns = originalKeyword.compatibleNouns;
			List<CompatibleNoun> list = new List<CompatibleNoun>(compatibleNouns.Length);
			list.AddRange(compatibleNouns);
			List<CompatibleNoun> list2 = list;
			list2.Add(item);
			originalKeyword.compatibleNouns = list2.ToArray();
		}

		[Obsolete("This doesn't work at the moment")]
		public static void AddNounWordSimple(string originalVerb, string nodeName, string keyWord, string displayText, bool clearText)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			if (originalVerb.Length < 1)
			{
				Plugin.WARNING("originalVerb text is invalid");
				return;
			}
			if (!DynamicBools.TryGetKeyword(originalVerb, out var terminalKeyword))
			{
				Plugin.WARNING("Unable to find word for " + originalVerb);
				return;
			}
			TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
			((Object)val).name = nodeName;
			val.displayText = displayText;
			val.clearPreviousText = clearText;
			CompatibleNoun val2 = new CompatibleNoun
			{
				noun = ScriptableObject.CreateInstance<TerminalKeyword>()
			};
			((Object)val2.noun).name = nodeName + "_Noun";
			val2.noun.word = keyWord.ToLower();
			val2.noun.isVerb = false;
			val2.result = val;
			val2.noun.specialKeywordResult = val;
			if (!Plugin.nodesAdded.Contains(val))
			{
				Plugin.nodesAdded.Add(val);
			}
			if (!Plugin.keywordsAdded.Contains(val2.noun))
			{
				Plugin.keywordsAdded.Add(val2.noun);
			}
			AddToKeyword(ref terminalKeyword, ref val2.noun);
		}
	}
	public class CommonThings
	{
		public static void CheckForAndDeleteKeyWord(string keyWord)
		{
			Plugin.Spam("Checking for " + keyWord);
			TerminalKeyword[] allKeywords = Plugin.instance.Terminal.terminalNodes.allKeywords;
			List<TerminalKeyword> list = new List<TerminalKeyword>(allKeywords.Length);
			list.AddRange(allKeywords);
			List<TerminalKeyword> list2 = list;
			for (int num = list2.Count - 1; num >= 0; num--)
			{
				if (list2[num].word.Equals(keyWord))
				{
					list2.RemoveAt(num);
					break;
				}
			}
			Plugin.instance.Terminal.terminalNodes.allKeywords = list2.ToArray();
			Plugin.Spam("keyword list adjusted, removed " + keyWord);
		}
	}
	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 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();
		}
	}
	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;
			}
			TerminalNode existingNode = LogicHandling.GetFromAllNodes("OtherCommands");
			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)
					{
						AddCommandKeyword(managedBool, listingName);
						if (managedBool.categoryText.ToLower() == "other")
						{
							AddingThings.AddToExistingNodeText("\n" + managedBool.configDescription, ref existingNode);
						}
					}
				}
				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);
				managedBool.TerminalNode = AddingThings.CreateNode(managedBool, keyword, 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 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)
		{
			TerminalKeyword[] allKeywords = Plugin.instance.Terminal.terminalNodes.allKeywords;
			List<TerminalKeyword> list = new List<TerminalKeyword>(allKeywords.Length);
			list.AddRange(allKeywords);
			List<TerminalKeyword> list2 = list;
			foreach (TerminalKeyword item in list2)
			{
				if (item.word.ToLower().Equals(keyWord.ToLower()))
				{
					return true;
				}
			}
			return false;
		}

		public static bool TryGetKeyword(string keyWord, out TerminalKeyword terminalKeyword)
		{
			TerminalKeyword[] allKeywords = Plugin.instance.Terminal.terminalNodes.allKeywords;
			List<TerminalKeyword> list = new List<TerminalKeyword>(allKeywords.Length);
			list.AddRange(allKeywords);
			List<TerminalKeyword> list2 = list;
			foreach (TerminalKeyword item in list2)
			{
				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> unlockables = StartOfRound.Instance.unlockablesList.unlockables;
			List<UnlockableItem> list = new List<UnlockableItem>(unlockables.Count);
			list.AddRange(unlockables);
			List<UnlockableItem> list2 = list;
			foreach (UnlockableItem item in list2)
			{
				if (item.unlockableName.Equals(unlockableName))
				{
					itemOut = item;
					return true;
				}
			}
			itemOut = null;
			return false;
		}

		public static bool TryGetAndReturnItem(string unlockableName, out Item itemOut)
		{
			Item[] buyableItemsList = Plugin.instance.Terminal.buyableItemsList;
			List<Item> list = new List<Item>(buyableItemsList.Length);
			list.AddRange(buyableItemsList);
			List<Item> list2 = list;
			foreach (Item item in list2)
			{
				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 (!(item.Value == 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 (!(item.Value == 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 || !(item.Value == commandAction))
				{
					continue;
				}
				node = item.Key;
				return true;
			}
			return false;
		}
	}
	public class RemoveThings
	{
		public static void OnTerminalDisable()
		{
			Plugin.Spam("OnTerminalDisable called");
			DeleteAllNodes(ref Plugin.nodesAdded);
			DeleteAllKeywords(ref Plugin.keywordsAdded);
			ConfigSetup.defaultListing.DeleteAll();
		}

		public static void DeleteNounWord(ref TerminalKeyword keyWord, string terminalKeyword)
		{
			CompatibleNoun[] compatibleNouns = keyWord.compatibleNouns;
			List<CompatibleNoun> list = new List<CompatibleNoun>(compatibleNouns.Length);
			list.AddRange(compatibleNouns);
			List<CompatibleNoun> list2 = list;
			List<CompatibleNoun> list3 = new List<CompatibleNoun>();
			foreach (CompatibleNoun item in list2)
			{
				if (item.noun.word.ToLower() == terminalKeyword.ToLower())
				{
					list3.Add(item);
				}
			}
			for (int num = list3.Count - 1; num >= 0; num--)
			{
				Plugin.Spam("Deleting noun: " + list3[num].noun.word + " from word: " + keyWord.word);
				Object.Destroy((Object)(object)list3[num].noun);
			}
			keyWord.compatibleNouns = list2.ToArray();
		}

		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}");
		}

		public static void DeleteAllKeywords(ref List<TerminalKeyword> keywordList)
		{
			if (keywordList.Count == 0)
			{
				return;
			}
			List<TerminalKeyword> list = keywordList;
			TerminalKeyword[] allKeywords = Plugin.instance.Terminal.terminalNodes.allKeywords;
			List<TerminalKeyword> list2 = new List<TerminalKeyword>(allKeywords.Length);
			list2.AddRange(allKeywords);
			List<TerminalKeyword> list3 = list2;
			foreach (TerminalKeyword keyword in keywordList)
			{
				if (DynamicBools.TryGetKeyword("buy", out var terminalKeyword))
				{
					DeleteNounWord(ref terminalKeyword, keyword.word);
				}
				for (int num = list3.Count - 1; num >= 0; num--)
				{
					if ((Object)(object)list3[num] == (Object)(object)keyword)
					{
						Plugin.Spam("Removing " + keyword.word + " from all keywords list");
						list3.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 = list3.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]);
					break;
				}
			}
		}

		public static bool TryGetAndDeleteUnlockableName(string unlockableName, out int indexPos)
		{
			List<UnlockableItem> unlockables = StartOfRound.Instance.unlockablesList.unlockables;
			List<UnlockableItem> list = new List<UnlockableItem>(unlockables.Count);
			list.AddRange(unlockables);
			List<UnlockableItem> list2 = list;
			for (int num = list2.Count - 1; num >= 0; num--)
			{
				if (list2[num].unlockableName.Equals(unlockableName))
				{
					Plugin.Spam("Unlockable: [" + unlockableName + "] found! Removing unlockable and noting index position");
					StartOfRound.Instance.unlockablesList.unlockables.Remove(list2[num]);
					indexPos = num;
					return true;
				}
			}
			indexPos = -1;
			return false;
		}
	}
	public class LogicHandling
	{
		public static bool GetNewDisplayText(MainListing providedListing, ref TerminalNode node)
		{
			if ((Object)(object)node == (Object)null || providedListing.Listing.Count == 0)
			{
				Plugin.Spam("node is null or listing is 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");
			EventManager.GetNewDisplayText.Invoke(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.MoreLogs("Not in special nodeListing dictionary");
			return false;
		}

		public static bool GetNewDisplayText(List<MainListing> providedListing, ref TerminalNode node)
		{
			if ((Object)(object)node == (Object)null || providedListing.Count == 0)
			{
				Plugin.Spam("node is null or listings do not exist");
				return false;
			}
			bool result = 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})");
					EventManager.GetNewDisplayText.Invoke(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 Func<string> GetFuncFromNode(List<MainListing> providedListing, ref TerminalNode node)
		{
			if ((Object)(object)node == (Object)null || providedListing.Count == 0)
			{
				Plugin.Spam("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;
		}

		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;
		}

		public static List<TerminalNode> GetAllNodes()
		{
			TerminalNode[] array = Resources.FindObjectsOfTypeAll<TerminalNode>();
			List<TerminalNode> list = new List<TerminalNode>(array.Length);
			list.AddRange(array);
			return list;
		}

		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;
		}
	}
}
namespace OpenLib.ConfigManager
{
	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 ManagedConfig
	{
		public string ConfigItemName;

		public bool RequiresNetworking;

		public int ConfigType = -1;

		public string StringValue;

		public int IntValue;

		public bool BoolValue = false;

		public List<string> KeywordList;

		public Func<string> MainAction;

		public int CommandType;

		public bool clearText;

		public bool alwaysInStock;

		public bool reuseFunc;

		public int maxStock;

		public int price;

		public int specialNum;

		public string nodeName;

		public string storeName;

		public string itemList;

		public string specialString;

		public string confirmText;

		public string denyText;

		public string categoryText;

		public string configDescription;

		public Func<string> ConfirmAction;

		public Func<string> DenyAction;

		public TerminalMenuItem menuItem;

		public TerminalNode TerminalNode;

		public UnlockableItem UnlockableItem;

		public ManagedConfig relatedConfigItem;

		public void ConfigChange(bool newValue)
		{
			if (newValue)
			{
				BoolValue = newValue;
			}
			else
			{
				BoolValue = newValue;
			}
		}

		public void ConfigChange(string newValue)
		{
			if (newValue != StringValue)
			{
				StringValue = newValue;
				Plugin.Spam("Updating string value for managed item " + ConfigItemName);
			}
		}

		public void SetManagedBoolValues(string configItemName, bool isEnabled, string descrip, bool isNetworked = false, string category = "", List<string> keywordList = null, Func<string> mainAction = null, int commandType = 0, bool clear = true, Func<string> confirmAction = null, Func<string> denyAction = null, string confirmTxt = "confirm", string denyTxt = "deny", string special = "", int specialInt = -1, string nodestring = "", string items = "", int value = 0, string storeString = "", bool inStock = true, int stockMax = 0, bool reuseFnc = false)
		{
			ConfigType = 0;
			BoolValue = isEnabled;
			MainAction = mainAction;
			KeywordList = keywordList;
			ConfigItemName = configItemName;
			RequiresNetworking = isNetworked;
			price = value;
			CommandType = commandType;
			clearText = clear;
			ConfirmAction = confirmAction;
			DenyAction = denyAction;
			confirmText = confirmTxt;
			denyText = denyTxt;
			specialNum = specialInt;
			specialString = special;
			itemList = items;
			storeName = storeString;
			alwaysInStock = inStock;
			maxStock = stockMax;
			nodeName = nodestring;
			categoryText = category;
			configDescription = descrip;
			reuseFunc = reuseFnc;
		}
	}
	public class ManagedBoolGet
	{
		public static bool TryGetItemByName(List<ManagedConfig> managedBools, string query, int configType, out ManagedConfig result)
		{
			if (managedBools.Count == 0)
			{
				Plugin.Spam("managedBools count = 0");
				result = null;
				return false;
			}
			Plugin.Spam("TryGetItemByName: " + query);
			foreach (ManagedConfig managedBool in managedBools)
			{
				if (managedBool.ConfigItemName == query && managedBool.ConfigType == configType)
				{
					result = managedBool;
					Plugin.Spam($"{query} found with matching config type: {configType}, returning true");
					return true;
				}
			}
			Plugin.Spam(query + " not found");
			result = null;
			return false;
		}

		public static bool CanAddToManagedBoolList(List<ManagedConfig> managedBools, string nodeName)
		{
			foreach (ManagedConfig managedBool in managedBools)
			{
				if (managedBool.ConfigItemName == nodeName)
				{
					Plugin.Log.LogWarning((object)("Tried to add " + nodeName + " to managedBools list when it's already in it!"));
					return false;
				}
			}
			Plugin.Spam("node is not in managedbool list and can be added!");
			return true;
		}

		public static bool TryGetItemByName(List<ManagedConfig> managedBools, string query)
		{
			foreach (ManagedConfig managedBool in managedBools)
			{
				if (managedBool.ConfigItemName == query)
				{
					return true;
				}
			}
			return false;
		}
	}
	public static class ConfigSetup
	{
		public static List<ManagedConfig> defaultManaged = new List<ManagedConfig>();

		public static MainListing defaultListing;

		public static ConfigEntry<bool> ExtensiveLogging { get; internal set; }

		public static ConfigEntry<bool> DeveloperLogging { get; internal set; }

		public static void BindConfigSettings()
		{
			Plugin.Log.LogInfo((object)"Binding configuration settings");
			ExtensiveLogging = MakeBool(((BaseUnityPlugin)Plugin.instance).Config, "Debug", "ExtensiveLogging", defaultValue: false, "Enable or Disable extensive logging for this mod.");
			DeveloperLogging = MakeBool(((BaseUnityPlugin)Plugin.instance).Config, "Debug", "DeveloperLogging", defaultValue: false, "Enable or Disable developer logging for this mod. (this will fill your log file FAST)");
		}

		public static ManagedConfig AddManagedBool(ConfigEntry<bool> boolEntry, List<ManagedConfig> managedItems, bool isNetworked = false, string category = "", string configString = "", Func<string> mainAction = null, int commandType = 0, bool clearText = true, Func<string> confirmAction = null, Func<string> denyAction = null, string confirmText = "confirm", string denyText = "deny", string special = "", int specialNum = -1, string nodeName = "", string itemList = "", int price = 0, string storeName = "", bool alwaysInStock = true, int maxStock = 0, bool reuseFunc = false)
		{
			List<string> keywordsPerConfigItem = CommonStringStuff.GetKeywordsPerConfigItem(configString);
			if (ManagedBoolGet.TryGetItemByName(managedItems, ((ConfigEntryBase)boolEntry).Definition.Key, 0, out var result))
			{
				result.SetManagedBoolValues(((ConfigEntryBase)boolEntry).Definition.Key, boolEntry.Value, ((ConfigEntryBase)boolEntry).Description.Description, isNetworked, category, keywordsPerConfigItem, mainAction, commandType, clearText, confirmAction, denyAction, confirmText, denyText, special, specialNum, nodeName, itemList, price, storeName, alwaysInStock, maxStock, reuseFunc);
				return result;
			}
			ManagedConfig managedConfig = new ManagedConfig();
			managedConfig.SetManagedBoolValues(((ConfigEntryBase)boolEntry).Definition.Key, boolEntry.Value, ((ConfigEntryBase)boolEntry).Description.Description, isNetworked, category, keywordsPerConfigItem, mainAction, commandType, clearText, confirmAction, denyAction, confirmText, denyText, special, specialNum, nodeName, itemList, price, storeName, alwaysInStock, maxStock, reuseFunc);
			managedItems.Add(managedConfig);
			return managedConfig;
		}

		public static ManagedConfig AddManagedBool(ConfigEntry<bool> boolEntry, List<ManagedConfig> managedItems, bool isNetworked = false, string category = "", ConfigEntry<string> configString = null, Func<string> mainAction = null, int commandType = 0, bool clearText = true, Func<string> confirmAction = null, Func<string> denyAction = null, string confirmText = "confirm", string denyText = "deny", string special = "", int specialNum = -1, string nodeName = "", string itemList = "", int price = 0, string storeName = "", bool alwaysInStock = true, int maxStock = 0, bool reuseFunc = false)
		{
			List<string> keywordList = new List<string>();
			bool flag = true;
			if (configString != null)
			{
				flag = false;
				keywordList = CommonStringStuff.GetKeywordsPerConfigItem(configString.Value);
			}
			if (ManagedBoolGet.TryGetItemByName(managedItems, ((ConfigEntryBase)boolEntry).Definition.Key, 0, out var result))
			{
				result