Decompiled source of ChallengeHub BlutEid v2.12.71

BepInEx\patchers\ChallengeHub.Valheim10Compat\ChallengeHub.Valheim10Compat.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Mono.Cecil;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.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 ChallengeHubValheim10Compat
{
	public static class Valheim10CompatPatcher
	{
		private static readonly ManualLogSource Log = Logger.CreateLogSource("ChallengeHub Valheim 1.0 Compat");

		private static bool _patched;

		public static IEnumerable<string> TargetDLLs { get; } = new string[1] { "assembly_valheim.dll" };

		public static void Initialize()
		{
		}

		public static void Patch(AssemblyDefinition assembly)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			if (assembly != null && assembly.MainModule != null)
			{
				TypeDefinition? obj = ((IEnumerable<TypeDefinition>)assembly.MainModule.Types).FirstOrDefault((Func<TypeDefinition, bool>)((TypeDefinition type) => string.Equals(((MemberReference)type).Name, "ZRoutedRpc", StringComparison.Ordinal)));
				FieldDefinition val = ((obj != null) ? ((IEnumerable<FieldDefinition>)obj.Fields).FirstOrDefault((Func<FieldDefinition, bool>)((FieldDefinition field) => string.Equals(((MemberReference)field).Name, "Everybody", StringComparison.Ordinal) && ((FieldReference)field).FieldType != null && (int)((FieldReference)field).FieldType.MetadataType == 10)) : null);
				if (val != null && val.IsLiteral)
				{
					val.Attributes = (FieldAttributes)(val.Attributes & 0xFFBF);
					val.Attributes = (FieldAttributes)(val.Attributes & 0x7FFF);
					val.Attributes = (FieldAttributes)(val.Attributes | 0x10);
					val.Constant = null;
					_patched = true;
				}
			}
		}

		public static void Finish()
		{
			if (_patched)
			{
				Log.LogInfo((object)"Valheim-1.0-RPC-Kompatibilitaet fuer AzuAntiCheat 4.3.11 aktiviert.");
			}
		}
	}
}

BepInEx\plugins\ChallengeHubValheim.BlutEid\ChallengeHub.Valheim10Compat.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Mono.Cecil;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.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 ChallengeHubValheim10Compat
{
	public static class Valheim10CompatPatcher
	{
		private static readonly ManualLogSource Log = Logger.CreateLogSource("ChallengeHub Valheim 1.0 Compat");

		private static bool _patched;

		public static IEnumerable<string> TargetDLLs { get; } = new string[1] { "assembly_valheim.dll" };

		public static void Initialize()
		{
		}

		public static void Patch(AssemblyDefinition assembly)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			if (assembly != null && assembly.MainModule != null)
			{
				TypeDefinition? obj = ((IEnumerable<TypeDefinition>)assembly.MainModule.Types).FirstOrDefault((Func<TypeDefinition, bool>)((TypeDefinition type) => string.Equals(((MemberReference)type).Name, "ZRoutedRpc", StringComparison.Ordinal)));
				FieldDefinition val = ((obj != null) ? ((IEnumerable<FieldDefinition>)obj.Fields).FirstOrDefault((Func<FieldDefinition, bool>)((FieldDefinition field) => string.Equals(((MemberReference)field).Name, "Everybody", StringComparison.Ordinal) && ((FieldReference)field).FieldType != null && (int)((FieldReference)field).FieldType.MetadataType == 10)) : null);
				if (val != null && val.IsLiteral)
				{
					val.Attributes = (FieldAttributes)(val.Attributes & 0xFFBF);
					val.Attributes = (FieldAttributes)(val.Attributes & 0x7FFF);
					val.Attributes = (FieldAttributes)(val.Attributes | 0x10);
					val.Constant = null;
					_patched = true;
				}
			}
		}

		public static void Finish()
		{
			if (_patched)
			{
				Log.LogInfo((object)"Valheim-1.0-RPC-Kompatibilitaet fuer AzuAntiCheat 4.3.11 aktiviert.");
			}
		}
	}
}

BepInEx\plugins\ChallengeHubValheim.BlutEid\ChallengeHubValheim.BlutEid.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net.WebSockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Splatform;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyMetadata("ChallengeHub.Product", "BlutEid")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.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 ChallengeHubValheim
{
	internal static class AdvancedQoLFeature
	{
		private sealed class ContainerOwnershipLease
		{
			internal ZDO Zdo;

			internal long OriginalOwner;

			internal bool Claimed;
		}

		internal sealed class SwimOverviewData
		{
			internal int Seconds;

			internal int EfficiencyPercent;

			internal int SafeGroundMeters;

			internal bool SafeGroundKnown;

			internal bool Critical;
		}

		private static Plugin _plugin;

		private static AdvancedQoLBehaviour _behaviour;

		private static ConfigEntry<float> _harvestRadius;

		private static ConfigEntry<int> _harvestMaxTargets;

		private static ConfigEntry<int> _maxGridSize;

		private static ConfigEntry<float> _doorCloseDelay;

		private static ConfigEntry<float> _doorSafetyRadius;

		private static ConfigEntry<float> _fuelContainerRadius;

		private static ConfigEntry<int> _storageMaxContainers;

		private static ConfigEntry<int> _signMaxFontSize;

		private static readonly float[] RotationSteps = new float[6] { 1f, 5f, 15f, 22.5f, 45f, 90f };

		private const string ContainerLockOwnerKey = "ChallengeHub.QoL.LockOwner";

		private const string ContainerLockUntilKey = "ChallengeHub.QoL.LockUntil";

		internal static float HarvestRadius
		{
			get
			{
				QoLWebConfig qoLWebConfig = RemoteQol();
				if (qoLWebConfig == null || !(qoLWebConfig.harvestRadius > 0f))
				{
					return Mathf.Clamp(_harvestRadius?.Value ?? 7f, 2f, 20f);
				}
				return Mathf.Clamp(RemoteQol().harvestRadius, 2f, 20f);
			}
		}

		internal static int HarvestMaxTargets
		{
			get
			{
				QoLWebConfig qoLWebConfig = RemoteQol();
				if (qoLWebConfig == null || qoLWebConfig.harvestMaxTargets <= 0)
				{
					return Mathf.Clamp(_harvestMaxTargets?.Value ?? 24, 2, 80);
				}
				return Mathf.Clamp(RemoteQol().harvestMaxTargets, 2, 80);
			}
		}

		internal static int MaximumGridSize
		{
			get
			{
				QoLWebConfig qoLWebConfig = RemoteQol();
				if (qoLWebConfig == null || qoLWebConfig.maxPlantGridSize <= 0)
				{
					return Mathf.Clamp(_maxGridSize?.Value ?? 5, 2, 5);
				}
				return Mathf.Clamp(RemoteQol().maxPlantGridSize, 2, 5);
			}
		}

		internal static float DoorCloseDelay
		{
			get
			{
				QoLWebConfig qoLWebConfig = RemoteQol();
				if (qoLWebConfig == null || !(qoLWebConfig.doorCloseDelaySeconds > 0f))
				{
					return Mathf.Clamp(_doorCloseDelay?.Value ?? 5f, 1f, 60f);
				}
				return Mathf.Clamp(RemoteQol().doorCloseDelaySeconds, 1f, 60f);
			}
		}

		internal static float DoorSafetyRadius
		{
			get
			{
				QoLWebConfig qoLWebConfig = RemoteQol();
				if (qoLWebConfig == null || !(qoLWebConfig.doorSafetyRadius > 0f))
				{
					return Mathf.Clamp(_doorSafetyRadius?.Value ?? 1.8f, 0.8f, 5f);
				}
				return Mathf.Clamp(RemoteQol().doorSafetyRadius, 0.8f, 5f);
			}
		}

		internal static float FuelContainerRadius
		{
			get
			{
				QoLWebConfig qoLWebConfig = RemoteQol();
				if (qoLWebConfig == null || !(qoLWebConfig.fuelContainerRadius > 0f))
				{
					return Mathf.Clamp(_fuelContainerRadius?.Value ?? 12f, 2f, 30f);
				}
				return Mathf.Clamp(RemoteQol().fuelContainerRadius, 2f, 30f);
			}
		}

		internal static int StorageMaxContainers
		{
			get
			{
				QoLWebConfig qoLWebConfig = RemoteQol();
				if (qoLWebConfig == null || qoLWebConfig.storageMaxContainers <= 0)
				{
					return Mathf.Clamp(_storageMaxContainers?.Value ?? 20, 1, 40);
				}
				return Mathf.Clamp(RemoteQol().storageMaxContainers, 1, 40);
			}
		}

		internal static int SignMaxFontSize
		{
			get
			{
				QoLWebConfig qoLWebConfig = RemoteQol();
				if (qoLWebConfig == null || qoLWebConfig.signMaxFontSize <= 0)
				{
					return Mathf.Clamp(_signMaxFontSize?.Value ?? 48, 18, 64);
				}
				return Mathf.Clamp(RemoteQol().signMaxFontSize, 18, 64);
			}
		}

		internal static float SwimCriticalStaminaPercent
		{
			get
			{
				QoLWebConfig qoLWebConfig = RemoteQol();
				if (qoLWebConfig == null || !(qoLWebConfig.swimCriticalStaminaPercent > 0f))
				{
					return 0.25f;
				}
				return Mathf.Clamp(RemoteQol().swimCriticalStaminaPercent, 0.05f, 0.9f);
			}
		}

		private static QoLWebConfig RemoteQol()
		{
			return _plugin?.RemoteConfig?.qol;
		}

		internal static void Initialize(Plugin plugin)
		{
			if (!((Object)(object)plugin == (Object)null))
			{
				_plugin = plugin;
				_harvestRadius = ((BaseUnityPlugin)plugin).Config.Bind<float>("QoLSkilltree.Advanced", "AreaHarvestRadius", 7f, "Radius der bewusst mit Alt+Benutzen ausgeloesten Flaechenernte.");
				_harvestMaxTargets = ((BaseUnityPlugin)plugin).Config.Bind<int>("QoLSkilltree.Advanced", "AreaHarvestMaxTargets", 24, "Maximale Anzahl zusaetzlicher Pickables pro Flaechenernte.");
				_maxGridSize = ((BaseUnityPlugin)plugin).Config.Bind<int>("QoLSkilltree.Advanced", "MaximumPlantGridSize", 5, "Maximal erlaubte Rastergroesse. Unterstuetzt werden 2, 3 und 5.");
				_doorCloseDelay = ((BaseUnityPlugin)plugin).Config.Bind<float>("QoLSkilltree.Advanced", "DoorCloseDelaySeconds", 5f, "Verzoegerung des Tuerwaechters.");
				_doorSafetyRadius = ((BaseUnityPlugin)plugin).Config.Bind<float>("QoLSkilltree.Advanced", "DoorSafetyRadius", 1.8f, "Tuer wird nur geschlossen, wenn kein Spieler in diesem Radius steht.");
				_fuelContainerRadius = ((BaseUnityPlugin)plugin).Config.Bind<float>("QoLSkilltree.Advanced", "FuelContainerRadius", 12f, "Reichweite berechtigter Lager fuer den Brennstoffhelfer.");
				_storageMaxContainers = ((BaseUnityPlugin)plugin).Config.Bind<int>("QoLSkilltree.Advanced", "StorageMaxContainers", 20, "Maximale Anzahl Kisten pro bewusst ausgeloestem Lager-Routing.");
				_signMaxFontSize = ((BaseUnityPlugin)plugin).Config.Bind<int>("QoLSkilltree.Advanced", "SignMaximumFontSize", 48, "Sicheres Schriftgroessenlimit der Schildwerkstatt.");
				_behaviour = ((Component)plugin).gameObject.GetComponent<AdvancedQoLBehaviour>() ?? ((Component)plugin).gameObject.AddComponent<AdvancedQoLBehaviour>();
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"Erweiterte QoL-Talente bereit: Lager-Routing, Landwirtschaft, Tueren, Brennstoff, Rotation, Schilder und Schwimm-HUD.");
				}
			}
		}

		internal static void OnTalentDataChanged()
		{
			_behaviour?.OnTalentDataChanged();
		}

		internal static IEnumerator IntelligentStoreNearby()
		{
			Player player = Player.m_localPlayer;
			TalentData data = TalentStore.GetLocalData();
			if ((Object)(object)player == (Object)null || data == null || !data.HasSkill("storage.quick_store") || !CharacterAdmissionFeature.CanUseNetworkedInventory(player))
			{
				yield break;
			}
			string inventoryBefore = CharacterAdmissionFeature.CaptureLocalInventoryFingerprint();
			Inventory playerInventory = ((Humanoid)player).GetInventory();
			if (playerInventory == null)
			{
				yield break;
			}
			List<Container> containers = (from container in QoLSkillRuntimeFeature.FindNearbyContainers(((Component)player).transform.position, QoLSkillRuntimeFeature.ContainerRadius)
				where IsContainerEligible(container, player.GetPlayerID())
				select container).Take((!data.HasSkill("storage.stack_nearby")) ? 1 : StorageMaxContainers).ToList();
			if (containers.Count == 0)
			{
				QoLSkillRuntimeFeature.ShowCenter("Keine berechtigte freie Kiste in Reichweite.");
				yield break;
			}
			int movedItems = 0;
			HashSet<Container> touched = new HashSet<Container>();
			List<ItemData> list = (from item in playerInventory.GetAllItems()
				where item != null && item.m_stack > 0 && !item.m_equipped && item.m_gridPos.y != 0
				where !QoLSkillRuntimeFeature.IsReservedItem(data, playerInventory, item)
				select item).ToList();
			foreach (ItemData source in list)
			{
				if (source == null || source.m_stack <= 0)
				{
					continue;
				}
				ItemData sourceTemplate = source.Clone();
				int remainingSource = Math.Max(1, source.m_stack);
				string itemKey = QoLSkillRuntimeFeature.ItemKey(sourceTemplate);
				string group = MaterialGroup(sourceTemplate);
				List<Container> list2 = (from container in containers
					select new
					{
						Container = container,
						Score = StorageTargetScore(container.GetInventory(), sourceTemplate, itemKey, @group, data.AllowEmptyStorageTargets)
					} into entry
					where entry.Score > 0
					orderby entry.Score descending, Vector3.Distance(((Component)player).transform.position, ((Component)entry.Container).transform.position)
					select entry.Container).ToList();
				foreach (Container item in list2)
				{
					if (remainingSource <= 0)
					{
						break;
					}
					Inventory inventory = item.GetInventory();
					ItemData val = FindCompatibleItem(playerInventory, sourceTemplate);
					if (inventory == null || val == null)
					{
						break;
					}
					int num = Math.Min(remainingSource, Math.Max(0, val.m_stack));
					if (num <= 0)
					{
						break;
					}
					inventory.CanAddItem(val, num);
					if (!TryAcquireContainerLock(item, player.GetPlayerID()))
					{
						continue;
					}
					ContainerOwnershipLease lease = null;
					try
					{
						lease = ClaimContainer(item);
						int stack = source.m_stack;
						int num2 = TransferCompatibleItems(playerInventory, inventory, sourceTemplate, stack);
						if (num2 <= 0)
						{
							continue;
						}
						remainingSource -= num2;
						movedItems += num2;
						touched.Add(item);
						InventoryReflection.NotifyChanged(inventory);
						InventoryReflection.NotifyChanged(playerInventory);
						SaveContainer(item);
						goto IL_04d3;
					}
					finally
					{
						RestoreContainerOwnership(lease);
						ReleaseContainerLock(item, player.GetPlayerID());
					}
					IL_04d3:
					yield return null;
				}
			}
			int count = touched.Count;
			if (movedItems > 0)
			{
				MeadowsSettlementFeature.TouchLocal(((Component)player).transform.position, "qol_storage");
				CharacterAdmissionFeature.PersistNetworkedInventoryChange(inventoryBefore, "qol_intelligent_store");
			}
			QoLSkillRuntimeFeature.ShowCenter((movedItems > 0) ? (movedItems + " Gegenstaende auf " + count + " Lager verteilt.") : (data.AllowEmptyStorageTargets ? "Keine passende Lagergruppe oder kein freier Stapel gefunden." : "Kein passendes Lager gefunden. Alt+U erlaubt auch leere Zielkisten."));
		}

		private static bool IsContainerEligible(Container container, long playerId)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)container == (Object)null || container.GetInventory() == null || container.IsInUse())
			{
				return false;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && !MeadowsSettlementFeature.CanModify(localPlayer, ((Component)container).transform.position, showMessage: false))
			{
				return false;
			}
			try
			{
				Vagon wagon = container.m_wagon;
				if ((Object)(object)wagon != (Object)null && wagon.InUse())
				{
					return false;
				}
			}
			catch
			{
			}
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(Container), "CheckAccess", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					object obj2 = methodInfo.Invoke(container, new object[1] { playerId });
					if (obj2 is bool && !(bool)obj2)
					{
						return false;
					}
				}
			}
			catch
			{
				return false;
			}
			try
			{
				if (container.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, false))
				{
					return false;
				}
			}
			catch
			{
			}
			return true;
		}

		private static ItemData FindCompatibleItem(Inventory inventory, ItemData template)
		{
			if (inventory == null)
			{
				return null;
			}
			return ((IEnumerable<ItemData>)inventory.GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData item) => IsCompatible(item, template) && item.m_stack > 0));
		}

		private static int TransferCompatibleItems(Inventory sourceInventory, Inventory targetInventory, ItemData template, int requested)
		{
			if (sourceInventory == null || targetInventory == null || template == null || requested <= 0)
			{
				return 0;
			}
			ItemData val = FindCompatibleItem(sourceInventory, template);
			if (val == null)
			{
				return 0;
			}
			int num = CountCompatible(sourceInventory, template);
			int num2 = CountCompatible(targetInventory, template);
			int requested2 = Math.Min(Math.Min(requested, num), Math.Max(0, val.m_stack));
			requested2 = MaximumAddable(targetInventory, val, requested2);
			if (requested2 <= 0)
			{
				return 0;
			}
			try
			{
				sourceInventory.RemoveItem(val, requested2);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Lagertransfer-Quelle konnte nicht reduziert werden: " + ex.Message));
				}
			}
			int num3 = Mathf.Clamp(num - CountCompatible(sourceInventory, template), 0, requested2);
			if (num3 <= 0)
			{
				return 0;
			}
			ItemData val2 = val.Clone();
			val2.m_stack = num3;
			try
			{
				targetInventory.AddItem(val2);
			}
			catch (Exception ex2)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogDebug((object)("Lagertransfer-Ziel abgelehnt: " + ex2.Message));
				}
				RestoreCompatibleAmount(sourceInventory, template, num3);
				return 0;
			}
			int num4 = Math.Max(0, CountCompatible(targetInventory, template) - num2);
			if (num4 > num3)
			{
				int num5 = num4 - num3;
				int num6 = RemoveCompatibleAmount(targetInventory, template, num5);
				num4 = Math.Max(0, CountCompatible(targetInventory, template) - num2);
				if (num6 < num5 || num4 > num3)
				{
					ManualLogSource log3 = Plugin.Log;
					if (log3 != null)
					{
						log3.LogError((object)("Lagertransfer-Ziel enthielt nach Rollback eine unbelegte Mehrmenge: " + num4 + "."));
					}
				}
			}
			int num7 = Math.Min(num4, num3);
			if (num7 < num3)
			{
				RestoreCompatibleAmount(sourceInventory, template, num3 - num7);
			}
			if (num7 != requested2)
			{
				ManualLogSource log4 = Plugin.Log;
				if (log4 != null)
				{
					log4.LogWarning((object)("Lagertransfer atomar begrenzt: Angefordert=" + requested2 + "; AusQuelle=" + num3 + "; ImZiel=" + num4 + "; Verbucht=" + num7 + "."));
				}
			}
			return num7;
		}

		private static void RestoreCompatibleAmount(Inventory inventory, ItemData template, int amount)
		{
			if (inventory == null || template == null || amount <= 0)
			{
				return;
			}
			ItemData val = template.Clone();
			val.m_stack = amount;
			try
			{
				inventory.AddItem(val);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)("Lagertransfer-Rollback zur Quelle fehlgeschlagen: " + ex.Message));
				}
			}
		}

		private static int RemoveCompatibleAmount(Inventory inventory, ItemData template, int amount)
		{
			int num = Math.Max(0, amount);
			int num2 = 0;
			while (num > 0)
			{
				ItemData val = FindCompatibleItem(inventory, template);
				if (val == null)
				{
					break;
				}
				int num3 = CountCompatible(inventory, template);
				int num4 = Math.Min(num, Math.Max(1, val.m_stack));
				try
				{
					inventory.RemoveItem(val, num4);
				}
				catch
				{
					break;
				}
				int num5 = Mathf.Clamp(num3 - CountCompatible(inventory, template), 0, num4);
				if (num5 <= 0)
				{
					break;
				}
				num2 += num5;
				num -= num5;
			}
			return num2;
		}

		private static bool IsCompatible(ItemData item, ItemData template)
		{
			if (item != null && template != null && string.Equals(QoLSkillRuntimeFeature.ItemKey(item), QoLSkillRuntimeFeature.ItemKey(template), StringComparison.Ordinal) && item.m_quality == template.m_quality && item.m_variant == template.m_variant && item.m_worldLevel == template.m_worldLevel)
			{
				return SameCheatState(item, template);
			}
			return false;
		}

		private static bool SameCheatState(ItemData left, ItemData right)
		{
			return true;
		}

		private static bool ContainsOppositeCheatStack(Inventory inventory, ItemData source)
		{
			return false;
		}

		private static int MaximumAddable(Inventory inventory, ItemData item, int requested)
		{
			if (inventory == null || item == null || requested <= 0)
			{
				return 0;
			}
			if (ContainsOppositeCheatStack(inventory, item))
			{
				return 0;
			}
			int num = 0;
			int num2 = requested;
			while (num < num2)
			{
				int num3 = num + (num2 - num + 1) / 2;
				bool flag;
				try
				{
					flag = inventory.CanAddItem(item, num3);
				}
				catch
				{
					flag = false;
				}
				if (flag)
				{
					num = num3;
				}
				else
				{
					num2 = num3 - 1;
				}
			}
			return num;
		}

		private static bool TryAcquireContainerLock(Container container, long playerId)
		{
			try
			{
				ZNetView val = (((Object)(object)container.m_rootObjectOverride != (Object)null) ? container.m_rootObjectOverride : ((Component)container).GetComponent<ZNetView>());
				ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null);
				if (val2 == null || (Object)(object)ZNet.instance == (Object)null)
				{
					return false;
				}
				if (!val.IsOwner())
				{
					val.ClaimOwnership();
				}
				long ticks = ZNet.instance.GetTime().Ticks;
				long num = val2.GetLong("ChallengeHub.QoL.LockUntil", 0L);
				long num2 = val2.GetLong("ChallengeHub.QoL.LockOwner", 0L);
				if (num > ticks && num2 != 0L && num2 != playerId)
				{
					return false;
				}
				val2.Set("ChallengeHub.QoL.LockOwner", playerId);
				val2.Set("ChallengeHub.QoL.LockUntil", ticks + TimeSpan.FromSeconds(12.0).Ticks);
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static void ReleaseContainerLock(Container container, long playerId)
		{
			try
			{
				ZNetView val = (((Object)(object)container.m_rootObjectOverride != (Object)null) ? container.m_rootObjectOverride : ((Component)container).GetComponent<ZNetView>());
				ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null);
				if (val2 != null && val2.GetLong("ChallengeHub.QoL.LockOwner", 0L) == playerId)
				{
					val2.Set("ChallengeHub.QoL.LockOwner", 0L);
					val2.Set("ChallengeHub.QoL.LockUntil", 0L);
				}
			}
			catch
			{
			}
		}

		private static int StorageTargetScore(Inventory inventory, ItemData source, string itemKey, string group, bool allowEmpty)
		{
			if (inventory == null || source == null)
			{
				return 0;
			}
			if (ContainsOppositeCheatStack(inventory, source))
			{
				return 0;
			}
			List<ItemData> allItems = inventory.GetAllItems();
			if (allItems.Any((ItemData item) => item != null && string.Equals(QoLSkillRuntimeFeature.ItemKey(item), itemKey, StringComparison.Ordinal) && SameCheatState(item, source)))
			{
				return 300;
			}
			if (!string.IsNullOrEmpty(group) && allItems.Any((ItemData item) => item != null && MaterialGroup(item) == group))
			{
				return 200;
			}
			if (allowEmpty && allItems.Count == 0)
			{
				return 100;
			}
			return 0;
		}

		private static int CountCompatible(Inventory inventory, ItemData source)
		{
			if (inventory == null || source == null)
			{
				return 0;
			}
			string key = QoLSkillRuntimeFeature.ItemKey(source);
			return (from item in inventory.GetAllItems()
				where item != null && string.Equals(QoLSkillRuntimeFeature.ItemKey(item), key, StringComparison.Ordinal) && item.m_quality == source.m_quality && item.m_variant == source.m_variant && item.m_worldLevel == source.m_worldLevel && SameCheatState(item, source)
				select item).Sum((ItemData item) => Math.Max(0, item.m_stack));
		}

		private static string MaterialGroup(ItemData item)
		{
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Invalid comparison between Unknown and I4
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Invalid comparison between Unknown and I4
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Invalid comparison between Unknown and I4
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Expected I4, but got Unknown
			if (item?.m_shared == null)
			{
				return string.Empty;
			}
			string text = (QoLSkillRuntimeFeature.ItemKey(item) + " " + item.m_shared.m_name).ToLowerInvariant();
			if (ContainsAny(text, "ore", "copper", "tin", "iron", "silver", "blackmetal", "flametal"))
			{
				return "ore-metal";
			}
			if (ContainsAny(text, "wood", "finewood", "roundlog", "yggdrasil"))
			{
				return "wood";
			}
			if (ContainsAny(text, "seed", "seeds", "carrot", "turnip", "onion", "barley", "flax", "sapling"))
			{
				return "seed-crop";
			}
			if (ContainsAny(text, "trophy"))
			{
				return "trophy";
			}
			if (ContainsAny(text, "hide", "leather", "pelt", "wolf", "deer"))
			{
				return "hide";
			}
			if (ContainsAny(text, "stone", "marble", "coal", "resin", "tar"))
			{
				return "construction";
			}
			if ((int)item.m_shared.m_itemType == 2)
			{
				return "food";
			}
			if ((int)item.m_shared.m_itemType == 9 || (int)item.m_shared.m_itemType == 23)
			{
				return "ammo";
			}
			return "type-" + ((int)item.m_shared.m_itemType).ToString(CultureInfo.InvariantCulture);
		}

		private static bool ContainsAny(string text, params string[] values)
		{
			return values.Any((string value) => text.Contains(value));
		}

		private static ContainerOwnershipLease ClaimContainer(Container container)
		{
			try
			{
				ZNetView val = (((Object)(object)container.m_rootObjectOverride != (Object)null) ? container.m_rootObjectOverride : ((Component)container).GetComponent<ZNetView>());
				if ((Object)(object)val == (Object)null || !val.IsValid())
				{
					return null;
				}
				ZDO zDO = val.GetZDO();
				ContainerOwnershipLease obj = new ContainerOwnershipLease
				{
					Zdo = zDO,
					OriginalOwner = ((zDO != null) ? zDO.GetOwner() : 0),
					Claimed = !val.IsOwner()
				};
				if (obj.Claimed)
				{
					val.ClaimOwnership();
				}
				return obj;
			}
			catch
			{
				return null;
			}
		}

		private static void RestoreContainerOwnership(ContainerOwnershipLease lease)
		{
			try
			{
				if (lease != null && lease.Claimed && lease.Zdo != null && lease.Zdo.IsValid() && lease.OriginalOwner != 0L)
				{
					lease.Zdo.SetOwner(lease.OriginalOwner);
				}
			}
			catch
			{
			}
		}

		private static void SaveContainer(Container container)
		{
			try
			{
				AccessTools.Method(typeof(Container), "Save", (Type[])null, (Type[])null)?.Invoke(container, Array.Empty<object>());
			}
			catch
			{
			}
		}

		internal static string BuildPlantProgress(Plant plant)
		{
			if ((Object)(object)plant == (Object)null || !TalentStore.HasSkill("comfort.growth_sight"))
			{
				return string.Empty;
			}
			try
			{
				ZNetView component = ((Component)plant).GetComponent<ZNetView>();
				ZDO val = ((component != null) ? component.GetZDO() : null);
				if (val == null || (Object)(object)ZNet.instance == (Object)null)
				{
					return string.Empty;
				}
				long ticks = val.GetLong(ZDOVars.s_plantTime, ZNet.instance.GetTime().Ticks);
				double num = Math.Max(0.0, (ZNet.instance.GetTime() - new DateTime(ticks)).TotalSeconds);
				MethodInfo methodInfo = AccessTools.Method(typeof(Plant), "GetGrowTime", (Type[])null, (Type[])null);
				float val2 = ((methodInfo != null) ? Convert.ToSingle(methodInfo.Invoke(plant, Array.Empty<object>()), CultureInfo.InvariantCulture) : plant.m_growTimeMax);
				val2 = Math.Max(1f, val2);
				float num2 = Mathf.Clamp01((float)(num / (double)val2));
				TimeSpan remaining = TimeSpan.FromSeconds(Math.Max(0.0, (double)val2 - num));
				return ProgressLine(num2, remaining, (num2 >= 1f) ? "erntereif" : "waechst");
			}
			catch
			{
				return string.Empty;
			}
		}

		internal static string BuildPickableProgress(Pickable pickable)
		{
			if ((Object)(object)pickable == (Object)null || !TalentStore.HasSkill("comfort.growth_sight"))
			{
				return string.Empty;
			}
			try
			{
				ZNetView component = ((Component)pickable).GetComponent<ZNetView>();
				ZDO val = ((component != null) ? component.GetZDO() : null);
				if (val == null)
				{
					return string.Empty;
				}
				if (!val.GetBool(ZDOVars.s_picked, false))
				{
					return ProgressLine(1f, TimeSpan.Zero, "erntereif");
				}
				if (pickable.m_respawnTimeMinutes <= 0f)
				{
					return "\n<color=#8fa0aa>Nicht nachwachsend</color>";
				}
				long num = val.GetLong(ZDOVars.s_pickedTime, 0L);
				if (num <= 1 || (Object)(object)ZNet.instance == (Object)null)
				{
					return string.Empty;
				}
				double num2 = Math.Max(0.0, (ZNet.instance.GetTime() - new DateTime(num)).TotalMinutes);
				float percent = Mathf.Clamp01((float)(num2 / (double)pickable.m_respawnTimeMinutes));
				TimeSpan remaining = TimeSpan.FromMinutes(Math.Max(0.0, (double)pickable.m_respawnTimeMinutes - num2));
				return ProgressLine(percent, remaining, "Regeneration");
			}
			catch
			{
				return string.Empty;
			}
		}

		private static string ProgressLine(float percent, TimeSpan remaining, string label)
		{
			string text = ((percent >= 0.99f) ? "#8CFF8C" : ((percent >= 0.66f) ? "#E7E47A" : ((percent >= 0.33f) ? "#FFC266" : "#FF8B78")));
			string text2 = ((remaining.TotalSeconds <= 1.0) ? "bereit" : HumanDuration(remaining));
			return "\n<color=" + text + ">" + label + ": " + Mathf.RoundToInt(percent * 100f) + "% · " + text2 + "</color>";
		}

		private static string HumanDuration(TimeSpan time)
		{
			if (time.TotalHours >= 1.0)
			{
				return Math.Floor(time.TotalHours) + " Std. " + time.Minutes + " Min.";
			}
			if (time.TotalMinutes >= 1.0)
			{
				return Math.Floor(time.TotalMinutes) + " Min. " + time.Seconds + " Sek.";
			}
			return Math.Max(1, time.Seconds) + " Sek.";
		}

		internal static IEnumerator HarvestArea(Pickable origin, Player player)
		{
			if ((Object)(object)origin == (Object)null || (Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || !TalentStore.HasSkill("comfort.area_harvest"))
			{
				yield break;
			}
			Vector3 originPosition;
			string prefab;
			try
			{
				originPosition = ((Component)origin).transform.position;
				prefab = Utils.GetPrefabName(((Component)origin).gameObject);
			}
			catch
			{
				yield break;
			}
			if (string.IsNullOrWhiteSpace(prefab))
			{
				yield break;
			}
			List<Pickable> list = (from target in (from hit in Physics.OverlapSphere(originPosition, HarvestRadius)
					select (!((Object)(object)hit != (Object)null)) ? null : ((Component)hit).GetComponentInParent<Pickable>() into target
					where (Object)(object)target != (Object)null && (Object)(object)target != (Object)(object)origin && Utils.GetPrefabName(((Component)target).gameObject) == prefab
					select target).Distinct()
				orderby SafeDistance(originPosition, target)
				select target).Take(HarvestMaxTargets).ToList();
			int harvested = 0;
			int harvestedSinceYield = 0;
			foreach (Pickable item in list)
			{
				if (!CanHarvest(item) || !TryGetPosition((Component)(object)item, out var position) || !MeadowsSettlementFeature.CanModify(player, position, showMessage: false) || !PrivateArea.CheckAccess(position, 0f, false, false) || !HasLineOfSight(player, position))
				{
					continue;
				}
				try
				{
					if (item.Interact((Humanoid)(object)player, false, false))
					{
						harvested++;
						harvestedSinceYield++;
					}
				}
				catch
				{
				}
				if (harvestedSinceYield >= 5)
				{
					harvestedSinceYield = 0;
					yield return null;
				}
			}
			if (harvested > 0)
			{
				MeadowsSettlementFeature.TouchLocal(originPosition, "qol_harvest");
				QoLSkillRuntimeFeature.ShowCenter("Flächenernte: " + harvested + " zusätzliche Ziele.");
			}
		}

		private static float SafeDistance(Vector3 origin, Pickable target)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetPosition((Component)(object)target, out var position))
			{
				return float.MaxValue;
			}
			return Vector3.Distance(origin, position);
		}

		private static bool TryGetPosition(Component component, out Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			position = Vector3.zero;
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			try
			{
				position = component.transform.position;
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static bool CanHarvest(Pickable target)
		{
			try
			{
				ZNetView component = ((Component)target).GetComponent<ZNetView>();
				ZDO val = ((component != null) ? component.GetZDO() : null);
				return (Object)(object)component != (Object)null && component.IsValid() && val != null && !val.GetBool(ZDOVars.s_picked, false) && val.GetBool(ZDOVars.s_enabled, true) && target.GetEnabled != 0;
			}
			catch
			{
				return false;
			}
		}

		private static bool HasLineOfSight(Player player, Vector3 target)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_0026: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			Vector3 eyePoint = ((Character)player).GetEyePoint();
			Vector3 val = target + Vector3.up * 0.5f - eyePoint;
			RaycastHit val2 = default(RaycastHit);
			if (!Physics.Raycast(eyePoint, ((Vector3)(ref val)).normalized, ref val2, ((Vector3)(ref val)).magnitude, LayerMask.GetMask(new string[4] { "Default", "static_solid", "piece", "terrain" })))
			{
				return true;
			}
			return Vector3.Distance(((RaycastHit)(ref val2)).point, target) < 1.25f;
		}

		internal static IEnumerator PlantGridExtras(Player player, Piece piecePrefab, Vector3 center, Quaternion rotation, int requestedGridSize)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || (Object)(object)piecePrefab == (Object)null || !TalentStore.HasSkill("building.grid_planting"))
			{
				yield break;
			}
			Plant plantPrefab = ((Component)piecePrefab).GetComponentInChildren<Plant>(true);
			if ((Object)(object)plantPrefab == (Object)null)
			{
				yield break;
			}
			int size = ((requestedGridSize <= 2) ? 2 : ((requestedGridSize >= 5 && MaximumGridSize >= 5) ? 5 : 3));
			float spacing = Mathf.Max(1.25f, plantPrefab.m_growRadius * 2.15f);
			List<Vector3> list = GridPositions(center, rotation, size, spacing);
			int placed = 0;
			foreach (Vector3 item in list)
			{
				if (Vector3.Distance(item, center) < 0.2f || !TryGroundPosition(item, out var position) || !CanPlantAt(player, plantPrefab, position))
				{
					continue;
				}
				if (!player.HaveRequirements(piecePrefab, (RequirementMode)0))
				{
					break;
				}
				try
				{
					TerrainModifier.SetTriggerOnPlaced(true);
					GameObject val = Object.Instantiate<GameObject>(((Component)piecePrefab).gameObject, position, rotation);
					TerrainModifier.SetTriggerOnPlaced(false);
					Piece component = val.GetComponent<Piece>();
					if ((Object)(object)component != (Object)null)
					{
						component.SetCreator(player.GetPlayerID(), ((IUser)PlatformManager.DistributionPlatform.LocalUser).PlatformUserID);
					}
					WearNTear component2 = val.GetComponent<WearNTear>();
					if (component2 != null)
					{
						component2.OnPlaced();
					}
					piecePrefab.m_placeEffect.Create(position, rotation, val.transform, 1f, -1, default(ZDOID));
					player.ConsumeResources(piecePrefab.m_resources, 0, -1, 1);
					ConsumePlantingCost(player);
					placed++;
				}
				catch (Exception ex)
				{
					TerrainModifier.SetTriggerOnPlaced(false);
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogDebug((object)("Rasterpflanzung Position uebersprungen: " + ex.Message));
					}
				}
				if (placed % 3 == 0)
				{
					yield return null;
				}
			}
			if (placed > 0)
			{
				MeadowsSettlementFeature.TouchLocal(center, "qol_planting");
				QoLSkillRuntimeFeature.ShowCenter("Rasterpflanzung: " + placed + " zusätzliche Pflanzen gesetzt.");
			}
		}

		internal static List<Vector3> GridPositions(Vector3 center, Quaternion playerRotation, int size, float spacing)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> list = new List<Vector3>();
			float num = (float)(size - 1) * 0.5f;
			Vector3 val = playerRotation * Vector3.right;
			Vector3 val2 = playerRotation * Vector3.forward;
			val.y = 0f;
			val2.y = 0f;
			((Vector3)(ref val)).Normalize();
			((Vector3)(ref val2)).Normalize();
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					list.Add(center + val * (((float)j - num) * spacing) + val2 * (((float)i - num) * spacing));
				}
			}
			return list;
		}

		private static bool TryGroundPosition(Vector3 raw, out Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			position = raw;
			float y = default(float);
			if (Heightmap.GetHeight(raw, ref y))
			{
				position.y = y;
				return true;
			}
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(raw + Vector3.up * 8f, Vector3.down, ref val, 20f, LayerMask.GetMask(new string[3] { "terrain", "piece", "static_solid" })))
			{
				position = ((RaycastHit)(ref val)).point;
				return true;
			}
			return false;
		}

		private static bool CanPlantAt(Player player, Plant plant, Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_0042: 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_0049: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			if (!MeadowsSettlementFeature.CanModify(player, position, showMessage: false))
			{
				return false;
			}
			if (!PrivateArea.CheckAccess(position, 0f, false, false))
			{
				return false;
			}
			if (!HasLineOfSight(player, position))
			{
				return false;
			}
			Heightmap val = Heightmap.FindHeightmap(position);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Biome biome = val.GetBiome(position, 0.02f, false);
			if ((plant.m_biome & biome) == 0)
			{
				return false;
			}
			if (plant.m_needCultivatedGround && !val.IsCultivated(position))
			{
				return false;
			}
			return Physics.OverlapSphere(position + Vector3.up * 0.5f, Mathf.Max(0.5f, plant.m_growRadius * 0.85f), LayerMask.GetMask(new string[3] { "piece", "piece_nonsolid", "Default_small" })).All((Collider collider) => (Object)(object)collider == (Object)null || collider.isTrigger);
		}

		private static void ConsumePlantingCost(Player player)
		{
			try
			{
				((Character)player).UseStamina(1f);
			}
			catch
			{
			}
			try
			{
				ItemData representativeEquippedItem = PlayerItemReflection.GetRepresentativeEquippedItem(player);
				((representativeEquippedItem != null) ? AccessTools.Method(((object)representativeEquippedItem).GetType(), "UseDurability", (Type[])null, (Type[])null) : null)?.Invoke(representativeEquippedItem, new object[1] { 1f });
			}
			catch
			{
			}
		}

		internal static bool TryFuelHoveredDevice(Player player, out string result)
		{
			result = string.Empty;
			TalentData localData = TalentStore.GetLocalData();
			if ((Object)(object)player == (Object)null || localData == null || !localData.HasSkill("storage.fuel_helper"))
			{
				return false;
			}
			Fireplace val = LookTarget.FindComponent<Fireplace>(7f);
			if ((Object)(object)val != (Object)null)
			{
				return FillFireplace(player, localData, val, out result);
			}
			Smelter val2 = LookTarget.FindComponent<Smelter>(7f);
			if ((Object)(object)val2 != (Object)null)
			{
				return FillSmelter(player, localData, val2, out result);
			}
			result = "Keine Feuerstelle oder Produktionsanlage anvisiert.";
			return false;
		}

		private static bool FillFireplace(Player player, TalentData data, Fireplace fireplace, out string result)
		{
			//IL_0040: 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_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			result = string.Empty;
			if (fireplace.m_infiniteFuel || (Object)(object)fireplace.m_fuelItem == (Object)null || !MeadowsSettlementFeature.CanModify(player, ((Component)fireplace).transform.position, showMessage: false) || !PrivateArea.CheckAccess(((Component)fireplace).transform.position, 0f, false, false))
			{
				return false;
			}
			ZNetView component = ((Component)fireplace).GetComponent<ZNetView>();
			ZDO val = ((component != null) ? component.GetZDO() : null);
			if (val == null)
			{
				return false;
			}
			float num = val.GetFloat(ZDOVars.s_fuel, 0f);
			int num2 = Mathf.Clamp(Mathf.CeilToInt(fireplace.m_maxFuel * (float)data.FuelTargetPercent / 100f), 1, Mathf.CeilToInt(fireplace.m_maxFuel));
			int num3 = Math.Max(0, num2 - Mathf.CeilToInt(num));
			if (num3 == 0)
			{
				result = "Brennstoffziel bereits erreicht.";
				return true;
			}
			string name = fireplace.m_fuelItem.m_itemData.m_shared.m_name;
			int num4 = ConsumeFuel(player, data, name, num3, ((Component)fireplace).transform.position, delegate
			{
				fireplace.AddFuel(1f);
			});
			if (num4 > 0)
			{
				MeadowsSettlementFeature.TouchLocal(((Component)fireplace).transform.position, "qol_fuel");
			}
			result = ((num4 > 0) ? ("Brennstoffhelfer: " + num4 + " × " + QoLSkillRuntimeFeature.Localize(name) + " nachgefüllt.") : "Kein berechtigter Brennstoff vorhanden.");
			return num4 > 0;
		}

		private static bool FillSmelter(Player player, TalentData data, Smelter smelter, out string result)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			result = string.Empty;
			if ((Object)(object)smelter.m_fuelItem == (Object)null || !MeadowsSettlementFeature.CanModify(player, ((Component)smelter).transform.position, showMessage: false) || !PrivateArea.CheckAccess(((Component)smelter).transform.position, 0f, false, false))
			{
				return false;
			}
			MethodInfo methodInfo = AccessTools.Method(typeof(Smelter), "GetFuel", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(Smelter), "SetFuel", (Type[])null, (Type[])null);
			if (methodInfo == null || methodInfo2 == null)
			{
				return false;
			}
			float num = Convert.ToSingle(methodInfo.Invoke(smelter, Array.Empty<object>()), CultureInfo.InvariantCulture);
			int num2 = Mathf.Clamp(Mathf.CeilToInt((float)(smelter.m_maxFuel * data.FuelTargetPercent) / 100f), 1, smelter.m_maxFuel);
			int num3 = Math.Max(0, num2 - Mathf.CeilToInt(num));
			if (num3 == 0)
			{
				result = "Brennstoffziel bereits erreicht.";
				return true;
			}
			string name = smelter.m_fuelItem.m_itemData.m_shared.m_name;
			int num4 = 0;
			int num5 = ConsumeFuel(player, data, name, num3, ((Component)smelter).transform.position, delegate
			{
			});
			if (num5 > 0)
			{
				ZNetView val = ((Component)smelter).GetComponent<ZNetView>() ?? ((Component)smelter).GetComponentInParent<ZNetView>();
				if ((Object)(object)val != (Object)null && !val.IsOwner())
				{
					val.ClaimOwnership();
				}
				methodInfo2.Invoke(smelter, new object[1] { num + (float)num5 });
				num4 = num5;
			}
			if (num4 > 0)
			{
				MeadowsSettlementFeature.TouchLocal(((Component)smelter).transform.position, "qol_fuel");
			}
			result = ((num4 > 0) ? ("Brennstoffhelfer: " + num4 + " × " + QoLSkillRuntimeFeature.Localize(name) + " nachgefüllt.") : "Kein berechtigter Brennstoff vorhanden.");
			return num4 > 0;
		}

		private static int ConsumeFuel(Player player, TalentData data, string itemName, int need, Vector3 devicePosition, Action addOne)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			int i = 0;
			Inventory inventory = ((Humanoid)player).GetInventory();
			for (; i < need; i++)
			{
				if (!inventory.HaveItem(itemName, true))
				{
					break;
				}
				inventory.RemoveItem(itemName, 1, -1, true);
				addOne();
			}
			if (i >= need || !data.HasSkill("storage.fuel_helper_storage"))
			{
				return i;
			}
			foreach (Container item in from c in QoLSkillRuntimeFeature.FindNearbyContainers(devicePosition, FuelContainerRadius)
				where IsContainerEligible(c, player.GetPlayerID())
				select c)
			{
				Inventory inventory2 = item.GetInventory();
				if (inventory2 == null || !TryAcquireContainerLock(item, player.GetPlayerID()))
				{
					continue;
				}
				ContainerOwnershipLease lease = null;
				try
				{
					lease = ClaimContainer(item);
					for (; i < need; i++)
					{
						if (!inventory2.HaveItem(itemName, true))
						{
							break;
						}
						inventory2.RemoveItem(itemName, 1, -1, true);
						addOne();
					}
					InventoryReflection.NotifyChanged(inventory2);
					SaveContainer(item);
				}
				finally
				{
					RestoreContainerOwnership(lease);
					ReleaseContainerLock(item, player.GetPlayerID());
				}
				if (i >= need)
				{
					break;
				}
			}
			return i;
		}

		internal static string BuildSignRichText(string raw, TalentData data)
		{
			string text = Regex.Replace(raw ?? string.Empty, "<[^>]+>", string.Empty).Replace("\r", " ").Replace("\0", string.Empty);
			if (text.Length > 120)
			{
				text = text.Substring(0, 120);
			}
			string text2 = ((data.SignAlignment == 1) ? "center" : ((data.SignAlignment == 2) ? "right" : "left"));
			string text3 = text;
			if (data.SignBold)
			{
				text3 = "<b>" + text3 + "</b>";
			}
			if (data.SignItalic)
			{
				text3 = "<i>" + text3 + "</i>";
			}
			string text4 = (data.SignColor = NormalizeSignColor(data.SignColor));
			return "<align=\"" + text2 + "\"><size=" + Mathf.Clamp(data.SignFontSize, 12, SignMaxFontSize) + "><color=" + text4 + ">" + text3 + "</color></size></align>";
		}

		private static string NormalizeSignColor(string value)
		{
			string text = (value ?? string.Empty).Trim();
			if (!Regex.IsMatch(text, "^#[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$"))
			{
				return "#FFFFFF";
			}
			return text.ToUpperInvariant();
		}

		internal static void CycleFineRotationStep(float direction)
		{
			TalentData localData = TalentStore.GetLocalData();
			if (localData == null || !localData.HasSkill("building.fine_rotation"))
			{
				return;
			}
			int num = 0;
			float num2 = float.MaxValue;
			for (int i = 0; i < RotationSteps.Length; i++)
			{
				float num3 = Mathf.Abs(RotationSteps[i] - localData.FineRotationStep);
				if (num3 < num2)
				{
					num2 = num3;
					num = i;
				}
			}
			num = ((direction >= 0f) ? ((num + 1) % RotationSteps.Length) : ((num - 1 + RotationSteps.Length) % RotationSteps.Length));
			localData.FineRotationStep = RotationSteps[num];
			TalentStore.SaveLocalSettings();
			QoLSkillRuntimeFeature.ShowCenter("Drehschritt: " + localData.FineRotationStep.ToString("0.#", CultureInfo.InvariantCulture) + "°");
		}

		internal static string RotationHudText()
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			TalentData localData = TalentStore.GetLocalData();
			if (localData == null || !localData.HasSkill("building.fine_rotation"))
			{
				return string.Empty;
			}
			string text = ((localData.FineRotationAxis == 1) ? "X" : ((localData.FineRotationAxis == 2) ? "Z" : "Y"));
			Player localPlayer = Player.m_localPlayer;
			GameObject val = (((Object)(object)localPlayer != (Object)null) ? PlayerBuildReflection.GetPlacementGhost(localPlayer) : null);
			Vector3 val2;
			if (!((Object)(object)val != (Object)null))
			{
				val2 = Vector3.zero;
			}
			else
			{
				Quaternion rotation = val.transform.rotation;
				val2 = ((Quaternion)(ref rotation)).eulerAngles;
			}
			Vector3 val3 = val2;
			string text2 = "Welt X " + FormatWorldAngle(val3.x) + " | Y " + FormatWorldAngle(val3.y) + " | Z " + FormatWorldAngle(val3.z);
			return text2 + "  ·  Achse " + text + "  ·  Schritt " + localData.FineRotationStep.ToString("0.#", CultureInfo.InvariantCulture) + "°  ·  " + (localData.FineRotationLocalFrame ? "Eingabe lokal" : "Eingabe Welt") + "  [Alt+V Achse | Alt+Shift+V Rahmen | Alt+Shift+Rad Schritt | Alt+Z Reset]";
		}

		private static string FormatWorldAngle(float angle)
		{
			float num = Mathf.Repeat(angle, 360f);
			if (num >= 359.95f || num < 0.05f)
			{
				num = 0f;
			}
			return num.ToString("0.0", CultureInfo.InvariantCulture) + "°";
		}

		internal static void ApplyFineRotation(Player player)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			TalentData localData = TalentStore.GetLocalData();
			if (!((Object)(object)player == (Object)null) && localData != null && localData.HasSkill("building.fine_rotation"))
			{
				GameObject placementGhost = PlayerBuildReflection.GetPlacementGhost(player);
				Piece selectedPiece = PlayerBuildReflection.GetSelectedPiece(player);
				if (!((Object)(object)placementGhost == (Object)null) && !((Object)(object)selectedPiece == (Object)null) && !IsRotationExcluded(selectedPiece))
				{
					Quaternion val = Quaternion.Euler(localData.FineRotationX, localData.FineRotationY, localData.FineRotationZ);
					placementGhost.transform.rotation = (localData.FineRotationLocalFrame ? (placementGhost.transform.rotation * val) : (val * placementGhost.transform.rotation));
				}
			}
		}

		private static bool IsRotationExcluded(Piece piece)
		{
			if ((Object)(object)piece == (Object)null)
			{
				return true;
			}
			if ((Object)(object)((Component)piece).GetComponentInChildren<Plant>(true) != (Object)null)
			{
				return true;
			}
			if ((Object)(object)((Component)piece).GetComponentInChildren<TerrainModifier>(true) != (Object)null)
			{
				return true;
			}
			return ContainsAny(Utils.GetPrefabName(((Component)piece).gameObject).ToLowerInvariant(), "sapling", "seed", "terrain", "raise", "cultivate", "path");
		}

		internal static void AdjustFineRotation(float delta)
		{
			TalentData localData = TalentStore.GetLocalData();
			if (localData != null && localData.HasSkill("building.fine_rotation"))
			{
				float num = Mathf.Sign(delta) * localData.FineRotationStep;
				if (localData.FineRotationAxis == 1)
				{
					localData.FineRotationX = Mathf.Repeat(localData.FineRotationX + num, 360f);
				}
				else if (localData.FineRotationAxis == 2)
				{
					localData.FineRotationZ = Mathf.Repeat(localData.FineRotationZ + num, 360f);
				}
				else
				{
					localData.FineRotationY = Mathf.Repeat(localData.FineRotationY + num, 360f);
				}
				TalentStore.SaveLocalSettings();
			}
		}

		internal static SwimOverviewData SwimOverview(Player player)
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || !TalentStore.HasSkill("orientation.swim_overview"))
			{
				return null;
			}
			try
			{
				if (!((Character)player).IsSwimming())
				{
					return null;
				}
			}
			catch
			{
				return null;
			}
			float num = 0f;
			float num2 = 0f;
			try
			{
				num = player.GetStamina();
				num2 = ((Character)player).GetMaxStamina();
			}
			catch
			{
			}
			float num3 = 0f;
			try
			{
				num3 = ((Character)player).GetSkills().GetSkillLevel((SkillType)103);
			}
			catch
			{
			}
			float num4 = ReadFloatField(player, "m_swimStaminaDrainMinSkill", 5f);
			float num5 = ReadFloatField(player, "m_swimStaminaDrainMaxSkill", 2f);
			float num6 = Mathf.Lerp(num4, num5, Mathf.Clamp01(num3 / 100f));
			float num7 = ((num6 > 0.01f) ? (num / num6) : 999f);
			float num8 = EstimateGroundDistance(((Component)player).transform.position);
			return new SwimOverviewData
			{
				Seconds = Mathf.Max(0, Mathf.RoundToInt(num7)),
				EfficiencyPercent = Mathf.Clamp(Mathf.RoundToInt((1f - num6 / Math.Max(0.01f, num4)) * 100f), 0, 100),
				SafeGroundKnown = (num8 < 999f),
				SafeGroundMeters = ((num8 < 999f) ? Mathf.Max(0, Mathf.RoundToInt(num8)) : 100),
				Critical = (num2 > 0f && num / num2 < SwimCriticalStaminaPercent)
			};
		}

		private static float ReadFloatField(object instance, string name, float fallback)
		{
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(instance.GetType(), name);
				return (fieldInfo != null) ? Convert.ToSingle(fieldInfo.GetValue(instance), CultureInfo.InvariantCulture) : fallback;
			}
			catch
			{
				return fallback;
			}
		}

		private static float EstimateGroundDistance(Vector3 position)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			int mask = LayerMask.GetMask(new string[3] { "terrain", "static_solid", "piece" });
			float num = 999f;
			RaycastHit val = default(RaycastHit);
			if (Physics.SphereCast(position + Vector3.up * 1.5f, 0.22f, Vector3.down, ref val, 102f, mask, (QueryTriggerInteraction)1) && ((RaycastHit)(ref val)).normal.y >= 0.55f)
			{
				num = Mathf.Min(num, Mathf.Max(0f, position.y - ((RaycastHit)(ref val)).point.y));
			}
			Vector3 val2 = default(Vector3);
			RaycastHit val3 = default(RaycastHit);
			for (int i = 0; i < 16; i++)
			{
				float num2 = (float)i * 22.5f * ((float)Math.PI / 180f);
				((Vector3)(ref val2))..ctor(Mathf.Cos(num2), 0f, Mathf.Sin(num2));
				if (Physics.Raycast(position + Vector3.up, val2, ref val3, 100f, mask))
				{
					num = Mathf.Min(num, ((RaycastHit)(ref val3)).distance);
				}
			}
			float num3 = default(float);
			if (Heightmap.GetHeight(position, ref num3))
			{
				num = Mathf.Min(num, Mathf.Max(0f, position.y - num3));
			}
			return num;
		}
	}
	internal sealed class AdvancedQoLBehaviour : MonoBehaviour
	{
		private readonly Dictionary<Door, float> _scheduledDoors = new Dictionary<Door, float>();

		private readonly List<GameObject> _gridPreview = new List<GameObject>();

		private Material _gridPreviewMaterial;

		private Piece _gridRotationPiece;

		private Quaternion _gridRotation;

		private bool _gridRotationReady;

		private float _nextDoorCheck;

		private float _nextPreviewUpdate;

		private bool _showSignEditor;

		private Sign _editingSign;

		private string _signText = string.Empty;

		private Rect _signWindow = new Rect(80f, 80f, 520f, 430f);

		private static readonly int SignWindowId = "ChallengeHub_SignWorkshop_v280".GetHashCode();

		private GUIStyle _hudStyle;

		private GUIStyle _signPreviewStyle;

		private GUIStyle _swimTitleStyle;

		private GUIStyle _swimValueStyle;

		private GUIStyle _swimWarningStyle;

		private Texture2D _swimPanelTexture;

		private Texture2D _swimCardTexture;

		internal void ScheduleDoor(Door door)
		{
			if (!((Object)(object)door == (Object)null) && TalentStore.HasSkill("comfort.door_guardian"))
			{
				_scheduledDoors[door] = Time.realtimeSinceStartup + AdvancedQoLFeature.DoorCloseDelay;
			}
		}

		internal void OnTalentDataChanged()
		{
			if (!TalentStore.HasSkill("building.sign_workshop"))
			{
				CloseSignEditor();
			}
			if (!TalentStore.HasSkill("building.grid_planting"))
			{
				ClearGridPreview();
			}
		}

		internal Quaternion StableGridRotation(Piece piece, GameObject ghost)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)piece == (Object)null || (Object)(object)ghost == (Object)null)
			{
				if (!((Object)(object)ghost != (Object)null))
				{
					return Quaternion.identity;
				}
				return ghost.transform.rotation;
			}
			bool flag = Mathf.Abs(Input.mouseScrollDelta.y) > 0.01f;
			if (!_gridRotationReady || (Object)(object)_gridRotationPiece != (Object)(object)piece || flag)
			{
				_gridRotationPiece = piece;
				_gridRotation = ghost.transform.rotation;
				_gridRotationReady = true;
			}
			return _gridRotation;
		}

		private void Update()
		{
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				ClearGridPreview();
				return;
			}
			bool flag = Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307);
			bool flag2 = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
			if (flag && !TalentMenuBehaviour.IsVisible)
			{
				if (Input.GetKeyDown((KeyCode)117) && TalentStore.HasSkill("storage.stack_nearby"))
				{
					TalentData localData = TalentStore.GetLocalData();
					localData.AllowEmptyStorageTargets = !localData.AllowEmptyStorageTargets;
					TalentStore.SaveLocalSettings();
					QoLSkillRuntimeFeature.ShowCenter("Leere Lagerziele: " + (localData.AllowEmptyStorageTargets ? "erlaubt" : "nur vorhandene Typen/Gruppen"));
				}
				else if (Input.GetKeyDown((KeyCode)106) && TalentStore.HasSkill("building.grid_planting"))
				{
					TalentData localData2 = TalentStore.GetLocalData();
					int num = (localData2.FarmingGridSize = ((localData2.FarmingGridSize == 2) ? 3 : ((localData2.FarmingGridSize == 3 && AdvancedQoLFeature.MaximumGridSize >= 5) ? 5 : 2)));
					TalentStore.SaveLocalSettings();
					QoLSkillRuntimeFeature.ShowCenter("Pflanzraster: " + num + "×" + num);
				}
				else if (Input.GetKeyDown((KeyCode)104) && TalentStore.HasSkill("storage.fuel_helper"))
				{
					TalentData localData3 = TalentStore.GetLocalData();
					localData3.FuelTargetPercent = ((localData3.FuelTargetPercent >= 100) ? 25 : (localData3.FuelTargetPercent + 25));
					TalentStore.SaveLocalSettings();
					QoLSkillRuntimeFeature.ShowCenter("Brennstoffziel: " + localData3.FuelTargetPercent + "%");
				}
				else if (Input.GetKeyDown((KeyCode)121) && TalentStore.HasSkill("storage.fuel_helper"))
				{
					AdvancedQoLFeature.TryFuelHoveredDevice(localPlayer, out var result);
					QoLSkillRuntimeFeature.ShowCenter(result);
				}
				else if (Input.GetKeyDown((KeyCode)100) && TalentStore.HasSkill("comfort.door_guardian"))
				{
					TalentData localData4 = TalentStore.GetLocalData();
					localData4.AutoCloseDoorsInDungeons = !localData4.AutoCloseDoorsInDungeons;
					TalentStore.SaveLocalSettings();
					QoLSkillRuntimeFeature.ShowCenter("Türwächter in Dungeons: " + (localData4.AutoCloseDoorsInDungeons ? "an" : "aus"));
				}
				else if (Input.GetKeyDown((KeyCode)105) && TalentStore.HasSkill("building.sign_workshop"))
				{
					Sign val = LookTarget.FindComponent<Sign>(7f);
					if ((Object)(object)val != (Object)null)
					{
						OpenSignEditor(val);
					}
				}
				else if (Input.GetKeyDown((KeyCode)118) && TalentStore.HasSkill("building.fine_rotation"))
				{
					TalentData localData5 = TalentStore.GetLocalData();
					if (flag2)
					{
						localData5.FineRotationLocalFrame = !localData5.FineRotationLocalFrame;
					}
					else
					{
						localData5.FineRotationAxis = (localData5.FineRotationAxis + 1) % 3;
					}
					TalentStore.SaveLocalSettings();
					QoLSkillRuntimeFeature.ShowCenter(AdvancedQoLFeature.RotationHudText());
				}
				else if (Input.GetKeyDown((KeyCode)122) && TalentStore.HasSkill("building.fine_rotation"))
				{
					TalentData localData6 = TalentStore.GetLocalData();
					if (flag2)
					{
						localData6.FineRotationX = (localData6.FineRotationY = (localData6.FineRotationZ = 0f));
					}
					else if (localData6.FineRotationAxis == 1)
					{
						localData6.FineRotationX = 0f;
					}
					else if (localData6.FineRotationAxis == 2)
					{
						localData6.FineRotationZ = 0f;
					}
					else
					{
						localData6.FineRotationY = 0f;
					}
					TalentStore.SaveLocalSettings();
					QoLSkillRuntimeFeature.ShowCenter("Drehung zurückgesetzt.");
				}
				float y = Input.mouseScrollDelta.y;
				if (Mathf.Abs(y) > 0.01f && TalentStore.HasSkill("building.fine_rotation"))
				{
					if (flag2)
					{
						AdvancedQoLFeature.CycleFineRotationStep(y);
					}
					else
					{
						AdvancedQoLFeature.AdjustFineRotation(y);
					}
				}
			}
			if (Time.realtimeSinceStartup >= _nextDoorCheck)
			{
				_nextDoorCheck = Time.realtimeSinceStartup + 0.25f;
				ProcessDoors(localPlayer);
			}
			if (Time.realtimeSinceStartup >= _nextPreviewUpdate)
			{
				_nextPreviewUpdate = Time.realtimeSinceStartup + 0.15f;
				UpdateGridPreview(localPlayer, flag);
			}
		}

		private void ProcessDoors(Player player)
		{
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			KeyValuePair<Door, float>[] array = _scheduledDoors.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<Door, float> keyValuePair = array[i];
				Door door = keyValuePair.Key;
				if ((Object)(object)door == (Object)null)
				{
					_scheduledDoors.Remove(keyValuePair.Key);
				}
				else
				{
					if (Time.realtimeSinceStartup < keyValuePair.Value)
					{
						continue;
					}
					_scheduledDoors.Remove(door);
					TalentData localData = TalentStore.GetLocalData();
					if (localData == null || !localData.HasSkill("comfort.door_guardian") || (((Character)player).InInterior() && !localData.AutoCloseDoorsInDungeons))
					{
						continue;
					}
					ZNetView component = ((Component)door).GetComponent<ZNetView>();
					ZDO val = ((component != null) ? component.GetZDO() : null);
					if (val == null || val.GetInt(ZDOVars.s_state, 0) == 0 || door.m_canNotBeClosed)
					{
						continue;
					}
					if (Player.GetAllPlayers().Any((Player other) => (Object)(object)other != (Object)null && Vector3.Distance(((Component)other).transform.position, ((Component)door).transform.position) <= AdvancedQoLFeature.DoorSafetyRadius))
					{
						_scheduledDoors[door] = Time.realtimeSinceStartup + 1f;
					}
					else if (MeadowsSettlementFeature.CanModify(player, ((Component)door).transform.position, showMessage: false) && (!door.m_checkGuardStone || PrivateArea.CheckAccess(((Component)door).transform.position, 0f, false, false)))
					{
						try
						{
							door.Interact((Humanoid)(object)player, false, false);
						}
						catch
						{
						}
					}
				}
			}
		}

		private void UpdateGridPreview(Player player, bool alt)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Expected O, but got Unknown
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			if (!alt || !TalentStore.HasSkill("building.grid_planting"))
			{
				ClearGridPreview();
				return;
			}
			Piece selectedPiece = PlayerBuildReflection.GetSelectedPiece(player);
			GameObject placementGhost = PlayerBuildReflection.GetPlacementGhost(player);
			Plant val = (((Object)(object)selectedPiece != (Object)null) ? ((Component)selectedPiece).GetComponentInChildren<Plant>(true) : null);
			if ((Object)(object)selectedPiece == (Object)null || (Object)(object)placementGhost == (Object)null || (Object)(object)val == (Object)null)
			{
				ClearGridPreview();
				return;
			}
			int farmingGridSize = TalentStore.GetLocalData().FarmingGridSize;
			float spacing = Mathf.Max(1.25f, val.m_growRadius * 2.15f);
			Quaternion playerRotation = StableGridRotation(selectedPiece, placementGhost);
			List<Vector3> list = AdvancedQoLFeature.GridPositions(placementGhost.transform.position, playerRotation, farmingGridSize, spacing);
			if ((Object)(object)_gridPreviewMaterial == (Object)null)
			{
				Shader val2 = Shader.Find("Unlit/Color") ?? Shader.Find("Standard");
				if ((Object)(object)val2 != (Object)null)
				{
					_gridPreviewMaterial = new Material(val2)
					{
						color = new Color(0.25f, 1f, 0.35f, 0.55f)
					};
				}
			}
			while (_gridPreview.Count < list.Count)
			{
				GameObject val3 = GameObject.CreatePrimitive((PrimitiveType)2);
				((Object)val3).name = "ChallengeHub_PlantGridPreview";
				Object.Destroy((Object)(object)val3.GetComponent<Collider>());
				val3.transform.localScale = new Vector3(0.25f, 0.02f, 0.25f);
				Renderer component = val3.GetComponent<Renderer>();
				if ((Object)(object)component != (Object)null && (Object)(object)_gridPreviewMaterial != (Object)null)
				{
					component.sharedMaterial = _gridPreviewMaterial;
				}
				_gridPreview.Add(val3);
			}
			float num = default(float);
			for (int i = 0; i < _gridPreview.Count; i++)
			{
				bool flag = i < list.Count;
				_gridPreview[i].SetActive(flag);
				if (flag)
				{
					Vector3 val4 = list[i];
					if (Heightmap.GetHeight(val4, ref num))
					{
						val4.y = num + 0.03f;
					}
					_gridPreview[i].transform.position = val4;
				}
			}
		}

		private void ClearGridPreview()
		{
			foreach (GameObject item in _gridPreview)
			{
				if ((Object)(object)item != (Object)null)
				{
					Object.Destroy((Object)(object)item);
				}
			}
			_gridPreview.Clear();
			_gridRotationPiece = null;
			_gridRotationReady = false;
		}

		private void OpenSignEditor(Sign sign)
		{
			//IL_0014: 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)
			if (!((Object)(object)sign == (Object)null) && MeadowsSettlementFeature.CanModify(Player.m_localPlayer, ((Component)sign).transform.position, showMessage: false) && PrivateArea.CheckAccess(((Component)sign).transform.position, 0f, true, false))
			{
				_editingSign = sign;
				string text = string.Empty;
				try
				{
					text = sign.GetText();
				}
				catch
				{
				}
				_signText = Regex.Replace(text ?? string.Empty, "<[^>]+>", string.Empty);
				_showSignEditor = true;
				ChallengeHubCursorController.Acquire("qol-sign-editor");
			}
		}

		private void CloseSignEditor()
		{
			_showSignEditor = false;
			_editingSign = null;
			ChallengeHubCursorController.Release("qol-sign-editor");
		}

		private void OnGUI()
		{
			//IL_0013: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			if (_hudStyle == null)
			{
				_hudStyle = new GUIStyle(GUI.skin.box)
				{
					alignment = (TextAnchor)4,
					fontSize = 15,
					wordWrap = true
				};
				_signPreviewStyle = new GUIStyle(GUI.skin.box)
				{
					alignment = (TextAnchor)4,
					fontSize = 18,
					wordWrap = true,
					richText = true
				};
				InitializeSwimStyles();
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && !TalentMenuBehaviour.IsVisible && (Event.current == null || (int)Event.current.type == 7))
			{
				string text = AdvancedQoLFeature.RotationHudText();
				if (!string.IsNullOrEmpty(text) && (Object)(object)PlayerBuildReflection.GetPlacementGhost(localPlayer) != (Object)null)
				{
					GUI.Box(new Rect((float)Screen.width * 0.5f - 330f, (float)Screen.height - 178f, 660f, 30f), text, _hudStyle);
				}
				AdvancedQoLFeature.SwimOverviewData swimOverviewData = AdvancedQoLFeature.SwimOverview(localPlayer);
				if (swimOverviewData != null)
				{
					DrawSwimOverview(swimOverviewData);
				}
			}
			if (_showSignEditor && (Object)(object)_editingSign != (Object)null)
			{
				_signWindow = GUI.Window(SignWindowId, _signWindow, new WindowFunction(DrawSignWindow), "ChallengeHub Schildwerkstatt");
			}
		}

		private void InitializeSwimStyles()
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Expected O, but got Unknown
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			Font[] source = Resources.FindObjectsOfTypeAll<Font>();
			Font font = ((IEnumerable<Font>)source).FirstOrDefault((Func<Font, bool>)((Font val) => ((Object)val).name == "AveriaSansLibre-Regular")) ?? ((IEnumerable<Font>)source).FirstOrDefault((Func<Font, bool>)((Font val) => ((Object)val).name == "AveriaSansLibre-Light")) ?? ((IEnumerable<Font>)source).FirstOrDefault((Func<Font, bool>)((Font val) => ((Object)val).name == "AveriaSansLibre-Bold")) ?? GUI.skin.font;
			_swimPanelTexture = SolidTexture(new Color(0.035f, 0.045f, 0.05f, 0.66f));
			_swimCardTexture = SolidTexture(new Color(0.12f, 0.16f, 0.17f, 0.72f));
			_swimTitleStyle = new GUIStyle(GUI.skin.label)
			{
				font = font,
				fontSize = 13,
				alignment = (TextAnchor)3
			};
			_swimTitleStyle.normal.textColor = new Color(0.88f, 0.84f, 0.72f, 1f);
			_swimValueStyle = new GUIStyle(GUI.skin.label)
			{
				font = font,
				fontSize = 16,
				alignment = (TextAnchor)8
			};
			_swimValueStyle.normal.textColor = Color.white;
			_swimWarningStyle = new GUIStyle(_swimValueStyle)
			{
				fontSize = 20,
				alignment = (TextAnchor)4
			};
			_swimWarningStyle.normal.textColor = new Color(1f, 0.32f, 0.2f, 1f);
		}

		private static Texture2D SolidTexture(Color color)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1);
			val.SetPixel(0, 0, color);
			val.Apply();
			return val;
		}

		private void DrawSwimOverview(AdvancedQoLFeature.SwimOverviewData data)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			float num = ResolveStaminaPanelBottom() + 8f;
			if (num < 50f || num + 74f > (float)Screen.height - 8f)
			{
				num = (float)Screen.height - 132f;
			}
			Rect val = default(Rect);
			((Rect)(ref val))..ctor((float)Screen.width * 0.5f - 195f, num, 390f, 74f);
			GUI.DrawTexture(val, (Texture)(object)_swimPanelTexture);
			DrawSwimCard(new Rect(((Rect)(ref val)).x + 7f, ((Rect)(ref val)).y + 7f, 116f, 60f), "◷  Restzeit", data.Seconds + " s");
			DrawSwimCard(new Rect(((Rect)(ref val)).x + 130f, ((Rect)(ref val)).y + 7f, 116f, 60f), "≈  Effizienz", data.EfficiencyPercent + " %");
			DrawSwimCard(new Rect(((Rect)(ref val)).x + 253f, ((Rect)(ref val)).y + 7f, 101f, 60f), "⌂  Stand", data.SafeGroundKnown ? (data.SafeGroundMeters + " m") : "> 100 m");
			if (data.Critical)
			{
				GUI.Label(new Rect(((Rect)(ref val)).xMax - 34f, ((Rect)(ref val)).y + 2f, 30f, 30f), "!", _swimWarningStyle);
			}
		}

		private void DrawSwimCard(Rect rect, string title, string value)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			GUI.DrawTexture(rect, (Texture)(object)_swimCardTexture);
			GUI.Label(new Rect(((Rect)(ref rect)).x + 7f, ((Rect)(ref rect)).y + 3f, ((Rect)(ref rect)).width - 14f, 24f), title, _swimTitleStyle);
			GUI.Label(new Rect(((Rect)(ref rect)).x + 7f, ((Rect)(ref rect)).y + 25f, ((Rect)(ref rect)).width - 14f, 29f), value, _swimValueStyle);
		}

		private static float ResolveStaminaPanelBottom()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Hud instance = Hud.instance;
				object obj = (((Object)(object)instance == (Object)null) ? null : AccessTools.Field(typeof(Hud), "m_staminaPanel"))?.GetValue(instance);
				GameObject val = (GameObject)((obj is GameObject) ? obj : null);
				RectTransform val2 = (RectTransform)((val != null) ? val.GetComponent<RectTransform>() : ((obj is RectTransform) ? obj : null));
				if ((Object)(object)val2 != (Object)null)
				{
					Rect rect = val2.rect;
					Vector3 val3 = Vector2.op_Implicit(RectTransformUtility.WorldToScreenPoint((Camera)null, ((Transform)val2).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center))));
					float num = (float)Screen.height - val3.y;
					rect = val2.rect;
					return num + ((Rect)(ref rect)).height * 0.5f;
				}
			}
			catch
			{
			}
			return (float)Screen.height - 214f;
		}

		private void DrawSignWindow(int id)
		{
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			TalentData localData = TalentStore.GetLocalData();
			if (localData == null)
			{
				CloseSignEditor();
				return;
			}
			GUILayout.Label("Text (max. 120 Zeichen)", Array.Empty<GUILayoutOption>());
			_signText = GUILayout.TextArea(_signText ?? string.Empty, 120, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(80f) });
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Farbe", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) });
			localData.SignColor = GUILayout.TextField(localData.SignColor ?? "#FFFFFF", 9, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) });
			GUILayout.Label("Größe", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			if (int.TryParse(GUILayout.TextField(localData.SignFontSize.ToString(CultureInfo.InvariantCulture), 3, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }), out var result))
			{
				localData.SignFontSize = Mathf.Clamp(result, 12, AdvancedQoLFeature.SignMaxFontSize);
			}
			localData.SignBold = GUILayout.Toggle(localData.SignBold, "Fett", Array.Empty<GUILayoutOption>());
			localData.SignItalic = GUILayout.Toggle(localData.SignItalic, "Kursiv", Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Links", Array.Empty<GUILayoutOption>()))
			{
				localData.SignAlignment = 0;
			}
			if (GUILayout.Button("Mitte", Array.Empty<GUILayoutOption>()))
			{
				localData.SignAlignment = 1;
			}
			if (GUILayout.Button("Rechts", Array.Empty<GUILayoutOption>()))
			{
				localData.SignAlignment = 2;
			}
			GUILayout.EndHorizontal();
			GUILayout.Label("Vorschau:", Array.Empty<GUILayoutOption>());
			GUILayout.Box(AdvancedQoLFeature.BuildSignRichText(_signText, localData), _signPreviewStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(70f) });
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			for (int i = 0; i < 3; i++)
			{
				int index = i;
				if (GUILayout.Button("Vorlage " + (i + 1), Array.Empty<GUILayoutOption>()))
				{
					ApplyOrSavePreset(localData, index, Event.current.shift);
				}
			}
			GUILayout.EndHorizontal();
			GUILayout.Label("Shift+Klick speichert den aktuellen Stil in die Vorlage.", Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Speichern", Array.Empty<GUILayoutOption>()))
			{
				try
				{
					_editingSign.SetText(AdvancedQoLFeature.BuildSignRichText(_signText, localData));
					MeadowsSettlementFeature.TouchLocal(((Component)_editingSign).transform.position, "qol_sign");
				}
				catch (Exception ex)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("Schildtext konnte nicht gespeichert werden: " + ex.Message));
					}
				}
				TalentStore.SaveLocalSettings();
				CloseSignEditor();
			}
			if (GUILayout.Button("Abbrechen", Array.Empty<GUILayoutOption>()))
			{
				CloseSignEditor();
			}
			GUILayout.EndHorizontal();
			GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref _signWindow)).width, 22f));
		}

		private static void ApplyOrSavePreset(TalentData data, int index, bool save)
		{
			while (data.SignStylePresets.Count <= index)
			{
				data.SignStylePresets.Add(new SignStylePresetData
				{
					Name = "Vorlage " + (data.SignStylePresets.Count + 1)
				});
			}
			SignStylePresetData signStylePresetData = data.SignStylePresets[index];
			if (save)
			{
				signStylePresetData.Color = data.SignColor;
				signStylePresetData.FontSize = data.SignFontSize;
				signStylePresetData.Bold = data.SignBold;
				signStylePresetData.Italic = data.SignItalic;
				signStylePresetData.Alignment = data.SignAlignment;
				signStylePresetData.Normalize();
				TalentStore.SaveLocalSettings();
			}
			else
			{
				data.SignColor = signStylePresetData.Color;
				data.SignFontSize = signStylePresetData.FontSize;
				data.SignBold = signStylePresetData.Bold;
				data.SignItalic = signStylePresetData.Italic;
				data.SignAlignment = signStylePresetData.Alignment;
			}
		}

		private void OnDestroy()
		{
			CloseSignEditor();
			ClearGridPreview();
			if ((Object)(object)_gridPreviewMaterial != (Object)null)
			{
				Object.Destroy((Object)(object)_gridPreviewMaterial);
			}
			_gridPreviewMaterial = null;
		}
	}
	[HarmonyPatch(typeof(Plant), "GetHoverText")]
	internal static class QoLPlantProgressPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Plant __instance, ref string __result)
		{
			__result += AdvancedQoLFeature.BuildPlantProgress(__instance);
		}
	}
	[HarmonyPatch(typeof(Pickable), "GetHoverText")]
	internal static class QoLPickableProgressPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Pickable __instance, ref string __result)
		{
			__result += AdvancedQoLFeature.BuildPickableProgress(__instance);
		}
	}
	[HarmonyPatch(typeof(Pickable), "Interact")]
	internal static class QoLAreaHarvestPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Pickable __instance, Humanoid character, bool repeat, bool alt)
		{
			Player val = (Player)(object)((character is Player) ? character : null);
			if (!(!alt || repeat) && !((Object)(object)val == (Object)null) && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && TalentStore.HasSkill("comfort.area_harvest") && CharacterAdmissionFeature.CanUseNetworkedInventory(val, showMessage: false))
			{
				Plugin instance = Plugin.Instance;
				if (instance != null)
				{
					((MonoBehaviour)instance).StartCoroutine(AdvancedQoLFeature.HarvestArea(__instance, val));
				}
			}
		}
	}
	[HarmonyPatch(typeof(Door), "Interact")]
	internal static class QoLDoorGuardianPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Door __instance, Humanoid character, bool hold, ref bool __result)
		{
			Player val = (Player)(object)((character is Player) ? character : null);
			if (!__result || hold || (Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer || !TalentStore.HasSkill("comfort.door_guardian"))
			{
				return;
			}
			object obj;
			if (__instance == null)
			{
				obj = null;
			}
			else
			{
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				obj = ((component != null) ? component.GetZDO() : null);
			}
			ZDO val2 = (ZDO)obj;
			if (val2 != null && val2.GetInt(ZDOVars.s_state, 0) != 0)
			{
				Plugin instance = Plugin.Instance;
				if (instance != null)
				{
					((Component)instance).GetComponent<AdvancedQoLBehaviour>()?.ScheduleDoor(__instance);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
	internal static class QoLFineRotationGhostPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				AdvancedQoLFeature.ApplyFineRotation(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "PlacePiece", new Type[]
	{
		typeof(Piece),
		typeof(Vector3),
		typeof(Quaternion),
		typeof(bool),
		typeof(bool)
	})]
	internal static class QoLGridPlantingPatch
	{
		internal sealed class State
		{
			internal Piece Piece;

			internal Vector3 Position;

			internal Quaternion Rotation;

			internal bool Requested;

			internal int Size;
		}

		[HarmonyPrefix]
		private static void Prefix(Player __instance, out State __state)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			__state = null;
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && TalentStore.HasSkill("building.grid_planting") && (Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307)))
			{
				Piece selectedPiece = PlayerBuildReflection.GetSelectedPiece(__instance);
				GameObject placementGhost = PlayerBuildReflection.GetPlacementGhost(__instance);
				if (!((Object)(object)selectedPiece == (Object)null) && !((Object)(object)placementGhost == (Object)null) && !((Object)(object)((Component)selectedPiece).GetComponentInChildren<Plant>(true) == (Object)null))
				{
					TalentData localData = TalentStore.GetLocalData();
					Plugin instance = Plugin.Instance;
					AdvancedQoLBehaviour advancedQoLBehaviour = ((instance != null) ? ((Component)instance).GetComponent<AdvancedQoLBehaviour>() : null);
					Quaternion rotation = (((Object)(object)advancedQoLBehaviour != (Object)null) ? advancedQoLBehaviour.StableGridRotation(selectedPiece, placementGhost) : placementGhost.transform.rotation);
					__state = new State
					{
						Piece = selectedPiece,
						Position = placementGhost.transform.position,
						Rotation = rotation,
						Requested = true,
						Size = (localData?.FarmingGridSize ?? 3)
					};
				}
			}
		}

		[HarmonyPostfix]
		private static void Postfix(Player __instance, State __state)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (__state != null && __state.Requested && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				Plugin instance = Plugin.Instance;
				if (instance != null)
				{
					((MonoBehaviour)instance).StartCoroutine(AdvancedQoLFeature.PlantGridExtras(__instance, __state.Piece, __state.Position, __state.Rotation, __state.Size));
				}
			}
		}
	}
	[DataContract]
	internal sealed class AxtblattPhotoEntry
	{
		[DataMember]
		public string url;

		[DataMember]
		public string caption;
	}
	[DataContract]
	internal sealed class AxtblattIssueEntry
	{
		[DataMember]
		public string id;

		[DataMember]
		public int issueNumber;

		[DataMember]
		public string title;

		[DataMember]
		public string subtitle;

		[DataMember]
		public string lead;

		[DataMember]
		public string body;

		[DataMember]
		public string category;

		[DataMember]
		public string author;

		[DataMember]
		public string publishedAt;

		[DataMember]
		public string[] shortNews;

		[DataMember]
		public AxtblattPhotoEntry[] photos;

		[DataMember]
		public string[] imagePages;
	}
	internal static class StartupWelcomeFeature
	{
		internal static void Initialize(Plugin plugin)
		{
			if (!((Object)(object)plugin == (Object)null) && !Application.isBatchMode && (Object)(object)((Component)plugin).GetComponent<BlutEidStartupBehaviour>() == (Object)null)
			{
				((Component)plugin).gameObject.AddComponent<BlutEidStartupBehaviour>();
			}
		}
	}
	internal sealed class BlutEidStartupBehaviour : MonoBehaviour
	{
		[Serializable]
		private sealed class MainMenuCharacterRegistration
		{
			public string action;

			public string clientVersion;

			public string clientSessionId;

			public string challengeShortCode;

			public string linkCode;

			public string characterId;

			public string characterName;
		}

		[Serializable]
		private sealed class MainMenuRegistrationResponse
		{
			public bool ok;

			public string status;

			public string error;

			public string message;
		}

		[Serializable]
		private sealed class MainMenuClientStartup
		{
			public string action;

			public string clientVersion;

			public string clientSessionId;

			public string challengeShortCode;

			public string linkCode;

			public string twitchLogin;

			public string startedAt;
		}

		[Serializable]
		private sealed class ClientStartupResponse
		{
			public bool ok;

			public bool recorded;

			public string status;

			public string error;
		}

		[Serializable]
		private sealed class DeathRunEnvelope
		{
			public bool ok;

			public bool worldReady;

			public DeathRunWeb run;
		}

		[Serializable]
		private sealed class DeathRunWeb
		{
			public string id;

			public string worldCode;

			public string worldPackageStatus;

			public bool canHostWorld;

			public string hostCharacterName;
		}

		internal static bool CharacterSelected;

		private Texture2D _image;

		private Texture2D _panel;

		private GUIStyle _button;

		private GUIStyle _title;

		private GUIStyle _status;

		private GUIStyle _version;

		private string _message = "Vorzeichen des Nordens · Charakter auswählen und Challenge-Welt starten";

		private bool _resumeRunning;

		private string _installedWorldCode = string.Empty;

		private IEnumerator Start()
		{
			yield return (object)new WaitForSecondsRealtime(1f);
			yield return ReportClientStartup();
		}

		private IEnumerator ReportClientStartup()
		{
			string endpoint = ((Plugin.ApiBaseUrl != null) ? ((Plugin.ApiBaseUrl.Value ?? string.Empty).TrimEnd(new char[1] { '/' }) + "/api/valheim/admission") : string.Empty);
			if (string.IsNullOrWhiteSpace(endpoint))
			{
				yield break;
			}
			for (int attempt = 0; attempt < 3; attempt++)
			{
				MainMenuClientStartup value = new MainMenuClientStartup
				{
					action = "client_start",
					challengeShortCode = "BLUTEID",
					linkCode = ((Plugin.PlayerLinkCode != null) ? (Plugin.PlayerLinkCode.Value ?? string.Empty) : string.Empty),
					twitchLogin = ((Plugin.TwitchLogin != null) ? (Plugin.TwitchLogin.Value ?? string.Empty) : string.Empty),
					clientVersion = "2.12.71",
					clientSessionId = Plugin.ClientSessionId,
					startedAt = DateTime.UtcNow.ToString("O")
				};
				byte[] bytes = Encoding.UTF8.GetBytes(ChallengeHubJson.Serialize(value));
				UnityWebRequest request = new UnityWebRequest(endpoint, "POST");
				try
				{
					request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bytes);
					request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
					request.SetRequestHeader("Content-Type", "application/json");
					ApplyMainMenuAuthorization(request);
					request.timeout = 15;
					yield return request.SendWebRequest();
					ClientStartupResponse clientStartupResponse = null;
					try
					{
						clientStartupResponse = ChallengeHubJson.Deserialize<ClientStartupResponse>(request.downloadHandler.text ?? string.Empty);
					}
					catch
					{
					}
					if ((int)request.result == 1 && clientStartupResponse != null && (clientStartupResponse.ok || clientStartupResponse.recorded))
					{
						ManualLogSource log = Plugin.Log;
						if (log != null)
						{
							log.LogInfo((object)("Blut-Eid Clientstart an ChallengeHub gemeldet: Version=2.12.71; Sitzung=" + Plugin.ClientSessionId));
						}
						break;
					}
					if (attempt == 2)
					{
						ManualLogSource log2 = Plugin.Log;
						if (log2 != null)
						{
							log2.LogWarning((object)("Blut-Eid Clientstart konnte nicht an ChallengeHub gemeldet werden: HTTP " + request.responseCode + " " + request.error));
						}
					}
				}
				finally
				{
					((IDisposable)request)?.Dispose();
				}
				yield return (object)new WaitForSecondsRealtime(3f * (float)(attempt + 1));
			}
		}

		private void OnGUI()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			if (IsMainMenuHome())
			{
				EnsureAssets();
				float num = Mathf.Clamp((float)Screen.width * 0.34f, 390f, 610f);
				float num2 = num / 1.777f;
				Rect val = default(Rect);
				((Rect)(ref val))..ctor((float)Screen.width - num - 24f, 24f, num, num2 + 128f);
				GUI.DrawTexture(val, (Texture)(object)_panel, (ScaleMode)0);
				Rect val2 = default(Rect);
				((Rect)(ref val2))..ctor(((Rect)(ref val)).x + 6f, ((Rect)(ref val)).y + 6f, num - 12f, num2 - 2f);
				if ((Object)(object)_image != (Object)null)
				{
					GUI.DrawTexture(val2, (Texture)(object)_image, (ScaleMode)2, true);
				}
				if (GUI.Button(val2, GUIContent.none, _button))
				{
					HandleCardClick();
				}
				GUI.Label(new Rect(((Rect)(ref val)).x + 18f, ((Rect)(ref val2)).yMax + 8f, num - 36f, 34f), "Der Blut-Eid: Vorzeichen des Nordens", _title);
				GUI.Label(new Rect(((Rect)(ref val)).x + 18f, ((Rect)(ref val2)).yMax + 45f, num - 36f, 42f), _message, _status);
				GUI.Label(new Rect(((Rect)(ref val)).x + 18f, ((Rect)(ref val2)).yMax + 91f, num - 36f, 24f), "ChallengeHub Blut-Eid v2.12.71  ·  Modpaket aktuell", _version);
			}
		}

		private static bool IsMainMenuHome()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			if (string.Equals(((Scene)(ref activeScene)).name, "start", StringComparison.OrdinalIgnoreCase))
			{
				return (Object)(object)Player.m_localPlayer == (Object)null;
			}
			return false;
		}

		private void HandleCardClick()
		{
			FejdStartup startup = Object.FindFirstObjectByType<FejdStartup>();
			if ((Object)(object)startup == (Object)null)
			{
				_message = "Valheim-Hauptmenü ist noch nicht bereit";
				return;
			}
			if (!string.IsNullOrWhiteSpace(_installedWorldCode))
			{
				RefreshAndSelectWorld(startup, _installedWorldCode);
				return;
			}
			if (!CharacterSelected)
			{
				_message = "Schritt 1 von 2 · Charakter auswählen";
				AccessTools.Method(typeof(FejdStartup), "ShowCharacterSelection", (Type[])null, (Type[])null)?.Invoke(startup, null);
				return;
			}
			PlayerLinkSetupFeature playerLinkSetupFeature = (((Object)(object)Plugin.Instance != (Object)null) ? ((Component)Plugin.Instance).GetComponent<PlayerLinkSetupFeature>() : null);
			_message = "Schritt 2 von 2 · Blut-Eid-Welt wird eingerichtet ...";
			if ((Object)(object)playerLinkSetupFeature == (Object)null)
			{
				_message = "ChallengeHub-Verbindung ist nicht bereit";
				return;
			}
			playerLinkSetupFeature.SelectDeathRunFromMainMenu(delegate(string message)
			{
				if (message.IndexOf("eingerichtet", StringComparison.OrdinalIgnoreCase) < 0)
				{
					_message = message;
				}
				else
				{
					((MonoBehaviour)this).StartCoroutine(RegisterSelectedCharacterAndOpenWebApp(startup));
				}
			});
		}

		private IEnumerator RegisterSelectedCharacterAndOpenWebApp(FejdStartup startup)
		{
			PlayerProfile val = SelectedProfile(startup);
			if (val == null)
			{
				CharacterSelected = false;
				_message = "Bitte zuerst einen Charakter auswählen";
				yield break;
			}
			string text = ((Plugin.PlayerLinkCode != null) ? (Plugin.PlayerLinkCode.Value ?? string.Empty).Trim() : string.Empty);
			if (string.IsNullOrWhiteSpace(text))
			{
				_message = "Player-Link-Code fehlt · bitte im ChallengeHub-Dialog eintragen";
				yield break;
			}
			string text2 = ((Plugin.PlayerAccessKey != null) ? (Plugin.PlayerAccessKey.Value ?? string.Empty).Trim() : string.Empty);
			if (string.IsNullOrWhiteSpace(text2) || !text2.StartsWith("vhp_", StringComparison.Ordinal))
			{
				_message = "Challenge-Geheimschluessel fehlt · im LiveChallenges-Profil bei Blut-Eid erzeugen";
				Plugin instance = Plugin.Instance;
				if (instance != null)
				{
					((Component)instance).GetComponent<PlayerLinkSetupFeature>()?.RequestRelink(_message);
				}
				yield break;
			}
			string characterId = val.GetPlayerID().ToString();
			string characterName = val.GetName() ?? "Valheim-Charakter";
			MainMenuCharacterRegistration value = new MainMenuCharacterRegistration
			{
				action = "register",
				challengeShortCode = "BLUTEID",
				linkCode = text,
				characterId = characterId,
				characterName = characterName,
				clientVersion = "2.12.71",
				clientSessionId = Plugin.ClientSessionId
			};
			string text3 = Plugin.ApiBaseUrl.Value.TrimEnd(new char[1] { '/' }) + "/api/valheim/admission";
			byte[] bytes = Encoding.UTF8.GetBytes(ChallengeHubJson.Serialize(value));
			UnityWebRequest request