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 Stackmaster v1.4.4
plugins/Stackmaster/Stackmaster.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Stackmaster.Core; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("JStack424")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Inventory sorting and nearby-storage planning for Valheim.")] [assembly: AssemblyFileVersion("1.4.4.0")] [assembly: AssemblyInformationalVersion("1.4.4+100d406b7cf7013739d0964b152c21b93c2ee790")] [assembly: AssemblyProduct("Stackmaster")] [assembly: AssemblyTitle("Stackmaster")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/JStack424/Stackmaster")] [assembly: AssemblyVersion("1.4.4.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Stackmaster { internal static class AtomicReservationFileStore { private const string DirectoryName = "Stackmaster.Reservations"; internal static bool TryRead(string logicalKey, out string payload, out bool exists) { payload = string.Empty; exists = false; string path = PathFor(logicalKey); if (!File.Exists(path)) { return true; } payload = File.ReadAllText(path, Encoding.UTF8); exists = true; return true; } internal static bool TryWrite(string logicalKey, string previousPayload, string candidatePayload) { if (string.IsNullOrEmpty(logicalKey) || previousPayload == null || candidatePayload == null) { return false; } string text = PathFor(logicalKey); Directory.CreateDirectory(Path.GetDirectoryName(text)); string text2 = text + "." + Guid.NewGuid().ToString("N") + ".tmp"; try { WriteThrough(text2, candidatePayload); try { if (File.Exists(text)) { File.Replace(text2, text, null); } else { File.Move(text2, text); } text2 = null; return true; } catch { if (DestinationEquals(text, candidatePayload)) { text2 = null; return true; } if (DestinationEquals(text, previousPayload)) { return false; } throw; } } finally { if (!string.IsNullOrEmpty(text2)) { try { File.Delete(text2); } catch { } } } } private static bool DestinationEquals(string path, string expected) { if (File.Exists(path)) { return string.Equals(File.ReadAllText(path, Encoding.UTF8), expected, StringComparison.Ordinal); } return false; } private static void WriteThrough(string path, string payload) { byte[] bytes = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false).GetBytes(payload); using FileStream fileStream = new FileStream(path, FileMode.CreateNew, FileAccess.Write, FileShare.None, 4096, FileOptions.WriteThrough); fileStream.Write(bytes, 0, bytes.Length); fileStream.Flush(flushToDisk: true); } private static string PathFor(string logicalKey) { if (string.IsNullOrEmpty(logicalKey)) { throw new ArgumentException("A reservation storage key is required.", "logicalKey"); } byte[] array; using (SHA256 sHA = SHA256.Create()) { array = sHA.ComputeHash(Encoding.UTF8.GetBytes(logicalKey)); } string path = BitConverter.ToString(array).Replace("-", string.Empty).ToLowerInvariant() + ".json"; return Path.Combine(Paths.ConfigPath, "Stackmaster.Reservations", path); } } internal static class ChestSortPreferences { private static readonly FieldInfo NetworkViewField = AccessTools.Field(typeof(Container), "m_nview"); private static readonly HashSet<string> SessionDisabled = new HashSet<string>(StringComparer.Ordinal); private static bool _storageHealthy; private static bool _failureLogged; internal static void Initialize() { SessionDisabled.Clear(); _storageHealthy = true; _failureLogged = false; } internal static bool TryGet(Container container, out string key, out bool enabled) { key = string.Empty; enabled = false; if (!TryCreateKey(container, out key)) { LogFailureOnce("Opened chest has no stable local player/world/ZDO identity; chest auto-sort was skipped."); return false; } if (SessionDisabled.Contains(key)) { return true; } if (!_storageHealthy) { return false; } try { bool num = PlayerPrefs.HasKey(key); int storedValue = ((!num) ? 1 : PlayerPrefs.GetInt(key, -1)); if (!ChestSortPreferencePolicy.TryInterpretStoredValue(num, storedValue, out enabled)) { DisableStorage("A saved chest auto-sort preference had an invalid value; chest auto-sort was disabled safely."); return false; } return true; } catch (Exception ex) { DisableStorage("Local chest auto-sort preferences could not be read; chest auto-sort was disabled safely: " + ex.GetType().Name); return false; } } internal static bool TrySet(string key, bool enabled) { if (string.IsNullOrEmpty(key) || !_storageHealthy) { return false; } if (enabled) { SessionDisabled.Remove(key); } else { SessionDisabled.Add(key); } try { if (enabled) { PlayerPrefs.DeleteKey(key); } else { PlayerPrefs.SetInt(key, 0); } PlayerPrefs.Save(); return true; } catch (Exception ex) { SessionDisabled.Add(key); DisableStorage("Local chest auto-sort preferences could not be saved; chest auto-sort was disabled safely: " + ex.GetType().Name); return false; } } internal static void Shutdown() { SessionDisabled.Clear(); _storageHealthy = false; } private static bool TryCreateKey(Container container, out string key) { key = string.Empty; if ((Object)(object)container == (Object)null || ((object)container).GetType() != typeof(Container) || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null || NetworkViewField == null) { return false; } object? value = NetworkViewField.GetValue(container); ZNetView val = (ZNetView)((value is ZNetView) ? value : null); if ((Object)(object)val == (Object)null || !val.IsValid()) { return false; } ZDO zDO = val.GetZDO(); if (zDO == null || ((ZDOID)(ref zDO.m_uid)).IsNone()) { return false; } return ChestSortPreferencePolicy.TryCreateKey(Player.m_localPlayer.GetPlayerID(), ZNet.instance.GetWorldUID(), ((object)Unsafe.As<ZDOID, ZDOID>(ref zDO.m_uid)/*cast due to .constrained prefix*/).ToString(), out key); } private static void DisableStorage(string message) { _storageHealthy = false; LogFailureOnce(message); } private static void LogFailureOnce(string message) { if (!_failureLogged) { _failureLogged = true; Plugin plugin = RuntimeContext.Plugin; if (plugin != null) { plugin.Log.LogWarning((object)message); } } } } internal sealed class CompatibilityResult { internal bool IsCompatible { get; } internal string Reason { get; } internal string Diagnostics { get; } internal CompatibilityResult(bool isCompatible, string reason, string diagnostics = "") { IsCompatible = isCompatible; Reason = reason; Diagnostics = diagnostics; } } internal static class CompatibilityGate { internal static CompatibilityResult Evaluate() { List<string> list = new List<string>(); string diagnostics = DescribeRuntimeIdentity(); Type[] array = new Type[47] { typeof(InventoryGui), typeof(Container), typeof(InventoryGrid), typeof(ItemData), typeof(SharedData), typeof(Vector2i), typeof(Modifier), typeof(GameObject), typeof(Transform), typeof(Requirement), typeof(Player), typeof(Hud), typeof(BuildUi), typeof(ZDOID), typeof(ZDO), typeof(Inventory), typeof(ZPackage), typeof(ZNetView), typeof(Humanoid), typeof(Game), typeof(ZNet), typeof(ZDOMan), typeof(Character), typeof(TextViewer), typeof(GameCamera), typeof(PlayerPrefs), typeof(Recipe), typeof(RequirementMode), typeof(ZInput), typeof(SplitDialog), typeof(CraftingStation), typeof(ZNetScene), typeof(PrivateArea), typeof(Fireplace), typeof(Smelter), typeof(ItemConversion), typeof(CookingStation), typeof(ShieldGenerator), typeof(SiegeMachine), typeof(ItemDrop), typeof(Vector3), typeof(ZDOVars), typeof(TextInput), typeof(KeyHints), typeof(Localization), typeof(Text), typeof(InventoryElement) }; foreach (Type type in array) { RuntimeContractValidator.RequireType(list, type); } HarmonyTargetManifest.Validate(list); RequireMethod(list, typeof(InventoryGui), "IsContainerOpen"); RequireMethod(list, typeof(InventoryGui), "UpdateRecipe", typeof(Player), typeof(float)); RequireStaticMethod(list, typeof(InventoryGui), "get_instance"); RequireMethod(list, typeof(Container), "CheckAccess", typeof(long)); RequireMethod(list, typeof(Container), "CheckForChanges"); RequireMethod(list, typeof(Container), "GetInventory"); RequireMethod(list, typeof(ZDOID), "IsNone"); RequireMethod(list, typeof(ZDO), "GetByteArray", typeof(int), typeof(byte[])); RequireMethod(list, typeof(ZDO), "get_DataRevision"); RequireMethod(list, typeof(ZDO), "get_OwnerRevision"); RequireMethod(list, typeof(Inventory), "Load", typeof(ZPackage)); RequireConstructor(list, typeof(Inventory), typeof(bool)); RequireConstructor(list, typeof(ZPackage), typeof(byte[])); RequireMethod(list, typeof(ZNetView), "HasOwner"); RequireMethod(list, typeof(Container), "IsOwner"); RequireMethod(list, typeof(Container), "IsInUse"); RequireMethod(list, typeof(Container), "SetInUse", typeof(bool)); RequireMethod(list, typeof(Container), "StackAll"); RequireMethod(list, typeof(Container), "RPC_RequestStack", typeof(long), typeof(long)); RequireMethod(list, typeof(ZDO), "GetOwner"); RequireMethod(list, typeof(ZDO), "SetOwner", typeof(long)); RequireStaticMethod(list, typeof(ZDOMan), "GetSessionID"); RequireMethod(list, typeof(ZDOMan), "GetZDO", typeof(ZDOID)); RequireMethod(list, typeof(ZDOMan), "ForceSendZDO", typeof(ZDOID)); RequireMethod(list, typeof(Character), "IsDead"); RequireMethod(list, typeof(Character), "InCutscene"); RequireMethod(list, typeof(Character), "IsTeleporting"); RequireStaticMethod(list, typeof(TextViewer), "get_instance"); RequireMethod(list, typeof(TextViewer), "IsVisible"); RequireStaticMethod(list, typeof(GameCamera), "InFreeFly"); RequireMethod(list, typeof(InventoryGrid), "GetInventory"); RequireMethod(list, typeof(InventoryGrid), "GetHoveredElement"); RequireMethod(list, typeof(Inventory), "MoveItemToThis", typeof(Inventory), typeof(ItemData), typeof(int), typeof(int), typeof(int)); RequireMethod(list, typeof(Inventory), "GetWidth"); RequireMethod(list, typeof(Inventory), "GetHeight"); RequireMethod(list, typeof(Inventory), "GetTotalWeight"); RequireMethod(list, typeof(Inventory), "ContainsItem", typeof(ItemData)); RequireMethod(list, typeof(Inventory), "GetAllItems"); RequireMethod(list, typeof(Inventory), "GetItemAt", typeof(int), typeof(int)); RequireMethod(list, typeof(Inventory), "RemoveAll"); RequireMethod(list, typeof(Inventory), "CountItems", typeof(string), typeof(int), typeof(bool)); RequireMethod(list, typeof(Inventory), "RemoveItem", typeof(ItemData), typeof(int)); RequireMethod(list, typeof(Inventory), "RemoveItem", typeof(string), typeof(int), typeof(int), typeof(bool)); RequireMethod(list, typeof(Inventory), "AddItem", typeof(ItemData), typeof(int), typeof(int), typeof(int), typeof(bool)); RequireMethod(list, typeof(Player), "ConsumeResources", typeof(Requirement[]), typeof(int), typeof(int), typeof(int)); RequireMethod(list, typeof(ItemData), "Clone"); RequireMethod(list, typeof(ItemData), "GetWeight", typeof(int)); RequireMethod(list, typeof(Requirement), "GetAmount", typeof(int)); RequireMethod(list, typeof(Recipe), "GetAmount", typeof(int), typeof(int).MakeByRefType(), typeof(ItemData).MakeByRefType(), typeof(int)); RequireMethod(list, typeof(Player), "GetHoverObject"); RequireMethod(list, typeof(Player), "GetMaxCarryWeight"); RequireMethod(list, typeof(Player), "GetPlayerID"); RequireMethod(list, typeof(ZNet), "GetWorldUID"); RequireStaticMethod(list, typeof(PlayerPrefs), "HasKey", typeof(string)); RequireStaticMethod(list, typeof(PlayerPrefs), "GetInt", typeof(string), typeof(int)); RequireStaticMethod(list, typeof(PlayerPrefs), "GetString", typeof(string), typeof(string)); RequireStaticMethod(list, typeof(PlayerPrefs), "SetInt", typeof(string), typeof(int)); RequireStaticMethod(list, typeof(PlayerPrefs), "SetString", typeof(string), typeof(string)); RequireStaticMethod(list, typeof(PlayerPrefs), "DeleteKey", typeof(string)); RequireStaticMethod(list, typeof(PlayerPrefs), "Save"); RequireStaticMethod(list, typeof(ZInput), "ResetButtonStatus", typeof(string)); RequireStaticMethod(list, typeof(ZInput), "IsGamepadActive"); RequireMethod(list, typeof(Localization), "RemoveTextFromCache", typeof(Text)); RequireMethod(list, typeof(SplitDialog), "get_IsActive"); RequireMethod(list, typeof(ZNetView), "IsOwner"); RequireMethod(list, typeof(ZNetView), "IsValid"); RequireMethod(list, typeof(ZNetView), "GetZDO"); RequireStaticMethod(list, typeof(CraftingStation), "get_Instances"); RequireStaticMethod(list, typeof(CraftingStation), "HaveBuildStationInRange", typeof(string), typeof(Vector3)); RequireMethod(list, typeof(CraftingStation), "GetStationBuildRange"); RequireMethod(list, typeof(CraftingStation), "GetLevel", typeof(bool)); RequireMethod(list, typeof(CraftingStation), "CheckUsable", typeof(Player), typeof(bool)); RequireStaticMethod(list, typeof(ZNetScene), "get_instance"); RequireMethod(list, typeof(ZNetScene), "GetPrefab", typeof(string)); RequireMethod(list, typeof(ZNetScene), "GetPrefabHash", typeof(GameObject)); RequireMethod(list, typeof(ZDO), "GetPrefab"); RequireMethod(list, typeof(ZNetView), "InvokeRPC", typeof(string), typeof(object[])); RequireStaticMethod(list, typeof(PrivateArea), "CheckAccess", typeof(Vector3), typeof(float), typeof(bool), typeof(bool)); RequireField(list, typeof(InventoryGui), "m_pvp"); RequireField(list, typeof(InventoryGui), "m_container"); RequireField(list, typeof(InventoryGui), "m_playerGrid"); RequireField(list, typeof(InventoryGui), "m_currentContainer"); RequireField(list, typeof(InventoryGui), "m_craftTimer"); RequireField(list, typeof(InventoryGui), "m_craftRecipe"); RequireField(list, typeof(InventoryGui), "m_selectedRecipe"); RequireField(list, typeof(InventoryGui), "m_reqList"); RequireField(list, typeof(InventoryGui), "m_craftUpgradeItem"); RequireField(list, typeof(InventoryGui), "m_selectedVariant"); RequireField(list, typeof(InventoryGui), "m_craftVariant"); RequireField(list, typeof(InventoryGui), "m_touchMultiCrafting"); Type type2 = AccessTools.Inner(typeof(InventoryGui), "RecipeDataPair"); if (type2 == null) { list.Add("InventoryGui.RecipeDataPair missing"); } else { RequireProperty(list, type2, "Recipe"); RequireProperty(list, type2, "ItemData"); } RequireField(list, typeof(InventoryGui), "m_multiCrafting"); RequireField(list, typeof(InventoryGui), "m_multiCraftAmount"); RequireField(list, typeof(InventoryGui), "m_dragItem"); RequireField(list, typeof(InventoryGui), "m_dragInventory"); RequireField(list, typeof(InventoryGui), "m_trophiesPanel"); RequireField(list, typeof(InventoryGui), "m_achievementsPanel"); RequireField(list, typeof(InventoryGui), "m_skillsDialog"); RequireField(list, typeof(InventoryGui), "m_textsDialog"); RequireField(list, typeof(InventoryGui), "m_splitDialog"); RequireField(list, typeof(InventoryGui), "m_variantDialog"); RequireField(list, typeof(Hud), "m_requirementItems"); RuntimeContractValidator.RequireField(list, typeof(Hud), "m_hoverName", typeof(TextMeshProUGUI), mustBeStatic: false); RequireField(list, typeof(KeyHints), "m_buildMenuHintsKB"); RequireField(list, typeof(Container), "m_nview"); RequireField(list, typeof(Container), "m_wagon"); RequireField(list, typeof(ZDO), "m_uid"); RequireField(list, typeof(ZDOVars), "s_items"); RequireField(list, typeof(Inventory), "m_onChanged"); RequireField(list, typeof(Inventory), "m_inventory"); RequireField(list, typeof(Player), "m_customData"); RequireField(list, typeof(Player), "m_noPlacementCost"); RequireField(list, typeof(TextInput), "m_inputField"); RequireProperty(list, typeof(InventoryElement), "Position"); RequireField(list, typeof(ItemData), "m_gridPos"); RuntimeContractValidator.RequireField(list, typeof(ItemData), "m_shared", typeof(SharedData), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(SharedData), "m_maxStackSize", typeof(int), mustBeStatic: false); RequireField(list, typeof(ItemData), "m_stack"); RequireField(list, typeof(ItemData), "m_quality"); RequireField(list, typeof(ItemData), "m_dropPrefab"); RequireField(list, typeof(ItemData), "m_worldLevel"); RequireField(list, typeof(ItemData), "m_equipped"); RequireField(list, typeof(Piece), "m_resources"); RuntimeContractValidator.RequireField(list, typeof(Piece), "m_name", typeof(string), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(Piece), "m_enabled", typeof(bool), mustBeStatic: false); RequireMethod(list, typeof(Piece), "IsPlacedByPlayer"); RequireField(list, typeof(Requirement), "m_resItem"); RequireField(list, typeof(Requirement), "m_amount"); RequireField(list, typeof(Piece), "m_craftingStation"); RuntimeContractValidator.RequireField(list, typeof(Player), "m_placementGhost", typeof(GameObject), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(Player), "m_placementStatus", typeof(PlacementStatus), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(CraftingStation), "m_name", typeof(string), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(ItemDrop), "m_itemData", typeof(ItemData), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(Fireplace), "m_canRefill", typeof(bool), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(Fireplace), "m_infiniteFuel", typeof(bool), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(Fireplace), "m_maxFuel", typeof(float), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(Fireplace), "m_fuelItem", typeof(ItemDrop), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(Smelter), "m_maxFuel", typeof(int), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(Smelter), "m_fuelItem", typeof(ItemDrop), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(Smelter), "m_conversion", typeof(List<ItemConversion>), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(ItemConversion), "m_from", typeof(ItemDrop), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(ShieldGenerator), "m_fuelItems", typeof(List<ItemDrop>), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(SiegeMachine), "m_engine", typeof(Smelter), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(CookingStation), "m_useFuel", typeof(bool), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(CookingStation), "m_maxFuel", typeof(int), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(CookingStation), "m_fuelItem", typeof(ItemDrop), mustBeStatic: false); RequireField(list, typeof(Recipe), "m_resources"); RequireField(list, typeof(Recipe), "m_requireOnlyOneIngredient"); if (list.Count != 0) { return new CompatibilityResult(isCompatible: false, string.Join("; ", list), diagnostics); } return new CompatibilityResult(isCompatible: true, "verified runtime contract", diagnostics); } internal static CompatibilityResult EvaluateExpeditionReservationUi() { List<string> list = new List<string>(); RuntimeContractValidator.RequireField(list, typeof(Piece), "m_icon", typeof(Sprite), mustBeStatic: false); if (list.Count != 0) { return new CompatibilityResult(isCompatible: false, string.Join("; ", list)); } return new CompatibilityResult(isCompatible: true, "verified optional reservation UI contract"); } internal static CompatibilityResult EvaluateBuildMenuReservationUi() { List<string> list = new List<string>(); RuntimeContractValidator.RequireField(list, typeof(Piece), "m_icon", typeof(Sprite), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(Hud), "m_buildUi", typeof(BuildUi), mustBeStatic: false); RuntimeContractValidator.RequireField(list, typeof(BuildUi), "m_tabContainer", typeof(RectTransform), mustBeStatic: false); RuntimeContractValidator.RequireMethod(list, typeof(Hud), "IsPieceSelectionVisible", true, false); RuntimeContractValidator.RequireMethod(list, typeof(BuildUi), "OnSelectPiece", false, false, typeof(Piece)); if (list.Count != 0) { return new CompatibilityResult(isCompatible: false, string.Join("; ", list)); } return new CompatibilityResult(isCompatible: true, "verified optional build-menu reservation UI contract"); } private static string DescribeRuntimeIdentity() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) Assembly assembly = typeof(Player).Assembly; string text = ((object)Version.CurrentVersion/*cast due to .constrained prefix*/).ToString(); string unityVersion = Application.unityVersion; string text2 = typeof(BaseUnityPlugin).Assembly.GetName().Version?.ToString() ?? "unknown"; string text3 = typeof(Harmony).Assembly.GetName().Version?.ToString() ?? "unknown"; Guid moduleVersionId = assembly.ManifestModule.ModuleVersionId; string[] obj = new string[12] { "Valheim label ", Application.version, ", API ", text, ", Unity ", unityVersion, ", BepInEx ", text2, ", Harmony ", text3, ", assembly_valheim MVID ", null }; Guid guid = moduleVersionId; obj[11] = guid.ToString(); return string.Concat(obj); } private static void RequireMethod(ICollection<string> failures, Type type, string name, params Type[] parameters) { RuntimeContractValidator.RequireMethod(failures, type, name, mustBeStatic: false, declaredOnly: false, parameters); } private static void RequireStaticMethod(ICollection<string> failures, Type type, string name, params Type[] parameters) { RuntimeContractValidator.RequireMethod(failures, type, name, mustBeStatic: true, declaredOnly: false, parameters); } private static void RequireConstructor(ICollection<string> failures, Type type, params Type[] parameters) { RuntimeContractValidator.RequireConstructor(failures, type, parameters); } private static void RequireProperty(ICollection<string> failures, Type type, string name) { RuntimeContractValidator.RequireProperty(failures, type, name); } private static void RequireField(ICollection<string> failures, Type type, string name) { RuntimeContractValidator.RequireField(failures, type, name); } } internal static class ConfigMigration { internal static ConfigEntry<KeyboardShortcut> BindRenamedKeyboardShortcut(ConfigFile config, string section, string legacyKey, string currentKey, KeyboardShortcut defaultShortcut, string currentDescription) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) if (config == null) { throw new ArgumentNullException("config"); } bool saveOnConfigSet = config.SaveOnConfigSet; config.SaveOnConfigSet = false; try { ConfigEntry<KeyboardShortcut> val = config.Bind<KeyboardShortcut>(section, legacyKey, defaultShortcut, "Legacy Stackmaster setting; migrated automatically and removed from the saved configuration."); ConfigEntry<KeyboardShortcut> val2 = config.Bind<KeyboardShortcut>(section, currentKey, defaultShortcut, currentDescription); if (((object)val2.Value/*cast due to .constrained prefix*/).Equals((object?)defaultShortcut) && !((object)val.Value/*cast due to .constrained prefix*/).Equals((object?)defaultShortcut)) { val2.Value = val.Value; } if (!config.Remove(((ConfigEntryBase)val).Definition)) { throw new InvalidOperationException("Could not retire legacy Stackmaster configuration key: " + legacyKey); } config.Save(); return val2; } finally { config.SaveOnConfigSet = saveOnConfigSet; } } internal static ConfigEntry<bool> BindRenamedDefaultEnabledBoolean(ConfigFile config, string section, string legacyKey, string currentKey, string currentDescription) { if (config == null) { throw new ArgumentNullException("config"); } bool saveOnConfigSet = config.SaveOnConfigSet; config.SaveOnConfigSet = false; try { ConfigEntry<bool> val = config.Bind<bool>(section, legacyKey, true, "Legacy Stackmaster setting; migrated automatically and removed from the saved configuration."); ConfigEntry<bool> val2 = config.Bind<bool>(section, currentKey, true, currentDescription); val2.Value = val.Value && val2.Value; if (!config.Remove(((ConfigEntryBase)val).Definition)) { throw new InvalidOperationException("Could not retire legacy Stackmaster configuration key: " + legacyKey); } config.Save(); return val2; } finally { config.SaveOnConfigSet = saveOnConfigSet; } } } internal sealed class ContainerHandle { internal string Id { get; } internal Container Container { get; } internal ZNetView NetworkView { get; } internal ZDO CapturedZdo { get; } internal ContainerSnapshot Snapshot { get; } internal Inventory ResourceInventory { get; } internal uint ResourceDataRevision { get; } internal uint ObservedDataRevision { get; } internal ZDOID ResourceZdoId { get; } internal ushort ResourceOwnerRevision { get; } internal long ResourceOwner { get; } internal bool ResourceReadable { get; } internal ContainerHandle(string id, Container container, ZNetView networkView, ZDO capturedZdo, ContainerSnapshot snapshot, Inventory resourceInventory, uint resourceDataRevision, uint observedDataRevision, ZDOID resourceZdoId, ushort resourceOwnerRevision, long resourceOwner, bool resourceReadable) { //IL_0044: 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) Id = id; Container = container; NetworkView = networkView; CapturedZdo = capturedZdo; Snapshot = snapshot; ResourceInventory = resourceInventory; ResourceDataRevision = resourceDataRevision; ObservedDataRevision = observedDataRevision; ResourceZdoId = resourceZdoId; ResourceOwnerRevision = resourceOwnerRevision; ResourceOwner = resourceOwner; ResourceReadable = resourceReadable; } } internal sealed class TargetDiscoveryDiagnostic { internal bool TargetPresent { get; } internal double Distance { get; } internal string Scope { get; } internal bool WithinScope { get; } internal bool Discovered { get; set; } internal string ObservedType { get; set; } internal bool? IsVanilla { get; set; } internal bool? HasNetworkView { get; set; } internal bool? NetworkViewValid { get; set; } internal bool? HasZdo { get; set; } internal bool? Refreshed { get; set; } internal bool? HasInventory { get; set; } internal bool? InUse { get; set; } internal bool? AccessGranted { get; set; } internal string RefreshFailure { get; set; } internal string AccessFailure { get; set; } internal TargetDiscoveryDiagnostic(bool targetPresent, double distance, StorageScope scope, Vector3 targetPosition) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) TargetPresent = targetPresent; Distance = distance; Scope = ((scope != null) ? scope.Description : "unavailable"); WithinScope = targetPresent && scope != null && scope.Contains(targetPosition); } internal string Format(DiscoveryResult discovery) { return string.Format(CultureInfo.InvariantCulture, "targetPresent={0} discovered={1} distance={2} scope={3} withinScope={4} searchTruncated={5} truncationReason={6} searchMs={7:0.00} objectScanMs={8:0.00} inspectionMs={9:0.00} budgetMs={10:0.00} candidates={11} inspected={12} minimumBeforeBudget={13} maximumNearby={14} type={15} vanilla={16} nview={17} nviewValid={18} zdo={19} refresh={20} inventory={21} inUse={22} access={23} refreshError={24} accessError={25}", TargetPresent, Discovered, double.IsPositiveInfinity(Distance) ? "n/a" : Distance.ToString("0.0", CultureInfo.InvariantCulture), Scope, WithinScope, discovery.Truncated, discovery.TruncationReason ?? "none", discovery.SearchMilliseconds, discovery.ObjectScanMilliseconds, discovery.InspectionMilliseconds, 25.0, discovery.NearbyCandidates, discovery.InspectedNearby, 8, 128, ObservedType ?? "n/a", FormatNullable(IsVanilla), FormatNullable(HasNetworkView), FormatNullable(NetworkViewValid), FormatNullable(HasZdo), FormatNullable(Refreshed), FormatNullable(HasInventory), FormatNullable(InUse), FormatNullable(AccessGranted), Sanitize(RefreshFailure), Sanitize(AccessFailure)); } private static string FormatNullable(bool? value) { if (!value.HasValue) { return "n/a"; } return value.Value.ToString(); } private static string Sanitize(string value) { if (string.IsNullOrEmpty(value)) { return "none"; } string text = value.Replace('\r', ' ').Replace('\n', ' ').Trim(); if (text.Length > 160) { return text.Substring(0, 160) + "…"; } return text; } } internal sealed class DiscoveryResult { internal IReadOnlyList<ContainerHandle> Containers { get; } internal bool Truncated { get; } internal double SearchMilliseconds { get; } internal double ObjectScanMilliseconds { get; } internal double InspectionMilliseconds { get; } internal int NearbyCandidates { get; } internal int InspectedNearby { get; } internal string TruncationReason { get; } internal TargetDiscoveryDiagnostic TargetDiagnostic { get; } internal StorageScope Scope { get; } internal DiscoveryResult(IReadOnlyList<ContainerHandle> containers, bool truncated, double searchMilliseconds, double objectScanMilliseconds, double inspectionMilliseconds, int nearbyCandidates, int inspectedNearby, string truncationReason, TargetDiscoveryDiagnostic targetDiagnostic, StorageScope scope) { Containers = containers; Truncated = truncated; SearchMilliseconds = searchMilliseconds; ObjectScanMilliseconds = objectScanMilliseconds; InspectionMilliseconds = inspectionMilliseconds; NearbyCandidates = nearbyCandidates; InspectedNearby = inspectedNearby; TruncationReason = truncationReason; TargetDiagnostic = targetDiagnostic; Scope = scope; } } internal static class ContainerDiscovery { internal const double SearchBudgetMilliseconds = 25.0; internal const int MinimumNearbyContainersBeforeBudget = 8; internal const int MaximumNearbyContainers = 128; private static readonly NearbyInspectionPolicy NearbyPolicy = new NearbyInspectionPolicy(8, 128, 25.0); private static readonly FieldInfo NetworkViewField = AccessTools.Field(typeof(Container), "m_nview"); private static readonly MethodInfo CheckAccessMethod = AccessTools.Method(typeof(Container), "CheckAccess", new Type[1] { typeof(long) }, (Type[])null); private static readonly MethodInfo CheckForChangesMethod = AccessTools.Method(typeof(Container), "CheckForChanges", (Type[])null, (Type[])null); internal static DiscoveryResult Discover(Player player, Container target, CompatibilityCatalog catalog, StorageScope scope, bool requireComplete = false, bool resourceReadOnly = false) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) List<ContainerHandle> list = new List<ContainerHandle>(); scope = scope ?? StorageScopeProvider.Resolve(player); double distance = (((Object)(object)target != (Object)null) ? ((double)Vector3.Distance(((Component)player).transform.position, ((Component)target).transform.position)) : double.PositiveInfinity); TargetDiscoveryDiagnostic targetDiscoveryDiagnostic = new TargetDiscoveryDiagnostic((Object)(object)target != (Object)null, distance, scope, (Vector3)(((Object)(object)target != (Object)null) ? ((Component)target).transform.position : default(Vector3))); if ((Object)(object)target != (Object)null && scope.Contains(((Component)target).transform.position)) { list.Add(Inspect(player, target, catalog, distance, isTarget: true, targetDiscoveryDiagnostic, resourceReadOnly)); } Stopwatch stopwatch = Stopwatch.StartNew(); Stopwatch stopwatch2 = Stopwatch.StartNew(); var array = (from container in Object.FindObjectsByType<Container>((FindObjectsInactive)0, (FindObjectsSortMode)0) where (Object)(object)container != (Object)null && (Object)(object)container != (Object)(object)target select new { Container = container, Distance = (double)Vector3.Distance(((Component)player).transform.position, ((Component)container).transform.position) } into candidate where scope.Contains(((Component)candidate.Container).transform.position) orderby candidate.Distance, ((Object)candidate.Container).GetInstanceID() select candidate).ToArray(); stopwatch2.Stop(); Stopwatch stopwatch3 = Stopwatch.StartNew(); int num = 0; string text = null; var array2 = array; foreach (var anon in array2) { double totalMilliseconds = stopwatch3.Elapsed.TotalMilliseconds; if (!requireComplete && !scope.RequiresCompleteDiscovery && !NearbyPolicy.CanInspectNext(num, totalMilliseconds)) { text = NearbyPolicy.StopReason(num, totalMilliseconds); break; } list.Add(Inspect(player, anon.Container, catalog, anon.Distance, isTarget: false, null, resourceReadOnly)); num++; } stopwatch3.Stop(); stopwatch.Stop(); bool flag = num < array.Length; if (flag && string.IsNullOrEmpty(text)) { text = "responsiveness limit reached"; } return new DiscoveryResult(list, flag, stopwatch.Elapsed.TotalMilliseconds, stopwatch2.Elapsed.TotalMilliseconds, stopwatch3.Elapsed.TotalMilliseconds, array.Length, num, text, targetDiscoveryDiagnostic, scope); } private static ContainerHandle Inspect(Player player, Container container, CompatibilityCatalog catalog, double distance, bool isTarget, TargetDiscoveryDiagnostic diagnostic, bool resourceReadOnly) { //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) object? value = NetworkViewField.GetValue(container); ZNetView val = (ZNetView)((value is ZNetView) ? value : null); bool flag = (Object)(object)val != (Object)null && val.IsValid(); ZDO val2 = (flag ? val.GetZDO() : null); string text = ((val2 != null) ? ((object)Unsafe.As<ZDOID, ZDOID>(ref val2.m_uid)/*cast due to .constrained prefix*/).ToString() : ("instance:" + ((Object)container).GetInstanceID())); Type type = ((object)container).GetType(); bool flag2 = type == typeof(Container) && type.Assembly == typeof(Container).Assembly; string failure = null; bool flag3 = !resourceReadOnly && flag2 && flag && val2 != null && TryRefreshFromNetwork(container, out failure); Inventory val3 = (flag3 ? container.GetInventory() : null); bool flag4 = flag3 && val3 != null; bool flag5 = isTarget && StorageAction.IsLocalOpenTarget(container); bool flag6 = flag4 && ((!flag5 && container.IsInUse()) || ((Object)(object)container.m_wagon != (Object)null && container.m_wagon.InUse())); string failure2 = null; bool num; if (!resourceReadOnly) { num = flag4; } else { if (!(flag2 && flag)) { goto IL_0140; } num = val2 != null; } if (!num) { goto IL_0140; } int num2 = (TryCheckAccess(player, container, out failure2) ? 1 : 0); goto IL_0141; IL_0140: num2 = 0; goto IL_0141; IL_0141: bool flag7 = (byte)num2 != 0; Inventory inventory = null; uint dataRevision = 0u; string failure3 = null; bool flag8 = resourceReadOnly && flag2 && flag && val2 != null && TryReadSerializedInventory(container, val2, out inventory, out dataRevision, out failure3); ResourceSnapshotReadPlan resourceSnapshotReadPlan = ResourceSnapshotPolicy.Evaluate(resourceReadOnly, flag4, flag7, flag6, flag8); bool captureLiveInventory = resourceSnapshotReadPlan.CaptureLiveInventory; int capacity = ((val3 != null) ? (val3.GetWidth() * val3.GetHeight()) : 0); IReadOnlyList<ItemStackSnapshot> readOnlyList2; if (!captureLiveInventory || val3 == null) { IReadOnlyList<ItemStackSnapshot> readOnlyList = Array.Empty<ItemStackSnapshot>(); readOnlyList2 = readOnlyList; } else { readOnlyList2 = InventorySnapshots.CaptureInventory(text, val3, catalog).Items; } IReadOnlyList<ItemStackSnapshot> items = readOnlyList2; bool useDetachedInventory = resourceSnapshotReadPlan.UseDetachedInventory; if (!flag8 && string.IsNullOrEmpty(failure)) { failure = failure3; } if (diagnostic != null) { diagnostic.Discovered = true; diagnostic.ObservedType = type.FullName; diagnostic.IsVanilla = flag2; diagnostic.HasNetworkView = (Object)(object)val != (Object)null; diagnostic.NetworkViewValid = flag; diagnostic.HasZdo = val2 != null; diagnostic.Refreshed = flag3; diagnostic.HasInventory = val3 != null; diagnostic.InUse = (flag4 ? new bool?(flag6) : ((bool?)null)); diagnostic.AccessGranted = (flag4 ? new bool?(flag7) : ((bool?)null)); diagnostic.RefreshFailure = failure; diagnostic.AccessFailure = failure2; } ContainerSnapshot snapshot = new ContainerSnapshot(text, distance, isTarget, flag4, captureLiveInventory, flag2, flag6, capacity, items); return new ContainerHandle(text, container, val, val2, snapshot, useDetachedInventory ? inventory : null, dataRevision, (val2 != null) ? val2.DataRevision : 0u, (ZDOID)(((??)val2?.m_uid) ?? default(ZDOID)), (ushort)((val2 != null) ? val2.OwnerRevision : 0), (val2 != null) ? val2.GetOwner() : 0, useDetachedInventory); } internal static bool TryReadSerializedInventory(Container container, ZDO zdo, out Inventory inventory, out uint dataRevision, out string failure) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown inventory = null; dataRevision = 0u; failure = null; try { uint dataRevision2 = zdo.DataRevision; byte[] byteArray = zdo.GetByteArray(ZDOVars.s_items, (byte[])null); uint dataRevision3 = zdo.DataRevision; if (dataRevision2 != dataRevision3) { failure = "container data revision changed while reading its serialized inventory"; return false; } Inventory val = new Inventory(true); if (byteArray != null) { val.Load(new ZPackage(byteArray)); } if (zdo.DataRevision != dataRevision3) { failure = "container data revision changed while decoding its serialized inventory"; return false; } if (!DetachedItemHydrator.TryHydrate(val.GetAllItems(), delegate(ItemData item) { ItemDrop val2 = (((Object)(object)item.m_dropPrefab != (Object)null) ? item.m_dropPrefab.GetComponent<ItemDrop>() : null); return (!((Object)(object)val2 != (Object)null) || val2.m_itemData == null) ? null : val2.m_itemData.m_shared; }, delegate(ItemData item, SharedData shared) { item.m_shared = shared; })) { failure = "detached inventory item metadata could not be resolved"; return false; } inventory = val; dataRevision = dataRevision3; return true; } catch (Exception ex) { failure = ex.Message; return false; } } internal static bool PersistedInventoryMatchesLive(Container container, out string failure) { failure = null; if ((Object)(object)container == (Object)null) { failure = "container disappeared before persistence verification"; return false; } try { object? value = NetworkViewField.GetValue(container); ZNetView val = (ZNetView)((value is ZNetView) ? value : null); ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null); Inventory inventory = container.GetInventory(); if (val2 == null || inventory == null || !TryReadSerializedInventory(container, val2, out var inventory2, out var _, out failure)) { if (string.IsNullOrEmpty(failure)) { failure = "container persistence state was unavailable"; } return false; } IEnumerable<string> first = InventoryRows(inventory); IEnumerable<string> second = InventoryRows(inventory2); if (!first.SequenceEqual<string>(second, StringComparer.Ordinal)) { failure = "container inventory mutation was not persisted to its network state"; return false; } return true; } catch (Exception ex) { failure = "container persistence verification failed: " + ex.GetType().Name; return false; } } private static IEnumerable<string> InventoryRows(Inventory inventory) { return from item in inventory.GetAllItems() orderby item.m_gridPos.y, item.m_gridPos.x select string.Join("\u001f", item.m_gridPos.x.ToString(CultureInfo.InvariantCulture), item.m_gridPos.y.ToString(CultureInfo.InvariantCulture), InventorySnapshots.PersistentItemKey(item), item.m_stack.ToString(CultureInfo.InvariantCulture)); } internal static bool RefreshFromNetwork(Container container) { string failure; bool num = TryRefreshFromNetwork(container, out failure); if (!num && (Object)(object)RuntimeContext.Plugin != (Object)null) { RuntimeContext.Plugin.Log.LogWarning((object)("Container refresh failed safely: " + failure)); } return num; } private static bool TryRefreshFromNetwork(Container container, out string failure) { failure = null; try { CheckForChangesMethod.Invoke(container, null); return true; } catch (Exception ex) { TargetInvocationException ex2 = ex as TargetInvocationException; failure = ((ex2 == null) ? ex.Message : (ex2.InnerException?.Message ?? ex2.Message)); return false; } } internal static bool CheckAccess(Player player, Container container) { string failure; bool num = TryCheckAccess(player, container, out failure); if (!num && !string.IsNullOrEmpty(failure) && (Object)(object)RuntimeContext.Plugin != (Object)null) { RuntimeContext.Plugin.Log.LogWarning((object)("Container access check failed safely: " + failure)); } return num; } private static bool TryCheckAccess(Player player, Container container, out string failure) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) failure = null; try { if (container.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, false)) { return false; } return (bool)CheckAccessMethod.Invoke(container, new object[1] { player.GetPlayerID() }); } catch (Exception ex) { TargetInvocationException ex2 = ex as TargetInvocationException; failure = ((ex2 == null) ? ex.Message : (ex2.InnerException?.Message ?? ex2.Message)); return false; } } } internal sealed class SessionToken { internal ZNet Network { get; } internal long LocalSession { get; } internal SessionToken(ZNet network, long localSession) { Network = network; LocalSession = localSession; } internal static bool TryCapture(out SessionToken token) { token = null; if (!RuntimeContext.Compatibility.IsCompatible || (Object)(object)ZNet.instance == (Object)null || ZDOMan.instance == null) { return false; } token = new SessionToken(ZNet.instance, ZDOMan.GetSessionID()); return true; } internal bool IsCurrent() { if (RuntimeContext.Compatibility.IsCompatible && Network == ZNet.instance && ZDOMan.instance != null) { return ZDOMan.GetSessionID() == LocalSession; } return false; } } internal sealed class CraftingIntent { internal InventoryGui Gui { get; } internal Player Player { get; } internal Recipe Recipe { get; } internal ItemData UpgradeItem { get; } internal int Quality { get; } internal int Variant { get; } internal bool MultiCrafting { get; } internal int Multiplier { get; } internal CraftingStation Station { get; } internal int StationLevel { get; } internal Vector3 PlayerPosition { get; } internal string ScopeSignature { get; } internal SessionToken Session { get; } internal CraftingIntent(InventoryGui gui, Player player, Recipe recipe, ItemData upgradeItem, int quality, int variant, bool multiCrafting, int multiplier, CraftingStation station, StorageScope scope, SessionToken session) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) Gui = gui; Player = player; Recipe = recipe; UpgradeItem = upgradeItem; Quality = quality; Variant = variant; MultiCrafting = multiCrafting; Multiplier = multiplier; Station = station; StationLevel = ((!((Object)(object)station == (Object)null)) ? station.GetLevel(true) : 0); PlayerPosition = ((Component)player).transform.position; ScopeSignature = scope?.Signature; Session = session; } } internal static class CraftingPreflightAction { private const float OwnershipTimeoutSeconds = 3f; private static readonly CraftingActionLifecycle Lifecycle = new CraftingActionLifecycle(); private static readonly MethodInfo OnCraftPressedMethod = AccessTools.Method(typeof(InventoryGui), "OnCraftPressed", Type.EmptyTypes, (Type[])null); private static readonly FieldInfo SelectedRecipeField = AccessTools.Field(typeof(InventoryGui), "m_selectedRecipe"); private static readonly Type RecipeDataPairType = AccessTools.Inner(typeof(InventoryGui), "RecipeDataPair"); private static readonly PropertyInfo SelectedRecipeProperty = AccessTools.Property(RecipeDataPairType, "Recipe"); private static readonly PropertyInfo SelectedUpgradeItemProperty = AccessTools.Property(RecipeDataPairType, "ItemData"); private static readonly FieldInfo SelectedVariantField = AccessTools.Field(typeof(InventoryGui), "m_selectedVariant"); private static readonly FieldInfo CraftRecipeField = AccessTools.Field(typeof(InventoryGui), "m_craftRecipe"); private static readonly FieldInfo CraftUpgradeItemField = AccessTools.Field(typeof(InventoryGui), "m_craftUpgradeItem"); private static readonly FieldInfo CraftVariantField = AccessTools.Field(typeof(InventoryGui), "m_craftVariant"); private static readonly FieldInfo MultiCraftingField = AccessTools.Field(typeof(InventoryGui), "m_multiCrafting"); private static readonly FieldInfo MultiCraftAmountField = AccessTools.Field(typeof(InventoryGui), "m_multiCraftAmount"); private static readonly FieldInfo TouchMultiCraftingField = AccessTools.Field(typeof(InventoryGui), "m_touchMultiCrafting"); private static readonly FieldInfo CraftTimerField = AccessTools.Field(typeof(InventoryGui), "m_craftTimer"); private static CraftingIntent _intent; private static CraftingResourcePlan _plan; private static PreparedCraftingResources _prepared; private static OwnershipBatch _ownership; private static int _generation; private static bool _resuming; internal static bool Prefix(InventoryGui gui) { if (_resuming) { return true; } if (!RuntimeContext.Compatibility.IsCompatible || (Object)(object)RuntimeContext.Plugin == (Object)null || !RuntimeContext.Plugin.CraftingFromNearbyChestsEnabled.Value) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || localPlayer.NoCostCheat() || ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGlobalKey((GlobalKeys)25))) { return true; } if (Lifecycle.IsActive) { if (_intent != null && IsSelectionCurrent(_intent, requireCraftFields: false)) { Show("Stackmaster: securing the required nearby materials."); return false; } Cancel("a newer crafting intent replaced the pending craft", notify: false); } if (ShouldUseVanillaPlayerInventory(gui)) { VanillaPlayerCraftContext.Begin(); return true; } if (!TryCaptureIntent(gui, out var intent)) { return true; } if (!NearbyResourceService.TryPlanCraftingResources(intent.Player, intent.Recipe, intent.Quality, intent.Multiplier, out var planned, out var failure)) { if (NearbyResourceService.IsTooFarFailure(failure)) { Show("Stackmaster: You're too far away from the required resources (over 100 m); nothing was consumed."); return false; } return true; } if (planned.Plan.RequiredUnits == 0) { return true; } _intent = intent; _plan = planned; ContainerHandle[] array = planned.RequiredHandles.Where((ContainerHandle handle) => !handle.NetworkView.IsOwner() || !handle.Container.IsOwner()).ToArray(); _generation = Lifecycle.Begin(array.Length != 0); if (array.Length == 0) { if (!TryPrepare(out failure)) { Cancel(failure, notify: true); return false; } return true; } Show("Stackmaster: securing the required nearby materials."); ((MonoBehaviour)RuntimeContext.Plugin).StartCoroutine(AcquireAndResume(_generation, intent.Session, array)); return false; } internal static void AfterVanillaStart(InventoryGui gui) { VanillaPlayerCraftContext.End(); if (!Lifecycle.Matches(_generation) || Lifecycle.Phase != CraftingActionPhase.Reserved || _intent == null || gui != _intent.Gui) { return; } if (_resuming) { MultiCraftingField.SetValue(gui, _intent.MultiCrafting); if (_intent.MultiCrafting) { MultiCraftAmountField.SetValue(gui, _intent.Multiplier); } } if (!IsSelectionCurrent(_intent, requireCraftFields: true) || GetCraftTimer(gui) < 0f || !Lifecycle.MarkCrafting(_generation)) { Cancel("vanilla did not start the reserved craft", notify: true); } } internal static Exception Finalizer(Exception exception) { VanillaPlayerCraftContext.End(); if (exception != null && Lifecycle.IsActive) { Cancel("craft start threw " + exception.GetType().Name, notify: true); } return exception; } internal static void Update(InventoryGui gui) { if (!Lifecycle.IsActive || _intent == null || gui != _intent.Gui) { return; } if (!RuntimeContext.Compatibility.IsCompatible || !_intent.Session.IsCurrent()) { Cancel("the network session changed during crafting", notify: false); return; } bool flag = Lifecycle.Phase == CraftingActionPhase.Crafting; if (!IsSelectionCurrent(_intent, flag)) { Cancel("the player, crafting selection, station, or storage scope changed", notify: true); } else if (flag && GetCraftTimer(gui) < 0f) { Cancel("the craft was canceled before completion", notify: false); } } internal static bool TryBeginPreparedTransaction(InventoryGui gui, Player player, Recipe recipe, int quality, int multiplier, out bool handled, out string failure) { handled = Lifecycle.IsActive; failure = null; if (!handled) { return false; } if (_intent == null || _prepared == null || gui != _intent.Gui || player != _intent.Player || recipe != _intent.Recipe || quality != _intent.Quality || multiplier != _intent.Multiplier || !IsSelectionCurrent(_intent, requireCraftFields: true) || !Lifecycle.TransferToTransaction(_generation)) { failure = "the prepared crafting intent no longer matches the finishing craft"; Cancel(failure, notify: true); return false; } PreparedCraftingResources prepared = _prepared; _prepared = null; ClearReferences(); Lifecycle.FinishTransferred(_generation); if (!NearbyResourceService.TryBeginPreparedCraftingTransaction(player, prepared, out failure)) { NearbyResourceService.ReleasePreparedCraftingResources(prepared); return false; } return true; } internal static void Cancel(string reason, bool notify) { if (Lifecycle.IsActive || _intent != null || _prepared != null || _ownership != null) { if (_intent != null && (Object)(object)_intent.Gui != (Object)null) { CraftTimerField.SetValue(_intent.Gui, -1f); } Lifecycle.Cancel(); if (_prepared != null) { NearbyResourceService.ReleasePreparedCraftingResources(_prepared); } if (_ownership != null) { OwnershipCoordinator.Cancel(_ownership, reason); } ClearReferences(); if (notify && !string.IsNullOrWhiteSpace(reason)) { Show("Stackmaster: craft canceled — " + reason + "."); } } } internal static void Shutdown(string reason) { Cancel(reason, notify: false); } private static IEnumerator AcquireAndResume(int generation, SessionToken session, ContainerHandle[] unowned) { if (!Lifecycle.Matches(generation) || !session.IsCurrent()) { yield break; } OwnershipBatch ownership; try { ownership = (_ownership = OwnershipCoordinator.Begin(unowned)); } catch (Exception ex) { Cancel("ownership request failed: " + ex.GetType().Name, notify: true); yield break; } float deadline = Time.realtimeSinceStartup + 3f; while (Lifecycle.Matches(generation) && session.IsCurrent()) { try { ownership.Refresh(); } catch (Exception ex2) { Cancel("ownership refresh failed: " + ex2.GetType().Name, notify: true); yield break; } if (ownership.IsComplete) { break; } if (Time.realtimeSinceStartup >= deadline) { ownership.Timeout(); break; } yield return null; } if (!Lifecycle.Matches(generation) || !session.IsCurrent()) { if (_ownership == ownership) { OwnershipCoordinator.Cancel(ownership, "craft acquisition became stale"); _ownership = null; } yield break; } try { ownership.Refresh(); if (!ownership.IsComplete) { ownership.Timeout(); } if (ownership.FailedContainerIds.Count != 0) { Cancel((ownership.OwnerRejectedContainerIds.Count != 0) ? "The required materials are currently in use" : "Stackmaster could not safely acquire the required materials", notify: true); yield break; } OwnershipLeaseManager.HoldForCrafting(ownership); OwnershipCoordinator.End(ownership); _ownership = null; if (!TryPrepare(out var failure)) { OwnershipLeaseManager.ReleaseBatch(ownership, "craft reservation failed"); Cancel(failure, notify: true); yield break; } if (!Lifecycle.MarkReserved(generation)) { Cancel("the ownership callback was stale", notify: true); yield break; } TouchMultiCraftingField.SetValue(_intent.Gui, _intent.MultiCrafting); SelectedVariantField.SetValue(_intent.Gui, _intent.Variant); try { _resuming = true; OnCraftPressedMethod.Invoke(_intent.Gui, null); } finally { _resuming = false; } } catch (TargetInvocationException ex3) { Cancel("vanilla craft start threw " + (ex3.InnerException ?? ex3).GetType().Name, notify: true); } catch (Exception ex4) { Cancel("ownership preparation threw " + ex4.GetType().Name, notify: true); } finally { if (_ownership == ownership) { OwnershipCoordinator.Cancel(ownership, "craft acquisition ended before reservation"); _ownership = null; } } } private static bool TryPrepare(out string failure) { failure = null; if (_intent == null || _plan == null || !IsSelectionCurrent(_intent, requireCraftFields: false)) { failure = "the crafting selection changed before reservation"; return false; } return NearbyResourceService.TryPrepareCraftingResources(_intent.Player, _plan, out _prepared, out failure); } private static bool ShouldUseVanillaPlayerInventory(InventoryGui gui) { Player localPlayer = Player.m_localPlayer; object value = SelectedRecipeField.GetValue(gui); Recipe val = (Recipe)((value == null) ? null : /*isinst with value type is only supported in some contexts*/); if ((Object)(object)localPlayer == (Object)null || value == null || (Object)(object)val == (Object)null) { return false; } object? value2 = SelectedUpgradeItemProperty.GetValue(value, null); ItemData val2 = (ItemData)((value2 is ItemData) ? value2 : null); int qualityLevel = ((val2 == null) ? 1 : (val2.m_quality + 1)); int craftMultiplier = ((val2 != null || (!ZInput.GetButton("AltPlace") && !ZInput.GetButton("JoyLStick") && !(bool)TouchMultiCraftingField.GetValue(gui))) ? 1 : Math.Max(1, (int)MultiCraftAmountField.GetValue(gui))); return NearbyResourceService.ShouldUseVanillaPlayerInventoryCraft(localPlayer, val, qualityLevel, craftMultiplier); } private static bool TryCaptureIntent(InventoryGui gui, out CraftingIntent intent) { intent = null; Player localPlayer = Player.m_localPlayer; object value = SelectedRecipeField.GetValue(gui); Recipe val = (Recipe)((value == null) ? null : /*isinst with value type is only supported in some contexts*/); if ((Object)(object)localPlayer == (Object)null || value == null || (Object)(object)val == (Object)null) { return false; } object? value2 = SelectedUpgradeItemProperty.GetValue(value, null); ItemData val2 = (ItemData)((value2 is ItemData) ? value2 : null); int quality = ((val2 == null) ? 1 : (val2.m_quality + 1)); bool flag = val2 == null && (ZInput.GetButton("AltPlace") || ZInput.GetButton("JoyLStick") || (bool)TouchMultiCraftingField.GetValue(gui)); int multiplier = ((!flag) ? 1 : Math.Max(1, (int)MultiCraftAmountField.GetValue(gui))); StorageScope storageScope = StorageScopeProvider.Resolve(localPlayer); if (storageScope == null || !SessionToken.TryCapture(out var token)) { return false; } intent = new CraftingIntent(gui, localPlayer, val, val2, quality, (int)SelectedVariantField.GetValue(gui), flag, multiplier, localPlayer.GetCurrentCraftingStation(), storageScope, token); return true; } private static bool IsSelectionCurrent(CraftingIntent intent, bool requireCraftFields) { //IL_00b9: 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_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) if (intent != null && !((Object)(object)intent.Player == (Object)null) && !((Object)(object)intent.Gui == (Object)null) && Player.m_localPlayer == intent.Player && !((Character)intent.Player).IsDead() && !((Character)intent.Player).IsTeleporting() && !((Character)intent.Player).InCutscene() && intent.Player.GetCurrentCraftingStation() == intent.Station && (!((Object)(object)intent.Station != (Object)null) || (intent.Station.CheckUsable(intent.Player, false) && intent.Station.GetLevel(true) == intent.StationLevel))) { Vector3 val = ((Component)intent.Player).transform.position - intent.PlayerPosition; if (!(((Vector3)(ref val)).sqrMagnitude > 0.0025f)) { object value = SelectedRecipeField.GetValue(intent.Gui); if (value == null || SelectedRecipeProperty.GetValue(value, null) != intent.Recipe || SelectedUpgradeItemProperty.GetValue(value, null) != intent.UpgradeItem || (int)SelectedVariantField.GetValue(intent.Gui) != intent.Variant) { return false; } StorageScope storageScope = StorageScopeProvider.Resolve(intent.Player); if (storageScope == null || !string.Equals(storageScope.Signature, intent.ScopeSignature, StringComparison.Ordinal)) { return false; } if (!requireCraftFields) { return true; } if (CraftRecipeField.GetValue(intent.Gui) == intent.Recipe && CraftUpgradeItemField.GetValue(intent.Gui) == intent.UpgradeItem && (int)CraftVariantField.GetValue(intent.Gui) == intent.Variant && (bool)MultiCraftingField.GetValue(intent.Gui) == intent.MultiCrafting) { if (intent.MultiCrafting) { return (int)MultiCraftAmountField.GetValue(intent.Gui) == intent.Multiplier; } return true; } return false; } } return false; } private static float GetCraftTimer(InventoryGui gui) { return (float)CraftTimerField.GetValue(gui); } private static void ClearReferences() { _intent = null; _plan = null; _prepared = null; _ownership = null; } private static void Show(string message) { MessageHud instance = MessageHud.instance; if (instance != null) { instance.ShowMessage((MessageType)2, message, 0, (Sprite)null, false, true); } } } internal static class DistanceDiagnosticTracker { private sealed class TrackedChest { internal string Id { get; } internal ZDOID ZdoId { get; } internal Vector3 Position { get; } internal Container OriginalContainer { get; } internal ZNetView OriginalView { get; } internal ZDO OriginalZdo { get; } internal TrackedChest(string id, ZDOID zdoId, Vector3 position, Container originalContainer, ZNetView originalView, ZDO originalZdo) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) Id = id; ZdoId = zdoId; Position = position; OriginalContainer = originalContainer; OriginalView = originalView; OriginalZdo = originalZdo; } } private const int MaximumTrackedChests = 16; private const float ObservationIntervalSeconds = 0.5f; private static readonly Dictionary<string, TrackedChest> Tracked = new Dictionary<string, TrackedChest>(StringComparer.Ordinal); private static readonly BoundedDiagnosticTransitionTracker Transitions = new BoundedDiagnosticTransitionTracker(16); private static float _nextObservationTime; private static bool _capacityLogged; private static bool _failureLogged; internal static void TrackRequiredHandles(IEnumerable<ContainerHandle> handles) { //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) if (handles == null) { return; } try { foreach (ContainerHandle item in handles.Where((ContainerHandle item) => item != null)) { if (Tracked.ContainsKey(item.Id)) { continue; } if (Tracked.Count >= 16) { if (!_capacityLogged && (Object)(object)RuntimeContext.Plugin != (Object)null) { _capacityLogged = true; RuntimeContext.Plugin.Log.LogWarning((object)"Distance diagnostic registry reached its 16-container session limit; existing tracked sources remain active."); } break; } ZDO originalZdo = (((Object)(object)item.NetworkView != (Object)null && item.NetworkView.IsValid()) ? item.NetworkView.GetZDO() : null); Vector3 position = (((Object)(object)item.Container != (Object)null) ? ((Component)item.Container).transform.position : Vector3.zero); Tracked.Add(item.Id, new TrackedChest(item.Id, item.ResourceZdoId, position, item.Container, item.NetworkView, originalZdo)); } } catch (Exception exception) { ReportFailureOnce(exception); } } internal static void ObserveCapture(Player player, StorageScope scope, IReadOnlyList<ContainerHandle> includedSources) { //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) try { if (Tracked.Count == 0 || (Object)(object)player == (Object)null || Time.realtimeSinceStartup < _nextObservationTime) { return; } _nextObservationTime = Time.realtimeSinceStartup + 0.5f; Dictionary<string, ContainerHandle> dictionary = (includedSources ?? Array.Empty<ContainerHandle>()).Where((ContainerHandle handle) => handle != null).GroupBy<ContainerHandle, string>((ContainerHandle handle) => handle.Id, StringComparer.Ordinal).ToDictionary<IGrouping<string, ContainerHandle>, string, ContainerHandle>((IGrouping<string, ContainerHandle> group) => group.Key, (IGrouping<string, ContainerHandle> group) => group.First(), StringComparer.Ordinal); TrackedChest[] array = Tracked.Values.ToArray(); foreach (TrackedChest trackedChest in array) { Container val = ResolveSceneContainer(trackedChest); ZNetView val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<ZNetView>() : null); bool flag = (Object)(object)val2 != (Object)null && val2.IsValid(); ZDO val3 = (flag ? val2.GetZDO() : null); ZDO val4 = ((ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(trackedChest.ZdoId) : null); ZDO val5 = val4 ?? val3; ContainerHandle value; bool flag2 = dictionary.TryGetValue(trackedChest.Id, out value); int sourceUnits = ((flag2 && value.ResourceInventory != null) ? (from item in value.ResourceInventory.GetAllItems() where item != null select item).Sum((ItemData item) => item.m_stack) : 0); bool scopeContainsKnownPosition = scope?.Contains(trackedChest.Position) ?? false; ContainerStreamDiagnosticState containerStreamDiagnosticState = new ContainerStreamDiagnosticState((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null && ((Component)val).gameObject.activeInHierarchy, val == trackedChest.OriginalContainer, (Object)(object)val2 != (Object)null, flag, val2 == trackedChest.OriginalView, val3 != null, val4 != null, val3 != null && val4 != null && val3 == val4, val4 != null && trackedChest.OriginalZdo != null && val4 == trackedChest.OriginalZdo, (val5 != null) ? val5.GetOwner() : 0, (ushort)((val5 != null) ? val5.OwnerRevision : 0), (val5 != null) ? val5.DataRevision : 0u, scopeContainsKnownPosition, flag2, sourceUnits); DiagnosticEmissionDecision diagnosticEmissionDecision = Transitions.Observe(trackedChest.Id, containerStreamDiagnosticState.Fingerprint); if (diagnosticEmissionDecision != DiagnosticEmissionDecision.SuppressDuplicate && diagnosticEmissionDecision != DiagnosticEmissionDecision.SuppressCapacity) { Plugin plugin = RuntimeContext.Plugin; if (plugin != null) { plugin.Log.LogWarning((object)("Nearby-resource distance diagnostic transition: containerId=" + trackedChest.Id + " transition=" + diagnosticEmissionDecision.ToString() + " distance=" + Vector3.Distance(((Component)player).transform.position, trackedChest.Position).ToString("0.0", CultureInfo.InvariantCulture) + " scope=" + ScopeSummary(scope) + " scopeContainsKnownPosition=" + containerStreamDiagnosticState.ScopeContainsKnownPosition + " sourceIncluded=" + containerStreamDiagnosticState.SourceIncluded + " sourceUnits=" + containerStreamDiagnosticState.SourceUnits.ToString(CultureInfo.InvariantCulture) + " containerLoaded=" + containerStreamDiagnosticState.ContainerLoaded + " capturedContainerRef=" + containerStreamDiagnosticState.CapturedContainerReferenceMatches + " nviewPresent=" + containerStreamDiagnosticState.NetworkViewPresent + " nviewValid=" + containerStreamDiagnosticState.NetworkViewValid + " capturedNviewRef=" + containerStreamDiagnosticState.CapturedNetworkViewReferenceMatches + " sceneZdo=" + containerStreamDiagnosticState.SceneZdoPresent + " managerZdo=" + containerStreamDiagnosticState.ManagerZdoPresent + " sceneManagerZdoRef=" + containerStreamDiagnosticState.SceneAndManagerZdoReferenceMatch + " capturedZdoRef=" + containerStreamDiagnosticState.CapturedZdoReferenceMatches + " owner=" + containerStreamDiagnosticState.Owner.ToString(CultureInfo.InvariantCulture) + " ownerRevision=" + containerStreamDiagnosticState.OwnerRevision.ToString(CultureInfo.InvariantCulture) + " dataRevision=" + containerStreamDiagnosticState.DataRevision.ToString(CultureInfo.InvariantCulture) + ".")); } } } } catch (Exception exception) { ReportFailureOnce(exception); } } internal static void ResetSession() { Tracked.Clear(); Transitions.Reset(); _nextObservationTime = 0f; _capacityLogged = false; _failureLogged = false; } private static Container ResolveSceneContainer(TrackedChest tracked) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)tracked.OriginalContainer != (Object)null && (Object)(object)((Component)tracked.OriginalContainer).gameObject != (Object)null && ((Component)tracked.OriginalContainer).gameObject.activeInHierarchy) { return tracked.OriginalContainer; } Container[] array = Object.FindObjectsByType<Container>((FindObjectsInactive)0, (FindObjectsSortMode)0); foreach (Container val in array) { if (!((Object)(object)val == (Object)null)) { ZNetView component = ((Component)val).GetComponent<ZNetView>(); ZDO val2 = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null); if (val2 != null && ((ZDOID)(ref val2.m_uid)).Equals(tracked.ZdoId)) { return val; } } } return null; } private static string ScopeSummary(StorageScope scope) { if (scope == null || scope.Plan == null) { return "unavailable"; } IReadOnlyList<WorkbenchZone> connectedZones = scope.Plan.ConnectedZones; if (scope.Kind != StorageScopeKind.WorkbenchMesh || connectedZones.Count == 0) { return scope.Kind.ToString(); } return scope.Kind.ToString() + "(zones=" + connectedZones.Count.ToString(CultureInfo.InvariantCulture) + ",first=" + connectedZones[0].Id + ",last=" + connectedZones[connectedZones.Count - 1].Id + ")"; } private static void ReportFailureOnce(Exception exception) { if (_failureLogged) { return; } _failureLogged = true; try { Plugin plugin = RuntimeContext.Plugin; if (plugin != null) { plugin.Log.LogWarning((object)("Distance diagnostics failed open without changing gameplay: " + exception.GetType().Name + ".")); } } catch { } } } internal static class OwnershipDistanceDiagnosticLog { internal static void LogActionSelection(Player player, StorageScope scope, IEnumerable<ContainerHandle> handles) { if (handles == null) { return; } RunFailOpen(delegate { DistanceDiagnosticTracker.TrackRequiredHandles(handles); foreach (ContainerHandle item in handles.Where((ContainerHandle item) => item != null)) { LogSnapshot("action-selection", item, player, scope, 0f, OwnershipLeaseManager.DescribeLifecycle(item.Id), null, includeScope: true, null); } }); } internal static void LogImmediateResult(ContainerHandle handle, string reason) { if (handle != null) { RunFailOpen(delegate { LogResult(handle, Time.realtimeSinceStartup, OwnershipLeaseManager.DescribeLifecycle(handle.Id), reason); }); } } internal static float CurrentTimeOrZero() { float current = 0f; RunFailOpen(delegate { current = Time.realtimeSinceStartup; }); return current; } internal static string DescribeLifecycleOrFallback(ContainerHandle handle, string suffix = "") { string description = "diagnostic-unavailable" + (suffix ?? string.Empty); if (handle == null) { return description; } RunFailOpen(delegate { description = OwnershipLeaseManager.DescribeLifecycle(handle.Id) + (suffix ?? string.Empty); }); return description; } internal static void LogTransition(ContainerHandle handle, float startedAt, string lifecyclePath, BoundedDiagnosticTransitionTracker transitions, string phase) { if (handle == null || transitions == null) { return; } RunFailOpen(delegate { OwnershipDiagnosticState ownershipDiagnosticState = Capture(handle); DiagnosticEmissionDecision diagnosticEmissionDecision = transitions.Observe(handle.Id, ownershipDiagnosticState.Fingerprint); if (diagnosticEmissionDecision != DiagnosticEmissionDecision.SuppressDuplicate && diagnosticEmissionDecision != DiagnosticEmissionDecision.SuppressCapacity) { LogSnapshot(phase, handle, Player.m_localPlayer, null, Time.realtimeSinceStartup - startedAt, lifecyclePath, ownershipDiagnosticState, includeScope: false, diagnosticEmissionDecision.ToString()); } }); } internal static void LogResult(ContainerHandle handle, float startedAt, string lifecyclePath, string result) { if (handle != null) { RunFailOpen(delegate { LogSnapshot("final", handle, Player.m_localPlayer, null, Time.realtimeSinceStartup - startedAt, lifecyclePath, Capture(handle), includeScope: false, result); }); } } private static OwnershipDiagnosticState Capture(ContainerHandle handle) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) Container container = handle.Container; bool flag = (Object)(object)container != (Object)null && (Object)(object)((Component)container).gameObject != (Object)null && ((Component)container).gameObject.activeInHierarchy; ZNetView val = (flag ? ((Component)container).GetComponent<ZNetView>() : null); bool flag2 = (Object)(object)val != (Object)null && val.IsValid(); ZDO val2 = (flag2 ? val.GetZDO() : null); ZDO val3 = ((ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(handle.ResourceZdoId) : null); ZDO val4 = val3 ?? val2; return new OwnershipDiagnosticState((val4 != null) ? val4.GetOwner() : 0, (ushort)((val4 != null) ? val4.OwnerRevision : 0), (val4 != null) ? val4.DataRevision : 0u, (Object)(object)val != (Object)null && val.HasOwner(), (Object)(object)val != (Object)null && val.IsOwner(), flag && container.IsOwner(), flag, flag && container == handle.Container, flag2, val == handle.NetworkView, val3 != null, val2 != null, val4 != null && string.Equals(((object)Unsafe.As<ZDOID, ZDOID>(ref val4.m_uid)/*cast due to .constrained prefix*/).ToString(), handle.Id, StringComparison.Ordinal), val4 != null && handle.CapturedZdo != null && val4 == handle.CapturedZdo, val2 != null && val3 != null && val2 == val3); } private static void RunFailOpen(Action action) { if (DiagnosticFailureBoundary.TryRun(action, out Exception failure)) { return; } try { Plugin plugin = RuntimeContext.Plugin; if (plugin != null) { plugin.Log.LogWarning((object)("Ownership diagnostics failed open without changing the action: " + failure.GetType().Name + ".")); } } catch { } } private static void LogSnapshot(string phase, ContainerHandle handle, Player player, StorageScope scope, float elapsed, string lifecyclePath, OwnershipDiagnosticState suppliedState, bool includeScope, string result) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) try { OwnershipDiagnosticState ownershipDiagnosticState = suppliedState ?? Capture(handle); long num = ((ZDOMan.instance != null) ? ZDOMan.GetSessionID() : 0); float num2 = (((Object)(object)player != (Object)null && (Object)(object)handle.Container != (Object)null) ? Vector3.Distance(((Component)player).transform.position, ((Component)handle.Container).transform.position) : ((handle.Snapshot != null) ? ((float)handle.Snapshot.Distance) : (-1f))); Plugin plugin = RuntimeContext.Plugin; if (plugin != null) { plugin.Log.LogWarning((object)("Nearby-resource ownership diagnostic: phase=" + phase + " lifecycle=" + lifecyclePath + " containerId=" + handle.Id + " elapsedMs=" + (elapsed * 1000f).ToString("0", CultureInfo.InvariantCulture) + " distance=" + num2.ToString("0.0", CultureInfo.InvariantCulture) + " localSession=" + num.ToString(CultureInfo.InvariantCulture) + " capturedOwner=" + handle.ResourceOwner.ToString(CultureInfo.InvariantCulture) + " capturedOwnerRevision=" + handle.ResourceOwnerRevision.ToString(CultureInfo.InvariantCulture) + " owner=" + ownershipDiagnosticState.Owner.ToString(CultureInfo.InvariantCulture) + " ownerRevision=" + ownershipDiagnosticState.OwnerRevision.ToString(CultureInfo.InvariantCulture) + " dataRevision=" + ownershipDiagnosticState.DataRevision.ToString(CultureInfo.InvariantCulture) + " hasOwner=" + ownershipDiagnosticState.HasOwner + " nviewIsOwner=" + ownershipDiagnosticState.NetworkViewIsOwner + " containerIsOwner=" + ownershipDiagnosticState.ContainerIsOwner + " containerLoaded=" + ownershipDiagnosticState.ContainerLoaded + " capturedContainerRef=" + ownershipDiagnosticState.CapturedContainerReferenceMatches + " nviewValid=" + ownershipDiagnosticState.NetworkViewValid + " capturedNviewRef=" + ownershipDiagnosticState.CapturedNetworkViewReferenceMatches + " managerZdo=" + ownershipDiagnosticState.ManagerZdoPresent + " sceneZdo=" + ownershipDiagnosticState.SceneZdoPresent + " zdoIdentity=" + ownershipDiagnosticState.ZdoIdentityMatches + " capturedZdoRef=" + ownershipDiagnosticState.CapturedZdoReferenceMatches + " sceneManagerZdoRef=" + ownershipDiagnosticState.SceneAndManagerZdoReferenceMatch + (includeScope ? (" scope=" + ((scope != null) ? scope.Description : "unavailable")) : string.Empty) + ((!string.IsNullOrEmpty(result)) ? (" result=" + result) : string.Empty) + ".")); } } catch (Exception ex) { try { Plugin plugin2 = RuntimeContext.Plugin; if (plugin2 != null) { plugin2.Log.LogWarning((object)("Ownership diagnostics failed open without changing the action: " + ex.GetType().Name + ".")); } } catch { } } } } internal static class ExpeditionMaterialVisuals { internal static bool TryAllocate(Player player, ProtectionState protection, out IReadOnlyDictionary<ItemData, int> allocations) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) allocations = new Dictionary<ItemData, int>(); try { if ((Object)(object)player == (Object)null || protection == null) { return false; } Inventory inventory = ((Humanoid)player).GetInventory(); InventorySnapshot snapshot = InventorySnapshots.CapturePlayer(player, protection, new CompatibilityCatalog()); if (!TryAllocateSlots(player, snapshot, out var allocations2)) { return false; } Dictionary<ItemData, int> dictionary = new Dictionary<ItemData, int>(); foreach (ReservationSlotAllocation item in allocations2) { Vector2i val = InventorySnapshots.PositionForSlot(inventory, item.PlayerSlot); ItemData itemAt = inventory.GetItemAt(val.x, val.y); if (itemAt != null) { dictionary[itemAt] = item.Quantity; } } allocations = dictionary; return true; } catch (Exception ex) { Plugin plugin = RuntimeContext.Plugin; if (plugin != null) { plugin.Log.LogWarning((object)("Expedition material highlights were skipped safely: " + ex.GetType().Name)); } allocations = new Dictionary<ItemData, int>(); return false; } } internal static bool TryAllocateSlots(Player player, InventorySnapshot snapshot, out IReadOnlyList<ReservationSlotAllocation> allocations) { allocations = Array.Empty<ReservationSlotAllocation>(); if ((Object)(object)player == (Object)null || snapshot == null || !ExpeditionReservations.TryGetAggregateRequirements(player, out var requirements)) { return false; } List<ReservationSlotAllocation> list = new List<ReservationSlotAllocation>(); Dictionary<int, int> dictionary = snapshot.Items.ToDictionary((ItemStackSnapshot item) => item.Slot, (ItemStackSnapshot item) => item.Quantity); foreach (ResourceRequirement requirement in requirements.OrderBy<ResourceRequirement, string>((ResourceRequirement item) => item.ItemName, StringComparer.Ordinal).ThenBy((ResourceRequirement item) => item.Quality)) { int num = requirement.Quantity; foreach (ItemStackSnapshot item in from item in snapshot.Items where !item.IsFixed && string.Equals(item.ResourceItemName, requirement.ItemName, StringComparison.Ordinal) && (requirement.Quality < 0 || item.ResourceQuality == requirement.Quality) orderby item.Slot select item) { if (num == 0) { break; } int num2 = Math.Min(dictionary[item.Slot], num); if (num2 > 0) { list.Add(new ReservationSlotAllocation(item.Slot, item.CompatibilityKey, item.ResourceItemName, item.ResourceQuality, num2)); dictionary[item.Slot] -= num2; num -= num2; } } } allocations = list; return true; } } internal static class ExpeditionReservationBuildUi { private const string RootName = "StackmasterBuildMenuReservations"; private static readonly FieldInfo TabContainerField = typeof(BuildUi).GetField("m_tabContainer", BindingFlags.Instance | BindingFlags.NonPublic); private static ReservationStripView _view; private static BuildUi _owner; private static Player _player; private static RectTransform _menuRect; private static RectTransform _hostRect; private static string _digest; private static bool _refreshRequested = true; private static bool _disabled; private static bool _failureLogged; internal static void Tick() { if (_disabled) { return; } try { Player localPlayer = Player.m_localPlayer; Hud instance = Hud.instance; BuildUi val = (((Object)(object)instance != (Object)null) ? instance.m_buildUi : null); if ((Object)(object)localPlayer == (Object)null || (Object)(object)val == (Object)null || !ReservationCardInteractions.HasActiveHammer(localPlayer) || !Hud.IsPieceSelectionVisible() || !((Component)val).gameObject.activeInHierarchy) { Hide(); return; } if (_owner != val || _player != localPlayer || _view == null || !_view.IsAlive || (Object)(object)_menuRect == (Object)null || (Object)(object)_hostRect == (Object)null) { Attach(val, localPlayer); } if (!_disabled && _view != null && _view.IsAlive) { _view.Root.transform.SetAsLastSibling(); RefreshVisible(localPlayer); UpdateGeometry(_menuRect, _hostRect); } } catch (Exception exception) { Disable("The optional build-menu reservation row stopped safely", exception); } } internal static void RequestRefresh() { _refreshRequested = true; RefreshVisible(Player.m_localPlayer); } internal static void RefreshVisible(Player player) { if (_view != null && !_view.IsAlive) { Destroy(); } else { if (_disabled || _view == null || (Object)(object)_owner == (Object)null || (Object)(object)player == (Object)null || player != Player.m_localPlayer || player != _player || (((Object)(object)Hud.instance != (Object)null) ? Hud.instance.m_buildUi : null) != _owner) { return; } if (!((Component)_owner).gameObject.activeInHierarchy || !Hud.IsPieceSelectionVisible() || !ReservationCardInteractions.HasActiveHammer(player)) { Hide(); return; } if (!ExpeditionReservations.TryGetRecords(player, out var records) || records.Count == 0) { _digest = string.Empty; if (!_view.SetVisible(visible: false)) { Destroy(); } return; } string text = Digest(records); if (_refreshRequested || !string.Equals(text, _digest, StringComparison.Ordinal)) { _view.Render(records, SelectPiece, ReleaseOne); _digest = text; _refreshRequested = false; } if (!_view.SetVisible(visible: true)) { Destroy(); } } } internal static void RearmSession() { Destroy(); _disabled = false; _failureLogged = false; _refreshRequested = true; } internal static void Destroy() { ReservationStripView view = _view; _view = null; _owner = null; _player = null; _menuRect = null; _hostRect = null; _digest = null; _refreshRequested = true; view?.Destroy(); } private static void Attach(BuildUi buildUi, Player player) { //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) Destroy(); CompatibilityResult compatibilityResult = CompatibilityGate.EvaluateBuildMenuReservationUi(); if (!compatibilityResult.IsCompatible) { Disable("The optional build-menu reservation row is unavailable: " + compatibilityResult.Reason); return; } object? obj = TabContainerField?.GetValue(buildUi); RectTransform val = (RectTransform)((obj is RectTransform) ? obj : null); if ((Object)(object)val == (Object)null) { throw new InvalidOperationException("BuildUi tab container is unavailable."); } Transform parent = ((Component)buildUi).transform.parent; RectTransform val2 = (RectTransform)(object)((parent is RectTransform) ? parent : null); if ((Object)(object)val2 == (Object)null) { throw new InvalidOperationException("BuildUi parent UI root is unavailable."); } Transform val3 = ((Transform)val2).Find("StackmasterBuildMenuReservations"); if ((Object)(object)val3 != (Object)null) { ((Component)val3).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)val3).gameObject); } Transform val4 = ((Component)buildUi).transform.Find("StackmasterBuildMenuReservations"); if ((Object)(object)val4 != (Object)null) { ((Component)val4).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)val4).gameObject); } TMP_Text textTemplate = ((IEnumerable<TMP_Text>)((Component)buildUi).GetComponentsInChildren<TMP_Text>(true)).FirstOrDefault((Func<TMP_Text, bool>)((TMP_Text candidate) => (Object)(object)candidate != (Object)null && (Object)(object)candidate.font != (Object)null)); _view = new ReservationStripView((Transform)(object)val2, "StackmasterBuildMenuReservations", textTemplate); _owner = buildUi; _player = player; _menuRect = val; _hostRect = val2; RectTransform rootRect = _view.RootRect; Vector2 anchorMin = (_view.RootRect.anchorMax = val2.pivot); rootRect.anchorMin = anchorMin; _view.RootRect.pivot = Vector2.zero; RectTransform rootRect2 = _view.RootRect; Rect rect = val.rect; rootRect2.sizeDelta = new Vector2(((Rect)(ref rect)).width, 54f); _view.Root.transform.SetAsLastSibling(); _refreshRequested = true; } private static void UpdateGeometry(RectTransform menuRect, RectTransform hostRect) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: 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_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) if (_view == null || !_view.IsAlive || (Object)(object)menuRect == (Object)null || (Object)(object)hostRect == (Object)null) { if (_view != null && !_view.IsAlive) { Destroy(); } return; } Vector3[] array = (Vector3[])(object)new Vector3[4]; menuRect.GetWorldCorners(array); float num = float.PositiveInfinity; float num2 = float.NegativeInfinity; float num3 = float.NegativeInfinity; Vector3[] array2 = array; foreach (Vector3 val in array2) { Vector3 val2 = ((Transform)hostRect).InverseTransformPoint(val); num = Mathf.Min(num, val2.x); num2 = Mathf.Max(num2, val2.x); num3 = Mathf.Max(num3, val2.y); } Vector3[] array3 = (Vector3[])(object)new Vector3[4]; hostRect.GetWorldCorners(array3); float num4 = Mathf.Abs(((Transform)hostRect).lossyScale.x); float num5 = Mathf.Abs(((Transform)hostRect).lossyScale.y); if (num4 <= 0.0001f || num5 <= 0.0001f) { throw new InvalidOperationException("The build-menu canvas root had an invalid UI scale."); } Rect safeArea = Screen.safeArea; Rect rect = hostRect.rect; float safeLeft = ((Rect)(ref rect)).xMin + (((Rect)(ref safeArea)).xMin - array3[0].x) / num4; float safeRight = ((Rect)(ref rect)).xMin + (((Rect)(ref safeArea)).xMax - array3[0].x) / num4; float safeTop = ((Rect)(ref rect)).yMin + (((Rect)(ref safeArea)).yMax - array3[0].y) / num5; BuildMenuReservationLayout buildMenuReservationLayout = BuildMenuReservationLayoutPlanner.Plan(num, num2, num3, safeLeft, safeRight, safeTop); if (!buildMenuReservationLayout.Visible) { if (!_view.SetVisible(visible: false)) { Destroy(); } } else { _view.RootRect.anchoredPosition = new Vector2(buildMenuReservationLayout.Left, buildMenuReservationLayout.Bottom); _view.RootRect.sizeDelta = new Vector2(buildMenuReservationLayout.Width, buildMenuReservationLayout.Height); ReservationStripLayout reservationStripLayout = ReservationStripLayoutPlanner.Plan(buildMenuReservationLayout.Width, 1f, _view.PreferredLabelWidth); _view.ApplyInnerGeometry(buildMenuReservationLayout.Width, reservationStripLayout.LabelWidth, reservationStripLayout.ViewportLeft, reservationStripLayout.ViewportRight); } } private static void SelectPiece(string pieceKey) { if (ReservationCardInteractions.SelectFromBuildMenu(pieceKey, _owner)) { Hide(); } } private static void ReleaseOne(string pieceKey, string visibleName) { try { ReservationCardInteractions.ReleaseOne(pieceKey, visibleName); } catch (Exception exception) { Disable("A build-menu reservation card could not be used safely", exception); } } private static void Hide() { if (_view != null && !_view.SetVisible(visible: false)) { Destroy(); return; } _digest = null; _refreshRequested = true; } private static string Digest(IEnumerable<ExpeditionReservationRecord> records) { StringBuilder stringBuilder = new StringBuilder(); foreach (ExpeditionReservationRecord item in records.OrderBy<ExpeditionReservationRecord, string>((ExpeditionReservationRecord value) => value.PieceKey, StringComparer.Ordinal)) { stringBuilder.Append(item.PieceKey).Append('\u001f').Append(item.DisplayName) .Append('\u001f') .Append(item.Count) .Append('\u001e'); } return stringBuilder.ToString(); } private static void Disable(string message, Exception exception = null) { Destroy(); _disabled = true; if (!_failureLogged && !((Object)(object)RuntimeContext.Plugin == (Object)null)) { _failureLogged = true; RuntimeContext.Plugin.Log.LogWarning((object)((exception == null) ? message : (message + ": " + exception))); } } } internal enum SuccessfulBuildReservationResult { NotApplicable, NotReserved, Consumed, PersistenceFailed } internal static class ExpeditionReservations { private const string CloneSuffix = "(Clone)"; private const string PiecePrefix = "prefab:"; private static ExpeditionReservationState _state = new ExpeditionReservationState(); private static string _loadedKey; private static bool _storageHealthy = true; private static bool _writesHealthy = true; private static bool _failureLogged; private static bool _buildConsumeWarningShown; internal static void Initialize() { _state = new ExpeditionReservationState(); _loadedKey = null; _storageHealthy = true; _writesHealthy = true; _failureLogged = false; _buildConsumeWarningShown = false; } internal static void Shutdown() { _state = new ExpeditionReservationState(); _loadedKey = null; _storageHealthy = false; _writesHealthy = false; } internal static bool CanCommitQuickGrab(Player player) { try { return _storageHealthy && _writesHealthy && (Object)(object)player != (Object)null && EnsureLoaded(player); } catch (Exception ex) { DisableStorage("Expedition reservations could not be prepared and were disabled for this session: " + ex.GetType().Name); return false; } } internal static bool CanRecordQuickGrab(Player player, string pieceKey, string displayName, IReadOnlyList<ResourceRequirement> requirements, out string failure) { failure = null; try { if (!CanCommitQuickGrab(player) || string.IsNullOrEmpty(pieceKey) || string.IsNullOrEmpty(displayName) || requirements == null) { failure = "reservations are unavailable"; return false; } if (ExpeditionReservationPersistence.TryAddDurably(_state, pieceKey, displayName, requirements, (string payload) => true, out ExpeditionReservationState _, out ExpeditionReservationPersistenceResult result)) { return true; } failure = FailureFor(result); return false; } catch (InvalidOperationException) { failure = "the safe reservation storage limit was reached"; return false; } catch (Exception ex2) { DisableStorage("Expedition reservations could not be validated and were disabled for this session: " + ex2.GetType().Name); failure = "reservations are unavailable"; return false; } } internal static bool TryAddQuickGrabReservation(Player player, Piece piece, string pieceKey, string displayName, IReadOnlyList<ResourceRequirement> requirements, out bool reservationCreated, out int committedCount, out string failure) { reservationCreated = false; committedCount = 0; failure = null; try { if ((Object)(object)player == (Object)null || (Object)(object)piece == (Object)null || string.IsNullOrEmpty(pieceKey) || string.IsNullOrEmpty(displayName) || requirements == null) { failure = "the material request could not be identified safely"; return false; } if (IsMaterialOnlyQuickGrabPiece(piece, pieceKey, displayName)) { return true; } if (!_storageHealthy || !_writesHealthy || !EnsureLoaded(player)) { failure = "reservations are unavailable"; return false; } string previousPayload = _state.Serialize(); Exception persistenceFailure = null; if (!ExpeditionReservationPersistence.TryAddDurably(_state, pieceKey, displayName, requirements, delegate(string payload) { try { return AtomicReservationFileStore.TryWrite(_loadedKey, previousPayload, payload); } catch (Exception ex4) { persistenceFailure = ex4; _writesHealthy = false; return false; } }, out ExpeditionReservationState committed, out ExpeditionReservationPersistenceResult result)) { failure = FailureFor(result); if (persistenceFailure != null) { LogFailureOnce("Quick Grab reservation could not be saved and was left unchanged: " + persistenceFailure.GetType().Name); } return false; } _state = committed; reservationCreated = true; committedCount = (from record in committed.Records where string.Equals(record.PieceKey, pieceKey, StringComparison.Ordinal) select record.Count).Single(); try { InventoryIntegration.RequestExpeditionRefresh(); } catch (Exception ex) { Plugin plugin = RuntimeContext.Plugin; if (plugin != null) { plugin.Log.LogWarning((object)("Quick Grab reservation UI refresh failed after save: " + ex.GetType().Name)); } } return true; } catch (InvalidOperationException) { failure = "the safe reservation storage limit was reached"; return false;