Decompiled source of DFGQoL v0.3.2

DFGQoL.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using MyMods.Web;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("DFGQoL")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.2.0")]
[assembly: AssemblyInformationalVersion("0.3.2+901b84ab23f2f10926b13865f9b40bb283490874")]
[assembly: AssemblyProduct("DFGQoL")]
[assembly: AssemblyTitle("DFGQoL")]
[assembly: AssemblyVersion("0.3.2.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MyMods.Web
{
	public static class WebNav
	{
		public sealed class Link
		{
			public readonly string Id;

			public readonly string Label;

			public readonly int Port;

			public string Url => "http://127.0.0.1:" + Port + "/";

			public Link(string id, string label, int port)
			{
				Id = id;
				Label = label;
				Port = port;
			}
		}

		public static readonly Link[] Links = new Link[13]
		{
			new Link("monsters", "Monsters", 8777),
			new Link("searoute", "SeaRoute", 8778),
			new Link("longboat", "Harpoon Longboat", 8779),
			new Link("tradewind", "TradeWind", 8780),
			new Link("safeharbor", "Safe Harbor", 8781),
			new Link("hub", "DFG Hub", 8782),
			new Link("vault", "Viking Vault", 8783),
			new Link("qolvault", "QoL Vault Buttons", 8784),
			new Link("qolinventory", "QoL Inventory Buttons", 8785),
			new Link("cacophony", "Cacophony", 8787),
			new Link("ominous", "Ominous", 8788),
			new Link("pebble", "Pebble", 8789),
			new Link("trolls", "Trolls", 8790)
		};

		public const string Style = "nav.top{position:sticky;top:0;z-index:20;font-family:Segoe UI,Arial,sans-serif;background:#0d1219;border-bottom:1px solid #2b3b4c;padding:6px 14px;display:flex;align-items:center;gap:6px;flex-wrap:wrap}\nnav.top .brand{color:#7f8fa0;font-size:11px;text-transform:uppercase;letter-spacing:.6px;margin-right:8px}\nnav.top a{color:#9fc3dd;text-decoration:none;font-size:13px;padding:4px 9px;border-radius:5px}\nnav.top a:hover{background:#1a2530}\nnav.top a.here{background:#3a2b4c;border:1px solid #55406b;color:#efe0ff}\n";

		public static string Html(string currentId)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("<nav class='top'><span class='brand'>MyMods</span>");
			Link[] links = Links;
			foreach (Link link in links)
			{
				stringBuilder.Append("<a class='");
				if (link.Id == currentId)
				{
					stringBuilder.Append("here");
				}
				stringBuilder.Append("' href='").Append(link.Url).Append("'>")
					.Append(link.Label)
					.Append("</a>");
			}
			stringBuilder.Append("</nav>");
			return stringBuilder.ToString();
		}

		public static Link Find(string id)
		{
			Link[] links = Links;
			foreach (Link link in links)
			{
				if (link.Id == id)
				{
					return link;
				}
			}
			return null;
		}
	}
}
namespace DFGQoL
{
	internal static class QoLSettings
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> ShowMainMenuLogo;

		internal static ConfigEntry<int> MainMenuLogoSize;

		internal static ConfigEntry<int> MainMenuLogoRightMargin;

		internal static ConfigEntry<int> MainMenuLogoTopMargin;

		internal static ConfigEntry<int> MainMenuLogoOpacity;

		internal static ConfigEntry<bool> DisableScreenShake;

		internal static ConfigEntry<bool> EnableSmoothMovement;

		internal static ConfigEntry<float> BaseCarryWeight;

		internal static ConfigEntry<bool> InfiniteFireFuel;

		internal static ConfigEntry<bool> InfiniteLightFuel;

		internal static ConfigEntry<float> ItemWeightPercent;

		internal static ConfigEntry<float> ItemStackSizePercent;

		internal static ConfigEntry<bool> NoTeleportPrevention;

		internal static ConfigEntry<bool> ItemsFloatInWater;

		internal static ConfigEntry<float> ToolDurabilityPercent;

		internal static ConfigEntry<float> WeaponDurabilityPercent;

		internal static ConfigEntry<float> BowDurabilityPercent;

		internal static ConfigEntry<float> ShieldDurabilityPercent;

		internal static ConfigEntry<float> ArmorDurabilityPercent;

		internal static ConfigEntry<float> TorchDurabilityPercent;

		internal static ConfigEntry<float> HelmetArmorPercent;

		internal static ConfigEntry<float> ChestArmorPercent;

		internal static ConfigEntry<float> LegArmorPercent;

		internal static ConfigEntry<float> CapeArmorPercent;

		internal static ConfigEntry<float> ShieldBlockPercent;

		internal static ConfigEntry<bool> DisableDamageFlash;

		internal static ConfigEntry<bool> ShowNumericalStamina;

		internal static ConfigEntry<int> NumericalStaminaTextSize;

		internal static ConfigEntry<bool> ShowBowAmmoCount;

		internal static ConfigEntry<int> BowAmmoTextSize;

		internal static ConfigEntry<bool> ShowGameClock;

		internal static ConfigEntry<bool> ClockUse24Hour;

		internal static ConfigEntry<int> ClockFontSize;

		internal static ConfigEntry<int> ClockTopOffset;

		internal static ConfigEntry<int> ClockRed;

		internal static ConfigEntry<int> ClockGreen;

		internal static ConfigEntry<int> ClockBlue;

		internal static ConfigEntry<int> ClockOpacity;

		internal static ConfigEntry<bool> EnableFieldOfView;

		internal static ConfigEntry<float> FieldOfView;

		internal static ConfigEntry<float> FieldOfViewStep;

		internal static ConfigEntry<KeyboardShortcut> IncreaseFieldOfViewKey;

		internal static ConfigEntry<KeyboardShortcut> DecreaseFieldOfViewKey;

		internal static ConfigEntry<bool> EnableRollHotkeys;

		internal static ConfigEntry<KeyboardShortcut> ForwardRollKey;

		internal static ConfigEntry<KeyboardShortcut> BackwardRollKey;

		internal static ConfigEntry<bool> DisableFog;

		internal static ConfigEntry<bool> EnableNightBrightness;

		internal static ConfigEntry<float> NightBrightnessMultiplier;

		internal static ConfigEntry<bool> EnableProductionCache;

		internal static ConfigEntry<bool> ProductionCacheAutoFuel;

		internal static ConfigEntry<bool> ProductionCacheAutoOre;

		internal static ConfigEntry<bool> ProductionCacheAutoOutput;

		internal static ConfigEntry<float> ProductionCacheRadius;

		internal static ConfigEntry<float> ProductionCacheInterval;

		internal static ConfigEntry<int> ProductionCacheMaxTransfersPerCycle;

		internal static ConfigEntry<int> ProductionCacheWidth;

		internal static ConfigEntry<int> ProductionCacheHeight;

		internal static ConfigEntry<int> ProductionCacheWoodCost;

		internal static ConfigEntry<int> ProductionCacheFineWoodCost;

		internal static ConfigEntry<int> ProductionCacheStoneCost;

		internal static ConfigEntry<int> ProductionCacheIronCost;

		internal static ConfigEntry<bool> ProductionCacheDebugLogging;

		internal static ConfigEntry<string> ProductionCacheModelFile;

		internal static ConfigEntry<float> ProductionCacheModelScale;

		internal static ConfigEntry<float> ProductionCacheModelRotationY;

		internal static ConfigEntry<float> ProductionCacheModelOffsetX;

		internal static ConfigEntry<float> ProductionCacheModelOffsetY;

		internal static ConfigEntry<float> ProductionCacheModelOffsetZ;

		internal static ConfigEntry<bool> EnableProductionCacheVaultTransfer;

		internal static ConfigEntry<float> ProductionCacheVaultTransferRadius;

		internal static ConfigEntry<float> ProductionCacheVaultMetalsButtonOffsetX;

		internal static ConfigEntry<float> ProductionCacheVaultMetalsButtonOffsetY;

		internal static ConfigEntry<float> ProductionCacheVaultAllButtonOffsetX;

		internal static ConfigEntry<float> ProductionCacheVaultAllButtonOffsetY;

		internal static ConfigEntry<float> ProductionCacheVaultButtonWidth;

		internal static ConfigEntry<float> ProductionCacheVaultButtonHeight;

		internal static ConfigEntry<string> ProductionCacheCustomTransferItems;

		internal static ConfigEntry<bool> EnableProductionCacheVaultWebGui;

		internal static ConfigEntry<int> ProductionCacheVaultWebPort;

		internal static ConfigEntry<bool> EnableCraftFromContainers;

		internal static ConfigEntry<float> CraftFromContainersRadius;

		internal static ConfigEntry<bool> CraftFromContainersIncludeCarts;

		internal static ConfigEntry<bool> CraftFromContainersIncludeShips;

		internal static ConfigEntry<bool> ShowAvailableAmount;

		internal static ConfigEntry<int> PlayerInventoryRows;

		internal static ConfigEntry<bool> EnableInventorySort;

		internal static ConfigEntry<bool> InventorySortStackFirst;

		internal static ConfigEntry<bool> InventorySortKeepHotbar;

		internal static ConfigEntry<bool> EnableFavorites;

		internal static ConfigEntry<string> FavoriteSlots;

		internal static ConfigEntry<string> FavoriteItems;

		internal static ConfigEntry<bool> EnableVaultDepositButton;

		internal static ConfigEntry<float> VaultDepositRadius;

		internal static ConfigEntry<bool> VaultDepositOnlyInRange;

		internal static ConfigEntry<float> InventoryButtonOffsetX;

		internal static ConfigEntry<float> InventoryButtonOffsetY;

		internal static ConfigEntry<float> InventoryButtonWidth;

		internal static ConfigEntry<float> InventoryButtonHeight;

		internal static ConfigEntry<bool> EnableInventoryButtonWebGui;

		internal static ConfigEntry<int> InventoryButtonWebPort;

		internal static ConfigEntry<bool> EnableContainerSpacing;

		internal static ConfigEntry<float> ContainerSpacing;

		internal static ConfigEntry<float> ContainerOffsetY;

		internal static ConfigEntry<float> ContainerOffsetX;

		internal static ConfigEntry<bool> EnableEquipmentPanel;

		internal static ConfigEntry<int> UtilitySlotCount;

		internal static ConfigEntry<bool> EnableQuickSlots;

		internal static ConfigEntry<int> QuickSlotCount;

		internal static ConfigEntry<float> EquipmentPanelX;

		internal static ConfigEntry<float> EquipmentPanelY;

		internal static ConfigEntry<bool> EquipmentPanelDraggable;

		internal static ConfigEntry<KeyboardShortcut> EquipmentPanelDragKey;

		internal static ConfigEntry<bool> ShowExtraUtilityVisuals;

		internal static ConfigEntry<bool> EnableChatImprovements;

		internal static ConfigEntry<bool> StaticChat;

		internal static ConfigEntry<bool> ChatHideOnLargeMap;

		internal static ConfigEntry<float> ChatWindowX;

		internal static ConfigEntry<float> ChatWindowY;

		internal static ConfigEntry<float> ChatWindowWidth;

		internal static ConfigEntry<float> ChatWindowHeight;

		internal static ConfigEntry<float> ChatExpandedWidth;

		internal static ConfigEntry<float> ChatExpandedHeight;

		internal static ConfigEntry<bool> ChatIsExpanded;

		internal static ConfigEntry<float> ChatWindowOpacity;

		internal static ConfigEntry<int> ChatFontSize;

		internal static ConfigEntry<int> ChatMaxVisibleLines;

		internal static ConfigEntry<bool> ChatShowTimestamps;

		internal static ConfigEntry<string> ChatTimestampFormat;

		internal static ConfigEntry<bool> ChatDisableForcedCase;

		internal static ConfigEntry<bool> ChatUppercaseShout;

		internal static ConfigEntry<bool> ChatShowSayChannelBadge;

		internal static ConfigEntry<bool> EnableDeathLogging;

		internal static ConfigEntry<bool> AnnounceDeathsInChat;

		internal static ConfigEntry<bool> EnableConnectionLogging;

		internal static ConfigEntry<bool> AnnouncePlayerJoinLeaveInChat;

		internal static ConfigEntry<KeyboardShortcut> WhoIsOnlineHotkey;

		internal static ConfigEntry<bool> ShowOnlineCountInHeader;

		internal static ConfigEntry<bool> ForcePlayerPositionOnMap;

		internal static ConfigEntry<bool> ShowBoatsOnMap;

		internal static ConfigEntry<bool> ShowCartsOnMap;

		internal static ConfigEntry<bool> EnableEventReporting;

		internal static ConfigEntry<string> EventReportToken;

		internal static ConfigEntry<string> EventServerName;

		internal static ConfigEntry<bool> ModifyItemDespawnDuration;

		internal static ConfigEntry<float> ItemDespawnDuration;

		internal static bool IsActive
		{
			get
			{
				if (Enabled != null)
				{
					return Enabled.Value;
				}
				return false;
			}
		}

		internal static void Bind(ConfigFile config)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Expected O, but got Unknown
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Expected O, but got Unknown
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Expected O, but got Unknown
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Expected O, but got Unknown
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Expected O, but got Unknown
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Expected O, but got Unknown
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Expected O, but got Unknown
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Expected O, but got Unknown
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Expected O, but got Unknown
			//IL_038c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0396: Expected O, but got Unknown
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ce: Expected O, but got Unknown
			//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0406: Expected O, but got Unknown
			//IL_0434: Unknown result type (might be due to invalid IL or missing references)
			//IL_043e: Expected O, but got Unknown
			//IL_046c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0476: Expected O, but got Unknown
			//IL_04a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ae: Expected O, but got Unknown
			//IL_0509: Unknown result type (might be due to invalid IL or missing references)
			//IL_0513: Expected O, but got Unknown
			//IL_0553: Unknown result type (might be due to invalid IL or missing references)
			//IL_055d: Expected O, but got Unknown
			//IL_05b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c2: Expected O, but got Unknown
			//IL_05e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f2: Expected O, but got Unknown
			//IL_061c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0626: Expected O, but got Unknown
			//IL_064d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0657: Expected O, but got Unknown
			//IL_067d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0687: Expected O, but got Unknown
			//IL_06b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06bb: Expected O, but got Unknown
			//IL_0704: Unknown result type (might be due to invalid IL or missing references)
			//IL_070e: Expected O, but got Unknown
			//IL_073c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0746: Expected O, but got Unknown
			//IL_0760: Unknown result type (might be due to invalid IL or missing references)
			//IL_0789: Unknown result type (might be due to invalid IL or missing references)
			//IL_07cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0869: Unknown result type (might be due to invalid IL or missing references)
			//IL_0873: Expected O, but got Unknown
			//IL_090d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0917: Expected O, but got Unknown
			//IL_0945: Unknown result type (might be due to invalid IL or missing references)
			//IL_094f: Expected O, but got Unknown
			//IL_0972: Unknown result type (might be due to invalid IL or missing references)
			//IL_097c: Expected O, but got Unknown
			//IL_099f: Unknown result type (might be due to invalid IL or missing references)
			//IL_09a9: Expected O, but got Unknown
			//IL_09cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_09d5: Expected O, but got Unknown
			//IL_09f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a03: Expected O, but got Unknown
			//IL_0a26: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a30: Expected O, but got Unknown
			//IL_0a54: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a5e: Expected O, but got Unknown
			//IL_0a81: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a8b: Expected O, but got Unknown
			//IL_0af3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0afd: Expected O, but got Unknown
			//IL_0b2b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b35: Expected O, but got Unknown
			//IL_0b63: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b6d: Expected O, but got Unknown
			//IL_0b9b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ba5: Expected O, but got Unknown
			//IL_0bd3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bdd: Expected O, but got Unknown
			//IL_0c26: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c30: Expected O, but got Unknown
			//IL_0c5e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c68: Expected O, but got Unknown
			//IL_0c96: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ca0: Expected O, but got Unknown
			//IL_0cce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cd8: Expected O, but got Unknown
			//IL_0d06: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d10: Expected O, but got Unknown
			//IL_0d3e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d48: Expected O, but got Unknown
			//IL_0d76: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d80: Expected O, but got Unknown
			//IL_0e22: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e2c: Expected O, but got Unknown
			//IL_0e9f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ea9: Expected O, but got Unknown
			//IL_0fc5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fcf: Expected O, but got Unknown
			//IL_1018: Unknown result type (might be due to invalid IL or missing references)
			//IL_1022: Expected O, but got Unknown
			//IL_1050: Unknown result type (might be due to invalid IL or missing references)
			//IL_105a: Expected O, but got Unknown
			//IL_1088: Unknown result type (might be due to invalid IL or missing references)
			//IL_1092: Expected O, but got Unknown
			//IL_10c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_10ca: Expected O, but got Unknown
			//IL_114d: Unknown result type (might be due to invalid IL or missing references)
			//IL_1157: Expected O, but got Unknown
			//IL_1185: Unknown result type (might be due to invalid IL or missing references)
			//IL_118f: Expected O, but got Unknown
			//IL_11bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_11c7: Expected O, but got Unknown
			//IL_122d: Unknown result type (might be due to invalid IL or missing references)
			//IL_1237: Expected O, but got Unknown
			//IL_12c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_12d0: Expected O, but got Unknown
			//IL_1327: Unknown result type (might be due to invalid IL or missing references)
			//IL_1331: Expected O, but got Unknown
			//IL_135f: Unknown result type (might be due to invalid IL or missing references)
			//IL_1369: Expected O, but got Unknown
			//IL_139e: Unknown result type (might be due to invalid IL or missing references)
			//IL_1485: Unknown result type (might be due to invalid IL or missing references)
			//IL_148f: Expected O, but got Unknown
			//IL_14bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_14c7: Expected O, but got Unknown
			//IL_14f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_14ff: Expected O, but got Unknown
			//IL_152d: Unknown result type (might be due to invalid IL or missing references)
			//IL_1537: Expected O, but got Unknown
			//IL_1580: Unknown result type (might be due to invalid IL or missing references)
			//IL_158a: Expected O, but got Unknown
			//IL_15af: Unknown result type (might be due to invalid IL or missing references)
			//IL_15b9: Expected O, but got Unknown
			//IL_15e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_15eb: Expected O, but got Unknown
			//IL_16fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_1819: Unknown result type (might be due to invalid IL or missing references)
			//IL_1823: Expected O, but got Unknown
			Enabled = config.Bind<bool>("General", "Enabled", true, "Master switch for DFG QoL.");
			ShowMainMenuLogo = config.Bind<bool>("MainMenu", "ShowLogo", true, "Show the DFG QoL logo on the Valheim main menu.");
			MainMenuLogoSize = config.Bind<int>("MainMenu", "LogoSize", 256, new ConfigDescription("Logo width and height in pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(64, 512), Array.Empty<object>()));
			MainMenuLogoRightMargin = config.Bind<int>("MainMenu", "LogoRightMargin", 32, new ConfigDescription("Distance in pixels from the right edge.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000), Array.Empty<object>()));
			MainMenuLogoTopMargin = config.Bind<int>("MainMenu", "LogoTopMargin", 24, new ConfigDescription("Distance in pixels from the top edge.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000), Array.Empty<object>()));
			MainMenuLogoOpacity = config.Bind<int>("MainMenu", "LogoOpacity", 255, new ConfigDescription("Logo opacity from 0 to 255.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 255), Array.Empty<object>()));
			DisableScreenShake = config.Bind<bool>("Player", "DisableScreenShake", false, "Disable all local camera shake effects.");
			EnableSmoothMovement = config.Bind<bool>("Player", "EnableSmoothMovement", true, "Enable physics interpolation on the local player character, eliminating camera stutter/judder when running or sprinting.");
			BaseCarryWeight = config.Bind<float>("Player", "BaseCarryWeight", 300f, new ConfigDescription("Base maximum carrying weight before Megingjord or status effect bonuses.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(100f, 2500f), Array.Empty<object>()));
			InfiniteFireFuel = config.Bind<bool>("Fire", "InfiniteFireFuel", false, "Keep campfires, hearths, and other fires a player placed lit without consuming fuel. World and dungeon fires are left alone.");
			InfiniteLightFuel = config.Bind<bool>("Fire", "InfiniteLightFuel", false, "Keep torches, sconces, and braziers a player placed lit without consuming fuel. Dungeon lights are left alone.");
			ItemWeightPercent = config.Bind<float>("Items.General", "WeightPercent", 0f, new ConfigDescription("Percentage modifier applied to every item's base weight.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-100f, 500f), Array.Empty<object>()));
			ItemStackSizePercent = config.Bind<float>("Items.General", "StackSizePercent", 0f, new ConfigDescription("Percentage modifier applied to stackable item maximums.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-90f, 500f), Array.Empty<object>()));
			NoTeleportPrevention = config.Bind<bool>("Items.General", "NoTeleportPrevention", false, "Allow normally restricted items to be teleported.");
			ItemsFloatInWater = config.Bind<bool>("Items.General", "FloatInWater", false, "Allow dropped items to float in water.");
			ToolDurabilityPercent = config.Bind<float>("Items.Durability", "ToolPercent", 0f, new ConfigDescription("Tool durability percentage modifier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-100f, 500f), Array.Empty<object>()));
			WeaponDurabilityPercent = config.Bind<float>("Items.Durability", "WeaponPercent", 0f, new ConfigDescription("Weapon durability percentage modifier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-100f, 500f), Array.Empty<object>()));
			BowDurabilityPercent = config.Bind<float>("Items.Durability", "BowPercent", 0f, new ConfigDescription("Bow and crossbow durability percentage modifier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-100f, 500f), Array.Empty<object>()));
			ShieldDurabilityPercent = config.Bind<float>("Items.Durability", "ShieldPercent", 0f, new ConfigDescription("Shield durability percentage modifier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-100f, 500f), Array.Empty<object>()));
			ArmorDurabilityPercent = config.Bind<float>("Items.Durability", "ArmorPercent", 0f, new ConfigDescription("Armor durability percentage modifier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-100f, 500f), Array.Empty<object>()));
			TorchDurabilityPercent = config.Bind<float>("Items.Durability", "TorchPercent", 0f, new ConfigDescription("Torch durability percentage modifier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-100f, 500f), Array.Empty<object>()));
			HelmetArmorPercent = config.Bind<float>("Items.Armor", "HelmetPercent", 0f, new ConfigDescription("Helmet armor percentage modifier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-100f, 500f), Array.Empty<object>()));
			ChestArmorPercent = config.Bind<float>("Items.Armor", "ChestPercent", 0f, new ConfigDescription("Chest armor percentage modifier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-100f, 500f), Array.Empty<object>()));
			LegArmorPercent = config.Bind<float>("Items.Armor", "LegPercent", 0f, new ConfigDescription("Leg armor percentage modifier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-100f, 500f), Array.Empty<object>()));
			CapeArmorPercent = config.Bind<float>("Items.Armor", "CapePercent", 0f, new ConfigDescription("Cape armor percentage modifier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-100f, 500f), Array.Empty<object>()));
			ShieldBlockPercent = config.Bind<float>("Items.Shields", "BlockPercent", 0f, new ConfigDescription("Shield block rating percentage modifier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-100f, 500f), Array.Empty<object>()));
			DisableDamageFlash = config.Bind<bool>("Hud", "DisableDamageFlash", false, "Hide the red screen flash when the local player takes damage.");
			ShowNumericalStamina = config.Bind<bool>("Hud", "ShowNumericalStamina", false, "Show the local player's numerical stamina below the vanilla stamina bar.");
			NumericalStaminaTextSize = config.Bind<int>("Hud", "NumericalStaminaTextSize", 16, new ConfigDescription("Numerical stamina text size.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 36), Array.Empty<object>()));
			ShowBowAmmoCount = config.Bind<bool>("Hud", "ShowBowAmmoCount", false, "Show the selected ammunition count while a bow is equipped.");
			BowAmmoTextSize = config.Bind<int>("Hud", "BowAmmoTextSize", 16, new ConfigDescription("Bow ammunition text size.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 36), Array.Empty<object>()));
			ShowGameClock = config.Bind<bool>("Hud", "ShowGameClock", false, "Show the current in-game day and time at the top center.");
			ClockUse24Hour = config.Bind<bool>("Hud", "ClockUse24Hour", true, "Use a 24-hour clock instead of AM/PM.");
			ClockFontSize = config.Bind<int>("Hud", "ClockFontSize", 26, new ConfigDescription("Clock text size.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 64), Array.Empty<object>()));
			ClockTopOffset = config.Bind<int>("Hud", "ClockTopOffset", 8, new ConfigDescription("Distance in pixels from the top of the screen.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 400), Array.Empty<object>()));
			ClockRed = config.Bind<int>("Hud", "ClockRed", 248, new ConfigDescription("Clock red channel from 0 to 255.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 255), Array.Empty<object>()));
			ClockGreen = config.Bind<int>("Hud", "ClockGreen", 105, new ConfigDescription("Clock green channel from 0 to 255.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 255), Array.Empty<object>()));
			ClockBlue = config.Bind<int>("Hud", "ClockBlue", 0, new ConfigDescription("Clock blue channel from 0 to 255.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 255), Array.Empty<object>()));
			ClockOpacity = config.Bind<int>("Hud", "ClockOpacity", 255, new ConfigDescription("Clock opacity from 0 to 255.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 255), Array.Empty<object>()));
			EnableFieldOfView = config.Bind<bool>("Camera", "EnableFieldOfView", false, "Override the local player camera field of view.");
			FieldOfView = config.Bind<float>("Camera", "FieldOfView", 65f, new ConfigDescription("Local player field of view in degrees.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 110f), Array.Empty<object>()));
			FieldOfViewStep = config.Bind<float>("Camera", "FieldOfViewStep", 5f, new ConfigDescription("Degrees changed by each FOV hotkey press.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f), Array.Empty<object>()));
			IncreaseFieldOfViewKey = config.Bind<KeyboardShortcut>("Camera", "IncreaseFieldOfViewKey", new KeyboardShortcut((KeyCode)280, Array.Empty<KeyCode>()), "Increase FOV while in first person.");
			DecreaseFieldOfViewKey = config.Bind<KeyboardShortcut>("Camera", "DecreaseFieldOfViewKey", new KeyboardShortcut((KeyCode)281, Array.Empty<KeyCode>()), "Decrease FOV while in first person.");
			EnableRollHotkeys = config.Bind<bool>("Controls", "EnableRollHotkeys", false, "Enable configurable forward and backward dodge hotkeys.");
			ForwardRollKey = config.Bind<KeyboardShortcut>("Controls", "ForwardRollKey", new KeyboardShortcut((KeyCode)290, Array.Empty<KeyCode>()), "Dodge forward relative to the player camera.");
			BackwardRollKey = config.Bind<KeyboardShortcut>("Controls", "BackwardRollKey", new KeyboardShortcut((KeyCode)291, Array.Empty<KeyCode>()), "Dodge backward relative to the player camera.");
			DisableFog = config.Bind<bool>("Environment", "DisableFog", false, "Disable local distance fog.");
			EnableNightBrightness = config.Bind<bool>("Environment", "EnableNightBrightness", false, "Increase local ambient and directional light at night.");
			NightBrightnessMultiplier = config.Bind<float>("Environment", "NightBrightnessMultiplier", 1.5f, new ConfigDescription("Night light multiplier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f), Array.Empty<object>()));
			EnableProductionCache = config.Bind<bool>("Production.Cache", "Enabled", false, "Register the buildable Production Cache and automate nearby kilns, smelters, and blast furnaces. Requires a restart when changed.");
			ProductionCacheAutoFuel = config.Bind<bool>("Production.Cache", "AutoFuel", true, "Move one accepted fuel item from a nearby Production Cache into an empty or partly filled production machine each cycle.");
			ProductionCacheAutoOre = config.Bind<bool>("Production.Cache", "AutoOre", true, "Move one accepted ore or wood item from a nearby Production Cache into a production machine each cycle.");
			ProductionCacheAutoOutput = config.Bind<bool>("Production.Cache", "AutoOutput", true, "Redirect finished products into a nearby Production Cache when the full output stack fits.");
			ProductionCacheRadius = config.Bind<float>("Production.Cache", "Radius", 10f, new ConfigDescription("Maximum distance in meters between a Production Cache and a production machine.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 30f), Array.Empty<object>()));
			ProductionCacheInterval = config.Bind<float>("Production.Cache", "TransferInterval", 5f, new ConfigDescription("Seconds between production input scans.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 60f), Array.Empty<object>()));
			ProductionCacheMaxTransfersPerCycle = config.Bind<int>("Production.Cache", "MaxTransfersPerMachinePerCycle", 1, new ConfigDescription("Maximum fuel items and ore items moved into each machine during one scan.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>()));
			ProductionCacheWidth = config.Bind<int>("Production.Cache", "Width", 8, new ConfigDescription("Container width in slots. Requires a restart when changed.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(4, 12), Array.Empty<object>()));
			ProductionCacheHeight = config.Bind<int>("Production.Cache", "Height", 4, new ConfigDescription("Container height in slots. Requires a restart when changed.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(3, 8), Array.Empty<object>()));
			ProductionCacheWoodCost = config.Bind<int>("Production.Cache", "WoodCost", 10, new ConfigDescription("Wood build cost. Requires a restart when changed.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ProductionCacheFineWoodCost = config.Bind<int>("Production.Cache", "FineWoodCost", 0, new ConfigDescription("Fine wood build cost. Requires a restart when changed.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ProductionCacheStoneCost = config.Bind<int>("Production.Cache", "StoneCost", 10, new ConfigDescription("Stone build cost. Requires a restart when changed.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ProductionCacheIronCost = config.Bind<int>("Production.Cache", "IronCost", 0, new ConfigDescription("Iron build cost. Requires a restart when changed.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ProductionCacheDebugLogging = config.Bind<bool>("Production.Cache", "DebugLogging", false, "Log production cache registration and individual transfers.");
			ProductionCacheModelFile = config.Bind<string>("Production.Cache", "ModelFile", "fuel_ore_chest.obj", "Filename or relative path to the custom 3D model for the Production Cache. Set to 'none' to keep vanilla chest visuals.");
			ProductionCacheModelScale = config.Bind<float>("Production.Cache", "ModelScale", 1f, new ConfigDescription("Scale multiplier for the custom Production Cache model.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
			ProductionCacheModelRotationY = config.Bind<float>("Production.Cache", "ModelRotationY", 0f, new ConfigDescription("Y-axis rotation offset in degrees for the custom model.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-180f, 180f), Array.Empty<object>()));
			ProductionCacheModelOffsetX = config.Bind<float>("Production.Cache", "ModelOffsetX", 0f, new ConfigDescription("X-axis position offset for the custom model.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-5f, 5f), Array.Empty<object>()));
			ProductionCacheModelOffsetY = config.Bind<float>("Production.Cache", "ModelOffsetY", 0f, new ConfigDescription("Y-axis position offset for the custom model.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-5f, 5f), Array.Empty<object>()));
			ProductionCacheModelOffsetZ = config.Bind<float>("Production.Cache", "ModelOffsetZ", 0f, new ConfigDescription("Z-axis position offset for the custom model.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-5f, 5f), Array.Empty<object>()));
			EnableProductionCacheVaultTransfer = config.Bind<bool>("Production.Cache", "VaultTransferEnabled", true, "Show Vault transfer buttons when viewing the Production Cache if a Viking Vault is within range.");
			ProductionCacheVaultTransferRadius = config.Bind<float>("Production.Cache", "VaultTransferRadius", 30f, new ConfigDescription("Maximum distance in meters between a Production Cache and a Viking Vault for ore transfer.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 100f), Array.Empty<object>()));
			ProductionCacheVaultMetalsButtonOffsetX = config.Bind<float>("Production.Cache", "VaultMetalsButtonOffsetX", 0f, new ConfigDescription("X-axis pixel offset for the 'Send Metals' button (default is beneath Take All).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-400f, 400f), Array.Empty<object>()));
			ProductionCacheVaultMetalsButtonOffsetY = config.Bind<float>("Production.Cache", "VaultMetalsButtonOffsetY", 0f, new ConfigDescription("Y-axis pixel offset for the 'Send Metals' button (default is beneath Take All).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-200f, 200f), Array.Empty<object>()));
			ProductionCacheVaultAllButtonOffsetX = config.Bind<float>("Production.Cache", "VaultAllButtonOffsetX", 0f, new ConfigDescription("X-axis pixel offset for the 'Send All' button (default is beneath Stack All).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-400f, 400f), Array.Empty<object>()));
			ProductionCacheVaultAllButtonOffsetY = config.Bind<float>("Production.Cache", "VaultAllButtonOffsetY", 0f, new ConfigDescription("Y-axis pixel offset for the 'Send All' button (default is beneath Stack All).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-200f, 200f), Array.Empty<object>()));
			ProductionCacheVaultButtonWidth = config.Bind<float>("Production.Cache", "VaultButtonWidth", 0f, new ConfigDescription("Custom width in pixels for the Vault buttons (0 uses vanilla button width).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>()));
			ProductionCacheVaultButtonHeight = config.Bind<float>("Production.Cache", "VaultButtonHeight", 0f, new ConfigDescription("Custom height in pixels for the Vault buttons (0 uses vanilla button height).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			ProductionCacheCustomTransferItems = config.Bind<string>("Production.Cache", "CustomTransferItems", "", "Comma-separated list of additional item prefab names to transfer to the vault (e.g. 'Bronze,Iron'). Leave blank for automatic detection of finished ores and metals.");
			EnableProductionCacheVaultWebGui = config.Bind<bool>("Production.Cache", "EnableWebGui", true, "Start a local web server for live-tuning Vault button positions.");
			ProductionCacheVaultWebPort = config.Bind<int>("Production.Cache", "WebPort", 8784, "Port for the Vault buttons live-tuning web GUI.");
			EnableCraftFromContainers = config.Bind<bool>("Crafting", "EnableCraftFromContainers", true, "Allow crafting recipes and placing building pieces using items from a nearby Viking Vault. Ordinary chests, carts, and ships are not used.");
			CraftFromContainersRadius = config.Bind<float>("Crafting", "CraftFromContainersRadius", 15f, new ConfigDescription("Maximum distance in meters to reach a Viking Vault when crafting or building.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 50f), Array.Empty<object>()));
			CraftFromContainersIncludeCarts = config.Bind<bool>("Crafting", "CraftFromContainersIncludeCarts", true, "Unused: vaults are building pieces, so carts are never a source.");
			CraftFromContainersIncludeShips = config.Bind<bool>("Crafting", "CraftFromContainersIncludeShips", true, "Unused: vaults are building pieces, so ships are never a source.");
			ShowAvailableAmount = config.Bind<bool>("Crafting", "ShowAvailableAmount", true, "Display total available items alongside required amount when crafting and building (e.g. '45/10') and recipe ownership/craftable counts.");
			PlayerInventoryRows = config.Bind<int>("Inventory", "PlayerInventoryRows", 5, new ConfigDescription("Number of inventory rows for the player backpack (default is 5 = 40 slots, vanilla is 4 = 32 slots).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(4, 8), Array.Empty<object>()));
			PlayerInventoryRows.SettingChanged += delegate
			{
				EquipmentSlots.OnPlayerInventoryRowsSettingChanged();
			};
			EnableInventorySort = config.Bind<bool>("Inventory", "EnableSortButton", true, "Show a 'Sort' button in the player inventory that stacks and tidies carried items.");
			InventorySortStackFirst = config.Bind<bool>("Inventory", "StackBeforeSort", true, "Merge matching partial stacks before sorting. Only merges items with the same name, quality and world level, and never splits quest items.");
			InventorySortKeepHotbar = config.Bind<bool>("Inventory", "KeepHotbarPinned", true, "Leave the top inventory row (number keys 1-8) untouched and only sort the rows below it. Disable to tidy the hotbar too, which changes what your number keys select.");
			EnableFavorites = config.Bind<bool>("Inventory", "EnableFavorites", true, "Allow favoriting inventory slots and item types so bulk actions leave them alone.");
			FavoriteSlots = config.Bind<string>("Inventory", "FavoriteSlots", "", "Comma-separated 'x:y' favorite slot coordinates, toggled in game with the Fav Slot button.");
			FavoriteItems = config.Bind<string>("Inventory", "FavoriteItems", "", "Comma-separated item names favorited to prevent sorting or dumping, toggled with Fav Item button.");
			EnableVaultDepositButton = config.Bind<bool>("Inventory", "EnableVaultDepositButton", true, "Show a 'To Vault' button in the player inventory to send carried items to a nearby Viking Vault.");
			VaultDepositRadius = config.Bind<float>("Inventory", "VaultDepositRadius", 30f, new ConfigDescription("Maximum distance in meters to a Viking Vault for the 'To Vault' button.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 100f), Array.Empty<object>()));
			VaultDepositOnlyInRange = config.Bind<bool>("Inventory", "VaultDepositOnlyInRange", false, "Only show the 'To Vault' button when a Viking Vault is within range. If false, the button is always visible and notifies if clicked while out of range.");
			InventoryButtonOffsetX = config.Bind<float>("Inventory", "ButtonOffsetX", 0f, new ConfigDescription("Horizontal pixel offset for the Fav Item / Fav Slot / Sort button row.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-600f, 600f), Array.Empty<object>()));
			InventoryButtonOffsetY = config.Bind<float>("Inventory", "ButtonOffsetY", 0f, new ConfigDescription("Vertical pixel offset for the inventory button row.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-400f, 400f), Array.Empty<object>()));
			InventoryButtonWidth = config.Bind<float>("Inventory", "ButtonWidth", 0f, new ConfigDescription("Button width in pixels (0 matches the vanilla button width).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 400f), Array.Empty<object>()));
			InventoryButtonHeight = config.Bind<float>("Inventory", "ButtonHeight", 0f, new ConfigDescription("Button height in pixels (0 matches the vanilla button height).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 150f), Array.Empty<object>()));
			EnableInventoryButtonWebGui = config.Bind<bool>("Inventory", "EnableWebGui", true, "Start a local web server for live-tuning the inventory button layout.");
			InventoryButtonWebPort = config.Bind<int>("Inventory", "WebPort", 8785, "Port for the inventory button live-tuning web GUI.");
			EnableContainerSpacing = config.Bind<bool>("Inventory", "EnableContainerSpacing", true, "Automatically space the chest/container window below the player inventory and sort buttons to prevent overlapping.");
			ContainerSpacing = config.Bind<float>("Inventory", "ContainerSpacing", 14f, new ConfigDescription("Vertical spacing in pixels between the player inventory/buttons and the chest container window.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			ContainerOffsetY = config.Bind<float>("Inventory", "ContainerOffsetY", 0f, new ConfigDescription("Additional vertical pixel offset for the chest container window.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-300f, 300f), Array.Empty<object>()));
			ContainerOffsetX = config.Bind<float>("Inventory", "ContainerOffsetX", 0f, new ConfigDescription("Additional horizontal pixel offset for the chest container window.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-400f, 400f), Array.Empty<object>()));
			EnableEquipmentPanel = config.Bind<bool>("Equipment", "EnableEquipmentPanel", true, "Show the paperdoll equipment panel to the right of your inventory.");
			EnableEquipmentPanel.SettingChanged += delegate
			{
				EquipmentSlots.UpdateSlotsGridPosition();
			};
			UtilitySlotCount = config.Bind<int>("Equipment", "UtilitySlotCount", 3, new ConfigDescription("Number of utility items (Megingjord, Wishbone, Demister, etc.) that can be equipped simultaneously.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 3), Array.Empty<object>()));
			UtilitySlotCount.SettingChanged += delegate
			{
				MultiUtility.OnUtilitySlotCountChanged();
			};
			EnableQuickSlots = config.Bind<bool>("Equipment", "EnableQuickSlots", false, "Enable quick slots (keys Z, V, B by default) below the equipment panel.");
			EnableQuickSlots.SettingChanged += delegate
			{
				EquipmentSlots.UpdateSlotsGridPosition();
			};
			QuickSlotCount = config.Bind<int>("Equipment", "QuickSlotCount", 3, new ConfigDescription("Number of quick slots available.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 6), Array.Empty<object>()));
			QuickSlotCount.SettingChanged += delegate
			{
				EquipmentSlots.UpdateSlotsGridPosition();
			};
			EquipmentPanelX = config.Bind<float>("Equipment", "EquipmentPanelX", 615f, new ConfigDescription("Horizontal pixel position of the equipment panel relative to the inventory.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1000f, 2500f), Array.Empty<object>()));
			EquipmentPanelY = config.Bind<float>("Equipment", "EquipmentPanelY", 28f, new ConfigDescription("Vertical pixel position of the equipment panel relative to the inventory.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1000f, 1000f), Array.Empty<object>()));
			EquipmentPanelDraggable = config.Bind<bool>("Equipment", "EquipmentPanelDraggable", false, "Allow dragging the equipment panel by its background at any time without holding the drag key.");
			EquipmentPanelDragKey = config.Bind<KeyboardShortcut>("Equipment", "EquipmentPanelDragKey", new KeyboardShortcut((KeyCode)308, Array.Empty<KeyCode>()), "Hold this key while dragging the equipment panel background to move it.");
			ShowExtraUtilityVisuals = config.Bind<bool>("Equipment", "ShowExtraUtilityVisuals", true, "Render extra utility items on the player model and replicate across multiplayer.");
			EnableChatImprovements = config.Bind<bool>("Chat", "EnableChatImprovements", true, "Enable modernized Norse Obsidian & Antique Gold chat window and enhancements.");
			StaticChat = config.Bind<bool>("Chat", "StaticChat", true, "Keep the chat window permanently visible instead of fading out after a few seconds.");
			ChatHideOnLargeMap = config.Bind<bool>("Chat", "HideOnLargeMap", false, "Hide the static chat window while the full-screen world map is open.");
			ChatWindowX = config.Bind<float>("Chat", "WindowPositionX", -1f, "Chat window horizontal position in screen pixels (-1 for default docked bottom-right position).");
			ChatWindowY = config.Bind<float>("Chat", "WindowPositionY", -1f, "Chat window vertical position in screen pixels (-1 for default docked bottom-right position).");
			ChatWindowWidth = config.Bind<float>("Chat", "WindowWidth", 480f, new ConfigDescription("Compact width of the chat window in pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(300f, 1000f), Array.Empty<object>()));
			ChatWindowHeight = config.Bind<float>("Chat", "WindowHeight", 240f, new ConfigDescription("Compact height of the chat window in pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(140f, 600f), Array.Empty<object>()));
			ChatExpandedWidth = config.Bind<float>("Chat", "ExpandedWidth", 680f, new ConfigDescription("Expanded width of the chat window in pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(400f, 1200f), Array.Empty<object>()));
			ChatExpandedHeight = config.Bind<float>("Chat", "ExpandedHeight", 500f, new ConfigDescription("Expanded height of the chat window in pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(300f, 900f), Array.Empty<object>()));
			ChatIsExpanded = config.Bind<bool>("Chat", "IsExpanded", false, "Whether the chat window starts in expanded mode.");
			ChatWindowOpacity = config.Bind<float>("Chat", "WindowOpacity", 0.9f, new ConfigDescription("Background opacity of the chat window card.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>()));
			ChatFontSize = config.Bind<int>("Chat", "FontSize", 15, new ConfigDescription("Font size of the chat messages.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 32), Array.Empty<object>()));
			ChatMaxVisibleLines = config.Bind<int>("Chat", "MaxVisibleLines", 40, new ConfigDescription("Maximum number of message lines visible in the buffer at once.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 150), Array.Empty<object>()));
			ChatShowTimestamps = config.Bind<bool>("Chat", "ShowTimestamps", true, "Display timestamps on incoming chat and system messages.");
			ChatTimestampFormat = config.Bind<string>("Chat", "TimestampFormat", "HH:mm", "Format for message timestamps (e.g. 'HH:mm', 'hh:mm tt').");
			ChatDisableForcedCase = config.Bind<bool>("Chat", "DisableForcedCase", true, "Prevent whispers from being forced to lowercase.");
			ChatUppercaseShout = config.Bind<bool>("Chat", "UppercaseShout", true, "Automatically uppercase shout messages.");
			ChatShowSayChannelBadge = config.Bind<bool>("Chat", "ShowSayChannelBadge", false, "Show '[SAY]' channel badge on normal local messages.");
			EnableDeathLogging = config.Bind<bool>("Chat", "EnableDeathLogging", true, "Log player deaths to console and broadcast cause of death.");
			AnnounceDeathsInChat = config.Bind<bool>("Chat", "AnnounceDeathsInChat", true, "Display player death announcements with detailed cause of death in chat.");
			EnableConnectionLogging = config.Bind<bool>("Chat", "EnableConnectionLogging", true, "Log player connections and disconnections to console.");
			AnnouncePlayerJoinLeaveInChat = config.Bind<bool>("Chat", "AnnouncePlayerJoinLeaveInChat", true, "Display player connection and disconnection announcements in chat.");
			WhoIsOnlineHotkey = config.Bind<KeyboardShortcut>("Chat", "WhoIsOnlineHotkey", new KeyboardShortcut((KeyCode)292, Array.Empty<KeyCode>()), "Hotkey to print the list of currently online players to chat.");
			ShowOnlineCountInHeader = config.Bind<bool>("Chat", "ShowOnlineCountInHeader", true, "Show the live count of online players next to the chat header title.");
			ForcePlayerPositionOnMap = config.Bind<bool>("Map", "ForcePlayerPositionOnMap", true, "Always display all connected players on the map regardless of their local sharing toggle.");
			ShowBoatsOnMap = config.Bind<bool>("Map", "ShowBoatsOnMap", true, "Display dynamic map pins for active boats and ships (Karve, Longship, etc.).");
			ShowCartsOnMap = config.Bind<bool>("Map", "ShowCartsOnMap", true, "Display dynamic map pins for active carts and wagons.");
			EnableEventReporting = config.Bind<bool>("Server", "EnableEventReporting", false, "Send chat, deaths, logins, and boss events to the public status page at https://dfgaming.net/status. Off unless you turn it on. Also requires EventReportToken.");
			EventReportToken = config.Bind<string>("Server", "EventReportToken", "", "Token from https://dfgaming.net/status after you log in. Reporting does nothing without it.");
			EventServerName = config.Bind<string>("Server", "EventServerName", "", "Name this world is filed under on https://dfgaming.net/status. Leave empty to use the Valheim world name, which every player on that world already shares. Set the same value on every client only when you want a different label.");
			ModifyItemDespawnDuration = config.Bind<bool>("Server", "ModifyItemDespawnDuration", false, "Enable custom despawn timer for items dropped in the wild outside player base range.");
			ItemDespawnDuration = config.Bind<float>("Server", "ItemDespawnDuration", 3600f, new ConfigDescription("Duration in seconds before wild dropped items despawn (default 3600 = 1 hour; protected by base/player radius).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(60f, 86400f), Array.Empty<object>()));
			Normalize();
		}

		private static void Normalize()
		{
			MainMenuLogoSize.Value = Mathf.Clamp(MainMenuLogoSize.Value, 64, 512);
			MainMenuLogoRightMargin.Value = Mathf.Clamp(MainMenuLogoRightMargin.Value, 0, 1000);
			MainMenuLogoTopMargin.Value = Mathf.Clamp(MainMenuLogoTopMargin.Value, 0, 1000);
			MainMenuLogoOpacity.Value = Mathf.Clamp(MainMenuLogoOpacity.Value, 0, 255);
			NumericalStaminaTextSize.Value = Mathf.Clamp(NumericalStaminaTextSize.Value, 10, 36);
			BowAmmoTextSize.Value = Mathf.Clamp(BowAmmoTextSize.Value, 10, 36);
			NightBrightnessMultiplier.Value = Mathf.Clamp(NightBrightnessMultiplier.Value, 1f, 3f);
			ProductionCacheRadius.Value = Mathf.Clamp(ProductionCacheRadius.Value, 3f, 30f);
			ProductionCacheInterval.Value = Mathf.Clamp(ProductionCacheInterval.Value, 1f, 60f);
			ProductionCacheMaxTransfersPerCycle.Value = Mathf.Clamp(ProductionCacheMaxTransfersPerCycle.Value, 1, 10);
			ProductionCacheWidth.Value = Mathf.Clamp(ProductionCacheWidth.Value, 4, 12);
			ProductionCacheHeight.Value = Mathf.Clamp(ProductionCacheHeight.Value, 3, 8);
			ProductionCacheWoodCost.Value = Mathf.Clamp(ProductionCacheWoodCost.Value, 0, 100);
			ProductionCacheFineWoodCost.Value = Mathf.Clamp(ProductionCacheFineWoodCost.Value, 0, 100);
			ProductionCacheStoneCost.Value = Mathf.Clamp(ProductionCacheStoneCost.Value, 0, 100);
			ProductionCacheIronCost.Value = Mathf.Clamp(ProductionCacheIronCost.Value, 0, 100);
			ProductionCacheModelScale.Value = Mathf.Clamp(ProductionCacheModelScale.Value, 0.1f, 5f);
			ProductionCacheModelRotationY.Value = Mathf.Clamp(ProductionCacheModelRotationY.Value, -180f, 180f);
			ProductionCacheModelOffsetX.Value = Mathf.Clamp(ProductionCacheModelOffsetX.Value, -5f, 5f);
			ProductionCacheModelOffsetY.Value = Mathf.Clamp(ProductionCacheModelOffsetY.Value, -5f, 5f);
			ProductionCacheModelOffsetZ.Value = Mathf.Clamp(ProductionCacheModelOffsetZ.Value, -5f, 5f);
			ProductionCacheVaultTransferRadius.Value = Mathf.Clamp(ProductionCacheVaultTransferRadius.Value, 5f, 100f);
			ProductionCacheVaultMetalsButtonOffsetX.Value = Mathf.Clamp(ProductionCacheVaultMetalsButtonOffsetX.Value, -400f, 400f);
			ProductionCacheVaultMetalsButtonOffsetY.Value = Mathf.Clamp(ProductionCacheVaultMetalsButtonOffsetY.Value, -200f, 200f);
			ProductionCacheVaultAllButtonOffsetX.Value = Mathf.Clamp(ProductionCacheVaultAllButtonOffsetX.Value, -400f, 400f);
			ProductionCacheVaultAllButtonOffsetY.Value = Mathf.Clamp(ProductionCacheVaultAllButtonOffsetY.Value, -200f, 200f);
			ProductionCacheVaultButtonWidth.Value = Mathf.Clamp(ProductionCacheVaultButtonWidth.Value, 0f, 300f);
			ProductionCacheVaultButtonHeight.Value = Mathf.Clamp(ProductionCacheVaultButtonHeight.Value, 0f, 100f);
			ItemWeightPercent.Value = Mathf.Clamp(ItemWeightPercent.Value, -100f, 500f);
			ItemStackSizePercent.Value = Mathf.Clamp(ItemStackSizePercent.Value, -90f, 500f);
			ToolDurabilityPercent.Value = Mathf.Clamp(ToolDurabilityPercent.Value, -100f, 500f);
			WeaponDurabilityPercent.Value = Mathf.Clamp(WeaponDurabilityPercent.Value, -100f, 500f);
			BowDurabilityPercent.Value = Mathf.Clamp(BowDurabilityPercent.Value, -100f, 500f);
			ShieldDurabilityPercent.Value = Mathf.Clamp(ShieldDurabilityPercent.Value, -100f, 500f);
			ArmorDurabilityPercent.Value = Mathf.Clamp(ArmorDurabilityPercent.Value, -100f, 500f);
			TorchDurabilityPercent.Value = Mathf.Clamp(TorchDurabilityPercent.Value, -100f, 500f);
			HelmetArmorPercent.Value = Mathf.Clamp(HelmetArmorPercent.Value, -100f, 500f);
			ChestArmorPercent.Value = Mathf.Clamp(ChestArmorPercent.Value, -100f, 500f);
			LegArmorPercent.Value = Mathf.Clamp(LegArmorPercent.Value, -100f, 500f);
			CapeArmorPercent.Value = Mathf.Clamp(CapeArmorPercent.Value, -100f, 500f);
			ShieldBlockPercent.Value = Mathf.Clamp(ShieldBlockPercent.Value, -100f, 500f);
			ClockFontSize.Value = Mathf.Clamp(ClockFontSize.Value, 10, 64);
			ClockTopOffset.Value = Mathf.Clamp(ClockTopOffset.Value, 0, 400);
			ClockRed.Value = Mathf.Clamp(ClockRed.Value, 0, 255);
			ClockGreen.Value = Mathf.Clamp(ClockGreen.Value, 0, 255);
			ClockBlue.Value = Mathf.Clamp(ClockBlue.Value, 0, 255);
			ClockOpacity.Value = Mathf.Clamp(ClockOpacity.Value, 0, 255);
			FieldOfView.Value = Mathf.Clamp(FieldOfView.Value, 30f, 110f);
			FieldOfViewStep.Value = Mathf.Clamp(FieldOfViewStep.Value, 1f, 20f);
			CraftFromContainersRadius.Value = Mathf.Clamp(CraftFromContainersRadius.Value, 2f, 50f);
			ChatWindowWidth.Value = Mathf.Clamp(ChatWindowWidth.Value, 300f, 1000f);
			ChatWindowHeight.Value = Mathf.Clamp(ChatWindowHeight.Value, 140f, 600f);
			ChatExpandedWidth.Value = Mathf.Clamp(ChatExpandedWidth.Value, 400f, 1200f);
			ChatExpandedHeight.Value = Mathf.Clamp(ChatExpandedHeight.Value, 300f, 900f);
			ChatWindowOpacity.Value = Mathf.Clamp(ChatWindowOpacity.Value, 0.1f, 1f);
			ChatFontSize.Value = Mathf.Clamp(ChatFontSize.Value, 10, 32);
			ChatMaxVisibleLines.Value = Mathf.Clamp(ChatMaxVisibleLines.Value, 10, 150);
			ItemDespawnDuration.Value = Mathf.Clamp(ItemDespawnDuration.Value, 60f, 86400f);
			InventoryButtonOffsetX.Value = Mathf.Clamp(InventoryButtonOffsetX.Value, -600f, 600f);
			InventoryButtonOffsetY.Value = Mathf.Clamp(InventoryButtonOffsetY.Value, -400f, 400f);
			InventoryButtonWidth.Value = Mathf.Clamp(InventoryButtonWidth.Value, 0f, 400f);
			InventoryButtonHeight.Value = Mathf.Clamp(InventoryButtonHeight.Value, 0f, 150f);
			if (BaseCarryWeight != null)
			{
				BaseCarryWeight.Value = Mathf.Clamp(BaseCarryWeight.Value, 100f, 2500f);
			}
			if (PlayerInventoryRows != null)
			{
				PlayerInventoryRows.Value = Mathf.Clamp(PlayerInventoryRows.Value, 4, 8);
			}
			if (UtilitySlotCount != null)
			{
				UtilitySlotCount.Value = Mathf.Clamp(UtilitySlotCount.Value, 1, 3);
			}
			if (QuickSlotCount != null)
			{
				QuickSlotCount.Value = Mathf.Clamp(QuickSlotCount.Value, 1, 6);
			}
			if (EquipmentPanelX != null)
			{
				EquipmentPanelX.Value = Mathf.Clamp(EquipmentPanelX.Value, -1000f, 2500f);
			}
			if (EquipmentPanelY != null)
			{
				EquipmentPanelY.Value = Mathf.Clamp(EquipmentPanelY.Value, -1000f, 1000f);
			}
			if (VaultDepositRadius != null)
			{
				VaultDepositRadius.Value = Mathf.Clamp(VaultDepositRadius.Value, 5f, 100f);
			}
			if (ContainerSpacing != null)
			{
				ContainerSpacing.Value = Mathf.Clamp(ContainerSpacing.Value, 0f, 100f);
			}
			if (ContainerOffsetY != null)
			{
				ContainerOffsetY.Value = Mathf.Clamp(ContainerOffsetY.Value, -300f, 300f);
			}
			if (ContainerOffsetX != null)
			{
				ContainerOffsetX.Value = Mathf.Clamp(ContainerOffsetX.Value, -400f, 400f);
			}
		}
	}
	internal sealed class PatchLifecycle
	{
		private static readonly Type[] PatchTypes = new Type[73]
		{
			typeof(ScreenShakePatch),
			typeof(DamageFlashPatch),
			typeof(DamageFlashUpdatePatch),
			typeof(FieldOfViewPatch),
			typeof(FireplaceFuelPatch),
			typeof(FireplaceFuelUpdatePatch),
			typeof(ItemDropAwakePatch),
			typeof(ItemDurabilityPatch),
			typeof(ItemArmorPatch),
			typeof(ItemShieldPatch),
			typeof(SmelterSpawnPatch),
			typeof(ContainerAwakePatch),
			typeof(ContainerOnDestroyedPatch),
			typeof(PlayerHaveRequirementItemsPatch),
			typeof(PlayerHaveRequirementsPiecePatch),
			typeof(PlayerConsumeResourcesPatch),
			typeof(PlayerGetFirstRequiredItemPatch),
			typeof(InventoryGuiSetupRequirementPatch),
			typeof(InventoryGuiDoCraftingPatch),
			typeof(InventoryGuiUpdateRecipePatch),
			typeof(InventoryGuiAwakePatch),
			typeof(InventoryGuiUpdateContainerPatch),
			typeof(InventoryGuiCloseContainerPatch),
			typeof(InventoryGuiHidePatch),
			typeof(InventorySortGuiAwakePatch),
			typeof(InventorySortGuiShowPatch),
			typeof(InventorySortGuiHidePatch),
			typeof(InventoryFavoritesLeftDownPatch),
			typeof(InventoryGridUpdateGuiPatch),
			typeof(ChatPatches),
			typeof(DeathLoggingFeature),
			typeof(ConnectionLoggingFeature),
			typeof(MapFeature),
			typeof(ServerFeature),
			typeof(MultiUtility.HumanoidEquipItemPatch),
			typeof(MultiUtility.HumanoidUnequipItemPatch),
			typeof(MultiUtility.HumanoidIsItemEquipedPatch),
			typeof(MultiUtility.HumanoidUnequipAllItemsPatch),
			typeof(MultiUtility.PlayerUnequipDeathDropItemsPatch),
			typeof(MultiUtility.HumanoidGetEquipmentWeightPatch),
			typeof(MultiUtility.HumanoidUpdateEquipmentPatch),
			typeof(MultiUtility.HumanoidGetSetCountPatch),
			typeof(MultiUtility.HumanoidUpdateEquipmentStatusEffectsPatch),
			typeof(MultiUtility.SEManRemoveStatusEffectPatch),
			typeof(MultiUtility.PlayerGetEquipmentEitrRegenModifierPatch),
			typeof(MultiUtility.PlayerUpdateModifiersPatch),
			typeof(MultiUtility.PlayerOnInventoryChangedPatch),
			typeof(MultiUtility.PlayerOnDestroyPatch),
			typeof(MultiUtilityVisuals.HumanoidSetupVisEquipmentPatch),
			typeof(MultiUtilityVisuals.VisEquipmentUpdateEquipmentVisualsPatch),
			typeof(SlotValidation.SlotsValidation.HumanoidSetupEquipmentMarkSlotsDirtyPatch),
			typeof(SlotValidation.SlotsValidation.PlayerOnInventoryChangedMarkSlotsDirtyPatch),
			typeof(SlotValidation.ItemsValidation.InventoryMoveAllMarkItemsDirtyPatch),
			typeof(SlotValidation.ItemsValidation.TombStoneEasyFitInInventoryMarkItemsDirtyPatch),
			typeof(SlotValidation.ItemsValidation.HumanoidEquipItemMarkDirtyPatch),
			typeof(SlotValidation.ItemsValidation.HumanoidUnequipItemMarkDirtyPatch),
			typeof(SlotValidation.InventoryGuiShowValidatePatch),
			typeof(EquipmentInventoryPatches.PlayerAwakeSetInventoryHeightPatch),
			typeof(EquipmentInventoryPatches.PlayerOnSpawnedUpdateInventoryPatch),
			typeof(EquipmentInventoryPatches.PlayerSetInventorySizePatch),
			typeof(EquipmentInventoryPatches.HumanoidDropInvalidItemsPatch),
			typeof(EquipmentInventoryPatches.PlayerLoadLayOutSlotsPatch),
			typeof(EquipmentInventoryPatches.InventorySlotsUsedPercentagePatch),
			typeof(EquipmentInventoryPatches.InventoryGetEmptySlotsPatch),
			typeof(EquipmentInventoryPatches.InventoryHaveEmptySlotPatch),
			typeof(EquipmentInventoryPatches.InventoryFindEmptySlotPatch),
			typeof(EquipmentInventoryPatches.InventoryGuiDoCraftingUpgradePatch),
			typeof(EquipmentInventoryPatches.InventoryGuiOnSelectedItemDragPatch),
			typeof(EquipmentInventoryPatches.EquipmentGridUpdateGuiPatch),
			typeof(EquipmentInventoryPatches.EquipmentGuiUpdatePatch),
			typeof(EquipmentInventoryPatches.PlayerGetMaxCarryWeightPatch),
			typeof(SmoothMovementPatch.PlayerAwakeInterpolationPatch),
			typeof(SmoothMovementPatch.PlayerOnSpawnedInterpolationPatch)
		};

		private readonly ManualLogSource m_log;

		private Harmony m_harmony;

		internal PatchLifecycle(ManualLogSource log)
		{
			m_log = log;
		}

		internal bool Apply()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			if (m_harmony != null)
			{
				return true;
			}
			Harmony val = new Harmony("com.dfg.qol");
			try
			{
				for (int i = 0; i < PatchTypes.Length; i++)
				{
					val.PatchAll(PatchTypes[i]);
				}
				m_harmony = val;
				m_log.LogInfo((object)"Harmony patches applied.");
				return true;
			}
			catch (Exception ex)
			{
				try
				{
					val.UnpatchSelf();
				}
				catch (Exception ex2)
				{
					m_log.LogError((object)("Harmony rollback failed: " + ex2));
				}
				m_harmony = null;
				m_log.LogError((object)("Harmony patch setup failed: " + ex));
				return false;
			}
		}

		internal void Shutdown()
		{
			if (m_harmony == null)
			{
				return;
			}
			try
			{
				m_harmony.UnpatchSelf();
				m_log.LogInfo((object)"Harmony patches removed.");
			}
			catch (Exception ex)
			{
				m_log.LogError((object)("Harmony cleanup failed: " + ex));
			}
			finally
			{
				m_harmony = null;
			}
		}
	}
	[BepInPlugin("com.dfg.qol", "DFG QoL", "0.3.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class DFGQoLPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.dfg.qol";

		public const string PluginName = "DFG QoL";

		public const string PluginVersion = "0.3.2";

		internal static ManualLogSource Log;

		internal static string PluginDirectory;

		private PatchLifecycle m_patches;

		internal static ConfigFile ConfigFileRef { get; private set; }

		internal static DFGQoLPlugin Instance { get; private set; }

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			ConfigFileRef = ((BaseUnityPlugin)this).Config;
			PluginDirectory = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			QoLSettings.Bind(((BaseUnityPlugin)this).Config);
			m_patches = new PatchLifecycle(Log);
			if (!m_patches.Apply())
			{
				((Behaviour)this).enabled = false;
				return;
			}
			EquipmentSlots.InitializeSlots();
			FireplaceFuelFeature.Initialize();
			EnvironmentFeature.Initialize();
			ItemSharedFeature.Initialize();
			ProductionCacheFeature.Initialize();
			ProductionCacheVaultWeb.Start(QoLSettings.ProductionCacheVaultWebPort.Value);
			InventoryButtonWeb.Start(QoLSettings.InventoryButtonWebPort.Value);
			CraftFromContainersFeature.Initialize();
			ChatFeature.Initialize();
			MapFeature.Initialize();
			ServerFeature.Initialize();
			try
			{
				RaidEventFeature.Initialize();
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Raid event hooks were skipped: " + ex.Message));
			}
			Log.LogInfo((object)("DFG QoL 0.3.2 loaded. Config: " + ((BaseUnityPlugin)this).Config.ConfigFilePath));
		}

		private void Update()
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			MainMenuLogo.Tick();
			GameClock.Update();
			EnvironmentFeature.Update();
			PlayerHud.Update();
			RollHotkeys.Update();
			ProductionCacheFeature.Update();
			ChatFeature.Update();
			MapFeature.Update();
			InventoryFavorites.Update();
			InventorySortFeature.Update();
			ConfigEntry<bool> enableQuickSlots = QoLSettings.EnableQuickSlots;
			if (enableQuickSlots == null || !enableQuickSlots.Value)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer != (Object)null) || !InventoryAccessor.TakeInput(localPlayer) || Hud.IsPieceSelectionVisible())
			{
				return;
			}
			for (int i = 0; i < EquipmentSlots.Slots.Length; i++)
			{
				EquipmentSlots.Slot slot = EquipmentSlots.Slots[i];
				if (slot != null && slot.IsHotkeySlot && slot.IsActive && slot.Item != null)
				{
					KeyboardShortcut shortcut = slot.GetShortcut();
					if (((KeyboardShortcut)(ref shortcut)).IsDown())
					{
						((Humanoid)localPlayer).UseItem((Inventory)null, slot.Item, false);
					}
				}
			}
		}

		private void LateUpdate()
		{
			SlotValidation.Validate();
		}

		private void OnGUI()
		{
			GameClock.Render();
			PlayerHud.Render();
			ProductionCacheVaultTransfer.RenderGui();
		}

		private void OnDestroy()
		{
			ProductionCacheVaultWeb.Stop();
			InventoryButtonWeb.Stop();
			InventorySortFeature.Shutdown();
			FireplaceFuelFeature.Shutdown();
			EnvironmentFeature.Shutdown();
			ItemSharedFeature.Shutdown();
			ProductionCacheFeature.Shutdown();
			ProductionCacheVaultTransfer.Shutdown();
			CraftFromContainersFeature.Shutdown();
			ChatFeature.Shutdown();
			MapFeature.Shutdown();
			ServerFeature.Shutdown();
			FieldOfViewFeature.RestoreAll();
			if (m_patches != null)
			{
				m_patches.Shutdown();
			}
		}
	}
	[HarmonyPatch(typeof(GameCamera), "UpdateFOV")]
	internal static class FieldOfViewPatch
	{
		private static void Postfix(GameCamera __instance)
		{
			FieldOfViewFeature.Update(__instance);
		}
	}
	internal static class FieldOfViewFeature
	{
		private sealed class OriginalState
		{
			internal float Fov;

			internal float FovBase;

			internal float FovTarget;

			internal float CameraFov;
		}

		private static readonly Dictionary<GameCamera, OriginalState> OriginalValues = new Dictionary<GameCamera, OriginalState>();

		private static FieldInfo s_distanceField;

		private static FieldInfo s_instanceField;

		private static FieldInfo s_fovBaseField;

		private static FieldInfo s_fovTargetField;

		private static FieldInfo s_cameraField;

		private static MethodInfo s_inInventoryEtcMethod;

		private static bool s_reflectionReady;

		private static bool s_warned;

		private static bool s_increaseWasDown;

		private static bool s_decreaseWasDown;

		private static float s_lastHotkey;

		internal static void Update(GameCamera camera)
		{
			if ((Object)(object)camera == (Object)null)
			{
				return;
			}
			EnsureReflection();
			if (!QoLSettings.IsActive || !QoLSettings.EnableFieldOfView.Value || !((Object)(object)Player.m_localPlayer != (Object)null) || !IsCurrentCamera(camera) || !ReflectionReady())
			{
				Restore(camera);
				UpdateHotkeyLatches();
				return;
			}
			if (!OriginalValues.TryGetValue(camera, out var value))
			{
				value = Capture(camera);
				OriginalValues.Add(camera, value);
			}
			HandleHotkeys(camera);
			Apply(camera, QoLSettings.FieldOfView.Value);
		}

		internal static void RestoreAll()
		{
			foreach (KeyValuePair<GameCamera, OriginalState> originalValue in OriginalValues)
			{
				if ((Object)(object)originalValue.Key != (Object)null)
				{
					RestoreState(originalValue.Key, originalValue.Value);
				}
			}
			OriginalValues.Clear();
		}

		private static OriginalState Capture(GameCamera camera)
		{
			object? value = s_cameraField.GetValue(camera);
			Camera val = (Camera)((value is Camera) ? value : null);
			return new OriginalState
			{
				Fov = camera.m_fov,
				FovBase = (float)s_fovBaseField.GetValue(camera),
				FovTarget = (float)s_fovTargetField.GetValue(camera),
				CameraFov = (((Object)(object)val != (Object)null) ? val.fieldOfView : 0f)
			};
		}

		private static void Apply(GameCamera camera, float fov)
		{
			camera.m_fov = fov;
			s_fovBaseField.SetValue(camera, fov);
			s_fovTargetField.SetValue(camera, fov);
			object? value = s_cameraField.GetValue(camera);
			Camera val = (Camera)((value is Camera) ? value : null);
			if ((Object)(object)val != (Object)null)
			{
				val.fieldOfView = fov;
			}
		}

		private static void Restore(GameCamera camera)
		{
			if (!((Object)(object)camera == (Object)null) && OriginalValues.TryGetValue(camera, out var value))
			{
				RestoreState(camera, value);
				OriginalValues.Remove(camera);
			}
		}

		private static void RestoreState(GameCamera camera, OriginalState state)
		{
			camera.m_fov = state.Fov;
			if (ReflectionReady())
			{
				s_fovBaseField.SetValue(camera, state.FovBase);
				s_fovTargetField.SetValue(camera, state.FovTarget);
				object? value = s_cameraField.GetValue(camera);
				Camera val = (Camera)((value is Camera) ? value : null);
				if ((Object)(object)val != (Object)null)
				{
					val.fieldOfView = state.CameraFov;
				}
			}
		}

		private static void EnsureReflection()
		{
			if (!s_reflectionReady)
			{
				s_distanceField = AccessTools.Field(typeof(GameCamera), "m_distance");
				s_instanceField = AccessTools.Field(typeof(GameCamera), "m_instance");
				s_fovBaseField = AccessTools.Field(typeof(GameCamera), "m_fovBase");
				s_fovTargetField = AccessTools.Field(typeof(GameCamera), "m_fovTarget");
				s_cameraField = AccessTools.Field(typeof(GameCamera), "m_camera");
				s_inInventoryEtcMethod = AccessTools.Method(typeof(PlayerController), "InInventoryEtc", (Type[])null, (Type[])null);
				s_reflectionReady = true;
				if (!ReflectionReady() && !s_warned)
				{
					s_warned = true;
					DFGQoLPlugin.Log.LogWarning((object)"FOV is unavailable because the current GameCamera fields changed.");
				}
			}
		}

		private static bool ReflectionReady()
		{
			if (s_distanceField != null && s_instanceField != null && s_fovBaseField != null && s_fovTargetField != null && s_cameraField != null)
			{
				return s_inInventoryEtcMethod != null;
			}
			return false;
		}

		private static void HandleHotkeys(GameCamera camera)
		{
			//IL_0005: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = QoLSettings.IncreaseFieldOfViewKey.Value;
			bool num = ((KeyboardShortcut)(ref value)).IsDown();
			value = QoLSettings.DecreaseFieldOfViewKey.Value;
			bool flag = ((KeyboardShortcut)(ref value)).IsDown();
			bool flag2 = num && !s_increaseWasDown;
			bool flag3 = flag && !s_decreaseWasDown;
			s_increaseWasDown = num;
			s_decreaseWasDown = flag;
			if (!flag2 && !flag3)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).InCutscene() || ((Character)localPlayer).InPlaceMode() || localPlayer.InRepairMode() || !IsFirstPerson(camera) || IsInputBlocked(localPlayer) || Menu.IsVisible() || Console.IsVisible() || Minimap.IsOpen() || Minimap.InTextInput() || Hud.InBuildUi() || Hud.InRadial() || Hud.IsPieceSelectionVisible())
			{
				return;
			}
			Chat val = Object.FindFirstObjectByType<Chat>();
			if ((!((Object)(object)val != (Object)null) || !val.HasFocus()) && !(Time.unscaledTime - s_lastHotkey < 0.2f))
			{
				float num2 = (flag2 ? 1f : (-1f));
				float num3 = Mathf.Clamp(QoLSettings.FieldOfView.Value + num2 * QoLSettings.FieldOfViewStep.Value, 30f, 110f);
				if (!Mathf.Approximately(num3, QoLSettings.FieldOfView.Value))
				{
					s_lastHotkey = Time.unscaledTime;
					QoLSettings.FieldOfView.Value = num3;
				}
			}
		}

		private static void UpdateHotkeyLatches()
		{
			//IL_0005: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = QoLSettings.IncreaseFieldOfViewKey.Value;
			s_increaseWasDown = ((KeyboardShortcut)(ref value)).IsDown();
			value = QoLSettings.DecreaseFieldOfViewKey.Value;
			s_decreaseWasDown = ((KeyboardShortcut)(ref value)).IsDown();
		}

		private static bool IsInputBlocked(Player player)
		{
			try
			{
				PlayerController component = ((Component)player).GetComponent<PlayerController>();
				return (Object)(object)component == (Object)null || (bool)s_inInventoryEtcMethod.Invoke(component, null);
			}
			catch (Exception ex)
			{
				if (!s_warned)
				{
					s_warned = true;
					DFGQoLPlugin.Log.LogWarning((object)("Could not read the current input gate: " + ex.Message));
				}
				return true;
			}
		}

		private static bool IsCurrentCamera(GameCamera camera)
		{
			try
			{
				return s_instanceField.GetValue(null) == camera;
			}
			catch (Exception ex)
			{
				if (!s_warned)
				{
					s_warned = true;
					DFGQoLPlugin.Log.LogWarning((object)("Could not identify the current player camera: " + ex.Message));
				}
				return false;
			}
		}

		private static bool IsFirstPerson(GameCamera camera)
		{
			try
			{
				return (float)s_distanceField.GetValue(camera) <= camera.m_minDistance + 0.05f;
			}
			catch (Exception ex)
			{
				if (!s_warned)
				{
					s_warned = true;
					DFGQoLPlugin.Log.LogWarning((object)("Could not read the current player camera distance: " + ex.Message));
				}
				return false;
			}
		}
	}
	public static class ChatFeature
	{
		public static void Initialize()
		{
			if ((Object)(object)Chat.instance != (Object)null)
			{
				ChatWindowController.Attach(Chat.instance);
			}
			DeathLoggingFeature.Initialize();
			ConnectionLoggingFeature.Initialize();
		}

		public static void Update()
		{
			ConnectionLoggingFeature.Update();
		}

		public static void Shutdown()
		{
			if ((Object)(object)ChatWindowController.Instance != (Object)null)
			{
				Object.Destroy((Object)(object)ChatWindowController.Instance);
			}
			DeathLoggingFeature.Shutdown();
			ConnectionLoggingFeature.Shutdown();
		}
	}
	public static class ChatPatches
	{
		[HarmonyPatch(typeof(Chat), "Awake")]
		[HarmonyPostfix]
		private static void Chat_Awake_Postfix(Chat __instance)
		{
			if (QoLSettings.IsActive && QoLSettings.EnableChatImprovements.Value)
			{
				((Terminal)__instance).m_maxVisibleBufferLength = QoLSettings.ChatMaxVisibleLines.Value;
				ChatWindowController.Attach(__instance);
			}
		}

		[HarmonyPatch(typeof(Chat), "Update")]
		[HarmonyPostfix]
		private static void Chat_Update_Postfix(Chat __instance)
		{
			if (QoLSettings.IsActive && QoLSettings.EnableChatImprovements.Value && QoLSettings.StaticChat.Value && (Object)(object)((Terminal)__instance).m_chatWindow != (Object)null)
			{
				bool num = Hud.IsUserHidden();
				bool flag = QoLSettings.ChatHideOnLargeMap.Value && Minimap.IsOpen();
				if (!num && !flag)
				{
					((Component)((Terminal)__instance).m_chatWindow).gameObject.SetActive(true);
				}
				else
				{
					((Component)((Terminal)__instance).m_chatWindow).gameObject.SetActive(false);
				}
			}
		}

		[HarmonyPatch(typeof(Chat), "IsChatDialogWindowVisible")]
		[HarmonyPrefix]
		private static bool Chat_IsChatDialogWindowVisible_Prefix(Chat __instance, ref bool __result)
		{
			if (QoLSettings.IsActive && QoLSettings.EnableChatImprovements.Value && QoLSettings.StaticChat.Value)
			{
				__result = (Object)(object)((Terminal)__instance).m_input != (Object)null && ((Component)((Terminal)__instance).m_input).gameObject.activeSelf;
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(Chat), "InputText")]
		[HarmonyPrefix]
		private static bool Chat_InputText_Prefix(Chat __instance)
		{
			if (!QoLSettings.IsActive)
			{
				return true;
			}
			if ((Object)(object)((Terminal)__instance).m_input == (Object)null)
			{
				return true;
			}
			string text = ((TMP_InputField)((Terminal)__instance).m_input).text;
			if (string.IsNullOrEmpty(text))
			{
				return true;
			}
			string text2 = text.Trim();
			if (text2.Equals("/who", StringComparison.OrdinalIgnoreCase) || text2.Equals("/players", StringComparison.OrdinalIgnoreCase) || text2.Equals("/online", StringComparison.OrdinalIgnoreCase))
			{
				ConnectionLoggingFeature.PrintOnlinePlayers(__instance);
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(Terminal), "AddString", new Type[]
		{
			typeof(PlatformUserID),
			typeof(string),
			typeof(Type),
			typeof(bool)
		})]
		[HarmonyPrefix]
		private static bool Terminal_AddString_Player_Prefix(Terminal __instance, PlatformUserID user, string text, Type type, bool timestamp)
		{
			//IL_0027: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			Chat val = (Chat)(object)((__instance is Chat) ? __instance : null);
			if (val == null)
			{
				return true;
			}
			if (!QoLSettings.IsActive || !QoLSettings.EnableChatImprovements.Value)
			{
				return true;
			}
			string text2 = "Unknown";
			PlayerInfo val2 = default(PlayerInfo);
			if (ZNet.TryGetPlayerByPlatformUserID(user, ref val2))
			{
				text2 = val2.m_name;
			}
			text2 = CensorShittyWords.FilterUGC(text2, (UGCType)2, user, 0L, (GetUserProfileCompletedHandler)null);
			FormatAndAdd(val, text2, text, type);
			return false;
		}

		[HarmonyPatch(typeof(Terminal), "AddString", new Type[]
		{
			typeof(string),
			typeof(string),
			typeof(Type),
			typeof(bool)
		})]
		[HarmonyPrefix]
		private static bool Terminal_AddString_Title_Prefix(Terminal __instance, string title, string text, Type type, bool timestamp)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			Chat val = (Chat)(object)((__instance is Chat) ? __instance : null);
			if (val == null)
			{
				return true;
			}
			if (!QoLSettings.IsActive || !QoLSettings.EnableChatImprovements.Value)
			{
				return true;
			}
			FormatAndAdd(val, title, text, type);
			return false;
		}

		[HarmonyPatch(typeof(Terminal), "AddString", new Type[] { typeof(string) })]
		[HarmonyPrefix]
		private static void Terminal_AddString_Text_Prefix(Terminal __instance, ref string text)
		{
			if (__instance is Chat && QoLSettings.IsActive && QoLSettings.EnableChatImprovements.Value && !string.IsNullOrEmpty(text) && QoLSettings.ChatShowTimestamps.Value && !text.StartsWith("<color=#7F91A6>[") && !text.StartsWith("[") && !text.StartsWith("/") && !text.StartsWith("Emotes:") && text.Trim().Length > 0)
			{
				string text2 = (string.IsNullOrEmpty(QoLSettings.ChatTimestampFormat.Value) ? "HH:mm" : QoLSettings.ChatTimestampFormat.Value);
				text = "<color=#7F91A6>[" + DateTime.Now.ToString(text2) + "]</color> " + text;
			}
		}

		private static void FormatAndAdd(Chat chat, string sender, string text, Type type)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected I4, but got Unknown
			if (!QoLSettings.ChatDisableForcedCase.Value)
			{
				if ((int)type == 2)
				{
					text = text.ToUpper();
				}
				else if ((int)type == 0)
				{
					text = text.ToLowerInvariant();
				}
			}
			else if ((int)type == 2 && QoLSettings.ChatUppercaseShout.Value)
			{
				text = text.ToUpper();
			}
			string text2 = "";
			if (QoLSettings.ChatShowTimestamps.Value)
			{
				string text3 = (string.IsNullOrEmpty(QoLSettings.ChatTimestampFormat.Value) ? "HH:mm" : QoLSettings.ChatTimestampFormat.Value);
				text2 = "<color=#7F91A6>[" + DateTime.Now.ToString(text3) + "]</color> ";
			}
			string text4 = "";
			string text5 = "#FFD661";
			string text6 = "#EBF2FA";
			switch ((int)type)
			{
			case 2:
				text4 = "<color=#FFD661><b>[SHOUT]</b></color> ";
				text5 = "#FFD661";
				text6 = "#FFF0A8";
				text = "<b>" + text + "</b>";
				break;
			case 0:
				text4 = "<color=#66CCFF><b>[WHISPER]</b></color> ";
				text5 = "#8AD6FF";
				text6 = "#B8E2FF";
				break;
			case 3:
				text4 = "<color=#61E07A><b>[PING]</b></color> ";
				text5 = "#61E07A";
				text6 = "#A3F2B0";
				break;
			default:
				if (QoLSettings.ChatShowSayChannelBadge.Value)
				{
					text4 = "<color=#D4AF37>[SAY]</color> ";
				}
				text5 = "#FFD661";
				text6 = "#EBF2FA";
				break;
			}
			string text7 = text2 + text4 + "<color=" + text5 + "><b>" + sender + "</b></color>: <color=" + text6 + ">" + text + "</color>";
			((Terminal)chat).AddString(text7);
			EventReporter.ReportEvent("chat", sender, text);
		}

		[HarmonyPatch(typeof(Terminal), "UpdateChat")]
		[HarmonyPrefix]
		private static bool Terminal_UpdateChat_Prefix(Terminal __instance)
		{
			if (!(__instance is Chat))
			{
				return true;
			}
			if (!QoLSettings.IsActive || !QoLSettings.EnableChatImprovements.Value)
			{
				return true;
			}
			if ((Object)(object)ChatWindowController.Instance != (Object)null && ChatWindowController.Instance.CurrentTab != ChatTab.All)
			{
				ChatWindowController.Instance.RenderActiveTab();
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(Terminal), "UpdateInput")]
		[HarmonyPrefix]
		private static bool Terminal_UpdateInput_Prefix(Terminal __instance)
		{
			Chat val = (Chat)(object)((__instance is Chat) ? __instance : null);
			if (val == null)
			{
				return true;
			}
			if (!QoLSettings.IsActive || !QoLSettings.EnableChatImprovements.Value)
			{
				return true;
			}
			if (Input.GetKeyDown((KeyCode)9))
			{
				bool num = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
				bool flag = Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305);
				string value = (((Object)(object)((Terminal)val).m_input != (Object)null) ? ((TMP_InputField)((Terminal)val).m_input).text : null);
				if (num || string.IsNullOrWhiteSpace(value))
				{
					ChatWindowController.Instance?.CycleTab(!flag);
					return false;
				}
			}
			return true;
		}

		[HarmonyPatch(typeof(InventoryGui), "Update")]
		[HarmonyPrefix]
		private static bool InventoryGui_Update_Prefix(InventoryGui __instance)
		{
			if (!QoLSettings.IsActive || !QoLSettings.EnableChatImprovements.Value)
			{
				return true;
			}
			if (Input.GetKeyDown((KeyCode)9) && (Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303)))
			{
				ZInput.ResetButtonStatus("Inventory");
				ZInput.ResetButtonStatus("JoyTabLeft");
				ZInput.ResetButtonStatus("JoyTabRight");
			}
			return true;
		}
	}
	public enum ChatTab
	{
		All,
		Online,
		Deaths,
		Logins
	}
	public class ChatWindowController : MonoBehaviour
	{
		private Chat m_chat;

		private RectTransform m_cardRect;

		private Image m_cardBg;

		private GameObject m_headerObj;

		private RectTransform m_headerRect;

		private Image m_headerBg;

		private Image m_goldLine;

		private TextMeshProUGUI m_titleText;

		private TextMeshProUGUI m_hintText;

		private GameObject m_expandBtnObj;

		private Button m_expandBtn;

		private TextMeshProUGUI m_expandBtnText;

		private Image m_expandBtnBg;

		private bool m_isExpanded;

		private GameObject m_tabBarObj;

		private RectTransform m_tabBarRect;

		private Image m_tabSeparatorLine;

		private readonly Button[] m_tabButtons = (Button[])(object)new Button[4];

		private readonly TextMeshProUGUI[] m_tabTexts = (TextMeshProUGUI[])(object)new TextMeshProUGUI[4];

		private readonly Image[] m_tabBgs = (Image[])(object)new Image[4];

		private int m_tabScrollHeight;

		private Image m_inputBg;

		private bool m_isDragging;

		private Vector2 m_dragOffset;

		private bool m_lastInputActive;

		private float m_headerTimer;

		private float m_lastClickTime;

		private static Sprite s_obsidianGoldSprite;

		private static Sprite s_inputBorderSprite;

		private static Sprite s_buttonBorderSprite;

		private static Sprite s_tabActiveSprite;

		private static Sprite s_tabInactiveSprite;

		private Traverse m_chatTraverse;

		private int m_lastCycleFrame = -1;

		public static ChatWindowController Instance { get; private set; }

		public ChatTab CurrentTab { get; private set; }

		private List<string> ChatBuffer
		{
			get
			{
				Traverse chatTraverse = m_chatTraverse;
				if (chatTraverse == null)
				{
					return null;
				}
				return chatTraverse.Field<List<string>>("m_chatBuffer")?.Value;
			}
		}

		private int ScrollHeight
		{
			get
			{
				if (m_chatTraverse == null)
				{
					return 0;
				}
				return m_chatTraverse.Field<int>("m_scrollHeight").Value;
			}
			set
			{
				if (m_chatTraverse != null)
				{
					m_chatTraverse.Field<int>("m_scrollHeight").Value = value;
				}
			}
		}

		private void TriggerUpdateChat()
		{
			Traverse chatTraverse = m_chatTraverse;
			if (chatTraverse != null)
			{
				Traverse obj = chatTraverse.Method("UpdateChat", Array.Empty<object>());
				if (obj != null)
				{
					obj.GetValue();
				}
			}
		}

		public static void Attach(Chat chat)
		{
			if (!((Object)(object)chat == (Object)null) && !((Object)(object)((Terminal)chat).m_chatWindow == (Object)null))
			{
				Image component = ((Component)((Terminal)chat).m_chatWindow).GetComponent<Image>();
				if ((Object)(object)component != (Object)null)
				{
					Object.Destroy((Object)(object)component);
				}
				Transform val = ((Transform)((Terminal)chat).m_chatWindow).Find("DFG_ChatHeader");
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
				ChatWindowController chatWindowController = ((Component)chat).GetComponent<ChatWindowController>();
				if ((Object)(object)chatWindowController == (Object)null)
				{
					chatWindowController = ((Component)chat).gameObject.AddComponent<ChatWindowController>();
				}
				chatWindowController.Initialize(chat);
			}
		}

		public void Initialize(Chat chat)
		{
			Instance = this;
			m_chat = chat;
			m_chatTraverse = Traverse.Create((object)chat);
			m_isExpanded = QoLSettings.ChatIsExpanded.Value;
			SetupCard();
			SetupHeader();
			SetupTabBar();
			SetupOutputArea();
			SetupInputField();
			ApplyPositionAndSize();
			UpdateTabButtons();
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		private static Sprite GetObsidianGoldSprite()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s_obsidianGoldSprite != (Object)null)
			{
				return s_obsidianGoldSprite;
			}
			Texture2D val = new Texture2D(24, 24, (TextureFormat)4, false);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0.74f, 0.58f, 0.28f, 1f);
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(0.18f, 0.23f, 0.32f, 0.9f);
			Color val4 = default(Color);
			((Color)(ref val4))..ctor(0.08f, 0.1f, 0.14f, 0.98f);
			for (int i = 0; i < 24; i++)
			{
				for (int j = 0; j < 24; j++)
				{
					if (j < 2 || j >= 22 || i < 2 || i >= 22)
					{
						val.SetPixel(j, i, val2);
						continue;
					}
					int num = 3;
					if (j < num || j >= 24 - num || i < num || i >= 24 - num)
					{
						val.SetPixel(j, i, val3);
					}
					else
					{
						val.SetPixel(j, i, val4);
					}
				}
			}
			((Texture)val).filterMode = (FilterMode)0;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			val.Apply();
			Vector4 val5 = default(Vector4);
			((Vector4)(ref val5))..ctor(4f, 4f, 4f, 4f);
			s_obsidianGoldSprite = Sprite.Create(val, new Rect(0f, 0f, 24f, 24f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, val5);
			return s_obsidianGoldSprite;
		}

		private static Sprite GetInputBorderSprite()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s_inputBorderSprite != (Object)null)
			{
				return s_inputBorderSprite;
			}
			Texture2D val = new Texture2D(16, 16, (TextureFormat)4, false);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0.74f, 0.58f, 0.28f, 0.85f);
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(0.06f, 0.08f, 0.11f, 0.98f);
			for (int i = 0; i < 16; i++)
			{
				for (int j = 0; j < 16; j++)
				{
					bool flag = j < 1 || j >= 15 || i < 1 || i >= 15;
					val.SetPixel(j, i, flag ? val2 : val3);
				}
			}
			((Texture)val).filterMode = (FilterMode)0;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			val.Apply();
			Vector4 val4 = default(Vector4);
			((Vector4)(ref val4))..ctor(2f, 2f, 2f, 2f);
			s_inputBorderSprite = Sprite.Create(val, new Rect(0f, 0f, 16f, 16f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, val4);
			return s_inputBorderSprite;
		}

		private static Sprite GetButtonBorderSprite()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s_buttonBorderSprite != (Object)null)
			{
				return s_buttonBorderSprite;
			}
			Texture2D val = new Texture2D(16, 16, (TextureFormat)4, false);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0.74f, 0.58f, 0.28f, 0.7f);
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(0.12f, 0.16f, 0.22f, 0.95f);
			for (int i = 0; i < 16; i++)
			{
				for (int j = 0; j < 16; j++)
				{
					bool flag = j < 1 || j >= 15 || i < 1 || i >= 15;
					val.SetPixel(j, i, flag ? val2 : val3);
				}
			}
			((Texture)val).filterMode = (FilterMode)0;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			val.Apply();
			Vector4 val4 = default(Vector4);
			((Vector4)(ref val4))..ctor(2f, 2f, 2f, 2f);
			s_buttonBorderSprite = Sprite.Create(val, new Rect(0f, 0f, 16f, 16f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, val4);
			return s_buttonBorderSprite;
		}

		private static Sprite GetTabActiveSprite()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s_tabActiveSprite != (Object)null)
			{
				return s_tabActiveSprite;
			}
			Texture2D val = new Texture2D(16, 16, (TextureFormat)4, false);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0.74f, 0.58f, 0.28f, 0.95f);
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(0.14f, 0.18f, 0.25f, 0.98f);
			for (int i = 0; i < 16; i++)
			{
				for (int j = 0; j < 16; j++)
				{
					bool flag = j < 1 || j >= 15 || i < 1 || i >= 15;
					val.SetPixel(j, i, flag ? val2 : val3);
				}
			}
			((Texture)val).filterMode = (FilterMode)0;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			val.Apply();
			Vector4 val4 = default(Vector4);
			((Vector4)(ref val4))..ctor(2f, 2f, 2f, 2f);
			s_tabActiveSprite = Sprite.Create(val, new Rect(0f, 0f, 16f, 16f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, val4);
			return s_tabActiveSprite;
		}

		private static Sprite GetTabInactiveSprite()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s_tabInactiveSprite != (Object)null)
			{
				return s_tabInactiveSprite;
			}
			Texture2D val = new Texture2D(16, 16, (TextureFormat)4, false);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0.18f, 0.23f, 0.32f, 0.7f);
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(0.08f, 0.1f, 0.14f, 0.85f);
			for (int i = 0; i < 16; i++)
			{
				for (int j = 0; j < 16; j++)
				{
					bool flag = j < 1 || j >= 15 || i < 1 || i >= 15;
					val.SetPixel(j, i, flag ? val2 : val3);
				}
			}
			((Texture)val).filterMode = (FilterMode)0;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			val.Apply();
			Vector4 val4 = default(Vector4);
			((Vector4)(ref val4))..ctor(2f, 2f, 2f, 2f);
			s_tabInactiveSprite = Sprite.Create(val, new Rect(0f, 0f, 16f, 16f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, val4);
			return s_tabInactiveSprite;
		}

		private void SetupCard()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Transform)((Terminal)m_chat).m_chatWindow).Find("DFG_ChatCard");
			GameObject val2;
			if ((Object)(object)val != (Object)null)
			{
				val2 = ((Component)val).gameObject;
				m_cardRect = val2.GetComponent<RectTransform>();
			}
			else
			{
				val2 = new GameObject("DFG_ChatCard");
				val2.transform.SetParent((Transform)(object)((Terminal)m_chat).m_chatWindow, false);
				m_cardRect = val2.AddComponent<RectTransform>();
			}
			m_cardBg = val2.GetComponent<Image>() ?? val2.AddComponent<Image>();
			m_cardBg.sprite = GetObsidianGoldSprite();
			m_cardBg.type = (Type)1;
			((Graphic)m_cardBg).color = new Color(1f, 1f, 1f, Mathf.Clamp01(QoLSettings.ChatWindowOpacity.Value));
			((Graphic)m_cardBg).raycastTarget = false;
		}

		private void SetupHeader()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03be: Expected O, but got