Decompiled source of ItemStackerFix v1.0.8

plugin/ItemStackerFix.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ItemStackerFix")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ItemStackerFix")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("68fef771-f28c-4880-bfed-027323d829a8")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
[BepInPlugin("com.travv.aleandtale.itemstack99safe", "ItemStack99 Safe (Vanilla Shop + 99 Stacks)", "1.0.9")]
public class ItemStack99Safe : BaseUnityPlugin
{
	internal const ushort NewMax = 99;

	internal static readonly Dictionary<ushort, ushort> OriginalMaxById = new Dictionary<ushort, ushort>();

	[ThreadStatic]
	internal static bool InShopTransaction;

	internal static ItemStack99Safe Instance;

	private void Awake()
	{
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		ItemData[] array = Resources.FindObjectsOfTypeAll<ItemData>();
		int num = 0;
		ItemData[] array2 = array;
		foreach (ItemData val in array2)
		{
			if (!((Object)(object)val == (Object)null))
			{
				if (!OriginalMaxById.ContainsKey(val.id))
				{
					OriginalMaxById[val.id] = val.maxStack;
				}
				if (val.maxStack > 1 && val.maxStack < 99)
				{
					val.maxStack = 99;
					num++;
				}
			}
		}
		new Harmony("com.travv.aleandtale.itemstack99safe").PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)$"ItemStack99Safe loaded. Updated {num}/{array.Length} ItemData maxStack values to {(ushort)99}.");
	}

	internal static ushort GetOriginalMax(ushort itemDataId)
	{
		ushort value;
		return (ushort)((!OriginalMaxById.TryGetValue(itemDataId, out value) || value <= 0) ? 1 : value);
	}

	internal static ushort GetVanillaMaxForMath(ItemData data)
	{
		if ((Object)(object)data == (Object)null)
		{
			return 1;
		}
		return GetOriginalMax(data.id);
	}

	internal static ushort GetShopPurchaseAmount(ItemData data)
	{
		if ((Object)(object)data == (Object)null)
		{
			return 1;
		}
		return (ushort)(data.buyByOne ? 1 : GetOriginalMax(data.id));
	}

	internal static void ApplyShopAmount(ref Item item)
	{
		ItemData val = default(ItemData);
		if (!((Object)(object)ItemManager.Instance == (Object)null) && ItemManager.Instance.GetItemData((uint)item.dataId, ref val) && !((Object)(object)val == (Object)null))
		{
			item.amount = GetShopPurchaseAmount(val);
			if (item.amount <= 0)
			{
				item.amount = 1;
			}
		}
	}

	internal static bool IsInShopSellContext()
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Invalid comparison between Unknown and I4
		if (InShopTransaction)
		{
			return true;
		}
		if ((Object)(object)PlayerInventory.Instance != (Object)null && (int)PlayerInventory.Instance.state == 15)
		{
			return true;
		}
		return false;
	}
}
[HarmonyPatch(typeof(ItemManager), "BuyServerRpc")]
public static class Patch_ItemManager_BuyServerRpc_Flag
{
	private static void Prefix()
	{
		ItemStack99Safe.InShopTransaction = true;
	}

	private static void Postfix()
	{
		ItemStack99Safe.InShopTransaction = false;
	}
}
[HarmonyPatch(typeof(ItemManager), "SellItemServerRpc")]
public static class Patch_ItemManager_SellItemServerRpc_Flag
{
	private static void Prefix()
	{
		ItemStack99Safe.InShopTransaction = true;
	}

	private static void Postfix()
	{
		ItemStack99Safe.InShopTransaction = false;
	}
}
[HarmonyPatch(typeof(ItemData), "GetItemPrice")]
public static class Patch_ItemData_GetItemPrice_ShopVanilla
{
	private static bool Prefix(ItemData __instance, ref ushort __result)
	{
		if (!ItemStack99Safe.InShopTransaction || (Object)(object)__instance == (Object)null)
		{
			return true;
		}
		ushort num = ItemStack99Safe.GetOriginalMax(__instance.id);
		if (num <= 0)
		{
			num = 1;
		}
		ushort num2 = (__instance.buyByOne ? ((ushort)Mathf.FloorToInt(1f * (float)(int)__instance.price / (float)(int)num)) : __instance.price);
		if (__instance.maxCharge > 0 && (Object)(object)__instance.containerClean != (Object)null)
		{
			num2 += __instance.containerClean.price;
		}
		__result = num2;
		return false;
	}
}
[HarmonyPatch(typeof(ItemManager), "GetItemSellPrice")]
public static class Patch_ItemManager_GetItemSellPrice_ShopVanilla
{
	private static bool Prefix(ItemManager __instance, Item item, ItemData itemData, ref ushort __result)
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Invalid comparison between Unknown and I4
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		if (!ItemStack99Safe.IsInShopSellContext() || (Object)(object)itemData == (Object)null)
		{
			return true;
		}
		ushort num = ItemStack99Safe.GetOriginalMax(itemData.id);
		if (num <= 0)
		{
			num = 1;
		}
		int num2 = itemData.price;
		if ((int)itemData.type == 10 && itemData.durability > 0)
		{
			num2 = Mathf.FloorToInt(1f * (float)num2 / (1f + (float)(int)item.repairCount));
		}
		else if (num > 1 && item.amount < num)
		{
			num2 = Mathf.FloorToInt(1f * (float)num2 * (float)(int)item.amount / (float)(int)num);
		}
		else if (itemData.maxCharge > 0 && (Object)(object)itemData.containerClean != (Object)null)
		{
			num2 = itemData.containerClean.price + Mathf.FloorToInt(1f * (float)num2 * (float)(int)item.charge / (float)(int)itemData.maxCharge);
		}
		else if (itemData.durability > 0 && item.durability < itemData.durability)
		{
			num2 = Mathf.FloorToInt(1f * (float)num2 * (float)(int)item.durability / (float)(int)itemData.durability);
		}
		__result = (ushort)num2;
		return false;
	}
}
[HarmonyPatch]
public static class Patch_ContainerNet_AddNewItem_AllOverloads
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		Type typeFromHandle = typeof(ContainerNet);
		return (from m in typeFromHandle.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
			where m.Name == "AddNewItem"
			select m).Where(delegate(MethodInfo m)
		{
			ParameterInfo[] parameters = m.GetParameters();
			return parameters.Length >= 1 && parameters[0].ParameterType == typeof(Item);
		}).Cast<MethodBase>();
	}

	private static void Prefix(ref Item item)
	{
		if (ItemStack99Safe.InShopTransaction)
		{
			ItemStack99Safe.ApplyShopAmount(ref item);
			return;
		}
		if (item.amount <= 0)
		{
			item.amount = 1;
		}
		if (item.amount > 99)
		{
			item.amount = 99;
		}
	}
}
[HarmonyPatch(typeof(ShopItemUI), "SetItemData")]
public static class Patch_ShopItemUI_SetItemData_ShowVanilla
{
	[ThreadStatic]
	private static ItemData _swapped;

	[ThreadStatic]
	private static ushort _saved;

	private static void Prefix(ItemData itemData)
	{
		_swapped = null;
		if (!((Object)(object)itemData == (Object)null))
		{
			_swapped = itemData;
			_saved = itemData.maxStack;
			itemData.maxStack = ItemStack99Safe.GetVanillaMaxForMath(itemData);
		}
	}

	private static void Postfix()
	{
		if ((Object)(object)_swapped != (Object)null)
		{
			_swapped.maxStack = _saved;
			_swapped = null;
		}
	}
}
[HarmonyPatch(typeof(ShopItemUI), "Upd")]
public static class Patch_ShopItemUI_Upd_ShowVanilla
{
	[ThreadStatic]
	private static ItemData _swapped;

	[ThreadStatic]
	private static ushort _saved;

	private static void Prefix(ShopItemUI __instance)
	{
		_swapped = null;
		if (!((Object)(object)__instance == (Object)null))
		{
			ItemData value = Traverse.Create((object)__instance).Field("_itemData").GetValue<ItemData>();
			if (!((Object)(object)value == (Object)null))
			{
				_swapped = value;
				_saved = value.maxStack;
				value.maxStack = ItemStack99Safe.GetVanillaMaxForMath(value);
			}
		}
	}

	private static void Postfix()
	{
		if ((Object)(object)_swapped != (Object)null)
		{
			_swapped.maxStack = _saved;
			_swapped = null;
		}
	}
}
[HarmonyPatch(typeof(ItemManager), "GetCommonLootItem")]
public static class Patch_ItemManager_GetCommonLootItem_VanillaAmounts
{
	private static void Postfix(ref Item __result)
	{
		ItemData val = default(ItemData);
		if ((Object)(object)ItemManager.Instance == (Object)null || !ItemManager.Instance.GetItemData((uint)__result.dataId, ref val) || (Object)(object)val == (Object)null || val.maxStack <= 1)
		{
			return;
		}
		ushort originalMax = ItemStack99Safe.GetOriginalMax(val.id);
		if (originalMax > 1)
		{
			if (__result.amount < 1)
			{
				__result.amount = 1;
			}
			if (__result.amount > originalMax)
			{
				__result.amount = originalMax;
			}
		}
	}
}
[HarmonyPatch(typeof(ItemManager), "GetCommonLootItem")]
public static class Patch_ItemManager_GetCommonLootItem_RandomVanilla
{
	private static void Postfix(ref Item __result)
	{
		ItemData val = default(ItemData);
		if ((Object)(object)ItemManager.Instance == (Object)null || !ItemManager.Instance.GetItemData((uint)__result.dataId, ref val) || (Object)(object)val == (Object)null)
		{
			return;
		}
		ushort originalMax = ItemStack99Safe.GetOriginalMax(val.id);
		if (originalMax > 1)
		{
			if (val.buyByOne)
			{
				__result.amount = 1;
			}
			else
			{
				__result.amount = (ushort)Random.Range(1, originalMax + 1);
			}
		}
	}
}