using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using InteractiveTerminalAPI.UI; using InteractiveTerminalAPI.UI.Application; using InteractiveTerminalAPI.UI.Cursor; using InteractiveTerminalAPI.UI.Page; using InteractiveTerminalAPI.UI.Screen; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LGUShop")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+8c5521e37f37e3d76518a16d04e5d1051842f105")] [assembly: AssemblyProduct("LGUShop")] [assembly: AssemblyTitle("LGUShop")] [assembly: AssemblyVersion("1.0.0.0")] [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; } } } namespace LGUShop { public class ShopItem { public string Name; public int Price; public TerminalKeyword BuyKeyword; public TerminalKeyword NounKeyword; public TerminalNode TriggerNode; public Item ItemAsset; public override string ToString() { return $"{Name} (${Price})"; } } public static class ItemDiscovery { public static List DiscoverItems(Terminal terminal) { List list = new List(); if ((Object)(object)terminal == (Object)null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"ItemDiscovery: terminal is null."); } return list; } TerminalKeyword val = ((IEnumerable)terminal.terminalNodes.allKeywords).FirstOrDefault((Func)((TerminalKeyword k) => (Object)(object)k != (Object)null && k.isVerb && k.word == "buy")); if ((Object)(object)val == (Object)null) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)"ItemDiscovery: 'buy' verb keyword not found."); } return list; } if (val.compatibleNouns == null) { return list; } CompatibleNoun[] compatibleNouns = val.compatibleNouns; foreach (CompatibleNoun val2 in compatibleNouns) { if ((Object)(object)val2?.noun == (Object)null || (Object)(object)val2.result == (Object)null) { continue; } TerminalKeyword noun = val2.noun; TerminalNode result = val2.result; if (result.itemCost <= 0 && result.buyItemIndex < 0) { continue; } Item val3 = null; if (result.buyItemIndex >= 0 && terminal.buyableItemsList != null && result.buyItemIndex < terminal.buyableItemsList.Length) { val3 = terminal.buyableItemsList[result.buyItemIndex]; } string name = val3?.itemName ?? noun.word ?? "(unnamed)"; int num = result.itemCost; if (num <= 0 && (Object)(object)val3 != (Object)null) { FieldInfo field = typeof(Item).GetField("creditsWorth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.GetValue(val3) is int num2) { num = num2; } } list.Add(new ShopItem { Name = name, Price = num, BuyKeyword = val, NounKeyword = noun, TriggerNode = result, ItemAsset = val3 }); } List list2 = (from s in list group s by s.Name.ToLowerInvariant() into g select g.First() into s orderby s.Name select s).ToList(); ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogInfo((object)$"ItemDiscovery: discovered {list2.Count} buyable items."); } return list2; } } internal class LGUShopApplication : PageApplication { private List _allItems; private Terminal _terminal; private bool _onMainMenu; public override void Initialization() { _terminal = Object.FindObjectOfType(); _allItems = ItemDiscovery.DiscoverItems(_terminal); BuildMainCategoryScreen(); } protected override void ScreenExit() { if (!_onMainMenu) { BuildMainCategoryScreen(); } else { ((TerminalApplication)this).ScreenExit(); } } private void BuildMainCategoryScreen() { //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Expected O, but got Unknown //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Expected O, but got Unknown //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0371: Expected O, but got Unknown //IL_03ba: Unknown result type (might be due to invalid IL or missing references) //IL_03bf: Unknown result type (might be due to invalid IL or missing references) //IL_03d4: Unknown result type (might be due to invalid IL or missing references) //IL_03e3: Expected O, but got Unknown //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_038b: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Expected O, but got Unknown //IL_039d: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Unknown result type (might be due to invalid IL or missing references) //IL_03b2: Expected O, but got Unknown _onMainMenu = true; List activeCategories = Plugin.ShopCfg.GetActiveCategories(); List list = new List(); HashSet assigned = new HashSet(); Dictionary> dictionary = new Dictionary>(); foreach (ShopCategory cat in activeCategories) { List list2 = (from it in _allItems where cat.Matches(it.Name) where !assigned.Contains(it.Name.ToLowerInvariant()) select it).ToList(); foreach (ShopItem item in list2) { assigned.Add(item.Name.ToLowerInvariant()); } if (list2.Count != 0) { PageCursorElement page = BuildCategoryPage(cat.DisplayName.Value, cat.Subtitle.Value, cat.Description.Value, list2); dictionary[cat.Name] = page; int count = list2.Count; list.Add(CursorElement.Create($"{cat.DisplayName.Value} ({count})", cat.Description.Value + "\n ", (Action)delegate { OpenCategoryPage(page); }, (Func)null, true)); } } if (Plugin.ShopCfg.ShowOtherCategory.Value) { List list3 = _allItems.Where((ShopItem it) => !assigned.Contains(it.Name.ToLowerInvariant())).ToList(); if (list3.Count > 0) { PageCursorElement otherPage = BuildCategoryPage("OTHER", "UNCATEGORIZED", "Items not assigned to a defined category.", list3); list.Add(CursorElement.Create($"OTHER ({list3.Count})", "Uncategorized items.\n ", (Action)delegate { OpenCategoryPage(otherPage); }, (Func)null, true)); } } list.Add(CursorElement.Create("EXIT", "Close the shop.", (Action)delegate { Object.Destroy((Object)(object)InteractiveTerminalManager.Instance); }, (Func)null, true)); CursorMenu val = CursorMenu.Create(0, '>', list.ToArray(), (Func[])null); List list4 = new List { (ITextElement)new TextElement { Text = " " }, (ITextElement)new TextElement { Text = $" Credits: ${_terminal?.groupCredits ?? 0}" }, (ITextElement)new TextElement { Text = " " } }; if (Plugin.ShopCfg.ShowYangzFlavorText.Value) { list4.Add((ITextElement)new TextElement { Text = " The Company appreciates your continued patronage." }); list4.Add((ITextElement)new TextElement { Text = " " }); } list4.Add((ITextElement)(object)val); BoxedScreen val2 = new BoxedScreen { Title = Plugin.ShopCfg.MainTitle.Value, elements = list4.ToArray() }; base.currentPage = PageCursorElement.Create(0, (IScreen[])(object)new IScreen[1] { (IScreen)val2 }, new BaseCursorMenu[1] { (BaseCursorMenu)(object)val }); ((BaseInteractiveApplication)(object)this).currentCursorMenu = (BaseCursorMenu)(object)val; ((TerminalApplication)this).currentScreen = (IScreen)(object)val2; } protected override int GetEntriesPerPage(K[] entries) { return Mathf.Max(1, Plugin.ShopCfg.ItemsPerPage.Value); } private void OpenCategoryPage(PageCursorElement page) { _onMainMenu = false; base.currentPage = page; IScreen currentScreen = ((PageElement)page).GetCurrentScreen(); BaseCursorMenu currentCursorMenu = page.GetCurrentCursorMenu(); ((BaseInteractiveApplication)(object)this).SwitchScreen(currentScreen, currentCursorMenu, false); } private PageCursorElement BuildCategoryPage(string title, string subtitle, string description, List items) { //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Expected O, but got Unknown //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Expected O, but got Unknown //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Expected O, but got Unknown //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Expected O, but got Unknown //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Expected O, but got Unknown //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Expected O, but got Unknown items = (from i in items orderby i.Price, i.Name select i).ToList(); int num = Mathf.Max(1, Plugin.ShopCfg.ItemsPerPage.Value); int num2 = Mathf.Max(1, Mathf.CeilToInt((float)items.Count / (float)num)); IScreen[] array = (IScreen[])(object)new IScreen[num2]; BaseCursorMenu[] array2 = new BaseCursorMenu[num2]; for (int j = 0; j < num2; j++) { int num3 = j * num; int count = Mathf.Min(num, items.Count - num3); List list = items.Skip(num3).Take(count).ToList(); CursorElement[] array3 = (CursorElement[])(object)new CursorElement[list.Count]; for (int k = 0; k < list.Count; k++) { ShopItem captured = list[k]; array3[k] = CursorElement.Create(FormatItemRow(captured), "", (Action)delegate { OpenItemConfirmation(captured); }, (Func)null, true); } CursorMenu val = (CursorMenu)(object)(array2[j] = (BaseCursorMenu)(object)CursorMenu.Create(0, '>', array3, (Func[])null)); int num4 = j; BoxedScreen val2 = new BoxedScreen(); val2.Title = title + " :: " + subtitle; val2.elements = (ITextElement[])(object)new ITextElement[6] { (ITextElement)new TextElement { Text = " " }, (ITextElement)new TextElement { Text = " " + description }, (ITextElement)new TextElement { Text = " " }, (ITextElement)new TextElement { Text = $" Credits: ${_terminal?.groupCredits ?? 0} Page {j + 1}/{num2}" }, (ITextElement)new TextElement { Text = " " }, (ITextElement)val }; array[num4] = (IScreen)(object)val2; } return PageCursorElement.Create(0, array, array2); } private static string FormatItemRow(ShopItem item) { string arg = ((item.Name.Length > 28) ? item.Name.Substring(0, 28) : item.Name.PadRight(28)); return $" {arg} ${item.Price}"; } private void OpenItemConfirmation(ShopItem item) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //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) //IL_00b4: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown CursorElement[] array = (CursorElement[])(object)new CursorElement[2] { CursorElement.Create($" Purchase - ${item.Price}", "", (Action)delegate { DoPurchase(item, 1); }, (Func)null, true), CursorElement.Create(" Cancel", "", (Action)delegate { BuildMainCategoryScreen(); }, (Func)null, true) }; CursorMenu val = CursorMenu.Create(0, '>', array, (Func[])null); BoxedScreen val2 = new BoxedScreen(); val2.Title = item.Name.ToUpperInvariant(); val2.elements = (ITextElement[])(object)new ITextElement[6] { (ITextElement)new TextElement { Text = " " }, (ITextElement)new TextElement { Text = " Item: " + item.Name }, (ITextElement)new TextElement { Text = $" Price: ${item.Price}" }, (ITextElement)new TextElement { Text = $" Available credits: ${_terminal?.groupCredits ?? 0}" }, (ITextElement)new TextElement { Text = " " }, (ITextElement)val }; BoxedScreen val3 = val2; ((BaseInteractiveApplication)(object)this).SwitchScreen((IScreen)(object)val3, (BaseCursorMenu)(object)val, false); } private void DoPurchase(ShopItem item, int quantity) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Expected O, but got Unknown PurchaseFlow.PurchaseResult purchaseResult = PurchaseFlow.AttemptBuy(_terminal, item, quantity); string text = PurchaseFlow.ResultToText(purchaseResult, item, quantity); CursorMenu val = CursorMenu.Create(0, '>', (CursorElement[])(object)new CursorElement[2] { CursorElement.Create(" Continue Shopping", "", (Action)delegate { BuildMainCategoryScreen(); }, (Func)null, true), CursorElement.Create(" Exit", "", (Action)delegate { Object.Destroy((Object)(object)InteractiveTerminalManager.Instance); }, (Func)null, true) }, (Func[])null); BoxedScreen val2 = new BoxedScreen(); val2.Title = ((purchaseResult == PurchaseFlow.PurchaseResult.Success) ? "TRANSACTION COMPLETE" : "TRANSACTION FAILED"); val2.elements = (ITextElement[])(object)new ITextElement[6] { (ITextElement)new TextElement { Text = " " }, (ITextElement)new TextElement { Text = " " + text }, (ITextElement)new TextElement { Text = " " }, (ITextElement)new TextElement { Text = $" Remaining credits: ${_terminal?.groupCredits ?? 0}" }, (ITextElement)new TextElement { Text = " " }, (ITextElement)val }; BoxedScreen val3 = val2; ((BaseInteractiveApplication)(object)this).SwitchScreen((IScreen)(object)val3, (BaseCursorMenu)(object)val, false); } } [BepInPlugin("com.y4ngz.lgushop", "LGUShop", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PLUGIN_GUID = "com.y4ngz.lgushop"; public const string PLUGIN_NAME = "LGUShop"; public const string PLUGIN_VERSION = "1.0.0"; internal static ManualLogSource Log; internal static Plugin Instance; internal static ShopConfig ShopCfg; internal static ConfigEntry ShopKeywords; internal static ConfigEntry InterceptVanillaStore; private void Awake() { //IL_006a: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; ShopKeywords = ((BaseUnityPlugin)this).Config.Bind("Main", "ShopKeywords", "shop", "Comma-separated keywords that open the shop. Type any of these in the terminal to launch the interactive shop UI. Default: 'shop'. Note: do NOT add 'store' here unless you have disabled TerminalStuff's StorePlus, or both will conflict."); InterceptVanillaStore = ((BaseUnityPlugin)this).Config.Bind("Main", "InterceptVanillaStore", false, "If true, ALSO intercept the vanilla 'store' keyword. Recommended only when TerminalStuff's StorePlus (TerminalStorePlus = false) is disabled."); ShopCfg = new ShopConfig(((BaseUnityPlugin)this).Config); try { new Harmony("com.y4ngz.lgushop").PatchAll(typeof(Plugin).Assembly); } catch (Exception arg) { Log.LogError((object)$"Harmony patch failed: {arg}"); } try { List list = (from s in ShopKeywords.Value.Split(',') select s.Trim() into s where !string.IsNullOrEmpty(s) select s).ToList(); if (InterceptVanillaStore.Value && !list.Contains("store")) { list.Add("store"); } if (list.Count == 0) { Log.LogWarning((object)"No shop keywords configured; shop will not be reachable."); } else if (list.Count == 1) { InteractiveTerminalManager.RegisterApplication(list[0]); Log.LogInfo((object)("Registered shop on keyword '" + list[0] + "'.")); } else { InteractiveTerminalManager.RegisterApplication(list.ToArray()); Log.LogInfo((object)("Registered shop on keywords: " + string.Join(", ", list))); } } catch (Exception arg2) { Log.LogError((object)$"Failed to register shop application: {arg2}"); } Log.LogInfo((object)"LGUShop v1.0.0 loaded."); } } public static class PurchaseFlow { public enum PurchaseResult { Success, NotEnoughCredits, DropshipFull, NoTerminal, UnknownError } public static PurchaseResult AttemptBuy(Terminal terminal, ShopItem item, int quantity = 1) { if ((Object)(object)terminal == (Object)null) { return PurchaseResult.NoTerminal; } if ((Object)(object)item?.TriggerNode == (Object)null) { return PurchaseResult.UnknownError; } int num = item.Price * quantity; if (terminal.groupCredits < num) { return PurchaseResult.NotEnoughCredits; } int num2 = terminal.orderedItemsFromTerminal?.Count ?? 0; try { _ = terminal.numberOfItemsInDropship; } catch { } if (num2 + quantity > 12 && num2 >= 12) { return PurchaseResult.DropshipFull; } try { for (int i = 0; i < quantity; i++) { terminal.orderedItemsFromTerminal.Add(item.TriggerNode.buyItemIndex); } terminal.groupCredits = Mathf.Max(0, terminal.groupCredits - num); terminal.SyncGroupCreditsServerRpc(terminal.groupCredits, terminal.numberOfItemsInDropship); return PurchaseResult.Success; } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"PurchaseFlow.AttemptBuy failed: {arg}"); } return PurchaseResult.UnknownError; } } public static string ResultToText(PurchaseResult result, ShopItem item, int quantity) { switch (result) { case PurchaseResult.Success: if (quantity != 1) { return $"Purchased: {quantity}x {item.Name} for ${item.Price * quantity}."; } return $"Purchased: {item.Name} for ${item.Price}."; case PurchaseResult.NotEnoughCredits: return "Insufficient credits to purchase " + item.Name + "."; case PurchaseResult.DropshipFull: return "Dropship is at maximum capacity."; case PurchaseResult.NoTerminal: return "Terminal not available."; default: return "Purchase failed."; } } } public class ShopConfig { public List Categories { get; } public ConfigEntry CategoryOrder { get; } public ConfigEntry ShowOtherCategory { get; } public ConfigEntry ItemsPerPage { get; } public ConfigEntry MainTitle { get; } public ConfigEntry ShowYangzFlavorText { get; } public ShopConfig(ConfigFile config) { ItemsPerPage = config.Bind("Display", "ItemsPerPage", 10, "How many items to show per scroll page within a category. Default: 10."); MainTitle = config.Bind("Display", "MainTitle", "FORTUNE-93 // EMPLOYEE PROVISIONS", "Title shown at the top of the main category-picker screen."); ShowYangzFlavorText = config.Bind("Display", "ShowYangzFlavorText", true, "Show Y4NGZ flavor lines on the main screen and category descriptions."); ShowOtherCategory = config.Bind("Categories", "ShowOtherCategory", true, "Show an 'Other' category for items not matched by any defined category. If false, unmatched items are silently hidden — only useful if you've defined categories that cover everything."); CategoryOrder = config.Bind("Categories", "CategoryOrder", "Tools,Combat,Utility,Cosmetic", "Comma-separated list of category names in display order. Each name listed here must have a matching `[Category.]` section below. Names not listed here won't appear in the shop."); Categories = new List(); DefineCategory(config, "Tools", "STANDARD ISSUE", "Standard-issue gear. The Company expects these to be returned in working order.", "flashlight,pro-flashlight,walkie,walkie-talkie,shovel,extension ladder,boombox,radar-booster,radar booster"); DefineCategory(config, "Combat", "OFFENSIVE LOADOUT", "Offensive equipment. Use of lethal force on hostile fauna is encouraged.", "stun grenade,zap gun,shotgun,kitchen knife,knife,yield sign,stop sign,gun"); DefineCategory(config, "Utility", "AUXILIARY EQUIPMENT", "Mission-critical support gear. Item availability subject to clearance.", "jetpack,tzp-inhalant,tzp,inhalant,key,lockpicker,lockpick,spray paint,spraypaint,mapper"); DefineCategory(config, "Cosmetic", "EMPLOYEE EXPRESSION", "Approved morale items. Limited stock. No refunds.", "suit,hat,cosmetic,clothing"); } private void DefineCategory(ConfigFile config, string name, string subtitle, string description, string items) { string text = "Category." + name; ConfigEntry enabled = config.Bind(text, "Enabled", true, "Whether the " + name + " category should appear in the shop."); ConfigEntry displayName = config.Bind(text, "DisplayName", name.ToUpperInvariant(), "Text shown on the main category-picker screen."); ConfigEntry subtitle2 = config.Bind(text, "Subtitle", subtitle, "Header text shown when this category is open."); ConfigEntry description2 = config.Bind(text, "Description", description, "Flavor text shown on the category page."); ConfigEntry itemNameMatches = config.Bind(text, "ItemNameMatches", items, "Comma-separated list of substrings to match against item names. Case-insensitive. An item belongs to this category if its name contains any substring here. First-match-wins across categories — list more-specific items first within a single category, and order categories by specificity in CategoryOrder."); Categories.Add(new ShopCategory { Name = name, Enabled = enabled, DisplayName = displayName, Subtitle = subtitle2, Description = description2, ItemNameMatches = itemNameMatches }); } public List GetActiveCategories() { List list = (from s in CategoryOrder.Value.Split(',') select s.Trim() into s where !string.IsNullOrEmpty(s) select s).ToList(); Dictionary dictionary = Categories.Where((ShopCategory c) => c.Enabled.Value).ToDictionary((ShopCategory c) => c.Name, (ShopCategory c) => c); List list2 = new List(); foreach (string item in list) { if (dictionary.TryGetValue(item, out var value)) { list2.Add(value); } } return list2; } } public class ShopCategory { public string Name; public ConfigEntry Enabled; public ConfigEntry DisplayName; public ConfigEntry Subtitle; public ConfigEntry Description; public ConfigEntry ItemNameMatches; public IEnumerable GetMatchSubstrings() { return from s in ItemNameMatches.Value.Split(',') select s.Trim().ToLowerInvariant() into s where !string.IsNullOrEmpty(s) select s; } public bool Matches(string itemName) { if (string.IsNullOrEmpty(itemName)) { return false; } string text = itemName.ToLowerInvariant(); foreach (string matchSubstring in GetMatchSubstrings()) { if (text.Contains(matchSubstring)) { return true; } } return false; } } public static class PluginInfo { public const string PLUGIN_GUID = "LGUShop"; public const string PLUGIN_NAME = "LGUShop"; public const string PLUGIN_VERSION = "1.0.0"; } }