Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of GrabMaterials v2.3.1
BepInEx/plugins/GrabMaterials.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GrabMaterials; using GrabMaterialsMod; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Extensions; using Jotunn.Managers; using Jotunn.Utils; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("GrabMaterials")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("GrabMaterials")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("f3f4f7f9-7343-4b53-9531-aa1e3d80ea19")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace GrabMaterialsMod { [BepInPlugin("DeathMonger.GrabMaterialsMod", "Grab Materials", "2.3.1")] [BepInProcess("valheim.exe")] public class GrabMaterialsMod : BaseUnityPlugin { public enum DeltaSetting { UseGlobal, On, Off } public class GrabPackConfig { public ConfigEntry<string> Name; public ConfigEntry<KeyboardShortcut> Key; public ConfigEntry<string> Items; public ConfigEntry<DeltaSetting> GrabDelta; public ButtonConfig Button; public GrabPackConfig(ConfigFile config, string section, string name, KeyboardShortcut keyboardShortcut, string items) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown Name = config.Bind<string>(section, section + " Name", name, new ConfigDescription("Name of the grab pack", (AcceptableValueBase)null, Array.Empty<object>())); Key = config.Bind<KeyboardShortcut>(section, section + " Key", keyboardShortcut, new ConfigDescription("Key to grab materials for the grab pack", (AcceptableValueBase)null, Array.Empty<object>())); Items = config.Bind<string>(section, section + " Items", items, new ConfigDescription("Items to grab for the grab pack", (AcceptableValueBase)null, Array.Empty<object>())); GrabDelta = config.Bind<DeltaSetting>(section, section + " Grab Delta", DeltaSetting.UseGlobal, new ConfigDescription("UseGlobal = follow the 'Grab Delta (default)' setting; On = only grab the shortfall (e.g. if the pack needs 10 wood and you have 7, only 3 will be grabbed); Off = always grab the full amount.", (AcceptableValueBase)null, Array.Empty<object>())); Button = new ButtonConfig { Name = Name.Value, ShortcutConfig = Key }; } } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static EventHandler <>9__39_0; public static EventHandler <>9__39_1; public static ConsoleEvent <>9__40_0; public static ConsoleEvent <>9__40_1; public static ConsoleEvent <>9__40_2; public static ConsoleEvent <>9__40_3; public static ConsoleEvent <>9__40_4; public static ConsoleEvent <>9__40_5; public static ConsoleEvent <>9__40_6; public static ConsoleEvent <>9__40_7; public static ConsoleEvent <>9__40_8; public static ConsoleEvent <>9__40_9; public static ConsoleEvent <>9__40_10; public static ConsoleEvent <>9__40_11; public static ConsoleEvent <>9__40_12; public static ConsoleEvent <>9__40_13; public static ConsoleEvent <>9__40_14; public static ConsoleEvent <>9__40_15; public static ConsoleEvent <>9__40_16; public static Action <>9__58_1; internal void <InitConfig>b__39_0(object s, EventArgs e) { PanelPause.Refresh(); } internal void <InitConfig>b__39_1(object sender, EventArgs e) { Log.LogInfo((object)("Grabpack renamed " + sender.ToString() + " " + e.ToString())); } internal void <InitCommands>b__40_0(ConsoleEventArgs args) { args.GrabItemsFromNearbyContainers(); } internal void <InitCommands>b__40_1(ConsoleEventArgs args) { args.GrabItemsFromNearbyContainers(); } internal void <InitCommands>b__40_2(ConsoleEventArgs args) { ConsoleCommands.GrabMaterialsForSelectedPiece(); } internal void <InitCommands>b__40_3(ConsoleEventArgs args) { args.GrabMaterialsForPiece(); } internal void <InitCommands>b__40_4(ConsoleEventArgs args) { ListKnownContainers(); } internal void <InitCommands>b__40_5(ConsoleEventArgs args) { ListLocalContainers(args); } internal void <InitCommands>b__40_6(ConsoleEventArgs args) { ListLocalContainerContents(args); } internal void <InitCommands>b__40_7(ConsoleEventArgs args) { ListGrabPacks(); } internal void <InitCommands>b__40_8(ConsoleEventArgs args) { ConsoleCommands.ResetPendingLedger(); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Grab delta ledger cleared.", 0, (Sprite)null, false); } } internal void <InitCommands>b__40_9(ConsoleEventArgs args) { ListLocalInventory(args); } internal void <InitCommands>b__40_10(ConsoleEventArgs args) { ListLocalInventory(args); } internal void <InitCommands>b__40_11(ConsoleEventArgs args) { SetInventoryStyle(args); } internal void <InitCommands>b__40_12(ConsoleEventArgs args) { FindContainersWithMatchingItems(args); } internal void <InitCommands>b__40_13(ConsoleEventArgs args) { FindContainersWithMatchingItems(args); } internal void <InitCommands>b__40_14(ConsoleEventArgs args) { StoreItemsInNearbyContainers(); } internal void <InitCommands>b__40_15(ConsoleEventArgs args) { CountInventory(args); } internal void <InitCommands>b__40_16(ConsoleEventArgs args) { ListAllPieces(); } internal void <OpenPackEditor>b__58_1() { ListGrabPacks(); } } private const string ModGuid = "DeathMonger.GrabMaterialsMod"; private readonly Harmony harmony = new Harmony("DeathMonger.GrabMaterialsMod"); public static GrabMaterialsMod Instance; internal static ManualLogSource Log; public ConfigEntry<bool> GrabDeltaGlobal; public ConfigEntry<float> GrabDeltaLedgerTimeout; public ConfigEntry<float> HighlightDuration; public ConfigEntry<float> PanelIdleTimeout; public ConfigEntry<float> PanelFadeDuration; public ConfigEntry<bool> PanelDismissOnMovement; public ConfigEntry<bool> PanelCategoryUnderlines; public ConfigEntry<bool> PanelShowItemIcons; public ConfigEntry<bool> PanelMarkUndiscovered; public ConfigEntry<bool> PanelPauseWhileOpen; public ConfigEntry<float> PanelIconSize; public ConfigEntry<MaterialsPanel.InventoryShape> InventoryShape; public ConfigEntry<MaterialsPanel.InventoryStyle> InventoryStyle; public ConfigEntry<bool> ShowDistanceHud; public ConfigEntry<bool> ShowDistanceCoords; public ConfigEntry<float> DistanceHudOffsetX; public ConfigEntry<float> DistanceHudOffsetY; public ConfigEntry<bool> ShowPackHud; public ConfigEntry<KeyboardShortcut> PackHudToggleKey; public ConfigEntry<PackHud.Anchor> PackHudAnchor; public ConfigEntry<float> PackHudOffsetX; public ConfigEntry<float> PackHudOffsetY; public ConfigEntry<bool> PackHudShowBuildPieceKey; public ConfigEntry<bool> PackHudHideUndiscovered; private ButtonConfig GrabSelectedPieceMatsButton; private ConfigEntry<KeyCode> GrabSelectedPieceMatsKeyboardConfig; public GrabPackConfig[] GrabPacks; private FileSystemWatcher _configWatcher; private static readonly MethodInfo KeyCodeToPathMethod = AccessTools.Method(typeof(ZInput), "KeyCodeToPath", new Type[2] { typeof(KeyCode), typeof(bool) }, (Type[])null); internal KeyCode GrabSelectedPieceKey => GrabSelectedPieceMatsKeyboardConfig.Value; private void Awake() { Log = ((BaseUnityPlugin)this).Logger; if ((Object)(object)Instance == (Object)null) { Log.LogInfo((object)"GrabMaterialsMod instance created and Awake called for the first time"); Instance = this; } else if ((Object)(object)Instance == (Object)(object)this) { Log.LogWarning((object)"GrabMaterialsMod Awake called an additional time"); } else { Log.LogError((object)"GrabMaterialsMod instance already exists, additional one created, should it be destroyed?"); Instance = this; } harmony.PatchAll(); InitConfig(); SetupConfigWatcher(); InitCommands(); InitButtons(); } private void SetupConfigWatcher() { try { _configWatcher = new FileSystemWatcher(Paths.ConfigPath, Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath)); _configWatcher.Changed += OnConfigFileChanged; _configWatcher.Created += OnConfigFileChanged; _configWatcher.Renamed += OnConfigFileChanged; _configWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; _configWatcher.EnableRaisingEvents = true; } catch (Exception ex) { Log.LogWarning((object)("Could not watch config file for changes: " + ex.Message)); } } private void OnConfigFileChanged(object sender, FileSystemEventArgs e) { if (!File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath)) { return; } try { ((BaseUnityPlugin)this).Config.Reload(); Log.LogInfo((object)"Config file changed on disk; settings reloaded"); } catch (Exception ex) { Log.LogError((object)("Config file changed but could not be reloaded: " + ex.Message)); } } private void InitConfig() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Expected O, but got Unknown //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Expected O, but got Unknown //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Expected O, but got Unknown //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Expected O, but got Unknown //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Expected O, but got Unknown //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Expected O, but got Unknown //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Expected O, but got Unknown //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Expected O, but got Unknown //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Expected O, but got Unknown //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Expected O, but got Unknown //IL_036f: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Expected O, but got Unknown //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03a5: Expected O, but got Unknown //IL_03c2: Unknown result type (might be due to invalid IL or missing references) //IL_03d2: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: Expected O, but got Unknown //IL_03fe: Unknown result type (might be due to invalid IL or missing references) //IL_0408: Expected O, but got Unknown //IL_042e: Unknown result type (might be due to invalid IL or missing references) //IL_0438: Expected O, but got Unknown //IL_045e: Unknown result type (might be due to invalid IL or missing references) //IL_0468: Expected O, but got Unknown //IL_048a: Unknown result type (might be due to invalid IL or missing references) //IL_0494: Expected O, but got Unknown //IL_04b6: Unknown result type (might be due to invalid IL or missing references) //IL_04c0: Expected O, but got Unknown //IL_04e6: Unknown result type (might be due to invalid IL or missing references) //IL_0518: Unknown result type (might be due to invalid IL or missing references) //IL_054a: Unknown result type (might be due to invalid IL or missing references) //IL_057c: Unknown result type (might be due to invalid IL or missing references) //IL_05a5: Unknown result type (might be due to invalid IL or missing references) //IL_05d7: Unknown result type (might be due to invalid IL or missing references) //IL_0609: Unknown result type (might be due to invalid IL or missing references) //IL_063b: Unknown result type (might be due to invalid IL or missing references) //IL_0664: Unknown result type (might be due to invalid IL or missing references) //IL_0697: Unknown result type (might be due to invalid IL or missing references) //IL_06e9: Unknown result type (might be due to invalid IL or missing references) new ConfigDescription("Key to grab portal materials", (AcceptableValueBase)null, Array.Empty<object>()); GrabSelectedPieceMatsKeyboardConfig = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Grab Selected Piece", "GrabSelectedPieceMatsKey", (KeyCode)106, new ConfigDescription("Key to grab materials for the currently selectede build piece", (AcceptableValueBase)null, Array.Empty<object>())); HighlightDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Client config", "Highlight Duration", 2f, new ConfigDescription("Duration in seconds to highlight containers when grabbing materials", (AcceptableValueBase)null, Array.Empty<object>())); GrabDeltaGlobal = ((BaseUnityPlugin)this).Config.Bind<bool>("Client config", "Grab Delta (default)", true, new ConfigDescription("If true, all grabs (packs, individual build pieces, /grab <piece>) only grab the shortfall between what you already have and what's needed. Per-pack settings can override this.", (AcceptableValueBase)null, Array.Empty<object>())); GrabDeltaLedgerTimeout = ((BaseUnityPlugin)this).Config.Bind<float>("Client config", "Grab Delta Ledger Timeout (seconds)", 30f, new ConfigDescription("Back-to-back delta grabs share a ledger so the same inventory isn't credited toward two different builds (e.g. /g cart then /g explore won't both 'see' the same 10 wood). After this many seconds without a delta grab, the ledger clears so the next grab considers only what's currently in your inventory. Set to 0 to effectively disable cross-grab tracking.", (AcceptableValueBase)null, Array.Empty<object>())); PanelIdleTimeout = ((BaseUnityPlugin)this).Config.Bind<float>("Panel UI", "Idle Timeout (seconds)", 15f, new ConfigDescription("Seconds the grab-results panel stays fully visible before fading out automatically.", (AcceptableValueBase)null, Array.Empty<object>())); PanelFadeDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Panel UI", "Fade Duration (seconds)", 3f, new ConfigDescription("Seconds the grab-results panel takes to fade out.", (AcceptableValueBase)null, Array.Empty<object>())); PanelDismissOnMovement = ((BaseUnityPlugin)this).Config.Bind<bool>("Panel UI", "Dismiss On Movement", true, new ConfigDescription("Start fading the panel when the player begins moving, attacking, blocking, or jumping. If false, only the idle timeout dismisses the panel.", (AcceptableValueBase)null, Array.Empty<object>())); InventoryStyle = ((BaseUnityPlugin)this).Config.Bind<MaterialsPanel.InventoryStyle>("Panel UI", "Inventory Style", MaterialsPanel.InventoryStyle.List, new ConfigDescription("Display style for the /inventory panel. List = grouped by category, count + name per row (counts right-aligned). Table = flat 3-column table with Category / Item / Count headers.", (AcceptableValueBase)null, Array.Empty<object>())); PanelCategoryUnderlines = ((BaseUnityPlugin)this).Config.Bind<bool>("Panel UI", "Category Underlines", true, new ConfigDescription("In List mode, draw a thin orange line under each category name. Has no effect in Table mode.", (AcceptableValueBase)null, Array.Empty<object>())); InventoryShape = ((BaseUnityPlugin)this).Config.Bind<MaterialsPanel.InventoryShape>("Panel UI", "Inventory Shape", MaterialsPanel.InventoryShape.SlightlyWide, new ConfigDescription("Target shape for the inventory panel in List mode. The panel auto-picks the column count that produces the closest match. MaxHeight = always 1 column. MaxWidth = fan out as many columns as fit on the screen.", (AcceptableValueBase)null, Array.Empty<object>())); PanelShowItemIcons = ((BaseUnityPlugin)this).Config.Bind<bool>("Panel UI", "Show Item Icons", true, new ConfigDescription("Show each item's icon next to its name in the inventory panel.", (AcceptableValueBase)null, Array.Empty<object>())); PanelMarkUndiscovered = ((BaseUnityPlugin)this).Config.Bind<bool>("Panel UI", "Mark Undiscovered Items", true, new ConfigDescription("Mark items in the /inventory panel that this character has never held with a '(new)' tag. Handy in multiplayer, where a shared chest is often full of a friend's crafting you have never handled yourself.", (AcceptableValueBase)null, Array.Empty<object>())); PanelPauseWhileOpen = ((BaseUnityPlugin)this).Config.Bind<bool>("Panel UI", "Pause While Inventory Panel Open", false, new ConfigDescription("Pause the game while the /inventory panel is up, the way the ESC menu does. Toggle it from the button in the panel's top-right corner. This works by itself when playing solo or hosting alone; on a dedicated server it takes the Pause My Server mod. The button shows whether the pause actually took effect.", (AcceptableValueBase)null, Array.Empty<object>())); PanelPauseWhileOpen.SettingChanged += delegate { PanelPause.Refresh(); }; PanelIconSize = ((BaseUnityPlugin)this).Config.Bind<float>("Panel UI", "Icon Size", 24f, new ConfigDescription("Width of the item-icon column in pixels. Icons are square and sized to fit. Beyond ~26 the row stays the same height so icons get visually capped by the row.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(12f, 40f), Array.Empty<object>())); ShowDistanceHud = ((BaseUnityPlugin)this).Config.Bind<bool>("Distance HUD", "Enabled", false, new ConfigDescription("Show a small always-on widget displaying the player's horizontal distance from the world center.", (AcceptableValueBase)null, Array.Empty<object>())); ShowDistanceCoords = ((BaseUnityPlugin)this).Config.Bind<bool>("Distance HUD", "Show Coordinates", false, new ConfigDescription("Also include the player's (X, Z) coordinates in the distance widget.", (AcceptableValueBase)null, Array.Empty<object>())); DistanceHudOffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("Distance HUD", "Offset X (px)", 10f, new ConfigDescription("Horizontal offset from the upper-left corner of the screen.", (AcceptableValueBase)null, Array.Empty<object>())); DistanceHudOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Distance HUD", "Offset Y (px)", 10f, new ConfigDescription("Vertical offset from the top of the screen.", (AcceptableValueBase)null, Array.Empty<object>())); ShowPackHud = ((BaseUnityPlugin)this).Config.Bind<bool>("Pack HUD", "Show Pack HUD", true, new ConfigDescription("Show a small on-screen list of your grab packs and their hotkeys, like the quick-slot labels in AzuExtendedPlayerInventory. Packs with no items are left out. The toggle key below flips this setting, so the state persists.", (AcceptableValueBase)null, Array.Empty<object>())); PackHudToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Pack HUD", "Toggle Key", new KeyboardShortcut((KeyCode)111, Array.Empty<KeyCode>()), new ConfigDescription("Key to show or hide the pack HUD.", (AcceptableValueBase)null, Array.Empty<object>())); PackHudAnchor = ((BaseUnityPlugin)this).Config.Bind<PackHud.Anchor>("Pack HUD", "Anchor", PackHud.Anchor.BottomLeft, new ConfigDescription("Which corner of the screen the pack HUD sits in. Offsets below are measured from that corner.", (AcceptableValueBase)null, Array.Empty<object>())); PackHudOffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("Pack HUD", "Offset X (px)", 10f, new ConfigDescription("Horizontal distance from the anchored corner.", (AcceptableValueBase)null, Array.Empty<object>())); PackHudOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Pack HUD", "Offset Y (px)", 300f, new ConfigDescription("Vertical distance from the anchored corner. The default clears the health and stamina bars in the bottom-left.", (AcceptableValueBase)null, Array.Empty<object>())); PackHudShowBuildPieceKey = ((BaseUnityPlugin)this).Config.Bind<bool>("Pack HUD", "Show Build Piece Key", true, new ConfigDescription("Also list the key that grabs materials for the build piece under the cursor.", (AcceptableValueBase)null, Array.Empty<object>())); PackHudHideUndiscovered = ((BaseUnityPlugin)this).Config.Bind<bool>("Pack HUD", "Hide Undiscovered Packs", true, new ConfigDescription("Hide packs that need a material you have never held. A pack reappears once you have picked up every material it needs, so early-game clutter like Karve or Longship packs stays out of the way until nails and the like are in hand.", (AcceptableValueBase)null, Array.Empty<object>())); GrabPacks = new GrabPackConfig[10] { new GrabPackConfig(((BaseUnityPlugin)this).Config, "Grab Pack 1", "Explore", new KeyboardShortcut((KeyCode)107, Array.Empty<KeyCode>()), "Workbench,Chest,Portal"), new GrabPackConfig(((BaseUnityPlugin)this).Config, "Grab Pack 2", "Karve Explore", new KeyboardShortcut((KeyCode)107, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Workbench,Chest,Portal,Karve"), new GrabPackConfig(((BaseUnityPlugin)this).Config, "Grab Pack 3", "Longship Explore", new KeyboardShortcut((KeyCode)107, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Workbench,Chest,Portal,Longship"), new GrabPackConfig(((BaseUnityPlugin)this).Config, "Grab Pack 4", "Swamp Explore", new KeyboardShortcut((KeyCode)107, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Workbench,Chest,Portal,Campfire"), new GrabPackConfig(((BaseUnityPlugin)this).Config, "Grab Pack 5", "Ashlands Explore", new KeyboardShortcut((KeyCode)108, Array.Empty<KeyCode>()), "Workbench,Portal,Campfire:10"), new GrabPackConfig(((BaseUnityPlugin)this).Config, "Grab Pack 6", "Ashlands Flametal", new KeyboardShortcut((KeyCode)108, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Workbench,Stone Cutter,Stone Portal,Shield Generator,Bones:10"), new GrabPackConfig(((BaseUnityPlugin)this).Config, "Grab Pack 7", "Grab Pack 7", new KeyboardShortcut((KeyCode)108, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), ""), new GrabPackConfig(((BaseUnityPlugin)this).Config, "Grab Pack 8", "Grab Pack 8", new KeyboardShortcut((KeyCode)108, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), ""), new GrabPackConfig(((BaseUnityPlugin)this).Config, "Grab Pack 9", "Grab Pack 9", new KeyboardShortcut((KeyCode)59, Array.Empty<KeyCode>()), ""), new GrabPackConfig(((BaseUnityPlugin)this).Config, "Grab Pack 10", "Grab Pack 10", new KeyboardShortcut((KeyCode)59, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "") }; GrabPacks[8].Name.SettingChanged += delegate(object sender, EventArgs e) { Log.LogInfo((object)("Grabpack renamed " + sender.ToString() + " " + e.ToString())); }; new ConfigFileWatcher(((BaseUnityPlugin)this).Config, 1000L); } private static void InitCommands() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_00d4: Expected O, but got Unknown //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0102: 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_010d: Expected O, but got Unknown //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Expected O, but got Unknown //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Expected O, but got Unknown //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Expected O, but got Unknown //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Expected O, but got Unknown //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Expected O, but got Unknown //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Expected O, but got Unknown //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Expected O, but got Unknown //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Expected O, but got Unknown //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Expected O, but got Unknown //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Expected O, but got Unknown //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_0380: Expected O, but got Unknown //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Unknown result type (might be due to invalid IL or missing references) //IL_03b3: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Expected O, but got Unknown object obj = <>c.<>9__40_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { args.GrabItemsFromNearbyContainers(); }; <>c.<>9__40_0 = val; obj = (object)val; } new ConsoleCommand("grab", "[items] - grab items from nearby containers. Use a piece name, a pack name, or 'new' for one of every item you have never held.", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj2 = <>c.<>9__40_1; if (obj2 == null) { ConsoleEvent val2 = delegate(ConsoleEventArgs args) { args.GrabItemsFromNearbyContainers(); }; <>c.<>9__40_1 = val2; obj2 = (object)val2; } new ConsoleCommand("g", "[items] - grab items from nearby containers. Use a piece name, a pack name, or 'new' for one of every item you have never held.", (ConsoleEvent)obj2, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj3 = <>c.<>9__40_2; if (obj3 == null) { ConsoleEvent val3 = delegate { ConsoleCommands.GrabMaterialsForSelectedPiece(); }; <>c.<>9__40_2 = val3; obj3 = (object)val3; } new ConsoleCommand("grabselected", "", (ConsoleEvent)obj3, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj4 = <>c.<>9__40_3; if (obj4 == null) { ConsoleEvent val4 = delegate(ConsoleEventArgs args) { args.GrabMaterialsForPiece(); }; <>c.<>9__40_3 = val4; obj4 = (object)val4; } new ConsoleCommand("grabpiece", "grab materials for named build piece, e.g. workbench or portal", (ConsoleEvent)obj4, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj5 = <>c.<>9__40_4; if (obj5 == null) { ConsoleEvent val5 = delegate { ListKnownContainers(); }; <>c.<>9__40_4 = val5; obj5 = (object)val5; } new ConsoleCommand("listcontainers", "list all known containers", (ConsoleEvent)obj5, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj6 = <>c.<>9__40_5; if (obj6 == null) { ConsoleEvent val6 = delegate(ConsoleEventArgs args) { ListLocalContainers(args); }; <>c.<>9__40_5 = val6; obj6 = (object)val6; } new ConsoleCommand("listlocalcontainers", "[radius] - Finds containers within the radius.", (ConsoleEvent)obj6, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj7 = <>c.<>9__40_6; if (obj7 == null) { ConsoleEvent val7 = delegate(ConsoleEventArgs args) { ListLocalContainerContents(args); }; <>c.<>9__40_6 = val7; obj7 = (object)val7; } new ConsoleCommand("listcontents", "[radius] - Finds containers within the radius and lists their contents.", (ConsoleEvent)obj7, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj8 = <>c.<>9__40_7; if (obj8 == null) { ConsoleEvent val8 = delegate { ListGrabPacks(); }; <>c.<>9__40_7 = val8; obj8 = (object)val8; } new ConsoleCommand("listpacks", "Lists your configured grab packs.", (ConsoleEvent)obj8, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj9 = <>c.<>9__40_8; if (obj9 == null) { ConsoleEvent val9 = delegate { ConsoleCommands.ResetPendingLedger(); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Grab delta ledger cleared.", 0, (Sprite)null, false); } }; <>c.<>9__40_8 = val9; obj9 = (object)val9; } new ConsoleCommand("grabreset", "Clear the grab-delta ledger so the next delta grab considers only what's currently in your inventory.", (ConsoleEvent)obj9, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj10 = <>c.<>9__40_9; if (obj10 == null) { ConsoleEvent val10 = delegate(ConsoleEventArgs args) { ListLocalInventory(args); }; <>c.<>9__40_9 = val10; obj10 = (object)val10; } new ConsoleCommand("inventory", "[filter] - counts of items in nearby containers. Filter by item name, by category, or with 'new' for items you have never held.", (ConsoleEvent)obj10, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj11 = <>c.<>9__40_10; if (obj11 == null) { ConsoleEvent val11 = delegate(ConsoleEventArgs args) { ListLocalInventory(args); }; <>c.<>9__40_10 = val11; obj11 = (object)val11; } new ConsoleCommand("i", "[filter] - counts of items in nearby containers. Filter by item name, by category, or with 'new' for items you have never held.", (ConsoleEvent)obj11, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj12 = <>c.<>9__40_11; if (obj12 == null) { ConsoleEvent val12 = delegate(ConsoleEventArgs args) { SetInventoryStyle(args); }; <>c.<>9__40_11 = val12; obj12 = (object)val12; } new ConsoleCommand("istyle", "[1-2] - cycle inventory display style (1=List, 2=Table)", (ConsoleEvent)obj12, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj13 = <>c.<>9__40_12; if (obj13 == null) { ConsoleEvent val13 = delegate(ConsoleEventArgs args) { FindContainersWithMatchingItems(args); }; <>c.<>9__40_12 = val13; obj13 = (object)val13; } new ConsoleCommand("search", "[search-text] - search for items matching this string in nearby containers", (ConsoleEvent)obj13, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj14 = <>c.<>9__40_13; if (obj14 == null) { ConsoleEvent val14 = delegate(ConsoleEventArgs args) { FindContainersWithMatchingItems(args); }; <>c.<>9__40_13 = val14; obj14 = (object)val14; } new ConsoleCommand("s", "[search-text] - search for items matching this string in nearby containers", (ConsoleEvent)obj14, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj15 = <>c.<>9__40_14; if (obj15 == null) { ConsoleEvent val15 = delegate { StoreItemsInNearbyContainers(); }; <>c.<>9__40_14 = val15; obj15 = (object)val15; } new ConsoleCommand("store", "[items] - stores items randomly nearby containers", (ConsoleEvent)obj15, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj16 = <>c.<>9__40_15; if (obj16 == null) { ConsoleEvent val16 = delegate(ConsoleEventArgs args) { CountInventory(args); }; <>c.<>9__40_15 = val16; obj16 = (object)val16; } new ConsoleCommand("count", "[name of item to count] - omit to count everything", (ConsoleEvent)obj16, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj17 = <>c.<>9__40_16; if (obj17 == null) { ConsoleEvent val17 = delegate { ListAllPieces(); }; <>c.<>9__40_16 = val17; obj17 = (object)val17; } new ConsoleCommand("listpieces", "", (ConsoleEvent)obj17, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private void InitButtons() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown GrabSelectedPieceMatsButton = new ButtonConfig { Name = "GrabSelectedPieceMaterials", Config = GrabSelectedPieceMatsKeyboardConfig }; InputManager.Instance.AddButton("DeathMonger.GrabMaterialsMod", GrabSelectedPieceMatsButton); GrabPackConfig[] grabPacks = GrabPacks; foreach (GrabPackConfig grabPackConfig in grabPacks) { InputManager.Instance.AddButton("DeathMonger.GrabMaterialsMod", grabPackConfig.Button); GrabPackConfig packRef = grabPackConfig; grabPackConfig.Key.SettingChanged += delegate { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) ButtonConfig button = packRef.Button; KeyboardShortcut value = packRef.Key.Value; RebindButton(button, ((KeyboardShortcut)(ref value)).MainKey); }; } } private static void RebindButton(ButtonConfig button, KeyCode key) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) try { if (button == null || ZInput.instance == null || KeyCodeToPathMethod == null) { return; } ButtonDef buttonDef = ZInput.instance.GetButtonDef(button.Name); if (buttonDef != null) { string text = KeyCodeToPathMethod.Invoke(null, new object[2] { key, false }) as string; if (!string.IsNullOrEmpty(text)) { buttonDef.Rebind(text); Log.LogInfo((object)$"Rebound {button.Name} to {key}"); } } } catch (Exception ex) { Log.LogWarning((object)("Could not rebind " + ((button != null) ? button.Name : null) + ": " + ex.Message)); } } private void InitButton(string name, KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown ButtonConfig val = new ButtonConfig { Name = name, Config = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("", name, key, (ConfigDescription)null) }; InputManager.Instance.AddButton("DeathMonger.GrabMaterialsMod", val); } private static bool GuiHasFocus() { if (!Console.IsVisible() && !Menu.IsVisible() && !InventoryGui.IsVisible() && !TextInput.IsVisible() && !StoreGui.IsVisible() && !Minimap.IsOpen() && !PlayerCustomizaton.IsBarberGuiVisible()) { if ((Object)(object)Chat.instance != (Object)null) { return Chat.instance.IsChatDialogWindowVisible(); } return false; } return true; } private void Update() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) MaterialsPanel.RefreshInputBlock(); MaterialsPanel.Tick(); DistanceHud.Tick(); PackHud.Tick(); PanelPause.Refresh(); if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || !Object.op_Implicit((Object)(object)Chat.instance) || Chat.instance.IsChatDialogWindowVisible()) { return; } if (ZInput.GetButtonDown(GrabSelectedPieceMatsButton.Name)) { ConsoleCommands.GrabMaterialsForSelectedPiece(); } KeyboardShortcut value = PackHudToggleKey.Value; if (((KeyboardShortcut)(ref value)).IsDown() && !GuiHasFocus()) { ShowPackHud.Value = !ShowPackHud.Value; PackHud.Refresh(); } GrabPackConfig[] grabPacks = GrabPacks; foreach (GrabPackConfig grabPackConfig in grabPacks) { if (ZInput.GetButtonDown(grabPackConfig.Button.Name)) { ConsoleCommands.GrabMaterialsForPack(grabPackConfig); } } } private void OnDestroy() { harmony.UnpatchSelf(); } private static void ListAllPieces() { //IL_01a3: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ZNetScene.instance)) { Log.LogWarning((object)"Cannot index: ZNetScene.instance is null"); return; } Log.LogWarning((object)"listing build pieces (prefabs with an associated component)"); Piece val = default(Piece); foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { if (!prefab.TryGetComponent<Piece>(ref val)) { continue; } string text = ""; try { text = ((!val.m_name.StartsWith("$")) ? (val.m_name ?? "") : Extensions.Localize(val.m_name)); } catch (Exception ex) { Log.LogError((object)("Error translating piece name " + val.m_name + ": " + ex.Message)); text = "translation failed"; } if (((Object)prefab).name == ((Object)val).name) { bool flag = false; foreach (Recipe recipe in ObjectDB.instance.m_recipes) { if ((Object)(object)recipe.m_item == (Object)(object)val && recipe.m_enabled) { flag = true; break; } } Log.LogInfo((object)$"{((Object)prefab).name} \"{text}\" {val.GetResourceList()} {flag} {prefab.activeInHierarchy} {((Behaviour)val).enabled} {val.m_enabled} {((Behaviour)val).isActiveAndEnabled} {val.IsPlacedByPlayer()} {val.m_category} {val.m_craftingStation}"); } else { Log.LogError((object)("DIFFERENT NAMES Piece: " + ((Object)prefab).name + " " + ((Object)val).name + " " + text)); } } } private static void ListKnownContainers() { int num = 0; Log.LogInfo((object)$"listing {Boxes.Containers.Count} known containers"); foreach (Container container in Boxes.Containers) { Log.LogInfo((object)$"{++num}. {((Object)container).name} {container.m_name} ({((object)container).GetType()} {((Object)container).GetInstanceID()})"); } } private static void ListLocalContainers(ConsoleEventArgs args) { int num = 0; float result = 10f; if (args.Length > 1) { float.TryParse(args[1], NumberStyles.Float, CultureInfo.InvariantCulture, out result); } List<Container> nearbyContainers = Boxes.GetNearbyContainers(result); Log.LogInfo((object)$"listing {nearbyContainers.Count} containers within {result} meters out of {Boxes.Containers.Count} known containers"); foreach (Container item in nearbyContainers) { Log.LogInfo((object)$"{++num}. {((Object)item).name} {item.m_name} ({((object)item).GetType()} {((Object)item).GetInstanceID()})"); } } private static void ListLocalContainerContents(ConsoleEventArgs args) { //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) float result = 50f; if (args.Length > 1) { float.TryParse(args[1], NumberStyles.Float, CultureInfo.InvariantCulture, out result); } List<Container> nearbyContainers = Boxes.GetNearbyContainers(result); Log.LogInfo((object)$"listing {nearbyContainers.Count} containers within {result} meters out of {Boxes.Containers.Count} known containers"); Log.LogInfo((object)$"showing the contents of {nearbyContainers.Count} nearby containers"); foreach (Container item in nearbyContainers) { Log.LogInfo((object)$"contents of {((Object)item).name} {((Object)item).GetInstanceID()}:"); foreach (ItemData allItem in item.GetInventory().GetAllItems()) { string text = ""; text = Extensions.Localize(allItem.m_shared.m_name); Log.LogInfo((object)$"{allItem.Count()},{text},{allItem.Name()},{allItem.GetCategory()},{allItem.m_shared.m_itemType},{allItem.IsWeapon()},{allItem.IsEquipable()},{allItem.m_shared.m_isDrink},{allItem.GetArmor()},{allItem.m_shared.m_armorMaterial},{allItem.m_shared.m_food},{allItem.m_shared.m_foodStamina},{allItem.m_shared.m_foodEitr},{allItem.m_shared.m_ammoType},{allItem.m_shared.m_questItem},{allItem.m_shared.m_skillType}"); } } } private static void SetInventoryStyle(ConsoleEventArgs args) { MaterialsPanel.InventoryStyle[] array = (MaterialsPanel.InventoryStyle[])Enum.GetValues(typeof(MaterialsPanel.InventoryStyle)); MaterialsPanel.InventoryStyle inventoryStyle; if (args.Length > 1 && int.TryParse(args[1], out var result) && result >= 1 && result <= array.Length) { inventoryStyle = array[result - 1]; } else { MaterialsPanel.InventoryStyle value = Instance.InventoryStyle.Value; int num = Array.IndexOf(array, value); inventoryStyle = array[(num + 1) % array.Length]; } Instance.InventoryStyle.Value = inventoryStyle; Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, $"Inventory style: {inventoryStyle}", 0, (Sprite)null, false); } } private static string FormatCategoryName(Extensions.ItemCategory cat) { string text = cat.ToString(); StringBuilder stringBuilder = new StringBuilder(text.Length + 4); for (int i = 0; i < text.Length; i++) { if (i > 0 && char.IsUpper(text[i])) { stringBuilder.Append(' '); } stringBuilder.Append(text[i]); } return stringBuilder.ToString(); } private static void ListLocalInventory(ConsoleEventArgs args) { float num = 50f; string text = ((args.Length > 1) ? args.ArgsAll.ToLower() : null); Player localPlayer = Player.m_localPlayer; bool flag = text == "new"; List<Container> nearbyContainers = Boxes.GetNearbyContainers(num); List<Smelter> nearbySmelters = Boxes.GetNearbySmelters(num); Log.LogInfo((object)$"searching {nearbyContainers.Count} containers and {nearbySmelters.Count} processors within {num} meters"); Dictionary<Extensions.ItemCategory, SortedDictionary<string, int>> dictionary = new Dictionary<Extensions.ItemCategory, SortedDictionary<string, int>>(); Dictionary<string, Sprite> dictionary2 = new Dictionary<string, Sprite>(); Dictionary<string, Dictionary<string, int>> dictionary3 = new Dictionary<string, Dictionary<string, int>>(); foreach (Container item in nearbyContainers) { Inventory inventory = item.GetInventory(); if (inventory == null) { continue; } bool flag2 = false; foreach (ItemData allItem in inventory.GetAllItems()) { string name = allItem.m_shared.m_name; string text2 = Extensions.Localize(name).ToLower(); Extensions.ItemCategory category = allItem.GetCategory(); string text3 = category.ToString().ToLower(); Extensions.ItemCategory result = Extensions.ItemCategory.None; bool flag3 = text != null && Enum.TryParse<Extensions.ItemCategory>(text, ignoreCase: true, out result); bool num2; if (!flag) { if (!flag3) { if (text == null || allItem.Name().Contains(text) || name.Contains(text) || text2.Contains(text)) { goto IL_0178; } num2 = text3.Contains(text); } else { num2 = category == result; } } else { if (!((Object)(object)localPlayer != (Object)null)) { continue; } num2 = !localPlayer.IsMaterialKnown(name); } if (!num2) { continue; } goto IL_0178; IL_0178: if (!dictionary.TryGetValue(category, out var value)) { value = (dictionary[category] = new SortedDictionary<string, int>()); } if (value.ContainsKey(name)) { value[name] += allItem.Count(); } else { value[name] = allItem.Count(); } if (!dictionary2.ContainsKey(name) && allItem.m_shared.m_icons != null && allItem.m_shared.m_icons.Length != 0) { dictionary2[name] = allItem.m_shared.m_icons[0]; } if (!flag2) { item.Highlight(); flag2 = true; } } } foreach (Smelter item2 in nearbySmelters) { Dictionary<string, int> queuedItems = Processors.GetQueuedItems(item2); if (queuedItems.Count == 0) { continue; } string label = Processors.GetLabel(item2); bool flag4 = false; foreach (KeyValuePair<string, int> item3 in queuedItems) { ObjectDB instance = ObjectDB.instance; GameObject val = ((instance != null) ? instance.GetItemPrefab(item3.Key) : null); if ((Object)(object)val == (Object)null) { continue; } ItemDrop component = val.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null) { continue; } ItemData itemData = component.m_itemData; string name2 = itemData.m_shared.m_name; string text4 = Extensions.Localize(name2).ToLower(); Extensions.ItemCategory category2 = itemData.GetCategory(); string text5 = category2.ToString().ToLower(); Extensions.ItemCategory result2 = Extensions.ItemCategory.None; bool flag5 = text != null && Enum.TryParse<Extensions.ItemCategory>(text, ignoreCase: true, out result2); bool num3; if (!flag) { if (!flag5) { if (text == null || itemData.Name().Contains(text) || name2.Contains(text) || text4.Contains(text)) { goto IL_039b; } num3 = text5.Contains(text); } else { num3 = category2 == result2; } } else { if (!((Object)(object)localPlayer != (Object)null)) { continue; } num3 = !localPlayer.IsMaterialKnown(name2); } if (!num3) { continue; } goto IL_039b; IL_039b: if (!dictionary.TryGetValue(category2, out var value2)) { value2 = (dictionary[category2] = new SortedDictionary<string, int>()); } if (value2.ContainsKey(name2)) { value2[name2] += item3.Value; } else { value2[name2] = item3.Value; } if (!dictionary3.TryGetValue(name2, out var value3)) { value3 = (dictionary3[name2] = new Dictionary<string, int>()); } value3.TryGetValue(label, out var value4); value3[label] = value4 + item3.Value; if (!dictionary2.ContainsKey(name2) && itemData.m_shared.m_icons != null && itemData.m_shared.m_icons.Length != 0) { dictionary2[name2] = itemData.m_shared.m_icons[0]; } if (!flag4) { Processors.Highlight(item2); flag4 = true; } } } if (dictionary.Count == 0) { string text6 = (string.IsNullOrEmpty(text) ? "No items in nearby containers" : (flag ? "Nothing here you have not held before" : ("No items match '" + text + "'"))); ((Character)Player.m_localPlayer).Message((MessageType)2, text6, 0, (Sprite)null, false); return; } bool flag6 = (Instance?.PanelMarkUndiscovered?.Value ?? true) && (Object)(object)localPlayer != (Object)null && !flag; List<MaterialsPanel.InventoryGroup> list = new List<MaterialsPanel.InventoryGroup>(); foreach (Extensions.ItemCategory value8 in Enum.GetValues(typeof(Extensions.ItemCategory))) { if (value8 == Extensions.ItemCategory.None || !dictionary.TryGetValue(value8, out var value5)) { continue; } List<MaterialsPanel.InventoryItem> list2 = new List<MaterialsPanel.InventoryItem>(value5.Count); foreach (KeyValuePair<string, int> item4 in value5) { string text7 = Extensions.Localize(item4.Key); bool flag7 = flag6 && !localPlayer.IsMaterialKnown(item4.Key); Log.LogInfo((object)string.Format("{0} {1} [{2}]{3}", item4.Value, text7, value8, flag7 ? " (new, never held)" : "")); dictionary2.TryGetValue(item4.Key, out var value6); int num4 = 0; string inProcessLocation = null; if (dictionary3.TryGetValue(item4.Key, out var value7)) { foreach (KeyValuePair<string, int> item5 in value7) { num4 += item5.Value; } if (value7.Count == 1) { using Dictionary<string, int>.Enumerator enumerator4 = value7.GetEnumerator(); if (enumerator4.MoveNext()) { inProcessLocation = enumerator4.Current.Key; } } else { inProcessLocation = "processing"; } } list2.Add(new MaterialsPanel.InventoryItem { Name = text7, Count = item4.Value, InProcess = num4, InProcessLocation = inProcessLocation, Icon = value6, SharedName = item4.Key, Undiscovered = flag7 }); } list.Add(new MaterialsPanel.InventoryGroup { CategoryName = FormatCategoryName(value8), Items = list2 }); } MaterialsPanel.ShowCategorizedInventory(string.IsNullOrEmpty(text) ? "Inventory" : (flag ? "New Items" : ("Inventory: " + text)), list, Instance.InventoryStyle.Value); } internal static string FormatShortcut(KeyboardShortcut shortcut) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) StringBuilder stringBuilder = new StringBuilder(); foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers) { string text = ((object)modifier/*cast due to .constrained prefix*/).ToString(); if (text.StartsWith("Left")) { text = text.Substring(4); } else if (text.StartsWith("Right")) { text = text.Substring(5); } if (text == "Control") { text = "Ctrl"; } stringBuilder.Append(text).Append(" + "); } stringBuilder.Append(((object)((KeyboardShortcut)(ref shortcut)).MainKey/*cast due to .constrained prefix*/).ToString()); return stringBuilder.ToString(); } private static string FormatDelta(GrabPackConfig pack) { bool flag = ConsoleCommands.ResolveDelta(pack.GrabDelta.Value); switch (pack.GrabDelta.Value) { case DeltaSetting.On: return "On"; case DeltaSetting.Off: return "Off"; default: if (!flag) { return "Off (default)"; } return "On (default)"; } } private static void ListGrabPacks() { //IL_006f: 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) Log.LogInfo((object)$"listing {Instance.GrabPacks.Length} configured grab packs"); List<MaterialsPanel.PackRow> list = new List<MaterialsPanel.PackRow>(Instance.GrabPacks.Length); GrabPackConfig[] grabPacks = Instance.GrabPacks; foreach (GrabPackConfig grabPackConfig in grabPacks) { Log.LogInfo((object)$"{grabPackConfig.Name.Value} ({grabPackConfig.Key.Value}): {grabPackConfig.Items.Value}"); GrabPackConfig packRef = grabPackConfig; bool flag = !string.IsNullOrEmpty(grabPackConfig.Items.Value); list.Add(new MaterialsPanel.PackRow { Name = grabPackConfig.Name.Value, Hotkey = FormatShortcut(grabPackConfig.Key.Value), Items = grabPackConfig.Items.Value, Delta = FormatDelta(grabPackConfig), OnClick = (flag ? ((Action)delegate { ConsoleCommands.GrabMaterialsForPack(packRef); }) : null), OnEdit = delegate { OpenPackEditor(packRef); } }); } MaterialsPanel.ShowPacks("Grab Packs", list); } private static void OpenPackEditor(GrabPackConfig pack) { MaterialsPanel.ShowPackEditor("Edit: " + pack.Name.Value, pack.Name.Value, pack.Items.Value, pack.GrabDelta.Value, delegate(string newName, string newItems, DeltaSetting newDelta) { pack.Name.Value = newName; pack.Items.Value = newItems; pack.GrabDelta.Value = newDelta; ListGrabPacks(); }, delegate { ListGrabPacks(); }); } private static void FindContainersWithMatchingItems(ConsoleEventArgs args) { if (args.Length <= 1) { string text = "Please specify the text you want to search for in nearby containers"; ((Component)Chat.instance).SendMessage(text); Log.LogInfo((object)text); return; } float num = 50f; string text2 = args[1]; List<Container> nearbyContainers = Boxes.GetNearbyContainers(num); Log.LogInfo((object)$"searching for {text2} in {nearbyContainers.Count} containers within {num} meters"); foreach (Container item in nearbyContainers) { Inventory inventory = item.GetInventory(); foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem.Name().Contains(text2)) { Log.LogInfo((object)("it contains " + text2 + "!")); item.Highlight(); } } if (inventory.ContainsItemByName(text2)) { Log.LogInfo((object)("it contains " + text2 + "!")); item.Highlight(); } } } private static void StoreItemsInNearbyContainers() { float num = 50f; List<Container> nearbyContainers = Boxes.GetNearbyContainers(num); Player localPlayer = Player.m_localPlayer; Inventory inventory = ((Humanoid)localPlayer).GetInventory(); List<ItemData> list = new List<ItemData>(); ((Character)localPlayer).Message((MessageType)2, $"Storing items in {nearbyContainers.Count} containers within {num} meters", 0, (Sprite)null, false); for (int i = 1; i < inventory.GetHeight(); i++) { for (int j = 0; j < inventory.GetWidth(); j++) { ItemData itemAt = inventory.GetItemAt(j, i); if (itemAt != null) { list.Add(itemAt); } } } Log.LogInfo((object)$"storing {list.Count()} items in {nearbyContainers.Count} containers within {num} meters"); int num2 = 0; while (list.Count > 0) { nearbyContainers[num2].StoreItemInContainer(list[0]); num2++; if (num2 == nearbyContainers.Count) { num2 = 0; } list.RemoveAt(0); } } private static void CountInventory(ConsoleEventArgs args) { string text = ""; int num = 0; Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); if (args.Length > 1) { text = args[1]; num = inventory.CountItems(text, -1, true); Log.LogInfo((object)$"{num} {text} in inventory"); } else { num = inventory.CountItems(); Log.LogInfo((object)$"{num} items in inventory"); } } } } namespace GrabMaterials { internal class Boxes { internal static readonly List<Container> Containers = new List<Container>(); private static readonly List<Container> ContainersToAdd = new List<Container>(); private static readonly List<Container> ContainersToRemove = new List<Container>(); internal static readonly List<Smelter> Smelters = new List<Smelter>(); private static readonly List<Smelter> SmeltersToAdd = new List<Smelter>(); private static readonly List<Smelter> SmeltersToRemove = new List<Smelter>(); internal static void AddContainer(Container container) { if (!Containers.Contains(container)) { ContainersToAdd.Add(container); Logger.LogDebug((object)$"Added container {((Object)container).name} ({((object)container).GetType()} {((Object)container).GetInstanceID()}) to list"); } UpdateContainers(); } internal static void RemoveContainer(Container container) { if (Containers.Contains(container)) { ContainersToRemove.Add(container); Logger.LogDebug((object)$"Removed container {((Object)container).name} ({((object)container).GetType()} {((Object)container).GetInstanceID()}) from list"); } UpdateContainers(); } internal static void UpdateContainers() { foreach (Container item in ContainersToAdd) { Containers.Add(item); } ContainersToAdd.Clear(); foreach (Container item2 in ContainersToRemove) { Containers.Remove(item2); } ContainersToRemove.Clear(); } internal static void ConditionallyAddContainer(Container container, string trigger) { if (container.GetInventory() != null) { Game.instance.GetPlayerProfile().GetPlayerID(); AddContainer(container); } } internal static void AddSmelter(Smelter smelter) { if (!Smelters.Contains(smelter)) { SmeltersToAdd.Add(smelter); Logger.LogDebug((object)$"Added smelter {((Object)smelter).name} ({((object)smelter).GetType()} {((Object)smelter).GetInstanceID()}) to list"); } UpdateSmelters(); } internal static void RemoveSmelter(Smelter smelter) { if (Smelters.Contains(smelter)) { SmeltersToRemove.Add(smelter); Logger.LogDebug((object)$"Removed smelter {((Object)smelter).name} ({((object)smelter).GetType()} {((Object)smelter).GetInstanceID()}) from list"); } UpdateSmelters(); } internal static void UpdateSmelters() { foreach (Smelter item in SmeltersToAdd) { Smelters.Add(item); } SmeltersToAdd.Clear(); foreach (Smelter item2 in SmeltersToRemove) { Smelters.Remove(item2); } SmeltersToRemove.Clear(); } internal static void ConditionallyAddSmelter(Smelter smelter) { if (!((Object)(object)smelter == (Object)null)) { AddSmelter(smelter); } } internal static List<Smelter> GetNearbySmelters(float radius) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) List<Smelter> list = new List<Smelter>(); if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return list; } Vector3 position = ((Component)Player.m_localPlayer).transform.position; foreach (Smelter smelter in Smelters) { if ((Object)(object)smelter == (Object)null || (Object)(object)((Component)smelter).transform == (Object)null) { SmeltersToRemove.Add(smelter); } else if (Vector3.Distance(position, ((Component)smelter).transform.position) < radius) { list.Add(smelter); } } UpdateSmelters(); return list; } internal static List<Container> GetNearbyContainers(float radius) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) List<Container> list = new List<Container>(); if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return list; } Vector3 position = ((Component)Player.m_localPlayer).transform.position; global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)$"checking distance of {Containers.Count} containers"); foreach (Container container in Containers) { if ((Object)(object)container == (Object)null) { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogWarning((object)"Found null container in list"); ContainersToRemove.Add(container); } else if ((Object)(object)((Component)container).transform == (Object)null) { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogWarning((object)("Found container " + ((Object)container).name + " with null transform in list")); ContainersToRemove.Add(container); } else if (Vector3.Distance(position, ((Component)container).transform.position) < radius) { list.Add(container); } } UpdateContainers(); return list; } } [HarmonyPatch(typeof(Chat), "SendText")] public class HookChatInputText { private const float SearchRadius = 50f; private static void SearchNearbyContainersFor(string query) { foreach (Piece nearbyMatchingPiece in GetNearbyMatchingPieces(query)) { HighlightPiece(nearbyMatchingPiece); } } private static IEnumerable<Piece> GetNearbyMatchingPieces(string query) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) List<Piece> list = new List<Piece>(); Piece.GetAllPiecesInRadius(((Component)Player.m_localPlayer).transform.position, 50f, list); return from p in list where Object.op_Implicit((Object)(object)((Component)p).GetComponent<Container>()) where ContainerContainsMatchingItem(p, query) select p; } private static bool ContainerContainsMatchingItem(Piece container, string query) { return (from i in ((Component)container).GetComponent<Container>().GetInventory().GetAllItems() where NormalizedItemName(i).Contains(query) select i).Any(); } private static string NormalizedItemName(ItemData itemData) { return itemData.m_shared.m_name.ToLower(); } private static void HighlightPiece(Piece p) { WearNTear component = ((Component)p).GetComponent<WearNTear>(); if (Object.op_Implicit((Object)(object)component)) { component.Highlight(); } } } internal static class ConsoleCommands { private struct ItemToGrab { public string Name; public int Count; public string FullName => "$item_" + Name; public ItemToGrab(string name, int count) { Name = name.Replace("$item_", ""); Count = count; } } private static Dictionary<string, Piece> pieceLookup = new Dictionary<string, Piece>(); private static Dictionary<string, GameObject> itemLookup = new Dictionary<string, GameObject>(); private static readonly Dictionary<string, int> _pendingByName = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); private static float _lastGrabTime; private static string _lastFailedRequestKey; private static float _lastFailedRequestTime; private const float OverrideTimeoutSeconds = 30f; private static FieldRef<Hud, List<PieceIconData>> _pieceIconsAccessor; private static Dictionary<string, string> sharedNameLookup = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); internal static bool GlobalDelta => global::GrabMaterialsMod.GrabMaterialsMod.Instance?.GrabDeltaGlobal?.Value ?? true; private static float LedgerTimeoutSeconds => global::GrabMaterialsMod.GrabMaterialsMod.Instance?.GrabDeltaLedgerTimeout?.Value ?? 30f; internal static bool ResolveDelta(global::GrabMaterialsMod.GrabMaterialsMod.DeltaSetting setting) { return setting switch { global::GrabMaterialsMod.GrabMaterialsMod.DeltaSetting.On => true, global::GrabMaterialsMod.GrabMaterialsMod.DeltaSetting.Off => false, _ => GlobalDelta, }; } internal static void ResetPendingLedger() { _pendingByName.Clear(); _lastGrabTime = 0f; } private static void MaybeExpirePendingLedger() { if (_pendingByName.Count != 0 && Time.time - _lastGrabTime > LedgerTimeoutSeconds) { _pendingByName.Clear(); } } private static int GetPending(string name) { if (!_pendingByName.TryGetValue(name, out var value)) { return 0; } return value; } private static void AddPending(string name, int amount) { if (amount > 0) { _pendingByName[name] = GetPending(name) + amount; } } internal static void ClearOverrideState() { _lastFailedRequestKey = null; _lastFailedRequestTime = 0f; } private static string ComputeRequestKey(string requestLabel, List<ItemToGrab> aggregated) { if (!string.IsNullOrEmpty(requestLabel)) { return "label:" + requestLabel.ToLowerInvariant(); } StringBuilder stringBuilder = new StringBuilder("items:"); foreach (ItemToGrab item in aggregated) { stringBuilder.Append(item.Name.ToLowerInvariant()).Append(':').Append(item.Count) .Append(','); } return stringBuilder.ToString(); } private static bool IsOverrideRequest(string key) { if (_lastFailedRequestKey != null && _lastFailedRequestKey == key) { return Time.time - _lastFailedRequestTime <= 30f; } return false; } public static void GrabMaterialsForPiece(this ConsoleEventArgs args) { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)("GrabMaterialsForPiece(" + args.FullLine + ")")); if (args.Length <= 1) { string text = "usage: /grabpiece <name>, e.g. /grab workbench"; ((Component)Chat.instance).SendMessage(text); global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)text); } else { string text2 = args[1]; global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)("name of piece to grab materials for: " + text2)); GrabMaterialsForPiece(text2); } } public static void GrabMaterialsForPack(global::GrabMaterialsMod.GrabMaterialsMod.GrabPackConfig grabPack) { GrabMaterialsForPack(grabPack.Name.Value, grabPack.Items.Value, ResolveDelta(grabPack.GrabDelta.Value)); } public static void GrabMaterialsForPack(string packName, string itemsString, bool grabDelta = false) { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)("GrabMaterialsForPack(" + packName + ", " + itemsString + ")")); List<ItemToGrab> list = new List<ItemToGrab>(); string[] array = itemsString.Replace(" ", "").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { ':' }, StringSplitOptions.RemoveEmptyEntries); if (array2.Length > 2) { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogError((object)("Invalid format for " + packName + " item list: was " + itemsString + ", expected 'item[:quantity],item[:quantity],...'")); return; } string text = array2[0]; int result = 1; if (array2.Length == 2 && !int.TryParse(array2[1], out result)) { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogError((object)("Invalid format for " + packName + " item list: was " + itemsString + ", expected 'item[:quantity],item[:quantity],...'")); return; } global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)$"grabbing {result} {text}"); foreach (ItemToGrab item in GetItemsToGrab(text, result)) { list.Add(item); } } GrabItemsFromNearbyContainers(list, 50f, packName, grabDelta); } public static void GrabUndiscoveredItems(float radius = 50f) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } HashSet<string> hashSet = new HashSet<string>(); List<ItemToGrab> list = new List<ItemToGrab>(); foreach (Container nearbyContainer in Boxes.GetNearbyContainers(radius)) { Inventory inventory = nearbyContainer.GetInventory(); if (inventory == null) { continue; } foreach (ItemData allItem in inventory.GetAllItems()) { string name = allItem.m_shared.m_name; if (!localPlayer.IsMaterialKnown(name) && hashSet.Add(name)) { list.Add(new ItemToGrab(allItem.Name(), 1)); } } } if (list.Count == 0) { ((Character)localPlayer).Message((MessageType)2, "Nothing here you have not held before", 0, (Sprite)null, false); return; } global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)$"grabbing one each of {list.Count} never-held items"); GrabItemsFromNearbyContainers(list, radius, "New Items"); } public static void GrabItemsFromNearbyContainers(this ConsoleEventArgs args) { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)$"GrabItemsFromNearbyContainers('{args.FullLine})' args.Length={args.Length}"); if (args.Length > 1) { if (args[1] == "pack") { int num = int.Parse(args[2]) - 1; GrabMaterialsForPack(global::GrabMaterialsMod.GrabMaterialsMod.Instance.GrabPacks[num]); return; } if (args.Length == 2 && string.Equals(args[1], "new", StringComparison.OrdinalIgnoreCase)) { GrabUndiscoveredItems(); return; } global::GrabMaterialsMod.GrabMaterialsMod.GrabPackConfig[] grabPacks = global::GrabMaterialsMod.GrabMaterialsMod.Instance.GrabPacks; foreach (global::GrabMaterialsMod.GrabMaterialsMod.GrabPackConfig grabPackConfig in grabPacks) { string argsAll = args.ArgsAll; global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)("Checking pack " + grabPackConfig.Name.Value + " against args.ArgsAll='" + argsAll + "'")); if (grabPackConfig.Name.Value == args.ArgsAll) { GrabMaterialsForPack(grabPackConfig); return; } } int num2 = args.Length - 1; int result = 0; int num3 = ((!int.TryParse(args[1], out result)) ? 1 : 2); int num4 = num2; if (result == 0) { num4 = (int.TryParse(args[num2], out result) ? (num2 - 1) : num2); if (result == 0) { result = 1; } } global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)$"count={result}, n={num2}, nameStartingArg={num3}, nameEndingArg={num4}"); StringBuilder stringBuilder = new StringBuilder(); for (int j = num3; j <= num4; j++) { if (stringBuilder.Length > 0) { stringBuilder.Append(" "); } stringBuilder.Append(args[j]); } string text = stringBuilder.ToString(); if (text != "") { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)$"grabbing {result} '{text}'"); GrabItemsFromNearbyContainers(text, result); return; } } string text2 = "usage: /grab <all | name> [count], e.g. /grab 10 wood"; ((Component)Chat.instance).SendMessage(text2); global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)text2); } public static Requirement[] GetPieceRequirements(string pieceName) { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)("GetPieceRequirements(" + pieceName + ")")); if (!Object.op_Implicit((Object)(object)ZNetScene.instance)) { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogWarning((object)"Cannot look for prefab: ZNetScene.instance is null"); return null; } global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)"looking for prefab..."); global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)$"ZNetScene.instance has {ZNetScene.instance.m_prefabs.Count} prefabs"); GameObject val = ZNetScene.instance.m_prefabs.Find((GameObject _prefab) => ((Object)_prefab).name == pieceName); if ((Object)(object)val == (Object)null) { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogError((object)("No prefab found for " + pieceName)); return null; } global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)("Prefab found: " + ((Object)val).name + " " + ((Object)val.gameObject).name + " " + val.gameObject.tag + " " + val.gameObject.GetComponent<Piece>().m_name)); return val.gameObject.GetComponent<Piece>().m_resources; } private static void GrabMaterialsForPiece(string pieceName) { Requirement[] pieceRequirements = GetPieceRequirements(pieceName); if (pieceRequirements != null) { List<ItemToGrab> list = new List<ItemToGrab>(); Requirement[] array = pieceRequirements; foreach (Requirement val in array) { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)$"Grabbing for {pieceName}: {val.m_amount} {val.m_resItem.m_itemData.m_shared.m_name}"); list.Add(new ItemToGrab(val.m_resItem.m_itemData.m_shared.m_name, val.m_amount)); } GrabItemsFromNearbyContainers(list, 50f, pieceName, GlobalDelta); } } private static void GrabItemsFromNearbyContainers(List<ItemToGrab> itemsToGrab, float radius, string requestLabel = null, bool grabDelta = false) { List<Container> nearbyContainers = Boxes.GetNearbyContainers(radius); Player localPlayer = Player.m_localPlayer; List<ItemToGrab> list = new List<ItemToGrab>(); foreach (ItemToGrab item in itemsToGrab) { int num = list.FindIndex((ItemToGrab a) => string.Equals(a.Name, item.Name, StringComparison.OrdinalIgnoreCase)); if (num >= 0) { ItemToGrab value = list[num]; value.Count += item.Count; list[num] = value; } else { list.Add(item); } } if (grabDelta) { MaybeExpirePendingLedger(); } int[] array = new int[list.Count]; int[] array2 = new int[list.Count]; for (int num2 = 0; num2 < list.Count; num2++) { if (grabDelta && (Object)(object)localPlayer != (Object)null) { Inventory inventory = ((Humanoid)localPlayer).GetInventory(); if (inventory != null) { foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem.isMatch(list[num2].Name)) { array[num2] += allItem.Count(); } } } int pending = GetPending(list[num2].Name); if (pending > 0) { array[num2] = Math.Max(0, array[num2] - pending); } } array2[num2] = Math.Max(0, list[num2].Count - array[num2]); } bool flag = true; for (int num3 = 0; num3 < list.Count; num3++) { if (array2[num3] > 0) { flag = false; break; } } int[] array3 = new int[list.Count]; foreach (Container item3 in nearbyContainers) { Inventory inventory2 = item3.GetInventory(); if (inventory2 == null) { continue; } foreach (ItemData allItem2 in inventory2.GetAllItems()) { for (int num4 = 0; num4 < list.Count; num4++) { if (array2[num4] != 0 && allItem2.isMatch(list[num4].Name)) { array3[num4] += allItem2.Count(); break; } } } } bool flag2 = false; for (int num5 = 0; num5 < list.Count; num5++) { if (array2[num5] > 0 && array3[num5] < array2[num5]) { flag2 = true; break; } } string text = ComputeRequestKey(requestLabel, list); bool flag3 = flag2 && IsOverrideRequest(text); if (flag2 && !flag3) { List<MaterialsPanel.ItemStatus> list2 = new List<MaterialsPanel.ItemStatus>(list.Count); List<string> list3 = new List<string>(); for (int num6 = 0; num6 < list.Count; num6++) { list2.Add(new MaterialsPanel.ItemStatus { Name = LocalizeItemName(list[num6]), Needed = list[num6].Count, Had = array[num6], Available = array3[num6] }); if (array2[num6] > array3[num6]) { list3.Add($"{array2[num6] - array3[num6]} of {list[num6].Count} {list[num6].Name}"); } } global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)("Cannot grab" + (string.IsNullOrEmpty(requestLabel) ? "" : (" for " + requestLabel)) + " - missing: " + string.Join(", ", list3))); MaterialsPanel.Show(string.IsNullOrEmpty(requestLabel) ? "Missing materials — run again to grab what's available" : ("Missing materials for " + requestLabel + " — run again to grab what's available"), list2); _lastFailedRequestKey = text; _lastFailedRequestTime = Time.time; if (grabDelta) { _lastGrabTime = Time.time; } return; } List<MaterialsPanel.ItemStatus> list4 = new List<MaterialsPanel.ItemStatus>(list.Count); for (int num7 = 0; num7 < list.Count; num7++) { ItemToGrab item2 = list[num7]; int num8 = array2[num7]; if (num8 > 0) { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)$"grabbing {num8} {item2.Name} from {nearbyContainers.Count} containers within {radius} meters"); for (int num9 = 0; num9 < nearbyContainers.Count; num9++) { if (num8 <= 0) { break; } int num10 = nearbyContainers[num9].GrabItemFromContainer(item2.Name, num8); num8 -= num10; } } int num11 = array2[num7] - num8; if (grabDelta) { AddPending(item2.Name, num11); } list4.Add(new MaterialsPanel.ItemStatus { Name = LocalizeItemName(item2), Needed = item2.Count, Had = array[num7], Available = num11 }); } if (grabDelta) { _lastGrabTime = Time.time; } ClearOverrideState(); string text2; if (!flag) { text2 = ((!flag3) ? (string.IsNullOrEmpty(requestLabel) ? "Grabbed materials" : ("Grabbed materials for " + requestLabel)) : (string.IsNullOrEmpty(requestLabel) ? "Partial grab" : ("Partial grab for " + requestLabel))); } else { text2 = (string.IsNullOrEmpty(requestLabel) ? "Already have everything" : ("Already have everything for " + requestLabel)); global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)text2); } MaterialsPanel.Show(text2, list4); } private static string LocalizeItemName(ItemToGrab item) { string text = Extensions.Localize(item.FullName); if (!string.IsNullOrEmpty(text) && !(text == item.FullName)) { return text; } return item.Name; } private static string LocalizePieceName(Piece piece) { if ((Object)(object)piece == (Object)null) { return null; } if (!piece.m_name.StartsWith("$")) { return piece.m_name; } try { string text = Extensions.Localize(piece.m_name); return (string.IsNullOrEmpty(text) || text == piece.m_name) ? piece.m_name : text; } catch { return piece.m_name; } } public static void GrabMaterialsForSelectedPiece() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { Piece val = GetHoveredBuildPiece() ?? localPlayer.GetSelectedPiece(); if (!Object.op_Implicit((Object)(object)val)) { string text = "No build piece selected or hovered"; global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)text); ((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false); } else { GrabMaterialsForPiece(val); } } } public static void HighlightContainersHolding(string sharedName) { if (string.IsNullOrEmpty(sharedName)) { return; } foreach (Container nearbyContainer in Boxes.GetNearbyContainers(50f)) { Inventory inventory = nearbyContainer.GetInventory(); if (inventory == null) { continue; } foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem.m_shared.m_name == sharedName) { nearbyContainer.Highlight(); break; } } } } public static void HighlightContainersHoldingAny(ICollection<string> sharedNames) { if (sharedNames == null || sharedNames.Count == 0) { return; } HashSet<string> hashSet = (sharedNames as HashSet<string>) ?? new HashSet<string>(sharedNames); foreach (Container nearbyContainer in Boxes.GetNearbyContainers(50f)) { Inventory inventory = nearbyContainer.GetInventory(); if (inventory == null) { continue; } foreach (ItemData allItem in inventory.GetAllItems()) { if (hashSet.Contains(allItem.m_shared.m_name)) { nearbyContainer.Highlight(); break; } } } } public static Piece GetHoveredBuildPiece() { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) Hud instance = Hud.instance; Player localPlayer = Player.m_localPlayer; if ((Object)(object)instance == (Object)null || (Object)(object)localPlayer == (Object)null) { return null; } if (_pieceIconsAccessor == null) { try { _pieceIconsAccessor = AccessTools.FieldRefAccess<Hud, List<PieceIconData>>("m_pieceIcons"); } catch (Exception ex) { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogWarning((object)("GrabMaterials: cannot reflect Hud.m_pieceIcons - " + ex.Message)); return null; } } List<PieceIconData> list = _pieceIconsAccessor.Invoke(instance); if (list == null) { return null; } foreach (PieceIconData item in list) { if (item == null) { continue; } Image icon = item.m_icon; if ((Object)(object)icon == (Object)null || !((Component)icon).gameObject.activeInHierarchy || !RectTransformUtility.RectangleContainsScreenPoint(((Graphic)icon).rectTransform, Vector2.op_Implicit(Input.mousePosition))) { continue; } Sprite sprite = icon.sprite; if ((Object)(object)sprite == (Object)null) { return null; } List<Piece> buildPieces = localPlayer.GetBuildPieces(); if (buildPieces == null) { return null; } foreach (Piece item2 in buildPieces) { if ((Object)(object)item2 != (Object)null && (Object)(object)item2.m_icon == (Object)(object)sprite) { return item2; } } return null; } return null; } public static void GrabMaterialsForPiece(Piece piece) { Requirement[] resources = piece.m_resources; global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)$"grabbing materials for selected piece {((Object)piece).name} - requires {resources.Count()} resources"); if (resources != null) { List<ItemToGrab> list = new List<ItemToGrab>(); Requirement[] array = resources; foreach (Requirement val in array) { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)$"{val.m_amount} {val.m_resItem.m_itemData.Name()}"); list.Add(new ItemToGrab(val.m_resItem.m_itemData.Name(), val.m_amount)); } GrabItemsFromNearbyContainers(list, 10f, LocalizePieceName(piece), GlobalDelta); } } private static void BuildPieceLookUp() { if ((Object)(object)ObjectDB.instance == (Object)null) { return; } if (!Object.op_Implicit((Object)(object)ZNetScene.instance)) { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogWarning((object)"Cannot index: ZNetScene.instance is null"); return; } global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)"building lookup table for all build pieces"); Piece val = default(Piece); foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { if (prefab.TryGetComponent<Piece>(ref val) && !StringExtensions.ContainsAny(((Object)prefab).name, new string[2] { "loot_chest", "TreasureChest" })) { string text = ""; try { text = ((!val.m_name.StartsWith("$")) ? val.m_name : Extensions.Localize(val.m_name)); } catch (Exception ex) { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogError((object)("Error translating piece name " + val.m_name + ": " + ex.Message)); text = val.m_name; } pieceLookup[text.ToLowerInvariant()] = val; } } } private static void BuildItemLookUp() { if ((Object)(object)ObjectDB.instance == (Object)null) { return; } Logger.LogInfo((object)"Building item lookup..."); foreach (GameObject item in ObjectDB.instance.m_items) { if (!((Object)(object)item == (Object)null)) { string name = ((Object)item).name; itemLookup[name] = item; } } Logger.LogInfo((object)$"Built a lookup table with {itemLookup.Count} items."); } private static void BuildSharedNameLookup() { if ((Object)(object)ObjectDB.instance == (Object)null) { return; } foreach (GameObject item in ObjectDB.instance.m_items) { string text = (((Object)(object)item != (Object)null) ? item.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared?.m_name; if (!string.IsNullOrEmpty(text) && text.StartsWith("$item_")) { string key = Extensions.TokenName(text); if (!sharedNameLookup.ContainsKey(key)) { sharedNameLookup[key] = text; } } } } internal static bool AreAllPackMaterialsKnown(string itemsString, Player player) { if ((Object)(object)player == (Object)null || string.IsNullOrWhiteSpace(itemsString)) { return true; } if ((Object)(object)ObjectDB.instance == (Object)null || !Object.op_Implicit((Object)(object)ZNetScene.instance)) { return true; } if (sharedNameLookup.Count == 0) { BuildSharedNameLookup(); } if (pieceLookup.Count == 0) { BuildPieceLookUp(); } string[] array = itemsString.Replace(" ", "").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = array[i].Split(new char[1] { ':' })[0]; string value2; if (pieceLookup.TryGetValue(text.ToLowerInvariant(), out var value)) { if (value.m_resources == null) { continue; } Requirement[] resources = value.m_resources; for (int j = 0; j < resources.Length; j++) { string text2 = resources[j].m_resItem?.m_itemData?.m_shared?.m_name; if (!string.IsNullOrEmpty(text2) && !player.IsMaterialKnown(text2)) { return false; } } } else if (sharedNameLookup.TryGetValue(text.Replace("$item_", ""), out value2) && !player.IsMaterialKnown(value2)) { return false; } } return true; } private static List<ItemToGrab> GetItemsToGrab(string name, int count = 1) { List<ItemToGrab> list = new List<ItemToGrab>(); if (pieceLookup.Count == 0) { BuildPieceLookUp(); } if (itemLookup.Count == 0) { BuildItemLookUp(); } if (pieceLookup.ContainsKey(name.ToLowerInvariant())) { Piece obj = pieceLookup[name.ToLowerInvariant()]; global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)("Found piece " + name + " in lookup table, grabbing materials for it")); Requirement[] resources = obj.m_resources; if (resources != null) { Requirement[] array = resources; foreach (Requirement val in array) { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)$"{val.m_amount} {val.m_resItem.m_itemData.Name()}"); list.Add(new ItemToGrab(val.m_resItem.m_itemData.Name(), val.m_amount * count)); } } } else { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)("No piece found for " + name + ", looking for material by this name instead")); list.Add(new ItemToGrab(name, count)); } return list; } public static void GrabItemsFromNearbyContainers(string name, int count = 1) { float radius = 50f; List<ItemToGrab> itemsToGrab = GetItemsToGrab(name, count); bool flag = pieceLookup.ContainsKey(name.ToLowerInvariant()); string requestLabel = (flag ? name : null); GrabItemsFromNearbyContainers(itemsToGrab, radius, requestLabel, flag && GlobalDelta); } } internal class ContainerFinder { public static List<Container> FindNearbyContainers(Vector3 position, float radius) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)$"FindNearbyContainers with {radius} meters"); global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)position); List<Container> list = new List<Container>(); Collider[] array = Physics.OverlapSphere(position, radius); global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)$"{array.Count()} colliders"); Collider[] array2 = array; foreach (Collider val in array2) { global::GrabMaterialsMod.GrabMaterialsMod.Log.LogInfo((object)(((Object)val).name ?? "")); Container component = ((Component)val).GetComponent<Container>(); ((Component)component).GetComponent<ContainerFilterService>(); if ((Object)(object)component != (Object)null) { list.Add(component); } } return list; } } [HarmonyPatch(typeof(Container), "Load")] internal class ContainerLoadPatch { private static void Postfix(Container __instance) { Boxes.ConditionallyAddContainer(__instance, "Load"); } } [HarmonyPatch(typeof(Container), "Awake")] internal static class ContainerAwakePatch { private static void Postfix(Container __instance) { Boxes.ConditionallyAddContainer(__instance, "Awake"); } } [HarmonyPatch(typeof(Container), "OnDestroyed")] internal static class ContainerOnDestroyedPatch { private static void Postfix(Container __instance) { Boxes.RemoveContainer(__instance); } } [HarmonyPatch(typeof(Player), "UpdateTeleport")] public static class PlayerUpdateTeleportPatchCleanupContainers { public static void Prefix(float dt) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsTeleporting()) { return; } foreach (Container item in from container in Boxes.Containers.ToList() where !((Object)container != (Object)null) || !((Object)((Component)container).transform != (Object)null) || container.GetInventory() == null where (Object)container != (Object)null select container) { Boxes.RemoveContainer(item); } } } [HarmonyPatch(typeof(WearNTear), "OnDestroy")] internal static class WearNTearOnDestroyPatch { private static void Prefix(WearNTear __instance) { Container[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<Container>(); Container[] componentsInParent = ((Component)__instance).GetComponentsInParent<Container>(); if (componentsInChildren.Length != 0) { Container[] array = componentsInChildren; for (int i = 0; i < array.Length; i++) { Boxes.RemoveContainer(array[i]); } } if (componentsInParent.Length != 0) { Container[] array2 = componentsInParent; for (int j = 0; j < array2.Length; j++) { Boxes.RemoveContainer(array2[j]); } } } } public static class DistanceHud { private const float UpdateInterval = 0.2f; private const float Width = 320f; private const float Height = 30f; private static GameObject _go; private static Text _text; private static RectTransform _rect; private static float _lastUpdate; private static bool Enabled => global::GrabMaterialsMod.GrabMaterialsMod.Instance?.ShowDistanceHud?.Value ?? true; private static bool ShowCoords => global::GrabMaterialsMod.GrabMaterialsMod.Instance?.ShowDistanceCoords?.Value == true; private static float OffsetX => global::GrabMaterialsMod.GrabMaterialsMod.Instance?.DistanceHudOffsetX?.Value ?? 10f; private static float OffsetY => global::GrabMaterialsMod.GrabMaterialsMod.Instance?.DistanceHudOffsetY?.Value ?? 10f; public static void Tick() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_00e0: Unknown result type (might be due to invalid IL or missing references) EnsureCreated(); if ((Object)(object)_text == (Object)null) { return; } Player localPlayer = Player.m_localPlayer; bool flag = Enabled && (Object)(object)localPlayer != (Object)null; if (_go.activeSelf != flag) { _go.SetActive(flag); } if (flag) { _rect.anchoredPosition = new Vector2(OffsetX, 0f - OffsetY); float time = Time.time; if (!(time - _lastUpdate < 0.2f)) { _lastUpdate = time; Vector3 position = ((Component)localPlayer).transform.position; float num = Mathf.Sqrt(position.x * position.x + position.z * position.z); _text.text = (ShowCoords ? $"World Center: {num:F0}m ({position.x:F0}, {position.z:F0})" : $"World Center: {num:F0}m"); } } } private static void EnsureCreated() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_go != (Object)null) && GUIManager.Instance != null && !((Object)(object)GUIManager.CustomGUIFront == (Object)null)) { _go = GUIManager.Instance.CreateText(string.Empty, GUIManager.CustomGUIFront.transform, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(OffsetX, 0f - OffsetY), GUIManager.Instance.AveriaSerifBold, 16, GUIManager.Instance.ValheimOrange, true, Color.black, 320f, 30f, false); ((Object)_go).name = "GrabMaterials_DistanceHud"; _rect = _go.GetComponent<RectTransform>(); _rect.pivot = new Vector2(0f, 1f); _rect.anchoredPosition = new Vector2(OffsetX, 0f - OffsetY); _text = _go.GetComponent<Text>(); _text.alignment = (TextAnchor)0; ((Graphic)_text).raycastTarget = false; } } } internal static class Extensions { public enum ItemCategory { None, Weapon, Armor, Tool, Shield, Arrow, Bolt, Trophy, Utility, Mead, BalancedFood, HealthFood, StaminaFood, EitrFood, RawMeat, CookedMeat, Summoning, Metal, Wood, Stone, Treasure, Skin, Plant, FoodIngredient, FishingBait, Seed, Weed, Material, Misc } private static readonly HashSet<string> BossSummoningNames = new HashSet<string> { "trophydeer", "ancientseed", "witheredbone", "dragonegg", "goblintotem", "seekerbrood", "trophyfader", "bellfragment", "sealbreaker", "sealbreakerfragment" }; private static readonly HashSet<string> RawMeatNames = new HashSet<string> { "rawmeat", "wolfmeat", "loxmeat", "deermeat", "serpentmeat", "fishraw", "haremeat", "seekermeat", "chickenmeat", "asksvintail", "bonemawmeat", "chickenegg", "entrails", "necktail" }; private static readonly HashSet<string> CookedMeatNames = new HashSet<string> { "cooked_boar_meat", "cookedwolfmeat", "cookedloxmeat", "cookeddeermeat", "serpentmeatcooked", "cookedfish", "cookedharemeat", "cookedseekermeat", "cookedchickenmeat", "cookedbonemawmeat", "NeckTailGrilled" }; private static readonly HashSet<string> FoodIngredientNames = new HashSet<string> { "barleyflour", "bloodclot", "royaljelly" }; private static readonly HashSet<string> FishingBaitNames = new HashSet<string> { "fishingbait", "fishingbaitashlands", "fishingbaitcave", "fishingbaitdeepnorth", "fishingbaitforest", "fishingbaitmistlands", "fishingbaitocean", "fishingbaitplains", "fishingbaitswamp" }; private static readonly HashSet<string> AmmoNames = new HashSet<string> { "payload_grausten", "payload_explosive" }; private static readonly HashSet<string> SkinNames = new HashSet<string> { "leatherscraps", "deerhide", "trollhide", "wolfpelt", "loxpelt", "feathers", "chitin", "scalehide", "harepelt", "carapace", "askbladder", "askhide", "bonemawtooth", "celestialfeather", "fenrisclaw", "fenrishair", "mandible", "queendrop", "morgenheart", "morgensinew", "needle", "root", "ooze", "wolf_fang" }; private static readonly HashSet<string> TreasureNames = new HashSet<string> { "coins", "ruby", "amber", "amberpearl", "silvernecklace" }; private static readonly HashSet<string> WoodNames = new HashSet<string> { "wood", "finewood", "roundlog", "yggdrasilwood", "elderbark", "blackwood" }; private static readonly HashSet<string> StoneNames = new HashSet<string> { "stone", "flint", "obsidian", "marble", "blackmarble", "coal", "crystal", "grausten" }; private static r