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 VHModpackFix v1.1.24
VHModpackFix.dll
Decompiled 3 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.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using TMPro; using UnityEngine; 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("VHModpackFix")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.24.0")] [assembly: AssemblyInformationalVersion("1.1.24")] [assembly: AssemblyProduct("VHModpackFix")] [assembly: AssemblyTitle("VHModpackFix")] [assembly: AssemblyVersion("1.1.24.0")] namespace Obelisk.VHModpackFix; internal static class AAABuildMenuLifecycleFixes { private const string PluginGuid = "Azumatt.AAABuildMenu"; private const string EnhancedMenuTypeName = "AAABuildMenu.EnhancedBuildMenu"; private const string PatchesTypeName = "AAABuildMenu.EnhancedBuildMenuPatches"; private const string PinnedTrackerTypeName = "AAABuildMenu.PinnedRecipeTracker"; private static readonly string[] HudReferenceFields = new string[29] { "_searchBarObject", "_searchInputField", "_scrollRect", "_clearSearchButton", "_filterButtonRow", "_allButton", "_canCraftButton", "_missingMaterialsButton", "_favoritesButton", "_recentButton", "_sortButton", "_sortButtonText", "_matchCountText", "_materialsButton", "_materialsDropdown", "_materialsSearchField", "_searchDebounceCoroutine", "_uiFont", "_tooltipPrefab", "_buttonSprite", "_hud", "_resizeHandle", "_moveHandle", "_vanillaButtonSprite", "SelectedPiece", "_materialsListContent", "_favoriteBorderSprite", "_allSprites", "_clickSfxPrefab" }; private static readonly string[] HudCollectionFields = new string[7] { "_selectedMaterials", "_favoriteStars", "_favoriteBorders", "_pinIndicators", "_prefabNameCache", "_categoryMasters", "_spriteCache" }; private static ConfigEntry<bool> _enabled; private static Type _enhancedMenuType; private static Type _patchesType; private static Type _pinnedTrackerType; private static FieldInfo _initializedField; private static FieldInfo _hudField; internal static void Init(Harmony harmony, ConfigFile config) { //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Expected O, but got Unknown //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Expected O, but got Unknown _enabled = ConfigLayout.Bind(config, "AAABuildMenu", "Restore enhanced menu after world re-entry", defaultValue: true, "Clears only AAABuildMenu's HUD-bound static state when Valheim destroys a world HUD. Search, filters, the expanded grid, pin tracker, and controls are then created for the next world HUD. Favorites and saved settings are preserved. Restart Valheim after changing this setting.", "AAABuildMenu compatibility"); if (!_enabled.Value || !Chainloader.PluginInfos.ContainsKey("Azumatt.AAABuildMenu")) { return; } _enhancedMenuType = AccessTools.TypeByName("AAABuildMenu.EnhancedBuildMenu"); _patchesType = AccessTools.TypeByName("AAABuildMenu.EnhancedBuildMenuPatches"); _pinnedTrackerType = AccessTools.TypeByName("AAABuildMenu.PinnedRecipeTracker"); if (_enhancedMenuType == null) { VHModpackFixPlugin.LogWarning("AAABuildMenu lifecycle type 'AAABuildMenu.EnhancedBuildMenu' was not found; the re-entry fix was skipped.", null); return; } _initializedField = AccessTools.Field(_enhancedMenuType, "_isInitialized"); _hudField = AccessTools.Field(_enhancedMenuType, "_hud"); MethodInfo methodInfo = AccessTools.Method(typeof(Hud), "Awake", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(Hud), "OnDestroy", (Type[])null, (Type[])null); if (_initializedField == null || _hudField == null || methodInfo == null || methodInfo2 == null) { VHModpackFixPlugin.LogWarning("AAABuildMenu lifecycle targets do not match the supported 1.0.1 layout; the re-entry fix was skipped.", null); return; } try { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(AAABuildMenuLifecycleFixes), "HudAwakePrefix", (Type[])null, (Type[])null)) { priority = 800 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(AAABuildMenuLifecycleFixes), "HudOnDestroyPostfix", (Type[])null, (Type[])null)) { priority = 0 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); VHModpackFixPlugin.LogInfo("AAABuildMenu world re-entry lifecycle repair installed."); } catch (Exception exception) { VHModpackFixPlugin.LogWarning("Could not install the AAABuildMenu world re-entry lifecycle repair", exception); } } private static void HudAwakePrefix(Hud __instance) { if (IsEnabled() && IsInitialized() && _hudField.GetValue(null) != __instance) { ResetHudState(); } } private static void HudOnDestroyPostfix(Hud __instance) { if (IsEnabled() && _hudField.GetValue(null) == __instance) { ResetHudState(); } } private static void ResetHudState() { try { _initializedField.SetValue(null, false); for (int i = 0; i < HudReferenceFields.Length; i++) { SetStaticField(_enhancedMenuType, HudReferenceFields[i], null); } for (int j = 0; j < HudCollectionFields.Length; j++) { ClearStaticCollection(_enhancedMenuType, HudCollectionFields[j]); } SetStaticField(_enhancedMenuType, "_origCaptured", false); SetStaticField(_enhancedMenuType, "_maskAdjusted", false); SetStaticField(_enhancedMenuType, "_origMaskCaptured", false); SetStaticField(_enhancedMenuType, "_vanillaButtonUsesSpriteSwap", false); SetStaticField(_enhancedMenuType, "_vanillaButtonResolved", false); SetStaticField(_enhancedMenuType, "_hasVanillaButton", false); SetStaticField(_enhancedMenuType, "_origWinCaptured", false); SetStaticField(_enhancedMenuType, "_sfxResolved", false); SetStaticField(_enhancedMenuType, "Columns", 15); FieldInfo fieldInfo = AccessTools.Field(_enhancedMenuType, "_lastScrollCategory"); if (fieldInfo != null) { fieldInfo.SetValue(null, Enum.ToObject(fieldInfo.FieldType, -999)); } ResetFilterState(); AccessTools.Property(_enhancedMenuType, "NeedsRefresh")?.SetValue(null, true, null); SetStaticField(_patchesType, "_menuWasVisible", false); ResetPinnedTrackerState(); VHModpackFixPlugin.LogInfo("AAABuildMenu HUD-bound state cleared for the next world."); } catch (Exception exception) { VHModpackFixPlugin.LogWarning("Could not clear stale AAABuildMenu HUD state", exception); } } private static void ResetFilterState() { object obj = AccessTools.Field(_enhancedMenuType, "_currentFilter")?.GetValue(null); if (obj != null) { SetInstanceProperty(obj, "SearchTerm", string.Empty); SetInstanceProperty(obj, "ShowOnlyCraftable", false); SetInstanceProperty(obj, "ShowMissingMaterials", false); SetInstanceProperty(obj, "ShowFavoritesOnly", false); SetInstanceProperty(obj, "ShowRecentOnly", false); SetInstanceProperty(obj, "ShowAll", false); } } private static void ResetPinnedTrackerState() { if (!(_pinnedTrackerType == null)) { SetStaticField(_pinnedTrackerType, "_root", null); SetStaticField(_pinnedTrackerType, "_rootRect", null); SetStaticField(_pinnedTrackerType, "_contentRoot", null); SetStaticField(_pinnedTrackerType, "_title", null); SetStaticField(_pinnedTrackerType, "_font", null); SetStaticField(_pinnedTrackerType, "_nextRefresh", 0f); ClearStaticCollection(_pinnedTrackerType, "_pieceCache"); ClearStaticCollection(_pinnedTrackerType, "_rows"); ClearStaticCollection(_pinnedTrackerType, "_shownPins"); } } private static void SetStaticField(Type type, string fieldName, object value) { if (!(type == null)) { AccessTools.Field(type, fieldName)?.SetValue(null, value); } } private static void ClearStaticCollection(Type type, string fieldName) { if (!(type == null)) { object obj = AccessTools.Field(type, fieldName)?.GetValue(null); obj?.GetType().GetMethod("Clear", Type.EmptyTypes)?.Invoke(obj, null); } } private static void SetInstanceProperty(object instance, string propertyName, object value) { instance.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public)?.SetValue(instance, value, null); } private static bool IsEnabled() { return _enabled?.Value ?? false; } private static bool IsInitialized() { object obj = _initializedField?.GetValue(null); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } } internal static class AdventureBackpacksAutoStoreCompat { [HarmonyPatch(typeof(Player), "Message")] private static class PlayerMessagePatch { private static bool Prefix(MessageType type, string msg) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return !ShouldSuppressMessage(type, msg); } } private const string VanillaContainerType = "AzuAutoStore.Interfaces.VanillaContainers"; private const string KgDrawerType = "AzuAutoStore.Interfaces.kgDrawer"; private const string BackpackContainerType = "AzuAutoStore.Interfaces.BackpackContainer"; private const string BackpackInventoryMarker = "$vapok_mod_level"; private const string FavoriteBorderName = "AzuAutoStoreFavoritingBorder"; private const string BackpackFavoriteDataKey = "obelisk.vhmodpackfix.backpackFavorite"; private const string EpicLootCustomDataPrefix = "randyknapp.mods.epicloot#"; private static ConfigEntry<bool> _autoStoreEnabled; private static ConfigEntry<bool> _pickupRoutingEnabled; private static MethodInfo _getEquippedBackpack; private static MethodInfo _getBackpackInventory; private static MethodInfo _isBackpackItem; private static MethodInfo _inventoryChanged; private static FieldInfo _inventoryGuiCurrentContainer; private static FieldInfo _inventoryGuiDragObject; private static FieldInfo _containerNetworkView; private static MethodInfo _containerCheckAccess; private static MethodInfo _getNearbyContainers; private static MethodInfo _storeToContainer; private static MethodInfo _vanillaContainerGetInventory; private static PropertyInfo _containerGameObject; private static FieldInfo _playerRange; private static MethodInfo _isItemNameOrSlotFavorite; private static MethodInfo _createFavoriteBorder; private static FieldInfo _favoriteBorderColor; private static FieldInfo _favoritingModifier1; private static FieldInfo _favoritingModifier2; private static FieldInfo _favoritingToggleState; private static FieldInfo _inventoryGridInventory; private static FieldInfo _inventoryGridElements; private static FieldInfo _elementQueuedImage; private static MethodInfo _inventoryGridGetButtonPos; private static bool _backpackReady; private static bool _autoStoreReady; private static bool _autoStorePatched; private static bool _pickupPatched; private static bool _containerTransferPatched; private static bool _loadRecoveryPatched; private static bool _backpackSaveHotPathPatched; private static bool _favoritePatched; private static bool _pickupApiFailureLogged; private static bool _favoriteFailureLogged; private static bool _favoriteBordersDirty = true; private static Inventory _lastBorderInventory; private static InventoryGrid _lastBorderGrid; private static Image _lastBorderFirstQueuedImage; private static int _lastBorderElementCount = -1; private static int _pickupBackpackCacheFrame = -1; private static Player _pickupBackpackCachePlayer; private static Inventory _pickupBackpackCacheInventory; [ThreadStatic] private static bool _tryStoreScope; [ThreadStatic] private static bool _suppressAzuFailureMessage; [ThreadStatic] private static int _backpackStored; [ThreadStatic] private static Inventory _activeStoreInventory; [ThreadStatic] private static ItemData _activeStoreItem; [ThreadStatic] private static Vector2i _activeStoreOriginalPosition; [ThreadStatic] private static object[] _playerInvokeArguments; [ThreadStatic] private static object[] _itemInvokeArguments; [ThreadStatic] private static object[] _nearbyInvokeArguments; [ThreadStatic] private static object[] _storeInvokeArguments; internal static void Init(Harmony harmony, ConfigFile config) { _autoStoreEnabled = ConfigLayout.Bind(config, "AdventureBackpacks", "AdventureBackpacks AzuAutoStore compatibility", defaultValue: true, "Lets AzuAutoStore move eligible items from your equipped AdventureBackpacks backpack into nearby storage. Favorite items remain protected.", "Fixes"); _pickupRoutingEnabled = ConfigLayout.Bind(config, "AdventureBackpacks", "Auto-pick matching items into AdventureBackpacks", defaultValue: false, "When the equipped backpack already contains an item type, sends whole matching stacks there during automatic pickup, manual pickup, and quick transfer from an opened container. Epic Loot stack data is supported; unknown special data is left to the normal inventory for safety.", "Experimental"); if (harmony == null || !ResolveBackpackApi()) { return; } if (!_loadRecoveryPatched) { PatchBackpackLoadRecovery(harmony); } if (!_backpackSaveHotPathPatched) { PatchBackpackSaveHotPath(harmony); } if (!_pickupPatched) { PatchPickupRouting(harmony); } if (!_containerTransferPatched) { PatchContainerTransfers(harmony); } if (ResolveAutoStoreApi()) { if (!_autoStorePatched) { PatchAutoStore(harmony); } if (!_favoritePatched) { PatchFavoriteSupport(harmony); } } } private static bool ResolveBackpackApi() { if (_backpackReady) { return true; } Type type = FindLoadedType("AdventureBackpacks.Extensions.PlayerExtensions"); Type type2 = FindLoadedType("AdventureBackpacks.Extensions.ItemDataExtensions"); _getEquippedBackpack = ((type == null) ? null : AccessTools.Method(type, "GetEquippedBackpack", new Type[1] { typeof(Player) }, (Type[])null)); Type type3 = _getEquippedBackpack?.ReturnType; _getBackpackInventory = ((type3 == null) ? null : AccessTools.Method(type3, "GetInventory", Type.EmptyTypes, (Type[])null)); _isBackpackItem = ((type2 == null) ? null : AccessTools.Method(type2, "IsBackpack", new Type[1] { typeof(ItemData) }, (Type[])null)); _inventoryChanged = AccessTools.Method(typeof(Inventory), "Changed", Type.EmptyTypes, (Type[])null); _inventoryGuiCurrentContainer = AccessTools.Field(typeof(InventoryGui), "m_currentContainer"); _inventoryGuiDragObject = AccessTools.Field(typeof(InventoryGui), "m_dragGo"); _containerNetworkView = AccessTools.Field(typeof(Container), "m_nview"); _containerCheckAccess = AccessTools.Method(typeof(Container), "CheckAccess", new Type[1] { typeof(long) }, (Type[])null); _backpackReady = _getEquippedBackpack != null && _getBackpackInventory != null && _inventoryChanged != null; return _backpackReady; } private static bool ResolveAutoStoreApi() { if (_autoStoreReady) { return true; } Type type = FindLoadedType("AzuAutoStore.Util.Boxes"); Type type2 = FindLoadedType("AzuAutoStore.Util.Functions"); Type type3 = FindLoadedType("AzuAutoStore.Interfaces.IContainer"); Type type4 = FindLoadedType("AzuAutoStore.Interfaces.VanillaContainers"); Type type5 = FindLoadedType("AzuAutoStore.AzuAutoStorePlugin"); if (type == null || type2 == null || type3 == null) { return false; } _getNearbyContainers = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo method) { if (method.Name != "GetNearbyContainers" || !method.IsGenericMethodDefinition) { return false; } ParameterInfo[] parameters = method.GetParameters(); return parameters.Length == 2 && parameters[1].ParameterType == typeof(float); })?.MakeGenericMethod(typeof(Player)); _storeToContainer = AccessTools.DeclaredMethod(type2, "StoreToContainer", new Type[3] { type3, typeof(ItemData), typeof(Inventory) }, (Type[])null); _vanillaContainerGetInventory = ((type4 == null) ? null : AccessTools.Method(type4, "GetInventory", Type.EmptyTypes, (Type[])null)); _containerGameObject = AccessTools.Property(type3, "gameObject"); _playerRange = ((type5 == null) ? null : AccessTools.Field(type5, "PlayerRange")); ResolveFavoriteApi(type5); _autoStoreReady = _isBackpackItem != null && _getNearbyContainers != null && _storeToContainer != null; return _autoStoreReady; } private static void ResolveFavoriteApi(Type pluginType) { Type type = FindLoadedType("AzuAutoStore.Patches.Favoriting.UserConfig"); Type type2 = FindLoadedType("AzuAutoStore.Patches.Favoriting.FavoritingMode"); Type type3 = FindLoadedType("AzuAutoStore.Patches.Favoriting.BorderRenderer"); _isItemNameOrSlotFavorite = ((type == null) ? null : AccessTools.Method(type, "IsItemNameOrSlotFavorited", new Type[1] { typeof(ItemData) }, (Type[])null)); _createFavoriteBorder = ((type3 == null) ? null : AccessTools.Method(type3, "CreateBorderImage", new Type[1] { typeof(Image) }, (Type[])null)); _favoriteBorderColor = ((pluginType == null) ? null : AccessTools.Field(pluginType, "BorderColorFavoritedItem")); _favoritingModifier1 = ((pluginType == null) ? null : AccessTools.Field(pluginType, "FavoritingModifierKeybind1")); _favoritingModifier2 = ((pluginType == null) ? null : AccessTools.Field(pluginType, "FavoritingModifierKeybind2")); _favoritingToggleState = ((type2 == null) ? null : AccessTools.Field(type2, "hasCurrentlyToggledFavoriting")); _inventoryGridInventory = AccessTools.Field(typeof(InventoryGrid), "m_inventory"); _inventoryGridElements = AccessTools.Field(typeof(InventoryGrid), "m_elements"); _inventoryGridGetButtonPos = AccessTools.Method(typeof(InventoryGrid), "GetButtonPos", new Type[1] { typeof(GameObject) }, (Type[])null); } private static void PatchAutoStore(Harmony harmony) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Expected O, but got Unknown //IL_00f1: Expected O, but got Unknown //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Expected O, but got Unknown //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Expected O, but got Unknown //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_0194: Expected O, but got Unknown Type type = FindLoadedType("AzuAutoStore.Util.Functions"); Type type2 = FindLoadedType("AzuAutoStore.Patches.ContainerAwakePatch"); MethodInfo methodInfo = AccessTools.Method(type, "TryStore", Type.EmptyTypes, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(type, "StoreSuccess", new Type[1] { typeof(int) }, (Type[])null); MethodInfo methodInfo3 = AccessTools.Method(type2, "TryAddContainer", new Type[1] { typeof(Container) }, (Type[])null); MethodInfo methodInfo4 = AccessTools.Method(typeof(Inventory), "Changed", Type.EmptyTypes, (Type[])null); if (!(methodInfo == null) && !(methodInfo2 == null) && !(methodInfo4 == null)) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "TryStorePrefix", (Type[])null, (Type[])null)) { priority = 800 }, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "TryStoreFinalizer", (Type[])null, (Type[])null)) { priority = 0 }, (HarmonyMethod)null); harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "StoreSuccessPrefix", (Type[])null, (Type[])null)) { priority = 800 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)_storeToContainer, new HarmonyMethod(AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "SkipEquippedBackpackContainerPrefix", (Type[])null, (Type[])null)) { priority = 800 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); if (methodInfo3 != null) { harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "SkipPlayerContainerRegistrationPrefix", (Type[])null, (Type[])null)) { priority = 800 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } harmony.Patch((MethodBase)methodInfo4, new HarmonyMethod(AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "InventoryChangedPrefix", (Type[])null, (Type[])null)) { priority = 800 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _autoStorePatched = true; } } private static void PatchPickupRouting(Harmony harmony) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(Humanoid), "Pickup", new Type[3] { typeof(GameObject), typeof(bool), typeof(bool) }, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(Player), "AutoPickup", new Type[1] { typeof(float) }, (Type[])null); if (methodInfo == null || methodInfo2 == null) { VHModpackFixPlugin.LogWarning("AdventureBackpacks pickup routing could not find the current Valheim pickup methods", null); return; } try { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "PickupAddTranspiler", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null); PatchAutoPickupMethod(harmony, methodInfo2); MethodInfo methodInfo3 = FindLoadedType("Valheim_Build_Camera.Utils")?.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo method) { if (method.Name != "AutoPickup") { return false; } ParameterInfo[] parameters = method.GetParameters(); return parameters.Length == 2 && parameters[0].ParameterType == typeof(float) && parameters[1].ParameterType == typeof(GameCamera).MakeByRefType(); }); if (methodInfo3 != null) { PatchAutoPickupMethod(harmony, methodInfo3); } _pickupPatched = true; } catch (Exception exception) { VHModpackFixPlugin.LogWarning("AdventureBackpacks pickup routing could not be installed", Unwrap(exception)); } } private static void PatchContainerTransfers(Harmony harmony) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Expected O, but got Unknown //IL_018e: Expected O, but got Unknown try { MethodInfo methodInfo = AccessTools.Method(typeof(Inventory), "MoveItemToThis", new Type[2] { typeof(Inventory), typeof(ItemData) }, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(Inventory), "MoveAll", new Type[1] { typeof(Inventory) }, (Type[])null); if (methodInfo != null) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "MoveItemToThisPrefix", (Type[])null, (Type[])null)) { priority = 800 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (methodInfo2 != null) { harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "MoveAllPrefix", (Type[])null, (Type[])null)) { priority = 800 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } Type type = FindLoadedType("InventorySlots.InventorySlotsPlugin"); MethodInfo methodInfo3 = ((type == null) ? null : AccessTools.Method(type, "SafeTakeAllItems", new Type[4] { typeof(Player), typeof(Inventory), typeof(Inventory), typeof(bool) }, (Type[])null)); if (methodInfo3 != null) { harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "SafeTakeAllPrefix", (Type[])null, (Type[])null)) { priority = 800 }, new HarmonyMethod(AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "SafeTakeAllPostfix", (Type[])null, (Type[])null)) { priority = 0 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } _containerTransferPatched = methodInfo != null || methodInfo2 != null; } catch (Exception exception) { VHModpackFixPlugin.LogWarning("AdventureBackpacks container pickup routing could not be installed", Unwrap(exception)); } } private static void PatchBackpackLoadRecovery(Harmony harmony) { //IL_0073: 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) //IL_008c: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(Inventory), "AddItem", new Type[4] { typeof(ItemData), typeof(int), typeof(int), typeof(int) }, (Type[])null); if (methodInfo == null) { return; } try { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "RepairLoadedBackpackSlotPrefix", (Type[])null, (Type[])null)) { priority = 800 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _loadRecoveryPatched = true; } catch (Exception exception) { VHModpackFixPlugin.LogWarning("AdventureBackpacks legacy slot recovery could not be installed", Unwrap(exception)); } } private static void PatchBackpackSaveHotPath(Harmony harmony) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.DeclaredMethod(_getEquippedBackpack?.DeclaringType?.Assembly.GetType("AdventureBackpacks.Patches.InventoryPatches+InventoryChangedPatch", throwOnError: false), "Postfix", new Type[1] { typeof(Inventory) }, (Type[])null); if (methodInfo == null) { return; } try { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "RemoveUnusedBackpackStackTraceTranspiler", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null); _backpackSaveHotPathPatched = true; } catch (Exception exception) { VHModpackFixPlugin.LogWarning("AdventureBackpacks save-path optimization could not be installed", Unwrap(exception)); } } private static void PatchFavoriteSupport(Harmony harmony) { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Expected O, but got Unknown //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Expected O, but got Unknown if (_isItemNameOrSlotFavorite == null || _inventoryGridGetButtonPos == null || _inventoryGridInventory == null || _inventoryGridElements == null) { return; } MethodInfo methodInfo = AccessTools.Method(typeof(InventoryGrid), "OnLeftClick", new Type[1] { typeof(UIInputHandler) }, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(InventoryGrid), "UpdateGui", new Type[2] { typeof(Player), typeof(ItemData) }, (Type[])null); if (methodInfo == null || methodInfo2 == null) { return; } try { HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "BackpackLeftClickPrefix", (Type[])null, (Type[])null)); val.priority = 800; val.before = new string[3] { "Azumatt.AzuAutoStore", "sighsorry.InventorySlots", "goldenrevolver.quick_stack_store" }; harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val = new HarmonyMethod(AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "RenderFavoriteBordersPostfix", (Type[])null, (Type[])null)); val.priority = 0; val.after = new string[2] { "Azumatt.AzuAutoStore", "goldenrevolver.quick_stack_store" }; harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)_isItemNameOrSlotFavorite, new HarmonyMethod(AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "AzuFavoriteCheckPrefix", (Type[])null, (Type[])null)) { priority = 800 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _favoritePatched = true; } catch (Exception exception) { LogFavoriteFailure("AdventureBackpacks favorite-item support could not be installed", exception); } } private static void PatchAutoPickupMethod(Harmony harmony, MethodInfo method) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown harmony.Patch((MethodBase)method, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "AutoPickupCanAddTranspiler", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null); } private static IEnumerable<CodeInstruction> PickupAddTranspiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod) { MethodInfo target = AccessTools.Method(typeof(Inventory), "AddItem", new Type[1] { typeof(ItemData) }, (Type[])null); MethodInfo replacement = AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "AddPickupItem", (Type[])null, (Type[])null); return ReplaceSingleCall(instructions, target, replacement, __originalMethod); } private static IEnumerable<CodeInstruction> AutoPickupCanAddTranspiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod) { MethodInfo target = AccessTools.Method(typeof(Inventory), "CanAddItem", new Type[2] { typeof(ItemData), typeof(int) }, (Type[])null); MethodInfo replacement = AccessTools.Method(typeof(AdventureBackpacksAutoStoreCompat), "CanAddPickupItem", (Type[])null, (Type[])null); return ReplaceSingleCall(instructions, target, replacement, __originalMethod); } private static IEnumerable<CodeInstruction> ReplaceSingleCall(IEnumerable<CodeInstruction> instructions, MethodInfo target, MethodInfo replacement, MethodBase original) { List<CodeInstruction> list = instructions.ToList(); for (int i = 0; i < list.Count; i++) { if (CodeInstructionExtensions.Calls(list[i], target)) { list[i].opcode = OpCodes.Call; list[i].operand = replacement; return list; } } VHModpackFixPlugin.LogWarning("AdventureBackpacks pickup routing found no compatible call in " + original?.DeclaringType?.FullName + "." + original?.Name, null); return list; } private static IEnumerable<CodeInstruction> RemoveUnusedBackpackStackTraceTranspiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod) { List<CodeInstruction> list = instructions.ToList(); ConstructorInfo objB = AccessTools.Constructor(typeof(StackTrace), Type.EmptyTypes, false); int num = -1; int num2 = 0; for (int i = 0; i < list.Count - 1; i++) { if (!(list[i].opcode != OpCodes.Newobj) && object.Equals(list[i].operand, objB) && !(list[i + 1].opcode != OpCodes.Pop)) { num = i; num2++; } } if (num2 != 1) { VHModpackFixPlugin.LogWarning($"AdventureBackpacks save-path optimization expected one unused StackTrace in {__originalMethod?.DeclaringType?.FullName}.{__originalMethod?.Name}, found {num2}", null); return list; } list[num].opcode = OpCodes.Nop; list[num].operand = null; list[num + 1].opcode = OpCodes.Nop; list[num + 1].operand = null; return list; } private static bool CanAddPickupItem(Inventory regularInventory, ItemData item, int stack) { if (regularInventory == null || item == null) { if (regularInventory != null && item != null) { return regularInventory.CanAddItem(item, stack); } return false; } if (regularInventory.CanAddItem(item, stack)) { return true; } int num = ((stack <= 0) ? item.m_stack : stack); if (TryGetPickupBackpack(regularInventory, item, out var backpackInventory, out var capacity) && capacity >= num) { return backpackInventory.CanAddItem(item, num); } return false; } private static bool AddPickupItem(Inventory regularInventory, ItemData item) { ConfigEntry<bool> pickupRoutingEnabled = _pickupRoutingEnabled; if (pickupRoutingEnabled == null || !pickupRoutingEnabled.Value || regularInventory == null || item == null || !TryGetPickupBackpack(regularInventory, item, out var backpackInventory, out var capacity) || capacity < item.m_stack || !backpackInventory.CanAddItem(item, item.m_stack)) { if (regularInventory != null && item != null) { return regularInventory.AddItem(item); } return false; } return backpackInventory.AddItem(item); } private static bool MoveItemToThisPrefix(Inventory __instance, Inventory fromInventory, ItemData item) { ConfigEntry<bool> pickupRoutingEnabled = _pickupRoutingEnabled; if (pickupRoutingEnabled == null || !pickupRoutingEnabled.Value || !IsCurrentOpenedContainerTransfer(__instance, fromInventory) || !TryMoveWholeStackToBackpack(__instance, fromInventory, item)) { return true; } return false; } private static void MoveAllPrefix(Inventory __instance, Inventory fromInventory) { ConfigEntry<bool> pickupRoutingEnabled = _pickupRoutingEnabled; if (pickupRoutingEnabled != null && pickupRoutingEnabled.Value) { RouteCurrentContainerItems(Player.m_localPlayer, __instance, fromInventory); } } private static void SafeTakeAllPrefix(Player player, Inventory playerInventory, Inventory containerInventory, out int __state) { ConfigEntry<bool> pickupRoutingEnabled = _pickupRoutingEnabled; __state = ((pickupRoutingEnabled != null && pickupRoutingEnabled.Value) ? RouteCurrentContainerItems(player, playerInventory, containerInventory) : 0); } private static void SafeTakeAllPostfix(ref int __result, int __state) { if (__state > 0) { __result += __state; } } private static int RouteCurrentContainerItems(Player player, Inventory playerInventory, Inventory containerInventory) { if ((Object)(object)player == (Object)null || playerInventory == null || containerInventory == null || player != Player.m_localPlayer || playerInventory != ((Humanoid)player).GetInventory() || !IsCurrentOpenedContainerTransfer(playerInventory, containerInventory)) { return 0; } int num = 0; List<ItemData> list = new List<ItemData>(containerInventory.GetAllItems()); list.Sort(delegate(ItemData left, ItemData right) { int num3 = left.m_gridPos.y.CompareTo(right.m_gridPos.y); return (num3 == 0) ? left.m_gridPos.x.CompareTo(right.m_gridPos.x) : num3; }); for (int num2 = 0; num2 < list.Count; num2++) { ItemData item = list[num2]; if (TryMoveWholeStackToBackpack(playerInventory, containerInventory, item)) { num++; } } return num; } private static bool IsCurrentOpenedContainerTransfer(Inventory playerInventory, Inventory containerInventory) { Player localPlayer = Player.m_localPlayer; InventoryGui instance = InventoryGui.instance; Container val = (Container)(((Object)(object)instance == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/); if ((Object)(object)localPlayer == (Object)null || (Object)(object)val == (Object)null || playerInventory == null || containerInventory == null || playerInventory != ((Humanoid)localPlayer).GetInventory() || val.GetInventory() != containerInventory || (Object)(object)((Component)val).GetComponent<TombStone>() != (Object)null || !CanMutateOpenedContainerDirectly(val, localPlayer)) { return false; } Inventory val2 = TryGetEquippedBackpackInventory(localPlayer); if (val2 != null) { return containerInventory != val2; } return false; } private static bool CanMutateOpenedContainerDirectly(Container container, Player player) { try { if (_containerCheckAccess != null) { object obj = _containerCheckAccess.Invoke(container, new object[1] { player.GetPlayerID() }); if (obj is bool && !(bool)obj) { return false; } } object? obj2 = _containerNetworkView?.GetValue(container); ZNetView val = (ZNetView)((obj2 is ZNetView) ? obj2 : null); return (Object)(object)val == (Object)null || !val.IsValid() || val.IsOwner(); } catch { return false; } } private static bool TryMoveWholeStackToBackpack(Inventory playerInventory, Inventory sourceInventory, ItemData item) { if (item == null || item.m_stack <= 0 || !sourceInventory.ContainsItem(item) || !TryGetPickupBackpack(playerInventory, item, out var backpackInventory, out var capacity) || sourceInventory == backpackInventory) { return false; } int stack = item.m_stack; if (capacity < stack || !backpackInventory.CanAddItem(item, stack)) { return false; } List<ItemData> list = new List<ItemData>(backpackInventory.GetAllItems()); int[] array = new int[list.Count]; for (int i = 0; i < list.Count; i++) { array[i] = list[i].m_stack; } ItemData val = item.Clone(); val.m_stack = stack; if (!backpackInventory.AddItem(val)) { RestoreBackpackTransfer(backpackInventory, val, list, array); VHModpackFixPlugin.LogWarning("AdventureBackpacks rejected a pre-checked whole-stack transfer; the normal inventory transfer was kept", null); return false; } sourceInventory.RemoveItem(item); if (sourceInventory.ContainsItem(item)) { RestoreBackpackTransfer(backpackInventory, val, list, array); VHModpackFixPlugin.LogWarning("AdventureBackpacks accepted an item but its source container could not remove the original stack", null); return false; } return true; } private static void RestoreBackpackTransfer(Inventory backpackInventory, ItemData transfer, List<ItemData> previousItems, int[] previousStacks) { List<ItemData> allItems = backpackInventory.GetAllItems(); allItems.Remove(transfer); for (int i = 0; i < previousItems.Count; i++) { ItemData val = previousItems[i]; if (allItems.Contains(val)) { val.m_stack = previousStacks[i]; } } _inventoryChanged.Invoke(backpackInventory, null); } private static bool TryGetPickupBackpack(Inventory regularInventory, ItemData item, out Inventory backpackInventory, out int capacity) { backpackInventory = null; capacity = 0; Player localPlayer = Player.m_localPlayer; ConfigEntry<bool> pickupRoutingEnabled = _pickupRoutingEnabled; if (pickupRoutingEnabled == null || !pickupRoutingEnabled.Value || (Object)(object)localPlayer == (Object)null || regularInventory != ((Humanoid)localPlayer).GetInventory() || item?.m_shared == null || item.m_stack <= 0 || item.m_shared.m_maxStackSize <= 1 || item.m_shared.m_questItem || item.IsWeapon() || HasUnsafeCustomData(item)) { return false; } backpackInventory = GetPickupBackpackInventory(localPlayer); if (backpackInventory == null || backpackInventory == regularInventory) { return false; } List<ItemData> allItems = backpackInventory.GetAllItems(); if (allItems == null || allItems.Count == 0) { return false; } string name = item.m_shared.m_name; bool flag = false; bool flag2 = false; bool flag3 = false; int num = 0; for (int num2 = allItems.Count - 1; num2 >= 0; num2--) { ItemData val = allItems[num2]; if (val == null || val.m_stack <= 0) { allItems.RemoveAt(num2); flag3 = true; } else if (val.m_shared != null && string.Equals(val.m_shared.m_name, name, StringComparison.Ordinal)) { flag = true; if (HasUnsafeCustomData(val)) { flag2 = true; } else if (val.m_quality == item.m_quality && val.m_worldLevel == item.m_worldLevel && val.m_stack < val.m_shared.m_maxStackSize) { num += val.m_shared.m_maxStackSize - val.m_stack; } } } if (flag3) { _inventoryChanged.Invoke(backpackInventory, null); } if (!flag || flag2) { return false; } int num3 = Math.Max(0, backpackInventory.GetEmptySlots()); capacity = num + num3 * Math.Max(1, item.m_shared.m_maxStackSize); return capacity > 0; } private static Inventory GetPickupBackpackInventory(Player player) { int frameCount = Time.frameCount; if (frameCount != _pickupBackpackCacheFrame || player != _pickupBackpackCachePlayer) { _pickupBackpackCacheFrame = frameCount; _pickupBackpackCachePlayer = player; _pickupBackpackCacheInventory = TryGetEquippedBackpackInventory(player); } return _pickupBackpackCacheInventory; } private static bool HasUnsafeCustomData(ItemData item) { if (item?.m_customData == null || item.m_customData.Count == 0) { return false; } foreach (string key in item.m_customData.Keys) { if (!string.Equals(key, "obelisk.vhmodpackfix.backpackFavorite", StringComparison.Ordinal) && !key.StartsWith("randyknapp.mods.epicloot#", StringComparison.Ordinal)) { return true; } } return false; } private static bool RepairLoadedBackpackSlotPrefix(Inventory __instance, ItemData item, int amount, ref int x, ref int y, ref bool __result) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_0065: Unknown result type (might be due to invalid IL or missing references) if (!IsAdventureBackpackInventory(__instance)) { return true; } if (item == null || amount <= 0 || item.m_stack <= 0) { __result = false; return false; } int width = __instance.GetWidth(); int height = __instance.GetHeight(); if (x >= 0 && x < width && y >= 0 && y < height) { return true; } Vector2i val = FindFreeSlot(__instance, width, height, y); if (val.x >= 0) { x = val.x; y = val.y; } return true; } private static bool SkipEquippedBackpackContainerPrefix(object container, ref int __result) { if (!IsEquippedAdventureBackpackContainer(container)) { return true; } __result = 0; return false; } private static bool SkipPlayerContainerRegistrationPrefix(Container container, ref bool __result) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)container == (Object)null || (Object)(object)localPlayer == (Object)null || (Object)(object)((Component)container).gameObject != (Object)(object)((Component)localPlayer).gameObject) { return true; } __result = false; return false; } private static void TryStorePrefix() { _tryStoreScope = false; _backpackStored = 0; ConfigEntry<bool> autoStoreEnabled = _autoStoreEnabled; if (autoStoreEnabled == null || !autoStoreEnabled.Value || !_autoStoreReady) { return; } try { _tryStoreScope = true; _backpackStored = StoreEquippedBackpack(); } catch (Exception exception) { _backpackStored = 0; VHModpackFixPlugin.LogWarning("AdventureBackpacks/AzuAutoStore integration failed", Unwrap(exception)); } } private static Exception TryStoreFinalizer(Exception __exception) { _tryStoreScope = false; _suppressAzuFailureMessage = false; _backpackStored = 0; ClearActiveStoreScope(); return __exception; } private static void StoreSuccessPrefix(ref int total) { if (_tryStoreScope) { total += _backpackStored; _backpackStored = 0; } } private static void InventoryChangedPrefix(Inventory __instance) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (__instance == _activeStoreInventory && _activeStoreItem != null) { _activeStoreItem.m_gridPos = _activeStoreOriginalPosition; } if (_favoritePatched && IsAdventureBackpackInventory(__instance)) { _favoriteBordersDirty = true; } } private static int StoreEquippedBackpack() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return 0; } Inventory val = TryGetEquippedBackpackInventory(localPlayer); if (val == null) { return 0; } RemoveInvalidRuntimeStacks(val); List<ItemData> allItems = val.GetAllItems(); if (allItems == null || allItems.Count == 0) { return 0; } object[] array = _nearbyInvokeArguments ?? (_nearbyInvokeArguments = new object[2]); array[0] = localPlayer; array[1] = GetPlayerRange(); object obj; try { obj = _getNearbyContainers.Invoke(null, array); } finally { array[0] = null; array[1] = null; } if (!(obj is IEnumerable enumerable)) { return 0; } List<ItemData> list = new List<ItemData>(allItems.Count); for (int i = 0; i < allItems.Count; i++) { ItemData val2 = allItems[i]; if (val2 != null && val2.m_stack > 0 && !val2.m_equipped && !IsBackpackItem(val2) && !IsBackpackStackFavorite(val2)) { list.Add(val2); } } int num = 0; foreach (object item in enumerable) { if (item == null || !IsSupportedContainer(item) || IsUnsafeSelfTarget(item, val, localPlayer)) { continue; } for (int num2 = list.Count - 1; num2 >= 0; num2--) { ItemData val3 = list[num2]; if (val3 == null || val3.m_stack <= 0 || !val.ContainsItem(val3)) { list.RemoveAt(num2); } else { num += StoreItem(item, val3, val, out var stopPass); if (stopPass) { return num; } if (val3.m_stack <= 0 || !val.ContainsItem(val3)) { list.RemoveAt(num2); } } } if (list.Count == 0) { break; } } return num; } private static int StoreItem(object container, ItemData sourceItem, Inventory sourceInventory, out bool stopPass) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_0073: Unknown result type (might be due to invalid IL or missing references) stopPass = false; int stack = sourceItem.m_stack; Vector2i gridPos = sourceItem.m_gridPos; Exception ex = null; _activeStoreInventory = sourceInventory; _activeStoreItem = sourceItem; _activeStoreOriginalPosition = gridPos; sourceItem.m_gridPos = new Vector2i(-1, -1); _suppressAzuFailureMessage = true; object[] array = _storeInvokeArguments ?? (_storeInvokeArguments = new object[3]); array[0] = container; array[1] = sourceItem; array[2] = sourceInventory; try { _storeToContainer.Invoke(null, array); } catch (Exception exception) { ex = Unwrap(exception); } finally { sourceItem.m_gridPos = gridPos; _suppressAzuFailureMessage = false; array[0] = null; array[1] = null; array[2] = null; ClearActiveStoreScope(); } if (sourceItem.m_stack <= 0 && sourceInventory.ContainsItem(sourceItem) && !RemoveZeroStack(sourceInventory, sourceItem)) { stopPass = true; VHModpackFixPlugin.LogWarning("AdventureBackpacks/AzuAutoStore could not clear an exhausted backpack stack", null); } int num = (sourceInventory.ContainsItem(sourceItem) ? Math.Max(0, sourceItem.m_stack) : 0); int num2 = Math.Max(0, Math.Min(stack, stack - num)); if (ex != null) { stopPass = true; VHModpackFixPlugin.LogWarning((num2 > 0) ? "AdventureBackpacks/AzuAutoStore stopped after a container accepted part of a stack and then reported an error" : "AdventureBackpacks/AzuAutoStore stopped after a container rejected a backpack transfer with an error", ex); } return num2; } private static bool RemoveZeroStack(Inventory inventory, ItemData item) { inventory.RemoveItem(item); if (!inventory.ContainsItem(item)) { return true; } inventory.GetAllItems().Remove(item); _inventoryChanged.Invoke(inventory, null); return !inventory.ContainsItem(item); } private static void ClearActiveStoreScope() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (_activeStoreItem != null) { _activeStoreItem.m_gridPos = _activeStoreOriginalPosition; } _activeStoreInventory = null; _activeStoreItem = null; _activeStoreOriginalPosition = default(Vector2i); } private static bool BackpackLeftClickPrefix(InventoryGrid __instance, UIInputHandler clickHandler) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null) && !((Object)(object)clickHandler == (Object)null)) { object? obj = _inventoryGridInventory?.GetValue(__instance); Inventory val = (Inventory)((obj is Inventory) ? obj : null); if (val != null && IsAdventureBackpackInventory(val) && IsBackpackFavoritingInputHeld()) { Player localPlayer = Player.m_localPlayer; InventoryGui instance = InventoryGui.instance; GameObject val2 = (GameObject)(((Object)(object)instance == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/); if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsTeleporting() || (Object)(object)val2 != (Object)null) { return true; } Vector2i val3; try { val3 = (Vector2i)_inventoryGridGetButtonPos.Invoke(__instance, new object[1] { ((Component)clickHandler).gameObject }); } catch (Exception exception) { LogFavoriteFailure("AdventureBackpacks could not read the clicked backpack slot", exception); return true; } if (val3.x < 0 || val3.y < 0) { return true; } ItemData itemAt = val.GetItemAt(val3.x, val3.y); if (itemAt?.m_shared == null) { return true; } try { ToggleBackpackStackFavorite(itemAt); _inventoryChanged.Invoke(val, null); _favoriteBordersDirty = true; return false; } catch (Exception exception2) { LogFavoriteFailure("AdventureBackpacks could not update the AzuAutoStore favorite item", exception2); return true; } } } return true; } private static bool AzuFavoriteCheckPrefix(ItemData item, ref bool __result) { if (IsBackpackStackFavorite(item)) { __result = true; return false; } if (item != null && item == _activeStoreItem && IsAdventureBackpackInventory(_activeStoreInventory)) { __result = false; return false; } return true; } private static bool IsBackpackFavoritingInputHeld() { object obj = _favoritingToggleState?.GetValue(null); if (obj is bool && (bool)obj) { return true; } if (!IsShortcutHeld(_favoritingModifier1)) { return IsShortcutHeld(_favoritingModifier2); } return true; } private static bool IsShortcutHeld(FieldInfo shortcutField) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (!(shortcutField?.GetValue(null) is ConfigEntry<KeyboardShortcut> val)) { return false; } KeyboardShortcut value = val.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey == 0 || !UnityInput.Current.GetKey(((KeyboardShortcut)(ref value)).MainKey)) { return false; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers) { if (!UnityInput.Current.GetKey(modifier)) { return false; } } return true; } private static void ToggleBackpackStackFavorite(ItemData item) { if (item.m_customData == null) { item.m_customData = new Dictionary<string, string>(); } if (!item.m_customData.Remove("obelisk.vhmodpackfix.backpackFavorite")) { item.m_customData["obelisk.vhmodpackfix.backpackFavorite"] = "1"; } } private static bool IsBackpackStackFavorite(ItemData item) { if (item?.m_customData != null) { return item.m_customData.ContainsKey("obelisk.vhmodpackfix.backpackFavorite"); } return false; } private static void RenderFavoriteBordersPostfix(InventoryGrid __instance) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) if (!_favoritePatched || (Object)(object)__instance == (Object)null) { return; } object? obj = _inventoryGridInventory?.GetValue(__instance); Inventory val = (Inventory)((obj is Inventory) ? obj : null); if (val == null || !IsAdventureBackpackInventory(val) || !(_inventoryGridElements?.GetValue(__instance) is IList list)) { return; } Image val2 = ((list.Count > 0) ? GetQueuedImage(list[0]) : null); if (_lastBorderGrid != __instance || _lastBorderInventory != val || _lastBorderElementCount != list.Count || _lastBorderFirstQueuedImage != val2) { _lastBorderGrid = __instance; _lastBorderInventory = val; _lastBorderElementCount = list.Count; _lastBorderFirstQueuedImage = val2; _favoriteBordersDirty = true; } if (!_favoriteBordersDirty) { return; } try { Color favoriteBorderColor = GetFavoriteBorderColor(); for (int i = 0; i < list.Count; i++) { Image val3 = FindFavoriteBorder(GetQueuedImage(list[i])); if ((Object)(object)val3 != (Object)null) { ((Behaviour)val3).enabled = false; } } int width = val.GetWidth(); List<ItemData> allItems = val.GetAllItems(); for (int j = 0; j < allItems.Count; j++) { ItemData val4 = allItems[j]; if (val4?.m_shared == null || val4.m_stack <= 0 || !IsBackpackStackFavorite(val4)) { continue; } int num = val4.m_gridPos.y * width + val4.m_gridPos.x; if (num >= 0 && num < list.Count) { Image queuedImage = GetQueuedImage(list[num]); Image val5 = FindFavoriteBorder(queuedImage) ?? CreateFavoriteBorder(queuedImage); if (!((Object)(object)val5 == (Object)null)) { ((Graphic)val5).color = favoriteBorderColor; ((Behaviour)val5).enabled = true; } } } _favoriteBordersDirty = false; } catch (Exception exception) { LogFavoriteFailure("AdventureBackpacks could not draw AzuAutoStore favorite borders", exception); } } private static Image GetQueuedImage(object element) { if (element == null) { return null; } if ((object)_elementQueuedImage == null) { _elementQueuedImage = AccessTools.Field(element.GetType(), "m_queued"); } object? obj = _elementQueuedImage?.GetValue(element); return (Image)((obj is Image) ? obj : null); } private static Image FindFavoriteBorder(Image queued) { Transform val = (((Object)(object)queued == (Object)null) ? null : ((Component)queued).transform.Find("AzuAutoStoreFavoritingBorder")); if (!((Object)(object)val == (Object)null)) { return ((Component)val).GetComponent<Image>(); } return null; } private static Image CreateFavoriteBorder(Image queued) { if ((Object)(object)queued == (Object)null || _createFavoriteBorder == null) { return null; } object? obj = _createFavoriteBorder.Invoke(null, new object[1] { queued }); return (Image)((obj is Image) ? obj : null); } private static Color GetFavoriteBorderColor() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) object obj = _favoriteBorderColor?.GetValue(null); object obj2 = obj?.GetType().GetProperty("Value")?.GetValue(obj); if (obj2 is Color) { return (Color)obj2; } return new Color(1f, 0.8482759f, 0f, 1f); } private static void LogFavoriteFailure(string message, Exception exception) { if (!_favoriteFailureLogged) { _favoriteFailureLogged = true; VHModpackFixPlugin.LogWarning(message, Unwrap(exception)); } } private static void RemoveInvalidRuntimeStacks(Inventory inventory) { List<ItemData> list = ((inventory != null) ? inventory.GetAllItems() : null); if (list != null && list.RemoveAll((ItemData item) => item == null || item.m_stack <= 0) > 0) { _inventoryChanged.Invoke(inventory, null); } } private static Vector2i FindFreeSlot(Inventory inventory, int width, int height, int preferredRow) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (preferredRow >= 0 && preferredRow < height) { for (int i = 0; i < width; i++) { if (inventory.GetItemAt(i, preferredRow) == null) { return new Vector2i(i, preferredRow); } } } for (int j = 0; j < height; j++) { if (j == preferredRow) { continue; } for (int k = 0; k < width; k++) { if (inventory.GetItemAt(k, j) == null) { return new Vector2i(k, j); } } } return new Vector2i(-1, -1); } internal static Inventory TryGetEquippedBackpackInventory(Player player) { try { return GetEquippedBackpackInventory(player); } catch (Exception exception) { if (!_pickupApiFailureLogged) { _pickupApiFailureLogged = true; VHModpackFixPlugin.LogWarning("AdventureBackpacks compatibility could not read the equipped backpack", Unwrap(exception)); } return null; } } private static Inventory GetEquippedBackpackInventory(Player player) { object[] array = _playerInvokeArguments ?? (_playerInvokeArguments = new object[1]); array[0] = player; try { object obj = _getEquippedBackpack.Invoke(null, array); return (Inventory)((obj == null) ? null : /*isinst with value type is only supported in some contexts*/); } finally { array[0] = null; } } private static bool IsBackpackItem(ItemData item) { object[] array = _itemInvokeArguments ?? (_itemInvokeArguments = new object[1]); array[0] = item; try { object obj = _isBackpackItem?.Invoke(null, array); return obj is bool && (bool)obj; } finally { array[0] = null; } } private static bool IsAdventureBackpackInventory(Inventory inventory) { if (inventory == null) { return false; } string name = inventory.GetName(); if (!string.IsNullOrEmpty(name)) { return name.IndexOf("$vapok_mod_level", StringComparison.Ordinal) >= 0; } return false; } private static bool IsSupportedContainer(object container) { string fullName = container.GetType().FullName; if (!string.Equals(fullName, "AzuAutoStore.Interfaces.VanillaContainers", StringComparison.Ordinal) && !string.Equals(fullName, "AzuAutoStore.Interfaces.kgDrawer", StringComparison.Ordinal)) { return string.Equals(fullName, "AzuAutoStore.Interfaces.BackpackContainer", StringComparison.Ordinal); } return true; } private static bool IsEquippedAdventureBackpackContainer(object container) { if (container == null || !string.Equals(container.GetType().FullName, "AzuAutoStore.Interfaces.VanillaContainers", StringComparison.Ordinal)) { return false; } try { Player localPlayer = Player.m_localPlayer; object? obj = _containerGameObject?.GetValue(container); GameObject val = (GameObject)((obj is GameObject) ? obj : null); int result; if ((Object)(object)localPlayer != (Object)null && (Object)(object)val == (Object)(object)((Component)localPlayer).gameObject) { object? obj2 = _vanillaContainerGetInventory?.Invoke(container, null); Inventory val2 = (Inventory)((obj2 is Inventory) ? obj2 : null); if (val2 != null) { result = (IsAdventureBackpackInventory(val2) ? 1 : 0); goto IL_0078; } } result = 0; goto IL_0078; IL_0078: return (byte)result != 0; } catch { return false; } } private static bool IsUnsafeSelfTarget(object container, Inventory sourceInventory, Player player) { try { if (string.Equals(container.GetType().FullName, "AzuAutoStore.Interfaces.VanillaContainers", StringComparison.Ordinal)) { object? obj = _vanillaContainerGetInventory?.Invoke(container, null); Inventory val = (Inventory)((obj is Inventory) ? obj : null); if (val != null && val == sourceInventory) { return true; } } object? obj2 = _containerGameObject?.GetValue(container); GameObject val2 = (GameObject)((obj2 is GameObject) ? obj2 : null); return (Object)(object)val2 != (Object)null && (Object)(object)player != (Object)null && (Object)(object)val2 == (Object)(object)((Component)player).gameObject; } catch (Exception exception) { VHModpackFixPlugin.LogWarning("AdventureBackpacks/AzuAutoStore skipped a container whose target could not be verified", Unwrap(exception)); return true; } } private static float GetPlayerRange() { object obj = _playerRange?.GetValue(null); if (!(obj?.GetType().GetProperty("Value")?.GetValue(obj) is float num) || !(num > 0f)) { return 20f; } return num; } private static Type FindLoadedType(string fullName) { if (string.IsNullOrEmpty(fullName)) { return null; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { try { Type type = assemblies[i].GetType(fullName, throwOnError: false); if (type != null) { return type; } } catch { } } return null; } private static Exception Unwrap(Exception exception) { if (!(exception is TargetInvocationException ex) || exception.InnerException == null) { return exception; } return ex.InnerException; } private static bool ShouldSuppressMessage(MessageType type, string message) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 if (!_suppressAzuFailureMessage || (int)type != 2 || string.IsNullOrEmpty(message)) { return false; } if (message.IndexOf("is not in nearby containers", StringComparison.Ordinal) < 0) { return message.IndexOf("cannot be stored based on configuration settings", StringComparison.Ordinal) >= 0; } return true; } } internal static class AdventureBackpacksContainerPanel { private const string ConfigRegistryTypeName = "AdventureBackpacks.Configuration.ConfigRegistry"; private const string InventoryGuiPatchesTypeName = "AdventureBackpacks.Patches.InventoryGuiPatches"; private const string PanelName = "VHModpackFix_AdventureBackpackPanel"; private static ConfigEntry<bool> _enabled; private static ConfigEntry<float> _offsetX; private static ConfigEntry<float> _offsetY; private static FieldInfo _currentContainerField; private static FieldInfo _dragItemField; private static FieldInfo _openWithInventoryField; private static FieldInfo _openWithHoverField; private static FieldInfo _backpackIsOpenField; private static RectTransform _panel; private static InventoryGrid _grid; private static TMP_Text _nameText; private static TMP_Text _weightText; private static InventoryGui _ownerGui; private static Inventory _shownInventory; private static bool _patched; private static bool _failureLogged; internal static void Init(Harmony harmony, ConfigFile config) { //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Expected O, but got Unknown _enabled = ConfigLayout.Bind(config, "AdventureBackpacks", "Show backpack beside opened containers", defaultValue: true, "When AdventureBackpacks' 'Open with Inventory' option is enabled, shows the equipped backpack beside a chest or other opened container.", "AdventureBackpacks UI"); _offsetX = ConfigLayout.Bind(config, "AdventureBackpacks", "Backpack panel offset X", 650f, "Horizontal backpack-panel offset from the opened container panel. Positive values move it right.", "AdventureBackpacks UI"); _offsetY = ConfigLayout.Bind(config, "AdventureBackpacks", "Backpack panel offset Y", 0f, "Vertical backpack-panel offset from the opened container panel. Positive values move it up.", "AdventureBackpacks UI"); if (harmony == null || AccessTools.TypeByName("AdventureBackpacks.Patches.InventoryGuiPatches") == null) { return; } ResolveFields(); if (!(_currentContainerField == null) && !(_dragItemField == null) && !_patched) { PatchPostfix(harmony, AccessTools.Method(typeof(InventoryGui), "Awake", (Type[])null, (Type[])null), "InventoryGuiAwakePostfix"); PatchPostfix(harmony, AccessTools.Method(typeof(InventoryGui), "UpdateContainer", (Type[])null, (Type[])null), "UpdateContainerPostfix"); PatchPostfix(harmony, AccessTools.Method(typeof(InventoryGui), "Hide", (Type[])null, (Type[])null), "HidePostfix"); PatchPostfix(harmony, AccessTools.Method(typeof(InventoryGui), "CloseContainer", (Type[])null, (Type[])null), "HidePostfix"); PatchPostfix(harmony, AccessTools.Method(typeof(InventoryGui), "OnDestroy", (Type[])null, (Type[])null), "OnDestroyPostfix"); MethodInfo methodInfo = AccessTools.Method(typeof(InventoryGui), "OnSelectedItem", (Type[])null, (Type[])null); if (methodInfo != null) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(AdventureBackpacksContainerPanel), "OnSelectedItemPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } _patched = true; } } private static void ResolveFields() { _currentContainerField = AccessTools.Field(typeof(InventoryGui), "m_currentContainer"); _dragItemField = AccessTools.Field(typeof(InventoryGui), "m_dragItem"); Type type = AccessTools.TypeByName("AdventureBackpacks.Configuration.ConfigRegistry"); _openWithInventoryField = ((type == null) ? null : AccessTools.Field(type, "OpenWithInventory")); _openWithHoverField = ((type == null) ? null : AccessTools.Field(type, "OpenWithHoverInteract")); Type type2 = AccessTools.TypeByName("AdventureBackpacks.Patches.InventoryGuiPatches"); _backpackIsOpenField = ((type2 == null) ? null : AccessTools.Field(type2, "BackpackIsOpen")); } private static void PatchPostfix(Harmony harmony, MethodInfo original, string patchName) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown if (original != null) { harmony.Patch((MethodBase)original, (HarmonyMethod)null, new HarmonyMethod(typeof(AdventureBackpacksContainerPanel), patchName, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static void InventoryGuiAwakePostfix(InventoryGui __instance) { try { DestroyPanel(); CreatePanel(__instance); } catch (Exception exception) { DestroyPanel(); LogFailure("AdventureBackpacks side panel could not be created", exception); } } private static void UpdateContainerPostfix(InventoryGui __instance, Player player) { if ((Object)(object)__instance == (Object)null || (Object)(object)player == (Object)null || __instance != _ownerGui) { HidePanel(); return; } try { RefreshPanel(__instance, player); } catch (Exception exception) { HidePanel(); LogFailure("AdventureBackpacks side panel was disabled after an unexpected UI error", exception); } } private static void RefreshPanel(InventoryGui gui, Player player) { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_panel == (Object)null) && !((Object)(object)_grid == (Object)null)) { ConfigEntry<bool> enabled = _enabled; if (enabled != null && enabled.Value && AdventureBackpacksOpenWithInventory() && !AdventureBackpackIsAlreadyOpen()) { object? value = _currentContainerField.GetValue(gui); Container val = (Container)((value is Container) ? value : null); if ((Object)(object)val == (Object)null || !val.IsOwner()) { HidePanel(); return; } Inventory val2 = AdventureBackpacksAutoStoreCompat.TryGetEquippedBackpackInventory(player); Inventory inventory = val.GetInventory(); if (val2 == null || inventory == null || val2 == inventory) { HidePanel(); return; } _panel.anchoredPosition = gui.m_container.anchoredPosition + new Vector2(_offsetX.Value, _offsetY.Value); bool num = !((Component)_panel).gameObject.activeSelf || _shownInventory != val2; if (!((Component)_panel).gameObject.activeSelf) { _shownInventory = val2; ((Component)_panel).gameObject.SetActive(true); } else if (_shownInventory != val2) { _shownInventory = val2; } object? value2 = _dragItemField.GetValue(gui); ItemData val3 = (ItemData)((value2 is ItemData) ? value2 : null); _grid.UpdateInventory(val2, (Player)null, val3); if (num) { _grid.ResetView(); } if ((Object)(object)_nameText != (Object)null) { string name = val2.GetName(); _nameText.text = ((Localization.instance == null) ? name : Localization.instance.Localize(name)); } if ((Object)(object)_weightText != (Object)null) { _weightText.text = Mathf.CeilToInt(val2.GetTotalWeight()).ToString(); } return; } } HidePanel(); } private static bool AdventureBackpacksOpenWithInventory() { ConfigEntry<bool> obj = _openWithInventoryField?.GetValue(null) as ConfigEntry<bool>; if (obj == null || !obj.Value) { return false; } ConfigEntry<bool> obj2 = _openWithHoverField?.GetValue(null) as ConfigEntry<bool>; if (obj2 == null) { return true; } return !obj2.Value; } private static bool AdventureBackpackIsAlreadyOpen() { object obj = _backpackIsOpenField?.GetValue(null); if (obj is bool) { return (bool)obj; } return false; } private static void CreatePanel(InventoryGui gui) { if ((Object)(object)gui == (Object)null || (Object)(object)gui.m_container == (Object)null) { return; } GameObject val = Object.Instantiate<GameObject>(((Component)gui.m_container).gameObject, ((Transform)gui.m_container).parent, false); ((Object)val).name = "VHModpackFix_AdventureBackpackPanel"; _panel = val.GetComponent<RectTransform>(); _ownerGui = gui; _grid = FindClonedComponent<InventoryGrid>((Transform)(object)gui.m_container, (Transform)(object)_panel, gui.ContainerGrid); if ((Object)(object)_panel == (Object)null || (Object)(object)_grid == (Object)null) { DestroyPanel(); return; } _nameText = FindClonedComponent<TMP_Text>((Transform)(object)gui.m_container, (Transform)(object)_panel, gui.m_containerName); _weightText = FindClonedComponent<TMP_Text>((Transform)(object)gui.m_container, (Transform)(object)_panel, gui.m_containerWeight); Button val2 = FindClonedComponent<Button>((Transform)(object)gui.m_container, (Transform)(object)_panel, gui.m_takeAllButton); Button val3 = FindClonedComponent<Button>((Transform)(object)gui.m_container, (Transform)(object)_panel, gui.m_stackAllButton); if ((Object)(object)val2 != (Object)null) { ((Component)val2).gameObject.SetActive(false); } if ((Object)(object)val3 != (Object)null) { ((Component)val3).gameObject.SetActive(false); } MethodInfo methodInfo = AccessTools.Method(typeof(InventoryGui), "OnSelectedItem", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(InventoryGui), "OnRightClickItem", (Type[])null, (Type[])null); _grid.m_onSelected = ((methodInfo == null) ? null : ((Action<InventoryGrid, ItemData, Vector2i, Modifier>)Delegate.CreateDelegate(typeof(Action<InventoryGrid, ItemData, Vector2i, Modifier>), gui, methodInfo))); _grid.m_onRightClick = ((methodInfo2 == null) ? null : ((Action<InventoryGrid, ItemData, Vector2i>)Delegate.CreateDelegate(typeof(Action<InventoryGrid, ItemData, Vector2i>), gui, methodInfo2))); _grid.OnMoveToUpperInventoryGrid = null; _grid.OnMoveToLowerInventoryGrid = null; val.SetActive(false); } private static bool OnSelectedItemPrefix(InventoryGui __instance, InventoryGrid grid, ItemData item, Modifier mod) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)grid == (Object)null || grid != _grid || (int)mod != 2 || item == null) { return true; } if (item.m_shared == null || item.m_shared.m_questItem) { return false; } Player localPlayer = Player.m_localPlayer; object? obj = _currentContainerField?.GetValue(__instance); Container val = (Container)((obj is Container) ? obj : null); Inventory inventory = grid.GetInventory(); Inventory val2 = (((Object)(object)val == (Object)null) ? null : val.GetInventory()); if ((Object)(object)localPlayer == (Object)null || inventory == null || val2 == null || inventory == val2 || !inventory.ContainsItem(item)) { return false; } try { val2.MoveItemToThis(inventory, item); __instance.m_moveItemEffects.Create(((Component)__instance).transform.position, Quaternion.identity, (Transform)null, 1f, -1); } catch (Exception exception) { LogFailure("AdventureBackpacks side-panel quick transfer failed", exception); } return false; } private static void HidePostfix(InventoryGui __instance) { if (__instance == _ownerGui) { HidePanel(); } } private static void OnDestroyPostfix(InventoryGui __instance) { if (__instance == _ownerGui) { DestroyPanel(); } } private static void HidePanel() { _shownInventory = null; if ((Object)(object)_panel != (Object)null) { ((Component)_panel).gameObject.SetActive(false); } } private static void DestroyPanel() { if ((Object)(object)_panel != (Object)null) { Object.Destroy((Object)(object)((Component)_panel).gameObject); } _panel = null; _grid = null; _nameText = null; _weightText = null; _ownerGui = null; _shownInventory = null; } private static T FindClonedComponent<T>(Transform originalRoot, Transform cloneRoot, T original) where T : Component { if ((Object)(object)originalRoot == (Object)null || (Object)(object)cloneRoot == (Object)null || (Object)(object)original == (Object)null) { return default(T); } string relativePath = GetRelativePath(originalRoot, ((Component)original).transform); if (relativePath == null) { return default(T); } Transform val = ((relativePath.Length == 0) ? cloneRoot : cloneRoot.Find(relativePath)); if (!((Object)(object)val == (Object)null)) { return ((Component)val).GetComponent<T>(); } return default(T); } private static string GetRelativePath(Transform root, Transform target) { if (root == target) { return string.Empty; } string text = ((Object)target).name; Transform parent = target.parent; while ((Object)(object)parent != (Object)null && parent != root) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } if (!((Object)(object)parent == (Object)null)) { return text; } return null; } private static Exception Unwrap(Exception exception) { if (!(exception is TargetInvocationException { InnerException: not null } ex)) { return exception; } return ex.InnerException; } private static void LogFailure(string message, Exception exception) { if (!_failureLogged) { _failureLogged = true; VHModpackFixPlugin.LogWarning(message, Unwrap(exception)); } } } internal static class AzuAutoStoreLogFixes { private const string AzuAutoStoreGuid = "Azumatt.AzuAutoStore"; private const string AzuAutoStoreLogSource = "AzuAutoStore"; private static ConfigEntry<bool> _enabled; internal static void Init(Harmony harmony, ConfigFile config) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown _enabled = ConfigLayout.Bind(config, "AzuAutoStore", "Suppress verbose debug logging", defaultValue: true, "Suppresses only Debug-level AzuAutoStore messages such as repeated nearby-item scans. Warnings, errors, information messages, and storage behavior are unchanged.", "AzuAutoStore compatibility"); if (!Chainloader.PluginInfos.ContainsKey("Azumatt.AzuAutoStore")) { return; } MethodInfo methodInfo = AccessTools.Method(typeof(ManualLogSource), "Log", new Type[2] { typeof(LogLevel), typeof(object) }, (Type[])null); try { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(AzuAutoStoreLogFixes), "FilterAzuAutoStoreDebugPrefix", (Type[])null, (Type[])null)) { priority = 800 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); VHModpackFixPlugin.LogInfo("AzuAutoStore Debug-level log filter installed."); } catch (Exception exception) { VHModpackFixPlugin.LogWarning("Could not install the AzuAutoStore Debug-level log filter", exception); } } private static bool FilterAzuAutoStoreDebugPrefix(ManualLogSource __instance, LogLevel level) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 ConfigEntry<bool> enabled = _enabled; if (enabled != null && enabled.Value && (int)level == 32) { return !string.Equals((__instance != null) ? __instance.SourceName : null, "AzuAutoStore", StringComparison.Ordinal); } return true; } } internal static class AzuCraftyBoxesContainerSafety { private const string VanillaContainerTypeName = "AzuCraftyBoxes.IContainers.VanillaContainer"; private const string BoxesTypeName = "AzuCraftyBoxes.Util.Functions.Boxes"; private static readonly string[] RegistryFieldNames = new string[3] { "Containers", "ContainersToAdd", "ContainersToRemove" }; private static ConfigEntry<bool> _enabled; private static FieldInfo _wrappedContainerField; private static FieldInfo[] _registryFields; private static bool _initialized; private static bool _cleanupLogged; internal static void Init(Harmony harmony, ConfigFile config) { //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Expected O, but got Unknown _enabled = ConfigLayout.Bind(config, "AzuCraftyBoxes", "AzuCraftyBoxes destroyed-container safety", defaultValue: true, "Skips and unregisters cached AzuCraftyBoxes chest wrappers after Unity has destroyed their underlying container.", "Fixes"); if (_initialized || harmony == null) { return; } Type type = AccessTools.TypeByName("AzuCraftyBoxes.IContainers.VanillaContainer"); Type type2 = AccessTools.TypeByName("AzuCraftyBoxes.Util.Functions.Boxes"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "GetPrefabName", Type.EmptyTypes, (Type[])null)); _wrappedContainerField = ((type == null) ? null : AccessTools.Field(type, "<_container>P")); if (methodInfo == null || _wrappedContainerField == null || _wrappedContainerField.FieldType != typeof(Container) || type2 == null) { return; } _registryFields = new FieldInfo[RegistryFieldNames.Length]; for (int i = 0; i < RegistryFieldNames.Length; i++) { FieldInfo fieldInfo = AccessTools.Field(type2, RegistryFieldNames[i]); if (fieldInfo == null || fieldInfo.FieldType != typeof(HashSet<Container>)) { _registryFields = null; return; } _registryFields[i] = fieldInfo; } MethodInfo methodInfo2 = AccessTools.Method(typeof(AzuCraftyBoxesContainerSafety), "GetPrefabNamePrefix", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2) { priority = 800 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _initialized = true; } private static bool GetPrefabNamePrefix(object __instance, ref string __result) { ConfigEntry<bool> enabled = _enabled; if (enabled == null || !enabled.Value || __instance == null) { return true; } object? value = _wrappedContainerField.GetValue(__instance); Container val = (Container)((value is Container) ? value : null); if ((Object)(object)val != (Object)null) { return true; } __result = string.Empty; if (val != null) { RemoveDestroyedContainer(val); } return false; } private static void RemoveDestroyedContainer(Container container) { bool flag = false; for (int i = 0; i < _registryFields.Length; i++) { if (_registryFields[i].GetValue(null) is HashSet<Container> hashSet) { flag |= hashSet.Remove(container); } } if (flag && !_cleanupLogged) { _cleanupLogged = true; VHModpackFixPlugin.LogInfo("Removed a destroyed container reference from AzuCraftyBoxes' registry"); } } } internal static class BalrondArsenalVisualFixes { private static readonly HashSet<int> AffectedChestPrefabHashes = new HashSet<int> { StringExtensionMethods.GetStableHashCode("ArmorDruidChest_bal"), StringExtensionMethods.GetStableHashCode("ArmorFrosteelChest_bal"), StringExtensionMethods.GetStableHashCode("ArmorMercChest_bal"), StringExtensionMethods.GetStableHashCode("ArmorSerpentLordChest_bal"), StringExtensionMethods.GetStableHashCode("ArmorSkaldChest_bal") }; private static readonly HashSet<int> AffectedLegPrefabHashes = new HashSet<int> { StringExtensionMethods.GetStableHashCode("ArmorFrosteelLegs_bal"), StringExtensionMethods.GetStableHashCode("ArmorLoxLegs_bal"), StringExtensionMethods.GetStableHashCode("ArmorSerpentLordLegs_bal") }; private static readonly FieldRef<VisEquipment, List<GameObject>> ChestItemInstances = AccessTools.FieldRefAccess<VisEquipment, List<GameObject>>("m_chestItemInstances"); private static readonly FieldRef<VisEquipment, List<GameObject>> LegItemInstances = AccessTools.FieldRefAccess<VisEquipment, List<GameObject>>("m_legItemInstances"); private static ConfigEntry<bool> _enabled; internal static void Bind(ConfigFile config) { _enabled = ConfigLayout.Bind(config, "Balrond Arsenal", "Enable Balrond Arsenal fixes", defaultValue: true, "Repair stretched Balrond Arsenal chest and leg armor without hiding or replacing any visual parts.", "Global Fix Switches"); } internal static void RestoreChestBones(VisEquipment equipment, int itemHash, bool changed) { if (ShouldRepair(equipment, itemHash, changed, AffectedChestPrefabHashes)) { RestoreDamagedBindings(equipment, ChestItemInstances.Invoke(equipment)); } } internal static void RestoreLegBones(VisEquipment equipment, int itemHash, bool changed) { if (ShouldRepair(equipment, itemHash, changed, AffectedLegPrefabHashes)) { RestoreDamagedBindings(equipment, LegItemInstances.Invoke(equipment)); } } private static bool ShouldRepair(VisEquipment equipment, int itemHash, bool changed, HashSet<int> affectedPrefabHashes) { if ((_enabled?.Value ?? false) && changed && (Object)(object)equipment != (Object)null) { return affectedPrefabHashes.Contains(itemHash); } return false; } private static void RestoreDamagedBindings(VisEquipment equipment, List<GameObject> roots) { SkinnedMeshRenderer bodyModel = equipment.m_bodyModel; Transform[] array = ((bodyModel != null) ? bodyModel.bones : null); if ((Object)(object)bodyModel == (Object)null || (Object)(object)bodyModel.rootBone == (Object)null || array == null || array.Length == 0 || ContainsNull(array) || roots == null) { return; } for (int i = 0; i < roots.Count; i++) { GameObject val = roots[i]; if ((Object)(object)val == (Object)null) { continue; } SkinnedMeshRenderer[] componentsInChildren = val.GetComponentsInChildren<SkinnedMeshRenderer>(true); foreach (SkinnedMeshRenderer val2 in componentsInChildren) { Mesh val3 = ((val2 != null) ? val2.sharedMesh : null); Transform[] array2 = ((val2 != null) ? val2.bones : null); if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val3 == (Object)null) && array2 != null && array2.Length == array.Length && val3.bindposeCount == array.Length && RepairNullBones(array2, array)) { val2.rootBone = bodyModel.rootBone; val2.bones = array2; } } } } private static bool RepairNullBones(Transform[] rendererBones, Transform[] bodyBones) { bool result = false; for (int i = 0; i < rendererBones.Length; i++) { if (!((Object)(object)rendererBones[i] != (Object)null)) { rendererBones[i] = bodyBones[i]; result = true; } } return result; } private static bool ContainsNull(Transform[] transforms) { for (int i = 0; i < transforms.Length; i++) { if ((Object)(object)transforms[i] == (Object)null) { return true; } } return false; } } [HarmonyPatch(typeof(VisEquipment), "SetChestEquipped", new Type[] { typeof(int) })] [HarmonyAfter(new string[] { "vapok.mods.adventurebackpacks", "com.jotunn.jotunn" })] internal static class BalrondArsenalVisEquipmentSetChestPatch { [HarmonyPriority(0)] private static void Postfix(VisEquipment __instance, int hash, bool __result) { BalrondArsenalVisualFixes.RestoreChestBones(__instance, hash, __result); } } [HarmonyPatch(typeof(VisEquipment), "SetLegEquipped", new Type[] { typeof(int) })] [HarmonyAfter(new string[] { "vapok.mods.adventurebackpacks", "com.jotunn.jotunn" })] internal static class BalrondArsenalVisEquipmentSetLegPatch { [HarmonyPriority(0)] private static void Postfix(VisEquipment __instance, int hash, bool __result) { BalrondArsenalVisualFixes.RestoreLegBones(__instance, hash, __result); } } internal static class BossAddNetworkVfxFixes { private const string BossAddGuid = "bossadd"; private static readonly MethodInfo UnityDestroyDelayed = AccessTools.Method(typeof(Object), "Destroy", new Type[2] { typeof(Object), typeof(float) }, (Type[])null); private static readonly MethodInfo SafeDestroyDelayed = AccessTools.Method(typeof(BossAddNetworkVfxFixes), "DestroyTemporaryVfxSafely", new Type[2] { typeof(Object), typeof(float) }, (Type[])null); private static readonly MethodInfo UnityDestroyImmediate = AccessTools.Method(typeof(Object), "Destroy", new Type[1] { typeof(Object) }, (Type[])null); private static readonly MethodInfo SafeDestroyImmediate = AccessTools.Method(typeof(BossAddNetworkVfxFixes), "DestroyTemporaryVfxSafely", new Type[1] { typeof(Object) }, (Type[])null); private static ConfigEntry<bool> _enabled; private static ConfigEntry<bool> _safeMiniBonemassProjectiles; internal static void Init(Harmony harmony, ConfigFile config) { _enabled = ConfigLayout.Bind(config, "BossAdd", "Safe temporary VFX cleanup", defaultValue: true, "Prevents BossAdd temporary boss effects from leaving destroyed network objects in Valheim's zone registry. This removes the repeating ZNetScene.RemoveObjects error that can appear after teleporting or unloading a zone. The switch affects future BossAdd cleanup immediately. Fully restart Valheim once after installing or updating, and restart if the repeating error began before this version was loaded.", "BossAdd compatibility"); _safeMiniBonemassProjectiles = ConfigLayout.Bind(config, "BossAdd", "Safe MiniBonemass projectile blocking", defaultValue: true, "Replaces BossAdd's unsafe Projectile.Setup cancellation for MiniBonemass. The projectile is initialized normally, then removed through Valheim's network scene before it can update or hit anything. This preserves BossAdd's intended projectile block without leaving SpawnAbility with a null owner. Restart Valheim after changing this setting.", "BossAdd compatibility"); if (Chainloader.PluginInfos.ContainsKey("bossadd")) { int num = 0; num += PatchMethod(harmony, "bossadd.Patches.BossSummonHelper", "SpecialSummon", "ReplaceDelayedVfxDestroyTranspiler"); num += PatchMethod(harmony, "bossadd.Patches.QueenBreathSummonPatch", "TrySummon", "ReplaceDelayedVfxDestroyTranspiler"); num += PatchMethod(harmony, "bossadd.Patches.QueenBroodSummonHelper", "DoSummon", "ReplaceDelayedVfxDestroyTranspiler"); num += PatchMethod(harmony, "bossadd.Patches.YagluthSkeletonSummonPatch", "DoSummon", "ReplaceDelayedVfxDestroyTranspiler"); num += PatchMethod(harmony, "bossadd.Patches.YagluthDeathZoneHandler", "OnAttackTrigger", "ReplaceDelayedVfxDestroyTranspiler"); num += PatchMethod(harmony, "bossadd.Patches.YagluthMeteorFireHandler", "Tick", "ReplaceImmediateVfxDestroyTranspiler"); num += PatchMethod(harmony, "bossadd.Patches.QueenPoisonZoneHandler", "Tick", "ReplaceImmediateVfxDestroyTranspiler"); num += PatchMethod(harmony, "bossadd.Patches.QueenPoisonZoneHandler", "SpawnZone", "ReplaceImmediateVfxDestroyTranspiler"); num += PatchMethod(harmony, "bossadd.Patches.QueenPoisonZoneHandler", "OnQueenDeath", "ReplaceImmediateVfxDestroyTranspiler"); VHModpackFixPlugin.LogInfo($"BossAdd network-VFX compatibility installed on {num}/9 cleanup paths."); if (_safeMiniBonemassProjectiles.Value) { InstallMiniBonemassProjectileRepair(harmony); } } } private static void InstallMiniBonemassProjectileRepair(Harmony harmony) { //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown Type type = AccessTools.TypeByName("bossadd.Patches.MiniBonemassProjectileBlockPatch"); MethodInfo unsafePrefix = ((type == null) ? null : AccessTools.Method(type, "Prefix", new Type[1] { typeof(Character) }, (Type[])null)); MethodInfo methodInfo = AccessTools.Method(typeof(Projectile), "Setup", new Type[6] { typeof(Character), typeof(Vector3), typeof(float), typeof(HitData), typeof(ItemData), typeof(ItemData) }, (Type[])null); if (unsafePrefix == null || methodInfo == null) { VHModpackFixPlugin.LogWarning("BossAdd MiniBonemass projectile targets were not found; the safety repair was skipped.", null); return; } Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo); if (patchInfo == null || !patchInfo.Prefixes.Any((Patch patch) => patch.PatchMethod == unsafePrefix)) { VHModpackFixPlugin.LogWarning("BossAdd MiniBonemass Projectile.Setup blocker was not installed; no patch was removed or replaced.", null); return; } try { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(BossAddNetworkVfxFixes), "RemoveBlockedMiniBonemassProjectilePostfix", (Type[])null, (Type[])null)) { priority = 0 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Unpatch((MethodBase)methodInfo, unsafePrefix); VHModpackFixPlugin.LogInfo("BossAdd MiniBonemass projectile blocker replaced with initialize-then-network-destroy handling."); } catch (Exception exception) { VHModpackFixPlugin.LogWarning("Could not replace the BossAdd MiniBonemass projectile blocker", exception); } } private static void RemoveBlockedMiniBonemassProjectilePostfix(Projectile __instance, Character owner) { if (!Object.op_Implicit((Object)(object)__instance) || !IsMiniBonemass(owner)) { return; } GameObject gameObject = ((Component)__instance).gameObject; ZNetView component = gameObject.GetComponent<ZNetView>(); ZNetScene instance = ZNetScene.instance; if (Object.op_Implicit((Object)(object)component) && component.IsValid()) { if (Object.op_Implicit((Object)(object)instance) && component.IsOwner()) { ((Behaviour)__instance).enabled = false; instance.Destroy(gameObject); } } else { ((Behaviour)__instance).enabled = false; Object.Destroy((Object)(object)gameObject); } } private static bool IsMiniBonemass(Character owner) { if (!Object.op_Implicit((Object)(object)owner)) { return false; } return Utils.GetPrefabName(((Component)owner).gameObject)?.StartsWith("MiniBonemass_", StringComparison.Ordinal) ?? false; } private static int PatchMethod(Harmony harmony, string typeName, string methodName, string transpilerName) { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown Type type = AccessTools.TypeByName(typeName); if (type == null) { VHModpackFixPlugin.LogWarning("BossAdd compatibility target type '" + typeName + "' was not found; this path was skipped.", null); return 0; } MethodInfo[] array = (from method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where method.Name == methodName select method).ToArray(); if (array.Length != 1) { VHModpackFixPlugin.LogWarning($"BossAdd compatibility expected one '{typeName}.{methodName}' method but found {array.Length}; this path was skipped.", null); return 0; } MethodInfo methodInfo = AccessTools.Method(typeof(BossAddNetworkVfxFixes), transpilerName, (Type[])null, (Type[])null); try { harmony.Patch((MethodBase)array[0], (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo) { priority = 0 }, (HarmonyMethod)null, (HarmonyMethod)null); return 1; } catch (Exception exception) { VHModpackFixPlugin.LogWarning("Could not install BossAdd compatibility for " + typeName + "." + methodName, exception); return 0; } } private static IEnumerable<CodeInstruction> ReplaceDelayedVfxDestroyTranspiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod) { List<CodeInstruction> list = instructions.ToList(); List<int> list2 = new List<int>(); for (int i = 0; i < list.Count; i++) { if (CodeInstructionExtensions.Calls(list[i], UnityDestroyDelayed)) { list2.Add(i); } } if (list2.Count != 1) { VHModpackFixPlugin.LogWarning($"BossAdd compatibility found {list2.Count} delayed VFX cleanup calls in {Describe(__originalMethod)}; expected one, so its IL was left unchanged.", null); return list; } list[list2[0]].opcode = OpCodes.Call; list[list2[0]].operand = SafeDestroyDelayed; return list; } private static IEnumerable<CodeInstruction> ReplaceImmediateVfxDestroyTranspiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod) { List<CodeInstruction> list = instructions.ToList(); List<int> list2 = new List<int>(); for (int i = 0; i < list.Count; i++) { if (CodeInstructionExtensions.Calls(list[i], UnityDestroyImmediate)) { list2.Add(i); } } if (list2.Count != 1) { VHModpackFixPlugin.LogWarning($"BossAdd compatibility found {list2.Count} immediate VFX cleanup calls in {Describe(__originalMethod)}; expected one, so its IL was left unchanged.", null); return list; } list[list2[0]].opcode = OpCodes.Call; list[list2[0]].operand = SafeDestroyImmediate; return list; } private static void DestroyTemporaryVfxSafely(Object value, float delay) { if (IsEnabled()) { GameObject val = (GameObject)(object)((value is GameObject) ? value : null); if (val != null && HasLiveNetworkView(val)) { BossAddSafeVfxCleanup bossAddSafeVfxCleanup = val.GetComponent<BossAddSafeVfxCleanup>(); if (!Object.op_Implicit((Object)(object)bossAddSafeVfxCleanup)) { bossAddSafeVfxCleanup = val.AddComponent<BossAddSafeVfxCleanup>(); } bossAddSafeVfxCleanup.Schedule(delay); return; } } Object.Destroy(value, delay); } private static void DestroyTemporaryVfxSafely(Object value) { if (IsEnabled()) { GameObject val = (GameObject)(object)((value is GameObject) ? value : null); if (val != null && HasLiveNetworkView(val)) { DestroyNetworkedHierarchy(val); return; } } Object.Destroy(value); } private static bool HasLiveNetworkView(GameObject root) { ZNetView[] componentsInChildren = root.GetComponentsInChildren<ZNetView>(true); for (int i = 0; i < componentsInChildren.Length; i++) { if (Object.op_Implicit((Object)(object)componentsInChildren[i]) && componentsInChildren[i].GetZDO() != null) { return true; } } return false; } internal static void DestroyNetworkedHierarchy(GameObject root) { if (!Object.op_Implicit((Object)(object)root)) { return; } ZNetScene instance = ZNetScene.instance; ZNetView[] componentsInChildren = root.GetComponentsInChildren<ZNetView>(true); bool flag = false; foreach (ZNetView val in componentsInChildren) { if (Object.op_Implicit((Object)(object)val) && val.GetZDO() != null) { flag = true; break; } } if (!flag) { Object.Destroy((Object)(object)root); } else { if (!Object.op_Implicit((Object)(object)instance) || ZDOMan.instance == null) { return; } foreach (ZNetView val2 in componentsInChildren) { if (Object.op_Implicit((Object)(object)val2) && val2.GetZDO() != null) { if (!val2.IsOwner()) { val2.ClaimOwnership(); } if (!val2.IsOwner()) { return; } } } for (int num = componentsInChildren.Length - 1; num >= 0; num--) { ZNetView val3 = componentsInChildren[num]; if (Object.op_Implicit((Object)(object)val3) && val3.GetZDO() != null) { instance.Destroy(((Component)val3).gameObject); } } if (Object.op_Implicit((Object)(object)root)) { Object.Destroy((Object)(object)root); } } } private static bool IsEnabled() { return _enabled?.Value ?? false; } private static string Describe(MethodBase method) { if (!(method == null)) { return method.DeclaringType?.FullName + "." + method.Name; } return "an unknown method"; } } public sealed class BossAddSafeVfxCleanup : MonoBehaviour { private bool _scheduled; internal void Schedule(float delay) { if