Decompiled source of Cano Fixedheim v3.4.0

Cano.Fixedheim.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Cano.Fixedheim")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("3.4.0.0")]
[assembly: AssemblyInformationalVersion("3.4.0")]
[assembly: AssemblyProduct("Cano.Fixedheim")]
[assembly: AssemblyTitle("Cano.Fixedheim")]
[assembly: AssemblyVersion("3.4.0.0")]
namespace Cano.Fixedheim;

internal static class BuildEffects
{
	private static int _depth;

	private static readonly Dictionary<GameObject, bool> VisualOnly = new Dictionary<GameObject, bool>();

	private static readonly List<EffectData> Switched = new List<EffectData>();

	internal static bool Inside => _depth > 0;

	internal static void Enter()
	{
		_depth++;
	}

	internal static void Leave()
	{
		_depth = Math.Max(0, _depth - 1);
		if (_depth == 0)
		{
			RestoreAll();
		}
	}

	internal static void Switch(EffectData data)
	{
		data.m_enabled = false;
		Switched.Add(data);
	}

	private static void RestoreAll()
	{
		if (Switched.Count == 0)
		{
			return;
		}
		foreach (EffectData item in Switched)
		{
			item.m_enabled = true;
		}
		Switched.Clear();
	}

	internal static bool IsVisualOnly(GameObject prefab)
	{
		if ((Object)(object)prefab == (Object)null)
		{
			return false;
		}
		if (VisualOnly.TryGetValue(prefab, out var value))
		{
			return value;
		}
		bool flag = (Object)(object)prefab.GetComponentInChildren<ParticleSystem>(true) != (Object)null;
		bool flag2 = (Object)(object)prefab.GetComponentInChildren<ZSFX>(true) != (Object)null || (Object)(object)prefab.GetComponentInChildren<AudioSource>(true) != (Object)null;
		value = flag && !flag2;
		VisualOnly[prefab] = value;
		Plugin.Debug("Build smoke: effect '" + ((Object)prefab).name + "' " + (value ? "will be hidden (particles only)." : (flag ? "kept (it also has a sound)." : "kept (no particles).")));
		return value;
	}
}
[HarmonyPatch(typeof(EffectList), "Create")]
internal static class BuildEffects_Create_Patch
{
	private static void Prefix(EffectList __instance)
	{
		if (!BuildEffects.Inside || __instance == null || __instance.m_effectPrefabs == null)
		{
			return;
		}
		EffectData[] effectPrefabs = __instance.m_effectPrefabs;
		foreach (EffectData val in effectPrefabs)
		{
			if (val != null && val.m_enabled && BuildEffects.IsVisualOnly(val.m_prefab))
			{
				BuildEffects.Switch(val);
			}
		}
	}
}
[HarmonyPatch(typeof(Player), "PlacePiece")]
internal static class BuildEffects_PlacePiece_Patch
{
	private static void Prefix()
	{
		BuildEffects.Enter();
	}

	private static void Finalizer()
	{
		BuildEffects.Leave();
	}
}
[HarmonyPatch(typeof(Player), "Repair")]
internal static class BuildEffects_Repair_Patch
{
	private static void Prefix()
	{
		BuildEffects.Enter();
	}

	private static void Finalizer()
	{
		BuildEffects.Leave();
	}
}
[HarmonyPatch(typeof(TerrainOp), "OnPlaced")]
internal static class BuildEffects_TerrainOp_Patch
{
	private static void Prefix()
	{
		BuildEffects.Enter();
	}

	private static void Finalizer()
	{
		BuildEffects.Leave();
	}
}
internal static class BuildIconSize
{
	private static readonly FieldInfo ContainerField = AccessTools.Field(typeof(BuildUi), "m_pieceButtonsContainer");

	private static readonly FieldInfo PrefabField = AccessTools.Field(typeof(BuildUi), "m_pieceButtonPrefab");

	private static readonly FieldInfo ButtonsField = AccessTools.Field(typeof(BuildUi), "m_pieceButtons");

	private static readonly FieldInfo ArrowField = AccessTools.Field(typeof(BuildUiPieceButton), "m_upgradeArrow");

	private static readonly FieldInfo StarField = AccessTools.Field(typeof(BuildUiPieceButton), "m_favoriteStar");

	private static readonly MethodInfo NavigationMethod = AccessTools.Method(typeof(BuildUi), "ConfigureButtonNavigation", (Type[])null, (Type[])null);

	private static GridLayoutGroup _grid;

	private static Vector2 _cell;

	private static Vector2 _spacing;

	private static Constraint _constraint;

	private static int _count;

	private static bool _described;

	private static bool _modified;

	internal static bool PendingRestore => _modified;

	private static float Factor
	{
		get
		{
			if (Settings.EnableBuildEnhancements == null || Settings.PieceIconSize == null || !Settings.EnableBuildEnhancements.Value || !Settings.EnablePieceIconSize.Value)
			{
				return 1f;
			}
			return (float)Settings.PieceIconSize.Value / 100f;
		}
	}

	internal static void OnSettingChanged()
	{
		BuildUi val = (((Object)(object)Hud.instance != (Object)null) ? Hud.instance.m_buildUi : null);
		if ((Object)(object)val != (Object)null && ((Behaviour)val).isActiveAndEnabled)
		{
			Apply(val);
		}
	}

	internal static void Apply(BuildUi ui)
	{
		float factor = Factor;
		if (factor == 1f && !_modified)
		{
			return;
		}
		RectTransform val = (RectTransform)((ContainerField != null) ? /*isinst with value type is only supported in some contexts*/: null);
		if (!((Object)(object)val == (Object)null))
		{
			GridLayoutGroup component = ((Component)val).GetComponent<GridLayoutGroup>();
			bool num = (((Object)(object)component != (Object)null) ? ApplyGrid(component, factor) : ApplyFallback(ui, factor));
			ApplyOverlays(ui, factor);
			Describe(ui, val, component);
			bool modified = _modified;
			_modified = factor != 1f;
			if (modified && !_modified)
			{
				Features.RequestRefresh();
			}
			if (num && NavigationMethod != null)
			{
				NavigationMethod.Invoke(ui, null);
			}
		}
	}

	private static bool ApplyGrid(GridLayoutGroup grid, float f)
	{
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Invalid comparison between Unknown and I4
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_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_006e: 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_0074: 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_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_grid != (Object)(object)grid)
		{
			_grid = grid;
			_cell = grid.cellSize;
			_spacing = grid.spacing;
			_constraint = grid.constraint;
			_count = grid.constraintCount;
		}
		int num = (((int)_constraint == 1) ? Mathf.Max(1, Mathf.FloorToInt((float)_count / f + 0.001f)) : _count);
		Vector2 val = _cell * f;
		Vector2 val2 = _spacing * f;
		if (grid.cellSize == val && grid.spacing == val2 && grid.constraintCount == num)
		{
			return false;
		}
		grid.cellSize = val;
		grid.spacing = val2;
		grid.constraintCount = num;
		return true;
	}

	private static bool ApplyFallback(BuildUi ui, float f)
	{
		//IL_0069: 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_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: 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)
		GameObject val = (GameObject)((PrefabField != null) ? /*isinst with value type is only supported in some contexts*/: null);
		RectTransform val2 = (RectTransform)(((Object)(object)val != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
		List<BuildUiPieceButton> list = ((ButtonsField != null) ? (ButtonsField.GetValue(ui) as List<BuildUiPieceButton>) : null);
		if ((Object)(object)val2 == (Object)null || list == null)
		{
			return false;
		}
		Vector2 val3 = val2.sizeDelta * f;
		bool result = false;
		foreach (BuildUiPieceButton item in list)
		{
			Transform transform = ((Component)item).transform;
			RectTransform val4 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			if (!((Object)(object)val4 == (Object)null) && !(val4.sizeDelta == val3))
			{
				val4.sizeDelta = val3;
				result = true;
			}
		}
		return result;
	}

	private static void ApplyOverlays(BuildUi ui, float f)
	{
		//IL_00a0: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//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_00e6: 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_00ff: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = (GameObject)((PrefabField != null) ? /*isinst with value type is only supported in some contexts*/: null);
		BuildUiPieceButton val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<BuildUiPieceButton>() : null);
		List<BuildUiPieceButton> list = ((ButtonsField != null) ? (ButtonsField.GetValue(ui) as List<BuildUiPieceButton>) : null);
		if ((Object)(object)val2 == (Object)null || list == null)
		{
			return;
		}
		FieldInfo[] array = new FieldInfo[2] { ArrowField, StarField };
		foreach (FieldInfo field in array)
		{
			RectTransform val3 = OverlayRect(field, val2);
			if ((Object)(object)val3 == (Object)null)
			{
				continue;
			}
			Vector2 val4 = val3.sizeDelta * f;
			Vector2 val5 = val3.anchoredPosition * f;
			foreach (BuildUiPieceButton item in list)
			{
				RectTransform val6 = OverlayRect(field, item);
				if (!((Object)(object)val6 == (Object)null))
				{
					if (val6.sizeDelta != val4)
					{
						val6.sizeDelta = val4;
					}
					if (val6.anchoredPosition != val5)
					{
						val6.anchoredPosition = val5;
					}
				}
			}
		}
	}

	private static RectTransform OverlayRect(FieldInfo field, BuildUiPieceButton button)
	{
		Image val = (Image)((field != null) ? /*isinst with value type is only supported in some contexts*/: null);
		if (!((Object)(object)val != (Object)null))
		{
			return null;
		}
		return ((Graphic)val).rectTransform;
	}

	private unsafe static void Describe(BuildUi ui, RectTransform container, GridLayoutGroup grid)
	{
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: 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_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Expected O, but got Unknown
		//IL_0159: 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)
		if (_described || Settings.DebugLogging == null || !Settings.DebugLogging.Value)
		{
			return;
		}
		_described = true;
		string[] obj = new string[5]
		{
			"Piece icon size: container '",
			((Object)container).name,
			"' has ",
			string.Join(", ", (from c in ((Component)container).GetComponents<Component>()
				select ((object)c).GetType().Name).ToArray()),
			null
		};
		object obj2;
		if (!((Object)(object)grid != (Object)null))
		{
			obj2 = "; NO GridLayoutGroup, using the per-button fallback.";
		}
		else
		{
			string[] obj3 = new string[9] { "; GridLayoutGroup, vanilla cell ", null, null, null, null, null, null, null, null };
			Vector2 cell = _cell;
			obj3[1] = ((object)(*(Vector2*)(&cell))/*cast due to .constrained prefix*/).ToString();
			obj3[2] = ", spacing ";
			cell = _spacing;
			obj3[3] = ((object)(*(Vector2*)(&cell))/*cast due to .constrained prefix*/).ToString();
			obj3[4] = ", ";
			obj3[5] = ((object)Unsafe.As<Constraint, Constraint>(ref _constraint)/*cast due to .constrained prefix*/).ToString();
			obj3[6] = " ";
			obj3[7] = _count.ToString();
			obj3[8] = ".";
			obj2 = string.Concat(obj3);
		}
		obj[4] = (string)obj2;
		Plugin.Debug(string.Concat(obj));
		GameObject val = (GameObject)((PrefabField != null) ? /*isinst with value type is only supported in some contexts*/: null);
		if (!((Object)(object)val == (Object)null))
		{
			RectTransform val2 = (RectTransform)val.transform;
			Plugin.Debug("Piece icon size: piece button prefab size " + ((object)val2.sizeDelta/*cast due to .constrained prefix*/).ToString() + ", children: " + string.Join("; ", (from c in ((IEnumerable)val2).OfType<RectTransform>()
				select ((Object)c).name + " anchors " + ((object)c.anchorMin/*cast due to .constrained prefix*/).ToString() + "-" + ((object)c.anchorMax/*cast due to .constrained prefix*/).ToString() + " size " + ((object)c.sizeDelta/*cast due to .constrained prefix*/).ToString()).ToArray()));
		}
	}
}
[HarmonyPatch(typeof(BuildUi), "UpdatePieceButtons")]
internal static class BuildIconSize_UpdatePieceButtons_Patch
{
	private static void Postfix(BuildUi __instance)
	{
		BuildIconSize.Apply(__instance);
	}
}
internal static class ListPin
{
	private static readonly FieldInfo PieceListsField = AccessTools.Field(typeof(BuildUi), "m_pieceLists");

	private static readonly FieldInfo CurrentPieceListField = AccessTools.Field(typeof(BuildUi), "m_currentPieceList");

	private static readonly FieldInfo FavoriteListField = AccessTools.Field(typeof(BuildUi), "m_favoritePieceList");

	public static int ListIndex = -1;

	public static int TagId = -1;

	private static bool _loaded;

	private static int _cachedFrame = -1;

	private static int _cachedCurrent = -1;

	public static bool HasPin => ListIndex >= 0;

	private static BuildUi Ui
	{
		get
		{
			if (!((Object)(object)Hud.instance != (Object)null))
			{
				return null;
			}
			return Hud.instance.m_buildUi;
		}
	}

	public static int CurrentListIndex()
	{
		if (_cachedFrame == Time.frameCount)
		{
			return _cachedCurrent;
		}
		_cachedFrame = Time.frameCount;
		_cachedCurrent = -1;
		BuildUi ui = Ui;
		if ((Object)(object)ui != (Object)null && CurrentPieceListField != null)
		{
			_cachedCurrent = (int)CurrentPieceListField.GetValue(ui);
		}
		return _cachedCurrent;
	}

	public static bool IsPinned(int tagId)
	{
		if (ListIndex >= 0 && TagId == tagId)
		{
			return ListIndex == CurrentListIndex();
		}
		return false;
	}

	public static void Toggle(int tagId)
	{
		int num = CurrentListIndex();
		if (num >= 0)
		{
			if (IsPinned(tagId))
			{
				Clear();
				return;
			}
			ListIndex = num;
			TagId = tagId;
			Save();
		}
	}

	public static void Clear()
	{
		ListIndex = -1;
		TagId = -1;
		Save();
	}

	public static FavoritePieceList FavoriteList()
	{
		BuildUi ui = Ui;
		if (!((Object)(object)ui != (Object)null) || !(FavoriteListField != null))
		{
			return null;
		}
		object? value = FavoriteListField.GetValue(ui);
		return (FavoritePieceList)((value is FavoritePieceList) ? value : null);
	}

	private static int FavoriteListIndex()
	{
		BuildUi ui = Ui;
		List<IPieceList> list = (((Object)(object)ui != (Object)null && PieceListsField != null) ? (PieceListsField.GetValue(ui) as List<IPieceList>) : null);
		if (list == null)
		{
			return -1;
		}
		for (int i = 0; i < list.Count; i++)
		{
			if (list[i] is FavoritePieceList)
			{
				return i;
			}
		}
		return -1;
	}

	public static void OnPlayerPresent()
	{
		if (_loaded)
		{
			return;
		}
		_loaded = true;
		if (!Settings.PersistPinnedList.Value)
		{
			return;
		}
		string value = Settings.PinnedListData.Value;
		if (!string.IsNullOrEmpty(value))
		{
			string[] array = value.Split(':');
			if (array.Length == 2 && int.TryParse(array[0], out var result) && int.TryParse(array[1], out var result2) && result >= 0)
			{
				ListIndex = result;
				TagId = result2;
			}
		}
	}

	public static void OnNoPlayer()
	{
		_loaded = false;
		if (!Settings.PersistPinnedList.Value && ListIndex >= 0)
		{
			ListIndex = -1;
			TagId = -1;
		}
	}

	public static void Save()
	{
		try
		{
			Settings.PinnedListData.Value = ((Settings.PersistPinnedList.Value && ListIndex >= 0) ? (ListIndex + ":" + TagId) : "");
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Could not save the pinned list: " + ex.Message));
		}
	}

	public static void OnFavoriteTagRemoved(int removedIndex)
	{
		if (ListIndex >= 0 && ListIndex == FavoriteListIndex())
		{
			if (TagId == removedIndex)
			{
				Clear();
			}
			else if (TagId > removedIndex)
			{
				TagId--;
				Save();
			}
		}
	}

	public static bool FillPinnedPieces(PieceTable table, List<Piece> result)
	{
		if (ListIndex < 0 || (Object)(object)table == (Object)null)
		{
			return false;
		}
		try
		{
			BuildUi ui = Ui;
			List<IPieceList> list = (((Object)(object)ui != (Object)null && PieceListsField != null) ? (PieceListsField.GetValue(ui) as List<IPieceList>) : null);
			if (list == null || ListIndex >= list.Count)
			{
				return false;
			}
			IPieceList obj = list[ListIndex];
			obj.UpdateAvailableTags(table);
			obj.GetAvailablePiecesWithTag(TagId, table, (IList<Piece>)result);
			return true;
		}
		catch (Exception ex)
		{
			Plugin.Debug("Pinned list could not be read, cycling the whole menu instead: " + ex.Message);
			result.Clear();
			return false;
		}
	}
}
[HarmonyPatch(typeof(FavoritePieceList), "RemoveTag")]
internal static class FavoritePieceList_RemoveTag_Patch
{
	private static void Postfix(int index)
	{
		try
		{
			ListPin.OnFavoriteTagRemoved(index);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Updating the pinned list after a list was removed failed: " + ex));
		}
	}
}
[HarmonyPatch(typeof(BuildUiTagButton), "Awake")]
internal static class BuildUiTagButton_Awake_Patch
{
	private static void Postfix(BuildUiTagButton __instance)
	{
		try
		{
			if ((Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).GetComponent<TagButtonExtras>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<TagButtonExtras>();
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Adding the list button extras failed: " + ex));
		}
	}
}
internal sealed class TagButtonExtras : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler, IPointerClickHandler
{
	private const int AddListTagId = -10;

	private static readonly FieldInfo TextMeshesField = AccessTools.Field(typeof(BuildUiTagButton), "m_textMeshes");

	private static readonly FieldInfo ToggledOnField = AccessTools.Field(typeof(BuildUiTagButton), "m_toggledOnObject");

	private static readonly FieldInfo TagsField = AccessTools.Field(typeof(FavoritePieceList), "m_tags");

	private static readonly MethodInfo RefreshFavoritesMethod = AccessTools.Method(typeof(BuildUi), "RefreshFavorites", (Type[])null, (Type[])null);

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

	private BuildUiTagButton _tag;

	private RectTransform _rect;

	private bool _hover;

	private Image _pin;

	private readonly Dictionary<Image, Color> _recolored = new Dictionary<Image, Color>();

	private GameObject _overlay;

	private RectTransform _clip;

	private RectTransform _labelRect;

	private TextMeshProUGUI _label;

	private Button _trash;

	private Image _trashBackground;

	private Image _trashIcon;

	private float _clock;

	private float _baseX;

	private float _labelY;

	private float _travel;

	private readonly List<TMP_Text> _hidden = new List<TMP_Text>();

	private bool IsCustomList
	{
		get
		{
			if ((Object)(object)_tag != (Object)null && _tag.m_canDeleteTag)
			{
				return _tag.m_tagId >= 0;
			}
			return false;
		}
	}

	private bool ListEditingOn
	{
		get
		{
			if (Features.ListEditing)
			{
				return IsCustomList;
			}
			return false;
		}
	}

	private bool PinningOn
	{
		get
		{
			if (Features.Pinning && (Object)(object)_tag != (Object)null)
			{
				return _tag.m_tagId != -10;
			}
			return false;
		}
	}

	private void Awake()
	{
		_tag = ((Component)this).GetComponent<BuildUiTagButton>();
		ref RectTransform rect = ref _rect;
		Transform transform = ((Component)this).transform;
		rect = (RectTransform)(object)((transform is RectTransform) ? transform : null);
	}

	private void OnDisable()
	{
		_hover = false;
		HideOverlay();
		RestoreHighlight();
	}

	internal static void AttachToExisting()
	{
		try
		{
			BuildUiTagButton[] array = Object.FindObjectsByType<BuildUiTagButton>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			foreach (BuildUiTagButton val in array)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).GetComponent<TagButtonExtras>() == (Object)null)
				{
					((Component)val).gameObject.AddComponent<TagButtonExtras>();
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Adding the list button extras to existing buttons failed: " + ex));
		}
	}

	public void OnPointerEnter(PointerEventData eventData)
	{
		_hover = true;
	}

	public void OnPointerExit(PointerEventData eventData)
	{
		_hover = false;
	}

	public void OnPointerClick(PointerEventData eventData)
	{
		//IL_000f: 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)
		if (!((Object)(object)_tag == (Object)null) && (int)eventData.button == 0)
		{
			if (PinningOn && KeyUtil.Held(Settings.ListPinModifier.Value))
			{
				ListPin.Toggle(_tag.m_tagId);
			}
			else if (eventData.clickCount == 2 && ListEditingOn && Settings.RenameOnDoubleClick.Value)
			{
				AskForNewName();
			}
		}
	}

	private void Update()
	{
		if ((Object)(object)_tag == (Object)null)
		{
			return;
		}
		if (!Features.ListEditing && !Features.Pinning)
		{
			if ((Object)(object)_pin != (Object)null && ((Behaviour)_pin).enabled)
			{
				((Behaviour)_pin).enabled = false;
			}
			RestoreHighlight();
			if ((Object)(object)_overlay != (Object)null && _overlay.activeSelf)
			{
				HideOverlay();
			}
			return;
		}
		UpdatePin();
		if (_hover && ListEditingOn && (Settings.ShowDeleteIcon.Value || Settings.ScrollLongListNames.Value))
		{
			if ((Object)(object)_overlay == (Object)null || !_overlay.activeSelf)
			{
				ShowOverlay();
			}
			AnimateOverlay();
		}
		else if ((Object)(object)_overlay != (Object)null && _overlay.activeSelf)
		{
			HideOverlay();
		}
	}

	private void UpdatePin()
	{
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		if (!PinningOn || !ListPin.IsPinned(_tag.m_tagId))
		{
			if ((Object)(object)_pin != (Object)null && ((Behaviour)_pin).enabled)
			{
				((Behaviour)_pin).enabled = false;
			}
			RestoreHighlight();
			return;
		}
		if ((Object)(object)_pin == (Object)null)
		{
			GameObject val = NewChild("CanoPinHighlight", typeof(Image));
			val.transform.SetAsFirstSibling();
			_pin = val.GetComponent<Image>();
			((Graphic)_pin).raycastTarget = false;
		}
		((Graphic)_pin).color = Settings.ListPinColor.Value;
		((Behaviour)_pin).enabled = true;
		TintSelectedHighlight();
	}

	private void TintSelectedHighlight()
	{
		//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_008f: 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_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: 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_00b3: 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_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = (GameObject)((ToggledOnField != null) ? /*isinst with value type is only supported in some contexts*/: null);
		if ((Object)(object)val == (Object)null || !val.activeInHierarchy)
		{
			RestoreHighlight();
			return;
		}
		Color value = Settings.ListPinColor.Value;
		Image[] componentsInChildren = val.GetComponentsInChildren<Image>(true);
		foreach (Image val2 in componentsInChildren)
		{
			if (!((Object)(object)val2 == (Object)null))
			{
				if (!_recolored.TryGetValue(val2, out var value2))
				{
					value2 = ((Graphic)val2).color;
					_recolored[val2] = value2;
				}
				((Graphic)val2).color = new Color(value.r, value.g, value.b, Mathf.Max(value2.a, value.a));
			}
		}
	}

	private void RestoreHighlight()
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		if (_recolored.Count == 0)
		{
			return;
		}
		foreach (KeyValuePair<Image, Color> item in _recolored)
		{
			if ((Object)(object)item.Key != (Object)null)
			{
				((Graphic)item.Key).color = item.Value;
			}
		}
		_recolored.Clear();
	}

	private void AskForNewName()
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Expected O, but got Unknown
		//IL_0068: Expected O, but got Unknown
		//IL_0068: Expected O, but got Unknown
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Expected O, but got Unknown
		int index = _tag.m_tagId;
		string displayName = _tag.m_displayName;
		UnifiedPopup.Push((PopupBase)new TextEntryPopup("Rename list", ConfirmDialog.Tint("Type a new name for \"" + displayName + "\"."), displayName, new PopupButtonCallback(UnifiedPopup.Pop), new ValidateTextEntry(FavoritePieceList.ValidateTagName), (RetrieveTextEntryResult)delegate(string entry)
		{
			if (FavoritePieceList.ValidateTagName(entry))
			{
				UnifiedPopup.Pop();
				ApplyRename(index, entry.Trim());
			}
		}, false));
		UnifiedPopup.SetFocus();
	}

	private static void ApplyRename(int index, string newName)
	{
		try
		{
			if (string.IsNullOrWhiteSpace(newName))
			{
				return;
			}
			FavoritePieceList val = ListPin.FavoriteList();
			List<string> list = ((val != null && TagsField != null) ? (TagsField.GetValue(val) as List<string>) : null);
			if (list == null || index < 0 || index >= list.Count)
			{
				return;
			}
			list[index] = newName;
			BuildUi val2 = (((Object)(object)Hud.instance != (Object)null) ? Hud.instance.m_buildUi : null);
			if (!((Object)(object)val2 == (Object)null))
			{
				if (RefreshFavoritesMethod != null)
				{
					RefreshFavoritesMethod.Invoke(val2, null);
				}
				val2.SelectPieceList((ListPin.CurrentListIndex() >= 0) ? ListPin.CurrentListIndex() : 3, true);
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Renaming the favourites list failed: " + ex));
		}
	}

	private GameObject NewChild(string name, params Type[] components)
	{
		//IL_0034: 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_004b: 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_005d: 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_0063: 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_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: 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_008e: Expected O, but got Unknown
		List<Type> list = new List<Type>
		{
			typeof(RectTransform),
			typeof(LayoutElement)
		};
		list.AddRange(components);
		GameObject val = new GameObject(name, list.ToArray());
		val.transform.SetParent(((Component)this).transform, false);
		val.GetComponent<LayoutElement>().ignoreLayout = true;
		RectTransform val2 = (RectTransform)val.transform;
		val2.anchorMin = Vector2.zero;
		val2.anchorMax = Vector2.one;
		val2.offsetMin = Vector2.zero;
		val2.offsetMax = Vector2.zero;
		return val;
	}

	private TMP_Text SourceText()
	{
		List<TextMeshProUGUI> list = ((TextMeshesField != null) ? (TextMeshesField.GetValue(_tag) as List<TextMeshProUGUI>) : null);
		if (list == null || list.Count == 0)
		{
			return null;
		}
		foreach (TextMeshProUGUI item in list)
		{
			if ((Object)(object)item != (Object)null && ((Component)item).gameObject.activeInHierarchy)
			{
				return (TMP_Text)(object)item;
			}
		}
		return (TMP_Text)(object)list[0];
	}

	private void BuildOverlay()
	{
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Expected O, but got Unknown
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: 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_00cb: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: 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_00f5: 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_0162: 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_0184: Expected O, but got Unknown
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: 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_01df: Unknown result type (might be due to invalid IL or missing references)
		_overlay = NewChild("CanoListOverlay");
		GameObject val = NewChild("Clip", typeof(RectMask2D));
		val.transform.SetParent(_overlay.transform, false);
		_clip = (RectTransform)val.transform;
		GameObject val2 = NewChild("Trash", typeof(Image), typeof(Button));
		val2.transform.SetParent(_overlay.transform, false);
		RectTransform val3 = (RectTransform)val2.transform;
		val3.anchorMin = new Vector2(1f, 0f);
		val3.anchorMax = new Vector2(1f, 1f);
		val3.pivot = new Vector2(1f, 0.5f);
		val3.offsetMin = Vector2.zero;
		val3.offsetMax = Vector2.zero;
		_trashBackground = val2.GetComponent<Image>();
		((Graphic)_trashBackground).color = new Color(0f, 0f, 0f, 0.65f);
		_trash = val2.GetComponent<Button>();
		((Selectable)_trash).targetGraphic = (Graphic)(object)_trashBackground;
		Button trash = _trash;
		Navigation navigation = default(Navigation);
		((Navigation)(ref navigation)).mode = (Mode)0;
		((Selectable)trash).navigation = navigation;
		((UnityEvent)_trash.onClick).AddListener(new UnityAction(OnTrashClicked));
		GameObject val4 = NewChild("Icon", typeof(Image));
		val4.transform.SetParent(val2.transform, false);
		RectTransform val5 = (RectTransform)val4.transform;
		val5.anchorMin = new Vector2(0.18f, 0.18f);
		val5.anchorMax = new Vector2(0.82f, 0.82f);
		_trashIcon = val4.GetComponent<Image>();
		_trashIcon.sprite = IconShapeGenerator.TrashCan();
		_trashIcon.preserveAspect = true;
		((Graphic)_trashIcon).raycastTarget = false;
	}

	private void EnsureLabel(TMP_Text source)
	{
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Expected O, but got Unknown
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_label != (Object)null)
		{
			return;
		}
		GameObject val = Object.Instantiate<GameObject>(((Component)source).gameObject, (Transform)(object)_clip, false);
		((Object)val).name = "Label";
		foreach (Transform item in new List<Transform>(val.GetComponentsInChildren<Transform>(true)))
		{
			if ((Object)(object)item != (Object)null && (Object)(object)item != (Object)(object)val.transform)
			{
				Object.Destroy((Object)(object)((Component)item).gameObject);
			}
		}
		Component[] components = val.GetComponents<Component>();
		foreach (Component val2 in components)
		{
			if (!(val2 is Transform) && !(val2 is CanvasRenderer) && !(val2 is TMP_Text))
			{
				Object.Destroy((Object)(object)val2);
			}
		}
		val.SetActive(true);
		_labelRect = (RectTransform)val.transform;
		_labelRect.anchorMin = new Vector2(0f, 0.5f);
		_labelRect.anchorMax = new Vector2(0f, 0.5f);
		_labelRect.pivot = new Vector2(0f, 0.5f);
		((Transform)_labelRect).localScale = Vector3.one;
		_label = val.GetComponent<TextMeshProUGUI>();
		((Graphic)_label).raycastTarget = false;
		((TMP_Text)_label).textWrappingMode = (TextWrappingModes)0;
		((TMP_Text)_label).overflowMode = (TextOverflowModes)0;
		((TMP_Text)_label).enableAutoSizing = false;
	}

	private void ShowOverlay()
	{
		//IL_0072: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: 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_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Expected O, but got Unknown
		//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0242: Unknown result type (might be due to invalid IL or missing references)
		//IL_0247: 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_025a: 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_026c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0271: Unknown result type (might be due to invalid IL or missing references)
		//IL_0273: Unknown result type (might be due to invalid IL or missing references)
		//IL_0284: Unknown result type (might be due to invalid IL or missing references)
		//IL_0296: Unknown result type (might be due to invalid IL or missing references)
		//IL_029d: 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_02ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_02da: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0300: Unknown result type (might be due to invalid IL or missing references)
		//IL_0305: Unknown result type (might be due to invalid IL or missing references)
		//IL_030c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0314: Unknown result type (might be due to invalid IL or missing references)
		//IL_031f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0324: Unknown result type (might be due to invalid IL or missing references)
		//IL_0339: Unknown result type (might be due to invalid IL or missing references)
		//IL_032c: Unknown result type (might be due to invalid IL or missing references)
		//IL_032f: Invalid comparison between Unknown and I4
		//IL_0331: Unknown result type (might be due to invalid IL or missing references)
		//IL_0334: Invalid comparison between Unknown and I4
		//IL_0348: Unknown result type (might be due to invalid IL or missing references)
		//IL_034b: Invalid comparison between Unknown and I4
		//IL_0365: Unknown result type (might be due to invalid IL or missing references)
		//IL_0350: Unknown result type (might be due to invalid IL or missing references)
		TMP_Text val = SourceText();
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		if ((Object)(object)_overlay == (Object)null)
		{
			BuildOverlay();
		}
		EnsureLabel(val);
		_overlay.SetActive(true);
		((TMP_Text)_label).font = val.font;
		((TMP_Text)_label).fontSharedMaterial = val.fontSharedMaterial;
		((TMP_Text)_label).fontSize = val.fontSize;
		((TMP_Text)_label).fontStyle = val.fontStyle;
		((TMP_Text)_label).fontWeight = val.fontWeight;
		((TMP_Text)_label).characterSpacing = val.characterSpacing;
		((TMP_Text)_label).lineSpacing = val.lineSpacing;
		((Graphic)_label).color = ((Graphic)val).color;
		((TMP_Text)_label).verticalAlignment = val.verticalAlignment;
		((TMP_Text)_label).horizontalAlignment = (HorizontalAlignmentOptions)1;
		((TMP_Text)_label).margin = new Vector4(0f, val.margin.y, 0f, val.margin.w);
		((TMP_Text)_label).text = val.text;
		((TMP_Text)_label).ForceMeshUpdate(false, false);
		float num;
		Rect rect;
		if (!((Object)(object)_rect != (Object)null))
		{
			num = 28f;
		}
		else
		{
			rect = _rect.rect;
			num = ((Rect)(ref rect)).height;
		}
		float num2 = Mathf.Clamp(num, 18f, 40f);
		bool value = Settings.ShowDeleteIcon.Value;
		float num3 = (value ? num2 : 0f);
		((RectTransform)((Component)_trash).transform).sizeDelta = new Vector2(num3, 0f);
		((Component)_trash).gameObject.SetActive(value);
		RectTransform val2 = (RectTransform)_overlay.transform;
		val.rectTransform.GetWorldCorners(Corners);
		float x = ((Transform)val2).InverseTransformPoint(Corners[0]).x;
		rect = val2.rect;
		float num4 = x - ((Rect)(ref rect)).xMin;
		_clip.offsetMin = new Vector2(Mathf.Max(0f, num4), 0f);
		_clip.offsetMax = new Vector2(0f - (num3 + 4f), 0f);
		Vector3 val3 = ((Transform)_clip).InverseTransformPoint(Corners[0]);
		Vector3 val4 = ((Transform)_clip).InverseTransformPoint(Corners[2]);
		Rect rect2 = _clip.rect;
		float num5 = val3.x - ((Rect)(ref rect2)).xMin;
		float num6 = val4.x - ((Rect)(ref rect2)).xMin;
		_labelY = (val3.y + val4.y) * 0.5f - ((Rect)(ref rect2)).center.y;
		float x2 = ((TMP_Text)_label).GetPreferredValues(((TMP_Text)_label).text).x;
		float num7 = val4.y - val3.y;
		_labelRect.sizeDelta = new Vector2(x2, num7);
		Vector4 margin = val.margin;
		float num8 = num6 - num5 - margin.x - margin.z;
		HorizontalAlignmentOptions horizontalAlignment = val.horizontalAlignment;
		if (x2 >= num8 || (int)horizontalAlignment == 1 || (int)horizontalAlignment == 8)
		{
			_baseX = num5 + margin.x;
		}
		else if ((int)horizontalAlignment == 4)
		{
			_baseX = num6 - margin.z - x2;
		}
		else
		{
			_baseX = num5 + margin.x + (num8 - x2) * 0.5f;
		}
		_travel = Mathf.Max(0f, _baseX + x2 - ((Rect)(ref rect2)).width + 2f);
		_clock = 0f;
		_hidden.Clear();
		List<TextMeshProUGUI> list = ((TextMeshesField != null) ? (TextMeshesField.GetValue(_tag) as List<TextMeshProUGUI>) : null);
		if (list != null)
		{
			foreach (TextMeshProUGUI item in list)
			{
				if ((Object)(object)item != (Object)null && ((Behaviour)item).enabled)
				{
					((Behaviour)item).enabled = false;
					_hidden.Add((TMP_Text)(object)item);
				}
			}
		}
		_overlay.transform.SetAsLastSibling();
		AnimateOverlay();
	}

	private void HideOverlay()
	{
		foreach (TMP_Text item in _hidden)
		{
			if ((Object)(object)item != (Object)null)
			{
				((Behaviour)item).enabled = true;
			}
		}
		_hidden.Clear();
		if ((Object)(object)_overlay != (Object)null && _overlay.activeSelf)
		{
			_overlay.SetActive(false);
		}
	}

	private void AnimateOverlay()
	{
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)_overlay == (Object)null) && _overlay.activeSelf && !((Object)(object)_labelRect == (Object)null))
		{
			float num = _baseX;
			if (_travel > 0.5f && Settings.ScrollLongListNames.Value)
			{
				float num2 = _travel / 40f;
				float num3 = 2f * (0.8f + num2);
				_clock += Time.unscaledDeltaTime;
				float num4 = _clock % num3;
				float num5 = ((num4 < 0.8f) ? 0f : ((num4 < 0.8f + num2) ? ((num4 - 0.8f) * 40f) : ((!(num4 < 1.6f + num2)) ? (_travel - (num4 - (1.6f + num2)) * 40f) : _travel)));
				num = _baseX - num5;
			}
			_labelRect.anchoredPosition = new Vector2(num, _labelY);
		}
	}

	private void OnTrashClicked()
	{
		if ((Object)(object)_tag != (Object)null && ListEditingOn)
		{
			_tag.OnDelete((UIInputHandler)null);
		}
	}
}
internal static class BuildTools
{
	private enum MenuRegion
	{
		None,
		Tabs,
		Tags,
		Pieces
	}

	private static readonly List<Piece> Nearby = new List<Piece>();

	private static readonly Dictionary<PieceTable, Piece> RepairPieces = new Dictionary<PieceTable, Piece>();

	private static bool _closeOnRelease;

	private static bool _noPlayerDone;

	private static bool _idleDone;

	private static readonly FieldInfo TabContainerField = AccessTools.Field(typeof(BuildUi), "m_tabContainer");

	private static readonly FieldInfo TagContainerField = AccessTools.Field(typeof(BuildUi), "m_tagListContainer");

	private static readonly FieldInfo PieceViewField = AccessTools.Field(typeof(BuildUi), "m_pieceView");

	private static readonly FieldInfo TabHandlerField = AccessTools.Field(typeof(BuildUi), "m_tabHandler");

	private static readonly FieldInfo ShowAllTagField = AccessTools.Field(typeof(BuildUi), "m_showAllTagsButton");

	private static readonly FieldInfo TagButtonsField = AccessTools.Field(typeof(BuildUi), "m_tagButtons");

	private static readonly FieldInfo PieceButtonsField = AccessTools.Field(typeof(BuildUi), "m_pieceButtons");

	private static readonly FieldInfo CurrentTagField = AccessTools.Field(typeof(BuildUi), "m_currentTagId");

	private static readonly MethodInfo OnSelectTagMethod = AccessTools.Method(typeof(BuildUi), "OnSelectTag", (Type[])null, (Type[])null);

	private static readonly MethodInfo UpdatePieceSelectionMethod = AccessTools.Method(typeof(BuildUi), "UpdatePieceSelection", (Type[])null, (Type[])null);

	private static readonly FieldInfo SearchFieldField = AccessTools.Field(typeof(BuildUi), "m_searchField");

	private static readonly FieldInfo SpecialButtonsField = AccessTools.Field(typeof(BuildUi), "m_specialButtonsContainer");

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

	private static readonly FieldInfo[] MenuPartFields = new FieldInfo[5] { TabContainerField, TagContainerField, PieceViewField, SearchFieldField, SpecialButtonsField };

	private const float MenuEdgeMargin = 12f;

	private static readonly FieldRef<Humanoid, ItemData> RightItemRef = MakeRightItemRef();

	private const string HammerPrefab = "Hammer";

	private static readonly string[] CycleToolPrefabs = new string[4] { "Hammer", "Hoe", "Cultivator", "Feaster" };

	private static ItemData _heldItem;

	private static bool _heldHammer;

	private static bool _heldCycleTool;

	private static readonly List<Piece> RawCycleSet = new List<Piece>();

	private static readonly List<Piece> CycleSet = new List<Piece>();

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

	private static readonly List<Piece> StepPieces = new List<Piece>();

	private static string _stepAnchor;

	internal static Piece ApprovedPiece;

	private static readonly MethodInfo RemovePieceMethod = AccessTools.Method(typeof(Player), "RemovePiece", (Type[])null, (Type[])null);

	private static readonly int RayMask = LayerMask.GetMask(new string[7] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "vehicle" });

	private static bool ModifierHeld
	{
		get
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if (Settings.EnableTagPieceScrolling.Value)
			{
				return KeyUtil.Held(Settings.BuildMenuScrollModifier.Value);
			}
			return false;
		}
	}

	public static void Tick()
	{
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: 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_0131: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			if (!_noPlayerDone)
			{
				_noPlayerDone = true;
				_idleDone = false;
				_closeOnRelease = false;
				PieceWear.Idle();
				PieceCycle.Tick(null);
				ListPin.OnNoPlayer();
			}
			return;
		}
		_noPlayerDone = false;
		ListPin.OnPlayerPresent();
		if (!Features.Build || !((Character)localPlayer).InPlaceMode() || InventoryGui.IsVisible())
		{
			if (!_idleDone)
			{
				_idleDone = true;
				_closeOnRelease = false;
				PieceWear.Idle();
				PieceCycle.Tick(localPlayer);
			}
			return;
		}
		_idleDone = false;
		if (_closeOnRelease)
		{
			CloseMenuIfModifierReleased();
		}
		bool flag = Hud.IsPieceSelectionVisible();
		if (!flag)
		{
			_stepAnchor = null;
		}
		if (Settings.EnableBuildMenuScrolling.Value && flag)
		{
			ScrollMenu(localPlayer);
		}
		if (Settings.EnableGhostPieceCycling.Value && !flag)
		{
			GhostCycle(localPlayer);
		}
		PieceCycle.Tick(localPlayer);
		PieceWear.Tick(localPlayer);
		if (Settings.EnableRepairTools.Value)
		{
			if (Settings.EnableAreaRepair.Value && Hotkeys.Down(Settings.AreaRepairHotkey.Value, Settings.AreaRepairHotkeyModifier.Value))
			{
				AreaRepair(localPlayer);
			}
			else if (Settings.EnableRepairHammerShortcut.Value && (flag || HoldingHammer(localPlayer)) && Hotkeys.Down(Settings.RepairHotkey.Value, Settings.RepairHotkeyModifier.Value))
			{
				SelectRepairTool(localPlayer);
			}
		}
	}

	private static void CloseMenuIfModifierReleased()
	{
		if (!Hud.IsPieceSelectionVisible() || !Settings.CloseMenuOnModifierRelease.Value || !Settings.EnableBuildMenuScrolling.Value || !Settings.EnableTagPieceScrolling.Value)
		{
			_closeOnRelease = false;
		}
		else if (!ModifierHeld)
		{
			_closeOnRelease = false;
			if (!PointerOverMenu())
			{
				Hud.HidePieceSelection();
			}
		}
	}

	internal static bool PointerOverMenu()
	{
		//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_013d: 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_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: 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)
		if (!Hud.IsPieceSelectionVisible())
		{
			return false;
		}
		BuildUi buildUi = Hud.instance.m_buildUi;
		float num = float.MaxValue;
		float num2 = float.MaxValue;
		float num3 = float.MinValue;
		float num4 = float.MinValue;
		bool flag = false;
		FieldInfo[] menuPartFields = MenuPartFields;
		foreach (FieldInfo fieldInfo in menuPartFields)
		{
			Component val = (Component)((fieldInfo != null) ? /*isinst with value type is only supported in some contexts*/: null);
			RectTransform val2 = (RectTransform)(((Object)(object)val != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			if (!((Object)(object)val2 == (Object)null) && ((Component)val2).gameObject.activeInHierarchy)
			{
				val2.GetWorldCorners(Corners);
				for (int j = 0; j < 4; j++)
				{
					num = Mathf.Min(num, Corners[j].x);
					num3 = Mathf.Max(num3, Corners[j].x);
					num2 = Mathf.Min(num2, Corners[j].y);
					num4 = Mathf.Max(num4, Corners[j].y);
				}
				flag = true;
			}
		}
		if (!flag)
		{
			return false;
		}
		Vector2 val3 = Vector2.op_Implicit(ZInput.pointerPosition);
		if (val3.x >= num - 12f && val3.x <= num3 + 12f && val3.y >= num2 - 12f)
		{
			return val3.y <= num4 + 12f;
		}
		return false;
	}

	private static FieldRef<Humanoid, ItemData> MakeRightItemRef()
	{
		try
		{
			return AccessTools.FieldRefAccess<Humanoid, ItemData>("m_rightItem");
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Held item lookup unavailable (the game may have changed): " + ex.Message));
			return null;
		}
	}

	private static void RefreshHeld(Player player)
	{
		ItemData val = (((Object)(object)player != (Object)null && RightItemRef != null) ? RightItemRef.Invoke((Humanoid)(object)player) : null);
		if (val == _heldItem)
		{
			return;
		}
		_heldItem = val;
		_heldHammer = false;
		_heldCycleTool = false;
		string text = ((val != null && (Object)(object)val.m_dropPrefab != (Object)null) ? ((Object)val.m_dropPrefab).name : null);
		if (text == null)
		{
			return;
		}
		_heldHammer = string.Equals(text, "Hammer", StringComparison.OrdinalIgnoreCase);
		string[] cycleToolPrefabs = CycleToolPrefabs;
		foreach (string b in cycleToolPrefabs)
		{
			if (string.Equals(text, b, StringComparison.OrdinalIgnoreCase))
			{
				_heldCycleTool = true;
				break;
			}
		}
	}

	internal static bool HoldingHammer(Player player)
	{
		RefreshHeld(player);
		return _heldHammer;
	}

	internal static bool HoldingCycleTool(Player player)
	{
		RefreshHeld(player);
		return _heldCycleTool;
	}

	internal static bool WheelBelongsToGhostCycling()
	{
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		if (PieceCycle.WheelActive(Player.m_localPlayer))
		{
			return true;
		}
		if (Settings.EnableBuildEnhancements == null || Settings.EnableGhostPieceCycling == null || !Settings.EnableBuildEnhancements.Value || !Settings.EnableGhostPieceCycling.Value)
		{
			return false;
		}
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return false;
		}
		if (PieceWear.LookComboActive(localPlayer))
		{
			return true;
		}
		if (KeyUtil.Held(Settings.GhostCycleModifier.Value) && HoldingCycleTool(localPlayer) && ((Character)localPlayer).InPlaceMode() && !Hud.IsPieceSelectionVisible())
		{
			return !InventoryGui.IsVisible();
		}
		return false;
	}

	private static List<Piece> GhostCycleSet(PieceTable table)
	{
		CycleSet.Clear();
		RawCycleSet.Clear();
		if (HoldingHammer(Player.m_localPlayer) && Settings.EnableListPinning.Value && ListPin.HasPin && ListPin.FillPinnedPieces(table, RawCycleSet))
		{
			AddPlaceable(RawCycleSet);
		}
		if (CycleSet.Count == 0)
		{
			RawCycleSet.Clear();
			RawCycleSet.AddRange(table.m_availablePieces);
			AddPlaceable(RawCycleSet);
		}
		return CycleSet;
	}

	private static void AddPlaceable(List<Piece> source)
	{
		foreach (Piece item in source)
		{
			if ((Object)(object)item != (Object)null && !item.m_repairPiece && !item.m_removePiece)
			{
				CycleSet.Add(item);
			}
		}
	}

	private static void GhostCycle(Player player)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		if (!KeyUtil.Held(Settings.GhostCycleModifier.Value) || !HoldingCycleTool(player) || PieceWear.LookComboActive(player))
		{
			return;
		}
		float num = Wheel();
		if (num == 0f)
		{
			return;
		}
		PieceTable buildTool = player.GetBuildTool();
		if ((Object)(object)buildTool == (Object)null)
		{
			return;
		}
		List<Piece> list = GhostCycleSet(buildTool);
		if (list.Count == 0)
		{
			return;
		}
		int num2 = ((!(num > 0f)) ? 1 : (-1));
		if (Settings.InvertGhostCycleDirection.Value)
		{
			num2 = -num2;
		}
		Piece selectedPiece = player.GetSelectedPiece();
		int num3 = -1;
		if ((Object)(object)selectedPiece != (Object)null)
		{
			for (int i = 0; i < list.Count; i++)
			{
				if (((Object)((Component)list[i]).gameObject).name == ((Object)((Component)selectedPiece).gameObject).name)
				{
					num3 = i;
					break;
				}
			}
		}
		Piece val = list[(num3 >= 0) ? Wrap(num3 + num2, list.Count) : ((num2 <= 0) ? (list.Count - 1) : 0)];
		if ((Object)(object)selectedPiece == (Object)null || ((Object)((Component)val).gameObject).name != ((Object)((Component)selectedPiece).gameObject).name)
		{
			player.SetSelectedPiece(val);
		}
	}

	internal static float Wheel()
	{
		//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_0006: 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_0013: Unknown result type (might be due to invalid IL or missing references)
		Vector2 mouseScrollDelta = Input.mouseScrollDelta;
		if (mouseScrollDelta.y == 0f)
		{
			return mouseScrollDelta.x;
		}
		return mouseScrollDelta.y;
	}

	private static bool Over(BuildUi ui, FieldInfo field)
	{
		//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)
		object? value = field.GetValue(ui);
		RectTransform val = (RectTransform)((value is RectTransform) ? value : null);
		if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeInHierarchy)
		{
			return RectTransformUtility.RectangleContainsScreenPoint(val, Vector2.op_Implicit(ZInput.pointerPosition), (Camera)null);
		}
		return false;
	}

	private static MenuRegion RegionUnderPointer(BuildUi ui)
	{
		if (Over(ui, TabContainerField))
		{
			return MenuRegion.Tabs;
		}
		if (Over(ui, TagContainerField))
		{
			return MenuRegion.Tags;
		}
		if (Over(ui, PieceViewField))
		{
			return MenuRegion.Pieces;
		}
		return MenuRegion.None;
	}

	internal static bool BlocksNativeScroll()
	{
		if (Settings.EnableBuildEnhancements == null || !Settings.EnableBuildEnhancements.Value || Settings.EnableBuildMenuScrolling == null || !Settings.EnableBuildMenuScrolling.Value || !ModifierHeld || !Hud.IsPieceSelectionVisible())
		{
			return false;
		}
		MenuRegion menuRegion = RegionUnderPointer(Hud.instance.m_buildUi);
		if (menuRegion != MenuRegion.Tags)
		{
			return menuRegion == MenuRegion.Pieces;
		}
		return true;
	}

	private static void ScrollMenu(Player player)
	{
		float num = Wheel();
		if (num == 0f)
		{
			return;
		}
		BuildUi buildUi = Hud.instance.m_buildUi;
		MenuRegion menuRegion = RegionUnderPointer(buildUi);
		bool value;
		switch (menuRegion)
		{
		default:
			value = Settings.EnableTagPieceScrolling.Value;
			break;
		case MenuRegion.Tabs:
			value = Settings.EnableTabScrolling.Value;
			break;
		case MenuRegion.None:
			return;
		}
		if (value && (menuRegion == MenuRegion.Tabs || ModifierHeld))
		{
			int step = ((!(num > 0f)) ? 1 : (-1));
			switch (menuRegion)
			{
			case MenuRegion.Tabs:
				StepTab(buildUi, step);
				_closeOnRelease = false;
				break;
			case MenuRegion.Tags:
				StepTag(buildUi, step);
				_closeOnRelease = false;
				break;
			default:
				StepPiece(buildUi, player, step);
				_closeOnRelease = Settings.CloseMenuOnModifierRelease.Value;
				break;
			}
		}
	}

	private static int Wrap(int index, int count)
	{
		return (index % count + count) % count;
	}

	private static void StepTab(BuildUi ui, int step)
	{
		object? value = TabHandlerField.GetValue(ui);
		TabHandler val = (TabHandler)((value is TabHandler) ? value : null);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		List<int> stepIds = StepIds;
		stepIds.Clear();
		for (int i = 0; i < val.m_tabs.Count; i++)
		{
			if ((Object)(object)val.m_tabs[i].m_button != (Object)null && ((Component)val.m_tabs[i].m_button).gameObject.activeInHierarchy)
			{
				stepIds.Add(i);
			}
		}
		if (stepIds.Count >= 2)
		{
			int num = Mathf.Max(0, stepIds.IndexOf(val.GetActiveTab()));
			ui.SelectPieceList(stepIds[Wrap(num + step, stepIds.Count)], false);
		}
	}

	private static void StepTag(BuildUi ui, int step)
	{
		List<int> stepIds = StepIds;
		stepIds.Clear();
		object? value = ShowAllTagField.GetValue(ui);
		BuildUiTagButton val = (BuildUiTagButton)((value is BuildUiTagButton) ? value : null);
		if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf)
		{
			stepIds.Add(val.m_tagId);
		}
		if (TagButtonsField.GetValue(ui) is List<BuildUiTagButton> list)
		{
			foreach (BuildUiTagButton item in list)
			{
				if ((Object)(object)item != (Object)null && ((Component)item).gameObject.activeSelf)
				{
					stepIds.Add(item.m_tagId);
				}
			}
		}
		if (stepIds.Count >= 2)
		{
			int num = Mathf.Max(0, stepIds.IndexOf((int)CurrentTagField.GetValue(ui)));
			OnSelectTagMethod.Invoke(ui, new object[1] { stepIds[Wrap(num + step, stepIds.Count)] });
		}
	}

	private static void StepPiece(BuildUi ui, Player player, int step)
	{
		//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)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Expected O, but got Unknown
		if (!(PieceButtonsField.GetValue(ui) is List<BuildUiPieceButton> list))
		{
			return;
		}
		List<Piece> stepPieces = StepPieces;
		stepPieces.Clear();
		int num = -1;
		int num2 = -1;
		foreach (BuildUiPieceButton item in list)
		{
			if (!((Object)(object)item == (Object)null) && ((Component)item).gameObject.activeSelf && !((Object)(object)item.Piece == (Object)null))
			{
				if (num2 < 0 && RectTransformUtility.RectangleContainsScreenPoint((RectTransform)((Component)item).transform, Vector2.op_Implicit(ZInput.pointerPosition), (Camera)null))
				{
					num2 = stepPieces.Count;
				}
				stepPieces.Add(item.Piece);
			}
		}
		if (stepPieces.Count == 0)
		{
			return;
		}
		string text = ((num2 >= 0) ? ((Object)((Component)stepPieces[num2]).gameObject).name : null);
		if (text != null && text != _stepAnchor)
		{
			num = num2;
		}
		_stepAnchor = text;
		if (num < 0)
		{
			Piece val = default(Piece);
			Vector2Int val2 = default(Vector2Int);
			int num3 = default(int);
			PieceCategory val3 = default(PieceCategory);
			PieceTable val4 = default(PieceTable);
			player.GetBuildSelection(ref val, ref val2, ref num3, ref val3, ref val4);
			if ((Object)(object)val != (Object)null)
			{
				for (int i = 0; i < stepPieces.Count; i++)
				{
					if (((Object)((Component)stepPieces[i]).gameObject).name == ((Object)((Component)val).gameObject).name)
					{
						num = i;
						break;
					}
				}
			}
		}
		Piece val5 = stepPieces[(num >= 0) ? Wrap(num + step, stepPieces.Count) : ((step <= 0) ? (stepPieces.Count - 1) : 0)];
		if (player.SetSelectedPiece(val5))
		{
			UpdatePieceSelectionMethod.Invoke(ui, new object[1] { val5 });
		}
	}

	private static void SelectRepairTool(Player player)
	{
		PieceTable buildTool = player.GetBuildTool();
		if ((Object)(object)buildTool == (Object)null)
		{
			return;
		}
		if (!RepairPieces.TryGetValue(buildTool, out var value))
		{
			value = null;
			foreach (GameObject piece in buildTool.m_pieces)
			{
				Piece val = (((Object)(object)piece != (Object)null) ? piece.GetComponent<Piece>() : null);
				if ((Object)(object)val != (Object)null && val.m_repairPiece)
				{
					value = val;
					break;
				}
			}
			RepairPieces[buildTool] = value;
		}
		if ((Object)(object)value == (Object)null)
		{
			return;
		}
		if (player.SetSelectedPiece(value))
		{
			if (Hud.IsPieceSelectionVisible())
			{
				Hud.HidePieceSelection();
			}
		}
		else
		{
			Plugin.Debug("Repair tool is not available in this build table.");
		}
	}

	private static void AreaRepair(Player player)
	{
		//IL_0010: 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)
		Nearby.Clear();
		Piece.GetAllPiecesInRadius(((Component)player).transform.position, Settings.AreaRepairRadius.Value, Nearby);
		int num = 0;
		int num2 = 0;
		foreach (Piece item in Nearby)
		{
			WearNTear val = (((Object)(object)item != (Object)null) ? ((Component)item).GetComponent<WearNTear>() : null);
			if (!((Object)(object)val == (Object)null) && PrivateArea.CheckAccess(((Component)item).transform.position, 0f, false, false))
			{
				if (PieceWear.HasChosenLook(item))
				{
					num2++;
				}
				else if (val.Repair())
				{
					num++;
				}
			}
		}
		Nearby.Clear();
		string text = ((num > 0) ? ("Repaired " + num + ((num == 1) ? " piece" : " pieces")) : "Nothing nearby needs repair");
		if (num2 > 0)
		{
			text = text + " (" + num2 + " left as placed)";
		}
		((Character)player).Message((MessageType)1, text, 0, (Sprite)null, false);
	}

	private static Piece LookedAtPiece(Player player)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: 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)
		RaycastHit val = default(RaycastHit);
		if (!Physics.Raycast(((Component)GameCamera.instance).transform.position, ((Component)GameCamera.instance).transform.forward, ref val, 50f, RayMask) || Vector3.Distance(((RaycastHit)(ref val)).point, ((Character)player).m_eye.position) >= player.m_maxPlaceDistance)
		{
			return null;
		}
		return ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Piece>();
	}

	private static bool DropsCargoWhenRemoved(Container c)
	{
		GameObject val = (((Object)(object)c.m_rootObjectOverride != (Object)null) ? ((Component)c.m_rootObjectOverride).gameObject : ((Component)c).gameObject);
		if (!((Object)(object)val.GetComponent<WearNTear>() != (Object)null))
		{
			return (Object)(object)val.GetComponent<Destructible>() != (Object)null;
		}
		return true;
	}

	internal static bool BeforeRemove(Player player, ref bool result)
	{
		if (!Settings.EnableBuildEnhancements.Value || (Object)(object)player != (Object)(object)Player.m_localPlayer || ConfirmDialog.IsOpen)
		{
			return true;
		}
		bool value = Settings.EnableBoatRemoval.Value;
		bool value2 = Settings.EnableCartRemoval.Value;
		if (!value && !value2)
		{
			return true;
		}
		Piece val = LookedAtPiece(player);
		if ((Object)(object)val == (Object)null || val.m_canBeRemoved)
		{
			return true;
		}
		Ship val2 = (value ? ((Component)val).GetComponentInChildren<Ship>() : null);
		Vagon val3 = (((Object)(object)val2 == (Object)null && value2) ? ((Component)val).GetComponentInChildren<Vagon>() : null);
		if ((Object)(object)val2 == (Object)null && (Object)(object)val3 == (Object)null)
		{
			return true;
		}
		if ((Object)(object)ApprovedPiece != (Object)null && (Object)(object)val != (Object)(object)ApprovedPiece)
		{
			ApprovedPiece = null;
			result = false;
			return false;
		}
		if ((Object)(object)val == (Object)(object)ApprovedPiece)
		{
			return true;
		}
		string text = (((Object)(object)val2 != (Object)null) ? "boat" : "cart");
		if (((Object)(object)val2 != (Object)null) ? (!val2.CanBeRemoved()) : val3.InUse())
		{
			((Character)player).Message((MessageType)2, ((Object)(object)val2 != (Object)null) ? "Can't deconstruct a boat while someone is aboard" : "Can't deconstruct a cart while it is hitched or open", 0, (Sprite)null, false);
			result = false;
			return false;
		}
		bool flag = (((Object)(object)val2 != (Object)null) ? Settings.AllowLoadedBoatRemoval.Value : Settings.AllowLoadedCartRemoval.Value);
		bool flag2 = false;
		Container[] componentsInChildren = ((Component)val).GetComponentsInChildren<Container>();
		foreach (Container val4 in componentsInChildren)
		{
			if (val4.GetInventory() != null && val4.GetInventory().NrOfItems() != 0)
			{
				if (!flag || !DropsCargoWhenRemoved(val4))
				{
					((Character)player).Message((MessageType)2, "Empty the " + text + "'s cargo before deconstructing it", 0, (Sprite)null, false);
					result = false;
					return false;
				}
				flag2 = true;
			}
		}
		if (((Object)(object)val2 != (Object)null) ? Settings.ConfirmBoatRemoval.Value : Settings.ConfirmCartRemoval.Value)
		{
			Piece target = val;
			ConfirmDialog.Show("Deconstruct this " + text + "? It will be removed and its parts returned." + (flag2 ? " Its cargo drops on the ground." : ""), delegate
			{
				if ((Object)(object)target == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
				{
					return;
				}
				ApprovedPiece = target;
				try
				{
					RemovePieceMethod.Invoke(Player.m_localPlayer, null);
				}
				finally
				{
					ApprovedPiece = null;
				}
			});
			result = false;
			return false;
		}
		ApprovedPiece = val;
		return true;
	}
}
[HarmonyPatch(typeof(ZInput), "GetMouseScrollWheel")]
internal static class BuildTools_GhostCycle_Wheel_Patch
{
	private static void Postfix(ref float __result)
	{
		if (__result != 0f && BuildTools.WheelBelongsToGhostCycling())
		{
			__result = 0f;
		}
	}
}
[HarmonyPatch(typeof(Player), "RemovePiece")]
internal static class BuildTools_RemovePiece_Patch
{
	private const float BreakVolume = 1.3f;

	private static bool _lifted;

	private static Piece _liftedPiece;

	private static Vector3 _pos;

	private static EffectList _hit;

	private static readonly HashSet<ZSFX> SoundsBefore = new HashSet<ZSFX>();

	private static bool Prefix(Player __instance, ref bool __result)
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!BuildTools.BeforeRemove(__instance, ref __result))
			{
				return false;
			}
			Piece approvedPiece = BuildTools.ApprovedPiece;
			if ((Object)(object)approvedPiece != (Object)null && !approvedPiece.m_canBeRemoved)
			{
				approvedPiece.m_canBeRemoved = true;
				_lifted = true;
				_liftedPiece = approvedPiece;
				_pos = ((Component)approvedPiece).transform.position;
				WearNTear component = ((Component)approvedPiece).GetComponent<WearNTear>();
				_hit = (((Object)(object)component != (Object)null && component.m_hitEffect != null && component.m_hitEffect.HasEffects()) ? component.m_hitEffect : null);
				SoundsBefore.Clear();
				foreach (IMonoUpdater instance in ZSFX.Instances)
				{
					ZSFX val = (ZSFX)(object)((instance is ZSFX) ? instance : null);
					if ((Object)(object)val != (Object)null)
					{
						SoundsBefore.Add(val);
					}
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Boat / cart removal failed: " + ex));
		}
		return true;
	}

	private static void Postfix(bool __result)
	{
		//IL_0051: 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_0064: 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_00a7: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		if (!_lifted)
		{
			return;
		}
		if ((Object)(object)_liftedPiece != (Object)null)
		{
			_liftedPiece.m_canBeRemoved = false;
		}
		_lifted = false;
		_liftedPiece = null;
		BuildTools.ApprovedPiece = null;
		EffectList hit = _hit;
		_hit = null;
		if (!__result)
		{
			SoundsBefore.Clear();
			return;
		}
		try
		{
			if (hit != null)
			{
				hit.Create(_pos, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			}
			foreach (IMonoUpdater instance in ZSFX.Instances)
			{
				ZSFX val = (ZSFX)(object)((instance is ZSFX) ? instance : null);
				if ((Object)(object)val != (Object)null && !SoundsBefore.Contains(val))
				{
					Vector3 val2 = ((Component)val).transform.position - _pos;
					if (((Vector3)(ref val2)).sqrMagnitude < 25f)
					{
						val.SetVolumeModifier(val.GetVolumeModifier() * 1.3f);
					}
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Deconstruct sound failed: " + ex.Message));
		}
		finally
		{
			SoundsBefore.Clear();
		}
	}
}
internal static class ConfirmDialog
{
	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static PopupButtonCallback <>9__5_1;

		internal void <Show>b__5_1()
		{
			_open = false;
			UnifiedPopup.Pop();
		}
	}

	private static bool _open;

	internal const string ConfirmColor = "#D5BA8E";

	public static bool IsOpen
	{
		get
		{
			if (_open && !UnifiedPopup.IsVisible())
			{
				_open = false;
			}
			return _open;
		}
	}

	internal static string Tint(string text)
	{
		if (string.IsNullOrEmpty(text) || text.IndexOf("<color", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return text;
		}
		return "<color=#D5BA8E>" + text + "</color>";
	}

	public static void Show(string message, Action onYes)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Expected O, but got Unknown
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Expected O, but got Unknown
		//IL_0044: 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_004f: Expected O, but got Unknown
		try
		{
			if (_open)
			{
				return;
			}
			string text = Tint(message);
			PopupButtonCallback val = delegate
			{
				_open = false;
				UnifiedPopup.Pop();
				if (onYes != null)
				{
					onYes();
				}
			};
			object obj = <>c.<>9__5_1;
			if (obj == null)
			{
				PopupButtonCallback val2 = delegate
				{
					_open = false;
					UnifiedPopup.Pop();
				};
				<>c.<>9__5_1 = val2;
				obj = (object)val2;
			}
			UnifiedPopup.Push((PopupBase)new YesNoPopup("Please confirm", text, val, (PopupButtonCallback)obj, false, false));
			_open = UnifiedPopup.IsVisible();
			if (!_open)
			{
				Plugin.Log.LogWarning((object)"The game's popup is not available; running the confirmed action without asking.");
				if (onYes != null)
				{
					onYes();
				}
			}
		}
		catch (Exception ex)
		{
			_open = false;
			Plugin.Log.LogError((object)("Could not show the confirmation popup, running the action without asking: " + ex));
			if (onYes != null)
			{
				onYes();
			}
		}
	}
}
internal static class Features
{
	private sealed class Group
	{
		public string Name;

		public Type[] Types;

		public Func<bool> Wanted;

		public Action OnEnabled;

		public Harmony H;

		public bool Active;

		public void Apply()
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			bool flag;
			try
			{
				flag = Wanted();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Feature '" + Name + "' check failed: " + ex));
				return;
			}
			if (flag == Active)
			{
				return;
			}
			try
			{
				if (flag)
				{
					Active = true;
					H = new Harmony("Cano.Fixedheim." + Name);
					Type[] types = Types;
					foreach (Type type in types)
					{
						H.PatchAll(type);
					}
					if (OnEnabled != null)
					{
						OnEnabled();
					}
					Plugin.Debug("Feature '" + Name + "': hooks installed.");
				}
				else
				{
					Active = false;
					if (H != null)
					{
						H.UnpatchSelf();
					}
					H = null;
					Plugin.Debug("Feature '" + Name + "': hooks removed.");
				}
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogError((object)("Feature '" + Name + "' could not be " + (flag ? "installed" : "removed") + ": " + ex2));
			}
		}
	}

	internal static bool Sorting;

	internal static bool StacksOn;

	internal static bool Build;

	internal static bool Rain;

	internal static bool Snow;

	internal static bool Ash;

	internal static bool Lava;

	internal static bool Smoke;

	internal static bool ListEditing;

	internal static bool Pinning;

	internal static bool DebugOn;

	private static float _nextReport;

	private static readonly List<Group> Groups = new List<Group>();

	private static bool _refreshRequested;

	private static void Add(string name, Func<bool> wanted, Action onEnabled, params Type[] types)
	{
		Groups.Add(new Group
		{
			Name = name,
			Wanted = wanted,
			OnEnabled = onEnabled,
			Types = types
		});
	}

	internal static void Init()
	{
		Add("core", () => true, null, typeof(InventoryGui_Show_Patch));
		Add("mousestacks", () => StacksOn, null, typeof(MouseStacks_Update_Patch), typeof(MouseStacks_OnSelectedItem_Patch), typeof(MouseStacks_Hide_Patch), typeof(MouseStacks_SetupDragItem_Patch), typeof(MouseStacks_UpdateCraftingPanel_Patch), typeof(MouseStacks_OnRightClickItem_Patch), typeof(MouseStacks_UpdateItemDrag_Patch));
		Add("scrollguard", () => StacksOn || (Build && Settings.EnableBuildMenuScrolling.Value), null, typeof(MouseStacks_ScrollRect_OnScroll_Patch));
		Add("buildcore", () => Build, null, typeof(PieceWear_Repair_Patch), typeof(FavoritePieceList_RemoveTag_Patch));
		Add("weather", () => Rain || Snow || Ash || Lava, null, typeof(PieceWear_UpdateWear_Patch));
		Add("damagelook", () => Build && Settings.EnableDamageLookCycling.Value, null, typeof(PieceWear_PlacePiece_Patch), typeof(PieceWear_OnPlaced_Patch), typeof(PieceWear_SetCreator_Patch));
		Add("smoke", () => Smoke, null, typeof(BuildEffects_Create_Patch), typeof(BuildEffects_PlacePiece_Patch), typeof(BuildEffects_Repair_Patch), typeof(BuildEffects_TerrainOp_Patch));
		Add("deconstruct", () => Build && (Settings.EnableBoatRemoval.Value || Settings.EnableCartRemoval.Value), null, typeof(BuildTools_RemovePiece_Patch));
		Add("highlightcycling", () => Build && Settings.EnablePieceCycling.Value, null, typeof(PieceCycle_Redirect_Patch));
		Add("wheel", () => Build && (Settings.EnableGhostPieceCycling.Value || Settings.EnableDamageLookCycling.Value || Settings.EnablePieceCycling.Value), null, typeof(BuildTools_GhostCycle_Wheel_Patch));
		Add("listbuttons", () => Build && (Settings.EnableFavoriteListEditing.Value || Settings.EnableListPinning.Value), TagButtonExtras.AttachToExisting, typeof(BuildUiTagButton_Awake_Patch));
		Add("iconsize", () => BuildIconSize.PendingRestore || (Build && Settings.EnablePieceIconSize.Value && Settings.PieceIconSize.Value != 100), null, typeof(BuildIconSize_UpdatePieceButtons_Patch));
		Add("buildtoolstands", () => Build && Settings.BlockOnStands.Value, null, typeof(HammerStands_ItemStand_Patch), typeof(HammerStands_ArmorStand_Patch));
		Refresh();
	}

	internal static void RequestRefresh()
	{
		_refreshRequested = true;
	}

	internal static void Tick()
	{
		if (DebugOn && (Rain || Snow || Ash || Lava))
		{
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime >= _nextReport)
			{
				_nextReport = unscaledTime + 20f;
				PieceWear.ReportWeather();
			}
		}
		if (_refreshRequested)
		{
			_refreshRequested = false;
			Refresh();
		}
	}

	internal static void Refresh()
	{
		Sorting = Settings.EnableSorting.Value;
		StacksOn = Settings.EnableMouseStacks.Value;
		Build = Settings.EnableBuildEnhancements.Value;
		Rain = Build && Settings.NoRainDamage.Value;
		Snow = Build && Settings.NoSnowDamage.Value;
		Ash = Build && Settings.NoAshDamage.Value;
		Lava = Build && Settings.NoLavaDamage.Value;
		Smoke = Build && Settings.NoBuildSmoke.Value;
		ListEditing = Build && Settings.EnableFavoriteListEditing.Value;
		Pinning = Build && Settings.EnableListPinning.Value;
		DebugOn = Settings.DebugLogging.Value;
		if (!Snow)
		{
			PieceWear.RestoreSnow();
		}
		foreach (Group group in Groups)
		{
			group.Apply();
		}
	}

	internal static void Shutdown()
	{
		foreach (Group group in Groups)
		{
			try
			{
				if (group.H != null)
				{
					group.H.UnpatchSelf();
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Feature '" + group.Name + "' unpatch failed: " + ex.Message));
			}
			group.H = null;
			group.Active = false;
		}
		PieceWear.RestoreSnow();
	}
}
internal static class GridAccess
{
	private static readonly FieldInfo ElementsField = AccessTools.Field(typeof(InventoryGrid), "m_elements");

	private static readonly FieldInfo InventoryField = AccessTools.Field(typeof(InventoryGrid), "m_inventory");

	private static bool _reported;

	public static void Verify()
	{
		if (!_reported)
		{
			_reported = true;
			string text = "";
			if (ElementsField == null)
			{
				text += " InventoryGrid.m_elements";
			}
			if (InventoryField == null)
			{
				text += " InventoryGrid.m_inventory";
			}
			if (text.Length > 0)
			{
				Plugin.Log.LogError((object)("This game version no longer has:" + text + ". Mouse Stacks' drag-to-distribute will not work until the mod is updated."));
			}
		}
	}

	public static IEnumerable<InventoryGrid> AllOpenGrids()
	{
		return Object.FindObjectsByType<InventoryGrid>((FindObjectsSortMode)0);
	}

	public static List<InventoryElement> Elements(InventoryGrid grid)
	{
		if (!(ElementsField == null) && !((Object)(object)grid == (Object)null))
		{
			return ElementsField.GetValue(grid) as List<InventoryElement>;
		}
		return null;
	}

	public static Inventory Inventory(InventoryGrid grid)
	{
		if (!(InventoryField == null) && !((Object)(object)grid == (Object)null))
		{
			object? value = InventoryField.GetValue(grid);
			return (Inventory)((value is Inventory) ? value : null);
		}
		return null;
	}

	public static ItemData ItemUnderMouse(InventoryGrid grid)
	{
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		List<InventoryElement> list = Elements(grid);
		Inventory val = Inventory(grid);
		if (list == null || val == null)
		{
			if (Settings.DebugLogging != null && Settings.DebugLogging.Value)
			{
				Plugin.Debug("    '" + ((Object)grid).name + "' (id " + ((Object)grid).GetInstanceID() + "): elements=" + ((list == null) ? "NULL" : list.Count.ToString()) + " inventory=" + ((val == null) ? "NULL" : ("ok(" + val.GetWidth() + "x" + val.GetHeight() + ")")));
			}
			return null;
		}
		for (int i = 0; i < list.Count; i++)
		{
			InventoryElement val2 = list[i];
			if ((Object)(object)val2 == (Object)null)
			{
				continue;
			}
			RectTransform elementRectTransform = val2.GetElementRectTransform();
			if ((Object)(object)elementRectTransform == (Object)null || !((Component)elementRectTransform).gameObject.activeInHierarchy || !RectTransformUtility.RectangleContainsScreenPoint(elementRectTransform, Vector2.op_Implicit(Input.mousePosition), CanvasCamera(elementRectTransform)))
			{
				continue;
			}
			Vector2i position = val2.Position;
			List<ItemData> list2 = Reflect.Items(val);
			if (list2 == null)
			{
				if (Settings.DebugLogging != null && Settings.DebugLogging.Value)
				{
					Plugin.Debug("    rect hit at (" + position.x + "," + position.y + ") but Reflect.Items(inventory) returned NULL.");
				}
				return null;
			}
			foreach (ItemData item in list2)
			{
				if (item.m_gridPos.x == position.x && item.m_gridPos.y == position.y)
				{
					return item;
				}
			}
			if (Settings.DebugLogging != null && Settings.DebugLogging.Value)
			{
				string text = "";
				foreach (ItemData item2 in list2)
				{
					text = text + item2.m_shared.m_name + "@(" + item2.m_gridPos.x + "," + item2.m_gridPos.y + ") ";
				}
				Plugin.Debug("    rect hit at (" + position.x + "," + position.y + ") but no item matched. " + list2.Count + " item(s): " + text);
			}
			return null;
		}
		if (Settings.DebugLogging != null && Settings.DebugLogging.Value)
		{
			DebugDescribeMiss(grid, list);
		}
		return null;
	}

	public static bool ElementAt(InventoryGrid grid, Vector2 screenPoint, out Vector2i pos)
	{
		//IL_0003: 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_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: 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)
		pos = new Vector2i(-1, -1);
		if ((Object)(object)grid == (Object)null || !((Behaviour)grid).isActiveAndEnabled)
		{
			return false;
		}
		List<InventoryElement> list = Elements(grid);
		if (list == null)
		{
			return false;
		}
		Transform transform = ((Component)grid).transform;
		RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
		if ((Object)(object)val != (Object)null && !RectTransformUtility.RectangleContainsScreenPoint(val, screenPoint, CanvasCamera(val)))
		{
			return false;
		}
		for (int i = 0; i < list.Count; i++)
		{
			InventoryElement val2 = list[i];
			if (!((Object)(object)val2 == (Object)null))
			{
				RectTransform elementRectTransform = val2.GetElementRectTransform();
				if (!((Object)(object)elementRectTransform == (Object)null) && ((Component)elementRectTransform).gameObject.activeInHierarchy && RectTransformUtility.RectangleContainsScreenPoint(elementRectTransform, screenPoint, CanvasCamera(elementRectTransform)))
				{
					pos = val2.Position;
					return true;
				}
			}
		}
		return false;
	}

	public static bool SlotUnderMouse(InventoryGrid grid, out int x, out int y)
	{
		//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_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_0154: Unknown result type (might be due to invalid IL or missing references)
		x = 0;
		y = 0;
		List<InventoryElement> list = Elements(grid);
		Inventory val = Inventory(grid);
		if (list == null || val == null)
		{
			if (Settings.DebugLogging != null && Settings.DebugLogging.Value)
			{
				Plugin.Debug("    '" + ((Object)grid).name + "' (id " + ((Object)grid).GetInstanceID() + "): elements=" + ((list == null) ? "NULL" : list.Count.ToString()) + " inventory=" + ((val == null) ? "NULL" : ("ok(" + val.GetWidth() + "x" + val.GetHeight() + ")")));
			}
			return false;
		}
		for (int i = 0; i < list.Count; i++)
		{
			InventoryElement val2 = list[i];
			if (!((Object)(object)val2 == (Object)null))
			{
				RectTransform elementRectTransform = val2.GetElementRectTransform();
				if (!((Object)(object)elementRectTransform == (Object)null) && ((Component)elementRectTransform).gameObject.activeInHierarchy && RectTransformUtility.RectangleContainsScreenPoint(elementRectTransform, Vector2.op_Implicit(Input.mousePosition), CanvasCamera(elementRectTransform)))
				{
					Vector2i position = val2.Position;
					x = position.x;
					y = position.y;
					return true;
				}
			}
		}
		if (Settings.DebugLogging != null && Settings.DebugLogging.Value)
		{
			DebugDescribeMiss(grid, list);
		}
		return false;
	}

	private unsafe static void DebugDescribeMiss(InventoryGrid grid, List<InventoryElement> elements)
	{
		//IL_00d0: 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_00da: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: 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_018a: 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)
		//IL_01a8: 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_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
		int num = 0;
		RectTransform val = null;
		foreach (InventoryElement element in elements)
		{
			if ((Object)(object)element == (Object)null)
			{
				continue;
			}
			RectTransform elementRectTransform = element.GetElementRectTransform();
			if (!((Object)(object)elementRectTransform == (Object)null) && ((Component)elementRectTransform).gameObject.activeInHierarchy)
			{
				num++;
				if ((Object)(object)val == (Object)null)
				{
					val = elementRectTransform;
				}
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			Plugin.Debug("    miss on '" + ((Object)grid).name + "': 0 of " + elements.Count + " slot elements are active - nothing to hit-test against.");
			return;
		}
		Camera val2 = CanvasCamera(val);
		Vector3[] array = (Vector3[])(object)new Vector3[4];
		val.GetWorldCorners(array);
		Vector2 val3 = RectTransformUtility.WorldToScreenPoint(val2, array[0]);
		Vector2 val4 = RectTransformUtility.WorldToScreenPoint(val2, array[2]);
		Canvas componentInParent = ((Component)val).GetComponentInParent<Canvas>();
		Canvas val5 = ((!((Object)(object)componentInParent != (Object)null)) ? null : (((Object)(object)componentInParent.rootCanvas != (Object)null) ? componentInParent.rootCanvas : componentInParent));
		string[] obj = new string[16]
		{
			"    miss on '",
			((Object)grid).name,
			"': ",
			num.ToString(),
			" of ",
			elements.Count.ToString(),
			" slots active, mouse=",
			((object)Input.mousePosition/*cast due to .constrained prefix*/).ToString(),
			", sample slot screen rect=",
			null,
			null,
			null,
			null,
			null,
			null,
			null
		};
		Vector2 val6 = val3;
		obj[9] = ((object)(*(Vector2*)(&val6))/*cast due to .constrained prefix*/).ToString();
		obj[10] = "..";
		val6 = val4;
		obj[11] = ((object)(*(Vector2*)(&val6))/*cast due to .constrained prefix*/).ToString();
		obj[12] = ", canvas renderMode=";
		obj[13] = (((Object)(object)val5 == (Object)null) ? "no canvas found" : ((object)val5.renderMode/*cast due to .constrained prefix*/).ToString());
		obj[14] = ", resolved camera=";
		obj[15] = (((Object)(object)val2 == (Object)null) ? "null" : ((Object)val2).name);
		Plugin.Debug(string.Concat(obj));
	}

	private static Camera CanvasCamera(RectTransform rect)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		Canvas componentInParent = ((Component)rect).GetComponentInParent<Canvas>();
		if ((Object)(object)componentInParent == (Object)null)
		{
			return null;
		}
		Canvas val = (((Object)(object)componentInParent.rootCanvas != (Object)null) ? componentInParent.rootCanvas : componentInParent);
		if ((int)val.renderMode != 0)
		{
			return val.worldCamera;
		}
		return null;
	}
}
internal static class HammerStands
{
	private const string HammerPrefab = "hammer";

	internal static bool Refuse(ItemData item)
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		if (item == null || item.m_shared == null)
		{
			return false;
		}
		if ((Object)(object)item.m_dropPrefab == (Object)null || !string.Equals(((Object)item.m_dropPrefab).name, "hammer", StringComparison.OrdinalIgnoreCase))
		{
			return false;
		}
		return !KeyUtil.Held(Settings.StandModifier.Value);
	}
}
[HarmonyPatch(typeof(ItemStand), "UseItem")]
internal static class HammerStands_ItemStand_Patch
{
	private static bool Prefix(ItemData item, ref bool __result)
	{
		if (!HammerStands.Refuse(item))
		{
			return true;
		}
		__result = false;
		return false;
	}
}
[HarmonyPatch(typeof(ArmorStand), "UseItem")]
internal static class HammerStands_ArmorStand_Patch
{
	private static bool Prefix(ItemData item, ref bool __result)
	{
		if (!HammerStands.Refuse(item))
		{
			return true;
		}
		__result = false;
		return false;
	}
}
internal static class Hotkeys
{
	public static bool Down(KeyCode key, KeyCode modifier)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: 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)
		if ((int)key == 0 || !KeyUtil.Pressed(key) || Typing())
		{
			return false;
		}
		if ((int)modifier != 0 && !KeyUtil.Held(modifier))
		{
			return false;
		}
		return !KeyUtil.AnyModifierHeldExcept(modifier);
	}

	public static bool Down(KeyboardShortcut shortcut)
	{
		//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_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: 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_0039: 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)
		KeyCode mainKey = ((KeyboardShortcut)(ref shortcut)).MainKey;
		if ((int)mainKey == 0 || !KeyUtil.Pressed(mainKey) || Typing())
		{
			return false;
		}
		bool[] array = new bool[5];
		foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
		{
			if (!KeyUtil.Held(modifier))
			{
				return false;
			}
			int num = KeyUtil.ModifierGroup(modifier);
			if (num > 0)
			{
				array[num] = true;
			}
		}
		for (int i = 1; i <= 4; i++)
		{
			if (!array[i] && KeyUtil.Held((KeyCode)(i switch
			{
				3 => 308, 
				2 => 306, 
				1 => 304, 
				_ => 310, 
			})))
			{
				return false;
			}
		}
		return true;
	}

	public static bool Typing()
	{
		if ((!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible())
		{
			return Menu.IsVisible();
		}
		return true;
	}
}
internal static class IconShapeGenerator
{
	private delegate bool ShapeTest(Vector2 point);

	private const int Size = 128;

	private const int SuperSample = 4;

	public static readonly Color32 SlateColor = new Color32((byte)148, (byte)140, (byte)122, byte.MaxValue);

	private static Sprite _trashCan;

	public static Sprite TrashCan()
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_trashCan == (Object)null)
		{
			_trashCan = Rasterize(TrashCanShape, "Cano.Fixedheim.Generated.TrashCan", SlateColor, emboss: true, TrashCanGroove);
		}
		return _trashCan;
	}

	private static bool TrashCanShape(Vector2 p)
	{
		//IL_0000: 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)
		float x = p.x;
		float y = p.y;
		if (y >= 92f && y <= 102f && Mathf.Abs(x - 64f) <= 42f)
		{
			return true;
		}
		if (y >= 102f && y <= 113f && Mathf.Abs(x - 64f) <= 13f)
		{
			return true;
		}
		if (y >= 14f && y <= 91f)
		{
			float num = (y - 14f) / 77f;
			float num2 = Mathf.Lerp(27f, 34f, num);
			return Mathf.Abs(x - 64f) <= num2;
		}
		return false;
	}

	private static bool TrashCanGroove(Vector2 p)
	{
		//IL_0000: 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)
		float x = p.x;
		float y = p.y;
		if (y >= 28f && y <= 78f)
		{
			float num = Mathf.Abs(x - 64f);
			if (num <= 2.5f)
			{
				return true;
			}
			if (Mathf.Abs(num - 15f) <= 2.5f)
			{
				return true;
			}
		}
		if (y >= 88f && y <= 90.5f && Mathf.Abs(x - 64f) <= 33f)
		{
			return true;
		}
		return false;
	}

	private static Sprite Rasterize(ShapeTest shape, string name, Color32 baseColor, bool emboss, ShapeTest groove = null)
	{
		//IL_018e: 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_0197: 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)
		//IL_0350: Unknown result type (might be due to invalid IL or missing references)
		//IL_0355: Unknown result type (might be due to invalid IL or missing references)
		//IL_035c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0362: Unknown result type (might be due to invalid IL or missing references)
		//IL_0369: Unknown result type (might be due to invalid IL or missing references)
		//IL_0370: Unknown result type (might be due to invalid IL or missing references)
		//IL_038b: Unknown result type (might be due to invalid IL or missing references)
		//IL_039a: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a9: Expected O, but got Unknown
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: 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_025f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0263: Unknown result type (might be due to invalid IL or missing references)
		//IL_0268: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0316: Unknown result type (might be due to invalid IL or missing references)
		//IL_031b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		float[,] array = new float[128, 128];
		float num = 0.25f;
		for (int i = 0; i < 128; i++)
		{
			for (int j = 0; j < 128; j++)
			{
				int num2 = 0;
				for (int k = 0; k < 4; k++)
				{
					for (int l = 0; l < 4; l++)
					{
						float num3 = (float)j + ((float)l + 0.5f) * num;
						float num4 = (float)i + ((float)k + 0.5f) * num;
						if (shape(new Vector2(num3, num4)))
						{
							num2++;
						}
					}
				}
				array[j, i] = (float)num2 / 16f;
			}
		}
		float[,] array2 = new float[128, 128];
		if (groove != null)
		{
			for (int m = 0; m < 128; m++)
			{
				for (int n = 0; n < 128; n++)
				{
					if (array[n, m] <= 0f)
					{
						continue;
					}
					int num5 = 0;
					for (int num6 = 0; num6 < 4; num6++)
					{
						for (int num7 = 0; num7 < 4; num7++)
						{
							if (groove(new Vector2((float)n + ((float)num7 + 0.5f) * num, (float)m + ((float)num6 + 0.5f) * num)))
							{
								num5++;
							}
						}
					}
					array2[n, m] = (float)num5 / 16f;
				}
			}
		}
		Color32[] array3 = (Color32[])(object)new Color32[16384];
		Vector3 val = new Vector3(-0.45f, 0.6f, 0.65f);
		Vector3 normalized = ((Vector3)(ref val)).normalized;
		for (int num8 = 0; num8 < 128; num8++)
		{
			for (int num9 = 0; num9 < 128; num9++)
			{
				float num10 = array[num9, num8];
				byte b = (byte)Mathf.RoundToInt(num10 * 255f);
				if (!emboss || num10 <= 0f)
				{
					array3[num8 * 128 + num9] = new Color32(baseColor.r, baseColor.g, baseColor.b, b);
					continue;
				}
				float num11 = SampleCoverage(array, num9 - 1, num8);
				float num12 = SampleCoverage(array, num9 + 1, num8);
				float num13 = SampleCoverage(array, num9, num8 - 1);
				float num14 = SampleCoverage(array, num9, num8 + 1);
				val = new Vector3((0f - (num12 - num11)) * 3.5f, (0f - (num14 - num13)) * 3.5f, 1f);
				float num15 = Vector3.Dot(((Vector3)(ref val)).normalized, normalized);
				float num16 = Mathf.Clamp(0.82f + num15 * 0.5f, 0.45f, 1.5f);
				num16 *= 1f - 0.42f * array2[num9, num8];
				byte b2 = (byte)Mathf.Clamp(Mathf.RoundToInt((float)(int)baseColor.r * num16), 0, 255);
				byte b3 = (byte)Mathf.Clamp(Mathf.RoundToInt((float)(int)baseColor.g * num16), 0, 255);
				byte b4 = (byte)Mathf.Clamp(Mathf.RoundToInt((float)(int)baseColor.b * num16), 0, 255);
				array3[num8 * 128 + num9] = new Color32(b2, b3, b4, b);
			}
		}
		Texture2D val2 = new Texture2D(128, 128, (TextureFormat)4, true);
		val2.SetPixels32(array3);
		val2.Apply();
		((Object)val2).name = name;
		((Texture)val2).filterMode = (FilterMode)1;
		((Texture)val2).wrapMode = (TextureWrapMode)1;
		Sprite obj = Sprite.Create(val2, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f), 100f);
		((Object)obj).name = name;
		return obj;
	}

	private static float SampleCoverage(float[,] coverage, int x, int y)
	{
		if (x < 0 || x >= 128 || y < 0 || y >= 128)
		{
			return 0f;
		}
		return coverage[x, y];
	}
}
internal enum SortMode
{
	Alphabetical,
	Weight,
	Category
}
internal static class InventorySorter
{
	public static bool Sort(Inventory inventory, SortMode mode, bool keepHotbar)
	{
		//IL_00c4: Unknown resul