Decompiled source of ItemStacksItemWeights v1.1.1

ItemStacksItemWeights.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using ConditionalConfigSync;
using HarmonyLib;
using UnityEngine;
using YamlDotNet.Serialization;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Item Stacks Item Weights")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Item Stacks Item Weights")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("52ea9c32-6004-4ec0-855e-6464cf26d40f")]
[assembly: AssemblyFileVersion("1.1.1")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.1.0")]
[module: UnverifiableCode]
namespace ItemStacksItemWeights;

public static class DocGen
{
	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static ConsoleEvent <>9__2_0;

		public static Func<KeyValuePair<string, string>, bool> <>9__5_0;

		public static Action<KeyValuePair<string, string>> <>9__5_1;

		public static Func<(string prefab, string token, string english, string localized, string stack, string weight, string type), int> <>9__5_2;

		public static Func<(string prefab, string token, string english, string localized, string stack, string weight, string type), int> <>9__5_3;

		public static Func<(string prefab, string token, string english, string localized, string stack, string weight, string type), int> <>9__5_4;

		public static Func<(string prefab, string token, string english, string localized, string stack, string weight, string type), int> <>9__5_5;

		public static Func<(string prefab, string token, string english, string localized, string stack, string weight, string type), int> <>9__5_6;

		public static Func<(string prefab, string token, string english, string localized, string stack, string weight, string type), int> <>9__5_7;

		public static Func<(string prefab, string token, string english, string localized, string stack, string weight, string type), int> <>9__5_8;

		internal void <InitCommand>b__2_0(ConsoleEventArgs args)
		{
			GenerateDocumentationFile(args.Context);
		}

		internal bool <GetFileText>b__5_0(KeyValuePair<string, string> kvp)
		{
			return !Localization.instance.m_translations.ContainsKey(kvp.Key);
		}

		internal void <GetFileText>b__5_1(KeyValuePair<string, string> kvp)
		{
			Localization.instance.AddWord(kvp.Key, kvp.Value);
		}

		internal int <GetFileText>b__5_2((string prefab, string token, string english, string localized, string stack, string weight, string type) r)
		{
			return r.prefab.Length;
		}

		internal int <GetFileText>b__5_3((string prefab, string token, string english, string localized, string stack, string weight, string type) r)
		{
			return r.token.Length;
		}

		internal int <GetFileText>b__5_4((string prefab, string token, string english, string localized, string stack, string weight, string type) r)
		{
			return r.english.Length;
		}

		internal int <GetFileText>b__5_5((string prefab, string token, string english, string localized, string stack, string weight, string type) r)
		{
			return r.localized.Length;
		}

		internal int <GetFileText>b__5_6((string prefab, string token, string english, string localized, string stack, string weight, string type) r)
		{
			return r.stack.Length;
		}

		internal int <GetFileText>b__5_7((string prefab, string token, string english, string localized, string stack, string weight, string type) r)
		{
			return r.weight.Length;
		}

		internal int <GetFileText>b__5_8((string prefab, string token, string english, string localized, string stack, string weight, string type) r)
		{
			return r.type.Length;
		}
	}

	private static readonly StringBuilder sb = new StringBuilder();

	internal const string docname = "Items stacks and weights.txt";

	public static void InitCommand()
	{
		//IL_0034: 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_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Expected O, but got Unknown
		object obj = <>c.<>9__2_0;
		if (obj == null)
		{
			ConsoleEvent val = delegate(ConsoleEventArgs args)
			{
				GenerateDocumentationFile(args.Context);
			};
			<>c.<>9__2_0 = val;
			obj = (object)val;
		}
		new ConsoleCommand("iwisdocs", "Save documentation file Items stacks and weights.txt to config directory", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
	}

	public static void GenerateDocumentationFile(Terminal terminal = null)
	{
		string text = Path.Combine(ItemStacksItemWeights.filepath, "Items stacks and weights.txt");
		try
		{
			Directory.CreateDirectory(ItemStacksItemWeights.filepath);
			File.WriteAllText(text, GetFileText(out var itemCount));
			string text2 = string.Format("Saved {0} items to \"\\BepinEx\\config\\{1}\\{2}\"", itemCount, "shudnal.ItemStacksItemWeights", "Items stacks and weights.txt");
			ItemStacksItemWeights.LogInfo(text2);
			if (terminal != null)
			{
				terminal.AddString(text2);
			}
		}
		catch (Exception ex)
		{
			ItemStacksItemWeights.LogWarning("Error when writing file (" + text + ")! Error: " + ex.Message);
		}
	}

	private static string Pad(string text, int width)
	{
		if (text.Length >= width)
		{
			return text;
		}
		return text + new string(' ', width - text.Length);
	}

	private static string GetFileText(out int itemCount)
	{
		sb.Clear();
		sb.AppendLine("This documentation is generated automatically. It contains every available item with identifiers used to configure stacks and weights.");
		sb.AppendLine("List does not include items without icons (incorrectly configured items or hidden items used by enemies, player model customization and such.");
		sb.AppendLine();
		itemCount = 0;
		if (!Object.op_Implicit((Object)(object)ObjectDB.instance))
		{
			return sb.ToString();
		}
		List<(string, string, string, string, string, string, string)> list = new List<(string, string, string, string, string, string, string)>();
		string selectedLanguage = Localization.instance.GetSelectedLanguage();
		Dictionary<string, string> dictionary = new Dictionary<string, string>();
		DictionaryExt.Copy<string, string>(dictionary, Localization.instance.m_translations);
		Localization.instance.SetLanguage("English");
		foreach (GameObject item5 in ObjectDB.instance.m_items)
		{
			if ((Object)(object)item5 == (Object)null)
			{
				continue;
			}
			ItemDrop component = item5.GetComponent<ItemDrop>();
			if (component == null)
			{
				continue;
			}
			ItemData itemData = component.m_itemData;
			if (itemData != null)
			{
				SharedData shared = itemData.m_shared;
				if (shared != null && shared.m_icons.Length != 0)
				{
					string name = ((Object)item5).name;
					string name2 = shared.m_name;
					string item = Localization.instance.Localize(name2);
					string item2 = shared.m_maxStackSize.ToString();
					string item3 = shared.m_weight.ToString();
					string item4 = ((object)Unsafe.As<ItemType, ItemType>(ref shared.m_itemType)/*cast due to .constrained prefix*/).ToString();
					list.Add((name, name2, item, "", item2, item3, item4));
				}
			}
		}
		Localization.instance.SetLanguage(selectedLanguage);
		CollectionExtensions.DoIf<KeyValuePair<string, string>>((IEnumerable<KeyValuePair<string, string>>)dictionary, (Func<KeyValuePair<string, string>, bool>)((KeyValuePair<string, string> kvp) => !Localization.instance.m_translations.ContainsKey(kvp.Key)), (Action<KeyValuePair<string, string>>)delegate(KeyValuePair<string, string> kvp)
		{
			Localization.instance.AddWord(kvp.Key, kvp.Value);
		});
		for (int num = 0; num < list.Count; num++)
		{
			(string, string, string, string, string, string, string) value = list[num];
			value.Item4 = Localization.instance.Localize(value.Item2);
			list[num] = value;
		}
		int num2 = Math.Max("Prefab name".Length, list.Max<(string, string, string, string, string, string, string)>(((string prefab, string token, string english, string localized, string stack, string weight, string type) r) => r.prefab.Length));
		int num3 = Math.Max("Token".Length, list.Max<(string, string, string, string, string, string, string)>(((string prefab, string token, string english, string localized, string stack, string weight, string type) r) => r.token.Length));
		int num4 = Math.Max("English".Length, list.Max<(string, string, string, string, string, string, string)>(((string prefab, string token, string english, string localized, string stack, string weight, string type) r) => r.english.Length));
		int num5 = Math.Max("Localized name".Length, list.Max<(string, string, string, string, string, string, string)>(((string prefab, string token, string english, string localized, string stack, string weight, string type) r) => r.localized.Length));
		int num6 = Math.Max("Stack".Length, list.Max<(string, string, string, string, string, string, string)>(((string prefab, string token, string english, string localized, string stack, string weight, string type) r) => r.stack.Length));
		int num7 = Math.Max("Weight".Length, list.Max<(string, string, string, string, string, string, string)>(((string prefab, string token, string english, string localized, string stack, string weight, string type) r) => r.weight.Length));
		int num8 = Math.Max("Type".Length, list.Max<(string, string, string, string, string, string, string)>(((string prefab, string token, string english, string localized, string stack, string weight, string type) r) => r.type.Length));
		sb.AppendLine(Pad("Prefab name", num2) + "   " + Pad("Token", num3) + "   " + Pad("English", num4) + "   " + Pad("Localized name", num5) + "   " + Pad("Stack", num6) + "   " + Pad("Weight", num7) + "   " + Pad("Type", num8));
		int count = num2 + num3 + num4 + num5 + num6 + num7 + num8 + 18;
		sb.AppendLine(new string('-', count));
		foreach (var (text, text2, text3, text4, text5, text6, text7) in list)
		{
			sb.AppendLine(Pad(text, num2) + "   " + Pad(text2, num3) + "   " + Pad(text3, num4) + "   " + Pad(text4, num5) + "   " + Pad(text5, num6) + "   " + Pad(text6, num7) + "   " + Pad(text7, num8));
		}
		itemCount = list.Count;
		return sb.ToString();
	}
}
public class ItemConfigurations : ISerializableParameter
{
	public const string global = "Global";

	[YamlMember(Alias = "WeightMultiplier")]
	public Dictionary<string, float> weightMultiplier = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase);

	[YamlMember(Alias = "WeightAmount")]
	public Dictionary<string, float> weightAmount = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase);

	[YamlMember(Alias = "StackMultiplier")]
	public Dictionary<string, float> stackMultiplier = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase);

	[YamlMember(Alias = "StackSize")]
	public Dictionary<string, int> stackSize = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

	public static ItemConfigurations CreateDefaultTemplate()
	{
		return new ItemConfigurations
		{
			weightMultiplier = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase) { { "Global", 1f } },
			weightAmount = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase) { { "Wood", 2f } },
			stackMultiplier = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase) { { "Global", 1f } },
			stackSize = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase) { { "Wood", 50 } }
		};
	}

	public void EnsureInitialized()
	{
		weightMultiplier = NormalizeDictionary(weightMultiplier);
		weightAmount = NormalizeDictionary(weightAmount);
		stackMultiplier = NormalizeDictionary(stackMultiplier);
		stackSize = NormalizeDictionary(stackSize);
	}

	private static Dictionary<string, T> NormalizeDictionary<T>(Dictionary<string, T> source)
	{
		if (source != null && source.Comparer.Equals(StringComparer.OrdinalIgnoreCase))
		{
			return source;
		}
		Dictionary<string, T> dictionary = new Dictionary<string, T>(StringComparer.OrdinalIgnoreCase);
		if (source != null)
		{
			foreach (KeyValuePair<string, T> item in source)
			{
				dictionary[item.Key] = item.Value;
			}
		}
		return dictionary;
	}

	public void Validate()
	{
		EnsureInitialized();
		foreach (KeyValuePair<string, int> item in stackSize)
		{
			if (item.Value < 1)
			{
				throw new FormatException("StackSize for '" + item.Key + "' must be positive.");
			}
		}
		ValidateNumbers(stackMultiplier, "StackMultiplier", allowZero: false);
		ValidateNumbers(weightMultiplier, "WeightMultiplier", allowZero: true);
		ValidateNumbers(weightAmount, "WeightAmount", allowZero: true);
	}

	private static void ValidateNumbers(Dictionary<string, float> values, string section, bool allowZero)
	{
		foreach (KeyValuePair<string, float> value in values)
		{
			if (float.IsNaN(value.Value) || float.IsInfinity(value.Value) || value.Value < 0f || (!allowZero && value.Value == 0f))
			{
				throw new FormatException(section + " for '" + value.Key + "' must be finite and " + (allowZero ? "non-negative" : "positive") + ".");
			}
		}
	}

	public void Serialize(ref ZPackage pkg)
	{
		EnsureInitialized();
		WriteDict(pkg, weightMultiplier);
		WriteDict(pkg, weightAmount);
		WriteDict(pkg, stackMultiplier);
		WriteDict(pkg, stackSize);
	}

	public void Deserialize(ref ZPackage pkg)
	{
		EnsureInitialized();
		ReadDict(pkg, weightMultiplier);
		ReadDict(pkg, weightAmount);
		ReadDict(pkg, stackMultiplier);
		ReadDict(pkg, stackSize);
	}

	public void Load(ItemConfigurations itemConfigurations)
	{
		EnsureInitialized();
		if (this != itemConfigurations)
		{
			if (itemConfigurations == null)
			{
				itemConfigurations = new ItemConfigurations();
			}
			itemConfigurations.EnsureInitialized();
			weightMultiplier.Clear();
			weightAmount.Clear();
			stackMultiplier.Clear();
			stackSize.Clear();
			DictionaryExt.Copy<string, float>(weightMultiplier, itemConfigurations.weightMultiplier);
			DictionaryExt.Copy<string, float>(weightAmount, itemConfigurations.weightAmount);
			DictionaryExt.Copy<string, float>(stackMultiplier, itemConfigurations.stackMultiplier);
			DictionaryExt.Copy<string, int>(stackSize, itemConfigurations.stackSize);
		}
	}

	public void FillItemNames()
	{
		CollectionExtensions.Do<string>((IEnumerable<string>)weightMultiplier.Keys.ToList(), (Action<string>)delegate(string key)
		{
			weightMultiplier[key.GetItemName()] = weightMultiplier[key];
		});
		CollectionExtensions.Do<string>((IEnumerable<string>)weightAmount.Keys.ToList(), (Action<string>)delegate(string key)
		{
			weightAmount[key.GetItemName()] = weightAmount[key];
		});
		CollectionExtensions.Do<string>((IEnumerable<string>)stackMultiplier.Keys.ToList(), (Action<string>)delegate(string key)
		{
			stackMultiplier[key.GetItemName()] = stackMultiplier[key];
		});
		CollectionExtensions.Do<string>((IEnumerable<string>)stackSize.Keys.ToList(), (Action<string>)delegate(string key)
		{
			stackSize[key.GetItemName()] = stackSize[key];
		});
	}

	private void ReadDict(ZPackage pkg, Dictionary<string, float> dictionary)
	{
		dictionary.Clear();
		int num = pkg.ReadInt();
		for (int i = 0; i < num; i++)
		{
			dictionary[pkg.ReadString()] = pkg.ReadSingle();
		}
	}

	private void ReadDict(ZPackage pkg, Dictionary<string, int> dictionary)
	{
		dictionary.Clear();
		int num = pkg.ReadInt();
		for (int i = 0; i < num; i++)
		{
			dictionary[pkg.ReadString()] = pkg.ReadInt();
		}
	}

	private void WriteDict(ZPackage pkg, Dictionary<string, float> dictionary)
	{
		pkg.Write(dictionary.Count);
		foreach (KeyValuePair<string, float> item in dictionary)
		{
			pkg.Write(item.Key);
			pkg.Write(item.Value);
		}
	}

	private void WriteDict(ZPackage pkg, Dictionary<string, int> dictionary)
	{
		pkg.Write(dictionary.Count);
		foreach (KeyValuePair<string, int> item in dictionary)
		{
			pkg.Write(item.Key);
			pkg.Write(item.Value);
		}
	}
}
public static class ItemDefaults
{
	[HarmonyPatch(typeof(ZoneSystem), "Start")]
	private static class ZoneSystem_Start_UpdateRegisters
	{
		private static void Postfix()
		{
			UpdateRegisters();
		}
	}

	public static readonly Dictionary<string, string> itemNames = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

	public static readonly Dictionary<string, float> itemWeight = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase);

	public static readonly Dictionary<string, int> itemStack = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

	public static void UpdateRegisters()
	{
		if (!Object.op_Implicit((Object)(object)ObjectDB.instance))
		{
			return;
		}
		foreach (GameObject item in ObjectDB.instance.m_items)
		{
			if ((Object)(object)item == (Object)null)
			{
				continue;
			}
			ItemDrop component = item.GetComponent<ItemDrop>();
			if (component == null)
			{
				continue;
			}
			ItemData itemData = component.m_itemData;
			if (itemData == null)
			{
				continue;
			}
			SharedData shared = itemData.m_shared;
			if (shared != null)
			{
				if (shared.m_name.StartsWith("$"))
				{
					itemNames[((Object)item).name] = shared.m_name;
					itemNames[shared.m_name] = shared.m_name;
				}
				if (!itemWeight.ContainsKey(((Object)item).name))
				{
					itemWeight[((Object)item).name] = shared.m_weight;
				}
				if (!itemWeight.ContainsKey(shared.m_name))
				{
					itemWeight[shared.m_name] = shared.m_weight;
				}
				if (!itemStack.ContainsKey(((Object)item).name))
				{
					itemStack[((Object)item).name] = shared.m_maxStackSize;
				}
				if (!itemStack.ContainsKey(shared.m_name))
				{
					itemStack[shared.m_name] = shared.m_maxStackSize;
				}
			}
		}
		ItemStacksItemWeights.LogInfo("Items defaults updated");
		DocGen.GenerateDocumentationFile();
		ItemProcessing.PatchObjectDB();
	}

	public static string GetItemName(this string input)
	{
		return itemNames.GetValueOrDefault(input.Trim(), input);
	}

	public static int GetDefaultItemStack(this SharedData shared)
	{
		return itemStack.GetValueOrDefault(shared.m_name, -1);
	}

	public static float GetDefaultItemWeight(this SharedData shared)
	{
		return itemWeight.GetValueOrDefault(shared.m_name, -1f);
	}

	public static TValue GetValueOrDefault<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue)
	{
		if (dictionary == null)
		{
			throw new ArgumentNullException("dictionary");
		}
		if (!dictionary.TryGetValue(key, out var value))
		{
			return defaultValue;
		}
		return value;
	}
}
public static class ItemProcessing
{
	[HarmonyPatch(typeof(ItemDrop), "Awake")]
	public static class ItemDrop_Awake_PatchItems
	{
		[HarmonyPriority(0)]
		private static void Postfix(ItemDrop __instance)
		{
			if (!((Object)(object)FejdStartup.instance != (Object)null))
			{
				PatchItem(__instance.m_itemData);
			}
		}
	}

	[HarmonyPatch(typeof(ItemDrop), "OnCreateNew", new Type[]
	{
		typeof(ItemDrop),
		typeof(bool)
	})]
	public static class ItemDrop_OnCreateNew_PatchItems
	{
		[HarmonyPriority(0)]
		private static void Postfix(ItemDrop item)
		{
			if (!((Object)(object)FejdStartup.instance != (Object)null))
			{
				PatchItem(item.m_itemData);
			}
		}
	}

	[HarmonyPatch(typeof(Player), "Load")]
	public static class Player_Load_PatchItems
	{
		[HarmonyPriority(0)]
		private static void Postfix(Player __instance)
		{
			if (!((Object)(object)FejdStartup.instance != (Object)null))
			{
				if (PatchPlayerInventory(__instance))
				{
					ItemStacksItemWeights.LogInfo("Patched player inventory");
				}
				containerInventoryUpdated.Clear();
				containerUpdateRequired = false;
			}
		}
	}

	[HarmonyPatch(typeof(InventoryGui), "Show")]
	public static class InventoryGui_Show_PatchItems
	{
		private static void Postfix()
		{
			PatchPlayerInventory(Player.m_localPlayer);
		}
	}

	[HarmonyPatch(typeof(InventoryGrid), "UpdateInventory")]
	public static class InventoryGrid_UpdateInventory_PatchContainerItems
	{
		private static void Postfix(InventoryGrid __instance)
		{
			if ((Object)(object)InventoryGui.instance != (Object)null && (Object)(object)__instance == (Object)(object)InventoryGui.instance.ContainerGrid && containerUpdateRequired && !containerInventoryUpdated.Contains(__instance.m_inventory))
			{
				if (PatchInventory(__instance.m_inventory))
				{
					ItemStacksItemWeights.LogInfo($"Inventory {__instance.m_inventory} patched");
				}
				containerInventoryUpdated.Add(__instance.m_inventory);
			}
		}
	}

	public static ItemConfigurations itemConfig = new ItemConfigurations();

	public static bool containerUpdateRequired = false;

	public static readonly List<Inventory> containerInventoryUpdated = new List<Inventory>();

	public static void OnConfigFileChange()
	{
		ItemStacksItemWeights.LogInfo("Item config updated");
		itemConfig.Load(ItemStacksItemWeights.configurationFile.Value);
		PatchObjectDB();
		if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
		{
			if (PatchPlayerInventory(Player.m_localPlayer))
			{
				ItemStacksItemWeights.LogInfo("Patched local player inventory");
			}
			containerUpdateRequired = true;
			containerInventoryUpdated.Clear();
		}
	}

	public static void PatchObjectDB()
	{
		itemConfig.FillItemNames();
		if (!Object.op_Implicit((Object)(object)ObjectDB.instance))
		{
			return;
		}
		foreach (GameObject item in ObjectDB.instance.m_items)
		{
			if ((Object)(object)item == (Object)null)
			{
				continue;
			}
			ItemDrop component = item.GetComponent<ItemDrop>();
			if (component == null)
			{
				continue;
			}
			ItemData itemData = component.m_itemData;
			if (itemData != null)
			{
				SharedData shared = itemData.m_shared;
				if (shared != null)
				{
					PatchShared(shared);
				}
			}
		}
		ItemStacksItemWeights.LogInfo("Patched ObjectDB items");
	}

	public static bool PatchShared(SharedData shared)
	{
		if (shared == null)
		{
			return false;
		}
		int maxStackSize = shared.m_maxStackSize;
		float weight = shared.m_weight;
		int defaultItemStack = shared.GetDefaultItemStack();
		if (defaultItemStack > 1)
		{
			shared.m_maxStackSize = defaultItemStack;
			int value2;
			float value3;
			float value4;
			if (itemConfig.stackSize.TryGetValue(shared.m_name, out var value))
			{
				shared.m_maxStackSize = value;
			}
			else if (itemConfig.stackSize.TryGetValue("Global", out value2))
			{
				shared.m_maxStackSize = value2;
			}
			else if (itemConfig.stackMultiplier.TryGetValue(shared.m_name, out value3))
			{
				shared.m_maxStackSize = ScaleStackSize(shared.m_maxStackSize, value3);
			}
			else if (itemConfig.stackMultiplier.TryGetValue("Global", out value4))
			{
				shared.m_maxStackSize = ScaleStackSize(shared.m_maxStackSize, value4);
			}
		}
		float defaultItemWeight = shared.GetDefaultItemWeight();
		if (defaultItemWeight >= 0f)
		{
			shared.m_weight = defaultItemWeight;
			float value6;
			float value7;
			float value8;
			if (itemConfig.weightAmount.TryGetValue(shared.m_name, out var value5))
			{
				shared.m_weight = value5;
			}
			else if (itemConfig.weightAmount.TryGetValue("Global", out value6))
			{
				shared.m_weight = value6;
			}
			else if (itemConfig.weightMultiplier.TryGetValue(shared.m_name, out value7))
			{
				shared.m_weight *= value7;
			}
			else if (itemConfig.weightMultiplier.TryGetValue("Global", out value8))
			{
				shared.m_weight *= value8;
			}
		}
		return maxStackSize != shared.m_maxStackSize || weight != shared.m_weight;
	}

	private static int ScaleStackSize(int stackSize, float multiplier)
	{
		return (int)Math.Max(1.0, Math.Min(2147483647.0, Math.Ceiling((double)stackSize * (double)multiplier)));
	}

	public static int PatchItem(ItemData item)
	{
		return PatchShared(item?.m_shared) ? 1 : 0;
	}

	public static bool PatchInventory(Inventory inventory)
	{
		if (inventory == null)
		{
			return false;
		}
		List<ItemData> inventory2 = inventory.m_inventory;
		if (inventory2 != null && ((IEnumerable<ItemData>)inventory2).Sum((Func<ItemData, int>)PatchItem) > 0)
		{
			inventory.Changed(false, false);
			return true;
		}
		return false;
	}

	public static bool PatchPlayerInventory(Player player)
	{
		return PatchInventory((player != null) ? ((Humanoid)player).GetInventory() : null);
	}
}
internal static class LargeStackSerialization
{
	[HarmonyPatch(typeof(ItemData), "Save", new Type[] { typeof(ZPackage) })]
	private static class ItemData_Save_PreserveFullStack
	{
		private struct SaveState
		{
			internal bool Changed;

			internal int Stack;

			internal Dictionary<string, string> CustomData;
		}

		[HarmonyPriority(800)]
		private static void Prefix(ItemData __instance, out SaveState __state)
		{
			__state = default(SaveState);
			Dictionary<string, string> customData = __instance.m_customData;
			bool flag = __instance.m_stack > 65535;
			if (flag || customData == null || customData.ContainsKey("shudnal.ItemStacksItemWeights.FullStack"))
			{
				Dictionary<string, string> dictionary = ((customData == null) ? new Dictionary<string, string>() : new Dictionary<string, string>(customData));
				dictionary.Remove("shudnal.ItemStacksItemWeights.FullStack");
				if (flag)
				{
					dictionary["shudnal.ItemStacksItemWeights.FullStack"] = __instance.m_stack.ToString(CultureInfo.InvariantCulture);
				}
				__state = new SaveState
				{
					Changed = true,
					Stack = __instance.m_stack,
					CustomData = customData
				};
				__instance.m_customData = dictionary;
				if (flag)
				{
					__instance.m_stack = 65535;
				}
			}
		}

		[HarmonyPriority(0)]
		private static void Finalizer(ItemData __instance, SaveState __state)
		{
			if (__state.Changed)
			{
				__instance.m_stack = __state.Stack;
				__instance.m_customData = __state.CustomData;
			}
		}
	}

	[HarmonyPatch(typeof(ItemData), "Load", new Type[]
	{
		typeof(ZPackage),
		typeof(ItemData),
		typeof(Item)
	})]
	private static class ItemData_Load_RestoreFullStack
	{
		[HarmonyPriority(0)]
		private static void Postfix(ItemData itemData)
		{
			Dictionary<string, string> customData = itemData.m_customData;
			if (customData != null)
			{
				string value;
				bool flag = customData.TryGetValue("shudnal.ItemStacksItemWeights.FullStack", out value);
				customData.Remove("shudnal.ItemStacksItemWeights.FullStack");
				if (flag && itemData.m_stack == 65535 && TryReadCount(value, out var stack))
				{
					itemData.m_stack = stack;
				}
			}
		}
	}

	private const string StackKey = "shudnal.ItemStacksItemWeights.FullStack";

	private static bool TryReadCount(string value, out int stack)
	{
		return int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out stack) && stack > 65535;
	}
}
[BepInPlugin("shudnal.ItemStacksItemWeights", "Item Stacks Item Weights", "1.1.1")]
[BepInDependency("_shudnal.ConditionalConfigSync", "1.0.5")]
public class ItemStacksItemWeights : BaseUnityPlugin
{
	public const string pluginID = "shudnal.ItemStacksItemWeights";

	public const string pluginName = "Item Stacks Item Weights";

	public const string pluginVersion = "1.1.1";

	public readonly Harmony harmony = new Harmony("shudnal.ItemStacksItemWeights");

	public static ItemStacksItemWeights instance;

	public static readonly ConfigSync configSync = new ConfigSync("shudnal.ItemStacksItemWeights")
	{
		DisplayName = "Item Stacks Item Weights",
		CurrentVersion = "1.1.1",
		MinimumRequiredVersion = "1.1.1",
		ModRequired = true
	};

	public static ConfigEntry<bool> configLocked;

	public static ConfigEntry<bool> loggingEnabled;

	public static ConfigEntry<bool> hideStackSize;

	public static ConfigEntry<bool> compactStackSize;

	public static ConfigEntry<bool> compactAmountSize;

	public static ConfigEntry<KeyboardShortcut> showFullStackSize;

	public static readonly CustomSyncedValue<ItemConfigurations> configurationFile = new CustomSyncedValue<ItemConfigurations>((ConditionalConfigSync)(object)configSync, "shudnal.ItemStacksItemWeights.ConfigurationFile", new ItemConfigurations(), 0, (IEqualityComparer<ItemConfigurations>)null);

	public static readonly string filename = "shudnal.ItemStacksItemWeights.yml";

	public static readonly string filepath = Path.Combine(Paths.ConfigPath, "shudnal.ItemStacksItemWeights");

	public static readonly string fullpath = Path.Combine(filepath, filename);

	public FileSystemWatcher fileWatcher;

	private bool reloadPending;

	private float reloadAt;

	private int reloadAttempts;

	private void Awake()
	{
		instance = this;
		ConfigInit();
		((ConditionalConfigSync)configSync).AddLockingConfigEntry<bool>(configLocked);
		Game.isModded = true;
		harmony.PatchAll();
	}

	private void Start()
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		if (!Directory.Exists(filepath))
		{
			Directory.CreateDirectory(filepath);
		}
		if (!File.Exists(fullpath))
		{
			File.WriteAllText(fullpath, new Serializer().Serialize((object)ItemConfigurations.CreateDefaultTemplate()));
		}
		fileWatcher = new FileSystemWatcher(filepath, filename);
		fileWatcher.Changed += ScheduleConfigReload;
		fileWatcher.Created += ScheduleConfigReload;
		fileWatcher.Renamed += ScheduleConfigReload;
		fileWatcher.Deleted += ScheduleConfigReload;
		fileWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
		fileWatcher.EnableRaisingEvents = true;
		((CustomSyncedValueBase)configurationFile).ValueChanged += ItemProcessing.OnConfigFileChange;
		LoadConfigs();
		ItemProcessing.OnConfigFileChange();
		DocGen.InitCommand();
	}

	private void OnDestroy()
	{
		reloadPending = false;
		fileWatcher?.Dispose();
		fileWatcher = null;
		((CustomSyncedValueBase)configurationFile).ValueChanged -= ItemProcessing.OnConfigFileChange;
		((BaseUnityPlugin)this).Config.Save();
		instance = null;
		Harmony obj = harmony;
		if (obj != null)
		{
			obj.UnpatchSelf();
		}
	}

	public static void LogInfo(object data)
	{
		if (loggingEnabled.Value)
		{
			((BaseUnityPlugin)instance).Logger.LogInfo(data);
		}
	}

	public static void LogWarning(object data)
	{
		((BaseUnityPlugin)instance).Logger.LogWarning(data);
	}

	public void ConfigInit()
	{
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		configLocked = config("General", "Lock Configuration", defaultValue: true, "Configuration is locked and can be changed by server admins only.");
		loggingEnabled = config("General", "Logging enabled", defaultValue: false, "Enable logging. [Not Synced with Server]", synchronizedSetting: false);
		hideStackSize = config("General", "Hide stack size", defaultValue: false, "Hide stack size of items");
		compactStackSize = config("General", "Compact stack size", defaultValue: false, "Display large stack sizes in a compact format (e.g. 1k instead of 1000, 1M instead of 1000000).");
		compactAmountSize = config("General", "Compact amount size", defaultValue: false, "Display large amount of items in a compact format (e.g. 1k instead of 1000, 1M instead of 1000000). The number is rounded down.");
		showFullStackSize = config<KeyboardShortcut>("General", "Show full stack size", new KeyboardShortcut((KeyCode)308, Array.Empty<KeyCode>()), "Hold to display stack sizes without changes. [Not Synced with Server]", synchronizedSetting: false);
		hideStackSize.SettingChanged += delegate
		{
			ItemStackText.ClearCache();
		};
		compactStackSize.SettingChanged += delegate
		{
			ItemStackText.ClearCache();
		};
		compactAmountSize.SettingChanged += delegate
		{
			ItemStackText.ClearCache();
		};
	}

	private ConfigEntry<T> config<T>(string group, string name, T defaultValue, ConfigDescription description, bool synchronizedSetting = true)
	{
		ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, defaultValue, description);
		((ConditionalConfigSync)configSync).AddConfigEntry<T>(val, (ConfigSyncMode)1, synchronizedSetting);
		return val;
	}

	private ConfigEntry<T> config<T>(string group, string name, T defaultValue, string description, bool synchronizedSetting = true)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Expected O, but got Unknown
		return config(group, name, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting);
	}

	public void ClearConfigs()
	{
		configurationFile.AssignLocalValueIfChanged(new ItemConfigurations());
		LogInfo("Config file cleared: " + filename);
	}

	private void ScheduleConfigReload(object sender, FileSystemEventArgs args)
	{
		reloadPending = true;
		reloadAt = Time.unscaledTime + 0.25f;
		reloadAttempts = 3;
	}

	private void Update()
	{
		if (reloadPending && !(Time.unscaledTime < reloadAt))
		{
			reloadAttempts--;
			if (TryLoadConfigs(out var error))
			{
				reloadPending = false;
				return;
			}
			if (reloadAttempts > 0)
			{
				reloadAt = Time.unscaledTime + 0.25f;
				return;
			}
			reloadPending = false;
			LogWarning($"Could not reload {filename}; keeping the last valid configuration. {error}");
		}
	}

	public void LoadConfigs()
	{
		if (!TryLoadConfigs(out var error))
		{
			LogWarning($"Could not load {filename}; keeping the last valid configuration. {error}");
			ScheduleConfigReload(null, null);
		}
	}

	private bool TryLoadConfigs(out Exception error)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		error = null;
		if (!File.Exists(fullpath))
		{
			ClearConfigs();
			return true;
		}
		try
		{
			ItemConfigurations itemConfigurations = new Deserializer().Deserialize<ItemConfigurations>(File.ReadAllText(fullpath)) ?? new ItemConfigurations();
			itemConfigurations.EnsureInitialized();
			itemConfigurations.Validate();
			configurationFile.AssignLocalValueIfChanged(itemConfigurations);
			LogInfo("Config file changed: " + filename);
			return true;
		}
		catch (Exception ex)
		{
			error = ex;
			return false;
		}
	}
}
internal static class ItemStackText
{
	[HarmonyPatch(typeof(HotkeyBar), "UpdateIcons")]
	public static class HotkeyBar_UpdateIcons_StackSizeFormatting
	{
		[HarmonyPriority(200)]
		public static void Postfix(HotkeyBar __instance)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = ItemStacksItemWeights.showFullStackSize.Value;
			if (((KeyboardShortcut)(ref value)).IsPressed() || (!ItemStacksItemWeights.hideStackSize.Value && !ItemStacksItemWeights.compactStackSize.Value && !ItemStacksItemWeights.compactAmountSize.Value))
			{
				return;
			}
			foreach (ElementData element in __instance.m_elements)
			{
				if (((Component)element.m_amount).gameObject.activeInHierarchy)
				{
					string text = element.m_amount.text;
					if (!string.IsNullOrEmpty(text))
					{
						element.m_amount.SetText(GetCompactText(text));
					}
				}
			}
		}
	}

	[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
	public static class InventoryGrid_UpdateGui_StackSizeFormatting
	{
		[HarmonyPriority(200)]
		public static void Postfix(InventoryGrid __instance)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = ItemStacksItemWeights.showFullStackSize.Value;
			if (((KeyboardShortcut)(ref value)).IsPressed() || (!ItemStacksItemWeights.hideStackSize.Value && !ItemStacksItemWeights.compactStackSize.Value && !ItemStacksItemWeights.compactAmountSize.Value))
			{
				return;
			}
			foreach (InventoryElement element in __instance.m_elements)
			{
				if (((Component)element.m_amount).gameObject.activeInHierarchy)
				{
					string text = element.m_amount.text;
					if (!string.IsNullOrEmpty(text))
					{
						element.m_amount.SetText(GetCompactText(text));
					}
				}
			}
		}
	}

	private static readonly Dictionary<string, string> compactTextCache = new Dictionary<string, string>(256);

	private const int CompactCacheLimit = 1024;

	internal static void ClearCache()
	{
		compactTextCache.Clear();
	}

	private static bool TryFindNextNumber(string text, int start, out int value, out int numStart, out int numLength)
	{
		value = 0;
		numStart = (numLength = 0);
		bool flag = false;
		for (int i = start; i < text.Length; i++)
		{
			char c = text[i];
			switch (c)
			{
			case '<':
				flag = true;
				continue;
			case '>':
				flag = false;
				continue;
			}
			if (flag || !char.IsDigit(c))
			{
				continue;
			}
			numStart = i;
			int num = 0;
			int j;
			for (j = i; j < text.Length && char.IsDigit(text[j]); j++)
			{
				int num2 = text[j] - 48;
				if (num2 < 0 || num2 > 9 || num > (int.MaxValue - num2) / 10)
				{
					return false;
				}
				num = num * 10 + num2;
			}
			value = num;
			numLength = j - i;
			return true;
		}
		return false;
	}

	private static string GetCompactText(string original)
	{
		if (compactTextCache.TryGetValue(original, out var value))
		{
			return value;
		}
		string text = BuildCompactText(original);
		if (compactTextCache.Count > 1024)
		{
			compactTextCache.Clear();
		}
		compactTextCache[original] = text;
		return text;
	}

	private static string TrimAfterIndexPreserveTags(string text, int cutIndex)
	{
		StringBuilder stringBuilder = new StringBuilder(text.Substring(0, cutIndex));
		int num = cutIndex;
		while (num < text.Length)
		{
			int num2 = text.IndexOf('<', num);
			if (num2 < 0)
			{
				break;
			}
			int num3 = text.IndexOf('>', num2 + 1);
			if (num3 < 0)
			{
				break;
			}
			stringBuilder.Append(text, num2, num3 - num2 + 1);
			num = num3 + 1;
		}
		return stringBuilder.ToString();
	}

	private static string BuildCompactText(string text)
	{
		if (!TryFindNextNumber(text, 0, out var value, out var numStart, out var numLength))
		{
			return text;
		}
		string text2 = (ItemStacksItemWeights.compactAmountSize.Value ? FormatCompact(value) : text.Substring(numStart, numLength));
		text = text.Substring(0, numStart) + text2 + text.Substring(numStart + numLength);
		int num = numStart + text2.Length;
		if (ItemStacksItemWeights.hideStackSize.Value)
		{
			return TrimAfterIndexPreserveTags(text, num);
		}
		if (ItemStacksItemWeights.compactStackSize.Value && TryFindNextNumber(text, num, out var value2, out var numStart2, out var numLength2))
		{
			string text3 = FormatCompact(value2);
			text = text.Substring(0, numStart2) + text3 + text.Substring(numStart2 + numLength2);
		}
		return text;
	}

	private static string FormatCompact(int value)
	{
		if (value < 1000)
		{
			return StringExtensionMethods.ToFastString(value);
		}
		if (value < 1000000)
		{
			return (Mathf.Floor((float)value / 100f) / 10f).ToString("0.#") + "k";
		}
		return (Mathf.Floor((float)value / 100000f) / 10f).ToString("0.#") + "M";
	}
}