Decompiled source of Hugins Desk Comfy Kit v0.1.0

plugins/HuginsDesk.ComfyKit/HuginsDesk.ComfyKit.dll

Decompiled 21 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using HuginsDesk.ComfyKit.Core;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("HuginsDesk.ComfyKit")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("HuginsDesk.ComfyKit")]
[assembly: AssemblyTitle("HuginsDesk.ComfyKit")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[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 HuginsDesk.ComfyKit
{
	internal static class BuildCameraMode
	{
		private static Player owner;

		private static Vector3 position;

		private static Vector3 origin;

		private static float yaw;

		private static float pitch;

		private static float health;

		internal static bool Active { get; private set; }

		internal static void Tick()
		{
			//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_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (Active && (!Plugin.Enabled(Feature.BuildCamera) || !Object.op_Implicit((Object)(object)localPlayer) || (Object)(object)localPlayer != (Object)(object)owner || ((Character)localPlayer).IsDead() || ((Character)localPlayer).IsTeleporting() || ((Character)localPlayer).IsAttached() || ((Character)localPlayer).InCutscene() || !((Character)localPlayer).InPlaceMode() || !Application.isFocused || ((Character)localPlayer).GetHealth() < health || Vector3.Distance(((Component)localPlayer).transform.position, origin) > 2f))
			{
				Exit();
				return;
			}
			bool flag = Plugin.Enabled(Feature.BuildCamera) && ShortcutDown();
			if (Active && (flag || ZInput.GetKeyDown((KeyCode)27, true)))
			{
				Exit();
			}
			else if (!Active && flag && Object.op_Implicit((Object)(object)localPlayer) && !InputGuard.Busy() && ((Character)localPlayer).TakeInput() && Object.op_Implicit((Object)(object)GameCamera.instance) && !GameCamera.InFreeFly() && ((Character)localPlayer).InPlaceMode() && !((Character)localPlayer).IsDead() && !((Character)localPlayer).IsTeleporting() && !((Character)localPlayer).IsAttached() && !((Character)localPlayer).IsSwimming() && ((Character)localPlayer).IsOnGround())
			{
				owner = localPlayer;
				origin = ((Component)localPlayer).transform.position;
				health = ((Character)localPlayer).GetHealth();
				position = ((Component)GameCamera.instance).transform.position;
				Vector3 eulerAngles = ((Component)GameCamera.instance).transform.eulerAngles;
				yaw = eulerAngles.y;
				pitch = Mathf.DeltaAngle(0f, eulerAngles.x);
				localPlayer.m_autoRun = false;
				((Character)localPlayer).m_moveDir = Vector3.zero;
				Active = true;
				Plugin.Message("Build camera · " + ((object)Plugin.Instance.CameraKey.Value/*cast due to .constrained prefix*/).ToString() + " / Esc to exit", "Камера строительства · " + ((object)Plugin.Instance.CameraKey.Value/*cast due to .constrained prefix*/).ToString() + " / Esc — выход");
			}
		}

		private static bool ShortcutDown()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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)
			KeyboardShortcut value = Plugin.Instance.CameraKey.Value;
			if (!ZInput.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey, true))
			{
				return false;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!ZInput.GetKey(modifier, true))
				{
					return false;
				}
			}
			return true;
		}

		internal static void Exit()
		{
			Active = false;
			owner = null;
		}

		internal static void Update(GameCamera camera, float dt)
		{
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: 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_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)owner))
			{
				Exit();
				return;
			}
			dt = Mathf.Min(dt, 0.05f);
			if (!InputGuard.Busy() && !Hud.IsPieceSelectionVisible() && !Hud.InRadial())
			{
				Vector2 mouseDelta = ZInput.GetMouseDelta();
				if (!ZInput.GetButton("JoyRotate"))
				{
					yaw += mouseDelta.x * 1.5f + ZInput.GetJoyRightStickX() * 110f * dt;
					pitch = Mathf.Clamp(pitch - mouseDelta.y * 1.5f + ZInput.GetJoyRightStickY() * 110f * dt, -85f, 85f);
				}
				Vector2 joyLeftStick = ZInput.GetJoyLeftStick();
				float num = Axis("Right", "Left") + joyLeftStick.x;
				float num2 = Axis("Forward", "Backward") + joyLeftStick.y;
				float num3 = Axis("Jump", "Crouch");
				if (ZInput.IsGamepadActive())
				{
					num3 += Axis("JoyJump", "JoyCrouch");
				}
				Vector3 val = Quaternion.Euler(0f, yaw, 0f) * new Vector3(num, 0f, num2) + Vector3.up * num3;
				float num4 = ((ZInput.GetButton("Run") || ZInput.GetButton("JoyRun")) ? 18 : 8);
				Vector3 val2 = position + Vector3.ClampMagnitude(val, 1f) * num4 * dt;
				val2 = ((Component)owner).transform.position + Vector3.ClampMagnitude(val2 - ((Component)owner).transform.position, 40f);
				Vector3 val3 = val2 - position;
				int mask = LayerMask.GetMask(new string[4] { "Default", "static_solid", "terrain", "piece" });
				RaycastHit val4 = default(RaycastHit);
				if (((Vector3)(ref val3)).sqrMagnitude > 1E-05f && Physics.SphereCast(position, 0.15f, ((Vector3)(ref val3)).normalized, ref val4, ((Vector3)(ref val3)).magnitude, mask, (QueryTriggerInteraction)1))
				{
					val2 = position + ((Vector3)(ref val3)).normalized * Mathf.Max(0f, ((RaycastHit)(ref val4)).distance - 0.03f);
				}
				position = val2;
			}
			((Component)camera).transform.SetPositionAndRotation(position, Quaternion.Euler(pitch, yaw, 0f));
			camera.m_camera.fieldOfView = camera.m_fov;
			camera.m_skyCamera.fieldOfView = camera.m_fov;
		}

		private static float Axis(string positive, string negative)
		{
			return (ZInput.GetButton(positive) ? 1 : 0) - (ZInput.GetButton(negative) ? 1 : 0);
		}

		internal static float Reach(Player player)
		{
			//IL_000b: 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)
			return Mathf.Min(52f, Vector3.Distance(((Character)player).m_eye.position, position) + 12f);
		}
	}
	[HarmonyPatch(typeof(GameCamera), "UpdateCamera")]
	internal static class BuildCameraPatch
	{
		private static bool Prefix(GameCamera __instance, float dt)
		{
			if (!BuildCameraMode.Active)
			{
				return true;
			}
			BuildCameraMode.Update(__instance, dt);
			return false;
		}
	}
	[HarmonyPatch(typeof(Player), "SetControls")]
	internal static class CameraControlsPatch
	{
		private static void Prefix(Player __instance, ref Vector3 movedir, ref bool jump, ref bool crouch, ref bool run, ref bool autoRun, ref bool dodge)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (BuildCameraMode.Active && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				movedir = Vector3.zero;
				jump = (crouch = (run = (autoRun = (dodge = false))));
				__instance.m_autoRun = false;
			}
		}
	}
	[HarmonyPatch(typeof(Player), "SetMouseLook")]
	internal static class CameraLookPatch
	{
		private static bool Prefix(Player __instance)
		{
			if (BuildCameraMode.Active)
			{
				return (Object)(object)__instance != (Object)(object)Player.m_localPlayer;
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal static class CameraReachPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(Player), "PieceRayTest", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Player), "UpdateWearNTearHover", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Player), "RemovePiece", (Type[])null, (Type[])null);
		}

		private static void Prefix(Player __instance, out float? __state)
		{
			__state = null;
			if (BuildCameraMode.Active && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				__state = __instance.m_maxPlaceDistance;
				__instance.m_maxPlaceDistance = Mathf.Max(__instance.m_maxPlaceDistance, BuildCameraMode.Reach(__instance));
			}
		}

		private static Exception Finalizer(Player __instance, float? __state, Exception __exception)
		{
			if (__state.HasValue)
			{
				__instance.m_maxPlaceDistance = __state.Value;
			}
			return __exception;
		}
	}
	internal static class ComfortUi
	{
		private static GameObject root;

		private static Canvas canvas;

		private static RectTransform clock;

		private static RectTransform backpack;

		private static RectTransform chest;

		private static TextMeshProUGUI clockText;

		private static Button sortButton;

		private static Button trashButton;

		private static Button undoButton;

		private static Button chestButton;

		private static TMP_FontAsset font;

		private static Sprite rounded;

		private static Texture2D texture;

		private static float nextClock;

		private static bool wasInventory;

		private static Player previousPlayer;

		private static bool russian;

		private static readonly Vector3[] corners = (Vector3[])(object)new Vector3[4];

		internal static void Tick()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead())
			{
				Hide();
				InventoryActions.ClearUndo();
				return;
			}
			bool flag = InventoryGui.IsVisible();
			if ((wasInventory && !flag) || (Object)(object)previousPlayer != (Object)(object)localPlayer)
			{
				InventoryActions.ClearUndo();
			}
			wasInventory = flag;
			previousPlayer = localPlayer;
			if (!Plugin.Enabled(Feature.Clock) && !Plugin.Enabled(Feature.Sorting) && !Plugin.Enabled(Feature.Trash))
			{
				Hide();
			}
			else
			{
				if (!Object.op_Implicit((Object)(object)root) && !Create())
				{
					return;
				}
				root.SetActive(true);
				bool flag2 = InputGuard.Busy(inventory: false);
				bool flag3 = Plugin.Enabled(Feature.Clock) && Object.op_Implicit((Object)(object)Hud.instance) && Hud.instance.IsVisible() && !flag2;
				((Component)clock).gameObject.SetActive(flag3);
				if (flag3)
				{
					PositionClock();
					((Graphic)((Component)clock).GetComponent<Image>()).raycastTarget = flag;
					if (Object.op_Implicit((Object)(object)EnvMan.instance) && Time.unscaledTime >= nextClock)
					{
						nextClock = Time.unscaledTime + 0.25f;
						((TMP_Text)clockText).text = Policies.ClockText(EnvMan.instance.GetDayFraction(), EnvMan.instance.GetDay(), Plugin.Russian);
					}
				}
				bool flag4 = flag && !flag2;
				((Component)backpack).gameObject.SetActive(flag4 && (Plugin.Enabled(Feature.Sorting) || Plugin.Enabled(Feature.Trash)));
				((Component)chest).gameObject.SetActive(flag4 && Plugin.Enabled(Feature.Sorting) && Object.op_Implicit((Object)(object)InventoryGui.instance.m_currentContainer));
				if (flag4)
				{
					if (russian != Plugin.Russian)
					{
						SetLabels();
					}
					bool flag5 = InventoryGui.instance.m_dragItem != null;
					((Component)sortButton).gameObject.SetActive(Plugin.Enabled(Feature.Sorting));
					((Component)trashButton).gameObject.SetActive(Plugin.Enabled(Feature.Trash));
					((Component)undoButton).gameObject.SetActive(Plugin.Enabled(Feature.Trash));
					((Selectable)sortButton).interactable = !flag5;
					((Selectable)trashButton).interactable = true;
					((Selectable)undoButton).interactable = InventoryActions.CanUndo && !flag5;
					((Selectable)chestButton).interactable = !flag5 && InventoryActions.ChestUsable(InventoryGui.instance.m_currentContainer);
					Follow(backpack, InventoryGui.instance.m_player);
					if (((Component)chest).gameObject.activeSelf)
					{
						Follow(chest, InventoryGui.instance.m_container);
					}
				}
			}
		}

		private static bool Create()
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI val = (Object.op_Implicit((Object)(object)InventoryGui.instance) ? ((Component)InventoryGui.instance).GetComponentInChildren<TextMeshProUGUI>(true) : null);
			if (!Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)Hud.instance))
			{
				val = ((Component)Hud.instance).GetComponentInChildren<TextMeshProUGUI>(true);
			}
			font = (Object.op_Implicit((Object)(object)val) ? ((TMP_Text)val).font : TMP_Settings.defaultFontAsset);
			if (!Object.op_Implicit((Object)(object)font))
			{
				return false;
			}
			root = new GameObject("Hugin.ComfyKit.UI", new Type[1] { typeof(RectTransform) });
			Object.DontDestroyOnLoad((Object)(object)root);
			canvas = root.AddComponent<Canvas>();
			canvas.renderMode = (RenderMode)0;
			canvas.sortingOrder = 25;
			CanvasScaler obj = root.AddComponent<CanvasScaler>();
			obj.uiScaleMode = (ScaleMode)1;
			obj.referenceResolution = new Vector2(1920f, 1080f);
			obj.matchWidthOrHeight = 0.5f;
			root.AddComponent<GraphicRaycaster>();
			MakeSprite();
			clock = Panel("Clock", new Vector2(210f, 34f));
			clockText = Label(clock, "", 18f);
			((Component)clock).gameObject.AddComponent<ClockDrag>();
			backpack = Panel("Backpack tools", new Vector2(348f, 36f));
			sortButton = Button(backpack, "Sort", 4f, 108f, delegate
			{
				InventoryActions.Sort(chest: false);
			});
			trashButton = Button(backpack, "Trash", 120f, 108f, InventoryActions.Trash);
			UIDragHandler obj2 = ((Component)trashButton).gameObject.AddComponent<UIDragHandler>();
			obj2.m_onReleasedOn = (Action<UIDragHandler>)Delegate.Combine(obj2.m_onReleasedOn, (Action<UIDragHandler>)delegate
			{
				InventoryActions.Trash();
			});
			undoButton = Button(backpack, "Undo", 236f, 108f, InventoryActions.Undo);
			chest = Panel("Chest tools", new Vector2(160f, 36f));
			chestButton = Button(chest, "Sort chest", 4f, 152f, delegate
			{
				InventoryActions.Sort(chest: true);
			});
			SetLabels();
			return true;
		}

		private static void SetLabels()
		{
			russian = Plugin.Russian;
			((TMP_Text)((Component)sortButton).GetComponentInChildren<TextMeshProUGUI>()).text = Plugin.L("Sort", "Сортировать");
			((TMP_Text)((Component)trashButton).GetComponentInChildren<TextMeshProUGUI>()).text = Plugin.L("Trash", "Удалить");
			((TMP_Text)((Component)undoButton).GetComponentInChildren<TextMeshProUGUI>()).text = Plugin.L("Undo", "Вернуть");
			((TMP_Text)((Component)chestButton).GetComponentInChildren<TextMeshProUGUI>()).text = Plugin.L("Sort chest", "Сортировать сундук");
		}

		private static RectTransform Panel(string name, Vector2 size)
		{
			//IL_0021: 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_003c: 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_0048: Expected O, but got Unknown
			//IL_0049: 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)
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(root.transform, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.sizeDelta = size;
			Image component = val.GetComponent<Image>();
			component.sprite = rounded;
			component.type = (Type)1;
			((Graphic)component).color = new Color(0.09f, 0.095f, 0.105f, 0.96f);
			return val2;
		}

		private static TextMeshProUGUI Label(RectTransform parent, string text, float size)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Label", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent((Transform)(object)parent, false);
			TextMeshProUGUI obj = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj).font = font;
			((TMP_Text)obj).text = text;
			((TMP_Text)obj).fontSize = size;
			((Graphic)obj).color = new Color(0.9f, 0.91f, 0.92f);
			((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
			((Graphic)obj).raycastTarget = false;
			((TMP_Text)obj).richText = false;
			((TMP_Text)obj).overflowMode = (TextOverflowModes)1;
			((TMP_Text)obj).rectTransform.anchorMin = Vector2.zero;
			((TMP_Text)obj).rectTransform.anchorMax = Vector2.one;
			((TMP_Text)obj).rectTransform.offsetMin = new Vector2(4f, 0f);
			((TMP_Text)obj).rectTransform.offsetMax = new Vector2(-4f, 0f);
			return obj;
		}

		private static Button Button(RectTransform parent, string name, float x, float width, Action action)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			val.transform.SetParent((Transform)(object)parent, false);
			RectTransform val2 = (RectTransform)val.transform;
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0f, 0.5f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(0f, 0.5f);
			val2.anchoredPosition = new Vector2(x, 0f);
			val2.sizeDelta = new Vector2(width, 28f);
			Image component = val.GetComponent<Image>();
			component.sprite = rounded;
			component.type = (Type)1;
			((Graphic)component).color = new Color(0.23f, 0.24f, 0.25f);
			Button component2 = val.GetComponent<Button>();
			((Selectable)component2).targetGraphic = (Graphic)(object)component;
			Navigation navigation = default(Navigation);
			((Navigation)(ref navigation)).mode = (Mode)0;
			((Selectable)component2).navigation = navigation;
			((UnityEvent)component2.onClick).AddListener((UnityAction)delegate
			{
				action();
			});
			Label(val2, name, 16f);
			return component2;
		}

		private static void Follow(RectTransform tools, RectTransform panel)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			panel.GetWorldCorners(corners);
			Canvas componentInParent = ((Component)panel).GetComponentInParent<Canvas>();
			Camera obj = ((Object.op_Implicit((Object)(object)componentInParent) && (int)componentInParent.renderMode != 0) ? componentInParent.worldCamera : null);
			Vector2 val = RectTransformUtility.WorldToScreenPoint(obj, corners[0]);
			Vector2 val2 = RectTransformUtility.WorldToScreenPoint(obj, corners[3]);
			Vector2 point = default(Vector2);
			((Vector2)(ref point))..ctor((val.x + val2.x) * 0.5f, val.y - 24f * canvas.scaleFactor);
			SetScreenPosition(tools, point);
		}

		internal static void PositionClock()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			SetScreenPosition(clock, new Vector2(UiState.Value.ClockX * (float)Screen.width, UiState.Value.ClockY * (float)Screen.height));
		}

		private static void SetScreenPosition(RectTransform rect, Vector2 point)
		{
			//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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			Rect rect2 = rect.rect;
			float num = ((Rect)(ref rect2)).width * canvas.scaleFactor * 0.5f + 4f;
			rect2 = rect.rect;
			float num2 = ((Rect)(ref rect2)).height * canvas.scaleFactor * 0.5f + 4f;
			point.x = Mathf.Clamp(point.x, num, Mathf.Max(num, (float)Screen.width - num));
			point.y = Mathf.Clamp(point.y, num2, Mathf.Max(num2, (float)Screen.height - num2));
			Vector2 anchoredPosition = default(Vector2);
			RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)root.transform, point, (Camera)null, ref anchoredPosition);
			rect.anchoredPosition = anchoredPosition;
		}

		private static void MakeSprite()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			texture = new Texture2D(32, 32, (TextureFormat)4, false);
			((Texture)texture).wrapMode = (TextureWrapMode)1;
			for (int i = 0; i < 32; i++)
			{
				for (int j = 0; j < 32; j++)
				{
					float num = Mathf.Max(0f, Mathf.Abs((float)j - 15.5f) - 9.5f);
					float num2 = Mathf.Max(0f, Mathf.Abs((float)i - 15.5f) - 9.5f);
					texture.SetPixel(j, i, new Color(1f, 1f, 1f, Mathf.Clamp01(6.5f - Mathf.Sqrt(num * num + num2 * num2))));
				}
			}
			texture.Apply();
			rounded = Sprite.Create(texture, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4(8f, 8f, 8f, 8f));
		}

		internal static bool PointerOverTools()
		{
			//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)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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)
			Vector2 val = Vector2.op_Implicit(ZInput.pointerPosition);
			if (Object.op_Implicit((Object)(object)root) && root.activeInHierarchy)
			{
				if ((!((Component)backpack).gameObject.activeInHierarchy || !RectTransformUtility.RectangleContainsScreenPoint(backpack, val)) && (!((Component)chest).gameObject.activeInHierarchy || !RectTransformUtility.RectangleContainsScreenPoint(chest, val)))
				{
					if (((Component)clock).gameObject.activeInHierarchy)
					{
						return RectTransformUtility.RectangleContainsScreenPoint(clock, val);
					}
					return false;
				}
				return true;
			}
			return false;
		}

		internal static void Hide()
		{
			if (Object.op_Implicit((Object)(object)root))
			{
				root.SetActive(false);
			}
		}

		internal static void Dispose()
		{
			if (Object.op_Implicit((Object)(object)root))
			{
				Object.Destroy((Object)(object)root);
			}
			if (Object.op_Implicit((Object)(object)rounded))
			{
				Object.Destroy((Object)(object)rounded);
			}
			if (Object.op_Implicit((Object)(object)texture))
			{
				Object.Destroy((Object)(object)texture);
			}
			root = null;
		}
	}
	internal sealed class ClockDrag : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler
	{
		private Vector2 offset;

		private bool dragging;

		public void OnBeginDrag(PointerEventData e)
		{
			//IL_0002: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			dragging = (int)e.button == 0 && InventoryGui.IsVisible() && !InputGuard.Busy(inventory: false);
			offset = Vector2.op_Implicit(((Component)this).transform.position) - e.position;
		}

		public void OnDrag(PointerEventData e)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			if (dragging && InventoryGui.IsVisible() && !InputGuard.Busy(inventory: false))
			{
				Vector2 val = e.position + offset;
				UiState.Move(val.x / (float)Mathf.Max(1, Screen.width), val.y / (float)Mathf.Max(1, Screen.height));
				ComfortUi.PositionClock();
			}
		}

		public void OnEndDrag(PointerEventData e)
		{
			dragging = false;
			UiState.Save();
		}
	}
	internal static class FarmGrid
	{
		private static readonly Collider[] nearby = (Collider[])(object)new Collider[256];

		private static readonly LineRenderer[] lines = (LineRenderer[])(object)new LineRenderer[14];

		private static GameObject root;

		private static Material material;

		private static GameObject selected;

		private static Vector3 anchor;

		private static Vector3 searchCenter;

		private static Vector3 lastPoint;

		private static float nextAnchor;

		private static float nextVisual;

		private static float lastHit;

		private static float spacing;

		private static bool anchored;

		internal static Plant Selected(Player player)
		{
			if (!Plugin.Enabled(Feature.FarmGrid) || !Object.op_Implicit((Object)(object)player) || (Object)(object)player != (Object)(object)Player.m_localPlayer || !Object.op_Implicit((Object)(object)player.m_buildPieces) || !Object.op_Implicit((Object)(object)player.m_placementGhost) || !((Character)player).InPlaceMode())
			{
				return null;
			}
			GameObject selectedPrefab = player.m_buildPieces.GetSelectedPrefab();
			Plant val = (Object.op_Implicit((Object)(object)selectedPrefab) ? selectedPrefab.GetComponent<Plant>() : null);
			if (!Object.op_Implicit((Object)(object)val) || !(val.m_attachDistance <= 0f))
			{
				return null;
			}
			return val;
		}

		internal static bool FreePlace(Player p)
		{
			if (!ZInput.IsNonClassicFunctionality() || !ZInput.IsGamepadActive())
			{
				if (!ZInput.GetButton("AltPlace"))
				{
					if (ZInput.GetButton("JoyAltPlace"))
					{
						return !ZInput.GetButton("JoyRotate");
					}
					return false;
				}
				return true;
			}
			return p.m_altPlace;
		}

		internal static void Snap(Player player, ref Vector3 point, ref Vector3 normal, ref Piece piece, ref Heightmap heightmap, ref Collider waterSurface)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			Plant val = Selected(player);
			if (!Object.op_Implicit((Object)(object)val) || FreePlace(player) || !Object.op_Implicit((Object)(object)heightmap))
			{
				return;
			}
			spacing = Mathf.Max(1f, val.m_growRadius * 2f + 0.15f);
			if (!Policies.Finite(spacing) || spacing > 30f)
			{
				return;
			}
			Vector3 val2;
			if (!((Object)(object)selected != (Object)(object)((Component)val).gameObject))
			{
				val2 = point - searchCenter;
				if (!(((Vector3)(ref val2)).sqrMagnitude > 900f))
				{
					goto IL_00b5;
				}
			}
			selected = ((Component)val).gameObject;
			searchCenter = point;
			anchored = false;
			nextAnchor = 0f;
			goto IL_00b5;
			IL_00b5:
			if (!anchored && Time.unscaledTime >= nextAnchor)
			{
				nextAnchor = Time.unscaledTime + 0.25f;
				anchor = Vector3.zero;
				int num = Physics.OverlapSphereNonAlloc(point, Mathf.Max(8f, spacing * 2f), nearby, LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid" }), (QueryTriggerInteraction)1);
				float num2 = float.MaxValue;
				for (int i = 0; i < num; i++)
				{
					Plant componentInParent = ((Component)nearby[i]).GetComponentInParent<Plant>();
					if (Object.op_Implicit((Object)(object)componentInParent) && !((Object)(object)((Component)componentInParent).gameObject == (Object)(object)player.m_placementGhost) && !(componentInParent.m_name != val.m_name) && Object.op_Implicit((Object)(object)componentInParent.m_nview) && componentInParent.m_nview.IsValid())
					{
						val2 = ((Component)componentInParent).transform.position - point;
						float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
						if (sqrMagnitude < num2)
						{
							num2 = sqrMagnitude;
							anchor = ((Component)componentInParent).transform.position;
							anchored = true;
						}
					}
				}
			}
			Vector3 val3 = point;
			val3.x = (float)Policies.Snap(point.x, anchor.x, spacing);
			val3.z = (float)Policies.Snap(point.z, anchor.z, spacing);
			RaycastHit val4 = default(RaycastHit);
			if (Physics.Raycast(val3 + Vector3.up * 4f, Vector3.down, ref val4, 8f, LayerMask.GetMask(new string[1] { "terrain" }), (QueryTriggerInteraction)1))
			{
				float num3 = (BuildCameraMode.Active ? BuildCameraMode.Reach(player) : player.m_maxPlaceDistance);
				if (!(Vector3.Distance(((Character)player).m_eye.position, ((RaycastHit)(ref val4)).point) > num3))
				{
					point = ((RaycastHit)(ref val4)).point;
					normal = ((RaycastHit)(ref val4)).normal;
					piece = null;
					waterSurface = null;
					heightmap = ((Component)((RaycastHit)(ref val4)).collider).GetComponent<Heightmap>();
					lastPoint = point;
					lastHit = Time.unscaledTime;
				}
			}
		}

		internal static void Validate(Player player)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)Selected(player)) && !FreePlace(player) && (int)player.m_placementStatus == 0)
			{
				Plant component = player.m_placementGhost.GetComponent<Plant>();
				if (Object.op_Implicit((Object)(object)component) && !component.HaveGrowSpace())
				{
					player.m_placementStatus = (PlacementStatus)5;
					player.SetPlacementGhostValid(false);
				}
			}
		}

		internal static void TickVisual()
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)Selected(localPlayer)) || FreePlace(localPlayer) || InputGuard.Busy() || !localPlayer.m_placementGhost.activeInHierarchy || Time.unscaledTime - lastHit > 0.3f)
			{
				Hide();
			}
			else
			{
				if (Time.unscaledTime < nextVisual)
				{
					return;
				}
				nextVisual = Time.unscaledTime + 0.1f;
				if (!Object.op_Implicit((Object)(object)root) && !Create())
				{
					return;
				}
				root.SetActive(true);
				Color val = (((int)localPlayer.m_placementStatus == 0) ? new Color(0.72f, 0.82f, 0.76f, 0.5f) : new Color(0.8f, 0.4f, 0.35f, 0.5f));
				RaycastHit val5 = default(RaycastHit);
				for (int i = 0; i < 14; i++)
				{
					LineRenderer val2 = lines[i];
					Color startColor = (val2.endColor = val);
					val2.startColor = startColor;
					int num = i % 7 - 3;
					for (int j = 0; j < 13; j++)
					{
						Vector3 val4 = lastPoint + ((i < 7) ? new Vector3((float)num * spacing, 0f, ((float)j * 0.5f - 3f) * spacing) : new Vector3(((float)j * 0.5f - 3f) * spacing, 0f, (float)num * spacing));
						if (Physics.Raycast(val4 + Vector3.up * 5f, Vector3.down, ref val5, 10f, LayerMask.GetMask(new string[1] { "terrain" }), (QueryTriggerInteraction)1))
						{
							val4.y = ((RaycastHit)(ref val5)).point.y;
						}
						val4.y += 0.035f;
						val2.SetPosition(j, val4);
					}
				}
			}
		}

		private static bool Create()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			Shader val = Shader.Find("Sprites/Default");
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			material = new Material(val);
			root = new GameObject("ComfyKit.PlantingGrid");
			for (int i = 0; i < lines.Length; i++)
			{
				GameObject val2 = new GameObject("Grid line");
				val2.transform.SetParent(root.transform);
				LineRenderer val3 = val2.AddComponent<LineRenderer>();
				lines[i] = val3;
				((Renderer)val3).sharedMaterial = material;
				val3.positionCount = 13;
				val3.widthMultiplier = 0.022f;
				val3.useWorldSpace = true;
				((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)val3).receiveShadows = false;
			}
			return true;
		}

		internal static void Hide()
		{
			if (Object.op_Implicit((Object)(object)root))
			{
				root.SetActive(false);
			}
		}

		internal static void Dispose()
		{
			if (Object.op_Implicit((Object)(object)root))
			{
				Object.Destroy((Object)(object)root);
			}
			if (Object.op_Implicit((Object)(object)material))
			{
				Object.Destroy((Object)(object)material);
			}
			root = null;
			selected = null;
			anchored = false;
		}
	}
	[HarmonyPatch(typeof(Player), "PieceRayTest")]
	internal static class FarmRayPatch
	{
		private static void Postfix(Player __instance, bool __result, ref Vector3 point, ref Vector3 normal, ref Piece piece, ref Heightmap heightmap, ref Collider waterSurface)
		{
			if (__result)
			{
				FarmGrid.Snap(__instance, ref point, ref normal, ref piece, ref heightmap, ref waterSurface);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
	internal static class FarmValidationPatch
	{
		private static void Postfix(Player __instance)
		{
			FarmGrid.Validate(__instance);
		}
	}
	internal static class InventoryActions
	{
		private static ItemData deleted;

		private static Player owner;

		internal static bool CanUndo
		{
			get
			{
				if (deleted != null && Object.op_Implicit((Object)(object)owner))
				{
					return (Object)(object)owner == (Object)(object)Player.m_localPlayer;
				}
				return false;
			}
		}

		internal static bool Usable
		{
			get
			{
				if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && !((Character)Player.m_localPlayer).IsDead() && !((Character)Player.m_localPlayer).IsTeleporting() && InventoryGui.IsVisible())
				{
					return !InputGuard.Busy(inventory: false);
				}
				return false;
			}
		}

		internal static void ClearUndo()
		{
			deleted = null;
			owner = null;
		}

		internal static bool ChestUsable(Container chest)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)chest) && chest.IsOwner() && chest.CheckAccess(Player.m_localPlayer.GetPlayerID()))
			{
				if (chest.m_checkGuardStone)
				{
					return PrivateArea.CheckAccess(((Component)chest).transform.position, 0f, false, false);
				}
				return true;
			}
			return false;
		}

		internal static void Sort(bool chest)
		{
			//IL_00bc: 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)
			if (!Plugin.Enabled(Feature.Sorting) || !Usable || InventoryGui.instance.m_dragItem != null)
			{
				return;
			}
			InventoryGui instance = InventoryGui.instance;
			if (chest && !ChestUsable(instance.m_currentContainer))
			{
				return;
			}
			Inventory val = (chest ? instance.m_currentContainer.GetInventory() : ((Humanoid)Player.m_localPlayer).GetInventory());
			ItemData[] array = val.GetAllItems().ToArray();
			try
			{
				foreach (SlotMove item in Policies.PlanSort(array.Select((ItemData item, int index) => new SlotItem
				{
					Id = index,
					X = item.m_gridPos.x,
					Y = item.m_gridPos.y,
					Category = (int)item.m_shared.m_itemType,
					Quality = item.m_quality,
					Variant = item.m_variant,
					Name = Localization.instance.Localize(item.m_shared.m_name),
					Fixed = item.m_equipped
				}), val.GetWidth(), val.GetHeight(), !chest))
				{
					array[item.Id].m_gridPos = new Vector2i(item.X, item.Y);
				}
				val.Changed(false, false);
			}
			catch (Exception ex)
			{
				Plugin.Warn("Sort cancelled: " + ex.Message);
			}
		}

		internal static void Trash()
		{
			if (!Plugin.Enabled(Feature.Trash) || !Usable)
			{
				return;
			}
			InventoryGui instance = InventoryGui.instance;
			Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory();
			ItemData dragItem = instance.m_dragItem;
			if (dragItem == null)
			{
				Plugin.Message("Drag an item onto Trash", "Перетащите предмет на «Удалить»");
				return;
			}
			if (instance.m_dragInventory != inventory || !inventory.ContainsItem(dragItem))
			{
				Plugin.Message("Move the item to your backpack first", "Сначала переместите предмет в рюкзак");
				return;
			}
			if (dragItem.m_equipped || dragItem.m_shared.m_questItem)
			{
				Plugin.Message("Equipped and quest items are protected", "Надетые и квестовые предметы защищены");
				return;
			}
			int num = Mathf.Clamp(instance.m_dragAmount, 1, dragItem.m_stack);
			ItemData val = dragItem.Clone();
			val.m_stack = num;
			val.m_equipped = false;
			if (inventory.RemoveItem(dragItem, num))
			{
				deleted = val;
				owner = Player.m_localPlayer;
				instance.SetupDragItem((ItemData)null, (Inventory)null, 1);
				Plugin.Message("Item removed · Undo is available until you close the inventory", "Предмет удалён · Отмена доступна до закрытия инвентаря");
			}
		}

		internal static void Undo()
		{
			//IL_0030: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.Enabled(Feature.Trash) && Usable && CanUndo && InventoryGui.instance.m_dragItem == null)
			{
				Inventory inventory = ((Humanoid)owner).GetInventory();
				Vector2i val = inventory.FindEmptySlot(true);
				if (val.x < 0)
				{
					Plugin.Message("Free one inventory slot to undo", "Для отмены освободите ячейку");
					return;
				}
				deleted.m_gridPos = val;
				inventory.m_inventory.Add(deleted);
				ClearUndo();
				inventory.Changed(false, false);
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "OnDropOutside")]
	internal static class InventoryDropPatch
	{
		private static bool Prefix()
		{
			return !ComfortUi.PointerOverTools();
		}
	}
	[BepInPlugin("treextr.huginsdesk.comfykit", "Hugin’s Desk — Comfy Kit", "0.1.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "treextr.huginsdesk.comfykit";

		public const string Name = "Hugin’s Desk — Comfy Kit";

		public const string Version = "0.1.0";

		internal static Plugin Instance;

		internal readonly Dictionary<Feature, ConfigEntry<bool>> Settings = new Dictionary<Feature, ConfigEntry<bool>>();

		internal readonly Dictionary<Feature, string> Blocked = new Dictionary<Feature, string>();

		private readonly List<Harmony> patches = new List<Harmony>();

		internal ConfigEntry<KeyboardShortcut> CameraKey;

		internal bool Ready;

		internal static bool Russian
		{
			get
			{
				if (Localization.instance != null)
				{
					return Localization.instance.GetSelectedLanguage() == "Russian";
				}
				return false;
			}
		}

		internal static bool Enabled(Feature feature)
		{
			if (Object.op_Implicit((Object)(object)Instance) && Instance.Ready && ((Behaviour)Instance).isActiveAndEnabled && Instance.Settings[feature].Value)
			{
				return !Instance.Blocked.ContainsKey(feature);
			}
			return false;
		}

		internal static string L(string en, string ru)
		{
			if (!Russian)
			{
				return en;
			}
			return ru;
		}

		internal static void Message(string en, string ru)
		{
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				((Character)Player.m_localPlayer).Message((MessageType)1, L(en, ru), 0, (Sprite)null, false);
			}
		}

		private void Awake()
		{
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Bind(Feature.AutoRepair, "1. Inventory", "Auto repair", "Repair eligible worn equipment when opening its station. Station requirements are preserved.");
			Bind(Feature.Trash, "1. Inventory", "Trash items", "Drop an item onto Trash in the inventory. Undo restores the last deletion while the inventory stays open. Equipped and quest items are protected.");
			Bind(Feature.Sorting, "1. Inventory", "Sort inventory", "Sort the backpack or the open chest. Your hotbar, equipped items, custom data and extra equipment rows stay untouched. Stacks are never merged.");
			Bind(Feature.FloatingItems, "1. Inventory", "Floating items", "Dropped items float on water. Existing native buoyancy is preserved. Multiplayer: the computer owning a drop must have this feature enabled.");
			Bind(Feature.WaterEquipment, "2. Building and farming", "Equipment in water", "Use equipment while swimming. Swimming physics and stamina remain unchanged.");
			Bind(Feature.Ladders, "2. Building and farming", "Smooth ladders", "Walk up steep ladders with a gentle assisted step. No push while standing still.");
			Bind(Feature.BuildCamera, "2. Building and farming", "Build camera", "Press B with a build tool equipped. WASD / left stick to move, Jump/Crouch to rise/lower, Run to speed up. B or Esc exits. Character stays put; costs, wards and station requirements remain.");
			Bind(Feature.FarmGrid, "2. Building and farming", "Planting grid", "Snap plants to a visible grid with safe spacing, aligned to nearby plants. Hold the game's alternate placement key to plant freely.");
			Bind(Feature.Clock, "3. Information", "Clock", "Compact game time and day. Drag it with the inventory open; position survives restarts.");
			Bind(Feature.Fermenter, "3. Information", "Fermenter progress", "Show progress and remaining time when looking at a fermenter. Roof and access requirements remain visible.");
			CameraKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("4. Controls", "Build camera shortcut", new KeyboardShortcut((KeyCode)98, Array.Empty<KeyCode>()), "Change the build camera shortcut if another mod uses B.");
		}

		private void Bind(Feature feature, string section, string label, string description)
		{
			Settings[feature] = ((BaseUnityPlugin)this).Config.Bind<bool>(section, label, true, description + "\nChanges apply immediately. Known duplicate mods automatically take priority for this feature.");
			Settings[feature].SettingChanged += delegate
			{
				RefreshFeatures();
			};
		}

		private void Start()
		{
			DetectConflicts();
			Install(Feature.AutoRepair, typeof(RepairPatch));
			Install(Feature.WaterEquipment, typeof(WaterEquipmentPatches));
			Install(Feature.FloatingItems, typeof(BuoyancyPatch));
			Install(Feature.Ladders, typeof(LadderPatch));
			Install(Feature.Fermenter, typeof(FermenterPatch));
			Install(Feature.FarmGrid, typeof(FarmRayPatch), typeof(FarmValidationPatch));
			Install(Feature.BuildCamera, typeof(BuildCameraPatch), typeof(CameraControlsPatch), typeof(CameraLookPatch), typeof(CameraReachPatch));
			Install(Feature.Trash, typeof(InventoryDropPatch));
			Ready = true;
			UiState.Load();
			RefreshFeatures();
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Hugin’s Desk — Comfy Kit 0.1.0: 10 feature switches; " + Blocked.Count + " suppressed or unavailable."));
		}

		private void Install(Feature feature, params Type[] types)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			if (Blocked.ContainsKey(feature))
			{
				return;
			}
			Harmony val = new Harmony("treextr.huginsdesk.comfykit." + feature);
			try
			{
				foreach (Type type in types)
				{
					val.CreateClassProcessor(type).Patch();
				}
				patches.Add(val);
			}
			catch (Exception ex)
			{
				val.UnpatchSelf();
				Blocked[feature] = "Game API patch failed";
				((BaseUnityPlugin)this).Logger.LogError((object)(feature.ToString() + " disabled: " + ex));
			}
		}

		private void DetectConflicts()
		{
			foreach (PluginInfo value in Chainloader.PluginInfos.Values)
			{
				if (!(value.Metadata.GUID == "treextr.huginsdesk.comfykit"))
				{
					string key = (value.Metadata.GUID + " " + value.Metadata.Name).ToLowerInvariant().Replace(" ", "").Replace("_", "")
						.Replace("-", "");
					Check(Feature.AutoRepair, value, key, "autorepair", "workbenchinventoryrepair");
					Check(Feature.WaterEquipment, value, key, "useequipmentinwater", "wieldequipmentwhileswimming", "underthesea", "hs.equipinwater", "divein");
					Check(Feature.Trash, value, key, "trashitems", "quickstackstore", "discardinventoryitems");
					Check(Feature.Sorting, value, key, "inventorysort", "quickstackstore");
					Check(Feature.Clock, value, key, "clockmod", "pineapple.clock", "displaydaytime", "displaydaytimeinhud");
					Check(Feature.Ladders, value, key, "betterladders", "kgladder");
					Check(Feature.BuildCamera, value, key, "buildcamera", "truecamera");
					Check(Feature.FloatingItems, value, key, "floatingitems");
					Check(Feature.FarmGrid, value, key, "farmgrid", "planteasily", "massfarming");
					Check(Feature.Fermenter, value, key, "fermenterpercentage", "gumshoetimersuite");
				}
			}
			foreach (KeyValuePair<Feature, string> item in Blocked)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)(item.Key.ToString() + ": letting " + item.Value + " handle this feature."));
			}
		}

		private void Check(Feature f, PluginInfo info, string key, params string[] candidates)
		{
			if (candidates.Any(key.Contains))
			{
				Blocked[f] = info.Metadata.Name;
			}
		}

		private void RefreshFeatures()
		{
			if (Ready)
			{
				if (!Enabled(Feature.BuildCamera))
				{
					BuildCameraMode.Exit();
				}
				if (!Enabled(Feature.FarmGrid))
				{
					FarmGrid.Hide();
				}
				BuoyancyPatch.Refresh();
				if (!Enabled(Feature.Trash))
				{
					InventoryActions.ClearUndo();
				}
			}
		}

		private void Update()
		{
			if (Ready)
			{
				BuildCameraMode.Tick();
				ComfortUi.Tick();
				FarmGrid.TickVisual();
				BuoyancyPatch.Tick();
			}
		}

		private void OnApplicationFocus(bool focus)
		{
			if (!focus)
			{
				BuildCameraMode.Exit();
				UiState.Save();
			}
		}

		private void OnDisable()
		{
			if (Ready)
			{
				BuildCameraMode.Exit();
				FarmGrid.Hide();
				BuoyancyPatch.Refresh();
				ComfortUi.Hide();
				UiState.Save();
			}
		}

		private void OnEnable()
		{
			if (Ready)
			{
				RefreshFeatures();
			}
		}

		private void OnDestroy()
		{
			Ready = false;
			BuildCameraMode.Exit();
			BuoyancyPatch.RemoveOwned();
			FarmGrid.Dispose();
			ComfortUi.Dispose();
			UiState.Save();
			foreach (Harmony patch in patches)
			{
				patch.UnpatchSelf();
			}
			InventoryActions.ClearUndo();
			Instance = null;
		}

		internal static void Warn(string text)
		{
			if (Object.op_Implicit((Object)(object)Instance))
			{
				((BaseUnityPlugin)Instance).Logger.LogWarning((object)text);
			}
		}
	}
	internal static class InputGuard
	{
		private static PropertyInfo managerVisible;

		private static object manager;

		private static bool resolved;

		internal static bool ManagerOpen()
		{
			if (!resolved)
			{
				resolved = true;
				foreach (PluginInfo value in Chainloader.PluginInfos.Values)
				{
					PropertyInfo propertyInfo = (Object.op_Implicit((Object)(object)value.Instance) ? ((object)value.Instance).GetType().GetProperty("DisplayingWindow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) : null);
					if (propertyInfo?.PropertyType == typeof(bool))
					{
						manager = value.Instance;
						managerVisible = propertyInfo;
						break;
					}
				}
			}
			try
			{
				return managerVisible != null && (bool)managerVisible.GetValue(manager, null);
			}
			catch
			{
				return false;
			}
		}

		internal static bool Busy(bool inventory = true)
		{
			if (Application.isFocused && !ManagerOpen() && !Console.IsVisible() && !Menu.IsVisible() && !Minimap.IsOpen() && !TextInput.IsVisible() && !StoreGui.IsVisible() && !UnifiedPopup.IsVisible() && (!Object.op_Implicit((Object)(object)Chat.instance) || !Chat.instance.HasFocus()))
			{
				if (inventory)
				{
					return InventoryGui.IsVisible();
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(CraftingStation), "Interact")]
	internal static class RepairPatch
	{
		private static void Postfix(CraftingStation __instance, Humanoid user, bool repeat)
		{
			Player localPlayer = Player.m_localPlayer;
			InventoryGui instance = InventoryGui.instance;
			if (!Plugin.Enabled(Feature.AutoRepair) || !Object.op_Implicit((Object)(object)localPlayer) || (Object)(object)user != (Object)(object)localPlayer || repeat || !Object.op_Implicit((Object)(object)instance) || (Object)(object)localPlayer.GetCurrentCraftingStation() != (Object)(object)__instance || !__instance.CheckUsable(localPlayer, false))
			{
				return;
			}
			List<ItemData> list = new List<ItemData>();
			((Humanoid)localPlayer).GetInventory().GetWornItems(list);
			int num = 0;
			for (int i = 0; i < list.Count; i++)
			{
				if (!instance.HaveRepairableItems())
				{
					break;
				}
				float num2 = list.Sum((ItemData item) => item.m_durability);
				instance.RepairOneItem();
				if (list.Sum((ItemData item) => item.m_durability) <= num2)
				{
					break;
				}
				num++;
			}
			if (num > 0)
			{
				Plugin.Message("Repaired " + num + " items", "Починено предметов: " + num);
			}
		}
	}
	[HarmonyPatch]
	internal static class WaterEquipmentPatches
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(Humanoid), "UpdateEquipment", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Humanoid), "EquipItem", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Player), "Update", (Type[])null, (Type[])null);
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input)
		{
			List<CodeInstruction> list = input.ToList();
			MethodInfo methodInfo = AccessTools.Method(typeof(Character), "IsSwimming", (Type[])null, (Type[])null);
			int num = 0;
			foreach (CodeInstruction item in list)
			{
				if (CodeInstructionExtensions.Calls(item, methodInfo))
				{
					item.opcode = OpCodes.Call;
					item.operand = AccessTools.Method(typeof(WaterEquipmentPatches), "BlocksEquipment", (Type[])null, (Type[])null);
					num++;
				}
			}
			if (num != 1)
			{
				throw new InvalidOperationException("Expected one swimming equipment guard; found " + num);
			}
			return list;
		}

		internal static bool BlocksEquipment(Character character)
		{
			if (!Plugin.Enabled(Feature.WaterEquipment) || !((Object)(object)character == (Object)(object)Player.m_localPlayer))
			{
				return character.IsSwimming();
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Fermenter), "GetHoverText")]
	internal static class FermenterPatch
	{
		private static void Postfix(Fermenter __instance, ref string __result)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Invalid comparison between Unknown and I4
			if (!Plugin.Enabled(Feature.Fermenter) || string.IsNullOrEmpty(__result) || !Object.op_Implicit((Object)(object)__instance.m_nview) || !__instance.m_nview.IsValid() || !PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, false, false) || (int)__instance.GetStatus() != 1)
			{
				return;
			}
			string text = Policies.FermentationText(__instance.GetFermentationTime(), __instance.m_fermentationDuration, Plugin.Russian);
			if (text.Length > 0)
			{
				if (!__instance.m_hasRoof || __instance.m_exposed)
				{
					text = Plugin.L("Needs shelter · ", "Нужно укрытие · ") + text;
				}
				__result = __result + "\n<color=#bfc6cc>" + text + "</color>";
			}
		}
	}
	[HarmonyPatch(typeof(AutoJumpLedge), "OnTriggerStay")]
	internal static class LadderPatch
	{
		private static float lastStep = float.NegativeInfinity;

		private static bool Prefix(AutoJumpLedge __instance, Collider collider)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: 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_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Enabled(Feature.Ladders))
			{
				return true;
			}
			Player component = ((Component)collider).GetComponent<Player>();
			if (!Object.op_Implicit((Object)(object)component) || (Object)(object)component != (Object)(object)Player.m_localPlayer || !Object.op_Implicit((Object)(object)((Character)component).m_nview) || !((Character)component).m_nview.IsOwner())
			{
				return true;
			}
			if (InputGuard.Busy() || BuildCameraMode.Active || ((Character)component).IsDead() || ((Character)component).IsTeleporting() || ((Character)component).IsAttached() || ((Character)component).IsSwimming())
			{
				return true;
			}
			if (((Character)component).InAttack() || ((Character)component).InDodge() || ((Character)component).IsKnockedBack() || ((Character)component).IsStaggering())
			{
				return true;
			}
			Vector3 val = Vector3.ProjectOnPlane(((Component)__instance).transform.forward, Vector3.up);
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			Vector3 moveDir = ((Character)component).m_moveDir;
			if (((Vector3)(ref moveDir)).sqrMagnitude < 0.01f || Vector3.Dot(((Vector3)(ref moveDir)).normalized, normalized) < 0.65f)
			{
				return true;
			}
			if (Time.fixedTime == lastStep)
			{
				return false;
			}
			lastStep = Time.fixedTime;
			Rigidbody body = ((Character)component).m_body;
			if (!Object.op_Implicit((Object)(object)body) || body.isKinematic)
			{
				return true;
			}
			float num = (((Character)component).IsRunning() ? 4.5f : 2.5f);
			Vector3 val2 = (normalized + Vector3.up) * Mathf.Min(0.1f, num * Time.fixedDeltaTime);
			RaycastHit val3 = default(RaycastHit);
			if (body.SweepTest(Vector3.up, ref val3, val2.y + 0.03f, (QueryTriggerInteraction)1))
			{
				return true;
			}
			body.MovePosition(body.position + val2);
			Vector3 linearVelocity = body.linearVelocity;
			if (linearVelocity.y < 0f)
			{
				body.linearVelocity = new Vector3(linearVelocity.x, 0f, linearVelocity.z);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(ItemDrop), "Start")]
	internal static class BuoyancyPatch
	{
		private static readonly Dictionary<ItemDrop, Floating> owned = new Dictionary<ItemDrop, Floating>();

		private static float nextCleanup;

		private static void Postfix(ItemDrop __instance)
		{
			Add(__instance);
		}

		private static void Add(ItemDrop item)
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.Enabled(Feature.FloatingItems) && Object.op_Implicit((Object)(object)item) && !owned.ContainsKey(item) && !Object.op_Implicit((Object)(object)((Component)item).GetComponent<Floating>()) && Object.op_Implicit((Object)(object)((Component)item).GetComponent<Rigidbody>()) && Object.op_Implicit((Object)(object)((Component)item).GetComponentInChildren<Collider>()) && Object.op_Implicit((Object)(object)((Component)item).GetComponent<ZNetView>()) && ((Component)item).GetComponent<ZNetView>().IsValid())
			{
				Floating val = ((Component)item).gameObject.AddComponent<Floating>();
				val.m_waterLevelOffset = 0.15f;
				owned[item] = val;
				val.SetLiquidLevel(Floating.GetLiquidLevel(((Component)item).transform.position, 1f, (LiquidType)0), (LiquidType)0, (Component)null);
			}
		}

		internal static void Refresh()
		{
			bool flag = Plugin.Enabled(Feature.FloatingItems);
			foreach (Floating value in owned.Values)
			{
				if (Object.op_Implicit((Object)(object)value) && ((Behaviour)value).enabled != flag)
				{
					((Behaviour)value).enabled = flag;
					((MonoBehaviour)value).CancelInvoke();
					if (flag)
					{
						((MonoBehaviour)value).InvokeRepeating("TerrainCheck", 15f, 30f);
					}
				}
			}
			if (flag)
			{
				ItemDrop[] array = Object.FindObjectsByType<ItemDrop>((FindObjectsSortMode)0);
				for (int i = 0; i < array.Length; i++)
				{
					Add(array[i]);
				}
				Cleanup();
			}
		}

		internal static void Tick()
		{
			if (!(Time.unscaledTime < nextCleanup))
			{
				nextCleanup = Time.unscaledTime + 15f;
				Cleanup();
			}
		}

		private static void Cleanup()
		{
			ItemDrop[] array = owned.Keys.Where((ItemDrop k) => !Object.op_Implicit((Object)(object)k)).ToArray();
			foreach (ItemDrop key in array)
			{
				owned.Remove(key);
			}
		}

		internal static void RemoveOwned()
		{
			foreach (Floating value in owned.Values)
			{
				if (Object.op_Implicit((Object)(object)value))
				{
					((Behaviour)value).enabled = false;
					Object.Destroy((Object)(object)value);
				}
			}
			owned.Clear();
		}
	}
	[Serializable]
	internal sealed class SavedUi
	{
		public float ClockX = 0.5f;

		public float ClockY = 0.94f;
	}
	internal static class UiState
	{
		internal static SavedUi Value = new SavedUi();

		private static bool dirty;

		private static string PathName => Path.Combine(Paths.ConfigPath, "treextr.huginsdesk.comfykit.ui.json");

		internal static void Load()
		{
			try
			{
				if (File.Exists(PathName))
				{
					Value = JsonUtility.FromJson<SavedUi>(File.ReadAllText(PathName)) ?? new SavedUi();
				}
				Value.ClockX = Policies.Unit(Value.ClockX, 0.5f);
				Value.ClockY = Policies.Unit(Value.ClockY, 0.94f);
			}
			catch (Exception ex)
			{
				Value = new SavedUi();
				Plugin.Warn("Clock position reset: " + ex.Message);
			}
		}

		internal static void Move(float x, float y)
		{
			Value.ClockX = Policies.Unit(x, 0.5f);
			Value.ClockY = Policies.Unit(y, 0.94f);
			dirty = true;
		}

		internal static void Save()
		{
			if (!dirty)
			{
				return;
			}
			try
			{
				string text = PathName + ".tmp";
				File.WriteAllText(text, JsonUtility.ToJson((object)Value, true));
				if (File.Exists(PathName))
				{
					File.Replace(text, PathName, null);
				}
				else
				{
					File.Move(text, PathName);
				}
				dirty = false;
			}
			catch (Exception ex)
			{
				Plugin.Warn("Could not save clock position: " + ex.Message);
			}
		}
	}
}
namespace HuginsDesk.ComfyKit.Core
{
	public enum Feature
	{
		AutoRepair,
		WaterEquipment,
		Trash,
		Clock,
		Ladders,
		Sorting,
		BuildCamera,
		FloatingItems,
		FarmGrid,
		Fermenter
	}
	public sealed class SlotItem
	{
		public int Id;

		public int X;

		public int Y;

		public int Category;

		public int Quality;

		public int Variant;

		public string Name;

		public bool Fixed;
	}
	public struct SlotMove
	{
		public int Id;

		public int X;

		public int Y;

		public SlotMove(int id, int x, int y)
		{
			Id = id;
			X = x;
			Y = y;
		}
	}
	public static class Policies
	{
		public static List<SlotMove> PlanSort(IEnumerable<SlotItem> items, int width, int height, bool player)
		{
			if (width <= 0 || height <= 0)
			{
				throw new ArgumentOutOfRangeException();
			}
			List<SlotItem> list = items.ToList();
			HashSet<long> hashSet = new HashSet<long>();
			HashSet<int> hashSet2 = new HashSet<int>();
			foreach (SlotItem item in list)
			{
				if (!hashSet2.Add(item.Id) || item.X < 0 || item.X >= width || item.Y < 0 || item.Y >= height || !hashSet.Add((long)item.Y * (long)width + item.X))
				{
					throw new InvalidOperationException("Inventory contains invalid or duplicate slots; sorting was cancelled.");
				}
			}
			Func<SlotItem, bool> fixedSlot = (SlotItem item) => item.Fixed || (player && (item.Y == 0 || item.Y >= 4));
			HashSet<long> hashSet3 = new HashSet<long>(from i in list.Where(fixedSlot)
				select (long)i.Y * (long)width + i.X);
			List<SlotItem> list2 = (from i in list
				where !fixedSlot(i)
				orderby i.Category
				select i).ThenBy<SlotItem, string>((SlotItem i) => i.Name ?? "", StringComparer.CurrentCultureIgnoreCase).ThenByDescending((SlotItem i) => i.Quality).ThenBy((SlotItem i) => i.Variant)
				.ThenBy((SlotItem i) => i.Id)
				.ToList();
			List<SlotMove> list3 = new List<SlotMove>();
			int num = 0;
			for (int num2 = (player ? 1 : 0); num2 < (player ? Math.Min(height, 4) : height); num2++)
			{
				for (int num3 = 0; num3 < width; num3++)
				{
					if (num >= list2.Count)
					{
						break;
					}
					if (!hashSet3.Contains((long)num2 * (long)width + num3))
					{
						list3.Add(new SlotMove(list2[num++].Id, num3, num2));
					}
				}
			}
			if (num != list2.Count)
			{
				throw new InvalidOperationException("Not enough unreserved slots.");
			}
			return list3;
		}

		public static double Snap(double coordinate, double anchor, double spacing)
		{
			if (!Finite(coordinate) || !Finite(anchor) || !Finite(spacing) || spacing <= 0.0)
			{
				return coordinate;
			}
			return anchor + Math.Round((coordinate - anchor) / spacing, MidpointRounding.AwayFromZero) * spacing;
		}

		public static bool Finite(double value)
		{
			if (!double.IsNaN(value))
			{
				return !double.IsInfinity(value);
			}
			return false;
		}

		public static float Unit(float value, float fallback)
		{
			if (!Finite(value))
			{
				return fallback;
			}
			return Math.Max(0f, Math.Min(1f, value));
		}

		public static string ClockText(double fraction, int day, bool russian)
		{
			if (!Finite(fraction))
			{
				fraction = 0.0;
			}
			int num = (int)Math.Floor((fraction - Math.Floor(fraction)) * 1440.0);
			return (russian ? "День " : "Day ") + Math.Max(1, day) + "  ·  " + (num / 60).ToString("00") + ":" + (num % 60).ToString("00");
		}

		public static string FermentationText(double elapsed, double duration, bool russian)
		{
			if (!Finite(elapsed) || !Finite(duration) || duration <= 0.0 || elapsed < 0.0)
			{
				return "";
			}
			double val = Math.Max(0.0, duration - elapsed);
			int num = (int)Math.Min(100.0, Math.Floor(100.0 * elapsed / duration));
			TimeSpan timeSpan = TimeSpan.FromSeconds(Math.Min(val, 864000.0));
			string text = ((timeSpan.TotalHours >= 1.0) ? $"{(int)timeSpan.TotalHours}:{timeSpan.Minutes:00}:{timeSpan.Seconds:00}" : $"{(int)timeSpan.TotalMinutes}:{timeSpan.Seconds:00}");
			return num + "%  ·  " + text + (russian ? " осталось" : " remaining");
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}