Decompiled source of InventoryExpansion v1.0.3

BepInEx/plugins/InventoryExpansion/InventoryExpansion.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.NET.Common;
using Candide;
using Candide.CandideUI;
using Candide.CandideUI.Containers;
using Candide.CandideUI.JobUiNew;
using Candide.CandideUI.ProximityWindows;
using Candide.CandideUI.UiInput;
using Candide.CandideUI.UserControls;
using Candide.CandideUI.Windows;
using Candide.CandideUI.WorshipUi.Altar;
using Candide.CandideUI.WorshipUi.Altar2;
using Candide.GameModels;
using Candide.GameModels.Models.Constructions;
using Candide.GameModels.Models.Items;
using Candide.Save;
using CandideCreator.Shared;
using CandideCreator.Shared.Serialization;
using CandideServer;
using CandideServer.Entities;
using CandideServer.EventBus;
using CandideServer.MessageModels.Players;
using CandideServer.Models.Buildings;
using CandideServer.Models.Player;
using CandideServer.ServerControllers;
using CandideServer.ServerManagers;
using CandideServer.ServerServices;
using CandideServer.SimulationModels;
using HarmonyLib;
using InventoryExpansion.Configuration;
using InventoryExpansion.Storage;
using Microsoft.Xna.Framework;
using ModSettingsMenu.Api;
using RomesteadLocalizationAPI.Api;
using Shared;
using Shared.Data;
using Shared.Inventory.DeltaModels;
using Shared.Messages;
using Shared.Models.Construction;
using Shared.Models.Items;
using Shared.Models.Player;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Inventory Expansion")]
[assembly: AssemblyDescription("Inventory Expansion For Romestead by Ice Box Studio")]
[assembly: AssemblyCompany("Ice Box Studio")]
[assembly: AssemblyProduct("Inventory Expansion")]
[assembly: AssemblyCopyright("Copyright (C) 2026 Ice Box Studio All rights reserved.")]
[assembly: ComVisible(false)]
[assembly: Guid("d5148b7f-4fe9-430d-8e20-9c268fd42b79")]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: TargetFramework(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")]
[assembly: AssemblyVersion("1.0.3.0")]
[module: RefSafetyRules(11)]
namespace InventoryExpansion
{
	internal static class I18n
	{
		public static readonly RomesteadLocalizer L = RomesteadLocalization.For("IceBoxStudio.Romestead.InventoryExpansion");
	}
	[BepInPlugin("IceBoxStudio.Romestead.InventoryExpansion", "Inventory Expansion", "1.0.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class InventoryExpansion : BasePlugin
	{
		private Harmony _harmony;

		public static InventoryExpansion Instance { get; private set; }

		internal static ManualLogSource Logger { get; private set; }

		public override void Load()
		{
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Expected O, but got Unknown
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Expected O, but got Unknown
			Instance = this;
			Logger = ((BasePlugin)this).Log;
			bool flag = default(bool);
			try
			{
				Logger.LogInfo((object)"=============================================");
				ManualLogSource logger = Logger;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(16, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Inventory Expansion");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" initializing...");
				}
				logger.LogInfo(val);
				ManualLogSource logger2 = Logger;
				val = new BepInExInfoLogInterpolatedStringHandler(10, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Author: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Ice Box Studio");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("(");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("https://steamcommunity.com/id/ibox666/");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")");
				}
				logger2.LogInfo(val);
				I18n.L.RegisterJson(Path.Combine(Paths.PluginPath, "InventoryExpansion", "Localization.json"));
				ConfigManager.Init(((BasePlugin)this).Config);
				ModSettingsMenuRegistration.Register(((BasePlugin)this).Config);
				_harmony = new Harmony("IceBoxStudio.Romestead.InventoryExpansion");
				_harmony.PatchAll(Assembly.GetExecutingAssembly());
				StackSizeHelper.ApplyAll();
				ManualLogSource logger3 = Logger;
				val = new BepInExInfoLogInterpolatedStringHandler(13, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Inventory Expansion");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" initialized.");
				}
				logger3.LogInfo(val);
				Logger.LogInfo((object)"=============================================");
			}
			catch (Exception ex)
			{
				ManualLogSource logger4 = Logger;
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(24, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("Inventory Expansion");
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" initialization error: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("\n");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.StackTrace);
				}
				logger4.LogError(val2);
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "IceBoxStudio.Romestead.InventoryExpansion";

		public const string PLUGIN_NAME = "Inventory Expansion";

		public const string PLUGIN_VERSION = "1.0.3";

		public const string PLUGIN_AUTHOR = "Ice Box Studio";

		public const string PLUGIN_AUTHOR_URL = "https://steamcommunity.com/id/ibox666/";

		public const int NEXUS_MODS_ID = 59;

		public const string THUNDERSTORE_TEAM = "Ice_Box_Studio_Romestead";

		public const string THUNDERSTORE_MOD_NAME = "InventoryExpansion";

		public const string UPDATE_MANIFEST_URL = "https://fastly.jsdelivr.net/gh/ibox233/MyMod_Version@main/InventoryExpansion.json";
	}
}
namespace InventoryExpansion.Storage
{
	internal static class BackpackRuntime
	{
		private static readonly Dictionary<Guid, ItemInstanceModel[]> PendingExtraSlots = new Dictionary<Guid, ItemInstanceModel[]>();

		public static void SetPendingExtraSlots(Guid characterId, ItemInstanceModel[] slots)
		{
			if (slots == null || slots.Length == 0)
			{
				PendingExtraSlots.Remove(characterId);
			}
			else
			{
				PendingExtraSlots[characterId] = slots;
			}
		}

		public static ItemInstanceModel[] TakePendingExtraSlots(Guid characterId)
		{
			if (!PendingExtraSlots.TryGetValue(characterId, out var value))
			{
				return Array.Empty<ItemInstanceModel>();
			}
			PendingExtraSlots.Remove(characterId);
			return value ?? Array.Empty<ItemInstanceModel>();
		}
	}
	internal static class BackpackSidecarStore
	{
		private static readonly byte[] Magic = Encoding.ASCII.GetBytes("BPEX1");

		private const int NonceSize = 12;

		private const int TagSize = 16;

		public static ItemInstanceModel[] Load(Guid characterId, bool logFailure = true)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			string path = GetPath(characterId);
			if (!File.Exists(path))
			{
				return Array.Empty<ItemInstanceModel>();
			}
			ItemInstanceModel[] array2;
			try
			{
				byte[] fileBytes = File.ReadAllBytes(path);
				using MemoryStream memoryStream = new MemoryStream(Decrypt(characterId, fileBytes));
				ItemInstanceModel[] array = new CandideDeserializer(Globals.GraphicsDevice, Globals.ContentManager).Deserialize<ItemInstanceModel[]>(Globals.Reflection, (Stream)memoryStream, false) ?? Array.Empty<ItemInstanceModel>();
				array2 = array;
				foreach (ItemInstanceModel obj in array2)
				{
					if (obj != null)
					{
						obj.CalculateStats();
					}
				}
				array2 = array;
			}
			catch (Exception ex)
			{
				if (logFailure)
				{
					ManualLogSource logger = InventoryExpansion.Logger;
					if (logger != null)
					{
						bool flag = default(bool);
						BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(39, 2, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed loading sidecar for character ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Guid>(characterId, "N");
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
						}
						logger.LogWarning(val);
					}
				}
				array2 = Array.Empty<ItemInstanceModel>();
			}
			return array2;
		}

		public static void Save(Guid characterId, ItemInstanceModel[] visibleExtraSlots)
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ItemInstanceModel[] array = MergeWithExistingHiddenSlots(characterId, visibleExtraSlots ?? Array.Empty<ItemInstanceModel>());
				using MemoryStream memoryStream = new MemoryStream();
				using (new CandideSerializer
				{
					Properties = 
					{
						CompactStrings = true
					}
				}.Serialize<ItemInstanceModel[]>(Globals.Reflection, (Stream)memoryStream, array, true))
				{
				}
				byte[] bytes = Encrypt(characterId, memoryStream.ToArray());
				string path = GetPath(characterId);
				Directory.CreateDirectory(Path.GetDirectoryName(path));
				string text = path + ".tmp";
				File.WriteAllBytes(text, bytes);
				if (File.Exists(path))
				{
					File.Replace(text, path, null);
				}
				else
				{
					File.Move(text, path);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger = InventoryExpansion.Logger;
				if (logger != null)
				{
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(38, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed saving sidecar for character ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Guid>(characterId, "N");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
					}
					logger.LogWarning(val);
				}
			}
		}

		private static ItemInstanceModel[] MergeWithExistingHiddenSlots(Guid characterId, ItemInstanceModel[] visibleExtraSlots)
		{
			ItemInstanceModel[] array = Load(characterId, logFailure: false);
			int num = Math.Max(array.Length, visibleExtraSlots.Length);
			if (num == 0)
			{
				return Array.Empty<ItemInstanceModel>();
			}
			ItemInstanceModel[] array2 = (ItemInstanceModel[])(object)new ItemInstanceModel[num];
			Array.Copy(array, 0, array2, 0, array.Length);
			Array.Copy(visibleExtraSlots, 0, array2, 0, visibleExtraSlots.Length);
			return array2;
		}

		private static string GetPath(Guid characterId)
		{
			return Path.Combine(Paths.ConfigPath, "InventoryExpansion", characterId.ToString("N") + ".iex");
		}

		private static byte[] Encrypt(Guid characterId, byte[] plainBytes)
		{
			byte[] key = GetKey(characterId);
			byte[] array = new byte[12];
			byte[] array2 = new byte[16];
			byte[] array3 = new byte[plainBytes.Length];
			RandomNumberGenerator.Fill(array);
			using AesGcm aesGcm = new AesGcm(key, 16);
			aesGcm.Encrypt(array, plainBytes, array3, array2, GetAad(characterId));
			using MemoryStream memoryStream = new MemoryStream();
			using BinaryWriter binaryWriter = new BinaryWriter(memoryStream, Encoding.UTF8, leaveOpen: true);
			binaryWriter.Write(Magic);
			binaryWriter.Write((byte)array.Length);
			binaryWriter.Write(array);
			binaryWriter.Write((byte)array2.Length);
			binaryWriter.Write(array2);
			binaryWriter.Write(array3.Length);
			binaryWriter.Write(array3);
			binaryWriter.Flush();
			return memoryStream.ToArray();
		}

		private static byte[] Decrypt(Guid characterId, byte[] fileBytes)
		{
			using MemoryStream memoryStream = new MemoryStream(fileBytes);
			using BinaryReader binaryReader = new BinaryReader(memoryStream, Encoding.UTF8, leaveOpen: true);
			byte[] array = binaryReader.ReadBytes(Magic.Length);
			if (array.Length != Magic.Length || !CryptographicOperations.FixedTimeEquals(array, Magic))
			{
				throw new InvalidDataException("Invalid sidecar header.");
			}
			byte count = binaryReader.ReadByte();
			byte[] nonce = binaryReader.ReadBytes(count);
			byte count2 = binaryReader.ReadByte();
			byte[] tag = binaryReader.ReadBytes(count2);
			int num = binaryReader.ReadInt32();
			if (num < 0 || num > memoryStream.Length - memoryStream.Position)
			{
				throw new InvalidDataException("Invalid sidecar payload length.");
			}
			byte[] array2 = binaryReader.ReadBytes(num);
			byte[] array3 = new byte[array2.Length];
			using AesGcm aesGcm = new AesGcm(GetKey(characterId), 16);
			aesGcm.Decrypt(nonce, array2, tag, array3, GetAad(characterId));
			return array3;
		}

		private static byte[] GetKey(Guid characterId)
		{
			return SHA256.HashData(Encoding.UTF8.GetBytes($"{"IceBoxStudio.Romestead.InventoryExpansion"}|{characterId:N}|backpack-sidecar-v1"));
		}

		private static byte[] GetAad(Guid characterId)
		{
			return Encoding.UTF8.GetBytes($"{"IceBoxStudio.Romestead.InventoryExpansion"}|{characterId:N}|v1");
		}
	}
	internal static class BackpackSlotHelper
	{
		public static bool Active
		{
			get
			{
				if (ConfigManager.Active)
				{
					return GetConfiguredExtraSlotCount(null) > 0;
				}
				return false;
			}
		}

		public static int GetVanillaSlotCount(PlayerCharacterModel character)
		{
			if (character == null)
			{
				return 36;
			}
			return 36 + InventoryHelper.GetBonusSlotsForCharacter(character);
		}

		public static ItemInstanceModel[] Slice(ItemInstanceModel[] slots, int start, int count)
		{
			if (slots == null || count <= 0 || start >= slots.Length)
			{
				return Array.Empty<ItemInstanceModel>();
			}
			if (start < 0)
			{
				count += start;
				start = 0;
			}
			count = Math.Min(count, slots.Length - start);
			if (count <= 0)
			{
				return Array.Empty<ItemInstanceModel>();
			}
			ItemInstanceModel[] array = (ItemInstanceModel[])(object)new ItemInstanceModel[count];
			Array.Copy(slots, start, array, 0, count);
			return array;
		}

		public static ItemInstanceModel[] BuildVanillaSlots(ItemInstanceModel[] slots, int vanillaCount)
		{
			if (slots == null)
			{
				return Array.Empty<ItemInstanceModel>();
			}
			int num = Math.Min(slots.Length, vanillaCount);
			ItemInstanceModel[] array = (ItemInstanceModel[])(object)new ItemInstanceModel[num];
			Array.Copy(slots, 0, array, 0, num);
			return array;
		}

		public static ItemInstanceModel[] MergeForLogin(PlayerCharacterModel character, ItemInstanceModel[] vanillaSlots, ItemInstanceModel[] sidecarSlots)
		{
			int vanillaSlotCount = GetVanillaSlotCount(character);
			int configuredExtraSlotCount = GetConfiguredExtraSlotCount(character);
			ItemInstanceModel[] array = (ItemInstanceModel[])(object)new ItemInstanceModel[vanillaSlotCount + configuredExtraSlotCount];
			if (vanillaSlots != null)
			{
				Array.Copy(vanillaSlots, 0, array, 0, Math.Min(vanillaSlots.Length, vanillaSlotCount));
			}
			ItemInstanceModel[] array2 = (ItemInstanceModel[])(object)new ItemInstanceModel[configuredExtraSlotCount];
			if (sidecarSlots != null)
			{
				Array.Copy(sidecarSlots, 0, array2, 0, Math.Min(sidecarSlots.Length, configuredExtraSlotCount));
			}
			Array.Copy(array2, 0, array, vanillaSlotCount, configuredExtraSlotCount);
			return array;
		}

		public static int GetConfiguredExtraSlotCount(PlayerCharacterModel character)
		{
			if (!ConfigManager.Active)
			{
				return 0;
			}
			return ConfigManager.PlayerBackpackExtraSlotCount;
		}
	}
	internal static class InventoryExpansionHelper
	{
		public const int PlayerColumns = 6;

		public const int ChestColumns = 5;

		public const int WorkshopColumns = 5;

		private const string PlaceableChestConstructionId = "placeable_chest:0";

		private const int VanillaPlaceableChestSlots = 25;

		private const int VanillaFoodStorageSlots = 25;

		private const int VanillaMaterialStorageSlots = 48;

		private const int VanillaWorkshopStorageSlots = 24;

		private const int VanillaWorkshopOutputSlots = 18;

		private const int VanillaLargeWorkshopOutputSlots = 24;

		public static int GetExtraSlots(InventoryExpansionKind kind)
		{
			if (!ConfigManager.Active)
			{
				return 0;
			}
			return kind switch
			{
				InventoryExpansionKind.PlaceableChest => ConfigManager.PlaceableChestExtraSlotCount, 
				InventoryExpansionKind.FoodStorage => ConfigManager.FoodStorageExtraSlotCount, 
				InventoryExpansionKind.MaterialStorage => ConfigManager.MaterialStorageExtraSlotCount, 
				InventoryExpansionKind.Workshop => ConfigManager.WorkshopExtraSlotCount, 
				_ => 0, 
			};
		}

		public static int GetVisibleRows(InventoryExpansionKind kind)
		{
			return kind switch
			{
				InventoryExpansionKind.PlayerBackpack => ConfigManager.PlayerBackpackVisibleRows, 
				InventoryExpansionKind.PlaceableChest => ConfigManager.PlaceableChestVisibleRows, 
				InventoryExpansionKind.FoodStorage => ConfigManager.FoodStorageVisibleRows, 
				InventoryExpansionKind.MaterialStorage => 10, 
				InventoryExpansionKind.Workshop => ConfigManager.WorkshopVisibleRows, 
				_ => 0, 
			};
		}

		public static void ResizeMessage(CreateNewInventoryMessage msg, InventoryExpansionKind kind)
		{
			if (msg != null && msg.SlotsFilters == null)
			{
				int extraSlots = GetExtraSlots(kind);
				if (extraSlots > 0)
				{
					msg.InventorySize += extraSlots;
				}
			}
		}

		public static void EnsureInventorySize(Guid? inventoryId, InventoryExpansionKind kind, IOInventoryCreationType type = (IOInventoryCreationType)2, string buildingTypeId = null)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (inventoryId.HasValue)
			{
				int targetSlots = GetTargetSlots(kind, type, buildingTypeId);
				SharedInventoryModel inventory = default(SharedInventoryModel);
				if (targetSlots > 0 && ServerGameState.TryGetInventory(inventoryId.Value, ref inventory))
				{
					EnsureInventorySize(inventory, targetSlots);
				}
			}
		}

		public static void ApplyLoadedInventories()
		{
			foreach (BuildingSimulationModel value in ServerGameState.Buildings.Values)
			{
				InventoryExpansionKind buildingKind = GetBuildingKind(value, (IOInventoryCreationType)2);
				if (buildingKind != InventoryExpansionKind.None)
				{
					string buildingTypeId = value.InstanceModel.BuildingTypeId;
					Guid? storageInventoryId = value.InstanceModel.StorageInventoryId;
					Guid? outputInventoryId = value.InstanceModel.OutputInventoryId;
					EnsureInventorySize(storageInventoryId, buildingKind, (IOInventoryCreationType)0, buildingTypeId);
					if (outputInventoryId != storageInventoryId)
					{
						EnsureInventorySize(outputInventoryId, buildingKind, (IOInventoryCreationType)1, buildingTypeId);
					}
				}
			}
			foreach (ServerEntityModel value2 in ServerGameState.Entities.Values)
			{
				if (IsPlayerPlacedChest(value2))
				{
					EnsureInventorySize(GetEntityInventoryId(value2), InventoryExpansionKind.PlaceableChest, (IOInventoryCreationType)2);
				}
			}
		}

		public static void EnsureInventorySize(SharedInventoryModel inventory, int targetSlots)
		{
			if (inventory != null && inventory.SlotsFilter == null && targetSlots > 0)
			{
				int num = inventory.InventorySlots.Length;
				if (targetSlots > num)
				{
					SimpleInventorySController.IncreaseInventorySpace(inventory.Id, targetSlots - num);
				}
				else if (targetSlots < num)
				{
					TryShrinkInventory(inventory, targetSlots);
				}
			}
		}

		private static int GetTargetSlots(InventoryExpansionKind kind, IOInventoryCreationType type, string buildingTypeId)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			int extraSlots = GetExtraSlots(kind);
			return kind switch
			{
				InventoryExpansionKind.PlaceableChest => 25 + extraSlots, 
				InventoryExpansionKind.FoodStorage => 25 + extraSlots, 
				InventoryExpansionKind.MaterialStorage => 48 + extraSlots, 
				InventoryExpansionKind.Workshop => GetVanillaWorkshopSlots(buildingTypeId, type) + extraSlots, 
				_ => 0, 
			};
		}

		private static bool TryShrinkInventory(SharedInventoryModel inventory, int targetSlots)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			ItemInstanceModel[] inventorySlots = inventory.InventorySlots;
			bool flag = default(bool);
			for (int i = targetSlots; i < inventorySlots.Length; i++)
			{
				ItemInstanceModel val = inventorySlots[i];
				if (val == null)
				{
					continue;
				}
				int num = FindEmptySlot(inventorySlots, targetSlots);
				if (num < 0)
				{
					ManualLogSource logger = InventoryExpansion.Logger;
					if (logger != null)
					{
						BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(114, 2, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Inventory ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Guid>(inventory.Id);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" still has items outside the configured slot limit. Empty the extra slots before shrinking it to ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(targetSlots);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" slots.");
						}
						logger.LogWarning(val2);
					}
					return false;
				}
				inventorySlots[num] = val;
				inventorySlots[i] = null;
				val.InventoryId = inventory.Id;
			}
			ItemInstanceModel[] array = (ItemInstanceModel[])(object)new ItemInstanceModel[targetSlots];
			Array.Copy(inventorySlots, array, targetSlots);
			inventory.InventorySlots = array;
			return true;
		}

		private static int FindEmptySlot(ItemInstanceModel[] slots, int count)
		{
			for (int i = 0; i < count; i++)
			{
				if (slots[i] == null)
				{
					return i;
				}
			}
			return -1;
		}

		private static int GetVanillaWorkshopSlots(string buildingTypeId, IOInventoryCreationType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			if ((int)type != 1)
			{
				return 24;
			}
			if (buildingTypeId == "bakery" || buildingTypeId == "university")
			{
				return 24;
			}
			return 18;
		}

		public static int GetVanillaWorkshopSlotCount(string buildingTypeId, IOInventoryCreationType type)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return GetVanillaWorkshopSlots(buildingTypeId, type);
		}

		public static int GetVanillaMaterialStorageSlotCount()
		{
			return 48;
		}

		public static bool IsPlaceableChestConstruction(string constructionId)
		{
			return string.Equals(constructionId, "placeable_chest:0", StringComparison.Ordinal);
		}

		public static bool IsPlayerPlacedChest(ServerEntityModel entity)
		{
			if (entity != null && entity.BaseId == EntityIds.Chest && entity.Parameters != null)
			{
				return entity.Parameters.ContainsKey("owner_character_id");
			}
			return false;
		}

		public static Guid? GetEntityInventoryId(ServerEntityModel entity)
		{
			if (entity != null && entity.InventoryId.HasValue)
			{
				return entity.InventoryId;
			}
			if (entity?.Parameters != null && entity.Parameters.TryGetValue("inventory_id", out var value) && Guid.TryParse(value, out var result))
			{
				return result;
			}
			return null;
		}

		public static InventoryExpansionKind GetBuildingKind(BuildingSimulationModel building, IOInventoryCreationType creationType)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (building == null)
			{
				return InventoryExpansionKind.None;
			}
			return GetBuildingKind(building.InstanceModel.BuildingTypeId, creationType);
		}

		public static InventoryExpansionKind GetBuildingKind(string buildingTypeId, IOInventoryCreationType creationType)
		{
			if (buildingTypeId == "food_storage")
			{
				return InventoryExpansionKind.FoodStorage;
			}
			if (buildingTypeId == "material_storage")
			{
				return InventoryExpansionKind.MaterialStorage;
			}
			if (IsWorkshopBuilding(buildingTypeId))
			{
				return InventoryExpansionKind.Workshop;
			}
			return InventoryExpansionKind.None;
		}

		private static bool IsWorkshopBuilding(string buildingTypeId)
		{
			switch (buildingTypeId)
			{
			case "bakery":
			case "quarry":
			case "blacksmith":
			case "university":
			case "carpenter":
			case "farmstead":
			case "claypit":
			case "pottery":
			case "leatherworker":
			case "lumber_yard":
			case "sculptor":
				return true;
			default:
				return false;
			}
		}
	}
	internal enum InventoryExpansionKind
	{
		None,
		PlayerBackpack,
		PlaceableChest,
		FoodStorage,
		MaterialStorage,
		Workshop
	}
	internal static class StackSizeHelper
	{
		private static readonly Dictionary<string, int> VanillaStackSizes = new Dictionary<string, int>();

		public static void Apply(ItemData item)
		{
			int num = ((!ConfigManager.Active) ? 1 : ConfigManager.StackSizeMultiplierValue);
			if (item != null && !string.IsNullOrEmpty(item.Id))
			{
				if (!VanillaStackSizes.TryGetValue(item.Id, out var value))
				{
					value = item.MaxStackSize;
					VanillaStackSizes[item.Id] = value;
				}
				if (value <= 1)
				{
					item.MaxStackSize = value;
					return;
				}
				long num2 = (long)value * (long)num;
				item.MaxStackSize = (int)((num2 > int.MaxValue) ? int.MaxValue : num2);
			}
		}

		public static void ApplyAll()
		{
			foreach (ItemData value in ItemDataBase.DataMap.Values)
			{
				Apply(value);
			}
			RefreshItemInstances();
		}

		private static void RefreshItemInstances()
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			try
			{
				foreach (ItemInstanceModel item in new List<ItemInstanceModel>(ServerGameState.ItemInstances.Values))
				{
					if (item != null)
					{
						item.CalculateStats();
						if (item.StackCount > item.Data.MaxStackSize)
						{
							item.Data.MaxStackSize = item.StackCount;
						}
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger = InventoryExpansion.Logger;
				if (logger != null)
				{
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(47, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed refreshing stack sizes on loaded items: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
					}
					logger.LogWarning(val);
				}
			}
		}
	}
}
namespace InventoryExpansion.Patches
{
	[HarmonyPatch(typeof(BuildingsSController))]
	internal static class BuildingsSControllerInventoryPatch
	{
		[HarmonyPatch("CreateBuildingInventory")]
		[HarmonyPrefix]
		private static void CreateBuildingInventoryPrefix(BuildingInstanceModel buildingInstance, CreateNewInventoryMessage msg, IOInventoryCreationType type)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				InventoryExpansionKind buildingKind = InventoryExpansionHelper.GetBuildingKind(buildingInstance?.BuildingTypeId, type);
				InventoryExpansionHelper.ResizeMessage(msg, buildingKind);
			}
			catch (Exception ex)
			{
				ManualLogSource logger = InventoryExpansion.Logger;
				if (logger != null)
				{
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(45, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed resizing building inventory creation: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
					}
					logger.LogWarning(val);
				}
			}
		}

		[HarmonyPatch("AfterWorldGameStateLoaded")]
		[HarmonyPostfix]
		private static void AfterWorldGameStateLoadedPostfix()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			try
			{
				InventoryExpansionHelper.ApplyLoadedInventories();
			}
			catch (Exception ex)
			{
				ManualLogSource logger = InventoryExpansion.Logger;
				if (logger != null)
				{
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(45, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed resizing loaded building inventories: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
					}
					logger.LogWarning(val);
				}
			}
		}
	}
	[HarmonyPatch(typeof(CharacterSaveManager), "SaveCharacter")]
	internal static class CharacterSaveManagerPatch
	{
		private sealed class SaveState
		{
			public SharedInventoryModel InventoryModel;

			public ItemInstanceModel[] OriginalSlots;
		}

		private static void Prefix(PlayerCharacterModel model, string name, bool loadedFromBackup, double timePlayedAtLoad, ref SaveState __state)
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			__state = null;
			if (model == null)
			{
				return;
			}
			try
			{
				SimpleInventory val = default(SimpleInventory);
				if (GameState.TryGetLocalPlayerInventory(ref val) && val?.Model?.InventorySlots != null)
				{
					int vanillaSlotCount = BackpackSlotHelper.GetVanillaSlotCount(model);
					ItemInstanceModel[] inventorySlots = val.Model.InventorySlots;
					if (inventorySlots.Length > vanillaSlotCount)
					{
						ItemInstanceModel[] visibleExtraSlots = BackpackSlotHelper.Slice(inventorySlots, vanillaSlotCount, inventorySlots.Length - vanillaSlotCount);
						BackpackSidecarStore.Save(model.EntityId, visibleExtraSlots);
						__state = new SaveState
						{
							InventoryModel = val.Model,
							OriginalSlots = inventorySlots
						};
						val.Model.InventorySlots = BackpackSlotHelper.BuildVanillaSlots(inventorySlots, vanillaSlotCount);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger = InventoryExpansion.Logger;
				if (logger != null)
				{
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(55, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed preparing character save for expanded backpack: ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
					}
					logger.LogWarning(val2);
				}
			}
		}

		private static Exception Finalizer(Exception __exception, SaveState __state)
		{
			if (__state?.InventoryModel != null && __state.OriginalSlots != null)
			{
				__state.InventoryModel.InventorySlots = __state.OriginalSlots;
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(ConstructionsServerManager), "SpawnConstruction", new Type[]
	{
		typeof(ConstructionModel),
		typeof(Rectangle),
		typeof(Guid),
		typeof(Guid),
		typeof(Dictionary<string, string>),
		typeof(Guid?),
		typeof(Guid?),
		typeof(Guid?)
	})]
	internal static class ConstructionsServerManagerPatch
	{
		private sealed class SpawnState
		{
			public CreateNewInventoryMessageState Inventory;
		}

		private sealed class CreateNewInventoryMessageState
		{
			public CreateNewInventoryMessage Message;

			public int InventorySize;
		}

		private static void Prefix(ConstructionModel construction, ref SpawnState __state)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			__state = null;
			try
			{
				if (construction?.SpawnInventoryParameters != null && InventoryExpansionHelper.IsPlaceableChestConstruction(construction.Id))
				{
					__state = new SpawnState
					{
						Inventory = new CreateNewInventoryMessageState
						{
							Message = construction.SpawnInventoryParameters,
							InventorySize = construction.SpawnInventoryParameters.InventorySize
						}
					};
					InventoryExpansionHelper.ResizeMessage(construction.SpawnInventoryParameters, InventoryExpansionKind.PlaceableChest);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger = InventoryExpansion.Logger;
				if (logger != null)
				{
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(42, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed resizing placeable chest creation: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
					}
					logger.LogWarning(val);
				}
			}
		}

		private static Exception Finalizer(Exception __exception, SpawnState __state)
		{
			if (__state?.Inventory?.Message != null)
			{
				__state.Inventory.Message.InventorySize = __state.Inventory.InventorySize;
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(InventoryControl))]
	internal static class InventoryControlScrollPatch
	{
		private sealed class InventoryScrollViewer : CandideVerticalScrollViewer
		{
			private const int ThinScrollbarWidth = 4;

			private const int PlayerScrollbarInset = 1;

			private const int StorageScrollbarInset = 6;

			private const int ThinScrollbarHitPadding = 3;

			private const int MinThumbHeight = 18;

			private static readonly Color TrackColor = new Color(24, 22, 18, 120);

			private static readonly Color ThumbColor = new Color(188, 174, 144, 230);

			private static readonly Color ThumbShadowColor = new Color(58, 50, 40, 180);

			private Rectangle _thumbBounds;

			private int _thumbMaxY = 1;

			private float? _dragStartY;

			public bool IsPlayerInventory => FindPlayerInventory() != null;

			public bool IsStorageWindowInventory => FindParent<InventoryWindow>() != null;

			public InventoryScrollViewer()
			{
				base.ShowVerticalScrollBar = false;
				((CandideUiElement)this).ClipToBounds = false;
			}

			public int GetVisibleRows(InventoryControl control)
			{
				int fixedLayoutVisibleRows = GetFixedLayoutVisibleRows(control);
				if (fixedLayoutVisibleRows > 0)
				{
					return fixedLayoutVisibleRows;
				}
				int inventoryWindowVisibleRows = GetInventoryWindowVisibleRows(control);
				if (inventoryWindowVisibleRows > 0)
				{
					return inventoryWindowVisibleRows;
				}
				return InventoryExpansionHelper.GetVisibleRows(GetInventoryKind(control));
			}

			public InventoryExpansionKind GetInventoryKind(InventoryControl control)
			{
				if (FindPlayerInventory() != null)
				{
					return InventoryExpansionKind.PlayerBackpack;
				}
				InventoryExpansionKind kindForControlInventory = GetKindForControlInventory(control);
				if (kindForControlInventory != InventoryExpansionKind.None)
				{
					return kindForControlInventory;
				}
				InventoryWindow val = FindParent<InventoryWindow>();
				if (val != null)
				{
					if (IsPlayerPlacedChest(val))
					{
						return InventoryExpansionKind.PlaceableChest;
					}
					return GetKindForInventoryId(val.InventoryId);
				}
				ItemProcessingWindow val2 = FindParent<ItemProcessingWindow>();
				if (val2 != null)
				{
					Guid? guid = control.Inventory?.Model?.Id;
					InventoryExpansionKind kindForInventoryId = GetKindForInventoryId(guid);
					if (kindForInventoryId != InventoryExpansionKind.None)
					{
						return kindForInventoryId;
					}
					return GetKindForInventoryId((guid == val2.StorageInventoryId) ? val2.StorageInventoryId : val2.OutputInventoryId);
				}
				return InventoryExpansionKind.None;
			}

			public void UpdateInventoryWindowBackground(InventoryControl control, int visibleRows)
			{
				InventoryWindow val = FindParent<InventoryWindow>();
				if (val != null && !IsManualGraphics(val))
				{
					int valueOrDefault = (control.Inventory?.Model?.InventorySlots?.Length).GetValueOrDefault();
					int num = Math.Max(1, control.ColumnCount);
					int visibleSlots = Math.Min(valueOrDefault, Math.Max(1, visibleRows) * num);
					SetChestBackground(val, visibleSlots);
				}
			}

			private static bool IsManualGraphics(InventoryWindow window)
			{
				object obj = AccessTools.Field(typeof(InventoryWindow), "ManualGraphics")?.GetValue(window);
				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;
			}

			private static void SetChestBackground(InventoryWindow window, int visibleSlots)
			{
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				string text = "media/interface/new_ui_parts/ui_chest";
				if (visibleSlots > 30)
				{
					text = "media/interface/new_ui_parts/ui_chest_large";
				}
				else if (visibleSlots > 20)
				{
					text = "media/interface/new_ui_parts/ui_chest_medium";
				}
				((CandideCustomGraphicsWindow)window).SetArgs(new CustomBackgroundArgs
				{
					SpriteSheet = Content.SpriteSheet(text),
					TopLeftPixelOffset = new Point(1, 1),
					BottomRightPixelOffset = new Point(1, 2)
				});
			}

			private int GetFixedLayoutVisibleRows(InventoryControl control)
			{
				//IL_0158: Unknown result type (might be due to invalid IL or missing references)
				//IL_0165: Unknown result type (might be due to invalid IL or missing references)
				if (FindParent<ItemProcessingWindow>() == null && FindParent<NewJobWindow>() == null && FindParent<CandideAltarWindow>() == null && FindParent<NewOfferingView>() == null)
				{
					return 0;
				}
				Guid? guid = control.Inventory?.Model?.Id;
				if (!guid.HasValue)
				{
					return 0;
				}
				int columns = Math.Max(1, control.ColumnCount);
				SimpleInventory val = default(SimpleInventory);
				if (GameState.TryGetLocalPlayerInventory(ref val) && val?.Model?.Id == guid.Value)
				{
					int num = control.Inventory?.Model?.InventorySlots?.Length ?? 36;
					return GetRowsForSlots(Math.Max(36, num - BackpackSlotHelper.GetConfiguredExtraSlotCount(null)), columns);
				}
				if (!TryGetBuildingInventoryInfo(guid.Value, out var buildingTypeId, out var type))
				{
					return 0;
				}
				if (InventoryExpansionHelper.GetBuildingKind(buildingTypeId, type) != InventoryExpansionKind.Workshop)
				{
					return 0;
				}
				return GetRowsForSlots(InventoryExpansionHelper.GetVanillaWorkshopSlotCount(buildingTypeId, type), columns);
			}

			private int GetInventoryWindowVisibleRows(InventoryControl control)
			{
				if (FindParent<InventoryWindow>() == null)
				{
					return 0;
				}
				if (GetInventoryKind(control) != InventoryExpansionKind.MaterialStorage)
				{
					return 0;
				}
				return GetRowsForSlots(InventoryExpansionHelper.GetVanillaMaterialStorageSlotCount(), Math.Max(1, control.ColumnCount));
			}

			private static bool TryGetBuildingInventoryInfo(Guid inventoryId, out string buildingTypeId, out IOInventoryCreationType type)
			{
				foreach (Building value in GameState.Buildings.Values)
				{
					if (value?.Model != null)
					{
						if (value.Model.StorageInventoryId == inventoryId)
						{
							buildingTypeId = value.Model.BuildingTypeId;
							type = (IOInventoryCreationType)0;
							return true;
						}
						if (value.Model.OutputInventoryId == inventoryId)
						{
							buildingTypeId = value.Model.BuildingTypeId;
							type = (IOInventoryCreationType)1;
							return true;
						}
					}
				}
				buildingTypeId = null;
				type = (IOInventoryCreationType)0;
				return false;
			}

			protected override Vector2 InternalMeasure(Vector2 availableSize)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				if (((CandideUiContainerSingleItem)this).Child != null)
				{
					return ((CandideUiContainerSingleItem)this).Child.Measure(availableSize);
				}
				return Vector2.Zero;
			}

			protected override void InternalDraw(UiRenderContext context)
			{
				if (((CandideUiContainerSingleItem)this).Child != null && ((CandideUiContainerSingleItem)this).Child.Visible)
				{
					DrawChild(context);
					DrawScrollbar(context);
				}
			}

			protected override void OnMount()
			{
				((CandideUiElement)this).OnMount();
				UiCursorInteractionSystem.CursorPrimaryPressed += OnMousePrimaryPressed;
				UiCursorInteractionSystem.CursorPressMove += OnMousePressMove;
				UiCursorInteractionSystem.CursorPressRelease += OnMousePressRelease;
			}

			protected override void OnDismount()
			{
				UiCursorInteractionSystem.CursorPrimaryPressed -= OnMousePrimaryPressed;
				UiCursorInteractionSystem.CursorPressMove -= OnMousePressMove;
				UiCursorInteractionSystem.CursorPressRelease -= OnMousePressRelease;
				_dragStartY = null;
				((CandideUiElement)this).OnDismount();
			}

			public override void OnCursorPrimaryDown()
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				((CandideVerticalScrollViewer)this).OnCursorPrimaryDown();
				TryStartDrag(UiCursorNavigationSystem.CursorWindowPosition);
			}

			private void DrawScrollbar(UiRenderContext context)
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: 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_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_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				//IL_007f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0084: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				if (((CandideVerticalScrollViewer)this).ScrollYMaximum <= 0)
				{
					_thumbBounds = Rectangle.Empty;
					return;
				}
				Rectangle trackBounds = GetTrackBounds();
				_thumbBounds = GetThumbBounds(trackBounds);
				int num = Math.Max(1, CandideUiSystem.Scale);
				context.DrawRectangle(trackBounds, TrackColor, 0f);
				context.DrawRectangle(new Rectangle(_thumbBounds.X, _thumbBounds.Y, num, _thumbBounds.Height), ThumbShadowColor, 0f);
				context.DrawRectangle(_thumbBounds, ThumbColor, 0f);
			}

			private Rectangle GetTrackBounds()
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0056: 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)
				Rectangle actualBounds = ((CandideUiElement)this).ActualBounds;
				int num = Math.Max(1, 4 * CandideUiSystem.Scale);
				int num2 = ((!IsStorageWindowInventory) ? 1 : 6) * CandideUiSystem.Scale;
				return new Rectangle((IsPlayerInventory || IsStorageWindowInventory) ? (((Rectangle)(ref actualBounds)).Right + num2) : (((Rectangle)(ref actualBounds)).Right - num - num2), ((Rectangle)(ref actualBounds)).Top, num, actualBounds.Height);
			}

			private Rectangle GetThumbBounds(Rectangle trackBounds)
			{
				//IL_000e: 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_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0083: Unknown result type (might be due to invalid IL or missing references)
				//IL_008b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0092: Unknown result type (might be due to invalid IL or missing references)
				CandideUiElement child = ((CandideUiContainerSingleItem)this).Child;
				int num = Math.Max(1, (child == null) ? 1 : child.Bounds.Height);
				int val = Math.Max(1, 18 * CandideUiSystem.Scale);
				int num2 = Math.Min(trackBounds.Height, Math.Max(val, trackBounds.Height * trackBounds.Height / num));
				_thumbMaxY = Math.Max(1, trackBounds.Height - num2);
				int num3 = ((CandideVerticalScrollViewer)this).ScrollYPosition * _thumbMaxY / Math.Max(1, ((CandideVerticalScrollViewer)this).ScrollYMaximum);
				return new Rectangle(trackBounds.X, trackBounds.Y + num3, trackBounds.Width, num2);
			}

			private void OnMousePrimaryPressed(object sender, Vector2 position)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				TryStartDrag(position);
			}

			private void OnMousePressMove(object sender, Vector2 delta)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				if (!_dragStartY.HasValue)
				{
					return;
				}
				Vector2 cursorWindowPosition = UiCursorNavigationSystem.CursorWindowPosition;
				float num = cursorWindowPosition.Y - _dragStartY.Value;
				_dragStartY = cursorWindowPosition.Y;
				if (_thumbMaxY > 0)
				{
					float num2 = ((CandideVerticalScrollViewer)this).RealScrollYPosition + num * (float)((CandideVerticalScrollViewer)this).ScrollYMaximum / (float)_thumbMaxY;
					if (num2 < 0f)
					{
						num2 = 0f;
					}
					else if (num2 > (float)((CandideVerticalScrollViewer)this).ScrollYMaximum)
					{
						num2 = ((CandideVerticalScrollViewer)this).ScrollYMaximum;
					}
					((CandideVerticalScrollViewer)this).RealScrollYPosition = num2;
				}
			}

			private void OnMousePressRelease(object sender, EventArgs e)
			{
				_dragStartY = null;
			}

			private void TryStartDrag(Vector2 globalPosition)
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				if (IsVisibleInTree() && ((CandideVerticalScrollViewer)this).ScrollYMaximum > 0 && IsOverCustomScrollbar(globalPosition))
				{
					_dragStartY = globalPosition.Y;
				}
			}

			private bool IsOverCustomScrollbar(Vector2 globalPosition)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: 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)
				Rectangle trackBounds = GetTrackBounds();
				Rectangle thumbBounds = GetThumbBounds(trackBounds);
				int num = 3 * CandideUiSystem.Scale;
				((Rectangle)(ref thumbBounds)).Inflate(num, num);
				return ((Rectangle)(ref thumbBounds)).Contains(((CandideUiElement)this).ToLocal(globalPosition));
			}

			private bool IsVisibleInTree()
			{
				for (CandideUiElement val = (CandideUiElement)(object)this; val != null; val = val.Parent)
				{
					if (!val.Visible)
					{
						return false;
					}
				}
				return ((CandideUiElement)this).Desktop != null;
			}

			private void DrawChild(UiRenderContext context)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: 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_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: 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_0023: 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_002e: 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)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: Unknown result type (might be due to invalid IL or missing references)
				bool scissorEnabled = context.ScissorEnabled;
				Rectangle scissor = context.Scissor;
				Rectangle val = ((Transform)(ref context.Transform)).Apply(((CandideUiElement)this).Bounds);
				Rectangle val2 = (scissorEnabled ? Rectangle.Intersect(scissor, val) : val);
				if (val2.Width > 0 && val2.Height > 0)
				{
					context.ScissorEnabled = true;
					context.Scissor = val2;
					((CandideUiContainerSingleItem)this).Child.Draw(context);
				}
				context.ScissorEnabled = scissorEnabled;
				context.Scissor = scissor;
			}

			private PlayerInventoryUserControl FindPlayerInventory()
			{
				return FindParent<PlayerInventoryUserControl>();
			}

			private T FindParent<T>() where T : CandideUiElement
			{
				for (CandideUiElement parent = ((CandideUiElement)this).Parent; parent != null; parent = parent.Parent)
				{
					T val = (T)(object)((parent is T) ? parent : null);
					if (val != null)
					{
						return val;
					}
				}
				return default(T);
			}
		}

		private const int SlotHeight = 30;

		private static readonly ConditionalWeakTable<InventoryControl, InventoryScrollViewer> Viewers = new ConditionalWeakTable<InventoryControl, InventoryScrollViewer>();

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		private static void ConstructorPostfix(InventoryControl __instance)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (__instance == null)
			{
				return;
			}
			try
			{
				object? value = AccessTools.Field(typeof(InventoryControl), "_mainPanel").GetValue(__instance);
				CandideVerticalStackPanel val = (CandideVerticalStackPanel)((value is CandideVerticalStackPanel) ? value : null);
				if (val != null && ((CandideUiContainerMultipleItems)val).RemoveChild((CandideUiElement)(object)__instance.Grid))
				{
					InventoryScrollViewer obj = new InventoryScrollViewer
					{
						VerticalScrollBackground = Color.Transparent
					};
					((CandideUiElement)obj).HorizontalAlignment = (HorizontalAlignment)3;
					((CandideUiElement)obj).VerticalAlignment = (VerticalAlignment)0;
					InventoryScrollViewer inventoryScrollViewer = obj;
					((CandideUiContainerSingleItem)inventoryScrollViewer).SetChild((CandideUiElement)(object)__instance.Grid);
					((CandideUiContainerMultipleItems)val).AddChild((CandideUiElement)(object)inventoryScrollViewer, true);
					Viewers.Remove(__instance);
					Viewers.Add(__instance, inventoryScrollViewer);
					UpdateViewerHeight(__instance, inventoryScrollViewer);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger = InventoryExpansion.Logger;
				if (logger != null)
				{
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(35, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed adding inventory scrollbar: ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
					}
					logger.LogWarning(val2);
				}
			}
		}

		[HarmonyPatch("InvalidateSlots")]
		[HarmonyPostfix]
		private static void InvalidateSlotsPostfix(InventoryControl __instance)
		{
			if (__instance != null && Viewers.TryGetValue(__instance, out var value))
			{
				UpdateViewerHeight(__instance, value);
			}
		}

		private static void UpdateViewerHeight(InventoryControl control, InventoryScrollViewer viewer)
		{
			int valueOrDefault = (control.Inventory?.Model?.InventorySlots?.Length).GetValueOrDefault();
			int num = Math.Max(1, control.ColumnCount);
			int num2 = (valueOrDefault + num - 1) / num;
			int visibleRows = viewer.GetVisibleRows(control);
			if (num2 <= 0)
			{
				((CandideUiElement)viewer).Height = null;
				((CandideVerticalScrollViewer)viewer).ScrollYPosition = 0;
				return;
			}
			if (visibleRows <= 0)
			{
				((CandideUiElement)viewer).Height = null;
				((CandideVerticalScrollViewer)viewer).ScrollYPosition = 0;
				return;
			}
			((CandideUiElement)viewer).Height = Math.Min(num2, visibleRows) * 30;
			viewer.UpdateInventoryWindowBackground(control, visibleRows);
			if (((CandideVerticalScrollViewer)viewer).ScrollYPosition > ((CandideVerticalScrollViewer)viewer).ScrollYMaximum)
			{
				((CandideVerticalScrollViewer)viewer).ScrollYPosition = ((CandideVerticalScrollViewer)viewer).ScrollYMaximum;
			}
		}

		private static InventoryExpansionKind GetKindForInventoryId(Guid? inventoryId)
		{
			if (!inventoryId.HasValue)
			{
				return InventoryExpansionKind.None;
			}
			foreach (Building value in GameState.Buildings.Values)
			{
				if (value?.Model != null && (!(value.Model.StorageInventoryId != inventoryId) || !(value.Model.OutputInventoryId != inventoryId)))
				{
					return InventoryExpansionHelper.GetBuildingKind(value.Model.BuildingTypeId, (IOInventoryCreationType)0);
				}
			}
			return InventoryExpansionKind.None;
		}

		private static InventoryExpansionKind GetKindForControlInventory(InventoryControl control)
		{
			Guid? inventoryId = ((control == null) ? ((Guid?)null) : control.Inventory?.Model?.Id);
			if (!inventoryId.HasValue)
			{
				return InventoryExpansionKind.None;
			}
			SimpleInventory val = default(SimpleInventory);
			if (GameState.TryGetLocalPlayerInventory(ref val) && val?.Model?.Id == inventoryId.Value)
			{
				return InventoryExpansionKind.PlayerBackpack;
			}
			return GetKindForInventoryId(inventoryId);
		}

		private static bool IsPlayerPlacedChest(InventoryWindow window)
		{
			if (window != null && window.CanRenameInventory && ((CustomGraphicsProximityWindow)window).AttachedEntity != null)
			{
				return ((CustomGraphicsProximityWindow)window).AttachedEntity.BaseGuid == EntityIds.Chest;
			}
			return false;
		}

		private static int GetRowsForSlots(int slots, int columns)
		{
			return (Math.Max(0, slots) + Math.Max(1, columns) - 1) / Math.Max(1, columns);
		}
	}
	[HarmonyPatch(typeof(ItemDataBase), "AddItems")]
	internal static class ItemDataBasePatch
	{
		private static void Postfix(List<ItemData> itemDataList)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			try
			{
				if (itemDataList == null)
				{
					return;
				}
				foreach (ItemData itemData in itemDataList)
				{
					StackSizeHelper.Apply(itemData);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger = InventoryExpansion.Logger;
				if (logger != null)
				{
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(39, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed applying stack size multiplier: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
					}
					logger.LogWarning(val);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerCharacterServerManager), "SetupCharacter")]
	internal static class PlayerCharacterServerManagerPatch
	{
		private static void Postfix(PlayerCharacterModel playerCharacter, ServerPlayerCharacter __result)
		{
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Expected O, but got Unknown
			if (!BackpackSlotHelper.Active || playerCharacter == null || __result == null)
			{
				return;
			}
			try
			{
				SharedInventoryModel val = default(SharedInventoryModel);
				if (!ServerGameState.TryGetInventory(__result.Character.CharacterInventoryModel.InventoryId, ref val))
				{
					return;
				}
				int vanillaSlotCount = BackpackSlotHelper.GetVanillaSlotCount(__result.Character);
				int configuredExtraSlotCount = BackpackSlotHelper.GetConfiguredExtraSlotCount(__result.Character);
				if (val.InventorySlots.Length < vanillaSlotCount + configuredExtraSlotCount)
				{
					SimpleInventorySController.IncreaseInventorySpace(val.Id, vanillaSlotCount + configuredExtraSlotCount - val.InventorySlots.Length);
				}
				ItemInstanceModel[] array = BackpackRuntime.TakePendingExtraSlots(playerCharacter.EntityId);
				int num = Math.Min(array.Length, Math.Max(0, val.InventorySlots.Length - vanillaSlotCount));
				for (int i = 0; i < num; i++)
				{
					ItemInstanceModel val2 = array[i];
					if (val2 == null)
					{
						continue;
					}
					ItemInstanceModel val3 = ItemInstanceSController.CreateNewItemInstance(val2.BaseDataId, val2.StackCount, Guid.NewGuid(), (Guid?)val.Id, (string)null);
					if (val3 != null)
					{
						if (val2.Auras.Count > 0)
						{
							ItemInstanceSController.AddItemAurasSilent(val3, val2.Auras);
						}
						if (val2.UsableInfo != null && val3.UsableInfo != null)
						{
							val3.UsableInfo.UsesLeft = val2.UsableInfo.UsesLeft;
							val3.UsableInfo.CooldownRemaining = val2.UsableInfo.CooldownRemaining;
						}
						val.InventorySlots[vanillaSlotCount + i] = val3;
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger = InventoryExpansion.Logger;
				if (logger != null)
				{
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val4 = new BepInExWarningLogInterpolatedStringHandler(42, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Failed restoring expanded backpack slots: ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(ex.Message);
					}
					logger.LogWarning(val4);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerLoginModel), "FromSaveModel")]
	internal static class PlayerLoginModelPatch
	{
		private static void Postfix(PlayerCharacterSaveModel saveModel, ref PlayerLoginModel __result)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			if (!BackpackSlotHelper.Active || saveModel?.CharacterModel == null || __result == null)
			{
				return;
			}
			try
			{
				ItemInstanceModel[] sidecarSlots = BackpackSidecarStore.Load(saveModel.CharacterModel.EntityId);
				__result.Inventory = BackpackSlotHelper.MergeForLogin(saveModel.CharacterModel, saveModel.Inventory, sidecarSlots);
			}
			catch (Exception ex)
			{
				ManualLogSource logger = InventoryExpansion.Logger;
				if (logger != null)
				{
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(43, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed merging backpack sidecar for login: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
					}
					logger.LogWarning(val);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerServerService), "Login")]
	internal static class PlayerServerServiceLoginPatch
	{
		private sealed class LoginState
		{
			public ItemInstanceModel[] OriginalInventory;
		}

		private static void Prefix(LoginModelMessage loginMessage, EventBusArgs args, ref LoginState __state)
		{
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			__state = null;
			if (loginMessage?.CharacterInfo?.CharacterModel == null || loginMessage.CharacterInfo.Inventory == null)
			{
				return;
			}
			try
			{
				int vanillaSlotCount = BackpackSlotHelper.GetVanillaSlotCount(loginMessage.CharacterInfo.CharacterModel);
				ItemInstanceModel[] inventory = loginMessage.CharacterInfo.Inventory;
				__state = new LoginState
				{
					OriginalInventory = inventory
				};
				if (inventory.Length <= vanillaSlotCount)
				{
					BackpackRuntime.SetPendingExtraSlots(loginMessage.CharacterInfo.CharacterModel.EntityId, Array.Empty<ItemInstanceModel>());
					return;
				}
				int count = Math.Min(BackpackSlotHelper.Active ? BackpackSlotHelper.GetConfiguredExtraSlotCount(loginMessage.CharacterInfo.CharacterModel) : 0, inventory.Length - vanillaSlotCount);
				ItemInstanceModel[] array = BackpackSlotHelper.Slice(inventory, vanillaSlotCount, count);
				if (!SimpleInventorySController.ValidateInventorySlots(array))
				{
					array = Array.Empty<ItemInstanceModel>();
				}
				BackpackRuntime.SetPendingExtraSlots(loginMessage.CharacterInfo.CharacterModel.EntityId, array);
				loginMessage.CharacterInfo.Inventory = BackpackSlotHelper.BuildVanillaSlots(inventory, vanillaSlotCount);
			}
			catch (Exception ex)
			{
				ManualLogSource logger = InventoryExpansion.Logger;
				if (logger != null)
				{
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(42, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed preparing expanded backpack login: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
					}
					logger.LogWarning(val);
				}
			}
		}

		private static void Postfix(LoginModelMessage loginMessage, EventBusArgs args, LoginState __state)
		{
			if (__state?.OriginalInventory != null && loginMessage?.CharacterInfo != null)
			{
				loginMessage.CharacterInfo.Inventory = __state.OriginalInventory;
			}
		}
	}
	[HarmonyPatch(typeof(ServerEntitySystemManager), "OnEntitiesGameStateLoaded")]
	internal static class ServerEntitySystemManagerPatch
	{
		private static void Postfix()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			try
			{
				InventoryExpansionHelper.ApplyLoadedInventories();
			}
			catch (Exception ex)
			{
				ManualLogSource logger = InventoryExpansion.Logger;
				if (logger != null)
				{
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(41, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed resizing loaded placeable chests: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
					}
					logger.LogWarning(val);
				}
			}
		}
	}
}
namespace InventoryExpansion.Configuration
{
	internal static class ConfigManager
	{
		private sealed class SectionTag
		{
			private readonly string _displayNameKey;

			public string Section { get; }

			public string DisplayName => Text(_displayNameKey);

			public int? Order { get; }

			public SectionTag(string section, string displayNameKey, int? order)
			{
				Section = section;
				_displayNameKey = displayNameKey;
				Order = order;
			}
		}

		private sealed class EntryTag
		{
			private readonly string _displayNameKey;

			private readonly string _descriptionKey;

			public string DisplayName => Text(_displayNameKey);

			public string Description => Text(_descriptionKey);

			public int? Order { get; }

			public double? SliderStep { get; }

			public EntryTag(string displayNameKey, string descriptionKey, int? order, double? sliderStep)
			{
				_displayNameKey = displayNameKey;
				_descriptionKey = descriptionKey;
				Order = order;
				SliderStep = sliderStep;
			}
		}

		public const string GeneralSection = "General";

		private const string StackSizeSection = "StackSize";

		private const string ExtraSlotsSection = "ExtraSlots";

		private const string VisibleRowsSection = "VisibleRows";

		public static ConfigEntry<bool> Enabled { get; private set; }

		public static ConfigEntry<int> StackSizeMultiplier { get; private set; }

		public static ConfigEntry<int> PlayerBackpackExtraSlots { get; private set; }

		public static ConfigEntry<int> PlaceableChestExtraSlots { get; private set; }

		public static ConfigEntry<int> FoodStorageExtraSlots { get; private set; }

		public static ConfigEntry<int> MaterialStorageExtraSlots { get; private set; }

		public static ConfigEntry<int> WorkshopExtraSlots { get; private set; }

		public static ConfigEntry<int> PlayerBackpackRows { get; private set; }

		public static ConfigEntry<int> PlaceableChestRows { get; private set; }

		public static ConfigEntry<int> FoodStorageRows { get; private set; }

		public static ConfigEntry<int> WorkshopRows { get; private set; }

		public static bool Active => Enabled?.Value ?? false;

		public static int StackSizeMultiplierValue => ValueOrDefault(StackSizeMultiplier, 1, 1);

		public static int PlayerBackpackExtraSlotCount => ValueOrDefault(PlayerBackpackExtraSlots, 0, 0);

		public static int PlaceableChestExtraSlotCount => ValueOrDefault(PlaceableChestExtraSlots, 0, 0);

		public static int FoodStorageExtraSlotCount => ValueOrDefault(FoodStorageExtraSlots, 0, 0);

		public static int MaterialStorageExtraSlotCount => ValueOrDefault(MaterialStorageExtraSlots, 0, 0);

		public static int WorkshopExtraSlotCount => ValueOrDefault(WorkshopExtraSlots, 0, 0);

		public static int PlayerBackpackVisibleRows => ValueOrDefault(PlayerBackpackRows, 6, 6);

		public static int PlaceableChestVisibleRows => StorageRowsOrDefault(PlaceableChestRows);

		public static int FoodStorageVisibleRows => StorageRowsOrDefault(FoodStorageRows);

		public static int WorkshopVisibleRows => StorageRowsOrDefault(WorkshopRows);

		public static void Init(ConfigFile config)
		{
			Enabled = config.Bind<bool>("General", "Enabled", true, Description("config.enabled.description", "entry.enabled", 1, "General", "section.general", 10));
			StackSizeMultiplier = config.Bind<int>("StackSize", "StackSizeMultiplier", 1, Description("config.stack_size_multiplier.description", "entry.stack_size_multiplier", 1, "StackSize", "section.stack_size", 20, (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), 1.0));
			PlayerBackpackExtraSlots = config.Bind<int>("ExtraSlots", "PlayerBackpackExtraSlots", 0, Description("config.player_backpack_extra_slots.description", "entry.player_backpack_extra_slots", 1, "ExtraSlots", "section.extra_slots", 30, (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 240), 1.0));
			PlaceableChestExtraSlots = config.Bind<int>("ExtraSlots", "PlaceableChestExtraSlots", 0, Description("config.placeable_chest_extra_slots.description", "entry.placeable_chest_extra_slots", 2, "ExtraSlots", "section.extra_slots", 30, (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), 1.0));
			FoodStorageExtraSlots = config.Bind<int>("ExtraSlots", "FoodStorageExtraSlots", 0, Description("config.food_storage_extra_slots.description", "entry.food_storage_extra_slots", 3, "ExtraSlots", "section.extra_slots", 30, (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), 1.0));
			MaterialStorageExtraSlots = config.Bind<int>("ExtraSlots", "MaterialStorageExtraSlots", 0, Description("config.material_storage_extra_slots.description", "entry.material_storage_extra_slots", 4, "ExtraSlots", "section.extra_slots", 30, (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 300), 1.0));
			WorkshopExtraSlots = config.Bind<int>("ExtraSlots", "WorkshopExtraSlots", 0, Description("config.workshop_extra_slots.description", "entry.workshop_extra_slots", 5, "ExtraSlots", "section.extra_slots", 30, (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), 1.0));
			PlayerBackpackRows = config.Bind<int>("VisibleRows", "PlayerBackpackRows", 6, Description("config.player_backpack_rows.description", "entry.player_backpack_rows", 1, "VisibleRows", "section.visible_rows", 40, (AcceptableValueBase)(object)new AcceptableValueRange<int>(6, 12), 1.0));
			PlaceableChestRows = config.Bind<int>("VisibleRows", "PlaceableChestRows", 5, Description("config.placeable_chest_rows.description", "entry.placeable_chest_rows", 2, "VisibleRows", "section.visible_rows", 40, (AcceptableValueBase)(object)new AcceptableValueList<int>(new int[2] { 5, 10 }), 1.0));
			FoodStorageRows = config.Bind<int>("VisibleRows", "FoodStorageRows", 5, Description("config.food_storage_rows.description", "entry.food_storage_rows", 3, "VisibleRows", "section.visible_rows", 40, (AcceptableValueBase)(object)new AcceptableValueList<int>(new int[2] { 5, 10 }), 1.0));
			WorkshopRows = config.Bind<int>("VisibleRows", "WorkshopRows", 5, Description("config.workshop_rows.description", "entry.workshop_rows", 4, "VisibleRows", "section.visible_rows", 40, (AcceptableValueBase)(object)new AcceptableValueList<int>(new int[2] { 5, 10 }), 1.0));
		}

		private static int ValueOrDefault(ConfigEntry<int> entry, int defaultValue, int min)
		{
			int num = entry?.Value ?? defaultValue;
			if (num >= min)
			{
				return num;
			}
			return min;
		}

		private static int StorageRowsOrDefault(ConfigEntry<int> entry)
		{
			if ((entry?.Value ?? 5) != 10)
			{
				return 5;
			}
			return 10;
		}

		private static ConfigDescription Description(string descriptionKey, string displayNameKey, int entryOrder, string section, string sectionDisplayNameKey, int sectionOrder, AcceptableValueBase acceptableValues = null, double? sliderStep = null)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			List<object> list = new List<object>
			{
				new SectionTag(section, sectionDisplayNameKey, sectionOrder),
				new EntryTag(displayNameKey, descriptionKey, entryOrder, sliderStep)
			};
			return new ConfigDescription(Text(descriptionKey), acceptableValues, list.ToArray());
		}

		private static string Text(string key)
		{
			return I18n.L.Text(key, Array.Empty<object>());
		}
	}
	internal static class ModSettingsMenuRegistration
	{
		private static ConfigFile _config;

		private static string _locale;

		private static bool _subscribed;

		public static void Register(ConfigFile config)
		{
			_config = config;
			if (!_subscribed)
			{
				ModSettingsRegistry.RefreshRequested += Refresh;
				_subscribed = true;
			}
			RegisterCurrent(config);
		}

		private static void Refresh()
		{
			if (_config != null)
			{
				string currentLocale = I18n.L.CurrentLocale;
				ModSettingsRegistration val = default(ModSettingsRegistration);
				if (!(_locale == currentLocale) || !ModSettingsRegistry.TryGet("IceBoxStudio.Romestead.InventoryExpansion", ref val))
				{
					RegisterCurrent(_config);
				}
			}
		}

		private static void RegisterCurrent(ConfigFile config)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			ModSettingsRegistry.Register("IceBoxStudio.Romestead.InventoryExpansion", Text("mod.name"), config, new ModSettingsModOptions
			{
				Icon = "cog",
				Version = "1.0.3",
				Author = "Ice Box Studio",
				Description = Text("mod.description"),
				NexusModsId = 59,
				ThunderstoreTeam = "Ice_Box_Studio_Romestead",
				ThunderstoreModName = "InventoryExpansion",
				UpdateManifestUrl = "https://fastly.jsdelivr.net/gh/ibox233/MyMod_Version@main/InventoryExpansion.json",
				Order = -70
			});
			_locale = I18n.L.CurrentLocale;
		}

		private static string Text(string key)
		{
			return I18n.L.Text(key, Array.Empty<object>());
		}
	}
}