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 NewtCraftHub v1.9.1
plugins/NewtCraftHub.dll
Decompiled a month 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.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using NewtCraftHub.Addons; using NewtCraftHub.Core; using NewtCraftHub.Integration; using NewtCraftHub.Patches; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("NewtCraftHub")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.9.1.0")] [assembly: AssemblyInformationalVersion("1.9.1+5da251a93cafd66c6ea77496b25a65aa08db9c9a")] [assembly: AssemblyProduct("NewtCraftHub")] [assembly: AssemblyTitle("NewtCraftHub")] [assembly: AssemblyVersion("1.9.1.0")] namespace NewtCraftHub { internal sealed class ConfigurationManagerAttributes { public bool? Browsable; } [BepInPlugin("newton.newtcraftboxes", "NewtCraftHub", "1.9.1")] [BepInProcess("valheim.exe")] [BepInProcess("valheim")] public sealed class Plugin : BaseUnityPlugin { public enum WhenFull { NearestChest, DropAtFeet } public const string Guid = "newton.newtcraftboxes"; public const string Name = "NewtCraftHub"; public const string Version = "1.9.1"; private const string RulesFileName = "newton.NewtCraftHub.yml"; private static readonly string[] LegacyRulesFileNames = new string[2] { "newton.NewtCraftBoxes.yml", "newton.CraftyStorage.yml" }; private const string LegacyConfigFileName = "newton.craftystorage.cfg"; private Harmony _harmony; private FileSystemWatcher _watcher; private volatile bool _rulesDirty; private FileSystemWatcher _configWatcher; private volatile bool _configDirty; private float _configReloadAt = -1f; private ConfigEntry<bool> _enabled; private ConfigEntry<bool> _craft; private ConfigEntry<bool> _fillWithShift; private ConfigEntry<bool> _shared; private ConfigEntry<bool> _cookingTimers; private ConfigEntry<bool> _cookingBurnTime; private ConfigEntry<string> _cookReadyIn; private ConfigEntry<string> _cookDone; private ConfigEntry<string> _cookBurns; private ConfigEntry<string> _cookBurnt; private ConfigEntry<string> _cookPaused; private ConfigEntry<float> _range; private ConfigEntry<KeyboardShortcut> _toggleKey; private ConfigEntry<bool> _onlyPlayerBuilt; private ConfigEntry<bool> _includeVehicles; private ConfigEntry<bool> _respectWards; private ConfigEntry<bool> _skipInUse; private ConfigEntry<bool> _takeOwnership; private ConfigEntry<bool> _stations; private ConfigEntry<float> _refreshInterval; private ConfigEntry<bool> _showAvailable; private ConfigEntry<bool> _debug; private ConfigEntry<bool> _showContents; private ConfigEntry<bool> _hoverAscending; private ConfigEntry<int> _hoverMaxItems; private ConfigEntry<ContentsSort> _hoverSortBy; private ConfigEntry<string> _hoverEntry; private ConfigEntry<string> _hoverOverflow; private ConfigEntry<string> _hoverCapacity; private ConfigEntry<bool> _itemInfo; private ConfigEntry<bool> _itemType; private ConfigEntry<bool> _itemTier; private ConfigEntry<bool> _itemStack; private ConfigEntry<bool> _itemNearby; private ConfigEntry<bool> _itemPrefab; private ConfigEntry<bool> _worldClock; private ConfigEntry<bool> _clockShadow; private ConfigEntry<bool> _farmGrid; private ConfigEntry<bool> _shiftHarvest; private ConfigEntry<string> _clockFormat; private ConfigEntry<string> _clockTemplate; private ConfigEntry<string> _clockPosition; private ConfigEntry<string> _clockColor; private ConfigEntry<string> _clockPeriods; private ConfigEntry<string> _gridColor; private ConfigEntry<int> _clockFontSize; private ConfigEntry<int> _gridSections; private ConfigEntry<int> _harvestMax; private ConfigEntry<float> _gridExtra; private ConfigEntry<float> _harvestRadius; private ConfigEntry<float> _harvestStamina; private ConfigEntry<KeyboardShortcut> _clockKey; private ConfigEntry<bool> _objectHealth; private ConfigEntry<bool> _healthTrees; private ConfigEntry<bool> _healthRocks; private ConfigEntry<bool> _healthOther; private ConfigEntry<bool> _healthColours; private ConfigEntry<bool> _areaRepair; private ConfigEntry<bool> _repairPerPiece; private ConfigEntry<float> _repairRadius; private ConfigEntry<bool> _portalItems; private ConfigEntry<bool> _tpMarkers; private ConfigEntry<bool> _tpPlayers; private ConfigEntry<bool> _tpMultiplayer; private ConfigEntry<bool> _tpPortalRules; private ConfigEntry<bool> _tpToMe; private ConfigEntry<float> _tpCooldown; private ConfigEntry<bool> _harvestBushes; private ConfigEntry<bool> _findItems; private ConfigEntry<bool> _creatureHealth; private ConfigEntry<bool> _healthPieces; private ConfigEntry<bool> _shipStatus; private ConfigEntry<bool> _shipWind; private ConfigEntry<bool> _shipPos; private ConfigEntry<string> _shipPosition; private ConfigEntry<int> _shipFont; private ConfigEntry<float> _findRange; private ConfigEntry<float> _findSeconds; private ConfigEntry<string> _findColor; private ConfigEntry<int> _tpMax; private ConfigEntry<bool> _extraSlots; private ConfigEntry<bool> _slotsAmmo; private ConfigEntry<bool> _slotsFood; private ConfigEntry<bool> _slotsMisc; private ConfigEntry<int> _slotsQuick; private ConfigEntry<int> _slotsUtility; private ConfigEntry<bool> _slotsHotbars; private ConfigEntry<bool> _graveTakeAll; private ConfigEntry<bool> _eternalFires; private ConfigEntry<bool> _eternalTorches; private ConfigEntry<bool> _eternalCampfires; private ConfigEntry<bool> _plantPickables; private ConfigEntry<bool> _growthTimers; private ConfigEntry<float> _plantRegrow; private ConfigEntry<string> _growReady; private ConfigEntry<string> _growBack; private ConfigEntry<string> _taming; private ConfigEntry<bool> _skipIntro; private ConfigEntry<bool> _saveAndPause; private ConfigEntry<bool> _craftSearch; private ConfigEntry<KeyboardShortcut> _pauseKey; private ConfigEntry<int> _snapshotsToKeep; private ConfigEntry<float> _pauseVoteSeconds; private ConfigEntry<float> _pauseResumeSeconds; private ConfigEntry<bool> _barsOnlyFocused; private ConfigEntry<bool> _recycle; private ConfigEntry<bool> _recycleButton; private ConfigEntry<float> _recyclePercent; private ConfigEntry<ModSettings.NoRecipe> _recycleNoRecipe; private ConfigEntry<WhenFull> _recycleFull; private ConfigEntry<KeyCode> _recycleKey; private ConfigEntry<string> _recycleLabel; private ConfigEntry<string> _recycleColor; private ConfigEntry<float> _barFade; private readonly ConfigEntry<KeyboardShortcut>[] _slotKeys = new ConfigEntry<KeyboardShortcut>[40]; private const int CurrentConfigVersion = 4; private const string DefaultRules = "# NewtCraftHub rules: per-container restrictions for pulling items.\n# Changes are picked up live while the game is running.\n#\n# groups: reusable lists of ITEM PREFAB names (case sensitive).\n# <container prefab>:\n# exclude: items or groups that must NOT be pulled from this container type\n# includeOverride: items or groups that are always allowed (wins over exclude)\n#\n# Predefined groups: All, Food, Potion, Fish, Swords, Bows, Crossbows, Axes, Clubs, Knives,\n# Pickaxes, Polearms, Spears, Equipment, Trophy, Boss Trophy, Crops, Seeds, Ores, Metals, Woods.\n#\n# Example:\n# groups:\n# Valuables:\n# - Coins\n# - Ruby\n# piece_chest_private:\n# exclude:\n# - All\n# piece_chest_wood:\n# exclude:\n# - Valuables\n# includeOverride:\n# - Coins\n"; private string RulesPath => Path.Combine(Paths.ConfigPath, "newton.NewtCraftHub.yml"); private void Awake() { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown Log.Info = ((BaseUnityPlugin)this).Logger.LogInfo; Log.Warn = ((BaseUnityPlugin)this).Logger.LogWarning; Log.Error = ((BaseUnityPlugin)this).Logger.LogError; Log.Debug = delegate(string s) { if (Runtime.Settings.DebugLogging) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[debug] " + s)); } }; MigrateLegacyConfig(); BindConfig(); LoadRules(); WatchRules(); WatchConfig(); SetUpCompatibility(); ((Component)this).gameObject.AddComponent<ClockHud>(); ((Component)this).gameObject.AddComponent<ShipHud>(); ((Component)this).gameObject.AddComponent<SlotBars>(); ((Component)this).gameObject.AddComponent<SaveAndPause>(); Pictograms.PrepareInBackground(96); _harmony = new Harmony("newton.newtcraftboxes"); int num = PatchInstaller.Apply(_harmony); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded ({2}/{3} patch groups active).", "NewtCraftHub", "1.9.1", num, PatchInstaller.PatchTypes.Length)); } private void MigrateLegacyConfig() { try { string text = Path.Combine(Paths.ConfigPath, "newton.craftystorage.cfg"); if (File.Exists(text) && !File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath)) { File.Copy(text, ((BaseUnityPlugin)this).Config.ConfigFilePath); ((BaseUnityPlugin)this).Config.Reload(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Imported settings from newton.craftystorage.cfg."); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not import newton.craftystorage.cfg: " + ex.Message)); } } private void BindConfig() { //IL_03d6: Unknown result type (might be due to invalid IL or missing references) //IL_03e0: Expected O, but got Unknown //IL_03f6: Unknown result type (might be due to invalid IL or missing references) //IL_04de: Unknown result type (might be due to invalid IL or missing references) //IL_04e8: Expected O, but got Unknown //IL_0532: Unknown result type (might be due to invalid IL or missing references) //IL_053c: Expected O, but got Unknown //IL_078c: Unknown result type (might be due to invalid IL or missing references) //IL_0834: Unknown result type (might be due to invalid IL or missing references) //IL_083e: Expected O, but got Unknown //IL_08dc: Unknown result type (might be due to invalid IL or missing references) //IL_08e6: Expected O, but got Unknown //IL_091a: Unknown result type (might be due to invalid IL or missing references) //IL_0924: Expected O, but got Unknown //IL_097d: Unknown result type (might be due to invalid IL or missing references) //IL_0987: Expected O, but got Unknown //IL_09bb: Unknown result type (might be due to invalid IL or missing references) //IL_09c5: Expected O, but got Unknown //IL_09f2: Unknown result type (might be due to invalid IL or missing references) //IL_09fc: Expected O, but got Unknown //IL_0af6: Unknown result type (might be due to invalid IL or missing references) //IL_0b00: Expected O, but got Unknown //IL_0b55: Unknown result type (might be due to invalid IL or missing references) //IL_0b5f: Expected O, but got Unknown //IL_0b8c: Unknown result type (might be due to invalid IL or missing references) //IL_0b96: Expected O, but got Unknown //IL_0c4e: Unknown result type (might be due to invalid IL or missing references) //IL_0c58: Expected O, but got Unknown //IL_0c8c: Unknown result type (might be due to invalid IL or missing references) //IL_0c96: Expected O, but got Unknown //IL_0d0a: Unknown result type (might be due to invalid IL or missing references) //IL_0d14: Expected O, but got Unknown //IL_0d7e: Unknown result type (might be due to invalid IL or missing references) //IL_0d88: Expected O, but got Unknown //IL_0db0: Unknown result type (might be due to invalid IL or missing references) //IL_0dba: Expected O, but got Unknown //IL_0eaf: Unknown result type (might be due to invalid IL or missing references) //IL_0f10: Unknown result type (might be due to invalid IL or missing references) //IL_0f87: Unknown result type (might be due to invalid IL or missing references) //IL_0fc8: Unknown result type (might be due to invalid IL or missing references) //IL_100b: Unknown result type (might be due to invalid IL or missing references) //IL_1015: Expected O, but got Unknown //IL_1049: Unknown result type (might be due to invalid IL or missing references) //IL_1053: Expected O, but got Unknown //IL_107d: Unknown result type (might be due to invalid IL or missing references) //IL_1087: Expected O, but got Unknown //IL_10bb: Unknown result type (might be due to invalid IL or missing references) //IL_10c5: Expected O, but got Unknown //IL_1168: Unknown result type (might be due to invalid IL or missing references) //IL_1172: Expected O, but got Unknown //IL_1296: Unknown result type (might be due to invalid IL or missing references) //IL_12a0: Expected O, but got Unknown _craft = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "CraftFromContainers", true, "ON/OFF: craft, build and upgrade using materials from nearby containers."); _stations = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "FeedStations", true, "ON/OFF: feed smelters, blast furnaces, kilns, windmills, spinning wheels, eitr refineries, fermenters and ovens from nearby containers (ore, fuel, mead bases, raw food) when your inventory has none."); _fillWithShift = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "ShiftFillsStations", true, "ON/OFF: hold Shift while pressing use on a smelter, furnace, kiln, windmill, spinning wheel, eitr refinery or oven to add as much as it can take at once (from your inventory, and from containers when FeedStations is on)."); _shared = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "SharedContainers", true, "ON/OFF: several players can have the same chest open at once and move items in it (no more 'in use'). Every player using the chest needs the mod with this on; a player without it still gets 'in use'. Carts and ships are not shared."); _cookingTimers = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "CookingTimers", true, "ON/OFF: countdown for each item on cooking stations, the iron cooking station and the stone oven (time until cooked, and until burnt). Options in '8 - Cooking Timers'."); _worldClock = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "WorldClock", true, "ON/OFF: in-game time and day at the top of the screen (options in 'A - World Clock')."); _farmGrid = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "FarmGrid", true, "ON/OFF: crops planted with the cultivator snap to an even grid lined up with the crops around them; hold Shift (free placement) to plant anywhere (options in 'B - Farm Grid')."); _shiftHarvest = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "ShiftHarvest", true, "ON/OFF: Shift + use on a ripe crop harvests the crops around it (on a berry or fruit bush: every fruit bush around it), nearest first, as many as your stamina allows (options in 'C - Shift Harvest')."); _objectHealth = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "ObjectHealth", true, "ON/OFF: health of the tree, log, rock or ore deposit under your crosshair, e.g. 'Fir 47/60' (options in 'D - Object Health')."); _areaRepair = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "AreaRepair", true, "ON/OFF: repairing a piece with the hammer also repairs every damaged piece around it (options in 'E - Area Repair')."); _portalItems = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "PortalItems", true, "ON/OFF: ores, metals, dragon eggs and other restricted items go through portals (for you), without the 'cannot teleport' warning and icon."); _tpMarkers = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "TeleportMarkers", true, "ON/OFF: personal teleport markers with /tp in chat: /tp create <name>, /tp <name>, /tp delete <name>, /tp list, /tp player <name> (options in 'F - Teleports')."); _findItems = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "FindItems", true, "ON/OFF: /find <item> in chat makes every container around you holding that item glow for a few seconds (options in 'G - Find')."); _creatureHealth = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "CreatureHealth", true, "ON/OFF: creature and boss health bars show their health as numbers next to the name, e.g. 'Greyling 12/20'."); _shipStatus = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "ShipStatus", true, "ON/OFF: while you are on a boat: speed, sail, heading, wind and position above the sailing HUD (options in 'H - Ship Status')."); _extraSlots = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "ExtraSlots", true, "ON/OFF: a panel beside the inventory with equipment, extra utility, quick, ammo, food and misc slots (options in 'I - Extra Slots'). Stays off while shudnal's ExtraSlots is installed; items in the slots are kept either way."); _recycle = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "Recycle", true, "ON/OFF: a Trash button beside the inventory recycles the item you drop on it (materials back) (options in 'L - Recycle'). Stays off while RecyclePlus is installed."); _eternalFires = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "EternalFires", true, "ON/OFF: torches, braziers, campfires and hearths you built never run out of fuel once lit (options in 'J - Eternal Fires'). Stays off while TorchesEternal is installed."); _growthTimers = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "GrowthTimers", true, "ON/OFF: looking at a healthy crop or sapling shows the time until it is grown, a picked berry bush, mushroom or flower the time until it grows back, e.g. 'Ready in 1h 23m', a wild animal being tamed its tameness and the time left, from 0% on, and a fermenter the time until the mead is ready (options in 'M - Growth Timers')."); _plantPickables = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "PlantPickables", true, "ON/OFF: plant raspberry, blueberry and cloudberry bushes, mushrooms (red, yellow, blue), thistle, dandelion, smoke puffs and fiddlehead with the cultivator, paid in what they grow (5 each, fiddlehead 15); planted ones grow back after picking and only planted ones can be removed again (cost back). Stays off while PlantEverything is installed."); _skipIntro = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "SkipIntroVideo", true, "ON/OFF: the Deep North intro video doesn't play when the game opens (it can still be watched from the main menu's cinematics). Applies the next time the game starts."); _saveAndPause = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "SaveAndPause", true, "ON/OFF: /saveall saves the world and every character and makes a snapshot of the world and your character; /loadall brings both back together; P (host) pauses the game for everyone, friends connected or not (options in 'O - Save & Pause')."); _craftSearch = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "CraftSearch", true, "ON/OFF: a search field above the recipe list of every crafting station (workbench, forge, cauldron, stone oven, preparation table, mead ketill, galdr table, black forge...): type part of a name to see only those recipes."); _showContents = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "ChestContentsOnHover", true, "ON/OFF: list what a chest, cart or ship storage holds when you look at it (options in '6 - Chest Contents')."); _itemInfo = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "ItemTooltipInfo", true, "ON/OFF: extra lines in item tooltips: type, tool tier, stack, amount in nearby containers (options in '7 - Item Tooltip')."); _showAvailable = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Features", "AvailableAmountText", true, "ON/OFF: show 'available/required' on crafting and building requirements when containers contribute."); MigrateOrphan(_stations, "2 - Containers", "UseForStations"); MigrateOrphan(_showAvailable, "4 - UI", "ShowAvailableAmount"); _enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Enabled", true, "Master switch for the whole mod (all features)."); _range = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "Range", 100f, new ConfigDescription("Maximum distance (meters) from the player to containers used for crafting/building.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>())); _toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("1 - General", "ToggleKey", KeyboardShortcut.Empty, "Optional hotkey to turn pulling from containers on/off in game."); _onlyPlayerBuilt = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Containers", "OnlyPlayerBuilt", true, "Ignore containers that were not built by a player (dungeon/treasure chests)."); _includeVehicles = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Containers", "IncludeShipsAndCarts", true, "Also use containers on ships and carts."); _respectWards = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Containers", "RespectWards", true, "Skip containers inside wards you don't have access to."); _skipInUse = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Containers", "SkipContainersInUse", true, "Skip containers currently opened by another player (recommended for multiplayer)."); _takeOwnership = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Containers", "TakeNetworkOwnership", true, "Multiplayer: ask the player whose game currently controls a chest to hand it over (the same request the game makes when you open it) before using it. Required to use chests near other players; when off, only chests your game already controls are used."); _refreshInterval = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Performance", "RefreshInterval", 0.5f, new ConfigDescription("Seconds between rescans of nearby containers while standing still. Item counts update instantly regardless.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>())); _debug = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Debug", "DebugLogging", false, "Verbose logging to BepInEx/LogOutput.log (and a 'Perf:' line every minute)."); _hoverMaxItems = ((BaseUnityPlugin)this).Config.Bind<int>("6 - Chest Contents", "MaxEntries", 8, new ConfigDescription("How many items the list shows; the rest is summarised by OverflowFormat. -1 shows everything.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-1, 100), Array.Empty<object>())); _hoverSortBy = ((BaseUnityPlugin)this).Config.Bind<ContentsSort>("6 - Chest Contents", "SortBy", ContentsSort.Amount, "Order of the list: Amount, Name, Weight (total) or Value (total)."); _hoverAscending = ((BaseUnityPlugin)this).Config.Bind<bool>("6 - Chest Contents", "SortAscending", false, "Reverse the order (smallest first / Z to A)."); _hoverEntry = ((BaseUnityPlugin)this).Config.Bind<string>("6 - Chest Contents", "EntryFormat", "<color=#FFFFAAFF>{0}</color> <color=#AAFFAAFF>{1}</color>", "One line per item. {0} = total amount, {1} = item name. Rich text colours allowed."); _hoverOverflow = ((BaseUnityPlugin)this).Config.Bind<string>("6 - Chest Contents", "OverflowFormat", "<color=#AAAAAAFF>+{0} more</color>", "Shown when there are more items than MaxEntries. {0} = how many are not listed. Empty = nothing."); _hoverCapacity = ((BaseUnityPlugin)this).Config.Bind<string>("6 - Chest Contents", "CapacityFormat", "<color=#AAAAAAFF>{0}/{1} slots</color>", "{0} = slots in use, {1} = total slots. Empty = nothing."); _itemType = ((BaseUnityPlugin)this).Config.Bind<bool>("7 - Item Tooltip", "ShowItemType", true, "Item type (Material, Tool, One Handed Weapon...)."); _itemTier = ((BaseUnityPlugin)this).Config.Bind<bool>("7 - Item Tooltip", "ShowToolTier", true, "Tool tier of tools and weapons (what they can mine / chop)."); _itemStack = ((BaseUnityPlugin)this).Config.Bind<bool>("7 - Item Tooltip", "ShowStackSize", true, "Stack size and maximum stack (e.g. 34/50)."); _itemNearby = ((BaseUnityPlugin)this).Config.Bind<bool>("7 - Item Tooltip", "ShowNearbyCount", true, "How many of this item the nearby containers hold (within Range, respecting the rules file)."); _itemPrefab = ((BaseUnityPlugin)this).Config.Bind<bool>("7 - Item Tooltip", "ShowPrefabName", false, "The item's internal (prefab) name, the one to write in the rules file."); _cookingBurnTime = ((BaseUnityPlugin)this).Config.Bind<bool>("8 - Cooking Timers", "ShowBurnTime", true, "When an item is cooked, also show how long until it burns."); _cookReadyIn = ((BaseUnityPlugin)this).Config.Bind<string>("8 - Cooking Timers", "ReadyInFormat", "<color=#FFFFAAFF>{0}</color> ready in <color=#AAFFAAFF>{1}</color>", "Item still cooking. {0} = item it becomes, {1} = time left (m:ss)."); _cookDone = ((BaseUnityPlugin)this).Config.Bind<string>("8 - Cooking Timers", "DoneFormat", "<color=#FFFFAAFF>{0}</color> <color=#AAFFAAFF>ready</color>", "Item cooked (used when ShowBurnTime is off or the station never burns food). {0} = item."); _cookBurns = ((BaseUnityPlugin)this).Config.Bind<string>("8 - Cooking Timers", "BurnsFormat", "<color=#FFFFAAFF>{0}</color> <color=#AAFFAAFF>ready</color>, burns in <color=#FF9988FF>{1}</color>", "Item cooked and waiting. {0} = item, {1} = time until it burns (m:ss)."); _cookBurnt = ((BaseUnityPlugin)this).Config.Bind<string>("8 - Cooking Timers", "BurntFormat", "<color=#FF9988FF>{0}</color> (burnt)", "Item burnt. {0} = what it turned into."); _cookPaused = ((BaseUnityPlugin)this).Config.Bind<string>("8 - Cooking Timers", "PausedText", "<color=#AAAAAAFF>(no heat)</color>", "Added to a line whose timer has stopped (fire out, no fuel). Empty = nothing."); _clockKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("A - World Clock", "ToggleKey", new KeyboardShortcut((KeyCode)278, Array.Empty<KeyCode>()), "Key that shows / hides the clock while playing."); _clockFormat = ((BaseUnityPlugin)this).Config.Bind<string>("A - World Clock", "TimeFormat", "HH:mm", "HH:mm = 24 h (14:05), hh:mm tt = 12 h (02:05 PM), or 'fuzzy' for the period name (Late morning...)."); _clockTemplate = ((BaseUnityPlugin)this).Config.Bind<string>("A - World Clock", "Text", "<size={3}>Day {2}</size>\n<b>{0}</b>", "What is shown. {0} = time, {1} = period name, {2} = day number, {3} = a smaller font size (3/4 of FontSize, for <size={3}>). \\n = new line. Rich text (<b>, <color=#FFD700>...) allowed."); _clockPosition = ((BaseUnityPlugin)this).Config.Bind<string>("A - World Clock", "Position", "50%,2%", "Top-centre of the text: x,y in pixels or x%,y% of the screen."); _clockFontSize = ((BaseUnityPlugin)this).Config.Bind<int>("A - World Clock", "FontSize", 24, new ConfigDescription("Text size.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(8, 96), Array.Empty<object>())); _clockColor = ((BaseUnityPlugin)this).Config.Bind<string>("A - World Clock", "Color", "FFFFFFFF", "Text colour, RRGGBBAA."); _clockShadow = ((BaseUnityPlugin)this).Config.Bind<bool>("A - World Clock", "Shadow", true, "Dark shadow behind the text, readable on snow and sky."); _clockPeriods = ((BaseUnityPlugin)this).Config.Bind<string>("A - World Clock", "PeriodNames", string.Join(",", WorldClock.DefaultFuzzyNames), "Names for the periods of the day ({1} and TimeFormat = fuzzy), comma-separated, spread evenly from midnight."); _gridSections = ((BaseUnityPlugin)this).Config.Bind<int>("B - Farm Grid", "GridLines", 2, new ConfigDescription("How many grid cells to draw around the crop you are placing (0 = snap without drawing).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>())); _gridExtra = ((BaseUnityPlugin)this).Config.Bind<float>("B - Farm Grid", "ExtraSpacing", 0.01f, new ConfigDescription("Metres added between crops, on top of the space they need to grow.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); _gridColor = ((BaseUnityPlugin)this).Config.Bind<string>("B - Farm Grid", "LineColor", "FFFFFF40", "Grid line colour, RRGGBBAA (the last two digits are the transparency)."); _harvestRadius = ((BaseUnityPlugin)this).Config.Bind<float>("C - Shift Harvest", "Radius", 15f, new ConfigDescription("Metres around the crop you press on.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>())); _harvestStamina = ((BaseUnityPlugin)this).Config.Bind<float>("C - Shift Harvest", "StaminaPerCrop", 4f, new ConfigDescription("Stamina used per crop; the harvest stops when you run out. 0 = free.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); _harvestMax = ((BaseUnityPlugin)this).Config.Bind<int>("C - Shift Harvest", "MaxCrops", 100, new ConfigDescription("Most crops one press can harvest.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 500), Array.Empty<object>())); _harvestBushes = ((BaseUnityPlugin)this).Config.Bind<bool>("C - Shift Harvest", "BerryBushes", true, "Shift + use on a berry or fruit bush (raspberries, blueberries, cloudberries...) picks every fruit bush around it, of any kind (mushrooms and other plants are left alone)."); _healthTrees = ((BaseUnityPlugin)this).Config.Bind<bool>("D - Object Health", "Trees", true, "Trees, logs and stumps."); _healthRocks = ((BaseUnityPlugin)this).Config.Bind<bool>("D - Object Health", "RocksAndDeposits", true, "Big rocks and ore deposits (copper, tin, silver...): the total of every piece still standing."); _healthOther = ((BaseUnityPlugin)this).Config.Bind<bool>("D - Object Health", "OtherObjects", true, "Other things you break with tools: small rocks, bushes, stones..."); _healthColours = ((BaseUnityPlugin)this).Config.Bind<bool>("D - Object Health", "Colours", true, "Current health in green, amber or red by how much is left."); _healthPieces = ((BaseUnityPlugin)this).Config.Bind<bool>("D - Object Health", "DamagedPieces", true, "Walls, floors, doors and other building pieces once they are damaged (intact ones show nothing)."); _repairRadius = ((BaseUnityPlugin)this).Config.Bind<float>("E - Area Repair", "Radius", 30f, new ConfigDescription("Metres around the piece you repair; every damaged piece within it that its station allows is fixed in one press.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>())); _repairPerPiece = ((BaseUnityPlugin)this).Config.Bind<bool>("E - Area Repair", "ChargePerPiece", false, "Hammer durability per area repair: false = one repair's worth per press, true = one per piece. Stamina is always charged per piece and the repair stops when you run out."); _tpCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("F - Teleports", "CooldownSeconds", 3f, new ConfigDescription("Seconds between two /tp teleports.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), Array.Empty<object>())); _tpMax = ((BaseUnityPlugin)this).Config.Bind<int>("F - Teleports", "MaxMarkersPerWorld", 50, new ConfigDescription("Most markers per character in one world.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 500), Array.Empty<object>())); _tpPlayers = ((BaseUnityPlugin)this).Config.Bind<bool>("F - Teleports", "ToPlayers", true, "/tp player <name> teleports next to another player: anyone nearby or sharing their position on the map, and anyone else with NewtCraftHub who accepts it (OthersCanTeleportToMe)."); _tpToMe = ((BaseUnityPlugin)this).Config.Bind<bool>("F - Teleports", "OthersCanTeleportToMe", true, "Other players with NewtCraftHub can /tp player to you even when you don't share your position on the map. Off: only while you share it or stand near them."); _tpMultiplayer = ((BaseUnityPlugin)this).Config.Bind<bool>("F - Teleports", "AllowInMultiplayer", true, "Allow /tp while other players are connected."); _tpPortalRules = ((BaseUnityPlugin)this).Config.Bind<bool>("F - Teleports", "FollowPortalRules", true, "When PortalItems is off, /tp refuses like a portal while you carry ores and other restricted items."); _findRange = ((BaseUnityPlugin)this).Config.Bind<float>("G - Find", "Range", 100f, new ConfigDescription("Metres around you that /find searches.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 300f), Array.Empty<object>())); _findSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("G - Find", "GlowSeconds", 5f, new ConfigDescription("How long the containers glow.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>())); _findColor = ((BaseUnityPlugin)this).Config.Bind<string>("G - Find", "GlowColor", "FF2A1AFF", "Glow colour, RRGGBBAA (bright red by default, apart from SargamAutoStore's green and blue)."); _shipPosition = ((BaseUnityPlugin)this).Config.Bind<string>("H - Ship Status", "Position", "50%,74%", "Top-centre of the readout: x,y in pixels or x%,y% of the screen."); _shipFont = ((BaseUnityPlugin)this).Config.Bind<int>("H - Ship Status", "FontSize", 18, new ConfigDescription("Text size.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(8, 64), Array.Empty<object>())); _shipWind = ((BaseUnityPlugin)this).Config.Bind<bool>("H - Ship Status", "ShowWind", true, "Wind efficiency for the sail (the game's own formula) on the second line."); _shipPos = ((BaseUnityPlugin)this).Config.Bind<bool>("H - Ship Status", "ShowPosition", true, "Your X / Z coordinates on the second line."); _slotsQuick = ((BaseUnityPlugin)this).Config.Bind<int>("I - Extra Slots", "QuickSlots", 3, new ConfigDescription("Quick slots for potions and meads.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 3), Array.Empty<object>())); _slotsUtility = ((BaseUnityPlugin)this).Config.Bind<int>("I - Extra Slots", "ExtraUtilitySlots", 3, new ConfigDescription("Extra utility slots beside the equipment (belts, wishbone, charms...); their effects work like the one you wear.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 3), Array.Empty<object>())); _slotsAmmo = ((BaseUnityPlugin)this).Config.Bind<bool>("I - Extra Slots", "AmmoSlots", true, "3 slots for arrows and bolts."); _slotsFood = ((BaseUnityPlugin)this).Config.Bind<bool>("I - Extra Slots", "FoodSlots", true, "3 slots for food."); _slotsMisc = ((BaseUnityPlugin)this).Config.Bind<bool>("I - Extra Slots", "MiscSlots", true, "2 slots for keys."); _slotsHotbars = ((BaseUnityPlugin)this).Config.Bind<bool>("I - Extra Slots", "Hotbars", true, "A potion bar right of the Forsaken power with your quick slots, empty ones included (Alt + Z / X / C)."); _graveTakeAll = ((BaseUnityPlugin)this).Config.Bind<bool>("I - Extra Slots", "GraveTakeAll", true, "Your own grave comes back in one go whenever it fits: potions, ammo, food and spare utility items go back to their slots and take no inventory cell; worn gear comes back into the inventory, not put on. The Take all window only opens when it really doesn't fit (then nothing is put on). Off: the game's own check."); KeyCode[] array = new KeyCode[3]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); KeyCode[] array2 = (KeyCode[])(object)array; for (int i = 0; i < 3; i++) { _slotKeys[i] = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("I - Extra Slots", $"Quick{i + 1}Key", new KeyboardShortcut(array2[i], (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), $"Drinks the potion in quick slot {i + 1}."); } for (int j = 0; j < 3; j++) { _slotKeys[8 + j] = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("I - Extra Slots", $"Ammo{j + 1}Key", new KeyboardShortcut((KeyCode)(49 + j), (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), $"Equips the ammo in ammo slot {j + 1}."); } KeyCode[] array3 = new KeyCode[3]; RuntimeHelpers.InitializeArray(array3, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); KeyCode[] array4 = (KeyCode[])(object)array3; for (int k = 0; k < 3; k++) { _slotKeys[11 + k] = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("I - Extra Slots", $"Food{k + 1}Key", new KeyboardShortcut(array4[k], (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), $"Eats the food in food slot {k + 1}."); } _pauseKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("O - Save & Pause", "PauseKey", new KeyboardShortcut((KeyCode)112, Array.Empty<KeyCode>()), "Pauses the game for everyone (also /pause): alone at once, with others by vote (everyone types 1 = pause or 2 = keep playing in chat; more than half must say 1). Paused: asks to resume. Players with NewtCraftHub pause too; others are told."); _pauseVoteSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("O - Save & Pause", "VoteSeconds", 30f, new ConfigDescription("How long a pause vote stays open. It ends early once everyone voted or the outcome is sure.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 120f), Array.Empty<object>())); _pauseResumeSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("O - Save & Pause", "ResumeSeconds", 3f, new ConfigDescription("Countdown shown to everyone before /resume ends the pause.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); _snapshotsToKeep = ((BaseUnityPlugin)this).Config.Bind<int>("O - Save & Pause", "SnapshotsToKeep", 10, new ConfigDescription("Snapshots /saveall keeps per world and character; older ones are deleted (they are the game's own backups, also listed in Manage saves).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), Array.Empty<object>())); _plantRegrow = ((BaseUnityPlugin)this).Config.Bind<float>("N - Plant Pickables", "RegrowMinutes", 0f, new ConfigDescription("0 (default) = the game's own time: a bush, mushroom or flower you planted grows back like a wild one (4-5 hours). 1 or more = that many minutes instead.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), Array.Empty<object>())); _growReady = ((BaseUnityPlugin)this).Config.Bind<string>("M - Growth Timers", "ReadyInFormat", "Ready in <color=#AAFFAAFF>{0}</color>", "Line under a healthy crop or sapling, and under a fermenter at work. {0} = time left (1h 23m, or 12m 05s counting down to 0m 00s). Rich text colours allowed."); _growBack = ((BaseUnityPlugin)this).Config.Bind<string>("M - Growth Timers", "GrowsBackFormat", "Grows back in <color=#AAFFAAFF>{0}</color>", "Line under a picked berry bush, mushroom or flower. {0} = time left. Rich text colours allowed."); _taming = ((BaseUnityPlugin)this).Config.Bind<string>("M - Growth Timers", "TamingFormat", "Tameness <color=#AAFFAAFF>{0}%</color>, tame in <color=#AAFFAAFF>{1}</color>", "Line under a wild animal being tamed (boar, wolf, lox...), shown from 0% on. {0} = tameness in percent, {1} = time left while it is fed and calm. Rich text colours allowed."); _recyclePercent = ((BaseUnityPlugin)this).Config.Bind<float>("L - Recycle", "ReturnPercent", 100f, new ConfigDescription("How much of an item's materials come back, every upgrade level included (0-100).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); _recycleNoRecipe = ((BaseUnityPlugin)this).Config.Bind<ModSettings.NoRecipe>("L - Recycle", "ItemsWithoutRecipe", ModSettings.NoRecipe.Ask, "Items that give nothing back (no recipe, or fewer than one craft, e.g. 15 arrows): Ask = delete after a confirmation, Delete = delete at once, Never = keep them."); _recycleFull = ((BaseUnityPlugin)this).Config.Bind<WhenFull>("L - Recycle", "WhenInventoryFull", WhenFull.NearestChest, "Materials that don't fit in your inventory: into the nearest chest with room (else at your feet), or dropped at your feet."); _recycleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("L - Recycle", "Hotkey", (KeyCode)127, "Recycles the item you are dragging (None = only the Trash button)."); _recycleButton = ((BaseUnityPlugin)this).Config.Bind<bool>("L - Recycle", "ShowTrashButton", true, "The Trash button beside the inventory."); _recycleLabel = ((BaseUnityPlugin)this).Config.Bind<string>("L - Recycle", "TrashLabel", "Trash", "The button's label."); _recycleColor = ((BaseUnityPlugin)this).Config.Bind<string>("L - Recycle", "TrashLabelColor", "FFD800FF", "The label colour, RRGGBBAA."); _barsOnlyFocused = ((BaseUnityPlugin)this).Config.Bind<bool>("K - Creature Health", "OnlyWhileFocused", true, "A creature's health bar shows only while your crosshair is on it and hides as soon as you look away (bosses, players and your mount keep theirs). Off = the game's own delay."); _barFade = ((BaseUnityPlugin)this).Config.Bind<float>("K - Creature Health", "FadeOutSeconds", 0.5f, new ConfigDescription("How long a health bar takes to fade out after you look away (0 = at once).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>())); _eternalTorches = ((BaseUnityPlugin)this).Config.Bind<bool>("J - Eternal Fires", "Torches", true, "Standing torches, wall sconces and braziers never run out."); _eternalCampfires = ((BaseUnityPlugin)this).Config.Bind<bool>("J - Eternal Fires", "CampfiresAndHearths", true, "Campfires, hearths, bonfires, the hot tub and every other fire you build never run out."); UpgradeOldDefaults(); ApplyConfig(); ((BaseUnityPlugin)this).Config.SettingChanged += delegate { ApplyConfig(); }; } private void UpgradeOldDefaults() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown ConfigEntry<int> val = ((BaseUnityPlugin)this).Config.Bind<int>("9 - Internal", "ConfigVersion", 0, new ConfigDescription("Used by the mod to update old default values once. Don't change it.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Browsable = false } })); if (val.Value >= 4) { return; } if (val.Value < 1 && Math.Abs(_range.Value - 20f) < 0.01f) { _range.Value = 100f; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Range was still the old default (20 m); updated to the new default, 100 m."); } if (val.Value < 2) { if (_clockTemplate.Value == "Day {2} <b>{0}</b>") { _clockTemplate.Value = "<size={3}>Day {2}</size>\n<b>{0}</b>"; } if (_clockFontSize.Value == 22) { _clockFontSize.Value = 24; } } if (val.Value < 3 && string.Equals(_findColor.Value, "FFC04DFF", StringComparison.OrdinalIgnoreCase)) { _findColor.Value = "FF2A1AFF"; } if (val.Value < 4 && Math.Abs(_plantRegrow.Value - 30f) < 0.01f) { _plantRegrow.Value = 0f; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Plant pickables: RegrowMinutes was the old default (30 min); planted bushes, mushrooms and flowers now grow back in the game's own time."); } val.Value = 4; ((BaseUnityPlugin)this).Config.Save(); } private void MigrateOrphan(ConfigEntry<bool> entry, string oldSection, string oldKey) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown try { Dictionary<ConfigDefinition, string> dictionary = typeof(ConfigFile).GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(((BaseUnityPlugin)this).Config, null) as Dictionary<ConfigDefinition, string>; ConfigDefinition key = new ConfigDefinition(oldSection, oldKey); if (dictionary != null && dictionary.TryGetValue(key, out var value)) { if (bool.TryParse(value, out var result)) { entry.Value = result; } dictionary.Remove(key); ((BaseUnityPlugin)this).Config.Save(); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogDebug((object)("Config migration of " + oldSection + "/" + oldKey + ": " + ex.Message)); } } private void ApplyConfig() { //IL_0468: Unknown result type (might be due to invalid IL or missing references) //IL_046d: Unknown result type (might be due to invalid IL or missing references) //IL_0575: Unknown result type (might be due to invalid IL or missing references) //IL_057a: Unknown result type (might be due to invalid IL or missing references) //IL_054b: Unknown result type (might be due to invalid IL or missing references) //IL_0544: Unknown result type (might be due to invalid IL or missing references) //IL_0550: Unknown result type (might be due to invalid IL or missing references) ModSettings settings = Runtime.Settings; settings.Enabled = _enabled.Value; settings.CraftFromContainers = _craft.Value; settings.Range = _range.Value; settings.OnlyPlayerBuilt = _onlyPlayerBuilt.Value; settings.IncludeVehicles = _includeVehicles.Value; settings.RespectWards = _respectWards.Value; settings.SkipContainersInUse = _skipInUse.Value; settings.TakeOwnership = _takeOwnership.Value; settings.UseForStations = _stations.Value; settings.FillStationsWithShift = _fillWithShift.Value; settings.SharedContainers = _shared.Value; settings.ShowCookingTimers = _cookingTimers.Value; settings.CookingShowBurnTime = _cookingBurnTime.Value; settings.CookingReadyInFormat = _cookReadyIn.Value; settings.CookingDoneFormat = _cookDone.Value; settings.CookingBurnsFormat = _cookBurns.Value; settings.CookingBurntFormat = _cookBurnt.Value; settings.CookingPausedText = _cookPaused.Value; settings.ShowWorldClock = _worldClock.Value; settings.ClockTimeFormat = _clockFormat.Value; settings.ClockTemplate = _clockTemplate.Value; settings.ClockPosition = _clockPosition.Value; settings.ClockFontSize = _clockFontSize.Value; settings.ClockColor = _clockColor.Value; settings.ClockShadow = _clockShadow.Value; settings.ClockPeriodNames = (string.IsNullOrWhiteSpace(_clockPeriods.Value) ? null : _clockPeriods.Value.Split(new char[1] { ',' })); settings.FarmGrid = _farmGrid.Value; settings.FarmGridSections = _gridSections.Value; settings.FarmGridExtraSpacing = _gridExtra.Value; settings.FarmGridColor = _gridColor.Value; settings.ShiftHarvest = _shiftHarvest.Value; settings.ShowObjectHealth = _objectHealth.Value; settings.ObjectHealthTrees = _healthTrees.Value; settings.ObjectHealthRocks = _healthRocks.Value; settings.ObjectHealthOther = _healthOther.Value; settings.ObjectHealthColours = _healthColours.Value; settings.ObjectHealthPieces = _healthPieces.Value; settings.CreatureHealth = _creatureHealth.Value; settings.ShowShipStatus = _shipStatus.Value; settings.ExtraSlots = _extraSlots.Value; settings.EternalFires = _eternalFires.Value; settings.PlantPickables = _plantPickables.Value; settings.PlantRegrowMinutes = _plantRegrow.Value; settings.GrowthTimers = _growthTimers.Value; settings.GrowthReadyFormat = SafeFormat(_growReady.Value, "Ready in <color=#AAFFAAFF>{0}</color>"); settings.GrowthBackFormat = SafeFormat(_growBack.Value, "Grows back in <color=#AAFFAAFF>{0}</color>"); settings.TamingFormat = SafeFormat(_taming.Value, "Tameness <color=#AAFFAAFF>{0}%</color>, tame in <color=#AAFFAAFF>{1}</color>"); settings.SkipIntroVideo = _skipIntro.Value; settings.SaveAndPause = _saveAndPause.Value; settings.CraftSearch = _craftSearch.Value; settings.SnapshotsToKeep = _snapshotsToKeep.Value; settings.PauseVoteSeconds = _pauseVoteSeconds.Value; settings.PauseResumeSeconds = _pauseResumeSeconds.Value; settings.CreatureBarsOnlyFocused = _barsOnlyFocused.Value; settings.Recycle = _recycle.Value; settings.RecycleButton = _recycleButton.Value; settings.RecyclePercent = _recyclePercent.Value; settings.RecycleWithoutRecipe = _recycleNoRecipe.Value; settings.RecycleOverflowToChest = _recycleFull.Value == WhenFull.NearestChest; settings.RecycleLabel = _recycleLabel.Value; settings.RecycleLabelColor = _recycleColor.Value ?? "FFD800FF"; Recycle.Key = _recycleKey.Value; try { PlantPickablesHook.Sync(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogDebug((object)("Plant pickables: " + ex.Message)); } settings.CreatureBarFadeSeconds = _barFade.Value; settings.EternalTorches = _eternalTorches.Value; settings.EternalCampfires = _eternalCampfires.Value; settings.Slots = new SlotLayout.Options(_slotsQuick.Value, _slotsUtility.Value, _slotsAmmo.Value, _slotsFood.Value, _slotsMisc.Value); settings.SlotHotbars = _slotsHotbars.Value; settings.GraveTakeAll = _graveTakeAll.Value; for (int i = 0; i < _slotKeys.Length; i++) { SlotBars.Keys[i] = _slotKeys[i]?.Value ?? KeyboardShortcut.Empty; } SlotBars.KeysChanged(((Component)this).GetComponent<SlotBars>()); SaveAndPause.PauseKey = _pauseKey.Value; settings.ShipPosition = _shipPosition.Value; settings.ShipFontSize = _shipFont.Value; settings.ShipShowWind = _shipWind.Value; settings.ShipShowPosition = _shipPos.Value; settings.AreaRepair = _areaRepair.Value; settings.AreaRepairRadius = _repairRadius.Value; settings.AreaRepairChargePerPiece = _repairPerPiece.Value; settings.PortalItems = _portalItems.Value; settings.TeleportMarkers = _tpMarkers.Value; settings.TeleportCooldown = _tpCooldown.Value; settings.MaxMarkersPerWorld = _tpMax.Value; settings.TeleportToPlayers = _tpPlayers.Value; settings.OthersCanTeleportToMe = _tpToMe.Value; settings.TeleportInMultiplayer = _tpMultiplayer.Value; settings.MarkersFollowPortalRules = _tpPortalRules.Value; settings.HarvestRadius = _harvestRadius.Value; settings.HarvestStaminaPerCrop = _harvestStamina.Value; settings.HarvestMaxCrops = _harvestMax.Value; settings.HarvestBushes = _harvestBushes.Value; settings.FindItems = _findItems.Value; settings.FindRange = _findRange.Value; settings.FindGlowSeconds = _findSeconds.Value; settings.FindGlowColor = _findColor.Value; settings.RefreshInterval = _refreshInterval.Value; settings.ShowAvailableInUi = _showAvailable.Value; settings.ShowContentsOnHover = _showContents.Value; settings.HoverMaxItems = _hoverMaxItems.Value; settings.HoverSortBy = _hoverSortBy.Value; settings.HoverSortAscending = _hoverAscending.Value; settings.HoverEntryFormat = _hoverEntry.Value; settings.HoverOverflowFormat = _hoverOverflow.Value; settings.HoverCapacityFormat = _hoverCapacity.Value; settings.ShowItemInfo = _itemInfo.Value; settings.ShowItemType = _itemType.Value; settings.ShowToolTier = _itemTier.Value; settings.ShowStackSize = _itemStack.Value; settings.ShowNearbyCount = _itemNearby.Value; settings.ShowPrefabName = _itemPrefab.Value; settings.DebugLogging = _debug.Value; Perf.Enabled = settings.DebugLogging; settings.Revision++; Runtime.Index.Invalidate(); } private void SetUpCompatibility() { Runtime.OtherModShowsChestContents = () => OtherPluginOptionIsOn("Azumatt.AzuHoverStats", "4 - Show Chest Contents", "Show Chest Contents"); Runtime.OtherModShowsItemTypeAndTier = () => OtherPluginOptionIsOn("Azumatt.AzuHoverStats", "1 - General", "Show Tooltip Information"); Runtime.OtherModShowsClock = Throttled(() => (OtherPluginOptionIsOn("aedenthorn.ClockMod", "General", "Enabled") && OtherPluginOptionIsOn("aedenthorn.ClockMod", "General", "ShowClock")) || OtherPluginOptionIsOn("Azumatt.AzuClock", "1 - General", "Show Clock"), "world clock", "another clock mod shows the time"); Runtime.OtherModOwnsTeleportCommand = () => IsPluginLoaded("com.andersondavid.valheim.unrestrictedmineralportals"); Runtime.OtherModRecycles = Throttled(() => IsPluginLoaded("TastyChickenLegs.RecyclePlus"), "recycling", "RecyclePlus has its own Trash button"); bool? plantMod = null; Runtime.OtherModPlantsPickables = delegate { if (!plantMod.HasValue) { plantMod = IsPluginLoaded("advize.PlantEverything"); if (plantMod.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"NewtCraftHub plant pickables stay off: PlantEverything is installed and adds the same cultivator recipes."); } } return plantMod.Value; }; Runtime.OtherModKeepsFiresLit = Throttled(() => IsPluginLoaded("Xenofell.TorchesEternal"), "eternal fires", "TorchesEternal keeps fires lit"); bool? extraSlotsMod = null; Runtime.OtherModOwnsSlots = delegate { if (!extraSlotsMod.HasValue) { extraSlotsMod = IsPluginLoaded("shudnal.ExtraSlots"); if (extraSlotsMod.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"NewtCraftHub extra slots stay off: shudnal's ExtraSlots is installed (remove it to use ours; the items stay where they are)."); } } return extraSlotsMod.Value; }; Runtime.OtherModRepairsArea = Throttled(() => OtherPluginOptionIsOn("Azumatt.AzuAreaRepair", "1 - General", "Area Repair"), "area repair", "AzuAreaRepair repairs areas"); Runtime.OtherModGridsCrops = Throttled(() => IsPluginLoaded("com.orianaventure.mod.VentureFarmGrid") || IsPluginLoaded("Moopfam.FarmGridRemake"), "farm grid", "another farm grid mod is installed"); } private static string SafeFormat(string value, string fallback) { if (string.IsNullOrWhiteSpace(value)) { return fallback; } try { string.Format(value, "1h 00m"); return value; } catch (FormatException) { return fallback; } } private static bool IsPluginLoaded(string guid) { if (Chainloader.PluginInfos.TryGetValue(guid, out var value)) { return (Object)(object)value.Instance != (Object)null; } return false; } private Func<bool> Throttled(Func<bool> check, string feature, string reason) { bool value = false; bool logged = false; float next = float.MinValue; return delegate { if (Time.time < next) { return value; } next = Time.time + 5f; try { value = check(); } catch (Exception) { value = false; } if (value && !logged) { logged = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)("NewtCraftHub " + feature + " stays off: " + reason + " (turn one of them off to use the other).")); } return value; }; } private static bool OtherPluginOptionIsOn(string guid, string section, string key) { try { if (!Chainloader.PluginInfos.TryGetValue(guid, out var value) || (Object)(object)value.Instance == (Object)null) { return false; } foreach (ConfigDefinition key2 in value.Instance.Config.Keys) { if (key2.Section == section && key2.Key == key) { return string.Equals(value.Instance.Config[key2].BoxedValue?.ToString(), "On", StringComparison.OrdinalIgnoreCase) || object.Equals(value.Instance.Config[key2].BoxedValue, true); } } } catch (Exception) { } return false; } private void LoadRules() { try { if (!File.Exists(RulesPath)) { string text = null; string[] legacyRulesFileNames = LegacyRulesFileNames; foreach (string text2 in legacyRulesFileNames) { string text3 = Path.Combine(Paths.ConfigPath, text2); if (File.Exists(text3)) { File.Copy(text3, RulesPath); text = text2; break; } } if (text != null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Imported your existing rules from " + text + ".")); } else { File.WriteAllText(RulesPath, "# NewtCraftHub rules: per-container restrictions for pulling items.\n# Changes are picked up live while the game is running.\n#\n# groups: reusable lists of ITEM PREFAB names (case sensitive).\n# <container prefab>:\n# exclude: items or groups that must NOT be pulled from this container type\n# includeOverride: items or groups that are always allowed (wins over exclude)\n#\n# Predefined groups: All, Food, Potion, Fish, Swords, Bows, Crossbows, Axes, Clubs, Knives,\n# Pickaxes, Polearms, Spears, Equipment, Trophy, Boss Trophy, Crops, Seeds, Ores, Metals, Woods.\n#\n# Example:\n# groups:\n# Valuables:\n# - Coins\n# - Ruby\n# piece_chest_private:\n# exclude:\n# - All\n# piece_chest_wood:\n# exclude:\n# - Valuables\n# includeOverride:\n# - Coins\n"); } } PullRules pullRules = PullRules.FromYaml(File.ReadAllText(RulesPath)); foreach (string warning in pullRules.Warnings) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("newton.NewtCraftHub.yml: " + warning)); } Runtime.SetRules(pullRules); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Rules loaded: {pullRules.ContainerRuleCount} container rule(s), {pullRules.GroupCount} custom group(s)."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Could not read newton.NewtCraftHub.yml, keeping previous rules: " + ex.Message)); } } private void WatchRules() { try { _watcher = new FileSystemWatcher(Paths.ConfigPath, "newton.NewtCraftHub.yml") { NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite) }; FileSystemEventHandler value = delegate { _rulesDirty = true; }; _watcher.Changed += value; _watcher.Created += value; _watcher.Renamed += delegate { _rulesDirty = true; }; _watcher.EnableRaisingEvents = true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Live reload of newton.NewtCraftHub.yml unavailable: " + ex.Message)); } } private void WatchConfig() { try { _configWatcher = new FileSystemWatcher(Path.GetDirectoryName(((BaseUnityPlugin)this).Config.ConfigFilePath), Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath)) { NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite) }; FileSystemEventHandler value = delegate { _configDirty = true; }; _configWatcher.Changed += value; _configWatcher.Created += value; _configWatcher.Renamed += delegate { _configDirty = true; }; _configWatcher.EnableRaisingEvents = true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Live reload of " + Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath) + " unavailable: " + ex.Message)); } } private void ReloadConfigIfChanged() { if (_configDirty) { _configDirty = false; _configReloadAt = Time.time + 0.5f; } if (_configReloadAt < 0f || Time.time < _configReloadAt) { return; } _configReloadAt = -1f; try { float range = Runtime.Settings.Range; ((BaseUnityPlugin)this).Config.Reload(); ApplyConfig(); if (Math.Abs(range - Runtime.Settings.Range) > 0.001f) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Settings reloaded: Range = {Runtime.Settings.Range} m."); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not reload " + Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath) + ": " + ex.Message)); } } private void Update() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) if (_rulesDirty) { _rulesDirty = false; LoadRules(); } ReloadConfigIfChanged(); Runtime.Tick(); FarmGrid.Tick(); TeleportCommands.Tick(); PlantPickablesHook.Tick(); FindCommand.Tick(); KeyboardShortcut value = _clockKey.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey != 0) { value = _clockKey.Value; if (((KeyboardShortcut)(ref value)).IsDown() && (Object)(object)Player.m_localPlayer != (Object)null) { ClockHud.ToggledOff = !ClockHud.ToggledOff; } } string text = Perf.EndFrame(Time.time); if (text != null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)text); } value = _toggleKey.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey == 0) { return; } value = _toggleKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { Runtime.ToggledOff = !Runtime.ToggledOff; Runtime.Index.Invalidate(); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)2, Runtime.ToggledOff ? "Crafting from containers: OFF" : "Crafting from containers: ON", 0, (Sprite)null, false); } } } private void OnDestroy() { _watcher?.Dispose(); _configWatcher?.Dispose(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } Scope.Reset(); } } internal static class BuildInfo { public const string Version = "1.9.1"; } } namespace NewtCraftHub.Patches { public static class PatchInstaller { public static readonly Type[] PatchTypes = new Type[75] { typeof(ContainerAwakePatch), typeof(AugmentScopePatch), typeof(SuppressScopePatch), typeof(CountItemsPatch), typeof(HaveItemPatch), typeof(ConsumeScopePatch), typeof(RemoveItemPatch), typeof(FreshnessPatch), typeof(RequirementTextPatch), typeof(BuildRevalidatePatch), typeof(OwnershipResponsePatch), typeof(StationFeedPatch), typeof(StationHoverPatch), typeof(ContainerHoverPatch), typeof(ItemTooltipPatch), typeof(StationFillPatch), typeof(SharedOpenPatch), typeof(SharedViewPatch), typeof(SharedLoadPatch), typeof(SharedEditPatch), typeof(CookingTimerPatch), typeof(FarmGridPatch), typeof(FarmGridPlantAllPatch), typeof(ShiftHarvestPatch), typeof(ObjectHealthPatch), typeof(AreaRepairPatch), typeof(PortalItemsPatch), typeof(TeleportCommandsPatch), typeof(TeleportRpcPatch), typeof(CreatureHealthPatch), typeof(EternalFiresPatch), typeof(EternalTubsPatch), typeof(SaveCommandsPatch), typeof(HoldPausePatch), typeof(PauseVoteChatPatch), typeof(RestoreOnMenuPatch), typeof(CraftSearchTemplatePatch), typeof(CraftSearchPanelPatch), typeof(CraftSearchFilterPatch), typeof(CraftSearchClosePatch), typeof(CraftSearchTickPatch), typeof(CraftSearchKeysPatch), typeof(PlantPickablesSyncPatch), typeof(PlantPickablesAwakePatch), typeof(PlantPickablesPickedPatch), typeof(PlantPickablesCreatorPatch), typeof(PlantPickablesRemovePatch), typeof(GrowthTimersPlantPatch), typeof(GrowthTimersPickablePatch), typeof(GrowthTimersTameablePatch), typeof(GrowthTimersFermenterPatch), typeof(RecycleShowPatch), typeof(RecycleDragPatch), typeof(SkipIntroPatch), typeof(SlotsRowsPatch), typeof(SlotsImportPatch), typeof(SlotsKeepOnLoadPatch), typeof(SlotsUtilityEffectsPatch), typeof(SlotsAddAtPatch), typeof(SlotsFreeSpacePatch), typeof(SlotsHaveEmptyPatch), typeof(SlotsUsedPercentagePatch), typeof(SlotsCanAddPatch), typeof(SlotsDropPatch), typeof(SlotsGuiPatch), typeof(SlotsGridPatch), typeof(SlotsEquipPatch), typeof(SlotsUnequipPatch), typeof(SlotsDeathPatch), typeof(SlotsGravePatch), typeof(SlotsGraveLoadPatch), typeof(SlotsTakeAllPatch), typeof(GraveFitPatch), typeof(SlotsStackAllPatch), typeof(SlotHotkeyInputPatch) }; public static int Apply(Harmony harmony) { int num = 0; Type[] patchTypes = PatchTypes; foreach (Type type in patchTypes) { try { if (harmony.CreateClassProcessor(type).Patch().Count == 0) { Log.Error("Patch " + type.Name + " hooked into nothing; that feature is disabled."); } else { num++; } } catch (Exception ex) { Log.Error("Patch " + type.Name + " could not be applied (" + ex.GetType().Name + ": " + ex.Message + "). That feature is disabled; the rest of the mod keeps working."); } } HashSet<Type> hashSet = new HashSet<Type>(PatchTypes); patchTypes = typeof(PatchInstaller).Assembly.GetTypes(); foreach (Type type2 in patchTypes) { if (type2.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0 && !hashSet.Contains(type2)) { Log.Error("Patch " + type2.Name + " is not in PatchInstaller.PatchTypes, so it never runs."); } } return num; } } [HarmonyPatch] internal static class ContainerAwakePatch { private static IEnumerable<MethodBase> TargetMethods() { return Reflect.Methods(typeof(Container), "Awake"); } private static void Postfix(Container __instance) { ContainerRegistry.Register(__instance); try { SharedContainers.Register(__instance); } catch (Exception ex) { Log.Warn("Shared chest setup failed for " + ((Object)__instance).name + ": " + ex.Message); } } } [HarmonyPatch] internal static class SharedOpenPatch { private static IEnumerable<MethodBase> TargetMethods() { return Reflect.Methods(typeof(Container), "RPC_OpenResponse"); } private static bool Prefix(Container __instance, bool granted) { if (!granted) { return SharedContainers.OnVanillaOpenRefused(__instance); } return true; } } [HarmonyPatch] internal static class SharedViewPatch { private static IEnumerable<MethodBase> TargetMethods() { return Reflect.Methods(typeof(InventoryGui), "UpdateContainer"); } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { MethodInfo objB = AccessTools.Method(typeof(Container), "IsOwner", (Type[])null, (Type[])null); MethodInfo operand = AccessTools.Method(typeof(SharedContainers), "CanView", (Type[])null, (Type[])null); List<CodeInstruction> list = instructions.ToList(); int num = 0; foreach (CodeInstruction item in list) { if ((item.opcode == OpCodes.Callvirt || item.opcode == OpCodes.Call) && object.Equals(item.operand, objB)) { item.opcode = OpCodes.Call; item.operand = operand; num++; } } if (num == 0) { throw new InvalidOperationException("Container.IsOwner check not found in InventoryGui.UpdateContainer"); } return list; } } [HarmonyPatch] internal static class SharedLoadPatch { private static IEnumerable<MethodBase> TargetMethods() { return Reflect.Methods(typeof(Container), "Load"); } private static void Prefix(Container __instance) { SharedContainers.BeforeLoad(__instance); } } [HarmonyPatch] internal static class SharedEditPatch { private static IEnumerable<MethodBase> TargetMethods() { foreach (MethodBase item in Reflect.Methods(typeof(InventoryGui), "OnSelectedItem")) { yield return item; } foreach (MethodBase item2 in Reflect.Methods(typeof(InventoryGui), "OnRightClickItem")) { yield return item2; } foreach (MethodBase item3 in Reflect.Methods(typeof(InventoryGui), "OnTakeAll")) { yield return item3; } foreach (MethodBase item4 in Reflect.Methods(typeof(InventoryGui), "OnStackAll")) { yield return item4; } foreach (MethodBase item5 in Reflect.Methods(typeof(InventoryGui), "OnDropOutside")) { yield return item5; } } private static bool Prefix(InventoryGui __instance, MethodBase __originalMethod, object[] __args) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //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) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) try { SharedContainers.GuiAction action = __originalMethod.Name switch { "OnSelectedItem" => SharedContainers.GuiAction.Select, "OnRightClickItem" => SharedContainers.GuiAction.RightClick, "OnTakeAll" => SharedContainers.GuiAction.TakeAll, "OnStackAll" => SharedContainers.GuiAction.StackAll, _ => SharedContainers.GuiAction.DropOutside, }; InventoryGrid grid = null; ItemData item = null; Vector2i pos = default(Vector2i); Modifier mod = (Modifier)0; foreach (object obj in __args) { InventoryGrid val = (InventoryGrid)((obj is InventoryGrid) ? obj : null); if (val != null) { grid = val; continue; } ItemData val2 = (ItemData)((obj is ItemData) ? obj : null); if (val2 != null) { item = val2; } else if (obj is Vector2i val3) { pos = val3; } else if (obj is Modifier val4) { mod = val4; } } return SharedContainers.BeforeGuiAction(__instance, action, grid, item, pos, mod); } catch (Exception ex) { Log.Warn("Shared chest click failed: " + ex.Message); return !SharedContainers.ShowsChestOwnedByOther(__instance); } } } [HarmonyPatch] internal static class AugmentScopePatch { private static IEnumerable<MethodBase> TargetMethods() { foreach (MethodBase item in Reflect.Methods(typeof(Player), "HaveRequirements")) { yield return item; } foreach (MethodBase item2 in Reflect.Methods(typeof(Player), "HaveRequirementItems")) { yield return item2; } foreach (MethodBase item3 in Reflect.Methods(typeof(InventoryGui), "SetupRequirement")) { yield return item3; } } private static void Prefix(object __0, out bool __state) { Recipe val = (Recipe)((__0 is Recipe) ? __0 : null); __state = val == null || !val.m_requireOnlyOneIngredient; if (__state) { Scope.Augment++; } } private static Exception Finalizer(Exception __exception, bool __state) { if (__state) { Scope.Exit(ref Scope.Augment); } return __exception; } } [HarmonyPatch] internal static class SuppressScopePatch { private static IEnumerable<MethodBase> TargetMethods() { return Reflect.Methods(typeof(Player), "UpdateKnownRecipesList"); } private static void Prefix() { Scope.Suppress++; } private static Exception Finalizer(Exception __exception) { Scope.Exit(ref Scope.Suppress); return __exception; } } [HarmonyPatch] internal static class CountItemsPatch { private static IEnumerable<MethodBase> TargetMethods() { return Reflect.Methods(typeof(Inventory), "CountItems", (MethodInfo m) => Reflect.FirstParamIs<string>(m) && m.ReturnType == typeof(int)); } private static void Postfix(Inventory __instance, string name, int quality, ref int __result) { if (Scope.Augmenting && !Scope.Consuming && name != null && Runtime.CraftActive && Runtime.IsLocalPlayerInventory(__instance)) { __result += Runtime.CountNearby(name, quality); } } } [HarmonyPatch] internal static class HaveItemPatch { private static IEnumerable<MethodBase> TargetMethods() { return Reflect.Methods(typeof(Inventory), "HaveItem", (MethodInfo m) => Reflect.FirstParamIs<string>(m) && m.ReturnType == typeof(bool)); } private static void Postfix(Inventory __instance, string name, ref bool __result) { if (!__result && Scope.Augmenting && !Scope.Consuming && name != null && Runtime.CraftActive && Runtime.IsLocalPlayerInventory(__instance) && Runtime.CountNearby(name, -1) > 0) { __result = true; } } } [HarmonyPatch] internal static class ConsumeScopePatch { private static IEnumerable<MethodBase> TargetMethods() { return Reflect.Methods(typeof(Player), "ConsumeResources"); } private static void Prefix(Player __instance, out bool __state) { __state = (Object)(object)__instance == (Object)(object)Player.m_localPlayer && !__instance.NoCostCheat(); if (__state) { Scope.Consume++; Runtime.Ledger.Begin(); Runtime.Index.Invalidate(); } } private static Exception Finalizer(Player __instance, Exception __exception, bool __state) { if (__state) { Scope.Exit(ref Scope.Consume); foreach (ConsumptionLedger.Entry item in Runtime.Ledger.Unsatisfied()) { Log.Warn($"Could only provide {item.Provided}/{item.Shortfall} of {item.Item} from nearby containers (another player may have taken them)."); } } return __exception; } } [HarmonyPatch] internal static class RemoveItemPatch { internal struct State { public int Before; public int Amount; } private static IEnumerable<MethodBase> TargetMethods() { return Reflect.Methods(typeof(Inventory), "RemoveItem", delegate(MethodInfo m) { ParameterInfo[] parameters = m.GetParameters(); return parameters.Length >= 2 && parameters[0].ParameterType == typeof(string) && parameters[1].ParameterType == typeof(int); }); } private static void Prefix(Inventory __instance, string name, int amount, int itemQuality, out State __state) { __state = new State { Before = -1, Amount = amount }; if (Scope.Consuming && name != null && Runtime.CraftActive && Runtime.IsLocalPlayerInventory(__instance)) { __state.Before = Runtime.CountInInventory(__instance, name, itemQuality); } } private static void Postfix(Inventory __instance, string name, int itemQuality, State __state) { if (__state.Before >= 0) { int amount = __state.Amount; int num = __state.Before - Runtime.CountInInventory(__instance, name, itemQuality); int num2 = amount - num; if (num2 > 0) { int provided = Runtime.TakeNearby(name, num2, itemQuality); Runtime.Ledger.Record(name, num2, provided); } } } } [HarmonyPatch] internal static class FreshnessPatch { private static IEnumerable<MethodBase> TargetMethods() { return Reflect.Methods(typeof(InventoryGui), "DoCrafting"); } private static void Prefix() { Runtime.Index.Invalidate(); } } [HarmonyPatch] internal static class BuildRevalidatePatch { private static IEnumerable<MethodBase> TargetMethods() { return Reflect.Methods(typeof(Player), "TryPlacePiece"); } private static bool Prefix(Player __instance, Piece piece, ref bool __result) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || !Runtime.CraftActive || (Object)(object)piece == (Object)null || __instance.NoCostCheat()) { return true; } Runtime.Index.Invalidate(); if (__instance.HaveRequirements(piece, (RequirementMode)0)) { return true; } __result = false; return false; } } [HarmonyPatch] internal static class OwnershipResponsePatch { private static IEnumerable<MethodBase> TargetMethods() { return Reflect.Methods(typeof(Container), "RPC_StackResponse"); } private static bool Prefix(Container __instance, object[] __args) { if (!OwnershipRequests.Consume(__instance)) { return true; } bool flag = default(bool); int num; if (__args.Length > 1) { object obj = __args[1]; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } } else { num = 0; } bool flag2 = (byte)((uint)num & (flag ? 1u : 0u)) != 0; if (!flag2) { DeferredTakes.OnDenied(__instance); } Log.Debug(flag2 ? ("Owner handed over " + ((Object)__instance).name) : ("Owner kept " + ((Object)__instance).name + " (open by someone)")); return false; } } [HarmonyPatch] internal static class CookingTimerPatch { private static bool s_warned; private static IEnumerable<MethodBase> TargetMethods() { return Reflect.Methods(typeof(CookingStation), "HoverText", (MethodInfo m) => m.ReturnType == typeof(string) && m.GetParameters().Length == 0); } private static void Postfix(CookingStation __instance, ref string __result) { try { using (Perf.Measure(Perf.Feature.CookingTimers)) { __result = CookingTimers.Append(__instance, __result); } } catch (Exception ex) { if (!s_warned) { s_warned = true; Log.Warn("Cooking timers: " + ex.Message + " (check the formats in '8 - Cooking Timers')"); } } } } [HarmonyPatch] internal static class StationFeedPatch { internal sealed class Use { public StationSupply.Loan Loan; public bool Counted; public float UsedBefore; } private static IEnumerable<MethodBase> TargetMethods() { foreach (MethodBase item in Reflect.Methods(typeof(Smelter), "OnAddOre")) { yield return item; } foreach (MethodBase item2 in Reflect.Methods(typeof(Smelter), "OnAddFuel")) { yield return item2; } foreach (MethodBase item3 in Reflect.Methods(typeof(CookingStation), "OnInteract")) { yield return item3; } foreach (MethodBase item4 in Reflect.Methods(typeof(CookingStation), "OnAddFuelSwitch")) { yield return item4; } foreach (MethodBase item5 in Reflect.Methods(typeof(Fermenter), "Interact")) { yield return item5; } } private static bool Prefix(object __instance, object[] __args, MethodBase __originalMethod, ref bool __result, out Use __state) { __state = null; try { if (StationCapacity.FullWithPending(__instance, __originalMethod.Name, out var counted, out var usedBefore)) { bool flag = default(bool); int num; if (__args.Length > 1) { object obj = __args[1]; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } } else { num = 0; } bool flag2 = (byte)((uint)num & (flag ? 1u : 0u)) != 0; foreach (object obj2 in __args) { Humanoid val = (Humanoid)((obj2 is Humanoid) ? obj2 : null); if (val != null && !flag2) { ((Character)val).Message((MessageType)2, "$msg_itsfull", 0, (Sprite)null, false); break; } } __result = false; return false; } __state = new Use { Counted = counted, UsedBefore = usedBefore, Loan = StationSupply.BeforeUse(__instance, __originalMethod.Name, __args) }; } catch (Exception ex) { Log.Warn("Station supply failed: " + ex.Message); } return true; } private static void Postfix(object __instance, MethodBase __originalMethod, bool __result, Use __state) { if (__state == null || !__state.Counted || !__result) { return; } try { StationCapacity.Sent(__instance, __originalMethod.Name, __state.UsedBefore); } catch (Exception ex) { Log.Debug("Station limit tracking: " + ex.Message); } } private static Exception Finalizer(Exception __exception, Use __state) { StationSupply.AfterUse(__state?.Loan); return __exception; } } [HarmonyPatch] internal static class ContainerHoverPatch { private static IEnumerable<MethodBase> TargetMethods() { return Reflect.Methods(typeof(Container), "GetHoverText"); } private static void Postfix(Container __instance, ref string __result) { try { string text = ContainerContents.Describe(__instance); if (text != null) { __result += text; } } catch (Exception ex) { Log.Debug("ContainerHoverPatch: " + ex.Message); } } } [HarmonyPatch] internal static class ItemTooltipPatch { private static IEnumerable<MethodBase> TargetMethods() { return Reflect.Methods(typeof(ItemData), "GetTooltip", (MethodInfo m) => m.IsStatic && Reflect.FirstParamIs<ItemData>(m)); } private static void Postfix(ItemData item, bool crafting, bool appending, ref string __result) { try { if (!appending) { string text; using (Perf.Measure(Perf.Feature.ItemTooltip)) { text = ItemTooltip.Describe(item, crafting); } if (text != null) { __result += text; } } } catch (Exception ex) { Log.Debug("ItemTooltipPatch: " + ex.Message); } } } [HarmonyPatch] internal static class StationFillPatch { private static IEnumerable<MethodBase> TargetMethods() { return Reflect.Methods(typeof(Switch), "Interact"); } private static bool Prefix(Switch __instance, Humanoid character, bool hold, bool alt, ref bool __result) { if (!alt || hold) { return true; } try { if (!StationSupply.TryFill(__instance, character, out var added)) { return true; } __result = added; return false; } catch (Exception ex) { Log.Warn("Station fill failed: " + ex.Message); return true; } } } [HarmonyPatch] internal static class StationHoverPatch { private static IEnumerable<MethodBase> TargetMethods() { foreach (MethodBase item in Reflect.Methods(typeof(Smelter), "OnHoverAddOre")) { yield return item; } foreach (MethodBase item2 in Reflect.Methods(typeof(Smelter), "OnHoverAddFuel")) { yield return item2; } foreach (MethodBase item3 in Reflect.Methods(typeof(CookingStation), "GetHoverText")) { yield return item3; } foreach (MethodBase item4 in Reflect.Methods(typeof(CookingStation), "OnHoverFuelSwitch")) { yield return item4; } foreach (MethodBase item5 in Reflect.Methods(typeof(Fermenter), "GetHoverText")) { yield return item5; } } private static void Postfix(object __instance, MethodBase __originalMethod) { try { StationSupply.Warm(__instance, __originalMethod.Name); } catch (Exception ex) { Log.Debug("StationHoverPatch: " + ex.Message); } } } [HarmonyPatch] internal static class RequirementTextPatch { private static readonly Dictionary<Type, PropertyInfo> s_textProps = new Dictionary<Type, PropertyInfo>(); private static IEnumerable<MethodBase> TargetMethods() { return Reflect.Methods(typeof(InventoryGui), "SetupRequirement"); } private static void Postfix(Transform elementRoot, Requirement req, bool craft) { //IL_012c: Unknown result type (might be due to invalid IL or missing references) try { if (!Runtime.Settings.ShowAvailableInUi || !Runtime.CraftActive) { return; } string text = req?.m_resItem?.m_itemData?.m_shared?.m_name; if ((Object)(object)elementRoot == (Object)null || text == null) { return; } int num = Runtime.CountNearby(text, -1); if (num <= 0) { return; } Transform val = elementRoot.Find("res_amount"); if ((Object)(object)val == (Object)null) { return; } PropertyInfo prop; Component val2 = FindTextComponent(((Component)val).gameObject, out prop); if ((Object)(object)val2 == (Object)null) { return; } string text2 = prop.GetValue(val2, null) as string; if (!string.IsNullOrEmpty(text2) && text2.IndexOf('/') < 0) { int num2 = Available(text, req, craft, num); prop.SetValue(val2, $"{num2}/{text2}", null); if (int.TryParse(text2, out var result) && num2 < result) { ((object)val2).GetType().GetProperty("color", typeof(Color))?.SetValue(val2, Color.red, null); } } } catch (Exception ex) { Log.Debug("RequirementTextPatch: " + ex.Message); } } private static int Available(string itemName, Requirement req, bool craft, int fromChestsAnyQuality) { Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); int maxQuality = req.m_resItem.m_itemData.m_shared.m_maxQuality; if (!craft || maxQuality <= 1) { return Runtime.CountInInventory(inventory, itemName, -1) + fromChestsAnyQuality; } int num = 0; for (int i = 1; i <= maxQuality; i++) { num = Math.Max(num, Runtime.CountInInventory(inventory, itemName, i) + Runtime.CountNearby(itemName, i)); } return num; } private static Component FindTextComponent(GameObject go, out PropertyInfo prop) { Component[] components = go.GetComponents<Component>(); foreach (Component val in components) { if (!((Object)(object)val == (Object)null)) { Type type = ((object)val).GetType(); if (!s_textProps.TryGetValue(type, out prop)) { prop = ((type.Name.IndexOf("Text", StringComparison.Ordinal) >= 0) ? type.GetProperty("text", typeof(string)) : null); s_textProps[type] = prop; } if (prop != null && prop.CanWrite) { return val; } } } prop = null; return null; } } } namespace NewtCraftHub.Integration { public static class ContainerContents { private struct Cached { public uint Revision; public int SettingsRevision; public ModSettings Settings; public string Text; } private sealed class Entry { public string Name; public string Label; public int Amount; public float Weight; public int Value; } private static readonly Dictionary<Container, Cached> s_cache = new Dictionary<Container, Cached>(ReferenceComparer<Container>.Instance); private static readonly Dictionary<string, Entry> s_byName = new Dictionary<string, Entry>(StringComparer.Ordinal); private static readonly List<Entry> s_sorted = new List<Entry>(); private static readonly StringBuilder s_sb = new StringBuilder(256); private static bool s_warnedFormat; private static bool s_warnedOtherMod; private static readonly Func<Container, long, bool> s_checkAccess = Reflect.InstanceFunc<Container, long, bool>("CheckAccess"); public static string Describe(Container container) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) ModSettings settings = Runtime.Settings; if (!settings.Enabled || !settings.ShowContentsOnHover || (Object)(object)container == (Object)null) { return null; } if (Runtime.OtherModShowsChestContents()) { if (!s_warnedOtherMod) { s_warnedOtherMod = true; Log.Warn("AzuHoverStats is also listing chest contents; NewtCraftHub' list is skipped. Turn off 'Show Chest Contents' in AzuHoverStats (or remove it) to use ours."); } return null; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return null; } if (s_checkAccess == null || !s_checkAccess(container, localPlayer.GetPlayerID())) { return null; } if (container.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, false)) { return null; } if (!ContainerRegistry.TryGet(container, out var src) || !src.IsAlive) { return null; } Inventory inventory = container.GetInventory(); uint revision = src.Revision; if (s_cache.TryGetValue(container, out var value) && value.Revision == revision && value.Settings == settings && value.SettingsRevision == settings.Revision) { return value.Text; } if (s_cache.Count > 512) { s_cache.Clear(); } Perf.Enter(); string text; try { text = Build(inventory, settings); } finally { Perf.Exit(); } s_cache[container] = new Cached { Revision = revision, Settings = settings, SettingsRevision = settings.Revision, Text = text }; return text; } private static string Build(Inventory inv, ModSettings s) { s_byName.Clear(); List<ItemData> allItems = inv.GetAllItems(); for (int i = 0; i < allItems.Count; i++) { ItemData val = allItems[i]; string text = val?.m_shared?.m_name; if (!string.IsNullOrEmpty(text)) { if (!s_byName.TryGetValue(text, out var value)) { Dictionary<string, Entry> dictionary = s_byName; Entry obj = new Entry { Name = text, Label = Localize(text) }; value = obj; dictionary[text] = obj; } value.Amount += val.m_stack; value.Weight += val.m_shared.m_weight * (float)val.m_stack; value.Value += val.m_shared.m_value * val.m_stack; } } if (s_byName.Count == 0) { return null; } s_sorted.Clear(); s_sorted.AddRange(s_byName.Values); s_sorted.Sort(delegate(Entry a, Entry b) { int num3 = s.HoverSortBy switch { ContentsSort.Name => string.Compare(a.Label, b.Label, StringComparison.CurrentCultureIgnoreCase), ContentsSort.Weight => a.Weight.CompareTo(b.Weight), ContentsSort.Value => a.Value.CompareTo(b.Value), _ => a.Amount.CompareTo(b.Amount), }; if (s.HoverSortBy != ContentsSort.Name) { num3 = -num3; } if (s.HoverSortAscending) { num3 = -num3; } return (num3 == 0) ? string.Compare(a.Label, b.Label, StringComparison.CurrentCultureIgnoreCase) : num3; }); s_sb.Clear(); int num = ((s.HoverMaxItems < 0) ? s_sorted.Count : Math.Min(Math.Max(1, s.HoverMaxItems), s_sorted.Count)); for (int num2 = 0; num2 < num; num2++) { s_sb.Append('\n').Append(Format(s.HoverEntryFormat, "<color=#FFFFAAFF>{0}</color> <color=#AAFFAAFF>{1}</color>", s_sorted[num2].Amount, s_sorted[num2].Label)); } if (s_sorted.Count > num && !string.IsNullOrEmpty(s.HoverOverflowFormat)) { s_sb.Append('\n').Append(Format(s.HoverOverflowFormat, "<color=#AAAAAAFF>+{0} more</color>", s_sorted.Count - num, null)); } if (!string.IsNullOrEmpty(s.HoverCapacityFormat)) { s_sb.Append('\n').Append(Format(s.HoverCapacityFormat, "<color=#AAAAAAFF>{0}/{1} slots</color>", inv.NrOfItems(), inv.GetWidth() * inv.GetHeight())); } return s_sb.ToString(); } private static string Format(string format, string fallback, object a, object b) { try { return string.Format(format, a, b); } catch (FormatException) { if (!s_warnedFormat) { s_warnedFormat = true; Log.Warn("Invalid hover format '" + format + "': using the default."); } return string.Format(fallback, a, b); } } private static string Localize(string token) { try { return (Localization.instance != null) ? Localization.instance.Localize(token) : token; } catch { return token; } } public static void Reset() { s_cache.Clear(); s_warnedFormat = false; s_warnedOtherMod = false; } } public static class ContainerRegistry { private static readonly List<IStorageSource> s_sources = new List<IStorageSource>(256); private static readonly Dictionary<Container, ContainerSource> s_byContainer = new Dictionary<Container, ContainerSource>(256, ReferenceComparer<Container>.Instance); public static IReadOnlyList<IStorageSource> Sources => s_sources; public static int Count => s_sources.Count; public static void Register(Container c) { if (!((Object)(object)c == (Object)null) && !s_byContainer.ContainsKey(c)) { ContainerSource containerSource = new ContainerSource(c); s_byContainer[c] = containerSource; s_sources.Add(containerSource); } } public static bool TryGet(Container c, out ContainerSource src) { src = null; if ((Object)(object)c != (Object)null) { return s_byContainer.TryGetValue(c, out src); } return false; } public static void Unregister(Container c) { if (!((Object)(object)c == (Object)null) && s_byContainer.TryGetValue(c, out var value)) { s_byContainer.Remove(c); s_sources.Remove(value); } } public static void Compact() { int num = 0; for (int i = 0; i < s_sources.Count; i++) { ContainerSource containerSource = (ContainerSource)s_sources[i]; if ((Object)(object)containerSource.Container == (Object)null) { s_byContainer.Remove(containerSource.Container); } else { s_sources[num++] = containerSource; } } if (num < s_sources.Count) { s_sources.RemoveRange(num, s_sources.Count - num); } } public static void Clear() { s_sources.Clear(); s_byContainer.Clear(); OwnershipRequests.Clear(); DeferredTakes.Clear(); } } public sealed class ContainerSource : IStorageSource { private const float RequestInterval = 2f; private static readonly Action<Container> s_save = Reflect.InstanceAction<Container>("Save"); private static readonly Action<Container> s_load = Reflect.InstanceAction<Container>("Load"); private static readonly Func<Container, long, bool> s_checkAccess = Reflect.InstanceFunc<Container, long, bool>("CheckAccess"); private static readonly Func<InventoryGui, Container> s_currentContainer = Reflect.FieldGetter<InventoryGui, Container>("m_currentContainer"); private static readonly List<ItemData> s_scratch = new List<ItemData>(16); private readonly Container _container; private ZNetView _nview; private string _prefabName; private readonly bool _isTombstone; private readonly bool _isVehicle; private float _lastRequest = float.NegativeInfinity; private int _playerBuilt = -1; private bool _accessOk; private float _accessCheckedAt = float.NegativeInfinity; private const float AccessRecheck = 3f; public static Func<ModSettings> SettingsProvider = () => Runtime.Settings; public Container Container => _container; private ZNetView NView { get { if ((Object)(object)_nview == (Object)null && (Object)(object)_container != (Object)null) { _nview = ((Component)_container).GetComponentInParent<ZNetView>(); } return _nview; } } public bool IsVehicle { get { if ((Object)(object)_container != (Object)null) { return _isVehicle; } return false; } } public bool IsAlive { get { if ((Object)(object)_container == (Object)null) { return false; } ZNetView nView = NView; if ((Object)(object)nView != (Object)null && nView.IsValid()) { return _container.GetInventory() != null; } return false; } } public bool IsUsable { get { //IL_010a: Unknown result type (might be due to invalid IL or missing references) if (!IsAlive || _isTombstone) { return false; } ModSettings modSettings = SettingsProvider(); ZDO zDO = NView.GetZDO(); if (modSettings.OnlyPlayerBuilt) { if (_playerBuilt < 0) { _playerBuilt = ((zDO.GetLong("creator", 0L) != 0) ? 1 : 0); } if (_playerBuilt == 0) { return false; } } if (!modSettings.IncludeVehicles && _isVehicle) { return false; } if (modSettings.SkipContainersInUse && !IsOpenByLocalPlayer() && (zDO.GetInt("InUse", 0) == 1 || _container.IsInUse())) { return false; } float time = Time.time; if (time - _accessCheckedAt >= 3f || time < _accessCheckedAt) { _accessCheckedAt = time; Player localPlayer = Player.m_localPlayer; long arg = (((Object)(object)localPlayer != (Object)null) ? localPlayer.GetPlayerID() : 0); _accessOk = s_checkAccess != null && s_checkAccess(_container, arg) && (!modSettings.RespectWards || PrivateArea.CheckAccess(((Component)_container).transform.position, 0f, false, false)); } return _accessOk; } } public bool IsReady { get { if (IsAlive) { return NView.IsOwner(); } return false; } } private bool Reachable { get { if (IsReady) { return true; } if (!SettingsProvider().TakeOwnership) { return false; } if (IsVehicle) { return !NView.GetZDO().HasOwner(); } return true; } } public Vec3 Position { get { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)_container).transform.position; return new Vec3(position.x, position.y, position.z); } } public string PrefabName { get { if (_prefabName != null) { return _prefabName; } ZNetView nView = NView; return _prefabName = Utils.GetPrefabName(((Object)(object)nView != (Object)null) ? ((Component)nView).gameObject : ((Component)_container).gameObject); } } public uint Revision { get { ZNetView nView = NView; if (!((Object)(object)nView != (Object)null) || !nView.IsValid()) { return 0u; } return nView.GetZDO().DataRevision; } } public ContainerSource(Container container) { _container = container; _isTombstone = (Object)(object)((Component)container).GetComponent<TombStone>() != (Object)null; _isVehicle = (Object)(object)((Component)container).GetComponent<ZNetView>() == (Object)null; } public void Prepare() { Request(force: false); } private void Request(bool force) { if (!IsAlive || IsReady || !SettingsProvider().TakeOwnership || !IsUsable) { return; } ZNetView nView = NView; if (!nView.GetZDO().HasOwner()) { nView.ClaimOwnership(); } else { if (IsVehicle) { return; } float time = Time.time; if ((!OwnershipRequests.IsPending(_container) || !(time - _lastRequest < 2f)) && (force || !(time - _lastRequest < 2f))) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { _lastRequest = time; OwnershipRequests.Add(_container); nView.InvokeRPC("RPC_RequestStack", new object[1] { localPlayer.GetPlayerID() }); Perf.OwnershipRequests++; Log.Debug($"Asked the owner for {PrefabName} at {Position}"); } } } } private bool IsOpenByLocalPlayer() { InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance != (Object)null && s_currentContainer != null) { return (Object)(object)s_currentContainer(instance) == (Object)(object)_container; } return false; } private static bool Matches(ItemData it, string itemName, int quality) { if (it?.m_shared != null && it.m_shared.m_name == itemName && (quality < 0 || it.m_quality == quality)) { return it.m_worldLevel >= Game.m_worldLevel; } return false; } public int Count(string itemName, int quality) { Inventory inventory = _container.GetInventory(); if (inventory == null || !Reachable) { return 0; } List<ItemData> allItems = inventory.GetAllItems(); int num = 0; for (int i = 0; i < allItems.Count; i++) { if (Matches(allItems[i], itemName, quality)) { num += allItems[i].m_stack; } } return num; } private Inventory BeginEdit() { if (!IsReady) { return null; } try { s_load?.Invoke(_container); } catch (Exception ex) { Log.Debug("Container.Load failed: " + ex.Message); } return _container.GetInventory(); } private void EndEdit() { try { s_save?.Invoke(_container); } catch (Exception ex) { Log.Debug("Container.Save failed: " + ex.Message); } } public int Take(string itemName, int amount, int quality) { if (amount <= 0) { return 0; } Inventory val = BeginEdit(); if (val == null) { return 0; } s_scratch.Clear(); List<ItemData> allItems = val.GetAllItems(); for (int i = 0; i < allItems.Count; i++) { if (Matches(allItems[i], itemName, quality)) { s_scratch.Add(allItems[i]); } } s_scratch.Sort((ItemData a, ItemData b) => a.m_stack.CompareTo(b.m_stack)); int num = 0; for (int num2 = 0; num2 < s_scratch.Count; num2++) { if (num >= amount) { break; } ItemData val2 = s_scratch[num2]; int num3 = Math.Min(val2.m_stack, amount - num); if (num3 > 0 && val.RemoveItem(val2, num3)) { num += num3; } } s_scratch.Clear(); if (num > 0) { EndEdit(); Log.Debug($"Took {num}x {itemName} from {PrefabName} at {Position}"); } return num; } public int TakeLater(string itemName, int amount, int quality) { if (amount <= 0 || !IsAlive || IsReady || !Reachable) { return 0; } int num = Math.Min(amount, Count(itemName, quality) - DeferredTakes.Reserved(this, itemName, quality)); if (num <= 0) { return 0; } Reques