Decompiled source of BiggerItemStack v2.0.0

BepInEx/plugins/BiggerItemStack/BiggerItemStack.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Bigger Item Stack")]
[assembly: AssemblyDescription("Stack and weight multipliers synchronized with Jotunn")]
[assembly: AssemblyCompany("Sixefyle")]
[assembly: AssemblyProduct("BiggerItemStack")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: AssemblyInformationalVersion("2.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("2.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BiggerItemStack
{
	[BepInPlugin("org.bepinex.plugins.bigger_item_Stack", "Bigger Item Stack", "2.0.0")]
	[BepInDependency("com.jotunn.jotunn", "2.30.2")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class ValheimMultipliersPlugin : BaseUnityPlugin
	{
		private sealed class PlayerDefaults
		{
			internal readonly float CarryWeight;

			internal PlayerDefaults(float carryWeight)
			{
				CarryWeight = carryWeight;
			}
		}

		private sealed class InventoryState
		{
			internal long Revision = -1L;
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private static class ObjectDatabaseAwakePatch
		{
			private static void Postfix(ObjectDB __instance)
			{
				instance?.ApplyPrefabs(__instance);
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		private static class ObjectDatabaseCopyPatch
		{
			private static void Postfix(ObjectDB __instance)
			{
				instance?.ApplyPrefabs(__instance);
			}
		}

		[HarmonyPatch(typeof(ItemDrop), "Awake")]
		private static class ItemAwakePatch
		{
			private static void Postfix(ItemDrop __instance)
			{
				instance?.ApplyItem(__instance.m_itemData);
			}
		}

		[HarmonyPatch(typeof(Player), "Awake")]
		private static class PlayerAwakePatch
		{
			private static void Postfix(Player __instance)
			{
				instance?.ApplyPlayer(__instance);
			}
		}

		[HarmonyPatch(typeof(Inventory), "UpdateTotalWeight")]
		private static class InventoryWeightUpdatePatch
		{
			private static void Prefix(Inventory __instance)
			{
				instance?.TrackInventory(__instance);
			}
		}

		[HarmonyPatch(typeof(Inventory), "GetTotalWeight")]
		private static class InventoryWeightReadPatch
		{
			private static void Prefix(Inventory __instance)
			{
				if ((Object)(object)instance != (Object)null && instance.inventoryStates.GetValue(__instance, (Inventory value) => new InventoryState()).Revision != instance.revision)
				{
					RecalculateInventoryWeight(__instance);
				}
			}
		}

		public const string PluginGuid = "org.bepinex.plugins.bigger_item_Stack";

		public const string PluginName = "Bigger Item Stack";

		public const string PluginVersion = "2.0.0";

		private static ValheimMultipliersPlugin instance;

		private static ConfigEntry<double> stackMultiplier;

		private static ConfigEntry<float> itemWeightMultiplier;

		private static ConfigEntry<float> playerWeightMultiplier;

		private readonly ItemDefaultsCache<SharedData> itemDefaults = new ItemDefaultsCache<SharedData>();

		private readonly ConditionalWeakTable<Player, PlayerDefaults> playerDefaults = new ConditionalWeakTable<Player, PlayerDefaults>();

		private readonly ConditionalWeakTable<Inventory, InventoryState> inventoryStates = new ConditionalWeakTable<Inventory, InventoryState>();

		private static readonly Action<Inventory> RecalculateInventoryWeight = AccessTools.MethodDelegate<Action<Inventory>>(AccessTools.Method(typeof(Inventory), "UpdateTotalWeight", (Type[])null, (Type[])null), (object)null, true);

		private Harmony harmony;

		private long revision;

		private void Awake()
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			instance = this;
			BindConfiguration();
			stackMultiplier.SettingChanged += OnSettingChanged;
			itemWeightMultiplier.SettingChanged += OnSettingChanged;
			playerWeightMultiplier.SettingChanged += OnSettingChanged;
			SynchronizationManager.OnConfigurationSynchronized += OnConfigurationSynchronized;
			ItemManager.OnItemsRegistered += RefreshValues;
			ItemManager.OnItemsRegisteredFejd += RefreshValues;
			harmony = new Harmony("org.bepinex.plugins.bigger_item_Stack");
			harmony.PatchAll(typeof(ValheimMultipliersPlugin).Assembly);
			RefreshValues();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Bigger Item Stack 2.0.0 by Sixefyle; Jotunn configuration synchronization enabled.");
		}

		private void BindConfiguration()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Expected O, but got Unknown
			stackMultiplier = ((BaseUnityPlugin)this).Config.Bind<double>("Multiplier", "ItemMaxStackMultiplier", 2.0, new ConfigDescription("Maximum stack multiplier. Unstackable items stay unstackable; stack limits are capped at 65535.", (AcceptableValueBase)(object)new AcceptableValueRange<double>(0.01, 1000.0), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			itemWeightMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Multiplier", "ItemWeightMultiplier", 1f, new ConfigDescription("Item weight multiplier. Zero makes items weightless.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			playerWeightMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Multiplier", "PlayerWeightMultiplier", 1f, new ConfigDescription("Base player carry capacity multiplier. Equipment and status-effect bonuses are then applied by Valheim.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1000f), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
		}

		private void OnSettingChanged(object sender, EventArgs args)
		{
			RefreshValues();
		}

		private void OnConfigurationSynchronized(object sender, ConfigurationSynchronizationEventArgs args)
		{
			if (args.InitialSynchronization || args.UpdatedPluginGUIDs.Contains("org.bepinex.plugins.bigger_item_Stack"))
			{
				RefreshValues();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Synchronized multipliers: stacks=" + stackMultiplier.Value + ", item weight=" + itemWeightMultiplier.Value + ", carry capacity=" + playerWeightMultiplier.Value));
			}
		}

		private void RefreshValues()
		{
			revision++;
			ApplyPrefabs(ObjectDB.instance);
			itemDefaults.ForEach(ApplySharedData);
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				ApplyPlayer(allPlayer);
			}
		}

		private void ApplyPrefabs(ObjectDB database)
		{
			if (!Object.op_Implicit((Object)(object)database) || database.m_items == null)
			{
				return;
			}
			foreach (GameObject item in database.m_items)
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					ItemDrop component = item.GetComponent<ItemDrop>();
					SharedData val = ((!Object.op_Implicit((Object)(object)component)) ? null : component.m_itemData?.m_shared);
					if (val != null)
					{
						ItemDefaults defaults = itemDefaults.TrackPrefab(((Object)item).name, val, val.m_maxStackSize, val.m_weight);
						ApplySharedData(val, defaults);
					}
				}
			}
		}

		private void ApplyItem(ItemData item)
		{
			if (item?.m_shared == null)
			{
				return;
			}
			GameObject dropPrefab = item.m_dropPrefab;
			string text = (Object.op_Implicit((Object)(object)dropPrefab) ? ((Object)dropPrefab).name : null);
			if (Object.op_Implicit((Object)(object)dropPrefab))
			{
				ItemDrop component = dropPrefab.GetComponent<ItemDrop>();
				SharedData val = ((!Object.op_Implicit((Object)(object)component)) ? null : component.m_itemData?.m_shared);
				if (val != null)
				{
					itemDefaults.TrackPrefab(text, val, val.m_maxStackSize, val.m_weight);
				}
			}
			SharedData shared = item.m_shared;
			ItemDefaults defaults = itemDefaults.TrackItem(text, shared, shared.m_maxStackSize, shared.m_weight);
			ApplySharedData(shared, defaults);
		}

		private static void ApplySharedData(SharedData shared, ItemDefaults defaults)
		{
			shared.m_maxStackSize = MultiplierMath.StackSize(defaults.StackSize, stackMultiplier.Value);
			shared.m_weight = MultiplierMath.ItemWeight(defaults.Weight, itemWeightMultiplier.Value);
		}

		private void ApplyPlayer(Player player)
		{
			if (Object.op_Implicit((Object)(object)player))
			{
				PlayerDefaults value = playerDefaults.GetValue(player, (Player val) => new PlayerDefaults(val.m_maxCarryWeight));
				player.m_maxCarryWeight = MultiplierMath.CarryWeight(value.CarryWeight, playerWeightMultiplier.Value);
			}
		}

		private void TrackInventory(Inventory inventory)
		{
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				ApplyItem(allItem);
			}
			inventoryStates.GetValue(inventory, (Inventory value) => new InventoryState()).Revision = revision;
		}

		private void OnDestroy()
		{
			stackMultiplier.SettingChanged -= OnSettingChanged;
			itemWeightMultiplier.SettingChanged -= OnSettingChanged;
			playerWeightMultiplier.SettingChanged -= OnSettingChanged;
			SynchronizationManager.OnConfigurationSynchronized -= OnConfigurationSynchronized;
			ItemManager.OnItemsRegistered -= RefreshValues;
			ItemManager.OnItemsRegisteredFejd -= RefreshValues;
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			itemDefaults.ForEach(delegate(SharedData shared, ItemDefaults defaults)
			{
				shared.m_maxStackSize = defaults.StackSize;
				shared.m_weight = defaults.Weight;
			});
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				if (Object.op_Implicit((Object)(object)allPlayer) && playerDefaults.TryGetValue(allPlayer, out var value))
				{
					allPlayer.m_maxCarryWeight = value.CarryWeight;
					RecalculateInventoryWeight(((Humanoid)allPlayer).GetInventory());
				}
			}
			instance = null;
		}
	}
	internal static class MultiplierMath
	{
		internal const int MaximumStackSize = 65535;

		internal const double MaximumMultiplier = 1000.0;

		internal static int StackSize(int original, double multiplier)
		{
			if (original <= 1)
			{
				return original;
			}
			double d = (double)original * Normalize(multiplier, 2.0, 0.01);
			return (int)Math.Max(1.0, Math.Min(65535.0, Math.Floor(d)));
		}

		internal static float ItemWeight(float original, float multiplier)
		{
			return ScaleWeight(original, Normalize(multiplier, 1.0, 0.0));
		}

		internal static float CarryWeight(float original, float multiplier)
		{
			return ScaleWeight(original, Normalize(multiplier, 1.0, 0.01));
		}

		private static float ScaleWeight(float original, double multiplier)
		{
			return (float)Math.Min(3.4028234663852886E+38, Math.Max(0.0, (double)original * multiplier));
		}

		private static double Normalize(double value, double fallback, double minimum)
		{
			if (double.IsNaN(value) || double.IsInfinity(value))
			{
				return fallback;
			}
			return Math.Max(minimum, Math.Min(1000.0, value));
		}
	}
	internal sealed class ItemDefaults
	{
		internal readonly int StackSize;

		internal readonly float Weight;

		internal ItemDefaults(int stackSize, float weight)
		{
			StackSize = stackSize;
			Weight = weight;
		}
	}
	internal sealed class ItemDefaultsCache<T> where T : class
	{
		private readonly ConditionalWeakTable<T, ItemDefaults> originals = new ConditionalWeakTable<T, ItemDefaults>();

		private readonly Dictionary<string, ItemDefaults> prefabs = new Dictionary<string, ItemDefaults>(StringComparer.Ordinal);

		private readonly List<WeakReference<T>> known = new List<WeakReference<T>>();

		internal ItemDefaults TrackPrefab(string name, T shared, int stackSize, float weight)
		{
			if (!originals.TryGetValue(shared, out var value))
			{
				value = Remember(shared, new ItemDefaults(stackSize, weight));
			}
			prefabs[name] = value;
			return value;
		}

		internal ItemDefaults TrackItem(string prefabName, T shared, int stackSize, float weight)
		{
			if (originals.TryGetValue(shared, out var value))
			{
				return value;
			}
			if (prefabName == null || !prefabs.TryGetValue(prefabName, out value))
			{
				value = new ItemDefaults(stackSize, weight);
			}
			return Remember(shared, value);
		}

		internal void ForEach(Action<T, ItemDefaults> action)
		{
			for (int num = known.Count - 1; num >= 0; num--)
			{
				if (known[num].TryGetTarget(out var target) && originals.TryGetValue(target, out var value))
				{
					action(target, value);
				}
				else
				{
					known.RemoveAt(num);
				}
			}
		}

		private ItemDefaults Remember(T shared, ItemDefaults defaults)
		{
			originals.Add(shared, defaults);
			known.Add(new WeakReference<T>(shared));
			return defaults;
		}
	}
}