Decompiled source of QOL KPX v2.3.0

QOL_KPX.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("QOL_KPX")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.3.0.0")]
[assembly: AssemblyInformationalVersion("2.3.0+8e1c531dbf9c80d1e61a45420e7a51e511639606")]
[assembly: AssemblyProduct("QOL_KPX")]
[assembly: AssemblyTitle("QOL_KPX")]
[assembly: AssemblyVersion("2.3.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace QolKpx
{
	internal static class Archery
	{
		internal static float StaminaReduction = 0.5f;

		internal static float AccuracyBonus = 1f;

		internal static bool Enabled = true;

		private static Player Local => Player.m_localPlayer;

		private static float Factor => ((Character)Local).GetSkillFactor((SkillType)8);

		private static bool IsLocalBow(Character c, ItemData weapon)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Invalid comparison between Unknown and I4
			if (Enabled && (Object)(object)Local != (Object)null && (Object)(object)c == (Object)(object)Local && weapon != null)
			{
				return (int)weapon.m_shared.m_skillType == 8;
			}
			return false;
		}

		[HarmonyPatch(typeof(ItemData), "GetDrawStaminaDrain")]
		[HarmonyPostfix]
		private static void DrawDrain(ItemData __instance, ref float __result)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Invalid comparison between Unknown and I4
			try
			{
				if (Enabled && !(__result <= 0f) && !((Object)(object)Local == (Object)null) && (int)__instance.m_shared.m_skillType == 8)
				{
					__result *= 1f - Factor * StaminaReduction;
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha na stamina do arco: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(Attack), "GetAttackStamina")]
		[HarmonyPostfix]
		private static void ShotStamina(ref float __result, Character ___m_character, ItemData ___m_weapon)
		{
			try
			{
				if (!(__result <= 0f) && IsLocalBow(___m_character, ___m_weapon))
				{
					__result *= 1f - Factor * StaminaReduction;
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha na stamina do disparo: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(Attack), "FireProjectileBurst")]
		[HarmonyPrefix]
		private static void AimBefore(Character ___m_character, ItemData ___m_weapon, out float __state)
		{
			__state = float.NaN;
			try
			{
				if (IsLocalBow(___m_character, ___m_weapon))
				{
					Attack attack = ___m_weapon.m_shared.m_attack;
					__state = attack.m_projectileAccuracy;
					attack.m_projectileAccuracy = Mathf.Lerp(attack.m_projectileAccuracy, attack.m_projectileAccuracyMin, Mathf.Clamp01(Factor * AccuracyBonus));
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha na precisão do arco: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(Attack), "FireProjectileBurst")]
		[HarmonyPostfix]
		private static void AimAfter(ItemData ___m_weapon, float __state)
		{
			if (!float.IsNaN(__state) && ___m_weapon != null)
			{
				___m_weapon.m_shared.m_attack.m_projectileAccuracy = __state;
			}
		}
	}
	internal static class BlastFurnace
	{
		internal struct Saved
		{
			internal bool active;

			internal float seconds;

			internal int fuel;
		}

		internal static bool Enabled = true;

		internal static float Efficiency = 0.5f;

		private const string Furnace = "blastfurnace";

		private const string Smelter = "smelter";

		private static readonly HashSet<string> borrowed = new HashSet<string>();

		private static readonly Func<Smelter, string> QueuedOre = AccessTools.MethodDelegate<Func<Smelter, string>>(AccessTools.Method(typeof(Smelter), "GetQueuedOre", (Type[])null, (Type[])null), (object)null, true);

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		[HarmonyPostfix]
		private static void Teach(ZNetScene __instance)
		{
			try
			{
				if (!Enabled || (Object)(object)__instance == (Object)null)
				{
					return;
				}
				Smelter val = Component(__instance, "blastfurnace");
				Smelter val2 = Component(__instance, "smelter");
				if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
				{
					return;
				}
				borrowed.Clear();
				foreach (ItemConversion item in val2.m_conversion)
				{
					if ((Object)(object)item?.m_from != (Object)null && (Object)(object)item.m_to != (Object)null)
					{
						borrowed.Add(((Object)((Component)item.m_from).gameObject).name);
					}
				}
				HashSet<string> hashSet = new HashSet<string>();
				foreach (ItemConversion item2 in val.m_conversion)
				{
					if ((Object)(object)item2?.m_from != (Object)null)
					{
						hashSet.Add(((Object)((Component)item2.m_from).gameObject).name);
					}
				}
				int num = 0;
				foreach (ItemConversion item3 in val2.m_conversion)
				{
					if (!((Object)(object)item3?.m_from == (Object)null) && !((Object)(object)item3.m_to == (Object)null) && hashSet.Add(((Object)((Component)item3.m_from).gameObject).name))
					{
						val.m_conversion.Add(item3);
						num++;
					}
				}
				Debug.Log((object)("[QOL KPX] [BlastFurnace] minérios com desconto: " + borrowed.Count + ", receitas novas: " + num));
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao ensinar o alto-forno: " + ex.Message));
			}
		}

		private static Smelter Component(ZNetScene scene, string prefabName)
		{
			GameObject prefab = scene.GetPrefab(prefabName);
			if (!((Object)(object)prefab != (Object)null))
			{
				return null;
			}
			return prefab.GetComponent<Smelter>();
		}

		[HarmonyPatch(typeof(Smelter), "UpdateSmelter")]
		[HarmonyPrefix]
		private static void Cheaper(Smelter __instance, out Saved __state)
		{
			__state = default(Saved);
			try
			{
				if (Enabled && !(Efficiency <= 0f) && !(Efficiency >= 1f) && !((Object)(object)__instance == (Object)null) && borrowed.Count != 0 && !(Utils.GetPrefabName(((Component)__instance).gameObject) != "blastfurnace") && borrowed.Contains(QueuedOre(__instance)))
				{
					__state.active = true;
					__state.seconds = __instance.m_secPerProduct;
					__state.fuel = __instance.m_fuelPerProduct;
					__instance.m_secPerProduct *= Efficiency;
					__instance.m_fuelPerProduct = Mathf.Max(1, Mathf.RoundToInt((float)__state.fuel * Efficiency));
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha no desconto do alto-forno: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(Smelter), "UpdateSmelter")]
		[HarmonyFinalizer]
		private static void Restore(Smelter __instance, Saved __state)
		{
			if (__state.active && !((Object)(object)__instance == (Object)null))
			{
				__instance.m_secPerProduct = __state.seconds;
				__instance.m_fuelPerProduct = __state.fuel;
			}
		}
	}
	internal static class Bronze
	{
		internal static bool Enabled = true;

		internal static float Ratio = 1f;

		private const string Item = "Bronze";

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		[HarmonyPostfix]
		private static void OnDbAwake(ObjectDB __instance)
		{
			Rebalance(__instance);
		}

		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		[HarmonyPostfix]
		private static void OnDbCopied(ObjectDB __instance)
		{
			Rebalance(__instance);
		}

		private static void Rebalance(ObjectDB db)
		{
			try
			{
				if (!Enabled || db?.m_recipes == null)
				{
					return;
				}
				foreach (Recipe recipe in db.m_recipes)
				{
					if ((Object)(object)recipe?.m_item == (Object)null || ((Object)((Component)recipe.m_item).gameObject).name != "Bronze" || recipe.m_resources == null || recipe.m_resources.Length == 0)
					{
						continue;
					}
					int num = 0;
					Requirement[] resources = recipe.m_resources;
					foreach (Requirement val in resources)
					{
						if ((Object)(object)val?.m_resItem != (Object)null)
						{
							num += val.m_amount;
						}
					}
					if (num > 0)
					{
						int num2 = Mathf.Max(1, Mathf.RoundToInt((float)num * Ratio));
						if (recipe.m_amount != num2)
						{
							Debug.Log((object)$"[QOL KPX] bronze: {num} de entrada passa a render {num2} (era {recipe.m_amount})");
							recipe.m_amount = num2;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao ajustar o bronze: " + ex.Message));
			}
		}
	}
	internal static class Building
	{
		internal static bool Enabled = true;

		internal static float Multiplier = 3f;

		[HarmonyPatch(typeof(WearNTear), "GetMaterialProperties")]
		[HarmonyPostfix]
		private static void Reinforce(ref float maxSupport, ref float horizontalLoss, ref float verticalLoss)
		{
			try
			{
				if (Enabled && !(Multiplier <= 0f))
				{
					maxSupport *= Multiplier;
					horizontalLoss /= Multiplier;
					verticalLoss /= Multiplier;
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha no limite de construção: " + ex.Message));
			}
		}
	}
	internal static class BuildTools
	{
		internal static bool NoStamina = true;

		internal static bool NoDurability = true;

		internal static bool NoMoveStamina = true;

		private static bool IsLocal(Player p)
		{
			if ((Object)(object)p != (Object)null)
			{
				return (Object)(object)p == (Object)(object)Player.m_localPlayer;
			}
			return false;
		}

		[HarmonyPatch(typeof(Player), "UseStamina")]
		[HarmonyPrefix]
		private static bool FreeWhileBuilding(Player __instance)
		{
			if (!NoMoveStamina || !IsLocal(__instance) || !((Character)__instance).InPlaceMode())
			{
				return true;
			}
			return false;
		}

		[HarmonyPatch(typeof(Player), "GetBuildStamina")]
		[HarmonyPostfix]
		private static void NoBuildStamina(Player __instance, ref float __result)
		{
			if (NoStamina && IsLocal(__instance))
			{
				__result = 0f;
			}
		}

		[HarmonyPatch(typeof(Player), "GetPlaceDurability")]
		[HarmonyPostfix]
		private static void NoPlaceWear(Player __instance, ref float __result)
		{
			if (NoDurability && IsLocal(__instance))
			{
				__result = 0f;
			}
		}

		[HarmonyPatch(typeof(Player), "Repair")]
		[HarmonyPrefix]
		private static void KeepWear(ItemData __0, out float __state)
		{
			__state = __0?.m_durability ?? (-1f);
		}

		[HarmonyPatch(typeof(Player), "Repair")]
		[HarmonyPostfix]
		private static void RestoreWear(Player __instance, ItemData __0, float __state)
		{
			if (NoDurability && __state >= 0f && __0 != null && IsLocal(__instance))
			{
				__0.m_durability = __state;
			}
		}
	}
	internal static class Charcoal
	{
		internal static bool Enabled = true;

		internal static int KilnCapacity = 100;

		internal static string WeightList = "Wood:1,RoundLog:5,FineWood:8,ElderBark:10,YggdrasilWood:15,Blackwood:20,Frostwood:25";

		private const string CoalName = "Coal";

		private static readonly FieldRef<Smelter, ZNetView> NView = AccessTools.FieldRefAccess<Smelter, ZNetView>("m_nview");

		private static readonly Func<Smelter, int> QueueSize = AccessTools.MethodDelegate<Func<Smelter, int>>(AccessTools.Method(typeof(Smelter), "GetQueueSize", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Func<Smelter, Inventory, ItemData> FindCookable = AccessTools.MethodDelegate<Func<Smelter, Inventory, ItemData>>(AccessTools.Method(typeof(Smelter), "FindCookableItem", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Dictionary<string, int> weights = new Dictionary<string, int>();

		private static readonly HashSet<string> warned = new HashSet<string>();

		private static string parsedFrom;

		private static void Parse()
		{
			if (parsedFrom == WeightList)
			{
				return;
			}
			parsedFrom = WeightList;
			weights.Clear();
			warned.Clear();
			string[] array = WeightList.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { ':' });
				if (array2.Length == 2 && int.TryParse(array2[1].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && result > 0)
				{
					weights[array2[0].Trim()] = result;
				}
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		[HarmonyPostfix]
		private static void Prepare(ZNetScene __instance)
		{
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Expected O, but got Unknown
			try
			{
				if (!Enabled || (Object)(object)__instance == (Object)null)
				{
					return;
				}
				Parse();
				int num = 1;
				foreach (int value in weights.Values)
				{
					if (value > num)
					{
						num = value;
					}
				}
				foreach (GameObject prefab2 in __instance.m_prefabs)
				{
					Smelter val = (((Object)(object)prefab2 != (Object)null) ? prefab2.GetComponent<Smelter>() : null);
					if ((Object)(object)val == (Object)null || val.m_conversion == null)
					{
						continue;
					}
					ItemDrop val2 = CoalFrom(val);
					if ((Object)(object)val2 == (Object)null)
					{
						continue;
					}
					int num2 = 0;
					foreach (KeyValuePair<string, int> weight in weights)
					{
						if (!IsInput(val, weight.Key))
						{
							GameObject prefab = __instance.GetPrefab(weight.Key);
							ItemDrop val3 = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<ItemDrop>() : null);
							if (!((Object)(object)val3 == (Object)null))
							{
								val.m_conversion.Add(new ItemConversion
								{
									m_from = val3,
									m_to = val2
								});
								num2++;
							}
						}
					}
					int maxOre = val.m_maxOre;
					val.m_maxOre = Mathf.Max(maxOre, Mathf.Max(KilnCapacity, num));
					Debug.Log((object)("[QOL KPX] [Charcoal] " + ((Object)prefab2).name + ": carga " + maxOre + " -> " + val.m_maxOre + ", madeiras novas: " + num2));
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao preparar o forno de carvão: " + ex.Message));
			}
		}

		private static ItemDrop CoalFrom(Smelter kiln)
		{
			foreach (ItemConversion item in kiln.m_conversion)
			{
				if ((Object)(object)item?.m_from != (Object)null && (Object)(object)item.m_to != (Object)null && Utils.GetPrefabName(((Component)item.m_to).gameObject) == "Coal")
				{
					return item.m_to;
				}
			}
			return null;
		}

		private static bool MakesCoal(Smelter smelter, string prefab)
		{
			foreach (ItemConversion item in smelter.m_conversion)
			{
				if (!((Object)(object)item?.m_from == (Object)null) && !((Object)(object)item.m_to == (Object)null) && !(Utils.GetPrefabName(((Component)item.m_from).gameObject) != prefab))
				{
					return Utils.GetPrefabName(((Component)item.m_to).gameObject) == "Coal";
				}
			}
			return false;
		}

		internal static int Weight(Smelter smelter, string prefab)
		{
			if (!Enabled || (Object)(object)smelter == (Object)null || string.IsNullOrEmpty(prefab))
			{
				return 1;
			}
			Parse();
			if (!weights.TryGetValue(prefab, out var value) || value <= 1)
			{
				return 1;
			}
			if (!MakesCoal(smelter, prefab))
			{
				return 1;
			}
			if (value > smelter.m_maxOre && warned.Add(prefab))
			{
				Debug.LogWarning((object)("[QOL KPX] [Charcoal] " + prefab + " pesa " + value + ", mas o forno só cabe " + smelter.m_maxOre + ": nunca vai entrar"));
			}
			return value;
		}

		internal static bool Fits(Smelter smelter, string prefab)
		{
			if ((Object)(object)smelter == (Object)null)
			{
				return false;
			}
			return QueueSize(smelter) + Weight(smelter, prefab) <= smelter.m_maxOre;
		}

		[HarmonyPatch(typeof(Smelter), "OnAddOre")]
		[HarmonyPrefix]
		private static bool OnlyWhatFits(Smelter __instance, Humanoid user, ref ItemData item, ref bool __result)
		{
			try
			{
				if (!Enabled || (Object)(object)__instance == (Object)null || (Object)(object)user == (Object)null)
				{
					return true;
				}
				Inventory inventory = user.GetInventory();
				bool flag = item != null;
				ItemData val = item ?? FindCookable(__instance, inventory);
				string text = (((Object)(object)val?.m_dropPrefab != (Object)null) ? ((Object)val.m_dropPrefab).name : null);
				if (text == null)
				{
					return true;
				}
				if (Fits(__instance, text))
				{
					return true;
				}
				if (!flag)
				{
					ItemData val2 = BestFit(__instance, inventory);
					if (val2 != null)
					{
						item = val2;
						return true;
					}
				}
				((Character)user).Message((MessageType)2, "$msg_itsfull", 0, (Sprite)null, false);
				__result = false;
				return false;
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao conferir a carga do forno: " + ex.Message));
			}
			return true;
		}

		internal static ItemData BestFit(Smelter smelter, Inventory inv)
		{
			if ((Object)(object)smelter == (Object)null || inv == null)
			{
				return null;
			}
			ItemData result = null;
			int num = 0;
			foreach (ItemData allItem in inv.GetAllItems())
			{
				string text = (((Object)(object)allItem?.m_dropPrefab != (Object)null) ? ((Object)allItem.m_dropPrefab).name : null);
				if (text != null && IsInput(smelter, text) && Fits(smelter, text))
				{
					int num2 = Weight(smelter, text);
					if (num2 > num)
					{
						result = allItem;
						num = num2;
					}
				}
			}
			return result;
		}

		internal static bool IsInput(Smelter smelter, string prefab)
		{
			foreach (ItemConversion item in smelter.m_conversion)
			{
				if ((Object)(object)item?.m_from != (Object)null && Utils.GetPrefabName(((Component)item.m_from).gameObject) == prefab)
				{
					return true;
				}
			}
			return false;
		}

		[HarmonyPatch(typeof(Smelter), "QueueOre")]
		[HarmonyPostfix]
		private static void Weigh(Smelter __instance, string name, bool cheated)
		{
			try
			{
				if (!Enabled || (Object)(object)__instance == (Object)null || string.IsNullOrEmpty(name))
				{
					return;
				}
				int num = Weight(__instance, name);
				if (num <= 1)
				{
					return;
				}
				ZNetView obj = NView.Invoke(__instance);
				ZDO val = ((obj != null) ? obj.GetZDO() : null);
				if (val == null)
				{
					return;
				}
				for (int i = 1; i < num; i++)
				{
					int num2 = val.GetInt(ZDOVars.s_queued, 0);
					if (num2 < __instance.m_maxOre)
					{
						val.Set("item" + num2, name);
						val.Set(ZDOVars.s_queued, num2 + 1, false);
						val.Set(ZDOVars.s_cheatedQueued, cheated);
						continue;
					}
					break;
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha no peso da madeira: " + ex.Message));
			}
		}
	}
	internal static class ChestCrafting
	{
		private class Request
		{
			internal Container Chest;

			internal string Name;

			internal int Amount;

			internal int Quality;

			internal int Tries;

			internal bool ForCredit;

			internal bool Replied;

			internal uint Revision;

			internal float Time;
		}

		internal static bool Enabled = true;

		private const string RpcTake = "QolKpx_ChestTake";

		private const string RpcTook = "QolKpx_ChestTook";

		private const float ReplyTimeout = 5f;

		private const int MaxTries = 3;

		private static readonly FieldRef<Container, ZNetView> View = AccessTools.FieldRefAccess<Container, ZNetView>("m_nview");

		private static readonly FieldRef<Container, uint> LoadedRevision = AccessTools.FieldRefAccess<Container, uint>("m_lastRevision");

		private static readonly FieldRef<InventoryGui, float> CraftTimer = AccessTools.FieldRefAccess<InventoryGui, float>("m_craftTimer");

		private static readonly FieldRef<InventoryGui, Recipe> CraftRecipe = AccessTools.FieldRefAccess<InventoryGui, Recipe>("m_craftRecipe");

		private static readonly FieldRef<InventoryGui, ItemData> CraftUpgradeItem = AccessTools.FieldRefAccess<InventoryGui, ItemData>("m_craftUpgradeItem");

		private static readonly FieldRef<InventoryGui, bool> MultiCrafting = AccessTools.FieldRefAccess<InventoryGui, bool>("m_multiCrafting");

		private static readonly FieldRef<InventoryGui, ItemData> DragItem = AccessTools.FieldRefAccess<InventoryGui, ItemData>("m_dragItem");

		private static readonly FieldRef<InventoryGui, ItemData> SplitItem = AccessTools.FieldRefAccess<InventoryGui, ItemData>("m_splitItem");

		private static readonly FieldInfo Stations = AccessTools.Field(typeof(CraftingStation), "m_allStations");

		private static readonly HashSet<Container> all = new HashSet<Container>();

		private static readonly List<Container> nearby = new List<Container>();

		private static readonly List<CraftingStation> covering = new List<CraftingStation>();

		private static float nearbyAt = -10f;

		private const float Refresh = 0.5f;

		private static readonly Dictionary<string, int> counts = new Dictionary<string, int>();

		private static int countsFrame = -1;

		private static int depth;

		private static readonly Dictionary<string, int> credit = new Dictionary<string, int>();

		private static readonly Dictionary<string, ItemDrop> prefabs = new Dictionary<string, ItemDrop>();

		private static readonly Dictionary<int, Request> requests = new Dictionary<int, Request>();

		private static readonly List<int> finished = new List<int>();

		private static int nextId;

		private static Player Local => Player.m_localPlayer;

		[HarmonyPatch(typeof(Container), "Awake")]
		[HarmonyPostfix]
		private static void Track(Container __instance)
		{
			try
			{
				if ((Object)(object)__instance == (Object)null || __instance.GetInventory() == null)
				{
					return;
				}
				all.Add(__instance);
				ZNetView val = View.Invoke(__instance);
				if (!((Object)(object)val == (Object)null))
				{
					Container chest = __instance;
					val.Register<string, int, int, int>("QolKpx_ChestTake", (Method<string, int, int, int>)delegate(long sender, string name, int amount, int quality, int id)
					{
						OnTake(chest, sender, name, amount, quality, id);
					});
					val.Register<int, int, bool>("QolKpx_ChestTook", (Action<long, int, int, bool>)OnTook);
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao registrar baú: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(Player), "HaveRequirementItems")]
		[HarmonyPrefix]
		private static void EnterRecipe(Player __instance, Recipe piece, bool discover, out bool __state)
		{
			__state = Enabled && (Object)(object)__instance == (Object)(object)Local && !discover && (Object)(object)piece != (Object)null && !piece.m_requireOnlyOneIngredient;
			if (__state)
			{
				depth++;
			}
		}

		[HarmonyPatch(typeof(Player), "HaveRequirementItems")]
		[HarmonyFinalizer]
		private static void LeaveRecipe(bool __state)
		{
			if (__state)
			{
				depth--;
			}
		}

		[HarmonyPatch(typeof(Player), "HaveRequirements", new Type[]
		{
			typeof(Piece),
			typeof(RequirementMode)
		})]
		[HarmonyPrefix]
		private static void EnterBuild(Player __instance, RequirementMode mode, out bool __state)
		{
			//IL_0015: 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_001a: Invalid comparison between Unknown and I4
			__state = Enabled && (Object)(object)__instance == (Object)(object)Local && ((int)mode == 0 || (int)mode == 2);
			if (__state)
			{
				depth++;
			}
		}

		[HarmonyPatch(typeof(Player), "HaveRequirements", new Type[]
		{
			typeof(Piece),
			typeof(RequirementMode)
		})]
		[HarmonyFinalizer]
		private static void LeaveBuild(bool __state)
		{
			if (__state)
			{
				depth--;
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "SetupRequirement")]
		[HarmonyPrefix]
		private static void EnterPanel(Player player, out bool __state)
		{
			__state = Enabled && (Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)Local;
			if (__state)
			{
				depth++;
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "SetupRequirement")]
		[HarmonyFinalizer]
		private static void LeavePanel(bool __state)
		{
			if (__state)
			{
				depth--;
			}
		}

		[HarmonyPatch(typeof(Inventory), "CountItems")]
		[HarmonyPostfix]
		private static void AddStock(Inventory __instance, string name, int quality, bool matchWorldLevel, ref int __result)
		{
			try
			{
				if (depth > 0 && name != null && !((Object)(object)Local == (Object)null) && __instance == ((Humanoid)Local).GetInventory())
				{
					__result += Stock(name, quality, matchWorldLevel);
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao contar os baús: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(Inventory), "HaveItem", new Type[]
		{
			typeof(string),
			typeof(bool)
		})]
		[HarmonyPostfix]
		private static void HaveStock(Inventory __instance, string name, bool matchWorldLevel, ref bool __result)
		{
			try
			{
				if (!__result && depth > 0 && name != null && !((Object)(object)Local == (Object)null) && __instance == ((Humanoid)Local).GetInventory())
				{
					__result = Stock(name, -1, matchWorldLevel) > 0;
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao contar os baús: " + ex.Message));
			}
		}

		internal static int Reachable(string name)
		{
			try
			{
				return (Enabled && name != null && (Object)(object)Local != (Object)null) ? Stock(name, -1, matchWorldLevel: true) : 0;
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao ler o estoque dos baús: " + ex.Message));
				return 0;
			}
		}

		private static int Stock(string name, int quality, bool matchWorldLevel)
		{
			if (countsFrame != Time.frameCount)
			{
				counts.Clear();
				countsFrame = Time.frameCount;
			}
			string key = name + "|" + quality + (matchWorldLevel ? "|1" : "|0");
			if (counts.TryGetValue(key, out var value))
			{
				return value;
			}
			value = ((quality <= 1 && credit.TryGetValue(name, out var value2)) ? value2 : 0);
			foreach (Container item in Nearby(force: false))
			{
				if (Valid(item))
				{
					value += Available(item, name, quality, matchWorldLevel);
				}
			}
			counts[key] = value;
			return value;
		}

		private static int Available(Container c, string name, int quality, bool matchWorldLevel)
		{
			int num = c.GetInventory().CountItems(name, quality, matchWorldLevel);
			foreach (Request value in requests.Values)
			{
				if ((Object)(object)value.Chest == (Object)(object)c && value.Name == name)
				{
					num -= value.Amount;
				}
			}
			return Mathf.Max(0, num);
		}

		[HarmonyPatch(typeof(InventoryGui), "OnCraftPressed")]
		[HarmonyPostfix]
		private static void PayOnClick(InventoryGui __instance)
		{
			try
			{
				Player local = Local;
				if (Enabled && !((Object)(object)local == (Object)null) && CraftTimer.Invoke(__instance) == 0f)
				{
					Recipe val = CraftRecipe.Invoke(__instance);
					if (!((Object)(object)val == (Object)null) && !val.m_requireOnlyOneIngredient && !local.NoCostCheat() && !ZoneSystem.instance.GetGlobalKey((GlobalKeys)25))
					{
						ItemData val2 = CraftUpgradeItem.Invoke(__instance);
						int qualityLevel = ((val2 == null) ? 1 : (val2.m_quality + 1));
						int multiplier = ((!MultiCrafting.Invoke(__instance)) ? 1 : __instance.m_multiCraftAmount);
						Pay(local, val.m_resources, qualityLevel, -1, multiplier, toCredit: true);
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao pagar a fabricação: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "Update")]
		[HarmonyPostfix]
		private static void Settle(InventoryGui __instance)
		{
			try
			{
				Expire();
				if (credit.Count == 0 || CraftTimer.Invoke(__instance) >= 0f)
				{
					return;
				}
				foreach (Request value in requests.Values)
				{
					if (value.ForCredit && !value.Replied)
					{
						return;
					}
				}
				Refund();
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao devolver material: " + ex.Message));
			}
		}

		private static void Refund()
		{
			Player local = Local;
			if ((Object)(object)local != (Object)null)
			{
				foreach (KeyValuePair<string, int> item in credit)
				{
					if (item.Value > 0 && prefabs.TryGetValue(item.Key, out var value) && !((Object)(object)value == (Object)null))
					{
						((Humanoid)local).GetInventory().AddItem(((Object)((Component)value).gameObject).name, item.Value, 1, 0, 0L, "", false, false);
					}
				}
			}
			credit.Clear();
			countsFrame = -1;
		}

		[HarmonyPatch(typeof(Player), "ConsumeResources")]
		[HarmonyPrefix]
		private static bool Consume(Player __instance, Requirement[] requirements, int qualityLevel, int itemQuality, int multiplier)
		{
			try
			{
				if (!Enabled || (Object)(object)__instance != (Object)(object)Local || requirements == null)
				{
					return true;
				}
				Pay(__instance, requirements, qualityLevel, itemQuality, multiplier, toCredit: false);
				return false;
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao tirar recursos dos baús: " + ex.Message));
				return true;
			}
		}

		private static void Pay(Player player, Requirement[] requirements, int qualityLevel, int itemQuality, int multiplier, bool toCredit)
		{
			CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
			Inventory inventory = ((Humanoid)player).GetInventory();
			List<Container> list = null;
			foreach (Requirement val in requirements)
			{
				if (val == null || !Object.op_Implicit((Object)(object)val.m_resItem) || (((Object)(object)currentCraftingStation != (Object)null) ? (currentCraftingStation.m_upgrader != val.m_upgraderResource) : val.m_upgraderResource))
				{
					continue;
				}
				int num = val.GetAmount(qualityLevel) * multiplier;
				if (num <= 0)
				{
					continue;
				}
				string name = val.m_resItem.m_itemData.m_shared.m_name;
				prefabs[name] = val.m_resItem;
				if (!toCredit && credit.TryGetValue(name, out var value))
				{
					int num2 = Mathf.Min(value, num);
					credit[name] = value - num2;
					num -= num2;
				}
				int num3 = Mathf.Min(num, inventory.CountItems(name, itemQuality, true));
				if (num3 > 0)
				{
					inventory.RemoveItem(name, num3, itemQuality, true);
					num -= num3;
					if (toCredit)
					{
						AddCredit(name, num3);
					}
				}
				if (num <= 0)
				{
					continue;
				}
				if (list == null)
				{
					list = Nearby(force: true);
				}
				foreach (Container item in list)
				{
					if (num <= 0)
					{
						break;
					}
					num -= Withdraw(item, name, num, itemQuality, toCredit);
				}
			}
			countsFrame = -1;
		}

		private static void AddCredit(string name, int amount)
		{
			credit.TryGetValue(name, out var value);
			credit[name] = value + amount;
		}

		private static int Withdraw(Container c, string name, int amount, int quality, bool toCredit)
		{
			if (!Valid(c))
			{
				return 0;
			}
			int num = Mathf.Min(amount, Available(c, name, quality, matchWorldLevel: true));
			if (num <= 0)
			{
				return 0;
			}
			ZNetView val = View.Invoke(c);
			if (!val.GetZDO().HasOwner())
			{
				val.ClaimOwnership();
			}
			if (val.IsOwner())
			{
				num = TakeFrom(c, name, num, quality);
				if (toCredit)
				{
					AddCredit(name, num);
				}
				return num;
			}
			Send(new Request
			{
				Chest = c,
				Name = name,
				Amount = num,
				Quality = quality,
				ForCredit = toCredit,
				Revision = LoadedRevision.Invoke(c),
				Time = Time.time
			});
			if (toCredit)
			{
				AddCredit(name, num);
			}
			return num;
		}

		private static void Send(Request r)
		{
			int num = ++nextId;
			r.Tries++;
			r.Time = Time.time;
			requests[num] = r;
			View.Invoke(r.Chest).InvokeRPC("QolKpx_ChestTake", new object[4] { r.Name, r.Amount, r.Quality, num });
		}

		private static void OnTake(Container c, long sender, string name, int amount, int quality, int id)
		{
			int num = 0;
			bool flag = false;
			try
			{
				ZNetView val = View.Invoke(c);
				if ((Object)(object)val == (Object)null || !val.IsValid() || !val.IsOwner())
				{
					flag = true;
				}
				else
				{
					num = TakeFrom(c, name, amount, quality);
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao atender pedido de baú: " + ex.Message));
			}
			try
			{
				ZNetView obj = View.Invoke(c);
				if (obj != null)
				{
					obj.InvokeRPC(sender, "QolKpx_ChestTook", new object[3] { id, num, flag });
				}
			}
			catch (Exception ex2)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao responder pedido de baú: " + ex2.Message));
			}
		}

		private static int TakeFrom(Container c, string name, int amount, int quality)
		{
			Inventory inventory = c.GetInventory();
			InventoryGui instance = InventoryGui.instance;
			ItemData val = (((Object)(object)instance != (Object)null) ? DragItem.Invoke(instance) : null);
			ItemData val2 = (((Object)(object)instance != (Object)null) ? SplitItem.Invoke(instance) : null);
			int num = 0;
			ItemData[] array = inventory.GetAllItems().ToArray();
			foreach (ItemData val3 in array)
			{
				if (num >= amount)
				{
					break;
				}
				if (val3 != val && val3 != val2 && !(val3.m_shared.m_name != name) && (quality < 0 || val3.m_quality == quality) && val3.m_worldLevel >= Game.m_worldLevel)
				{
					int num2 = Mathf.Min(val3.m_stack, amount - num);
					if (inventory.RemoveItem(val3, num2))
					{
						num += num2;
					}
				}
			}
			return num;
		}

		private static void OnTook(long sender, int id, int removed, bool notOwner)
		{
			try
			{
				if (!requests.TryGetValue(id, out var value))
				{
					return;
				}
				if (notOwner && value.Tries < 3 && Valid(value.Chest))
				{
					requests.Remove(id);
					Send(value);
					return;
				}
				if (removed < value.Amount)
				{
					if (value.ForCredit)
					{
						AddCredit(value.Name, removed - value.Amount);
					}
					else
					{
						Debug.LogWarning((object)$"[QOL KPX] baú entregou {removed} de {value.Amount} {value.Name}");
					}
				}
				value.Amount = removed;
				value.Replied = true;
				countsFrame = -1;
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao ler resposta de baú: " + ex.Message));
			}
		}

		private static void Expire()
		{
			if (requests.Count == 0)
			{
				return;
			}
			finished.Clear();
			foreach (KeyValuePair<int, Request> request in requests)
			{
				Request value = request.Value;
				if ((Object)(object)value.Chest == (Object)null)
				{
					finished.Add(request.Key);
				}
				else if (value.Replied)
				{
					if (value.Amount <= 0 || LoadedRevision.Invoke(value.Chest) != value.Revision || Time.time - value.Time > 5f)
					{
						finished.Add(request.Key);
					}
				}
				else if (Time.time - value.Time > 5f)
				{
					if (value.ForCredit)
					{
						AddCredit(value.Name, -value.Amount);
					}
					Debug.LogWarning((object)$"[QOL KPX] baú não respondeu ao pedido de {value.Amount} {value.Name}");
					finished.Add(request.Key);
				}
			}
			foreach (int item in finished)
			{
				requests.Remove(item);
			}
			if (finished.Count > 0)
			{
				countsFrame = -1;
			}
		}

		private static List<Container> Nearby(bool force)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			if (!force && Time.time - nearbyAt < 0.5f)
			{
				return nearby;
			}
			nearbyAt = Time.time;
			nearby.Clear();
			Player local = Local;
			List<CraftingStation> list = Stations?.GetValue(null) as List<CraftingStation>;
			if ((Object)(object)local == (Object)null || list == null)
			{
				return nearby;
			}
			Vector3 position = ((Component)local).transform.position;
			covering.Clear();
			foreach (CraftingStation item in list)
			{
				if ((Object)(object)item != (Object)null && Flat(((Component)item).transform.position, position) < item.GetStationBuildRange())
				{
					covering.Add(item);
				}
			}
			if (covering.Count == 0)
			{
				return nearby;
			}
			all.RemoveWhere((Container c) => (Object)(object)c == (Object)null);
			foreach (Container item2 in all)
			{
				if (!Allowed(item2))
				{
					continue;
				}
				Vector3 position2 = ((Component)item2).transform.position;
				foreach (CraftingStation item3 in covering)
				{
					if (Flat(((Component)item3).transform.position, position2) < item3.GetStationBuildRange())
					{
						nearby.Add(item2);
						break;
					}
				}
			}
			return nearby;
		}

		private static float Flat(Vector3 a, Vector3 b)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			a.y = b.y;
			return Vector3.Distance(a, b);
		}

		private static bool Allowed(Container c)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Invalid comparison between Unknown and I4
			if (c.GetInventory() == null)
			{
				return false;
			}
			if (Object.op_Implicit((Object)(object)((Component)c).GetComponent<TombStone>()) || Object.op_Implicit((Object)(object)((Component)c).GetComponent<Smelter>()))
			{
				return false;
			}
			if (c.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)c).transform.position, 0f, false, false))
			{
				return false;
			}
			PrivacySetting privacy = c.m_privacy;
			if ((int)privacy != 0)
			{
				if ((int)privacy == 2)
				{
					return true;
				}
				return false;
			}
			Piece component = ((Component)c).GetComponent<Piece>();
			if ((Object)(object)component != (Object)null)
			{
				return component.GetCreator() == Game.instance.GetPlayerProfile().GetPlayerID();
			}
			return false;
		}

		private static bool Valid(Container c)
		{
			if ((Object)(object)c == (Object)null)
			{
				return false;
			}
			ZNetView val = View.Invoke(c);
			if ((Object)(object)val != (Object)null)
			{
				return val.IsValid();
			}
			return false;
		}
	}
	internal static class CookTime
	{
		internal static bool Enabled = true;

		private const int NotDone = 0;

		private const int Done = 1;

		private const int Burnt = 2;

		private static readonly FieldRef<CookingStation, ZNetView> CookView = AccessTools.FieldRefAccess<CookingStation, ZNetView>("m_nview");

		private static readonly FieldRef<Fermenter, ZNetView> BarrelView = AccessTools.FieldRefAccess<Fermenter, ZNetView>("m_nview");

		[HarmonyPatch(typeof(CookingStation), "GetHoverText")]
		[HarmonyPostfix]
		private static void CookingLeft(CookingStation __instance, ref string __result)
		{
			try
			{
				if (!Enabled || string.IsNullOrEmpty(__result) || (Object)(object)__instance == (Object)null)
				{
					return;
				}
				ZNetView val = CookView.Invoke(__instance);
				if ((Object)(object)val == (Object)null || !val.IsValid())
				{
					return;
				}
				ZDO zDO = val.GetZDO();
				string text = "";
				for (int i = 0; i < __instance.m_slots.Length; i++)
				{
					string text2 = zDO.GetString("slot" + i, "");
					if (string.IsNullOrEmpty(text2))
					{
						continue;
					}
					int num = zDO.GetInt("slotstatus" + i, 0);
					string text3 = Name(text2);
					switch (num)
					{
					case 2:
						text = text + "\n" + text3 + ": burnt";
						continue;
					case 1:
						text = text + "\n" + text3 + ": ready";
						continue;
					}
					ItemConversion val2 = Conversion(__instance, text2);
					if (val2 != null)
					{
						float seconds = val2.m_cookTime - zDO.GetFloat("slot" + i, 0f);
						text = text + "\n" + text3 + ": ready in " + Spell(seconds);
					}
				}
				if (text.Length > 0)
				{
					__result = Insert(__result, text);
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha no tempo da fogueira: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(Fermenter), "GetHoverText")]
		[HarmonyPostfix]
		private static void FermentingLeft(Fermenter __instance, ref string __result)
		{
			try
			{
				if (!Enabled || string.IsNullOrEmpty(__result) || (Object)(object)__instance == (Object)null || (Object)(object)ZNet.instance == (Object)null)
				{
					return;
				}
				ZNetView val = BarrelView.Invoke(__instance);
				if ((Object)(object)val == (Object)null || !val.IsValid())
				{
					return;
				}
				long num = val.GetZDO().GetLong(ZDOVars.s_startTime, 0L);
				if (num != 0L)
				{
					double totalSeconds = (ZNet.instance.GetTime() - new DateTime(num)).TotalSeconds;
					float num2 = __instance.m_fermentationDuration - (float)totalSeconds;
					if (!(num2 <= 0f))
					{
						__result = Insert(__result, "\nReady in " + Spell(num2));
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha no tempo do fermentador: " + ex.Message));
			}
		}

		private static string Insert(string hover, string lines)
		{
			int num = hover.IndexOf("\n[");
			if (num >= 0)
			{
				return hover.Substring(0, num) + lines + hover.Substring(num);
			}
			return hover + lines;
		}

		private static ItemConversion Conversion(CookingStation station, string itemName)
		{
			foreach (ItemConversion item in station.m_conversion)
			{
				if ((Object)(object)item?.m_from != (Object)null && ((Object)item.m_from).name == itemName)
				{
					return item;
				}
			}
			return null;
		}

		private static string Name(string prefab)
		{
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(prefab) : null);
			ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
			if (!((Object)(object)val2 != (Object)null))
			{
				return prefab;
			}
			return Localization.instance.Localize(val2.m_itemData.m_shared.m_name);
		}

		private static string Spell(float seconds)
		{
			int num = Mathf.Max(0, Mathf.CeilToInt(seconds));
			int num2 = num / 3600;
			int num3 = num % 3600 / 60;
			int num4 = num % 60;
			if (num2 > 0)
			{
				if (num3 <= 0)
				{
					return num2 + "h";
				}
				return num2 + "h " + num3 + "m";
			}
			if (num3 > 0)
			{
				if (num4 <= 0)
				{
					return num3 + "m";
				}
				return num3 + "m " + num4 + "s";
			}
			return num4 + "s";
		}
	}
	internal static class Crafting
	{
		internal static SkillType Skill;

		internal static float MaxDiscount = 0.25f;

		internal static float XpPerCraft = 0.2f;

		internal static bool Enabled = true;

		private static Requirement[] lowered;

		private static int[] originalAmounts;

		private static Player Local => Player.m_localPlayer;

		[HarmonyPatch(typeof(Requirement), "GetAmount")]
		[HarmonyPostfix]
		private static void Discount(ref int __result)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (Enabled && __result > 1 && !((Object)(object)Local == (Object)null))
				{
					float num = 1f - ((Character)Local).GetSkillFactor(Skill) * MaxDiscount;
					__result = Round((float)__result * num);
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha no desconto de criação: " + ex.Message));
			}
		}

		private static int Discounted(int amount)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (amount <= 1 || (Object)(object)Local == (Object)null)
			{
				return amount;
			}
			float num = 1f - ((Character)Local).GetSkillFactor(Skill) * MaxDiscount;
			return Round((float)amount * num);
		}

		[HarmonyPatch(typeof(Player), "HaveRequirements", new Type[]
		{
			typeof(Piece),
			typeof(RequirementMode)
		})]
		[HarmonyPrefix]
		private static void DiscountBuildCheck(Player __instance, Piece piece, RequirementMode mode)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			lowered = null;
			try
			{
				if (!Enabled || (Object)(object)__instance != (Object)(object)Local || (int)mode != 0)
				{
					return;
				}
				Requirement[] array = piece?.m_resources;
				if (array != null && array.Length != 0)
				{
					lowered = array;
					originalAmounts = new int[array.Length];
					for (int i = 0; i < array.Length; i++)
					{
						originalAmounts[i] = array[i].m_amount;
						array[i].m_amount = Discounted(array[i].m_amount);
					}
				}
			}
			catch (Exception ex)
			{
				lowered = null;
				Debug.LogWarning((object)("[QOL KPX] falha no desconto da checagem de construção: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(Player), "HaveRequirements", new Type[]
		{
			typeof(Piece),
			typeof(RequirementMode)
		})]
		[HarmonyFinalizer]
		private static void RestoreBuildCheck()
		{
			Requirement[] array = lowered;
			lowered = null;
			if (array != null)
			{
				for (int i = 0; i < array.Length && i < originalAmounts.Length; i++)
				{
					array[i].m_amount = originalAmounts[i];
				}
			}
		}

		private static int Round(float value)
		{
			return Mathf.Max(1, Mathf.FloorToInt(value + 0.5f));
		}

		private static void Gain()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (Enabled && !((Object)(object)Local == (Object)null))
			{
				((Character)Local).RaiseSkill(Skill, XpPerCraft);
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
		[HarmonyPostfix]
		private static void CraftXp(Player player)
		{
			try
			{
				if ((Object)(object)player == (Object)(object)Local)
				{
					Gain();
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha no XP de criação: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(Player), "GetBuildStamina")]
		[HarmonyPostfix]
		private static void HammerXp(Player __instance)
		{
			try
			{
				if ((Object)(object)__instance == (Object)(object)Local)
				{
					Gain();
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha no XP de martelo: " + ex.Message));
			}
		}
	}
	internal static class Equipment
	{
		internal static readonly ItemType[] Types;

		internal const int Width = 10;

		internal const int Row = 4;

		internal const int FoodCount = 3;

		private static readonly FieldRef<Inventory, int> HeightRef;

		private static readonly FieldRef<Inventory, int> WidthRef;

		private static readonly FieldRef<InventoryGrid, List<InventoryElement>> ElementsRef;

		private static readonly MethodInfo Changed;

		private static readonly object[] ChangedArgs;

		private static bool enabled;

		private static float basePanelWidth;

		private static Vector2 basePanelPos;

		private static bool logged;

		private static readonly Vector3[] PanelCorners;

		private static readonly Vector3[] CellCorners;

		internal static bool Active => enabled;

		internal static int FoodColumn(int i)
		{
			return Types.Length + i;
		}

		private static string IconKey(int k)
		{
			if (k >= Types.Length)
			{
				return "Food";
			}
			return ((object)Unsafe.As<ItemType, ItemType>(ref Types[k])/*cast due to .constrained prefix*/).ToString();
		}

		private static bool IsPlayerInv(Inventory inv)
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null && inv != null)
			{
				return ((Humanoid)Player.m_localPlayer).GetInventory() == inv;
			}
			return false;
		}

		private static int SlotFor(ItemData item)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return Array.IndexOf(Types, item.m_shared.m_itemType);
		}

		internal static bool IsFood(ItemData item)
		{
			SharedData val = item?.m_shared;
			if (val != null)
			{
				if (!(val.m_food > 0f) && !(val.m_foodStamina > 0f))
				{
					return val.m_foodEitr > 0f;
				}
				return true;
			}
			return false;
		}

		internal static void EnsureSize(Inventory inv, bool on)
		{
			enabled = on;
			if (inv != null)
			{
				int num = (on ? 10 : 8);
				int num2 = (on ? 5 : 4);
				if (num < WidthRef.Invoke(inv))
				{
					VacateColumns(inv, num);
				}
				if (WidthRef.Invoke(inv) != num)
				{
					WidthRef.Invoke(inv) = num;
				}
				if (HeightRef.Invoke(inv) != num2)
				{
					HeightRef.Invoke(inv) = num2;
				}
			}
		}

		private static void VacateColumns(Inventory inv, int keep)
		{
			try
			{
				int num = 0;
				foreach (ItemData item in new List<ItemData>(inv.GetAllItems()))
				{
					if (item.m_gridPos.x >= keep && MoveToFreeSlot(inv, item, keep))
					{
						num++;
					}
				}
				if (num > 0)
				{
					Changed?.Invoke(inv, ChangedArgs);
					Debug.Log((object)$"[QOL KPX] {num} item(ns) tirado(s) das colunas que seriam removidas");
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao esvaziar colunas: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(Player), "Load", new Type[] { typeof(ZPackage) })]
		[HarmonyPrefix]
		private static void GrowBeforeLoad(Player __instance)
		{
			try
			{
				if ((Object)(object)__instance != (Object)null)
				{
					EnsureSize(((Humanoid)__instance).GetInventory(), enabled);
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao preparar a mochila antes do load: " + ex.Message));
			}
		}

		internal static void EnsurePanel(bool on, float gap)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: 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_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_0370: Unknown result type (might be due to invalid IL or missing references)
			//IL_0375: Unknown result type (might be due to invalid IL or missing references)
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_playerGrid == (Object)null)
			{
				return;
			}
			RectTransform player = instance.m_player;
			InventoryGrid playerGrid = instance.m_playerGrid;
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			if (basePanelWidth <= 0f)
			{
				basePanelWidth = player.sizeDelta.x;
				basePanelPos = player.anchoredPosition;
			}
			List<InventoryElement> list = ElementsRef.Invoke(playerGrid);
			Inventory inventory = playerGrid.GetInventory();
			int num = ((inventory != null) ? inventory.GetWidth() : 0);
			if (!on || list == null || num == 0 || list.Count < 5 * num)
			{
				instance.SetInventorySize(4);
				player.sizeDelta = new Vector2(basePanelWidth, player.sizeDelta.y);
				player.anchoredPosition = basePanelPos;
				return;
			}
			float elementSpace = playerGrid.m_elementSpace;
			float num2 = (float)(num - 8) * elementSpace;
			instance.SetInventorySize(5);
			player.sizeDelta = new Vector2(basePanelWidth + num2, player.sizeDelta.y + gap);
			for (int i = 0; i < num; i++)
			{
				InventoryElement val = list[4 * num + i];
				InventoryElement val2 = list[3 * num + i];
				if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Transform transform = ((Component)val).transform;
				RectTransform val3 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				Transform transform2 = ((Component)val2).transform;
				RectTransform val4 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null);
				if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val4 == (Object)null))
				{
					val3.anchoredPosition = new Vector2(val4.anchoredPosition.x, val4.anchoredPosition.y - elementSpace - gap);
					if (i < Types.Length + 3)
					{
						SlotIcons.Apply((Transform)(object)val3, IconKey(i));
					}
				}
			}
			if (num >= 10)
			{
				InventoryElement obj = list[9];
				object obj2;
				if (obj == null)
				{
					obj2 = null;
				}
				else
				{
					Transform obj3 = ((Component)obj).transform.Find("binding");
					obj2 = ((obj3 != null) ? ((Component)obj3).GetComponent<TMP_Text>() : null);
				}
				TMP_Text val5 = (TMP_Text)obj2;
				if ((Object)(object)val5 != (Object)null && val5.text != "0")
				{
					val5.text = "0";
				}
			}
			InventoryElement obj4 = list[0];
			Transform obj5 = ((obj4 != null) ? ((Component)obj4).transform : null);
			RectTransform val6 = (RectTransform)(object)((obj5 is RectTransform) ? obj5 : null);
			InventoryElement obj6 = list[num - 1];
			Transform obj7 = ((obj6 != null) ? ((Component)obj6).transform : null);
			RectTransform val7 = (RectTransform)(object)((obj7 is RectTransform) ? obj7 : null);
			Transform obj8 = ((val6 != null) ? ((Transform)val6).parent : null);
			RectTransform val8 = (RectTransform)(object)((obj8 is RectTransform) ? obj8 : null);
			if ((Object)(object)val6 == (Object)null || (Object)(object)val7 == (Object)null || (Object)(object)val8 == (Object)null)
			{
				return;
			}
			player.GetWorldCorners(PanelCorners);
			float x = PanelCorners[0].x;
			float x2 = PanelCorners[2].x;
			val6.GetWorldCorners(CellCorners);
			float x3 = CellCorners[0].x;
			val7.GetWorldCorners(CellCorners);
			float x4 = CellCorners[2].x;
			float num3 = (x + x2) * 0.5f - (x3 + x4) * 0.5f;
			float x5 = ((Transform)val8).InverseTransformVector(new Vector3(num3, 0f, 0f)).x;
			if (Mathf.Abs(x5) > 0.5f)
			{
				foreach (InventoryElement item in list)
				{
					Transform obj9 = ((item != null) ? ((Component)item).transform : null);
					RectTransform val9 = (RectTransform)(object)((obj9 is RectTransform) ? obj9 : null);
					if ((Object)(object)val9 != (Object)null)
					{
						val9.anchoredPosition += new Vector2(x5, 0f);
					}
				}
			}
			if (!logged)
			{
				logged = true;
				Debug.Log((object)($"[QOL KPX-UI] painel=[{x:F1}..{x2:F1}] " + $"grid=[{x3:F1}..{x4:F1}] dx={x5:F1} " + $"tam={player.sizeDelta} space={elementSpace} pivoCelula={val6.pivot}"));
			}
		}

		[HarmonyPatch(typeof(Humanoid), "DropInvalidItems")]
		[HarmonyPrefix]
		private static void GrowBeforeValidation(Humanoid __instance)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				Inventory inventory = __instance.GetInventory();
				EnsureSize(inventory, enabled);
				Rescue(inventory);
			}
		}

		private static void Rescue(Inventory inv)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (inv == null)
				{
					return;
				}
				int width = inv.GetWidth();
				int height = inv.GetHeight();
				int num = 0;
				foreach (ItemData item in new List<ItemData>(inv.GetAllItems()))
				{
					Vector2i gridPos = item.m_gridPos;
					if ((gridPos.x < 0 || gridPos.y < 0 || gridPos.x >= width || gridPos.y >= height) && MoveToFreeSlot(inv, item))
					{
						num++;
					}
				}
				if (num > 0)
				{
					Changed?.Invoke(inv, ChangedArgs);
					Debug.Log((object)$"[QOL KPX] {num} item(ns) fora da grade devolvido(s) à mochila");
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao resgatar itens fora da grade: " + ex.Message));
			}
		}

		private static bool MoveToFreeSlot(Inventory inv, ItemData item, int maxWidth = int.MaxValue)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Min(inv.GetWidth(), maxWidth);
			for (int i = 0; i < 4; i++)
			{
				for (int j = 0; j < num; j++)
				{
					if (inv.GetItemAt(j, i) == null)
					{
						item.m_gridPos = new Vector2i(j, i);
						return true;
					}
				}
			}
			return false;
		}

		[HarmonyPatch(typeof(Inventory), "FindEmptySlot")]
		[HarmonyPostfix]
		private static void KeepRowFree(Inventory __instance, bool __0, ref Vector2i __result)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			if (!IsPlayerInv(__instance) || (__result.x >= 0 && __result.y < 4))
			{
				return;
			}
			__result = new Vector2i(-1, -1);
			int width = __instance.GetWidth();
			for (int i = 0; i < 4; i++)
			{
				int num = (__0 ? i : (3 - i));
				for (int j = 0; j < width; j++)
				{
					if (__instance.GetItemAt(j, num) == null)
					{
						__result = new Vector2i(j, num);
						return;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Inventory), "GetEmptySlots")]
		[HarmonyPostfix]
		private static void FreeSlots(Inventory __instance, ref int __result)
		{
			if (!IsPlayerInv(__instance))
			{
				return;
			}
			for (int i = 0; i < __instance.GetWidth(); i++)
			{
				if (__instance.GetItemAt(i, 4) == null)
				{
					__result--;
				}
			}
		}

		[HarmonyPatch(typeof(Inventory), "HaveEmptySlot")]
		[HarmonyPostfix]
		private static void HaveSlot(Inventory __instance, ref bool __result)
		{
			if (!__result || !IsPlayerInv(__instance))
			{
				return;
			}
			__result = false;
			for (int i = 0; i < 4; i++)
			{
				if (__result)
				{
					break;
				}
				for (int j = 0; j < __instance.GetWidth(); j++)
				{
					if (__result)
					{
						break;
					}
					if (__instance.GetItemAt(j, i) == null)
					{
						__result = true;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Inventory), "CanAddItem", new Type[]
		{
			typeof(ItemData),
			typeof(int)
		})]
		[HarmonyPostfix]
		private static void CanAdd(Inventory __instance, ItemData __0, int __1, ref bool __result)
		{
			if (!__result || __0 == null || !IsPlayerInv(__instance))
			{
				return;
			}
			int num = ((__1 > 0) ? __1 : __0.m_stack);
			int num2 = 0;
			int width = __instance.GetWidth();
			for (int i = 0; i < 4; i++)
			{
				for (int j = 0; j < width; j++)
				{
					if (__instance.GetItemAt(j, i) == null)
					{
						num2++;
					}
				}
			}
			__result = __instance.FindFreeStackSpace(__0.m_shared.m_name, (float)__0.m_worldLevel) + num2 * __0.m_shared.m_maxStackSize >= num;
		}

		[HarmonyPatch(typeof(InventoryGrid), "DropItem")]
		[HarmonyPrefix]
		private static bool GuardDrop(InventoryGrid __instance, ItemData __1, Vector2i __3, ref bool __result)
		{
			//IL_000d: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			if (!IsPlayerInv(__instance.GetInventory()) || __3.y != 4)
			{
				return true;
			}
			if ((__3.x < Types.Length) ? (SlotFor(__1) == __3.x) : IsFood(__1))
			{
				return true;
			}
			__result = false;
			return false;
		}

		[HarmonyPatch(typeof(Humanoid), "EquipItem")]
		[HarmonyPostfix]
		private static void MoveToSlot(Humanoid __instance, ItemData __0, bool __result)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!__result || !enabled || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return;
				}
				int num = SlotFor(__0);
				if (num >= 0)
				{
					Inventory inventory = __instance.GetInventory();
					EnsureSize(inventory, enabled);
					if (inventory.GetItemAt(num, 4) == null)
					{
						__0.m_gridPos = new Vector2i(num, 4);
						Changed?.Invoke(inventory, ChangedArgs);
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao mover para o slot: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(Humanoid), "UnequipItem")]
		[HarmonyPostfix]
		private static void BackToBag(Humanoid __instance, ItemData __0)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!enabled || __0 == null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || __0.m_gridPos.y != 4)
				{
					return;
				}
				Inventory inventory = __instance.GetInventory();
				for (int i = 0; i < 4; i++)
				{
					for (int j = 0; j < inventory.GetWidth(); j++)
					{
						if (inventory.GetItemAt(j, i) == null)
						{
							__0.m_gridPos = new Vector2i(j, i);
							Changed?.Invoke(inventory, ChangedArgs);
							return;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao devolver a peça: " + ex.Message));
			}
		}

		static Equipment()
		{
			ItemType[] array = new ItemType[7];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			Types = (ItemType[])(object)array;
			HeightRef = AccessTools.FieldRefAccess<Inventory, int>("m_height");
			WidthRef = AccessTools.FieldRefAccess<Inventory, int>("m_width");
			ElementsRef = AccessTools.FieldRefAccess<InventoryGrid, List<InventoryElement>>("m_elements");
			Changed = AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null);
			ChangedArgs = new object[2] { false, false };
			enabled = true;
			PanelCorners = (Vector3[])(object)new Vector3[4];
			CellCorners = (Vector3[])(object)new Vector3[4];
		}
	}
	internal static class Exploration
	{
		internal static int NewPixels;

		[HarmonyPatch(typeof(Minimap), "Explore", new Type[]
		{
			typeof(int),
			typeof(int)
		})]
		[HarmonyPostfix]
		private static void Count(bool __result)
		{
			if (__result)
			{
				NewPixels++;
			}
		}
	}
	internal static class ExtraSlots
	{
		internal static bool Enabled = true;

		private static Player Local => Player.m_localPlayer;

		internal static bool CanTakeInput()
		{
			if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus())
			{
				return false;
			}
			if (Console.IsVisible() || TextInput.IsVisible())
			{
				return false;
			}
			if (InventoryGui.IsVisible() || Menu.IsVisible())
			{
				return false;
			}
			return true;
		}

		internal static void Tick()
		{
			try
			{
				if (Enabled && !((Object)(object)Local == (Object)null) && CanTakeInput())
				{
					if (Input.GetKeyDown((KeyCode)57))
					{
						Local.UseHotbarItem(9);
					}
					else if (Input.GetKeyDown((KeyCode)48))
					{
						Local.UseHotbarItem(10);
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha no atalho de poção: " + ex.Message));
			}
		}
	}
	internal static class Fires
	{
		internal static bool Enabled = true;

		[HarmonyPatch(typeof(Fireplace), "UpdateFireplace")]
		[HarmonyPrefix]
		private static void NeverRunOut(Fireplace __instance)
		{
			try
			{
				if (Enabled && (Object)(object)__instance != (Object)null)
				{
					__instance.m_infiniteFuel = true;
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha no combustível infinito: " + ex.Message));
			}
		}
	}
	internal static class FoodDecay
	{
		internal static bool Enabled = true;

		private static readonly FieldRef<Player, List<Food>> FoodsRef = AccessTools.FieldRefAccess<Player, List<Food>>("m_foods");

		private static readonly FieldRef<Player, float> BaseHpRef = AccessTools.FieldRefAccess<Player, float>("m_baseHP");

		private static readonly FieldRef<Player, float> BaseStaminaRef = AccessTools.FieldRefAccess<Player, float>("m_baseStamina");

		private static readonly MethodInfo SetMaxEitrMethod = AccessTools.Method(typeof(Player), "SetMaxEitr", new Type[2]
		{
			typeof(float),
			typeof(bool)
		}, (Type[])null);

		[HarmonyPatch(typeof(Hud), "UpdateFood")]
		[HarmonyPostfix]
		private static void SolidFoodIcons(Hud __instance)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!Enabled || (Object)(object)__instance == (Object)null || __instance.m_foodIcons == null)
				{
					return;
				}
				Image[] foodIcons = __instance.m_foodIcons;
				foreach (Image val in foodIcons)
				{
					if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf)
					{
						((Graphic)val).color = Color.white;
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao fixar o ícone da comida: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(Player), "UpdateFood")]
		[HarmonyPrefix]
		private static void SaveCurrent(Player __instance, out float[] __state)
		{
			__state = ((!((Object)(object)__instance == (Object)(object)Player.m_localPlayer)) ? null : new float[2]
			{
				((Character)__instance).GetHealth(),
				__instance.GetStamina()
			});
		}

		[HarmonyPatch(typeof(Player), "UpdateFood")]
		[HarmonyPostfix]
		private static void KeepFull(Player __instance, float[] __state)
		{
			try
			{
				if (!Enabled || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return;
				}
				List<Food> list = FoodsRef.Invoke(__instance);
				if (list == null || list.Count == 0)
				{
					return;
				}
				float num = BaseHpRef.Invoke(__instance);
				float num2 = BaseStaminaRef.Invoke(__instance);
				float num3 = 0f;
				foreach (Food item in list)
				{
					SharedData shared = item.m_item.m_shared;
					item.m_health = shared.m_food;
					item.m_stamina = shared.m_foodStamina;
					item.m_eitr = shared.m_foodEitr;
					num += item.m_health;
					num2 += item.m_stamina;
					num3 += item.m_eitr;
				}
				__instance.SetMaxHealth(num, false);
				__instance.SetMaxStamina(num2, false);
				SetMaxEitrMethod?.Invoke(__instance, new object[2] { num3, false });
				if (__state != null)
				{
					float num4 = Mathf.Min(__state[0], ((Character)__instance).GetMaxHealth());
					if (((Character)__instance).GetHealth() < num4)
					{
						((Character)__instance).SetHealth(num4);
					}
					float num5 = Mathf.Min(__state[1], ((Character)__instance).GetMaxStamina()) - __instance.GetStamina();
					if (num5 > 0f)
					{
						((Character)__instance).AddStamina(num5);
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha no efeito da comida: " + ex.Message));
			}
		}
	}
	internal static class FoodSlots
	{
		internal static bool Enabled = true;

		private static readonly FieldRef<Player, List<Food>> FoodsRef = AccessTools.FieldRefAccess<Player, List<Food>>("m_foods");

		private static float timer;

		private static bool IsActive(List<Food> foods, ItemData item)
		{
			foreach (Food food in foods)
			{
				if (food.m_item.m_shared.m_name == item.m_shared.m_name)
				{
					return true;
				}
			}
			return false;
		}

		internal static void Tick(float dt)
		{
			try
			{
				Player localPlayer = Player.m_localPlayer;
				if (!Enabled || (Object)(object)localPlayer == (Object)null)
				{
					return;
				}
				timer += dt;
				if (timer < 0.5f)
				{
					return;
				}
				timer = 0f;
				Inventory inventory = ((Humanoid)localPlayer).GetInventory();
				List<Food> list = FoodsRef.Invoke(localPlayer);
				if (inventory == null || list == null)
				{
					return;
				}
				for (int i = 0; i < 3; i++)
				{
					ItemData itemAt = inventory.GetItemAt(Equipment.FoodColumn(i), 4);
					if (itemAt != null && Equipment.IsFood(itemAt) && !IsActive(list, itemAt) && localPlayer.CanEat(itemAt, false))
					{
						((Humanoid)localPlayer).ConsumeItem(inventory, itemAt, false);
						break;
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao comer automaticamente: " + ex.Message));
			}
		}
	}
	internal static class Grave
	{
		internal static bool Enabled = true;

		[HarmonyPatch(typeof(Container), "Awake")]
		[HarmonyPrefix]
		private static void Enlarge(Container __instance)
		{
			try
			{
				if (Enabled && !((Object)(object)__instance == (Object)null) && !((Object)(object)((Component)__instance).GetComponent<TombStone>() == (Object)null))
				{
					if (__instance.m_width < 10)
					{
						__instance.m_width = 10;
					}
					if (__instance.m_height < 5)
					{
						__instance.m_height = 5;
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao dimensionar a lápide: " + ex.Message));
			}
		}
	}
	internal static class Hotbar
	{
		[HarmonyPatch(typeof(HotkeyBar), "UpdateIcons")]
		[HarmonyPostfix]
		private static void TenthKeyIsZero(HotkeyBar __instance)
		{
			try
			{
				if (!Equipment.Active || (Object)(object)__instance == (Object)null)
				{
					return;
				}
				Transform transform = ((Component)__instance).transform;
				if (transform.childCount >= 10)
				{
					Transform obj = transform.GetChild(9).Find("binding");
					TMP_Text val = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null);
					if ((Object)(object)val != (Object)null && val.text == "10")
					{
						val.text = "0";
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha no número do atalho: " + ex.Message));
			}
		}
	}
	internal static class Signs
	{
		internal static bool Enabled = true;

		[HarmonyPatch(typeof(Sign), "GetHoverText")]
		[HarmonyPostfix]
		private static void ShowShift(ref string __result)
		{
			try
			{
				if (Enabled && !string.IsNullOrEmpty(__result) && __result.Contains("$KEY_Use"))
				{
					__result = __result.Replace("$KEY_Use", "Shift + $KEY_Use");
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha no texto da placa: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(Sign), "Interact")]
		[HarmonyPrefix]
		private static bool RequireShift(bool __2, ref bool __result)
		{
			try
			{
				if (!Enabled || __2)
				{
					return true;
				}
				__result = false;
				return false;
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha no atalho da placa: " + ex.Message));
				return true;
			}
		}
	}
	internal static class HammerHover
	{
		internal static bool Enabled = true;

		private static bool inHoverCheck;

		[HarmonyPatch(typeof(Player), "UpdateHover")]
		[HarmonyPrefix]
		private static void OpenWindow()
		{
			inHoverCheck = Enabled;
		}

		[HarmonyPatch(typeof(Player), "UpdateHover")]
		[HarmonyPostfix]
		private static void CloseWindow()
		{
			inHoverCheck = false;
		}

		[HarmonyPatch(typeof(Player), "InPlaceMode")]
		[HarmonyPostfix]
		private static void PretendNotBuilding(ref bool __result)
		{
			if (inHoverCheck)
			{
				__result = false;
			}
		}
	}
	internal static class Intro
	{
		internal static bool Enabled = true;

		[HarmonyPatch(typeof(CinematicsManager), "Awake")]
		[HarmonyPostfix]
		private static void SkipStartupVideo(CinematicsManager __instance)
		{
			try
			{
				if (Enabled && (Object)(object)__instance != (Object)null)
				{
					__instance.m_introOnStartup = false;
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao pular o vídeo de abertura: " + ex.Message));
			}
		}
	}
	internal static class KeepAchievements
	{
		internal static bool Enabled = true;

		private static bool restore;

		[HarmonyPatch(typeof(Achievements), "IsCheatedAtAll")]
		[HarmonyPrefix]
		private static void HideModdedFlag()
		{
			restore = false;
			try
			{
				if (Enabled && Game.isModded)
				{
					Game.isModded = false;
					restore = true;
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao manter achievements: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(Achievements), "IsCheatedAtAll")]
		[HarmonyFinalizer]
		private static void RestoreModdedFlag()
		{
			if (restore)
			{
				Game.isModded = true;
			}
			restore = false;
		}
	}
	internal static class MapShare
	{
		internal static bool Enabled = true;

		private const string RpcCells = "QolKpx_MapCells";

		private const string RpcFull = "QolKpx_MapFull";

		private const string RpcAsk = "QolKpx_MapAsk";

		private const float SendInterval = 2f;

		private const float JoinDelay = 5f;

		private const float SaveInterval = 30f;

		private static readonly FieldRef<Minimap, BitArray> ExploredRef = AccessTools.FieldRefAccess<Minimap, BitArray>("m_explored");

		private static readonly FieldRef<Minimap, BitArray> OthersRef = AccessTools.FieldRefAccess<Minimap, BitArray>("m_exploredOthers");

		private static readonly FieldRef<Minimap, Texture2D> FogRef = AccessTools.FieldRefAccess<Minimap, Texture2D>("m_fogTexture");

		private static readonly Func<Minimap, int, int, bool> ExploreOthers = AccessTools.MethodDelegate<Func<Minimap, int, int, bool>>(AccessTools.Method(typeof(Minimap), "ExploreOthers", new Type[2]
		{
			typeof(int),
			typeof(int)
		}, (Type[])null), (object)null, true);

		private static BitArray world;

		private static int worldSize;

		private static bool worldDirty;

		private static float saveTimer;

		private static string tag;

		private static readonly List<int> pending = new List<int>();

		private static bool live;

		private static float sendTimer;

		private static float joinTimer;

		private static ZRoutedRpc registeredOn;

		private static Player announcedFor;

		private static string WorldFile => Path.Combine(Paths.ConfigPath, "qol.kpx." + tag + ".map");

		private static bool OnServer
		{
			get
			{
				if ((Object)(object)ZNet.instance != (Object)null)
				{
					return ZNet.instance.IsServer();
				}
				return false;
			}
		}

		internal static string WorldTag()
		{
			ZNet instance = ZNet.instance;
			long num = (((Object)(object)instance != (Object)null) ? instance.GetWorldUID() : 0);
			if (num == 0L)
			{
				return "unknown";
			}
			return num.ToString();
		}

		[HarmonyPatch(typeof(Minimap), "Explore", new Type[]
		{
			typeof(Vector3),
			typeof(float)
		})]
		[HarmonyPrefix]
		private static void OpenWindow()
		{
			live = Enabled;
		}

		[HarmonyPatch(typeof(Minimap), "Explore", new Type[]
		{
			typeof(Vector3),
			typeof(float)
		})]
		[HarmonyFinalizer]
		private static void CloseWindow()
		{
			live = false;
		}

		[HarmonyPatch(typeof(Minimap), "Explore", new Type[]
		{
			typeof(int),
			typeof(int)
		})]
		[HarmonyPostfix]
		private static void Record(Minimap __instance, int __0, int __1, bool __result)
		{
			if (live && __result)
			{
				pending.Add(__1 * __instance.m_textureSize + __0);
			}
		}

		internal static void Tick(float dt)
		{
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Expected O, but got Unknown
			try
			{
				ZRoutedRpc instance = ZRoutedRpc.instance;
				if (!Enabled || instance == null)
				{
					return;
				}
				if (registeredOn != instance)
				{
					instance.Register<ZPackage>("QolKpx_MapCells", (Action<long, ZPackage>)OnCells);
					instance.Register<ZPackage>("QolKpx_MapFull", (Action<long, ZPackage>)OnFull);
					instance.Register("QolKpx_MapAsk", (Action<long>)OnAsk);
					registeredOn = instance;
					PortalPins.Register(instance);
				}
				string text = WorldTag();
				if (tag != text)
				{
					if (tag != null && worldDirty && world != null)
					{
						SaveWorld();
					}
					tag = text;
					world = null;
					worldSize = 0;
					worldDirty = false;
					live = false;
					pending.Clear();
					announcedFor = null;
					joinTimer = 0f;
					if (OnServer)
					{
						LoadWorld();
					}
					PortalPins.NewWorld(text);
				}
				if (OnServer)
				{
					saveTimer += dt;
					if (saveTimer >= 30f)
					{
						if (worldDirty)
						{
							SaveWorld();
						}
						PortalPins.Tick();
					}
				}
				Minimap instance2 = Minimap.instance;
				if ((Object)(object)instance2 == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
				{
					announcedFor = null;
					joinTimer = 0f;
					pending.Clear();
					return;
				}
				if ((Object)(object)announcedFor != (Object)(object)Player.m_localPlayer)
				{
					joinTimer += dt;
					if (joinTimer < 5f)
					{
						return;
					}
					announcedFor = Player.m_localPlayer;
					joinTimer = 0f;
					instance.InvokeRoutedRPC(0L, "QolKpx_MapFull", new object[1] { PackFull(instance2) });
					instance.InvokeRoutedRPC(0L, "QolKpx_MapAsk", Array.Empty<object>());
				}
				sendTimer += dt;
				if (sendTimer < 2f || pending.Count == 0)
				{
					return;
				}
				sendTimer = 0f;
				ZPackage val = new ZPackage();
				val.Write(instance2.m_textureSize);
				val.Write(pending.Count);
				foreach (int item in pending)
				{
					val.Write(item);
				}
				if (OnServer)
				{
					MergeWorld(instance2.m_textureSize, pending);
				}
				pending.Clear();
				instance.InvokeRoutedRPC(0L, "QolKpx_MapCells", new object[1] { val });
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao compartilhar o mapa: " + ex.Message));
			}
		}

		private static void OnAsk(long sender)
		{
			try
			{
				if (!Enabled || ZRoutedRpc.instance == null)
				{
					return;
				}
				if (OnServer)
				{
					if (world != null)
					{
						ZRoutedRpc.instance.InvokeRoutedRPC(sender, "QolKpx_MapFull", new object[1] { PackRuns(world, worldSize) });
					}
					PortalPins.SendAllTo(sender);
				}
				else if ((Object)(object)Minimap.instance != (Object)null)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(sender, "QolKpx_MapFull", new object[1] { PackFull(Minimap.instance) });
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao responder o mapa: " + ex.Message));
			}
		}

		private static void OnCells(long sender, ZPackage pkg)
		{
			try
			{
				if (Enabled)
				{
					int num = pkg.ReadInt();
					int num2 = pkg.ReadInt();
					List<int> list = new List<int>(num2);
					for (int i = 0; i < num2; i++)
					{
						list.Add(pkg.ReadInt());
					}
					if (OnServer)
					{
						MergeWorld(num, list);
					}
					Minimap instance = Minimap.instance;
					if ((Object)(object)instance != (Object)null && num == instance.m_textureSize)
					{
						Apply(instance, list);
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao receber células do mapa: " + ex.Message));
			}
		}

		private static void OnFull(long sender, ZPackage pkg)
		{
			try
			{
				if (Enabled)
				{
					int num = pkg.ReadInt();
					List<int> cells = new List<int>(UnpackRuns(pkg));
					if (OnServer)
					{
						MergeWorld(num, cells);
					}
					Minimap instance = Minimap.instance;
					if ((Object)(object)instance != (Object)null && num == instance.m_textureSize)
					{
						Apply(instance, cells);
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao receber o mapa: " + ex.Message));
			}
		}

		private static void Apply(Minimap map, IEnumerable<int> cells)
		{
			BitArray bitArray = ExploredRef.Invoke(map);
			BitArray bitArray2 = OthersRef.Invoke(map);
			if (bitArray == null || bitArray2 == null)
			{
				return;
			}
			int textureSize = map.m_textureSize;
			bool flag = false;
			foreach (int cell in cells)
			{
				if (cell >= 0 && cell < bitArray.Length && !bitArray[cell] && !bitArray2[cell] && ExploreOthers(map, cell % textureSize, cell / textureSize))
				{
					flag = true;
				}
			}
			if (flag)
			{
				FogRef.Invoke(map).Apply();
			}
		}

		private static ZPackage PackFull(Minimap map)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			BitArray bitArray = ExploredRef.Invoke(map);
			BitArray bitArray2 = OthersRef.Invoke(map);
			List<int> list = new List<int>();
			bool flag = false;
			int num = 0;
			for (int i = 0; i < bitArray.Length; i++)
			{
				bool flag2 = bitArray[i] || bitArray2[i];
				if (flag2 == flag)
				{
					num++;
					continue;
				}
				list.Add(num);
				flag = flag2;
				num = 1;
			}
			list.Add(num);
			ZPackage val = new ZPackage();
			val.Write(map.m_textureSize);
			val.Write(list.Count);
			foreach (int item in list)
			{
				val.Write(item);
			}
			return val;
		}

		private static ZPackage PackRuns(BitArray bits, int size)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			List<int> list = new List<int>();
			bool flag = false;
			int num = 0;
			for (int i = 0; i < bits.Length; i++)
			{
				if (bits[i] == flag)
				{
					num++;
					continue;
				}
				list.Add(num);
				flag = bits[i];
				num = 1;
			}
			list.Add(num);
			ZPackage val = new ZPackage();
			val.Write(size);
			val.Write(list.Count);
			foreach (int item in list)
			{
				val.Write(item);
			}
			return val;
		}

		private static void MergeWorld(int size, IEnumerable<int> cells)
		{
			if (size <= 0 || size > 8192)
			{
				return;
			}
			if (world == null)
			{
				world = new BitArray(size * size);
				worldSize = size;
			}
			if (size != worldSize)
			{
				return;
			}
			foreach (int cell in cells)
			{
				if (cell >= 0 && cell < world.Length && !world[cell])
				{
					world[cell] = true;
					worldDirty = true;
				}
			}
		}

		private static void LoadWorld()
		{
			try
			{
				if (File.Exists(WorldFile))
				{
					byte[] array = File.ReadAllBytes(WorldFile);
					if (array.Length >= 4)
					{
						worldSize = BitConverter.ToInt32(array, 0);
						byte[] array2 = new byte[array.Length - 4];
						Array.Copy(array, 4, array2, 0, array2.Length);
						world = new BitArray(array2)
						{
							Length = worldSize * worldSize
						};
						Debug.Log((object)$"[QOL KPX] mapa do mundo {tag} carregado ({worldSize}x{worldSize})");
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao ler o mapa do mundo: " + ex.Message));
			}
		}

		private static void SaveWorld()
		{
			try
			{
				saveTimer = 0f;
				worldDirty = false;
				if (world != null)
				{
					byte[] array = new byte[(world.Length + 7) / 8];
					world.CopyTo(array, 0);
					byte[] array2 = new byte[array.Length + 4];
					Buffer.BlockCopy(BitConverter.GetBytes(worldSize), 0, array2, 0, 4);
					Buffer.BlockCopy(array, 0, array2, 4, array.Length);
					File.WriteAllBytes(WorldFile, array2);
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha ao gravar o mapa do mundo: " + ex.Message));
			}
		}

		private static IEnumerable<int> UnpackRuns(ZPackage pkg)
		{
			int count = pkg.ReadInt();
			int pos = 0;
			for (int k = 0; k < count; k++)
			{
				int run = pkg.ReadInt();
				if (k % 2 == 1)
				{
					for (int j = 0; j < run; j++)
					{
						yield return pos + j;
					}
				}
				pos += run;
			}
		}
	}
	internal static class Mining
	{
		internal static SkillType Skill;

		internal static float MaxDamageBonus = 1f;

		internal static float TierWeight = 0.25f;

		internal static float XpPerHit = 1f;

		internal static bool Enabled = true;

		private static Player Local => Player.m_localPlayer;

		internal static float OneShotChance(float factor)
		{
			return factor * 0.1f + factor * factor * factor * 0.05f;
		}

		private static void Boost(HitData hit, int minToolTier, bool supportsRadius)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			if (!Enabled || hit == null || (Object)(object)Local == (Object)null || (Object)(object)hit.GetAttacker() != (Object)(object)Local || hit.m_damage.m_pickaxe <= 0f || !hit.CheckToolTier(minToolTier, false))
			{
				return;
			}
			float skillFactor = ((Character)Local).GetSkillFactor(Skill);
			hit.m_damage.m_pickaxe *= 1f + skillFactor * MaxDamageBonus * (1f + (float)hit.m_toolTier * TierWeight);
			if (Random.value < OneShotChance(skillFactor))
			{
				hit.m_damage.m_pickaxe *= 1000f;
				if (supportsRadius)
				{
					hit.m_radius = Mathf.Max(hit.m_radius, 8f);
				}
				((Character)Local).Message((MessageType)1, "Vein shattered!", 0, (Sprite)null, false);
			}
			((Character)Local).RaiseSkill(Skill, XpPerHit);
			Strength.Effort();
		}

		[HarmonyPatch(typeof(MineRock5), "Damage")]
		[HarmonyPrefix]
		private static void Rock5(MineRock5 __instance, HitData __0)
		{
			Safe(delegate
			{
				Boost(__0, __instance.m_minToolTier, supportsRadius: true);
			});
		}

		[HarmonyPatch(typeof(MineRock), "Damage")]
		[HarmonyPrefix]
		private static void Rock(MineRock __instance, HitData __0)
		{
			Safe(delegate
			{
				Boost(__0, __instance.m_minToolTier, supportsRadius: false);
			});
		}

		private static void Safe(Action a)
		{
			try
			{
				a();
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha no bônus de mineração: " + ex.Message));
			}
		}
	}
	internal static class PingText
	{
		internal static string Pending;

		internal static bool Beam = true;

		internal static float BeamHeight = 500f;

		internal static float BeamSeconds = 0f;

		internal static float BeamWidth = 0.3f;

		private static bool warned;

		[HarmonyPatch(typeof(Chat), "AddInworldText")]
		[HarmonyPostfix]
		private static void OnPing(Chat __instance, object[] __args)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Invalid comparison between Unknown and I4
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (__args == null || __args.Length < 4 || !(__args[3] is Type val) || (int)val != 3)
				{
					return;
				}
				if (!string.IsNullOrEmpty(Pending))
				{
					List<WorldTextInstance> worldTexts = __instance.WorldTexts;
					if (worldTexts != null && worldTexts.Count > 0)
					{
						WorldTextInstance val2 = worldTexts[worldTexts.Count - 1];
						val2.m_text = Pending;
						if ((Object)(object)val2.m_textMeshField != (Object)null)
						{
							((TMP_Text)val2.m_textMeshField).text = val2.m_name + ": " + Pending;
						}
					}
					Pending = null;
				}
				if (__args[2] is Vector3 position)
				{
					ShowBeam(position);
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha no texto do ping: " + ex.Message));
			}
		}

		internal static void ShowBeam(Vector3 position)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (Beam && !((Object)(object)Plugin.Host == (Object)null))
				{
					Plugin.Host.StartCoroutine(BeamRoutine(position));
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[QOL KPX] falha no feixe do ping: " + ex.Message));
			}
		}

		private static IEnumerator BeamRoutine(Vector3 position)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			Shader val = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color") ?? Shader.Find("UI/Default") ?? Shader.Find("Particles/Standard Unlit");
			if ((Object)(object)val == (Object)null)
			{
				if (!warned)
				{
					warned = true;
					Debug.LogWarning((object)"[QOL KPX] nenhum shader para o feixe do ping");
				}
				yield break;
			}
			float life = ((BeamSeconds > 0f) ? BeamSeconds : (((Object)(object)Chat.instance != (Object)null) ? Chat.instance.m_worldTextTTL : 5f));
			GameObject go = new GameObject("qolkpx_ping_beam");
			go.transform.position = position;
			LineRenderer line = go.AddComponent<LineRenderer>();
			line.useWorldSpace = true;
			line.positionCount = 2;
			line.SetPosition(0, position);
			line.SetPosition(1, position + Vector3.up * BeamHeight);
			line.startWidth = BeamWidth;
			line.endWidth = BeamWidth;
			((Renderer)line).material = new Material(val);
			((Renderer)line).material.color = Color.white;
			line.startColor = new Color(1f, 1f, 1f, 0.9f);
			line.endColor = new Color(1f, 1f, 1f, 0.1f);
			float total = life;
			while (life > 0f && (Object)(object)go != (Object)null)
			{
				life -= Time.deltaTime;
				if ((Object)(object)line != (Object)null && (Object)(object)((Renderer)line).material != (Object)null)
				{
					((Renderer)line).material.color = new Color(1f, 1f, 1f, Mathf.Clamp01(life / total));
				}
				yield return null;
			}
			if ((Object)(object)go != (Object)null)
			{
				Object.Destroy((Object)(object)go);
			}
		}
	}
	[BepInPlugin("qol.kpx", "QOL KPX", "2.3.0")]
	public class Plugin : BaseUnityPlugin
	{
		private static class Repair
		{
			internal static readonly MethodInfo RepairOne = AccessTools.Method(typeof(InventoryGui), "RepairOneItem", (Type[])null, (Type[])null);

			internal static readonly MethodInfo HaveRepairable = AccessTools.Method(typeof(InventoryGui), "HaveRepairableItems", (Type[])null, (Type[])null);

			[HarmonyPatch(typeof(InventoryGui), "UpdateRepair")]
			[HarmonyPostfix]
			private static void RepairAll(InventoryGui __instance)
			{
				if (!autoRepair.Value)
				{
					return;
				}
				for (int i = 0; i < 64; i++)
				{
					if (!(bool)HaveRepairable.Invoke(__instance, null))
					{
						break;
					}
					RepairOne.Invoke(__instance, null);
				}
			}
		}

		private static class Float
		{
			private static int added;

			[HarmonyPatch(typeof(ObjectDB), "Awake")]
			[HarmonyPostfix]
			[HarmonyPriority(200)]
			private static void OnDbAwake(ObjectDB __instance)
			{
				ApplyAll(__instance);
			}

			[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
			[HarmonyPostfix]
			[HarmonyPriority(200)]
			private static void OnDbCopied(ObjectDB __instance)
			{
				ApplyAll(__instance);
			}

			private static void ApplyAll(ObjectDB db)
			{
				//IL_0082: Unknown result type (might be due to invalid IL or missing references)
				//IL_0087: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					if (!floatItems.Value || db?.m_items == null)
					{
						return;
					}
					added = 0;
					foreach (GameObject item in db.m_items)
					{
						if (!((Object)(object)item == (Object)null) && !((Object)(object)item.GetComponent<Floating>() != (Object)null))
						{
							Rigidbody component = item.GetComponent<Rigidbody>();
							if (!((Object)(object)component == (Object)null) && !((Object)(object)item.GetComponentInChildren<Collider>() == (Object)null))
							{
								item.AddComponent<Floating>().m_waterLevelOffset = 0.7f;
								component.centerOfMass = Normalize(component.centerOfMass);
								added++;
							}
						}
					}
					if (added > 0)
					{
						Debug.Log((object)$"[QOL KPX] {added} itens passam a boiar");
					}
				}
				catch (Exception ex)
				{
					Debug.LogWarning((object)("[QOL KPX] falha ao fazer os itens boiarem: " + ex.Message));
				}
			}

			private static Vector3 Normalize(Vector3 mass)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				if (mass.x < -1f)
				{
					mass.x = 0f;
				}
				if (mass.y < -1f)
				{
					mass.y = 0f;
				}
				if (mass.z < -1f)
				{
					mass.z = 0f;
				}
				return mass;
			}
		}

		private const SkillType Skill = (SkillType)715293104;

		private const SkillType ExploreSkill = (SkillType)715293105;

		private const SkillType MiningSkill = (SkillType)715293106;

		private const SkillType VitalitySkill = (SkillType)715293107;

		private const SkillType WoodSkill = (SkillType)715293108;

		private const SkillType CraftSkill = (SkillType)715293109;

		private const SkillType StrengthSkill = (SkillType)715293110;

		private static ConfigEntry<float> xpRate;

		private static ConfigEntry<float> maxSpeed;

		private static ConfigEntry<float> maxJump;

		private static ConfigEntry<float> maxFall;

		private static ConfigEntry<bool> autoRepair;

		private static ConfigEntry<bool> clockEnabled;

		private static ConfigEntry<bool> floatItems;

		private static ConfigEntry<bool> equipSlots;

		private static ConfigEntry<bool> exploreEnabled;

		private static ConfigEntry<bool> miningEnabled;

		private static ConfigEntry<int> portalPinIcon;

		private static ConfigEntry<string> charcoalWeights;

		private static ConfigEntry<int> kilnCapacity;

		private static ConfigEntry<float> shipPerPlayer;

		private static ConfigEntry<float> furnaceEfficiency;

		private static ConfigEntry<float> bronzeRatio;

		private static ConfigEntry<int> smelterWidth;

		private static ConfigEntry<int> smelterRows;

		private static ConfigEntry<int> capeLevel;

		private static ConfigEntry<int> capeResin;

		private static ConfigEntry<float> clockOffset;

		private static ConfigEntry<float> clockSize;

		private static ConfigEntry<float> maxRadius;

		private static ConfigEntry<float> xpPerPixel;

		private static ConfigEntry<float> foodGap;

		private static ConfigEntry<float> slotIconAlpha;

		private static ConfigEntry<float> miningBonus;

		private static ConfigEntry<float> miningTierWeight;

		private static ConfigEntry<float> miningXp;

		private static ConfigEntry<bool> vitalityEnabled;

		private static ConfigEntry<bool> buildNoStamina;

		private static ConfigEntry<bool> buildNoWear;

		private static ConfigEntry<bool> woodEnabled;

		private static ConfigEntry<bool> buildNoMoveStamina;

		private static ConfigEntry<float> woodBonus;

		private static ConfigEntry<float> woodTierWeight;

		private static ConfigEntry<float> woodXp;

		private static ConfigEntry<bool> archeryEnabled;

		private static ConfigEntry<bool> craftEnabled;

		private static ConfigEntry<bool> strengthEnabled;

		private static ConfigEntry<bool> foodNoDecay;

		private static ConfigEntry<bool> foodAutoEat;

		private static ConfigEntry<bool> restedEnabled;

		private static ConfigEntry<bool> firesEnabled;

		private static ConfigEntry<bool> extraSlots;

		private static ConfigEntry<bool> teleportAll;

		private static ConfigEntry<bool> introSkip;

		private static ConfigEntry<bool> shipEnabled;

		private static ConfigEntry<bool> furnaceEnabled;

		private static ConfigEntry<bool> signShift;

		private static ConfigEntry<bool> hoverBuildTool;

		private static ConfigEntry<bool> swimKeepGear;

		private static ConfigEntry<bool> slotIcons;

		private static ConfigEntry<bool> keepAchievements;

		private static ConfigEntry<bool> pingEnabled;

		private static ConfigEntry<bool> mapShare;

		private static ConfigEntry<bool> serverConfig;

		private static ConfigEntry<bool> portalPins;

		private static ConfigEntry<bool> charcoal;

		private static ConfigEntry<bool> smelterBox;

		private static ConfigEntry<bool> trollCape;

		private static ConfigEntry<bool> bronze;

		private static ConfigEntry<KeyboardShortcut> pingKey;

		private static ConfigEntry<KeyboardShortcut> pingForceKey;

		private static ConfigEntry<bool> pingShowName;

		private static ConfigEntry<bool> pingBeam;

		private static ConfigEntry<bool> freeMovement;

		private static ConfigEntry<float> terrainLimit;

		private static ConfigEntry<float> buildSupport;

		private static ConfigEntry<float> stubHealth;

		private static ConfigEntry<bool> stubsEnabled;

		private static ConfigEntry<bool> quickStack;

		private static ConfigEntry<bool> quickStackMerge;

		private static ConfigEntry<bool> showStock;

		private static ConfigEntry<bool> cookTime;

		private static ConfigEntry<bool> tarEnabled;

		private static ConfigEntry<bool> buildEnabled;

		private static ConfigEntry<bool> chestCrafting;

		private static ConfigEntry<float> pingBeamHeight;

		private static ConfigEntry<float> pingBeamSeconds;

		private static ConfigEntry<float> pingPinRange;

		private static ConfigEntry<float> pingDistance;

		private static ConfigEntry<float> restedMinutes;

		private static ConfigEntry<float> strengthBonus;

		private static ConfigEntry<float> strengthXpEffort;

		private static ConfigEntry<float> strengthXpLoad;

		private static ConfigEntry<float> strengthLoad;

		private static ConfigEntry<float> craftDiscount;

		private static ConfigEntry<float> craftXp;

		private static ConfigEntry<float> archeryStamina;

		private static ConfigEntry<float> archeryAccuracy;

		private static ConfigEntry<float> vitalityBonus;

		private static ConfigEntry<float> vitalityXp;

		private static ConfigEntry<float> vitalityStamina;

		internal static ConfigFile Cfg;

		internal static MonoBehaviour Host;

		private Player player;

		private float walk;

		private float jog;

		private float run;

		private float jump;

		private float baseRadius;

		private TMP_Text clock;

		internal static Action ApplyConfig;

		private void ApplyConfigValues()
		{
			ExtraSlots.Enabled = extraSlots.Value;
			SlotIcons.Enabled = slotIcons.Value;
			SlotIcons.Alpha = slotIconAlpha.Value;
			Mining.Enabled = miningEnabled.Value;
			Mining.MaxDamageBonus = miningBonus.Value;
			Mining.TierWeight = miningTierWeight.Value;
			Mining.XpPerHit = miningXp.Value;
			Vitality.Enabled = vitalityEnabled.Value;
			Vitality.MaxHealthBonus = vitalityBonus.Value;
			Vitality.MaxStaminaBonus = vitalityStamina.Value;
			Vitality.XpPerHealth = vitalityXp.Value;
			Strength.Enabled = strengthEnabled.Value;
			Strength.MaxBonus = strengthBonus.Value;
			Strength.XpPerEffort = strengthXpEffort.Value;
			Strength.XpPerSecond = strengthXpLoad.Value;
			Strength.LoadThreshold = strengthLoad.Value;
			Crafting.Enabled = craftEnabled.Value;
			Crafting.MaxDiscount = craftDiscount.Value;
			Crafting.XpPerCraft = craftXp.Value;
			Rested.Enabled = restedEnabled.Value;
			Rested.MinutesPerLevel = restedMinutes.Value;
			Fires.Enabled = firesEnabled.Value;
			Teleport.Enabled = teleportAll.Value;
			Intro.Enabled = introSkip.Value;
			Signs.Enabled = signShift.Value;
			HammerHover.Enabled = hoverBuildTool.Value;
			Swim.Enabled = swimKeepGear.Value;
			KeepAchievements.Enabled = keepAchievements.Value;
			QuickPing.Enabled = pingEnabled.Value;
			QuickPing.MaxDistance = pingDistance.Value;
			QuickPing.ShowName = pingShowName.Value;
			Building.Enabled = buildEnabled.Value;
			Building.Multiplier = buildSupport.Value;
			ChestCrafting.Enabled = chestCrafting.Value;
			Terrain.Limit = terrainLimit.Value;
			Stubs.Enabled = stubsEnabled.Value;
			Tar.Enabled = tarEnabled.Value;
			Stubs.Health = stubHealth.Value;
			QuickStack.Enabled = quickStack.Value;
			QuickStack.Merge = quickStackMerge.Value;
			Requirements.Enabled = showStock.Value;
			CookTime.Enabled = cookTime.Value;
			Stamina.FreeMovement = freeMovement.Value;
			PingText.Beam = pingBeam.Value;
			PingText.BeamHeight = pingBeamHeight.Value;
			PingText.BeamSeconds = pingBeamSeconds.Value;
			QuickPing.PinRange = pingPinRange.Value;
			MapShare.Enabled = mapShare.Value;
			Bronze.Enabled = bronze.Value;
			Bronze.Ratio = bronzeRatio.Value;
			TrollCape.Enabled = trollCape.Value;
			TrollCape.Level = capeLevel.Value;
			TrollCape.ResinCost = capeResin.Value;
			SmelterBox.Enabled = smelterBox.Value;
			SmelterBox.Width = smelterWid