Decompiled source of Controller Forge v1.0.0

BepInEx/plugins/ControllerForge.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ControllerForgeSlots;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
using Valheim.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Controller Forge")]
[assembly: AssemblyDescription("Controller interface and radial wheels for Valheim")]
[assembly: AssemblyCompany("elHUDlessG")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
internal static class CraftingNavigation
{
	private static readonly ManualLogSource CraftLog = Logger.CreateLogSource("Controller Forge CraftDiag");

	private static readonly FieldInfo CurrentlyHoldingCraft = AccessTools.Field(typeof(InventoryGui), "m_currentlyHoldingOnCraftButton");

	private static readonly FieldInfo CraftTimer = AccessTools.Field(typeof(InventoryGui), "m_craftTimer");

	private static readonly FieldInfo CraftDuration = AccessTools.Field(typeof(InventoryGui), "m_craftDuration");

	private static readonly FieldInfo CraftRecipe = AccessTools.Field(typeof(InventoryGui), "m_craftRecipe");

	private static readonly FieldInfo SelectedRecipeField = AccessTools.Field(typeof(InventoryGui), "m_selectedRecipe");

	private static readonly FieldInfo RecipeListRoot = AccessTools.Field(typeof(InventoryGui), "m_recipeListRoot");

	private static readonly List<RectTransform> visibleRows = new List<RectTransform>();

	private static InventoryGui owner;

	private static int direction;

	private static float repeatAt;

	private static bool focusing;

	private static float suppressAutomaticCancelUntil;

	private static readonly FieldInfo CraftButton = AccessTools.Field(typeof(InventoryGui), "m_craftButton");

	private static readonly FieldInfo CraftCancelButton = AccessTools.Field(typeof(InventoryGui), "m_craftCancelButton");

	private static readonly MethodInfo CraftPressed = AccessTools.Method(typeof(InventoryGui), "OnCraftPressed", (Type[])null, (Type[])null);

	private static readonly MethodInfo CraftCancelPressed = AccessTools.Method(typeof(InventoryGui), "OnCraftCancelPressed", (Type[])null, (Type[])null);

	private static string RecipeName(object value)
	{
		if (value == null)
		{
			return "null";
		}
		Recipe val = (Recipe)((value is Recipe) ? value : null);
		if ((Object)(object)val == (Object)null)
		{
			PropertyInfo propertyInfo = AccessTools.Property(value.GetType(), "Recipe");
			if (propertyInfo != null)
			{
				object? value2 = propertyInfo.GetValue(value, null);
				val = (Recipe)((value2 is Recipe) ? value2 : null);
			}
		}
		if (!Object.op_Implicit((Object)(object)val))
		{
			return value.GetType().Name;
		}
		if (Object.op_Implicit((Object)(object)val.m_item) && val.m_item.m_itemData != null && val.m_item.m_itemData.m_shared != null)
		{
			return val.m_item.m_itemData.m_shared.m_name;
		}
		return ((Object)val).name;
	}

	internal static string DebugState(InventoryGui gui)
	{
		if (!Object.op_Implicit((Object)(object)gui))
		{
			return "gui=null";
		}
		Button val = (Button)((CraftButton != null) ? /*isinst with value type is only supported in some contexts*/: null);
		Button val2 = (Button)((CraftCancelButton != null) ? /*isinst with value type is only supported in some contexts*/: null);
		object value = ((SelectedRecipeField != null) ? SelectedRecipeField.GetValue(gui) : null);
		object value2 = ((CraftRecipe != null) ? CraftRecipe.GetValue(gui) : null);
		object obj = ((CurrentlyHoldingCraft != null) ? CurrentlyHoldingCraft.GetValue(gui) : null);
		object obj2 = ((CraftTimer != null) ? CraftTimer.GetValue(gui) : null);
		object obj3 = ((CraftDuration != null) ? CraftDuration.GetValue(gui) : null);
		return "selected=" + RecipeName(value) + " craftRecipe=" + RecipeName(value2) + " holding=" + (obj ?? "?")?.ToString() + " timer=" + (obj2 ?? "?")?.ToString() + "/" + (obj3 ?? "?")?.ToString() + " craftActive=" + (Object.op_Implicit((Object)(object)val) && ((Component)val).gameObject.activeInHierarchy) + " craftInteractable=" + (Object.op_Implicit((Object)(object)val) && ((Selectable)val).interactable) + " cancelActive=" + (Object.op_Implicit((Object)(object)val2) && ((Component)val2).gameObject.activeInHierarchy) + " cancelInteractable=" + (Object.op_Implicit((Object)(object)val2) && ((Selectable)val2).interactable);
	}

	internal static void DebugLog(string message, InventoryGui gui)
	{
		CraftLog.LogInfo((object)("[CraftDiag] " + message + " | " + DebugState(gui)));
	}

	private static void HandleCraftButton(InventoryGui gui)
	{
		if (!Object.op_Implicit((Object)(object)gui) || !WheelInput.Down("JoyButtonX"))
		{
			return;
		}
		DebugLog("X DOWN", gui);
		if (((CraftTimer != null) ? ((float)CraftTimer.GetValue(gui)) : (-1f)) >= 0f)
		{
			Button val = (Button)((CraftCancelButton != null) ? /*isinst with value type is only supported in some contexts*/: null);
			if (Object.op_Implicit((Object)(object)val) && ((Component)val).gameObject.activeInHierarchy && ((Selectable)val).interactable && CraftCancelPressed != null)
			{
				DebugLog("calling OnCraftCancelPressed", gui);
				CraftCancelPressed.Invoke(gui, null);
				DebugLog("returned from OnCraftCancelPressed", gui);
			}
			else
			{
				DebugLog("X BLOCKED before OnCraftCancelPressed", gui);
			}
			return;
		}
		Button val2 = (Button)((CraftButton != null) ? /*isinst with value type is only supported in some contexts*/: null);
		if (Object.op_Implicit((Object)(object)val2) && ((Component)val2).gameObject.activeInHierarchy && ((Selectable)val2).interactable && CraftPressed != null)
		{
			DebugLog("calling OnCraftPressed", gui);
			suppressAutomaticCancelUntil = Time.unscaledTime + 0.12f;
			CraftPressed.Invoke(gui, null);
			DebugLog("returned from OnCraftPressed", gui);
		}
		else
		{
			DebugLog("X BLOCKED before OnCraftPressed", gui);
		}
	}

	internal static bool AllowCraftCancel(InventoryGui gui)
	{
		if (!InventoryPanels.Crafting)
		{
			return true;
		}
		return Time.unscaledTime >= suppressAutomaticCancelUntil;
	}

	private static bool BuildVisibleRows(InventoryGui gui)
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Expected O, but got Unknown
		visibleRows.Clear();
		if (!Object.op_Implicit((Object)(object)gui) || RecipeListRoot == null)
		{
			return false;
		}
		object? value = RecipeListRoot.GetValue(gui);
		RectTransform val = (RectTransform)((value is RectTransform) ? value : null);
		if (!Object.op_Implicit((Object)(object)val))
		{
			return false;
		}
		foreach (Transform item in (Transform)val)
		{
			object obj = (object)item;
			RectTransform val2 = (RectTransform)((obj is RectTransform) ? obj : null);
			if (Object.op_Implicit((Object)(object)val2) && ((Component)val2).gameObject.activeInHierarchy && Object.op_Implicit((Object)(object)((Transform)val2).Find("icon")))
			{
				visibleRows.Add(val2);
			}
		}
		return visibleRows.Count > 0;
	}

	private static Button RowButton(RectTransform row)
	{
		if (!Object.op_Implicit((Object)(object)row))
		{
			return null;
		}
		Button component = ((Component)row).GetComponent<Button>();
		if (Object.op_Implicit((Object)(object)component))
		{
			return component;
		}
		Button[] componentsInChildren = ((Component)row).GetComponentsInChildren<Button>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			if (Object.op_Implicit((Object)(object)componentsInChildren[i]) && ((Component)componentsInChildren[i]).gameObject.activeInHierarchy)
			{
				return componentsInChildren[i];
			}
		}
		if (componentsInChildren.Length == 0)
		{
			return null;
		}
		return componentsInChildren[0];
	}

	private static bool IsSelected(RectTransform row)
	{
		if (!Object.op_Implicit((Object)(object)row))
		{
			return false;
		}
		Transform val = ((Transform)row).Find("selected");
		if (Object.op_Implicit((Object)(object)val))
		{
			return ((Component)val).gameObject.activeSelf;
		}
		return false;
	}

	private static void ForceRowHighlight(RectTransform wanted)
	{
		for (int i = 0; i < visibleRows.Count; i++)
		{
			Transform val = (Object.op_Implicit((Object)(object)visibleRows[i]) ? ((Transform)visibleRows[i]).Find("selected") : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				((Component)val).gameObject.SetActive((Object)(object)visibleRows[i] == (Object)(object)wanted);
			}
		}
	}

	private static bool SelectRow(RectTransform row)
	{
		Button val = RowButton(row);
		if (!Object.op_Implicit((Object)(object)val))
		{
			return false;
		}
		((UnityEvent)val.onClick).Invoke();
		return true;
	}

	private static ScrollRect RecipeScroll(InventoryGui gui, out RectTransform root)
	{
		root = (RectTransform)((RecipeListRoot != null) ? /*isinst with value type is only supported in some contexts*/: null);
		if (!Object.op_Implicit((Object)(object)root))
		{
			return null;
		}
		return ((Component)root).GetComponentInParent<ScrollRect>();
	}

	private static void ScrollToTop(InventoryGui gui)
	{
		RectTransform root;
		ScrollRect val = RecipeScroll(gui, out root);
		if (Object.op_Implicit((Object)(object)val))
		{
			val.verticalNormalizedPosition = 1f;
		}
	}

	private static void KeepRowVisible(InventoryGui gui, RectTransform row)
	{
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: 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: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		RectTransform root;
		ScrollRect val = RecipeScroll(gui, out root);
		if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)root) || !Object.op_Implicit((Object)(object)row))
		{
			return;
		}
		RectTransform val2 = (RectTransform)(Object.op_Implicit((Object)(object)val.viewport) ? ((object)val.viewport) : ((object)/*isinst with value type is only supported in some contexts*/));
		if (!Object.op_Implicit((Object)(object)val2))
		{
			return;
		}
		Canvas.ForceUpdateCanvases();
		Bounds val3 = RectTransformUtility.CalculateRelativeRectTransformBounds((Transform)(object)val2, (Transform)(object)row);
		float num = 0f;
		float y = ((Bounds)(ref val3)).min.y;
		Rect rect = val2.rect;
		if (y < ((Rect)(ref rect)).yMin)
		{
			rect = val2.rect;
			num = ((Rect)(ref rect)).yMin - ((Bounds)(ref val3)).min.y;
		}
		else
		{
			float y2 = ((Bounds)(ref val3)).max.y;
			rect = val2.rect;
			if (y2 > ((Rect)(ref rect)).yMax)
			{
				rect = val2.rect;
				num = ((Rect)(ref rect)).yMax - ((Bounds)(ref val3)).max.y;
			}
		}
		if (!(Mathf.Abs(num) < 0.01f))
		{
			rect = root.rect;
			float height = ((Rect)(ref rect)).height;
			rect = val2.rect;
			float num2 = Mathf.Max(0f, height - ((Rect)(ref rect)).height);
			float num3 = Mathf.Clamp(root.anchoredPosition.y + num, 0f, num2);
			root.anchoredPosition = new Vector2(root.anchoredPosition.x, num3);
			val.velocity = Vector2.zero;
			if (num2 > 0.01f)
			{
				val.verticalNormalizedPosition = 1f - num3 / num2;
			}
			Canvas.ForceUpdateCanvases();
		}
	}

	internal static void FocusFirst(InventoryGui gui)
	{
		if (Object.op_Implicit((Object)(object)gui) && !focusing)
		{
			((MonoBehaviour)gui).StartCoroutine(FocusFirstAfterLayout(gui));
		}
	}

	private static IEnumerator FocusFirstAfterLayout(InventoryGui gui)
	{
		focusing = true;
		yield return null;
		if (!Object.op_Implicit((Object)(object)gui) || !InventoryPanels.Crafting)
		{
			focusing = false;
			yield break;
		}
		Canvas.ForceUpdateCanvases();
		owner = gui;
		direction = 0;
		repeatAt = 0f;
		if (BuildVisibleRows(gui))
		{
			ScrollToTop(gui);
			Canvas.ForceUpdateCanvases();
			RectTransform obj = visibleRows[0];
			SelectRow(obj);
			ForceRowHighlight(obj);
			ScrollToTop(gui);
		}
		focusing = false;
	}

	internal static void Update(InventoryGui gui)
	{
		bool flag = Object.op_Implicit((Object)(object)Player.m_localPlayer) && (Object)(object)Player.m_localPlayer.GetCurrentCraftingStation() != (Object)null;
		if (!InventoryPanels.Crafting || InventoryPanels.WorkstationPlayerFocus || (!InventoryPanels.CanSwitch(gui) && !flag))
		{
			direction = 0;
			owner = null;
			return;
		}
		if ((Object)(object)owner != (Object)(object)gui)
		{
			owner = gui;
			direction = 0;
		}
		if (CraftingCategories.HandleInput(gui))
		{
			direction = 0;
			return;
		}
		HandleCraftButton(gui);
		bool flag2 = WheelInput.Held("JoyLStickDown") || WheelInput.Held("JoyDPadDown");
		bool flag3 = WheelInput.Held("JoyLStickUp") || WheelInput.Held("JoyDPadUp");
		int num = ((flag2 != flag3) ? (flag2 ? 1 : (-1)) : 0);
		if (num == 0)
		{
			direction = 0;
			return;
		}
		bool flag4 = num != direction;
		if (!flag4 && Time.unscaledTime < repeatAt)
		{
			return;
		}
		direction = num;
		repeatAt = Time.unscaledTime + (flag4 ? 0.35f : 0.16f);
		if (!BuildVisibleRows(gui))
		{
			return;
		}
		int num2 = -1;
		for (int i = 0; i < visibleRows.Count; i++)
		{
			if (IsSelected(visibleRows[i]))
			{
				num2 = i;
				break;
			}
		}
		if (num2 < 0)
		{
			num2 = ((num > 0) ? (-1) : visibleRows.Count);
		}
		int num3 = Mathf.Clamp(num2 + num, 0, visibleRows.Count - 1);
		if (num3 != num2)
		{
			RectTransform val = visibleRows[num3];
			if (SelectRow(val))
			{
				ForceRowHighlight(val);
				KeepRowVisible(gui, val);
			}
		}
	}
}
[HarmonyPatch(typeof(InventoryGui), "UpdateRecipeGamepadInput")]
internal static class CraftingNavigationNativePatch
{
	[HarmonyPrefix]
	private static bool Prefix()
	{
		return !InventoryPanels.Crafting;
	}
}
[HarmonyPatch(typeof(InventoryGui), "OnCraftPressed")]
internal static class CraftingDiagnosticsPressedPatch
{
	[HarmonyPrefix]
	private static void Prefix(InventoryGui __instance)
	{
		CraftingNavigation.DebugLog("ENTER OnCraftPressed", __instance);
	}

	[HarmonyPostfix]
	private static void Postfix(InventoryGui __instance)
	{
		CraftingNavigation.DebugLog("EXIT OnCraftPressed", __instance);
	}
}
[HarmonyPatch(typeof(InventoryGui), "OnCraftCancelPressed")]
internal static class CraftingDiagnosticsCancelPatch
{
	[HarmonyPrefix]
	[HarmonyPriority(800)]
	private static bool Prefix(InventoryGui __instance, out bool __state)
	{
		__state = CraftingNavigation.AllowCraftCancel(__instance);
		if (!__state)
		{
			CraftingNavigation.DebugLog("BLOCKED duplicate automatic OnCraftCancelPressed", __instance);
			return false;
		}
		CraftingNavigation.DebugLog("ENTER OnCraftCancelPressed", __instance);
		return true;
	}

	[HarmonyPostfix]
	private static void Postfix(InventoryGui __instance, bool __state)
	{
		if (__state)
		{
			CraftingNavigation.DebugLog("EXIT OnCraftCancelPressed", __instance);
		}
	}
}
[HarmonyPatch(typeof(InventoryGui), "UpdateCraftingPanel")]
internal static class CraftingDiagnosticsPanelPatch
{
	private static string previous;

	[HarmonyPostfix]
	private static void Postfix(InventoryGui __instance)
	{
		if (!InventoryPanels.Crafting)
		{
			previous = null;
			return;
		}
		string text = CraftingNavigation.DebugState(__instance);
		if (!(text == previous))
		{
			previous = text;
			CraftingNavigation.DebugLog("UpdateCraftingPanel state changed", __instance);
		}
	}
}
internal static class WheelSkin
{
	private static readonly FieldInfo Elements = AccessTools.Field(typeof(RadialBase), "m_elements");

	private static readonly Dictionary<RadialMenuElement, Image> skins = new Dictionary<RadialMenuElement, Image>();

	private static readonly Dictionary<RadialMenuElement, Component> numbers = new Dictionary<RadialMenuElement, Component>();

	private static readonly Dictionary<long, Sprite> sprites = new Dictionary<long, Sprite>();

	private static readonly FieldInfo ItemData = AccessTools.Field(typeof(ItemElement), "m_data");

	private static MethodInfo loadImage;

	private static int warmKind;

	private static int warmFrame = -1;

	private static Color32[] wood;

	private static int woodWidth;

	private static int woodHeight;

	internal static float OuterRadius => (Object.op_Implicit((Object)(object)RadialData.SO) ? RadialData.SO.ElementsDistance : 240f) + 85f;

	internal static void WarmOne()
	{
		if (Object.op_Implicit((Object)(object)RadialData.SO) && !(Mathf.Abs(OuterRadius - 405f) > 0.01f) && warmKind < 10 && warmFrame != Time.frameCount)
		{
			warmFrame = Time.frameCount;
			Sprite(warmKind++);
		}
	}

	private static Sprite Baked(int kind, float outer)
	{
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Expected O, but got Unknown
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		if (kind != 8 && Mathf.Abs(outer - 405f) > 0.01f)
		{
			return null;
		}
		using Stream stream = typeof(WheelSkin).Assembly.GetManifestResourceStream("ControllerForge.WheelTextures." + kind + ".png");
		if (stream == null)
		{
			return null;
		}
		long start = WheelPerformance.Start();
		if (loadImage == null)
		{
			loadImage = AccessTools.Method(AccessTools.TypeByName("UnityEngine.ImageConversion"), "LoadImage", new Type[3]
			{
				typeof(Texture2D),
				typeof(byte[]),
				typeof(bool)
			}, (Type[])null);
		}
		if (loadImage == null)
		{
			return null;
		}
		using MemoryStream memoryStream = new MemoryStream();
		stream.CopyTo(memoryStream);
		Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
		((Texture)val).wrapMode = (TextureWrapMode)1;
		if (!(bool)loadImage.Invoke(null, new object[3]
		{
			val,
			memoryStream.ToArray(),
			true
		}))
		{
			Object.Destroy((Object)(object)val);
			return null;
		}
		Sprite result = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
		WheelPerformance.Write("Load baked wheel texture " + kind + ": " + WheelPerformance.Ms(WheelPerformance.Milliseconds(start)) + ".");
		return result;
	}

	internal static int Number(Vector2 position)
	{
		//IL_0000: 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)
		return Mathf.RoundToInt(Mathf.Repeat(Mathf.Atan2(position.x, position.y) * 57.29578f, 360f) / 45f) % 8 + 1;
	}

	internal static bool ArrowContains(float x, float down, float outer)
	{
		float num = outer + 24f;
		if (x <= num && down <= num && x >= 0.48f * num && down >= 0.48f * num)
		{
			return x * x + down * down >= (outer + 13f) * (outer + 13f);
		}
		return false;
	}

	private static Color Wood(float u, float v)
	{
		//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_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		if (wood == null)
		{
			long start = WheelPerformance.Start();
			Texture2D texture = DualInventory.Frame().texture;
			woodWidth = ((Texture)texture).width;
			woodHeight = ((Texture)texture).height;
			wood = texture.GetPixels32();
			WheelPerformance.Write("Inventory wood load/read " + WheelPerformance.Ms(WheelPerformance.Milliseconds(start)) + " (" + woodWidth + "x" + woodHeight + ").");
		}
		int num = Mathf.Clamp((int)((0.1f + 0.8f * u) * (float)woodWidth), 0, woodWidth - 1);
		int num2 = Mathf.Clamp((int)((0.1f + 0.8f * v) * (float)woodHeight), 0, woodHeight - 1);
		Color result = Color32.op_Implicit(wood[num2 * woodWidth + num]);
		result.a = 1f;
		return result;
	}

	private static Color Surface(float distance, float u, float v)
	{
		//IL_0008: 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)
		//IL_00c4: 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_005f: 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_0085: 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_0033: Unknown result type (might be due to invalid IL or missing references)
		if (distance < 0f)
		{
			return Color.clear;
		}
		Color result = (Color)((distance < 1f) ? new Color(0.22f, 0.12f, 0.045f) : ((distance < 2.2f) ? new Color(0.91f, 0.74f, 0.45f) : ((distance < 4.5f) ? Color.Lerp(new Color(0.68f, 0.45f, 0.19f), new Color(0.38f, 0.24f, 0.1f), (distance - 2.2f) / 2.3f) : ((distance < 5.5f) ? new Color(0.1f, 0.065f, 0.035f) : Wood(u, v)))));
		result.a = Mathf.Clamp01(distance);
		return result;
	}

	internal static Sprite Sprite(int kind)
	{
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Expected O, but got Unknown
		//IL_0268: Unknown result type (might be due to invalid IL or missing references)
		//IL_0277: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: 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_0210: Unknown result type (might be due to invalid IL or missing references)
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0204: Unknown result type (might be due to invalid IL or missing references)
		float outerRadius = OuterRadius;
		long key = ((long)Mathf.RoundToInt(outerRadius * 100f) << 4) | (uint)kind;
		if (sprites.TryGetValue(key, out var value))
		{
			return value;
		}
		value = Baked(kind, outerRadius);
		if (Object.op_Implicit((Object)(object)value))
		{
			sprites[key] = value;
			return value;
		}
		long start = WheelPerformance.Start();
		int num = ((kind == 8) ? 384 : 640);
		float num2 = kind switch
		{
			9 => outerRadius + 24f, 
			8 => 320f, 
			_ => outerRadius * 2f, 
		};
		float num3 = num2 / (float)num;
		Texture2D val = new Texture2D(num, num, (TextureFormat)4, false);
		((Texture)val).wrapMode = (TextureWrapMode)1;
		Color[] array = (Color[])(object)new Color[num * num];
		List<Vector2> nails = Nails(kind, outerRadius);
		for (int i = 0; i < num; i++)
		{
			for (int j = 0; j < num; j++)
			{
				float num4 = ((float)j + 0.5f) * num3;
				float num5 = ((float)i + 0.5f) * num3;
				float num11;
				switch (kind)
				{
				case 8:
					num11 = 159f - Vector2.Distance(new Vector2(num4, num5), new Vector2(160f, 160f));
					break;
				case 9:
				{
					float num12 = num2 - num5;
					num11 = Mathf.Min(Mathf.Min(num2 - num4, num2 - num12), Mathf.Min(Mathf.Min(num4 - 0.48f * num2, num12 - 0.48f * num2), Mathf.Sqrt(num4 * num4 + num12 * num12) - outerRadius - 13f));
					break;
				}
				default:
				{
					float num6 = num4 - outerRadius;
					float num7 = num5 - outerRadius;
					float num8 = Mathf.Sqrt(num6 * num6 + num7 * num7);
					float num9 = Mathf.Atan2(num6, num7) * 57.29578f;
					float num10 = Mathf.Abs(Mathf.DeltaAngle((float)kind * 45f, num9));
					num11 = Mathf.Min(Mathf.Min(num8 - 169f, outerRadius - num8), num8 * Mathf.Sin((21.3f - num10) * (MathF.PI / 180f)));
					break;
				}
				}
				Color val2 = Surface(num11, (float)j / (float)num, (float)i / (float)num);
				if (num11 >= 0f)
				{
					val2 = NailColor(num4, num5, nails, val2);
				}
				array[i * num + j] = val2;
			}
		}
		double value2 = WheelPerformance.Milliseconds(start);
		long start2 = WheelPerformance.Start();
		val.SetPixels(array);
		val.Apply(false, true);
		value = Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num), new Vector2(0.5f, 0.5f), 100f);
		sprites[key] = value;
		string text = kind switch
		{
			9 => "arrow panel", 
			8 => "tool center", 
			_ => "weapon sector " + (kind + 1), 
		};
		WheelPerformance.Write("Generate " + text + " " + num + "x" + num + ", radius " + outerRadius + ": raster " + WheelPerformance.Ms(value2) + ", upload/sprite " + WheelPerformance.Ms(WheelPerformance.Milliseconds(start2)) + ", total " + WheelPerformance.Ms(WheelPerformance.Milliseconds(start)) + ".");
		return value;
	}

	private static List<Vector2> Nails(int kind, float outer)
	{
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: 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_00e4: 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)
		List<Vector2> list = new List<Vector2>();
		if (kind < 8)
		{
			float[] array = new float[2]
			{
				183f,
				outer - 14f
			};
			foreach (float num in array)
			{
				float[] array2 = new float[2] { -16f, 16f };
				foreach (float num2 in array2)
				{
					float num3 = ((float)kind * 45f + num2) * (MathF.PI / 180f);
					list.Add(new Vector2(outer + Mathf.Sin(num3) * num, outer + Mathf.Cos(num3) * num));
				}
			}
		}
		else if (kind == 8)
		{
			for (int k = 0; k < 8; k++)
			{
				float num4 = (float)k * 45f * (MathF.PI / 180f);
				list.Add(new Vector2(160f + Mathf.Sin(num4) * 150f, 160f + Mathf.Cos(num4) * 150f));
			}
		}
		else
		{
			float num5 = outer + 24f;
			list.Add(new Vector2(num5 - 10f, 10f));
			list.Add(new Vector2(0.48f * num5 + 10f, 10f));
			list.Add(new Vector2(num5 - 10f, 0.52f * num5 - 10f));
		}
		return list;
	}

	private static Color NailColor(float x, float y, List<Vector2> nails, Color baseColor)
	{
		//IL_000e: 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)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: 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_0108: 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)
		foreach (Vector2 nail in nails)
		{
			float num = x - nail.x;
			float num2 = y - nail.y;
			float num3 = num * num + num2 * num2;
			if (!(num3 > 36f))
			{
				float num4 = Mathf.Sqrt(num3);
				if (num4 > 4.4f)
				{
					return Color.Lerp(baseColor, new Color(0.035f, 0.025f, 0.016f), 0.65f * (6f - num4) / 1.6f);
				}
				float num5 = Mathf.Clamp01(0.52f + (num2 - num) / 10f);
				return (Color)((num4 > 3.5f) ? new Color(0.15f, 0.11f, 0.065f) : Color.Lerp(new Color(0.28f, 0.23f, 0.16f), new Color(0.82f, 0.76f, 0.61f), num5));
			}
		}
		return baseColor;
	}

	internal static void Arrange(RadialBase radial, List<RadialMenuElement> elements)
	{
		if (!DirectWeaponsPatch.IsWeapons(radial) || !Object.op_Implicit((Object)(object)RadialData.SO.EmptyElement))
		{
			return;
		}
		radial.StartOffset = 0;
		if (!DualInventory.Enabled)
		{
			while (elements.Count < 8)
			{
				elements.Add((RadialMenuElement)(object)Object.Instantiate<EmptyElement>(RadialData.SO.EmptyElement));
			}
			return;
		}
		Dictionary<ItemData, RadialMenuElement> dictionary = new Dictionary<ItemData, RadialMenuElement>();
		foreach (RadialMenuElement element in elements)
		{
			ItemElement val = (ItemElement)(object)((element is ItemElement) ? element : null);
			ItemData val2 = (ItemData)(Object.op_Implicit((Object)(object)val) ? /*isinst with value type is only supported in some contexts*/: null);
			if (val2 != null)
			{
				dictionary[val2] = element;
			}
		}
		List<ItemData> list = DualInventory.WeaponSlots();
		elements.Clear();
		foreach (ItemData item in list)
		{
			elements.Add((RadialMenuElement)((item != null && dictionary.TryGetValue(item, out var value)) ? ((object)value) : ((object)Object.Instantiate<EmptyElement>(RadialData.SO.EmptyElement))));
		}
	}

	internal static void Apply(RadialBase radial)
	{
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: 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_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		//IL_0173: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: 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_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0289: Unknown result type (might be due to invalid IL or missing references)
		//IL_028e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0290: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Unknown result type (might be due to invalid IL or missing references)
		//IL_021d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0235: Unknown result type (might be due to invalid IL or missing references)
		//IL_0251: Unknown result type (might be due to invalid IL or missing references)
		//IL_026a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0372: Unknown result type (might be due to invalid IL or missing references)
		//IL_0357: Unknown result type (might be due to invalid IL or missing references)
		//IL_0308: Unknown result type (might be due to invalid IL or missing references)
		//IL_030f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0327: Unknown result type (might be due to invalid IL or missing references)
		bool flag = DirectWeaponsPatch.IsWeapons(radial);
		if ((!flag && !FoodWheel.IsFood(radial)) || !(Elements.GetValue(radial) is RadialArray<RadialMenuElement> val))
		{
			return;
		}
		if (skins.Count > 24)
		{
			List<RadialMenuElement> list = new List<RadialMenuElement>();
			foreach (KeyValuePair<RadialMenuElement, Image> skin in skins)
			{
				if (!Object.op_Implicit((Object)(object)skin.Key) || !Object.op_Implicit((Object)(object)skin.Value))
				{
					list.Add(skin.Key);
				}
			}
			foreach (RadialMenuElement item in list)
			{
				skins.Remove(item);
				numbers.Remove(item);
			}
		}
		Vector2 val5 = default(Vector2);
		for (int i = 0; i < val.Count; i++)
		{
			RadialMenuElement element = val.GetElement(i);
			if (!Object.op_Implicit((Object)(object)element))
			{
				continue;
			}
			Vector2 val2 = Vector2.op_Implicit(element.LocalPosition);
			int num = Number(val2);
			if (!skins.TryGetValue(element, out var value) || !Object.op_Implicit((Object)(object)value))
			{
				GameObject val3 = new GameObject("ControllerWoodWedge", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				RectTransform val4 = (RectTransform)val3.transform;
				((Transform)val4).SetParent(((Component)element).transform, false);
				((Vector2)(ref val5))..ctor(0.5f, 0.5f);
				val4.pivot = val5;
				Vector2 anchorMin = (val4.anchorMax = val5);
				val4.anchorMin = anchorMin;
				val4.sizeDelta = Vector2.one * (2f * OuterRadius);
				val4.anchoredPosition = -val2;
				((Transform)val4).SetAsFirstSibling();
				value = val3.GetComponent<Image>();
				value.sprite = Sprite(num - 1);
				((Graphic)value).raycastTarget = false;
				skins[element] = value;
				if (flag)
				{
					Component val7 = ReservedGearHud.Label(((Component)element).transform, radial, num.ToString(), new Vector2(36f, 32f), ((Vector2)(ref val2)).normalized * (OuterRadius - ((Vector2)(ref val2)).magnitude - 20f), 22f);
					if (val7 is Graphic)
					{
						((Graphic)val7).color = new Color(0.62f, 0.83f, 1f, 1f);
					}
					numbers[element] = val7;
				}
			}
			((RectTransform)((Component)value).transform).anchoredPosition = -val2;
			Sprite val8 = Sprite(num - 1);
			if ((Object)(object)value.sprite != (Object)(object)val8)
			{
				value.sprite = val8;
			}
			if (numbers.TryGetValue(element, out var value2) && Object.op_Implicit((Object)(object)value2))
			{
				if (value2.gameObject.activeSelf != flag)
				{
					value2.gameObject.SetActive(flag);
				}
				ReservedGearHud.SetText(value2, num.ToString());
				((RectTransform)value2.transform).anchoredPosition = ((Vector2)(ref val2)).normalized * (OuterRadius - ((Vector2)(ref val2)).magnitude - 20f);
			}
			if (Object.op_Implicit((Object)(object)element.Background))
			{
				((Behaviour)element.Background).enabled = false;
			}
			((Graphic)value).color = (Color)(element.Selected ? new Color(1f, 0.86f, 0.6f, 1f) : Color.white);
		}
	}
}
[HarmonyPatch(typeof(RadialBase), "SetRadialLayout")]
internal static class WeaponWheelNorthOrderPatch
{
	[HarmonyPrefix]
	private static void Prefix(RadialBase __instance)
	{
		if (DirectWeaponsPatch.IsWeapons(__instance))
		{
			__instance.StartOffset = 0;
		}
	}
}
internal static class CraftingSkin
{
	[CompilerGenerated]
	private static class <>O
	{
		public static WillRenderCanvases <0>__KeepWorkbenchHidden;

		public static WillRenderCanvases <1>__RepositionWorkbench;
	}

	private static readonly Dictionary<string, FieldInfo> fields = new Dictionary<string, FieldInfo>();

	private static readonly Type TextType = AccessTools.TypeByName("TMPro.TMP_Text");

	private static readonly PropertyInfo Font = AccessTools.Property(TextType, "fontSize");

	private static readonly PropertyInfo Text = AccessTools.Property(TextType, "text");

	private static readonly PropertyInfo Alignment = AccessTools.Property(TextType, "alignment");

	private static readonly PropertyInfo Wrapping = AccessTools.Property(TextType, "enableWordWrapping");

	private static readonly PropertyInfo AutoSize = AccessTools.Property(TextType, "enableAutoSizing");

	private static readonly PropertyInfo SelectedRecipe = AccessTools.Property(AccessTools.Field(typeof(InventoryGui), "m_selectedRecipe").FieldType, "Recipe");

	private static readonly Type LocalizationType = AccessTools.TypeByName("Localization");

	private static readonly PropertyInfo LocalizationInstance = AccessTools.Property(LocalizationType, "instance");

	private static readonly MethodInfo Localize = AccessTools.Method(LocalizationType, "Localize", new Type[1] { typeof(string) }, (Type[])null);

	private static Recipe descriptionRecipe;

	private static string shortDescription;

	private static string fullRecipeInfo;

	private static InventoryGui owner;

	private static RectTransform root;

	private static RectTransform detail;

	private static Component craftingHeading;

	private static RectTransform categoryStrip;

	private static Component emptyCategory;

	private static readonly Dictionary<CraftingCategory, Button> categoryButtons = new Dictionary<CraftingCategory, Button>();

	private static Sprite nail;

	private static Sprite materialFrame;

	private const float WorkbenchCraftingScale = 0.665f;

	private const float WorkbenchCraftingWidthScale = 0.75f;

	private const float WorkbenchVerticalGapPixels = 16f;

	private const float WorkbenchHorizontalOffsetPixels = 0f;

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

	private static Vector2 normalPlayerPosition;

	private static Vector2 normalCraftingPosition;

	private static Vector3 normalCraftingScale;

	private static bool savedWorkbenchTransforms;

	private static bool workbenchSubscribed;

	private static InventoryGui workbenchGui;

	private static RectTransform workbenchPlayer;

	private static RectTransform workbenchCrafting;

	private static RectTransform workbenchStorageReference;

	private static RectTransform workbenchViewport;

	private static Canvas workbenchCanvas;

	private static bool workbenchLayoutLogged;

	private static CanvasGroup closingWorkbenchPlayer;

	private static CanvasGroup closingWorkbenchCrafting;

	private static float closingWorkbenchPlayerAlpha;

	private static float closingWorkbenchCraftingAlpha;

	private static bool hidingWorkbench;

	private static readonly List<Graphic> hiddenGraphics = new List<Graphic>();

	private static readonly List<Image> materialBackdrops = new List<Image>();

	private static readonly HashSet<GameObject> styledRows = new HashSet<GameObject>();

	private static bool warned;

	private static CanvasGroup WorkbenchFadeGroup(RectTransform panel)
	{
		if (!Object.op_Implicit((Object)(object)panel))
		{
			return null;
		}
		CanvasGroup component = ((Component)panel).GetComponent<CanvasGroup>();
		if (!Object.op_Implicit((Object)(object)component))
		{
			return ((Component)panel).gameObject.AddComponent<CanvasGroup>();
		}
		return component;
	}

	private static void KeepWorkbenchHidden()
	{
		if (Object.op_Implicit((Object)(object)closingWorkbenchPlayer))
		{
			closingWorkbenchPlayer.alpha = 0f;
		}
		if (Object.op_Implicit((Object)(object)closingWorkbenchCrafting))
		{
			closingWorkbenchCrafting.alpha = 0f;
		}
	}

	internal static void HideImmediately(InventoryGui gui)
	{
		//IL_00a3: 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_00ae: Expected O, but got Unknown
		if (!hidingWorkbench)
		{
			object obj = Get(gui, "m_player");
			RectTransform panel = (RectTransform)((obj is RectTransform) ? obj : null);
			object obj2 = Get(gui, "m_crafting");
			object panel2 = ((obj2 is RectTransform) ? obj2 : null);
			closingWorkbenchPlayer = WorkbenchFadeGroup(panel);
			closingWorkbenchCrafting = WorkbenchFadeGroup((RectTransform)panel2);
			closingWorkbenchPlayerAlpha = (Object.op_Implicit((Object)(object)closingWorkbenchPlayer) ? closingWorkbenchPlayer.alpha : 1f);
			closingWorkbenchCraftingAlpha = (Object.op_Implicit((Object)(object)closingWorkbenchCrafting) ? closingWorkbenchCrafting.alpha : 1f);
			hidingWorkbench = true;
			KeepWorkbenchHidden();
			RestorePosition(gui);
			object obj3 = <>O.<0>__KeepWorkbenchHidden;
			if (obj3 == null)
			{
				WillRenderCanvases val = KeepWorkbenchHidden;
				<>O.<0>__KeepWorkbenchHidden = val;
				obj3 = (object)val;
			}
			Canvas.preWillRenderCanvases += (WillRenderCanvases)obj3;
		}
	}

	internal static void ShowAgain()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Expected O, but got Unknown
		if (hidingWorkbench)
		{
			object obj = <>O.<0>__KeepWorkbenchHidden;
			if (obj == null)
			{
				WillRenderCanvases val = KeepWorkbenchHidden;
				<>O.<0>__KeepWorkbenchHidden = val;
				obj = (object)val;
			}
			Canvas.preWillRenderCanvases -= (WillRenderCanvases)obj;
			if (Object.op_Implicit((Object)(object)closingWorkbenchPlayer))
			{
				closingWorkbenchPlayer.alpha = closingWorkbenchPlayerAlpha;
			}
			if (Object.op_Implicit((Object)(object)closingWorkbenchCrafting))
			{
				closingWorkbenchCrafting.alpha = closingWorkbenchCraftingAlpha;
			}
			closingWorkbenchPlayer = null;
			closingWorkbenchCrafting = null;
			hidingWorkbench = false;
		}
	}

	private static Sprite MaterialFrame()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Expected O, but got Unknown
		//IL_0150: 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_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: 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)
		//IL_00bc: 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_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_00c1: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)materialFrame))
		{
			return materialFrame;
		}
		Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
		((Object)val).name = "ControllerCraftMaterialFrame";
		((Texture)val).wrapMode = (TextureWrapMode)1;
		Color[] array = (Color[])(object)new Color[4096];
		Color val2 = default(Color);
		for (int i = 0; i < 64; i++)
		{
			for (int j = 0; j < 64; j++)
			{
				int num = Math.Min(Math.Min(j, i), Math.Min(63 - j, 63 - i));
				bool flag = i >= 60 || j < 4;
				switch (num)
				{
				case 0:
					((Color)(ref val2))..ctor(0.1f, 0.075f, 0.045f);
					break;
				case 1:
					val2 = (flag ? new Color(0.64f, 0.48f, 0.26f) : new Color(0.32f, 0.22f, 0.11f));
					break;
				case 2:
					((Color)(ref val2))..ctor(0.43f, 0.31f, 0.16f);
					break;
				case 3:
					((Color)(ref val2))..ctor(0.12f, 0.085f, 0.045f);
					break;
				default:
					val2 = Color.clear;
					break;
				}
				array[i * 64 + j] = val2;
			}
		}
		val.SetPixels(array);
		val.Apply(false, true);
		materialFrame = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4(4f, 4f, 4f, 4f));
		return materialFrame;
	}

	private static void Divider(Transform parent, float y, bool ornament)
	{
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: 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_0052: 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_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		Color color = default(Color);
		((Color)(ref color))..ctor(0.65f, 0.48f, 0.25f);
		if (ornament)
		{
			float[] array = new float[2] { 24f, 287f };
			foreach (float num in array)
			{
				Image obj = ((Component)Box(parent, "ControllerCraftDivider", new Vector2(239f, 2f), new Vector2(num, y), wood: false)).gameObject.AddComponent<Image>();
				((Graphic)obj).color = color;
				((Graphic)obj).raycastTarget = false;
			}
			RectTransform obj2 = Box(parent, "ControllerCraftDividerMark", new Vector2(8f, 8f), new Vector2(270f, y + 3f), wood: false);
			((Transform)obj2).localRotation = Quaternion.Euler(0f, 0f, 45f);
			Image obj3 = ((Component)obj2).gameObject.AddComponent<Image>();
			((Graphic)obj3).color = color;
			((Graphic)obj3).raycastTarget = false;
		}
		else
		{
			Image obj4 = ((Component)Box(parent, "ControllerCraftDivider", new Vector2(502f, 2f), new Vector2(24f, y), wood: false)).gameObject.AddComponent<Image>();
			((Graphic)obj4).color = color;
			((Graphic)obj4).raycastTarget = false;
		}
	}

	private static void ShortDescription(InventoryGui gui)
	{
		object obj = Get(gui, "m_selectedRecipe");
		Recipe val = (Recipe)((obj == null) ? null : /*isinst with value type is only supported in some contexts*/);
		object obj2 = Get(gui, "m_recipeDecription");
		Component val2 = (Component)((obj2 is Component) ? obj2 : null);
		if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.m_item) || !Object.op_Implicit((Object)(object)val2))
		{
			ItemInfoLayout.ClearCraftingInfo();
			return;
		}
		Component component = val2.GetComponent(TextType);
		if (!Object.op_Implicit((Object)(object)component))
		{
			ItemInfoLayout.ClearCraftingInfo();
			return;
		}
		string text = Text.GetValue(component, null) as string;
		if ((Object)(object)descriptionRecipe != (Object)(object)val)
		{
			descriptionRecipe = val;
			fullRecipeInfo = null;
			shortDescription = (string)Localize.Invoke(LocalizationInstance.GetValue(null, null), new object[1] { val.m_item.m_itemData.m_shared.m_description });
		}
		if (!string.IsNullOrEmpty(text) && !string.Equals(text, shortDescription, StringComparison.Ordinal))
		{
			fullRecipeInfo = text;
		}
		ItemInfoLayout.SetCraftingInfo(val2, fullRecipeInfo);
		Graphic val3 = (Graphic)(object)((component is Graphic) ? component : null);
		if (Object.op_Implicit((Object)(object)val3))
		{
			((Behaviour)val3).enabled = false;
		}
	}

	private static object Get(InventoryGui gui, string name)
	{
		if (!fields.TryGetValue(name, out var value))
		{
			value = AccessTools.Field(typeof(InventoryGui), name);
			fields[name] = value;
		}
		if (!(value == null))
		{
			return value.GetValue(gui);
		}
		return null;
	}

	private static RectTransform Box(Transform parent, string name, Vector2 size, Vector2 point, bool wood)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Expected O, but got Unknown
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Expected O, but got Unknown
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
		RectTransform val2 = (RectTransform)val.transform;
		Place(val2, parent, size, point);
		if (wood)
		{
			Image obj = val.AddComponent<Image>();
			obj.sprite = DualInventory.Frame();
			obj.type = (Type)1;
			((Graphic)obj).raycastTarget = false;
			Pins(val2, size);
		}
		return val2;
	}

	private static void Place(RectTransform rect, Transform parent, Vector2 size, Vector2 point)
	{
		//IL_0029: 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_0040: 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_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)((Transform)rect).parent != (Object)(object)parent)
		{
			((Transform)rect).SetParent(parent, false);
		}
		Vector2 val = default(Vector2);
		((Vector2)(ref val))..ctor(0f, 1f);
		rect.anchorMax = val;
		rect.anchorMin = val;
		rect.pivot = new Vector2(0f, 1f);
		rect.sizeDelta = size;
		rect.anchoredPosition = point;
		((Transform)rect).localScale = Vector3.one;
	}

	private static void Pins(RectTransform parent, Vector2 size)
	{
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: 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_01a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Expected O, but got Unknown
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: 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_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)nail))
		{
			Texture2D val = new Texture2D(16, 16, (TextureFormat)4, false);
			Color[] array = (Color[])(object)new Color[256];
			for (int i = 0; i < 16; i++)
			{
				for (int j = 0; j < 16; j++)
				{
					float num = (float)j - 7.5f;
					float num2 = (float)i - 7.5f;
					float num3 = Mathf.Sqrt(num * num + num2 * num2);
					array[i * 16 + j] = (Color)((num3 > 7f) ? Color.clear : ((num3 > 5.8f) ? new Color(0.11f, 0.09f, 0.06f) : Color.Lerp(new Color(0.23f, 0.2f, 0.16f), new Color(0.77f, 0.73f, 0.64f), Mathf.Clamp01(0.5f + (num2 - num) / 18f))));
				}
			}
			val.SetPixels(array);
			val.Apply(false, true);
			nail = Sprite.Create(val, new Rect(0f, 0f, 16f, 16f), new Vector2(0.5f, 0.5f));
		}
		Vector2[] array2 = (Vector2[])(object)new Vector2[4]
		{
			new Vector2(8f, -8f),
			new Vector2(size.x - 20f, -8f),
			new Vector2(8f, 0f - size.y + 20f),
			new Vector2(size.x - 20f, 0f - size.y + 20f)
		};
		foreach (Vector2 point in array2)
		{
			Image obj = ((Component)Box((Transform)(object)parent, "ControllerCraftNail", new Vector2(12f, 12f), point, wood: false)).gameObject.AddComponent<Image>();
			obj.sprite = nail;
			((Graphic)obj).raycastTarget = false;
		}
	}

	private static void FontSize(Component label, float size, bool wrap)
	{
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)label))
		{
			return;
		}
		Component component = label.GetComponent(TextType);
		if (Object.op_Implicit((Object)(object)component))
		{
			Font.SetValue(component, size, null);
			if (AutoSize != null)
			{
				AutoSize.SetValue(component, false, null);
			}
			if (Wrapping != null)
			{
				Wrapping.SetValue(component, wrap, null);
			}
			Graphic val = (Graphic)(object)((component is Graphic) ? component : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				((Behaviour)val).enabled = true;
				val.color = new Color(0.94f, 0.88f, 0.72f);
			}
		}
	}

	private static Component Label(InventoryGui gui, Transform parent, string value, Vector2 size, Vector2 point, float font)
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Expected O, but got Unknown
		object obj = Get(gui, "m_recipeName");
		Component val = (Component)((obj is Component) ? obj : null);
		if (!Object.op_Implicit((Object)(object)val))
		{
			return null;
		}
		GameObject obj2 = Object.Instantiate<GameObject>(val.gameObject, parent, false);
		((Object)obj2).name = "ControllerCraftLabel";
		obj2.SetActive(true);
		Place((RectTransform)obj2.transform, parent, size, point);
		Component component = obj2.GetComponent(TextType);
		Text.SetValue(component, value, null);
		Alignment.SetValue(component, Enum.Parse(Alignment.PropertyType, "Center"), null);
		FontSize(component, font, wrap: false);
		Graphic[] componentsInChildren = obj2.GetComponentsInChildren<Graphic>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			componentsInChildren[i].raycastTarget = false;
		}
		return component;
	}

	private static void Move(InventoryGui gui, string name, Transform parent, Vector2 size, Vector2 point, float font = 0f)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Expected O, but got Unknown
		object obj = Get(gui, name);
		Component val = (Component)((obj is Component) ? obj : null);
		if (Object.op_Implicit((Object)(object)val))
		{
			Place((RectTransform)val.transform, parent, size, point);
			if (font > 0f)
			{
				FontSize(val, font, wrap: true);
			}
		}
	}

	private static void BuildCategoryTabs(InventoryGui gui)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Expected O, but got Unknown
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		categoryButtons.Clear();
		categoryStrip = Box((Transform)(object)root, "ControllerForgeCategories", new Vector2(876f, 36f), new Vector2(12f, -86f), wood: false);
		foreach (CraftingCategory value in Enum.GetValues(typeof(CraftingCategory)))
		{
			RectTransform val = Box((Transform)(object)categoryStrip, "ControllerForgeCategory" + value, new Vector2(210f, 36f), Vector2.zero, wood: true);
			Image component = ((Component)val).GetComponent<Image>();
			((Graphic)component).raycastTarget = true;
			Button val2 = ((Component)val).gameObject.AddComponent<Button>();
			((Selectable)val2).targetGraphic = (Graphic)(object)component;
			((Selectable)val2).transition = (Transition)0;
			Navigation navigation = default(Navigation);
			((Navigation)(ref navigation)).mode = (Mode)0;
			((Selectable)val2).navigation = navigation;
			CraftingCategory captured = value;
			((UnityEvent)val2.onClick).AddListener((UnityAction)delegate
			{
				CraftingCategories.Select(gui, captured);
			});
			Label(gui, (Transform)(object)val, value.ToString(), new Vector2(186f, 32f), new Vector2(12f, -2f), 24f);
			categoryButtons.Add(value, val2);
		}
	}

	private static void UpdateCategoryTabs(InventoryGui gui)
	{
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Expected O, but got Unknown
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: 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_0100: Expected O, but got Unknown
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Expected O, but got Unknown
		//IL_01e6: 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_013a: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)categoryStrip))
		{
			return;
		}
		((Component)categoryStrip).gameObject.SetActive(CraftingCategories.TabsVisible);
		int num = (CraftingCategories.ShowAll ? 4 : 3);
		float num2 = (876f - (float)(num - 1) * 8f) / (float)num;
		int num3 = 0;
		bool flag = CraftingCategories.Busy(gui);
		foreach (CraftingCategory value in Enum.GetValues(typeof(CraftingCategory)))
		{
			Button val = categoryButtons[value];
			bool flag2 = value != CraftingCategory.All || CraftingCategories.ShowAll;
			((Component)val).gameObject.SetActive(flag2);
			if (!flag2)
			{
				continue;
			}
			RectTransform val2 = (RectTransform)((Component)val).transform;
			Place(val2, (Transform)(object)categoryStrip, new Vector2(num2, 36f), new Vector2((float)num3++ * (num2 + 8f), 0f));
			int num4 = 0;
			foreach (Transform item in (Transform)val2)
			{
				Transform val3 = item;
				if (((Object)val3).name == "ControllerCraftNail")
				{
					((RectTransform)val3).anchoredPosition = new Vector2((num4 % 2 == 0) ? 8f : (num2 - 20f), (float)((num4 < 2) ? (-8) : (-16)));
					num4++;
				}
				else if (((Object)val3).name == "ControllerCraftLabel")
				{
					Place((RectTransform)val3, (Transform)(object)val2, new Vector2(num2 - 24f, 32f), new Vector2(12f, -2f));
				}
			}
			((Selectable)val).interactable = !flag;
			((Graphic)((Component)val).GetComponent<Image>()).color = (Color)((value == CraftingCategories.Selected) ? new Color(1f, 0.76f, 0.38f, 1f) : Color.white);
		}
		if (Object.op_Implicit((Object)(object)emptyCategory))
		{
			emptyCategory.gameObject.SetActive(CraftingCategories.RecipeCount(gui) == 0);
		}
	}

	private static void Build(InventoryGui gui)
	{
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: 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_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: 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_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_020e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0230: Unknown result type (might be due to invalid IL or missing references)
		//IL_023f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b9: 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_02d2: Expected O, but got Unknown
		//IL_0333: Unknown result type (might be due to invalid IL or missing references)
		//IL_033a: Unknown result type (might be due to invalid IL or missing references)
		//IL_033c: Unknown result type (might be due to invalid IL or missing references)
		//IL_033d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0344: Unknown result type (might be due to invalid IL or missing references)
		//IL_0352: 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_02e5: 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_0305: Unknown result type (might be due to invalid IL or missing references)
		//IL_0315: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_03cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0505: Unknown result type (might be due to invalid IL or missing references)
		//IL_0514: Unknown result type (might be due to invalid IL or missing references)
		//IL_0538: Unknown result type (might be due to invalid IL or missing references)
		//IL_0547: Unknown result type (might be due to invalid IL or missing references)
		//IL_056b: Unknown result type (might be due to invalid IL or missing references)
		//IL_057a: Unknown result type (might be due to invalid IL or missing references)
		//IL_059e: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0400: Unknown result type (might be due to invalid IL or missing references)
		//IL_0414: Unknown result type (might be due to invalid IL or missing references)
		//IL_0423: Unknown result type (might be due to invalid IL or missing references)
		//IL_042d: Expected O, but got Unknown
		//IL_0464: Unknown result type (might be due to invalid IL or missing references)
		//IL_047a: Unknown result type (might be due to invalid IL or missing references)
		//IL_047f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0489: Expected O, but got Unknown
		//IL_06e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_06f7: Unknown result type (might be due to invalid IL or missing references)
		object obj = Get(gui, "m_crafting");
		RectTransform val = (RectTransform)((obj is RectTransform) ? obj : null);
		object obj2 = Get(gui, "m_recipeListRoot");
		RectTransform val2 = (RectTransform)((obj2 is RectTransform) ? obj2 : null);
		ScrollRect val3 = (Object.op_Implicit((Object)(object)val2) ? ((Component)val2).GetComponentInParent<ScrollRect>() : null);
		if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val3) || (Object)(object)((Component)val3).transform == (Object)(object)val)
		{
			return;
		}
		owner = gui;
		styledRows.Clear();
		hiddenGraphics.Clear();
		materialBackdrops.Clear();
		Vector2 val4 = default(Vector2);
		((Vector2)(ref val4))..ctor(0.5f, 0.5f);
		val.pivot = val4;
		Vector2 anchorMin = (val.anchorMax = val4);
		val.anchorMin = anchorMin;
		val.sizeDelta = new Vector2(900f, 650f);
		val.anchoredPosition = new Vector2(150f, 0f);
		root = Box((Transform)(object)val, "ControllerCraftSkin", new Vector2(900f, 650f), new Vector2(0f, 0f), wood: true);
		RectTransform obj3 = root;
		RectTransform obj4 = root;
		RectTransform obj5 = root;
		((Vector2)(ref val4))..ctor(0.5f, 0.5f);
		obj5.pivot = val4;
		anchorMin = (obj4.anchorMax = val4);
		obj3.anchorMin = anchorMin;
		root.anchoredPosition = Vector2.zero;
		RectTransform parent = Box((Transform)(object)root, "ControllerCraftHeader", new Vector2(876f, 70f), new Vector2(12f, -12f), wood: true);
		craftingHeading = Label(gui, (Transform)(object)parent, gui.InUpradeTab() ? "UPGRADE" : "CRAFTING", new Vector2(850f, 50f), new Vector2(13f, -10f), 34f);
		BuildCategoryTabs(gui);
		RectTransform parent2 = Box((Transform)(object)root, "ControllerCraftRecipes", new Vector2(314f, 502f), new Vector2(12f, -130f), wood: true);
		detail = Box((Transform)(object)root, "ControllerCraftDetails", new Vector2(550f, 502f), new Vector2(338f, -130f), wood: true);
		emptyCategory = Label(gui, (Transform)(object)parent2, "No recipes in this category", new Vector2(270f, 90f), new Vector2(22f, -32f), 23f);
		if (Object.op_Implicit((Object)(object)emptyCategory) && Wrapping != null)
		{
			Wrapping.SetValue(emptyCategory, true, null);
		}
		Divider((Transform)(object)detail, -185f, ornament: true);
		Divider((Transform)(object)detail, -412f, ornament: false);
		Place((RectTransform)((Component)val3).transform, (Transform)(object)parent2, new Vector2(290f, 478f), new Vector2(12f, -12f));
		if (Object.op_Implicit((Object)(object)val3.viewport))
		{
			val3.viewport.anchorMin = Vector2.zero;
			val3.viewport.anchorMax = Vector2.one;
			val3.viewport.offsetMin = Vector2.zero;
			val3.viewport.offsetMax = Vector2.zero;
		}
		((Vector2)(ref val4))..ctor(0f, 1f);
		val2.pivot = val4;
		anchorMin = (val2.anchorMax = val4);
		val2.anchorMin = anchorMin;
		val2.sizeDelta = new Vector2(290f, val2.sizeDelta.y);
		if (Object.op_Implicit((Object)(object)val3.verticalScrollbar))
		{
			((Component)val3.verticalScrollbar).gameObject.SetActive(false);
		}
		AccessTools.Field(typeof(InventoryGui), "m_recipeListSpace").SetValue(gui, 96f);
		Move(gui, "m_recipeIcon", (Transform)(object)detail, new Vector2(170f, 170f), new Vector2(190f, -10f));
		object obj6 = Get(gui, "m_minStationLevelIcon");
		Component val8 = (Component)((obj6 is Component) ? obj6 : null);
		Graphic[] componentsInChildren;
		if (Object.op_Implicit((Object)(object)val8))
		{
			Place((RectTransform)val8.transform, (Transform)(object)detail, new Vector2(64f, 64f), new Vector2(452f, -112f));
			object obj7 = Get(gui, "m_minStationLevelText");
			Component val9 = (Component)((obj7 is Component) ? obj7 : null);
			if (Object.op_Implicit((Object)(object)val9) && (Object)(object)val9.transform != (Object)(object)val8.transform)
			{
				Place((RectTransform)val9.transform, val8.transform, new Vector2(64f, 64f), Vector2.zero);
				Component component = val9.GetComponent(TextType);
				if (Object.op_Implicit((Object)(object)component))
				{
					Alignment.SetValue(component, Enum.Parse(Alignment.PropertyType, "Center"), null);
				}
			}
			componentsInChildren = val8.GetComponentsInChildren<Graphic>(true);
			foreach (Graphic obj8 in componentsInChildren)
			{
				((Behaviour)obj8).enabled = true;
				obj8.raycastTarget = false;
			}
		}
		Move(gui, "m_recipeDecription", (Transform)(object)detail, new Vector2(290f, 120f), new Vector2(226f, -95f), 20f);
		Move(gui, "m_craftButton", (Transform)(object)detail, new Vector2(410f, 55f), new Vector2(70f, -430f));
		Move(gui, "m_craftCancelButton", (Transform)(object)detail, new Vector2(410f, 55f), new Vector2(70f, -430f));
		Move(gui, "m_craftProgressPanel", (Transform)(object)detail, new Vector2(410f, 55f), new Vector2(70f, -430f));
		Move(gui, "m_variantButton", (Transform)(object)detail, new Vector2(110f, 32f), new Vector2(410f, -379f));
		string[] array = new string[2] { "m_craftButton", "m_craftCancelButton" };
		foreach (string name in array)
		{
			object obj9 = Get(gui, name);
			Button val10 = (Button)((obj9 is Button) ? obj9 : null);
			if (Object.op_Implicit((Object)(object)val10))
			{
				Image component2 = ((Component)val10).GetComponent<Image>();
				if (Object.op_Implicit((Object)(object)component2))
				{
					component2.sprite = DualInventory.Frame();
					component2.type = (Type)1;
				}
				Component[] componentsInChildren2 = ((Component)val10).GetComponentsInChildren(TextType, true);
				for (int j = 0; j < componentsInChildren2.Length; j++)
				{
					FontSize(componentsInChildren2[j], 28f, wrap: false);
				}
			}
		}
		if (Get(gui, "m_recipeRequirementList") is GameObject[] array2)
		{
			GameObject[] array3 = array2;
			foreach (GameObject val11 in array3)
			{
				val11.transform.SetParent((Transform)(object)detail, false);
				RectTransform obj10 = Box(val11.transform, "ControllerMaterialTile", new Vector2(64f, 60f), new Vector2(33f, 3f), wood: false);
				Image val12 = ((Component)obj10).gameObject.AddComponent<Image>();
				val12.sprite = MaterialFrame();
				val12.type = (Type)1;
				((Graphic)val12).raycastTarget = false;
				((Transform)obj10).SetAsFirstSibling();
				Transform val13 = val11.transform.Find("res_icon");
				Image[] componentsInChildren3 = val11.GetComponentsInChildren<Image>(true);
				foreach (Image val14 in componentsInChildren3)
				{
					if (!((Object)(object)val14 == (Object)(object)val12) && (!Object.op_Implicit((Object)(object)val13) || !((Component)val14).transform.IsChildOf(val13)))
					{
						((Behaviour)val14).enabled = false;
						materialBackdrops.Add(val14);
					}
				}
				array = new string[2] { "res_name", "res_amount" };
				foreach (string text in array)
				{
					Transform val15 = val11.transform.Find(text);
					FontSize((Component)(object)val15, 18f, wrap: false);
					Component val16 = (Object.op_Implicit((Object)(object)val15) ? ((Component)val15).GetComponent(TextType) : null);
					if (Object.op_Implicit((Object)(object)val16))
					{
						Alignment.SetValue(val16, Enum.Parse(Alignment.PropertyType, "Center"), null);
					}
				}
			}
		}
		componentsInChildren = ((Component)val).GetComponentsInChildren<Graphic>(true);
		foreach (Graphic val17 in componentsInChildren)
		{
			if (!((Component)val17).transform.IsChildOf((Transform)(object)root))
			{
				((Behaviour)val17).enabled = false;
				hiddenGraphics.Add(val17);
			}
		}
	}

	private static Vector2 WorkbenchScreenSize(RectTransform rect, Camera camera)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		rect.GetWorldCorners(WorkbenchCorners);
		Vector2 val = RectTransformUtility.WorldToScreenPoint(camera, WorkbenchCorners[0]);
		Vector2 val2 = val;
		for (int i = 1; i < 4; i++)
		{
			Vector2 val3 = RectTransformUtility.WorldToScreenPoint(camera, WorkbenchCorners[i]);
			val = Vector2.Min(val, val3);
			val2 = Vector2.Max(val2, val3);
		}
		return val2 - val;
	}

	private static void WorkbenchPlace(RectTransform rect, Vector2 pivotScreen, Camera camera)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		Vector3 position = default(Vector3);
		if (Object.op_Implicit((Object)(object)workbenchViewport) && RectTransformUtility.ScreenPointToWorldPointInRectangle(workbenchViewport, pivotScreen, camera, ref position))
		{
			((Transform)rect).position = position;
		}
	}

	private unsafe static void RepositionWorkbench()
	{
		//IL_00a0: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: 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_011c: 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_0132: 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_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: 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)
		//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0219: Unknown result type (might be due to invalid IL or missing references)
		//IL_023a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0244: Unknown result type (might be due to invalid IL or missing references)
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_0263: Unknown result type (might be due to invalid IL or missing references)
		//IL_026b: Unknown result type (might be due to invalid IL or missing references)
		//IL_027e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0294: Unknown result type (might be due to invalid IL or missing references)
		//IL_029e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_0301: Unknown result type (might be due to invalid IL or missing references)
		//IL_0306: 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_033d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0342: Unknown result type (might be due to invalid IL or missing references)
		//IL_037c: Unknown result type (might be due to invalid IL or missing references)
		//IL_037d: Unknown result type (might be due to invalid IL or missing references)
		//IL_039b: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)workbenchGui) || !Object.op_Implicit((Object)(object)workbenchPlayer) || !Object.op_Implicit((Object)(object)workbenchCrafting) || !Object.op_Implicit((Object)(object)workbenchCanvas) || !Object.op_Implicit((Object)(object)workbenchViewport) || !InventoryPanels.Crafting)
		{
			return;
		}
		Player localPlayer = Player.m_localPlayer;
		if (!Object.op_Implicit((Object)(object)localPlayer) || (Object)(object)localPlayer.GetCurrentCraftingStation() == (Object)null)
		{
			return;
		}
		Transform obj = ((Transform)workbenchPlayer).Find("ControllerInventory_CraftingSupplies");
		RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
		if (!Object.op_Implicit((Object)(object)val) || !((Component)val).gameObject.activeInHierarchy)
		{
			return;
		}
		((Transform)workbenchCrafting).localScale = new Vector3(0.49875003f, 0.665f, 1f);
		Camera camera = (((int)workbenchCanvas.renderMode == 0) ? null : workbenchCanvas.worldCamera);
		Vector2 val2 = WorkbenchScreenSize(workbenchPlayer, camera);
		Vector2 val3 = WorkbenchScreenSize(workbenchCrafting, camera);
		Vector2 val4 = (Object.op_Implicit((Object)(object)workbenchStorageReference) ? WorkbenchScreenSize(workbenchStorageReference, camera) : Vector2.zero);
		Rect rect = workbenchPlayer.rect;
		if (((Rect)(ref rect)).width <= 0f)
		{
			return;
		}
		rect = workbenchPlayer.rect;
		if (!(((Rect)(ref rect)).height <= 0f))
		{
			float x = val2.x;
			rect = workbenchPlayer.rect;
			float num = x / ((Rect)(ref rect)).width;
			float y = val2.y;
			rect = workbenchPlayer.rect;
			float num2 = y / ((Rect)(ref rect)).height;
			float num3 = val.anchoredPosition.x * num;
			rect = val.rect;
			float num4 = ((Rect)(ref rect)).width * num;
			rect = val.rect;
			float num5 = ((Rect)(ref rect)).height * num2;
			float num6 = 16f * num2;
			float num7 = num3 + num4;
			float num8 = ((val4.y > 1f) ? (num5 + num6 + val4.y) : (num5 + num6 + val3.y));
			float num9 = Mathf.Max(val2.y, num8);
			Rect pixelRect = workbenchCanvas.pixelRect;
			float num10 = ((Rect)(ref pixelRect)).center.x - num7 * 0.5f + 0f;
			float num11 = ((Rect)(ref pixelRect)).center.y + num9 * 0.5f;
			WorkbenchPlace(workbenchPlayer, new Vector2(num10 + workbenchPlayer.pivot.x * val2.x, num11 - (1f - workbenchPlayer.pivot.y) * val2.y), camera);
			float num12 = num10 + num3 + num4 - val3.x;
			WorkbenchPlace(workbenchCrafting, new Vector2(num12 + workbenchCrafting.pivot.x * val3.x, num11 - num5 - num6 - (1f - workbenchCrafting.pivot.y) * val3.y), camera);
			float num13 = val3.x / Mathf.Max(0.0001f, num);
			float x2 = val.anchoredPosition.x;
			rect = val.rect;
			float width = Mathf.Max(0f, ((Rect)(ref rect)).width - num13 - 12f);
			float height = val3.y / Mathf.Max(0.0001f, num2);
			RectTransform parent = workbenchPlayer;
			rect = val.rect;
			ItemInfoLayout.Show(parent, x2, 0f - ((Rect)(ref rect)).height - 16f, width, height);
			if (!workbenchLayoutLogged)
			{
				workbenchLayoutLogged = true;
				string[] obj2 = new string[10] { "[Layout test] workstation | player=", null, null, null, null, null, null, null, null, null };
				Vector2 val5 = val2;
				obj2[1] = ((object)(*(Vector2*)(&val5))/*cast due to .constrained prefix*/).ToString();
				obj2[2] = " supplies=";
				obj2[3] = ((object)new Vector2(num4, num5)/*cast due to .constrained prefix*/).ToString();
				obj2[4] = " crafting=";
				val5 = val3;
				obj2[5] = ((object)(*(Vector2*)(&val5))/*cast due to .constrained prefix*/).ToString();
				obj2[6] = " storageRef=";
				val5 = val4;
				obj2[7] = ((object)(*(Vector2*)(&val5))/*cast due to .constrained prefix*/).ToString();
				obj2[8] = " total=";
				obj2[9] = ((object)new Vector2(num7, num9)/*cast due to .constrained prefix*/).ToString();
				DualInventory.Log(string.Concat(obj2));
			}
		}
	}

	private static void PrepareWorkbenchLayout(InventoryGui gui)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: 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_0056: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Expected O, but got Unknown
		object obj = Get(gui, "m_player");
		RectTransform val = (RectTransform)((obj is RectTransform) ? obj : null);
		object obj2 = Get(gui, "m_crafting");
		RectTransform val2 = (RectTransform)((obj2 is RectTransform) ? obj2 : null);
		if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2))
		{
			return;
		}
		if (!savedWorkbenchTransforms)
		{
			normalPlayerPosition = val.anchoredPosition;
			normalCraftingPosition = val2.anchoredPosition;
			normalCraftingScale = ((Transform)val2).localScale;
			savedWorkbenchTransforms = true;
		}
		workbenchGui = gui;
		workbenchPlayer = val;
		workbenchCrafting = val2;
		object obj3 = Get(gui, "m_container");
		workbenchStorageReference = (RectTransform)((obj3 is RectTransform) ? obj3 : null);
		workbenchCanvas = ((Component)val).GetComponentInParent<Canvas>();
		workbenchCanvas = (Object.op_Implicit((Object)(object)workbenchCanvas) ? workbenchCanvas.rootCanvas : null);
		workbenchViewport = (RectTransform)(Object.op_Implicit((Object)(object)workbenchCanvas) ? /*isinst with value type is only supported in some contexts*/: null);
		if (!workbenchSubscribed)
		{
			object obj4 = <>O.<1>__RepositionWorkbench;
			if (obj4 == null)
			{
				WillRenderCanvases val3 = RepositionWorkbench;
				<>O.<1>__RepositionWorkbench = val3;
				obj4 = (object)val3;
			}
			Canvas.preWillRenderCanvases += (WillRenderCanvases)obj4;
			workbenchSubscribed = true;
		}
		RepositionWorkbench();
	}

	internal static void RestorePosition(InventoryGui gui)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		if (workbenchSubscribed)
		{
			object obj = <>O.<1>__RepositionWorkbench;
			if (obj == null)
			{
				WillRenderCanvases val = RepositionWorkbench;
				<>O.<1>__RepositionWorkbench = val;
				obj = (object)val;
			}
			Canvas.preWillRenderCanvases -= (WillRenderCanvases)obj;
			workbenchSubscribed = false;
		}
		object obj2 = Get(gui, "m_player");
		RectTransform val2 = (RectTransform)((obj2 is RectTransform) ? obj2 : null);
		object obj3 = Get(gui, "m_crafting");
		RectTransform val3 = (RectTransform)((obj3 is RectTransform) ? obj3 : null);
		if (savedWorkbenchTransforms)
		{
			if (Object.op_Implicit((Object)(object)val2))
			{
				val2.anchoredPosition = normalPlayerPosition;
			}
			if (Object.op_Implicit((Object)(object)val3))
			{
				val3.anchoredPosition = normalCraftingPosition;
				((Transform)val3).localScale = normalCraftingScale;
			}
		}
		savedWorkbenchTransforms = false;
		workbenchGui = null;
		workbenchPlayer = null;
		workbenchCrafting = null;
		workbenchStorageReference = null;
		workbenchCanvas = null;
		workbenchViewport = null;
		workbenchLayoutLogged = false;
		ItemInfoLayout.ClearCraftingInfo();
		if (!DualInventory.CombinedStorage)
		{
			ItemInfoLayout.Hide();
		}
	}

	internal static void Apply(InventoryGui gui)
	{
		try
		{
			ApplyCore(gui);
		}
		catch (Exception ex)
		{
			if (!warned)
			{
				warned = true;
				DualInventory.Log("Crafting appearance: " + ex);
			}
		}
	}

	private static void ApplyCore(InventoryGui gui)
	{
		//IL_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Expected O, but got Unknown
		//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0225: Unknown result type (might be due to invalid IL or missing references)
		//IL_022a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0234: 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_0299: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02eb: 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_0331: Unknown result type (might be due to invalid IL or missing references)
		//IL_0377: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_04eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_051c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0526: Expected O, but got Unknown
		//IL_0542: Unknown result type (might be due to invalid IL or missing references)
		//IL_0551: Unknown result type (might be due to invalid IL or missing references)
		//IL_058f: Unknown result type (might be due to invalid IL or missing references)
		//IL_059e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0601: Unknown result type (might be due to invalid IL or missing references)
		//IL_0610: Unknown result type (might be due to invalid IL or missing references)
		if (!InventoryPanels.Crafting)
		{
			return;
		}
		if ((Object)(object)owner != (Object)(object)gui || !Object.op_Implicit((Object)(object)root))
		{
			Build(gui);
		}
		if (!Object.op_Implicit((Object)(object)root))
		{
			return;
		}
		UpdateCategoryTabs(gui);
		if (Object.op_Implicit((Object)(object)craftingHeading))
		{
			string text = (gui.InUpradeTab() ? "UPGRADE" : "CRAFTING");
			if (!string.Equals(Text.GetValue(craftingHeading, null) as string, text, StringComparison.Ordinal))
			{
				Text.SetValue(craftingHeading, text, null);
			}
		}
		PrepareWorkbenchLayout(gui);
		ShortDescription(gui);
		object obj = Get(gui, "m_recipeName");
		Component val = (Component)((obj is Component) ? obj : null);
		Component obj2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent(TextType) : null);
		Graphic val2 = (Graphic)(object)((obj2 is Graphic) ? obj2 : null);
		if (Object.op_Implicit((Object)(object)val2))
		{
			((Behaviour)val2).enabled = false;
		}
		foreach (Graphic hiddenGraphic in hiddenGraphics)
		{
			if (Object.op_Implicit((Object)(object)hiddenGraphic) && ((Behaviour)hiddenGraphic).enabled)
			{
				((Behaviour)hiddenGraphic).enabled = false;
			}
		}
		foreach (Image materialBackdrop in materialBackdrops)
		{
			if (Object.op_Implicit((Object)(object)materialBackdrop) && ((Behaviour)materialBackdrop).enabled)
			{
				((Behaviour)materialBackdrop).enabled = false;
			}
		}
		object obj3 = Get(gui, "m_recipeListRoot");
		RectTransform val3 = (RectTransform)((obj3 is RectTransform) ? obj3 : null);
		int num = 0;
		foreach (Transform item in (Transform)val3)
		{
			object obj4 = (object)item;
			RectTransform val4 = (RectTransform)((obj4 is RectTransform) ? obj4 : null);
			if (!Object.op_Implicit((Object)(object)val4) || !((Component)val4).gameObject.activeSelf || !Object.op_Implicit((Object)(object)((Transform)val4).Find("icon")))
			{
				continue;
			}
			Place(val4, (Transform)(object)val3, new Vector2(290f, 90f), new Vector2(0f, (float)(-(num++) * 96)));
			if (!styledRows.Add(((Component)val4).gameObject))
			{
				continue;
			}
			Button[] componentsInChildren = ((Component)val4).GetComponentsInChildren<Button>(true);
			foreach (Button obj5 in componentsInChildren)
			{
				Navigation navigation = ((Selectable)obj5).navigation;
				((Navigation)(ref navigation)).mode = (Mode)0;
				((Selectable)obj5).navigation = navigation;
			}
			((Transform)Box((Transform)(object)val4, "ControllerCraftRow", new Vector2(290f, 90f), Vector2.zero, wood: true)).SetAsFirstSibling();
			Transform obj6 = ((Transform)val4).Find("icon");
			RectTransform val5 = (RectTransform)(object)((obj6 is RectTransform) ? obj6 : null);
			if (Object.op_Implicit((Object)(object)val5))
			{
				Place(val5, (Transform)(object)val4, new Vector2(60f, 60f), new Vector2(10f, -15f));
			}
			Transform obj7 = ((Transform)val4).Find("name");
			RectTransform val6 = (RectTransform)(object)((obj7 is RectTransform) ? obj7 : null);
			if (Object.op_Implicit((Object)(object)val6))
			{
				Place(val6, (Transform)(object)val4, new Vector2(204f, 65f), new Vector2(80f, -12f));
				FontSize((Component)(object)val6, 23f, wrap: true);
			}
			Transform obj8 = ((Transform)val4).Find("selected");
			RectTransform val7 = (RectTransform)(object)((obj8 is RectTransform) ? obj8 : null);
			if (Object.op_Implicit((Object)(object)val7))
			{
				Place(val7, (Transform)(object)val4, new Vector2(290f, 90f), Vector2.zero);
				Image component = ((Component)val7).GetComponent<Image>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.sprite = DualInventory.Frame();
					component.type = (Type)1;
					((Graphic)component).color = new Color(1f, 0.69f, 0.22f, 0.65f);
				}
				((Transform)val7).SetSiblingIndex(1);
			}
		}
		val3.SetSizeWithCurrentAnchors((Axis)1, (float)Mathf.Max(478, num * 96));
		if (!(Get(gui, "m_recipeRequirementList") is GameObject[] array))
		{
			return;
		}
		int num2 = 0;
		GameObject[] array2 = array;
		foreach (GameObject val8 in array2)
		{
			if (Object.op_Implicit((Object)(object)val8))
			{
				Transform val9 = val8.transform.Find("res_icon");
				if (Object.op_Implicit((Object)(object)val9) && ((Component)val9).gameObject.activeSelf)
				{
					num2++;
				}
			}
		}
		int num3 = 0;
		foreach (GameObject val10 in array)
		{
			if (!Object.op_Implicit((Object)(object)val10) || !val10.activeSelf)
			{
				continue;
			}
			Transform obj9 = val10.transform.Find("res_icon");
			RectTransform val11 = (RectTransform)(object)((obj9 is RectTransform) ? obj9 : null);
			bool flag = Object.op_Implicit((Object)(object)val11) && ((Component)val11).gameObject.activeSelf;
			Transform val12 = val10.transform.Find("ControllerMaterialTile");
			if (Object.op_Implicit((Object)(object)val12))
			{
				((Component)val12).gameObject.SetActive(flag);
			}
			if (!flag)
			{
				continue;
			}
			int num4 = num3++;
			int num5 = num4 % 2;
			int num6 = num4 / 2;
			Place((RectTransform)val10.transform, (Transform)(object)detail, new Vector2(130f, 110f), new Vector2((float)((550 - Mathf.Min(2, num2) * 145) / 2 + num5 * 145), (float)(-200 - num6 * 95)));
			if (Object.op_Implicit((Object)(object)val11))
			{
				Place(val11, val10.transform, new Vector2(54f, 54f), new Vector2(38f, 0f));
			}
			Transform obj10 = val10.transform.Find("res_name");
			RectTransform val13 = (RectTransform)(object)((obj10 is RectTransform) ? obj10 : null);
			if (Object.op_Implicit((Object)(object)val13))
			{
				Place(val13, val10.transform, new Vector2(130f, 26f), new Vector2(0f, -60f));
				((Component)val13).gameObject.SetActive(flag);
				FontSize((Component)(object)val13, 18f, wrap: false);
				((Transform)val13).SetAsLastSibling();
			}
			Transform obj11 = val10.transform.Find("res_amount");
			RectTransform val14 = (RectTransform)(object)((obj11 is RectTransform) ? obj11 : null);
			if (!Object.op_Implicit((Object)(object)val14))
			{
				continue;
			}
			Place(val14, val10.transform, new Vector2(130f, 26f), new Vector2(0f, -86f));
			((Component)val14).gameObject.SetActive(flag);
			Component component2 = ((Component)val14).GetComponent(TextType);
			if (Object.op_Implicit((Object)(object)component2))
			{
				Font.SetValue(component2, 18f, null);
				Graphic val15 = (Graphic)(object)((component2 is Graphic) ? component2 : null);
				if (Object.op_Implicit((Object)(object)val15))
				{
					((Behaviour)val15).enabled = true;
				}
			}
			((Transform)val14).SetAsLastSibling();
		}
	}
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInIncompatibility("valheim.controller.wheels")]
[BepInIncompatibility("shudnal.ExtraSlots")]
[BepInPlugin("valheim.controller.forge", "Controller Forge", "1.0.0")]
public sealed class ControllerForgePlugin : BaseUnityPlugin
{
	internal static ConfigEntry<bool> DirectWeapons;

	internal static ConfigEntry<bool> ShowAllCraftingTab;

	internal static ConfigEntry<bool> ShowGearSpecs;

	internal static ConfigEntry<float> WeaponSelectionTime;

	internal static ConfigEntry<float> FoodSelectionTime;

	private Harmony harmony;

	private void Awake()
	{
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Expected O, but got Unknown
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Expected O, but got Unknown
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Expected O, but got Unknown
		WheelPerformance.Log = ((BaseUnityPlugin)this).Logger;
		DirectWeapons = ((BaseUnityPlugin)this).Config.Bind<bool>("Wheels", "Weapon Button Opens Weapons", true, "Created by elHUDlessG. Controller setup: keep Steam Input ON and use the default Valheim controller layout. No custom F8 or Ctrl mappings are needed; reset earlier test layouts to the default. Open weapons and tools directly from the existing wheel action.");
		WeaponSelectionTime = ((BaseUnityPlugin)this).Config.Bind<float>("Selection Timing", "Weapon Selection Time Multiplier", 0.25f, new ConfigDescription("Weapon and tool selection duration relative to Valheim's hover selection time. Lower is faster. 0.25 is half the duration used in 1.1.31; 0.5 restores 1.1.31.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 5f), Array.Empty<object>()));
		FoodSelectionTime = ((BaseUnityPlugin)this).Config.Bind<float>("Selection Timing", "Food Selection Time Multiplier", 1f, new ConfigDescription("Food and potion selection duration relative to Valheim's hover selection time. Lower is faster. 1 keeps the existing food selection timing. Does not change wheel opening time.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 5f), Array.Empty<object>()));
		ShowAllCraftingTab = ((BaseUnityPlugin)this).Config.Bind<bool>("Crafting", "Show All Recipes Tab", true, "Show All alongside Armor, Weapons and Arrows so food and other recipes remain reachable. Disable to show only the three category tabs; stations with no matching categories keep their normal recipe list.");
		ShowGearSpecs = ((BaseUnityPlugin)this).Config.Bind<bool>("Gear Inventory", "Show Gear Specs", false, "Show the highlighted Gear item's specs in the bottom-left corner of the screen. Controller Start/Menu or F9 toggles this setting while the no

BepInEx/plugins/ControllerForgeSlots.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Controller Forge Slots")]
[assembly: AssemblyDescription("Original inventory slot backend for Controller Forge")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ControllerForgeSlots
{
	[BepInPlugin("valheim.controller.forge.slots", "Controller Forge Slots", "1.0.0")]
	[BepInIncompatibility("shudnal.ExtraSlots")]
	public sealed class ControllerForgeSlotsPlugin : BaseUnityPlugin
	{
		private Harmony harmony;

		private void Awake()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			API.GetSlots();
			harmony = new Harmony("valheim.controller.forge.slots");
			harmony.PatchAll(typeof(ControllerForgeSlotsPlugin).Assembly);
			MethodInfo methodInfo = typeof(EmptyCellPatch).GetMethod("Prefix").MakeGenericMethod(PositionCodec.PositionType);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Inventory), "FindEmptySlot", (Type[])null, (Type[])null), new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Inventory), "AddItem", new Type[2]
			{
				typeof(ItemData),
				PositionCodec.PositionType
			}, (Type[])null), new HarmonyMethod(typeof(ExactPositionPatch).GetMethod("Prefix")), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Controller Forge Slots 1.0.0 loaded");
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}
	}
	internal static class InventoryRules
	{
		private sealed class Owner
		{
			internal readonly Player Player;

			internal Owner(Player player)
			{
				Player = player;
			}
		}

		private static readonly ConditionalWeakTable<Inventory, Owner> owners = new ConditionalWeakTable<Inventory, Owner>();

		private static readonly FieldInfo heightField = AccessTools.Field(typeof(Inventory), "m_height");

		private static readonly MethodInfo changed = AccessTools.Method(typeof(Inventory), "Changed", new Type[2]
		{
			typeof(bool),
			typeof(bool)
		}, (Type[])null);

		[ThreadStatic]
		internal static ItemData Adding;

		[ThreadStatic]
		internal static int Loading;

		internal static bool IsPlayer(Inventory inventory)
		{
			Owner value;
			if (inventory != null)
			{
				return owners.TryGetValue(inventory, out value);
			}
			return false;
		}

		internal static void Attach(Player player)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory != null)
			{
				owners.Remove(inventory);
				owners.Add(inventory, new Owner(player));
				EnsureHeight(inventory);
			}
		}

		internal static void EnsureHeight(Inventory inventory)
		{
			if (inventory == null)
			{
				return;
			}
			int val = API.RequiredHeight(inventory);
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				val = Math.Max(val, PositionCodec.Get(allItem).y + 1);
			}
			heightField.SetValue(inventory, Math.Max(val, inventory.GetHeight()));
		}

		internal static void Notify(Inventory inventory)
		{
			changed.Invoke(inventory, new object[2] { true, false });
		}

		internal static bool Ordinary(Inventory inventory, GridCell cell)
		{
			if (cell.x >= 0 && cell.x < inventory.GetWidth() && cell.y >= 0)
			{
				return cell.y < 5;
			}
			return false;
		}

		internal static bool Allowed(Inventory inventory, ItemData item, GridCell position)
		{
			if (Ordinary(inventory, position))
			{
				return true;
			}
			return API.At(inventory, position)?.ItemFits(item) ?? false;
		}

		internal static GridCell Empty(Inventory inventory, ItemData item, bool topFirst)
		{
			if (item != null)
			{
				SlotDefinition[] slots = API.GetSlots();
				foreach (SlotDefinition slotDefinition in slots)
				{
					GridCell result = slotDefinition.PositionFor(inventory);
					if (!slotDefinition.Recovery && slotDefinition.ItemFits(item) && inventory.GetItemAt(result.x, result.y) == null)
					{
						return result;
					}
				}
			}
			for (int j = 0; j < 5; j++)
			{
				int num = (topFirst ? j : (4 - j));
				for (int k = 0; k < inventory.GetWidth(); k++)
				{
					if (inventory.GetItemAt(k, num) == null)
					{
						return new GridCell(k, num);
					}
				}
			}
			return new GridCell(-1, -1);
		}

		internal static int Capacity(Inventory inventory, ItemData item)
		{
			int num = 0;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem.m_shared.m_name == item.m_shared.m_name && allItem.m_quality == item.m_quality && allItem.m_worldLevel == item.m_worldLevel)
				{
					num += Math.Max(0, allItem.m_shared.m_maxStackSize - allItem.m_stack);
				}
			}
			int num2 = 0;
			for (int i = 0; i < 5; i++)
			{
				for (int j = 0; j < inventory.GetWidth(); j++)
				{
					if (inventory.GetItemAt(j, i) == null)
					{
						num2++;
					}
				}
			}
			SlotDefinition[] slots = API.GetSlots();
			foreach (SlotDefinition slotDefinition in slots)
			{
				GridCell gridCell = slotDefinition.PositionFor(inventory);
				if (!slotDefinition.Recovery && slotDefinition.ItemFits(item) && inventory.GetItemAt(gridCell.x, gridCell.y) == null)
				{
					num2++;
				}
			}
			return num + num2 * Math.Max(1, item.m_shared.m_maxStackSize);
		}

		internal static void Reconcile(Inventory inventory)
		{
			if (!IsPlayer(inventory))
			{
				return;
			}
			API.ClearRecovery();
			ItemData[] array = inventory.GetAllItems().ToArray();
			int width = inventory.GetWidth();
			SlotDefinition[] slots = API.GetSlots();
			int[] reservedCells = slots.Select((SlotDefinition slot) => Cell(slot.PositionFor(inventory), width)).ToArray();
			int[] currentCells = array.Select((ItemData item2) => Cell(PositionCodec.Get(item2), width)).ToArray();
			int[][] allowedSpecialCells = array.Select((ItemData item2) => (from slot in slots
				where slot.ItemFits(item2)
				select Cell(slot.PositionFor(inventory), width)).ToArray()).ToArray();
			int[] array2 = CellPlanner.Assign(width, 5, currentCells, allowedSpecialCells, reservedCells);
			for (int num = 0; num < array.Length; num++)
			{
				PositionCodec.Set(array[num], new GridCell(array2[num] % width, array2[num] / width));
			}
			ItemData[] array3 = array;
			foreach (ItemData item in array3)
			{
				API.AddRecovery(inventory, item);
			}
			EnsureHeight(inventory);
			Notify(inventory);
		}

		private static int Cell(GridCell pos, int width)
		{
			if (pos.x >= 0 && pos.x < width && pos.y >= 0)
			{
				return pos.y * width + pos.x;
			}
			return -1;
		}
	}
	[HarmonyPatch(typeof(Player), "Awake")]
	internal static class PlayerAwakePatch
	{
		[HarmonyPostfix]
		private static void Postfix(Player __instance)
		{
			InventoryRules.Attach(__instance);
		}
	}
	[HarmonyPatch(typeof(Player), "Load")]
	internal static class PlayerLoadPatch
	{
		[HarmonyPrefix]
		private static void Prefix(Player __instance)
		{
			InventoryRules.Attach(__instance);
			InventoryRules.Loading++;
		}

		[HarmonyPostfix]
		private static void Postfix(Player __instance)
		{
			InventoryRules.Reconcile(((Humanoid)__instance).GetInventory());
		}

		[HarmonyFinalizer]
		private static void Finalizer()
		{
			InventoryRules.Loading--;
		}
	}
	[HarmonyPatch(typeof(Player), "SetInventorySize")]
	internal static class PlayerSizePatch
	{
		[HarmonyPrefix]
		private static bool Prefix(Player __instance)
		{
			InventoryRules.Attach(__instance);
			return false;
		}
	}
	[HarmonyPatch(typeof(Humanoid), "DropInvalidItems")]
	internal static class PreserveLoadedItemsPatch
	{
		[HarmonyPrefix]
		private static void Prefix(Humanoid __instance)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val != null)
			{
				InventoryRules.Attach(val);
			}
		}
	}
	internal static class EmptyCellPatch
	{
		public static bool Prefix<T>(Inventory __instance, bool __0, ref T __result)
		{
			if (!InventoryRules.IsPlayer(__instance) || InventoryRules.Loading > 0)
			{
				return true;
			}
			__result = (T)PositionCodec.Box(InventoryRules.Empty(__instance, InventoryRules.Adding, __0));
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
	internal static class PickupContextPatch
	{
		[HarmonyPrefix]
		private static void Prefix(Inventory __instance, ItemData __0, out ItemData __state)
		{
			__state = InventoryRules.Adding;
			if (InventoryRules.IsPlayer(__instance))
			{
				InventoryRules.Adding = __0;
			}
		}

		[HarmonyFinalizer]
		private static void Finalizer(ItemData __state)
		{
			InventoryRules.Adding = __state;
		}
	}
	internal static class ExactPositionPatch
	{
		public static bool Prefix(Inventory __instance, ItemData __0, object __1, ref bool __result)
		{
			if (!InventoryRules.IsPlayer(__instance) || InventoryRules.Loading > 0 || InventoryRules.Allowed(__instance, __0, PositionCodec.Read(__1)))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
	{
		typeof(ItemData),
		typeof(int),
		typeof(int),
		typeof(int),
		typeof(bool)
	})]
	internal static class PositionedAddPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(Inventory __instance, ItemData __0, int __2, int __3, bool __4, ref bool __result)
		{
			if (!InventoryRules.IsPlayer(__instance) || InventoryRules.Loading > 0 || __4)
			{
				return true;
			}
			if (InventoryRules.Allowed(__instance, __0, new GridCell(__2, __3)))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "CanAddItem", new Type[]
	{
		typeof(ItemData),
		typeof(int)
	})]
	internal static class CapacityPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(Inventory __instance, ItemData __0, int __1, ref bool __result)
		{
			if (!InventoryRules.IsPlayer(__instance) || __0 == null || InventoryRules.Loading > 0)
			{
				return true;
			}
			int num = ((__1 <= 0) ? __0.m_stack : __1);
			__result = InventoryRules.Capacity(__instance, __0) >= num && (API.CapacityFilter?.Invoke(__instance, __0, num) ?? true);
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "GetEmptySlots")]
	internal static class EmptyCountPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(Inventory __instance, ref int __result)
		{
			if (!InventoryRules.IsPlayer(__instance))
			{
				return true;
			}
			int num = 0;
			for (int i = 0; i < 5; i++)
			{
				for (int j = 0; j < __instance.GetWidth(); j++)
				{
					if (__instance.GetItemAt(j, i) == null)
					{
						num++;
					}
				}
			}
			__result = num;
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "HaveEmptySlot")]
	internal static class HasEmptyPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(Inventory __instance, ref bool __result)
		{
			if (!InventoryRules.IsPlayer(__instance))
			{
				return true;
			}
			__result = InventoryRules.Empty(__instance, null, topFirst: true).x >= 0;
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "SetHeight")]
	internal static class HeightPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Inventory __instance)
		{
			if (InventoryRules.IsPlayer(__instance))
			{
				InventoryRules.EnsureHeight(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
	internal static class GridHeightPatch
	{
		[HarmonyPrefix]
		private static void Prefix(InventoryGrid __instance)
		{
			Inventory inventory = __instance.GetInventory();
			if (InventoryRules.IsPlayer(inventory))
			{
				InventoryRules.EnsureHeight(inventory);
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "EquipItem")]
	internal static class EquippedItemPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Humanoid __instance, ItemData __0, bool __result)
		{
			if (!__result)
			{
				return;
			}
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			SlotDefinition[] slots = API.GetSlots();
			foreach (SlotDefinition slotDefinition in slots)
			{
				if ((!(slotDefinition.ID == "Helmet") && !(slotDefinition.ID == "Chest") && !(slotDefinition.ID == "Legs") && !(slotDefinition.ID == "Shoulder") && !(slotDefinition.ID == "Utility") && !(slotDefinition.ID == "Trinket")) || !slotDefinition.ItemFits(__0))
				{
					continue;
				}
				Inventory inventory = ((Humanoid)val).GetInventory();
				GridCell gridCell = slotDefinition.PositionFor(inventory);
				ItemData itemAt = inventory.GetItemAt(gridCell.x, gridCell.y);
				if (itemAt != null && itemAt != __0)
				{
					GridCell cell = PositionCodec.Get(__0);
					if (!InventoryRules.Ordinary(inventory, cell))
					{
						cell = InventoryRules.Empty(inventory, null, topFirst: true);
					}
					if (cell.x < 0)
					{
						break;
					}
					PositionCodec.Set(itemAt, cell);
				}
				if (PlayerInventoryOperations.MoveToSlot(__0, slotDefinition))
				{
					break;
				}
			}
		}
	}
	public sealed class SlotDefinition
	{
		internal readonly int Index;

		private readonly Func<string> label;

		private readonly Func<ItemData, bool> filter;

		private readonly Func<bool> active;

		public string ID { get; }

		public string Name => label();

		public bool IsActive
		{
			get
			{
				if (!Recovery)
				{
					return active();
				}
				return Item != null;
			}
		}

		public bool Recovery { get; internal set; }

		public bool IsAmmoSlot { get; }

		public bool IsFoodSlot { get; }

		public bool IsMiscSlot { get; }

		public object GridPosition => PositionCodec.Box(PositionFor(API.LocalInventory));

		public ItemData Item
		{
			get
			{
				Inventory localInventory = API.LocalInventory;
				if (localInventory == null)
				{
					return null;
				}
				return localInventory.GetItemAt(PositionFor(API.LocalInventory).x, PositionFor(API.LocalInventory).y);
			}
		}

		public bool IsFree => Item == null;

		internal GridCell PositionFor(Inventory inventory)
		{
			int num = ((inventory != null) ? inventory.GetWidth() : 8);
			return new GridCell(Index % num, 5 + Index / num);
		}

		internal SlotDefinition(string id, int index, Func<string> label, Func<ItemData, bool> filter, Func<bool> active, string kind)
		{
			ID = id;
			Index = index;
			this.label = label;
			this.filter = filter;
			this.active = active;
			IsAmmoSlot = kind == "ammo";
			IsFoodSlot = kind == "food";
			IsMiscSlot = kind == "misc";
		}

		public bool ItemFits(ItemData item)
		{
			if (item != null && item.m_shared != null && IsActive)
			{
				return filter(item);
			}
			return false;
		}
	}
	public static class API
	{
		public const int RegularRows = 5;

		private static readonly List<SlotDefinition> definitions;

		private static Func<ItemData, bool> miscFilter;

		internal static Func<Inventory, ItemData, int, bool> CapacityFilter;

		internal static Inventory LocalInventory
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					return null;
				}
				return ((Humanoid)Player.m_localPlayer).GetInventory();
			}
		}

		static API()
		{
			definitions = new List<SlotDefinition>();
			Equipment("Helmet", (ItemType)6);
			Equipment("Chest", (ItemType)7);
			Equipment("Legs", (ItemType)11);
			Equipment("Shoulder", (ItemType)17);
			Equipment("Utility", (ItemType)18);
			Equipment("Trinket", (ItemType)24);
			for (int i = 0; i < 3; i++)
			{
				Add("Food" + i, "FOOD", Food, "food");
			}
			for (int j = 0; j < 3; j++)
			{
				Add("Ammo" + j, "ARROWS", Ammo, "ammo");
			}
			for (int k = 0; k < 4; k++)
			{
				Add("Misc" + k, "EXTRA", Misc, "misc");
			}
		}

		private static void Equipment(string id, ItemType type)
		{
			//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)
			Add(id, id.ToUpperInvariant(), (ItemData item) => item.m_shared.m_itemType == type, "equipment");
		}

		private static void Add(string id, string label, Func<ItemData, bool> filter, string kind)
		{
			definitions.Add(new SlotDefinition(id, definitions.Count, () => label, filter, () => true, kind));
		}

		private static bool Food(ItemData item)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			if ((int)item.m_shared.m_itemType == 2)
			{
				return item.m_shared.m_food > 0f;
			}
			return false;
		}

		private static bool Ammo(ItemData item)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			if ((int)item.m_shared.m_itemType != 9)
			{
				return (int)item.m_shared.m_itemType == 23;
			}
			return true;
		}

		private static bool Misc(ItemData item)
		{
			if (!item.m_shared.m_questItem && (!Object.op_Implicit((Object)(object)item.m_dropPrefab) || !(((Object)item.m_dropPrefab).name == "CryptKey")))
			{
				return miscFilter?.Invoke(item) ?? false;
			}
			return true;
		}

		public static void SetCapacityFilter(Func<Inventory, ItemData, int, bool> filter)
		{
			CapacityFilter = filter;
		}

		internal static void ClearRecovery()
		{
			definitions.RemoveAll((SlotDefinition slot) => slot.Recovery);
		}

		internal static void AddRecovery(Inventory inventory, ItemData item)
		{
			GridCell pos = PositionCodec.Get(item);
			if (pos.y >= 5 && At(inventory, pos) == null)
			{
				int index = (pos.y - 5) * inventory.GetWidth() + pos.x;
				SlotDefinition slotDefinition = null;
				slotDefinition = new SlotDefinition("Recovery" + index, index, () => "RECOVERY", (ItemData candidate) => inventory.GetItemAt(pos.x, pos.y) == candidate, () => true, "recovery");
				slotDefinition.Recovery = true;
				definitions.Add(slotDefinition);
			}
		}

		public static void SetMiscFilter(Func<ItemData, bool> filter)
		{
			miscFilter = filter;
		}

		public static bool AddSlot(string id, Func<string> label, Func<ItemData, bool> filter, Func<bool> active)
		{
			if (string.IsNullOrWhiteSpace(id) || label == null || filter == null || active == null || definitions.Count((SlotDefinition slot) => !slot.Recovery) >= 32 || FindSlot(id) != null)
			{
				return false;
			}
			definitions.Add(new SlotDefinition(id, definitions.Count, label, filter, active, "custom"));
			if (LocalInventory != null)
			{
				InventoryRules.EnsureHeight(LocalInventory);
			}
			return true;
		}

		public static SlotDefinition FindSlot(string id)
		{
			return definitions.Find((SlotDefinition slot) => slot.ID == id);
		}

		public static SlotDefinition[] GetSlots()
		{
			return definitions.ToArray();
		}

		public static SlotDefinition[] GetAmmoSlots()
		{
			return definitions.Where((SlotDefinition slot) => slot.IsAmmoSlot).ToArray();
		}

		public static SlotDefinition[] GetMiscSlots()
		{
			return definitions.Where((SlotDefinition slot) => slot.IsMiscSlot).ToArray();
		}

		public static int GetInventoryHeightPlayer()
		{
			return 5;
		}

		public static ItemData[] GetFoodSlotsItems()
		{
			return (from slot in definitions
				where slot.IsFoodSlot
				select slot.Item).ToArray();
		}

		public static ItemData[] GetAllSlotItems()
		{
			return (from slot in definitions
				select slot.Item into item
				where item != null
				select item).ToArray();
		}

		public static bool IsItemInSlot(ItemData item)
		{
			if (item != null)
			{
				return definitions.Any((SlotDefinition slot) => slot.Item == item);
			}
			return false;
		}

		internal static SlotDefinition At(Inventory inventory, GridCell position)
		{
			return definitions.Find(delegate(SlotDefinition slot)
			{
				GridCell gridCell = slot.PositionFor(inventory);
				return gridCell.x == position.x && gridCell.y == position.y;
			});
		}

		internal static int RequiredHeight(Inventory inventory)
		{
			return 5 + (definitions.Count + inventory.GetWidth() - 1) / inventory.GetWidth();
		}
	}
	public static class PlayerInventoryOperations
	{
		public static bool MoveToSlot(ItemData item, SlotDefinition slot)
		{
			Inventory localInventory = API.LocalInventory;
			if (localInventory == null || slot == null || !localInventory.ContainsItem(item) || !slot.ItemFits(item))
			{
				return false;
			}
			GridCell cell = slot.PositionFor(localInventory);
			ItemData itemAt = localInventory.GetItemAt(cell.x, cell.y);
			if (itemAt == item)
			{
				return true;
			}
			if (itemAt != null)
			{
				return false;
			}
			PositionCodec.Set(item, cell);
			InventoryRules.Notify(localInventory);
			return true;
		}
	}
	public static class CellPlanner
	{
		public static int[] Assign(int width, int regularRows, int[] currentCells, int[][] allowedSpecialCells, int[] reservedCells)
		{
			if (width <= 0 || regularRows <= 0 || currentCells.Length != allowedSpecialCells.Length)
			{
				throw new ArgumentException("Invalid inventory geometry.");
			}
			HashSet<int> hashSet = new HashSet<int>();
			HashSet<int> hashSet2 = new HashSet<int>(reservedCells);
			int[] array = Enumerable.Repeat(-1, currentCells.Length).ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				if (allowedSpecialCells[i].Contains(currentCells[i]) && hashSet.Add(currentCells[i]))
				{
					array[i] = currentCells[i];
				}
			}
			for (int j = 0; j < array.Length; j++)
			{
				if (array[j] < 0 && currentCells[j] >= 0 && currentCells[j] < width * regularRows && !hashSet2.Contains(currentCells[j]) && hashSet.Add(currentCells[j]))
				{
					array[j] = currentCells[j];
				}
			}
			for (int k = 0; k < array.Length; k++)
			{
				if (array[k] >= 0)
				{
					continue;
				}
				int[] array2 = allowedSpecialCells[k];
				foreach (int num in array2)
				{
					if (num >= 0 && hashSet.Add(num))
					{
						array[k] = num;
						break;
					}
				}
				if (array[k] < 0)
				{
					int m;
					for (m = 0; hashSet.Contains(m) || hashSet2.Contains(m); m++)
					{
					}
					hashSet.Add(m);
					array[k] = m;
				}
			}
			return array;
		}
	}
	internal struct GridCell
	{
		internal int x;

		internal int y;

		internal GridCell(int x, int y)
		{
			this.x = x;
			this.y = y;
		}
	}
	internal static class PositionCodec
	{
		internal static readonly Type PositionType = AccessTools.TypeByName("Vector2i");

		private static readonly FieldInfo x = AccessTools.Field(PositionType, "x");

		private static readonly FieldInfo y = AccessTools.Field(PositionType, "y");

		private static readonly FieldInfo itemPosition = AccessTools.Field(typeof(ItemData), "m_gridPos");

		internal static object Box(GridCell cell)
		{
			object obj = Activator.CreateInstance(PositionType);
			x.SetValue(obj, cell.x);
			y.SetValue(obj, cell.y);
			return obj;
		}

		internal static GridCell Read(object value)
		{
			return new GridCell((int)x.GetValue(value), (int)y.GetValue(value));
		}

		internal static GridCell Get(ItemData item)
		{
			return Read(itemPosition.GetValue(item));
		}

		internal static void Set(ItemData item, GridCell cell)
		{
			itemPosition.SetValue(item, Box(cell));
		}
	}
}