Decompiled source of Station Tasks v1.1.0

plugins/StationTasks.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BetrValheim.Drawers;
using HarmonyLib;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("StationTasks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("StationTasks")]
[assembly: AssemblyTitle("StationTasks")]
[assembly: AssemblyVersion("1.1.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 StationTasks
{
	[BepInPlugin("local.valheim.stationtasks", "Station Tasks", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Id = "local.valheim.stationtasks";

		internal static Plugin Instance;

		internal static bool InRefill;

		internal static StationHandle Current;

		private static Func<Vector3, Vector3, string, bool> usableMaterial;

		private static bool reportedError;

		private Harmony harmony;

		internal ConfigEntry<KeyCode> Modifier;

		internal ConfigEntry<float> DefaultRadius;

		internal TaskWindow Window;

		private void Awake()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Modifier = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "Task modifier", (KeyCode)306, "Hold this key while interacting with a production station to configure its task.");
			DefaultRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Defaults", "Stock radius", 20f, new ConfigDescription("Starting stock-count radius for a new task. Each station can override this.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f), Array.Empty<object>()));
			harmony = new Harmony("local.valheim.stationtasks");
			try
			{
				Assembly assembly = typeof(Drawer).Assembly;
				Type type = assembly.GetType("BetrValheim.Refill.Refiller", throwOnError: true);
				StockCounter.Initialize(assembly);
				usableMaterial = AccessTools.MethodDelegate<Func<Vector3, Vector3, string, bool>>(Required(type, "IsUsableMaterial"), (object)null, true);
				Patch(Required(type, "Tick"), "BeginTick", null, "EndTick");
				Patch(Required(type, "ResetPassDiagnostics"), null, "BeginPass");
				Patch(Required(type, "Mine"), null, "SelectStation");
				Type[] array = new Type[3]
				{
					typeof(Smelter),
					typeof(CookingStation),
					typeof(Fermenter)
				};
				foreach (Type type2 in array)
				{
					Patch(Required(type, "PickMaterial", new Type[3]
					{
						typeof(Vector3),
						typeof(Vector3),
						type2
					}), "PickMaterial");
					Patch(Required(type2, "Awake"), null, "StationAwake");
				}
				Patch(Required(type, "TryTake"), "BeforeTake", "AfterTake");
				Patch(Required(typeof(Player), "Interact", new Type[3]
				{
					typeof(GameObject),
					typeof(bool),
					typeof(bool)
				}), "Interact");
				string[] array2 = new string[3] { "OnHoverAddOre", "OnHoverAddFuel", "OnHoverEmptyOre" };
				foreach (string name in array2)
				{
					Patch(Required(typeof(Smelter), name), null, "Hover");
				}
				array2 = new string[2] { "GetHoverText", "OnHoverFuelSwitch" };
				foreach (string name2 in array2)
				{
					Patch(Required(typeof(CookingStation), name2), null, "Hover");
				}
				Patch(Required(typeof(Fermenter), "GetHoverText"), null, "Hover");
				Window = ((Component)this).gameObject.AddComponent<TaskWindow>();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Station Tasks ready. Hold " + ((object)Modifier.Value/*cast due to .constrained prefix*/).ToString() + " and interact with a production station."));
			}
			catch (Exception ex)
			{
				harmony.UnpatchSelf();
				((BaseUnityPlugin)this).Logger.LogError((object)("Station Tasks could not integrate with this BetrValheim version; no hooks remain installed. " + ex));
			}
		}

		private static MethodInfo Required(Type type, string name, Type[] args = null)
		{
			return AccessTools.Method(type, name, args, (Type[])null) ?? throw new MissingMethodException(type.FullName, name);
		}

		private void Patch(MethodInfo method, string prefix = null, string postfix = null, string finalizer = null)
		{
			harmony.Patch((MethodBase)method, Hook(prefix), Hook(postfix), (HarmonyMethod)null, Hook(finalizer), (HarmonyMethod)null);
			static HarmonyMethod Hook(string name)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Expected O, but got Unknown
				if (name != null)
				{
					return new HarmonyMethod(typeof(Plugin), name, (Type[])null);
				}
				return null;
			}
		}

		private void OnDestroy()
		{
			if (Object.op_Implicit((Object)(object)Window))
			{
				Window.Close();
			}
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		private static void BeginTick()
		{
			InRefill = true;
			Current = null;
		}

		private static void EndTick()
		{
			InRefill = false;
			Current = null;
		}

		private static void BeginPass()
		{
			StockCounter.BeginPass();
		}

		private static void StationAwake(Component __instance)
		{
			StationHandle.Attach(__instance);
		}

		private static void SelectStation(ZNetView nview, bool __result)
		{
			if (InRefill)
			{
				Current = ((__result && Object.op_Implicit((Object)(object)nview)) ? ((Component)nview).GetComponent<StationHandle>() : null);
			}
		}

		private static bool PickMaterial(Vector3 playerPosition, Vector3 station, ref string __result)
		{
			//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)
			if (!InRefill || !Object.op_Implicit((Object)(object)Current))
			{
				return true;
			}
			__result = null;
			try
			{
				TaskRule rule = Current.Rule;
				ProductionRecipe productionRecipe = ((rule == null) ? null : Current.Recipe(rule.Input));
				if (StockCounter.CanAdd(Current, rule, productionRecipe) && usableMaterial(playerPosition, station, productionRecipe.Input))
				{
					__result = productionRecipe.Input;
				}
			}
			catch (Exception error)
			{
				Report(error);
			}
			return false;
		}

		private static bool BeforeTake(Vector3 playerPosition, Vector3 station, string prefabName, ref bool __result, out ProductionRecipe __state)
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			__state = null;
			if (!InRefill || !Object.op_Implicit((Object)(object)Current) || !Current.Valid)
			{
				return true;
			}
			bool flag = Current.Fuel == prefabName;
			if (!flag)
			{
				__state = Current.Recipe(prefabName);
			}
			try
			{
				TaskRule rule = Current.Rule;
				ProductionRecipe productionRecipe = ((rule == null) ? null : Current.Recipe(rule.Input));
				if ((!flag) ? (prefabName == rule?.Input && StockCounter.CanAdd(Current, rule, productionRecipe)) : RefillPolicy.AllowFuel(rule, productionRecipe != null, Current.NeedsFuel(), StockCounter.CanAdd(Current, rule, productionRecipe) && usableMaterial(playerPosition, station, productionRecipe.Input)))
				{
					return true;
				}
			}
			catch (Exception error)
			{
				Report(error);
			}
			__result = false;
			return false;
		}

		private static void AfterTake(bool __result, ProductionRecipe __state)
		{
			if (__result && InRefill && Object.op_Implicit((Object)(object)Current) && __state != null)
			{
				StockCounter.Reserve(Current, __state);
			}
		}

		private static void Report(Exception error)
		{
			if (!reportedError)
			{
				reportedError = true;
				((BaseUnityPlugin)Instance).Logger.LogError((object)("A station task check failed. Pulling for the affected task is stopped. " + error));
			}
		}

		private static bool Interact(Player __instance, GameObject go, bool hold)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || !Object.op_Implicit((Object)(object)Instance.Window))
			{
				return true;
			}
			if (Instance.Window.IsOpen)
			{
				return false;
			}
			if (!Input.GetKey(Instance.Modifier.Value))
			{
				return true;
			}
			StationHandle stationHandle = StationHandle.Find(go);
			if (!Object.op_Implicit((Object)(object)stationHandle) || !stationHandle.Valid || stationHandle.Recipes.Count == 0)
			{
				return true;
			}
			if (!hold && stationHandle.MayEdit())
			{
				Instance.Window.Open(stationHandle);
			}
			return false;
		}

		private static void Hover(Component __instance, ref string __result)
		{
			//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)
			StationHandle component = __instance.GetComponent<StationHandle>();
			if (Object.op_Implicit((Object)(object)component) && component.Valid && component.Recipes.Count != 0)
			{
				TaskRule rule = component.Rule;
				string text = "Idle (target 0) — configure task";
				if (component.HasTask)
				{
					ProductionRecipe productionRecipe = ((rule == null) ? null : component.Recipe(rule.Input));
					text = ((productionRecipe == null) ? "Invalid task — edit or reset" : (((rule.Target == 0) ? "Idle: " : (rule.Paused ? "Paused: " : "Maintain: ")) + ProductionRecipe.Local(productionRecipe.To.m_itemData.m_shared.m_name) + " ×" + rule.Target));
				}
				__result = __result + "\n<color=#ffd479>[" + ((object)Instance.Modifier.Value/*cast due to .constrained prefix*/).ToString() + " + Use]</color> " + text;
			}
		}
	}
	public sealed class ProductionRecipe
	{
		public ItemDrop From;

		public ItemDrop To;

		public int Amount;

		public string Input => ((Object)From).name;

		public string Output => ((Object)To).name;

		public string Label => Local(From.m_itemData.m_shared.m_name) + " → " + Local(To.m_itemData.m_shared.m_name) + ((Amount > 1) ? (" ×" + Amount) : "");

		public static string Local(string value)
		{
			if (Localization.instance == null)
			{
				return value;
			}
			return Localization.instance.Localize(value);
		}
	}
	public sealed class StationHandle : MonoBehaviour
	{
		public const string TaskKey = "codex_station_tasks_v1";

		internal static readonly List<StationHandle> All = new List<StationHandle>();

		private static readonly FieldInfo DelayedTap = AccessTools.Field(typeof(Fermenter), "m_delayedTapItem");

		public ZNetView View;

		public Smelter Smelter;

		public CookingStation Cooker;

		public Fermenter Fermenter;

		public readonly List<ProductionRecipe> Recipes = new List<ProductionRecipe>();

		private string cachedValue;

		private TaskRule cachedRule;

		public string Title => ProductionRecipe.Local(Object.op_Implicit((Object)(object)Smelter) ? Smelter.m_name : (Object.op_Implicit((Object)(object)Cooker) ? Cooker.m_name : Fermenter.m_name));

		public bool Valid
		{
			get
			{
				if (Object.op_Implicit((Object)(object)View))
				{
					return View.IsValid();
				}
				return false;
			}
		}

		public bool HasTask
		{
			get
			{
				if (Valid)
				{
					return !string.IsNullOrEmpty(View.GetZDO().GetString("codex_station_tasks_v1", ""));
				}
				return false;
			}
		}

		public TaskRule Rule
		{
			get
			{
				string text = (Valid ? View.GetZDO().GetString("codex_station_tasks_v1", "") : "");
				if (text != cachedValue)
				{
					cachedValue = text;
					TaskRule.TryDecode(text, out cachedRule);
				}
				return cachedRule;
			}
		}

		public string Fuel
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)Smelter) || !Object.op_Implicit((Object)(object)Smelter.m_fuelItem))
				{
					if (!Object.op_Implicit((Object)(object)Cooker) || !Cooker.m_useFuel || !Object.op_Implicit((Object)(object)Cooker.m_fuelItem))
					{
						return null;
					}
					return ((Object)Cooker.m_fuelItem).name;
				}
				return ((Object)Smelter.m_fuelItem).name;
			}
		}

		private void Awake()
		{
			View = ((Component)this).GetComponent<ZNetView>();
			Smelter = ((Component)this).GetComponent<Smelter>();
			Cooker = ((Component)this).GetComponent<CookingStation>();
			Fermenter = ((Component)this).GetComponent<Fermenter>();
			if (Object.op_Implicit((Object)(object)Smelter))
			{
				foreach (ItemConversion item in Smelter.m_conversion)
				{
					Add(item.m_from, item.m_to, 1);
				}
			}
			if (Object.op_Implicit((Object)(object)Cooker))
			{
				foreach (ItemConversion item2 in Cooker.m_conversion)
				{
					Add(item2.m_from, item2.m_to, 1);
				}
			}
			if (Object.op_Implicit((Object)(object)Fermenter))
			{
				foreach (ItemConversion item3 in Fermenter.m_conversion)
				{
					Add(item3.m_from, item3.m_to, item3.m_producedItems);
				}
			}
			All.Add(this);
		}

		private void Add(ItemDrop from, ItemDrop to, int amount)
		{
			if (Object.op_Implicit((Object)(object)from) && Object.op_Implicit((Object)(object)to) && amount > 0 && !Recipes.Any((ProductionRecipe r) => r.Input == ((Object)from).name))
			{
				Recipes.Add(new ProductionRecipe
				{
					From = from,
					To = to,
					Amount = amount
				});
			}
		}

		private void OnDestroy()
		{
			All.Remove(this);
		}

		public ProductionRecipe Recipe(string input)
		{
			return Recipes.Find((ProductionRecipe r) => r.Input == input);
		}

		public static StationHandle Find(GameObject go)
		{
			if (!Object.op_Implicit((Object)(object)go))
			{
				return null;
			}
			StationHandle componentInParent = go.GetComponentInParent<StationHandle>();
			if (Object.op_Implicit((Object)(object)componentInParent))
			{
				return componentInParent;
			}
			Component componentInParent2 = (Component)(object)go.GetComponentInParent<Smelter>();
			if (!Object.op_Implicit((Object)(object)componentInParent2))
			{
				componentInParent2 = (Component)(object)go.GetComponentInParent<CookingStation>();
			}
			if (!Object.op_Implicit((Object)(object)componentInParent2))
			{
				componentInParent2 = (Component)(object)go.GetComponentInParent<Fermenter>();
			}
			if (!Object.op_Implicit((Object)(object)componentInParent2))
			{
				return null;
			}
			return Attach(componentInParent2);
		}

		public static StationHandle Attach(Component station)
		{
			return station.GetComponent<StationHandle>() ?? station.gameObject.AddComponent<StationHandle>();
		}

		public bool MayEdit()
		{
			//IL_0024: 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_0039: 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)
			Player localPlayer = Player.m_localPlayer;
			if (Valid && Object.op_Implicit((Object)(object)localPlayer) && !((Character)localPlayer).IsDead())
			{
				Vector3 val = ((Component)localPlayer).transform.position - ((Component)this).transform.position;
				if (((Vector3)(ref val)).sqrMagnitude <= 100f)
				{
					return PrivateArea.CheckAccess(((Component)this).transform.position, 0f, false, false);
				}
			}
			return false;
		}

		public bool Save(TaskRule rule)
		{
			if (!MayEdit() || (rule != null && Recipe(rule.Input) == null))
			{
				return false;
			}
			View.ClaimOwnership();
			if (!View.IsOwner())
			{
				return false;
			}
			View.GetZDO().Set("codex_station_tasks_v1", rule?.Encode() ?? "");
			StockCounter.Invalidate();
			return true;
		}

		public long Queued(string output)
		{
			if (!Valid)
			{
				return 0L;
			}
			ZDO zDO = View.GetZDO();
			long num = 0L;
			if (Object.op_Implicit((Object)(object)Smelter))
			{
				int num2 = zDO.GetInt(ZDOVars.s_queued, 0);
				for (int i = 0; i < num2; i++)
				{
					if (Recipe(zDO.GetString("item" + i, ""))?.Output == output)
					{
						num++;
					}
				}
				if (Recipe(zDO.GetString(ZDOVars.s_spawnOre, ""))?.Output == output)
				{
					num += zDO.GetInt(ZDOVars.s_spawnAmount, 0);
				}
			}
			if (Object.op_Implicit((Object)(object)Cooker))
			{
				for (int j = 0; j < Cooker.m_slots.Length; j++)
				{
					if (zDO.GetInt("slotstatus" + j, 0) != 2)
					{
						string text = zDO.GetString("slot" + j, "");
						if (text == output || Recipe(text)?.Output == output)
						{
							num++;
						}
					}
				}
			}
			if (Object.op_Implicit((Object)(object)Fermenter))
			{
				int num3 = zDO.GetInt(ZDOVars.s_content, 0);
				int num4 = (((MonoBehaviour)Fermenter).IsInvoking("DelayedTap") ? ((int)DelayedTap.GetValue(Fermenter)) : 0);
				foreach (ProductionRecipe recipe in Recipes)
				{
					if (recipe.Output == output)
					{
						int stableHashCode = StringExtensionMethods.GetStableHashCode(recipe.Input);
						if (stableHashCode == num3)
						{
							num += recipe.Amount;
						}
						if (stableHashCode == num4)
						{
							num += recipe.Amount;
						}
					}
				}
			}
			return num;
		}

		public bool NeedsFuel()
		{
			if (!Valid)
			{
				return false;
			}
			ZDO zDO = View.GetZDO();
			if (Object.op_Implicit((Object)(object)Smelter))
			{
				return zDO.GetInt(ZDOVars.s_queued, 0) > 0;
			}
			if (Object.op_Implicit((Object)(object)Cooker))
			{
				for (int i = 0; i < Cooker.m_slots.Length; i++)
				{
					if (!string.IsNullOrEmpty(zDO.GetString("slot" + i, "")) && zDO.GetInt("slotstatus" + i, 0) == 0)
					{
						return true;
					}
				}
			}
			return false;
		}
	}
	public static class StockCounter
	{
		private static Func<List<Container>> containers;

		private static Func<List<Drawer>> drawers;

		private static Func<Container, bool> mayOpen;

		private static Func<List<ItemDrop>> groundItems;

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

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

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

		public static void Initialize(Assembly assembly)
		{
			Type type = assembly.GetType("BetrValheim.Core.ContainerIndex", throwOnError: true);
			FieldInfo field = AccessTools.Field(type, "Known") ?? throw new MissingFieldException("ContainerIndex.Known");
			containers = () => (List<Container>)field.GetValue(null);
			mayOpen = AccessTools.MethodDelegate<Func<Container, bool>>(AccessTools.Method(type, "PlayerMayOpen", (Type[])null, (Type[])null), (object)null, true);
			drawers = AccessTools.MethodDelegate<Func<List<Drawer>>>(AccessTools.PropertyGetter(assembly.GetType("BetrValheim.Drawers.DrawerIndex", throwOnError: true), "All"), (object)null, true);
			FieldInfo groundField = AccessTools.Field(typeof(ItemDrop), "s_instances") ?? throw new MissingFieldException("ItemDrop.s_instances");
			groundItems = () => (List<ItemDrop>)groundField.GetValue(null);
		}

		public static void Invalidate()
		{
			Stored.Clear();
			Baseline.Clear();
			Reserved.Clear();
		}

		public static void BeginPass()
		{
			Invalidate();
			foreach (StationHandle item in StationHandle.All)
			{
				if (!Object.op_Implicit((Object)(object)item) || !item.Valid)
				{
					continue;
				}
				foreach (ProductionRecipe recipe in item.Recipes)
				{
					(int, string) key = (((Object)item).GetInstanceID(), recipe.Output);
					if (!Baseline.ContainsKey(key))
					{
						Baseline[key] = item.Queued(recipe.Output);
					}
				}
			}
		}

		public static void Reserve(StationHandle station, ProductionRecipe recipe)
		{
			(int, string) key = (((Object)station).GetInstanceID(), recipe.Output);
			Reserved.TryGetValue(key, out var value);
			Reserved[key] = value + recipe.Amount;
		}

		public static long CountStored(StationHandle station, ProductionRecipe recipe, float radius, bool cache)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: 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_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			(int, string) key = (((Object)station).GetInstanceID(), recipe.Output);
			if (cache && Stored.TryGetValue(key, out var value))
			{
				return value;
			}
			Vector3 position = ((Component)station).transform.position;
			float num = radius * radius;
			long num2 = 0L;
			Vector3 val;
			foreach (Container item in containers())
			{
				if (!Object.op_Implicit((Object)(object)item))
				{
					continue;
				}
				val = ((Component)item).transform.position - position;
				if (((Vector3)(ref val)).sqrMagnitude > num || !mayOpen(item))
				{
					continue;
				}
				Inventory inventory = item.GetInventory();
				if (inventory == null)
				{
					continue;
				}
				foreach (ItemData allItem in inventory.GetAllItems())
				{
					if (Object.op_Implicit((Object)(object)allItem.m_dropPrefab) && ((Object)allItem.m_dropPrefab).name == recipe.Output)
					{
						num2 += allItem.m_stack;
					}
				}
			}
			foreach (Drawer item2 in drawers())
			{
				if (Object.op_Implicit((Object)(object)item2))
				{
					val = ((Component)item2).transform.position - position;
					if (((Vector3)(ref val)).sqrMagnitude <= num && PrivateArea.CheckAccess(((Component)item2).transform.position, 0f, false, false) && item2.ItemName == recipe.Output)
					{
						num2 += item2.Count;
					}
				}
			}
			foreach (ItemDrop item3 in groundItems())
			{
				if (Object.op_Implicit((Object)(object)item3))
				{
					val = ((Component)item3).transform.position - position;
					if (((Vector3)(ref val)).sqrMagnitude <= num && item3.m_itemData != null && Utils.GetPrefabName(((Component)item3).gameObject) == recipe.Output)
					{
						num2 += item3.m_itemData.m_stack;
					}
				}
			}
			if (cache)
			{
				Stored[key] = num2;
			}
			return num2;
		}

		public static long CountQueued(StationHandle station, ProductionRecipe recipe, float radius, bool reservations)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			long num = 0L;
			float num2 = radius * radius;
			foreach (StationHandle item in StationHandle.All)
			{
				if (!Object.op_Implicit((Object)(object)item) || !item.Valid)
				{
					continue;
				}
				Vector3 val = ((Component)item).transform.position - ((Component)station).transform.position;
				if (!(((Vector3)(ref val)).sqrMagnitude > num2))
				{
					long num3 = item.Queued(recipe.Output);
					(int, string) key = (((Object)item).GetInstanceID(), recipe.Output);
					if (reservations && Baseline.TryGetValue(key, out var value))
					{
						Reserved.TryGetValue(key, out var value2);
						num3 = QueueMath.Projected(num3, value, value2);
					}
					num += num3;
				}
			}
			return num;
		}

		public static bool CanAdd(StationHandle station, TaskRule rule, ProductionRecipe recipe)
		{
			if (rule != null && rule.Target > 0 && !rule.Paused && recipe != null)
			{
				return rule.CanAdd(recipe.Input, CountStored(station, recipe, rule.Radius, cache: true), CountQueued(station, recipe, rule.Radius, reservations: true), recipe.Amount);
			}
			return false;
		}
	}
	public sealed class TaskRule
	{
		public string Input;

		public int Target;

		public float Radius;

		public bool Paused;

		public string Encode()
		{
			return string.Join("|", "1", Input, Target.ToString(CultureInfo.InvariantCulture), Radius.ToString(CultureInfo.InvariantCulture), Paused ? "1" : "0");
		}

		public static bool TryDecode(string value, out TaskRule rule)
		{
			rule = null;
			if (string.IsNullOrEmpty(value))
			{
				return false;
			}
			string[] array = value.Split(new char[1] { '|' });
			if (array.Length != 5 || array[0] != "1" || string.IsNullOrWhiteSpace(array[1]) || !int.TryParse(array[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || !float.TryParse(array[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) || result < 0 || result > 1000000 || float.IsNaN(result2) || float.IsInfinity(result2) || result2 < 1f || result2 > 200f || (array[4] != "0" && array[4] != "1"))
			{
				return false;
			}
			rule = new TaskRule
			{
				Input = array[1],
				Target = result,
				Radius = result2,
				Paused = (array[4] == "1")
			};
			return true;
		}

		public bool CanAdd(string input, long stored, long queued, int batchSize)
		{
			if (!Paused && input == Input && batchSize > 0)
			{
				return Math.Max(0L, stored) + Math.Max(0L, queued) + batchSize <= Target;
			}
			return false;
		}
	}
	public static class RefillPolicy
	{
		public static bool AllowFuel(TaskRule rule, bool hasRecipe, bool loadedWork, bool canStart)
		{
			if (rule != null && rule.Target > 0 && hasRecipe)
			{
				return loadedWork || canStart;
			}
			return false;
		}
	}
	public static class QueueMath
	{
		public static long Projected(long observed, long baseline, long reserved)
		{
			return Math.Max(observed, baseline + reserved);
		}
	}
	public sealed class TaskWindow : MonoBehaviour
	{
		private const float Width = 860f;

		private const float Height = 652f;

		private static readonly Vector2 TopLeft = new Vector2(0f, 1f);

		private StationHandle station;

		private int selected;

		private GameObject root;

		private RectTransform panel;

		private InputField targetField;

		private InputField radiusField;

		private Toggle pauseToggle;

		private Text stockText;

		private Text queueText;

		private Text feedback;

		private Text stateText;

		private Text batchText;

		private Text saveText;

		private Button saveButton;

		private readonly List<Button> recipeButtons = new List<Button>();

		private readonly List<Image> recipeMarkers = new List<Image>();

		private float nextStatus;

		private GUIManager Gui => GUIManager.Instance;

		private Color Gold => Gui.ValheimOrange;

		private Color Beige => Gui.ValheimBeige;

		public bool IsOpen { get; private set; }

		public void Open(StationHandle value)
		{
			Close();
			if (!Object.op_Implicit((Object)(object)GUIManager.CustomGUIFront) || value.Recipes.Count == 0)
			{
				return;
			}
			station = value;
			TaskRule rule = station.Rule;
			selected = ((rule != null) ? Math.Max(0, station.Recipes.FindIndex((ProductionRecipe r) => r.Input == rule.Input)) : 0);
			try
			{
				Build(rule);
				IsOpen = true;
				GUIManager.BlockInput(true);
				RefreshSelection();
				nextStatus = 0f;
			}
			catch
			{
				Close();
				throw;
			}
		}

		public void Close()
		{
			if (IsOpen)
			{
				GUIManager.BlockInput(false);
			}
			IsOpen = false;
			if (Object.op_Implicit((Object)(object)root))
			{
				root.SetActive(false);
				Object.Destroy((Object)(object)root);
			}
			root = null;
			station = null;
			recipeButtons.Clear();
			recipeMarkers.Clear();
		}

		private void OnDestroy()
		{
			Close();
		}

		private void Build(TaskRule rule)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0067: 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)
			//IL_0082: 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_0089: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: 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_022a: 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_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			//IL_044f: Unknown result type (might be due to invalid IL or missing references)
			//IL_047d: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ec: 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_05d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0603: Unknown result type (might be due to invalid IL or missing references)
			//IL_0636: Unknown result type (might be due to invalid IL or missing references)
			//IL_0674: Unknown result type (might be due to invalid IL or missing references)
			//IL_0753: Unknown result type (might be due to invalid IL or missing references)
			root = new GameObject("StationTasks", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			root.transform.SetParent(GUIManager.CustomGUIFront.transform, false);
			root.transform.SetAsLastSibling();
			RectTransform component = root.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			Vector2 offsetMin = (component.offsetMax = Vector2.zero);
			component.offsetMin = offsetMin;
			((Graphic)root.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.58f);
			panel = Gui.CreateWoodpanel(root.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 860f, 652f, false).GetComponent<RectTransform>();
			((Object)((Component)panel).gameObject).name = "StationTaskWoodPanel";
			Label((Transform)(object)panel, station.Title, 32f, 20f, 714f, 48f, 36, Gold, Gui.NorseBold);
			Label((Transform)(object)panel, "STATION TASK", 34f, 75f, 440f, 26f, 19, Beige);
			stateText = Label((Transform)(object)panel, "IDLE", 624f, 75f, 188f, 26f, 19, Gold);
			stateText.alignment = (TextAnchor)5;
			MakeButton((Transform)(object)panel, "×", 790f, 25f, 40f, 36f, Close);
			Fill((Transform)(object)panel, 30f, 111f, 800f, 1f, new Color(0.85f, 0.64f, 0.3f, 0.55f));
			Fill((Transform)(object)panel, 407f, 128f, 1f, 376f, new Color(0.85f, 0.64f, 0.3f, 0.25f));
			Label((Transform)(object)panel, "RECIPE", 34f, 128f, 344f, 26f, 20, Gold);
			BuildRecipeList();
			Label((Transform)(object)panel, "KEEP IN STOCK", 434f, 128f, 374f, 26f, 20, Gold);
			targetField = MakeInput("Target", 434f, 163f, 210f, 52f, (ContentType)2, (rule?.Target ?? 0).ToString(CultureInfo.InvariantCulture), 7, 26);
			Label((Transform)(object)panel, "finished items", 659f, 172f, 157f, 32f, 18, Beige);
			Label((Transform)(object)panel, "0 keeps this station idle. Set a target to start production.", 434f, 224f, 382f, 46f, 17, Beige);
			Label((Transform)(object)panel, "Stock radius", 434f, 279f, 234f, 32f, 20, Beige);
			radiusField = MakeInput("Radius", 679f, 273f, 99f, 42f, (ContentType)3, (rule?.Radius ?? Plugin.Instance.DefaultRadius.Value).ToString(CultureInfo.InvariantCulture), 6, 21);
			Label((Transform)(object)panel, "m", 790f, 280f, 30f, 30f, 19, Beige);
			Fill((Transform)(object)panel, 430f, 330f, 392f, 80f, new Color(0f, 0f, 0f, 0.3f));
			Label((Transform)(object)panel, "Available nearby", 444f, 339f, 250f, 28f, 18, Beige);
			stockText = Label((Transform)(object)panel, "—", 700f, 339f, 108f, 28f, 22, Gold);
			stockText.alignment = (TextAnchor)5;
			Label((Transform)(object)panel, "In production", 444f, 375f, 250f, 28f, 18, Beige);
			queueText = Label((Transform)(object)panel, "—", 700f, 375f, 108f, 28f, 22, Gold);
			queueText.alignment = (TextAnchor)5;
			GameObject val = Gui.CreateToggle((Transform)(object)panel, 26f, 26f);
			Place(val.GetComponent<RectTransform>(), 434f, 429f, 26f, 26f);
			pauseToggle = val.GetComponent<Toggle>();
			Text componentInChildren = val.GetComponentInChildren<Text>();
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				componentInChildren.text = "";
			}
			pauseToggle.SetIsOnWithoutNotify(rule?.Paused ?? false);
			Label((Transform)(object)panel, "Pause new production", 473f, 426f, 344f, 34f, 19, Beige);
			batchText = Label((Transform)(object)panel, "", 434f, 470f, 380f, 44f, 16, Beige);
			Label((Transform)(object)panel, "Choose the item this station will make.", 34f, 505f, 350f, 28f, 16, Beige);
			feedback = Label((Transform)(object)panel, "", 34f, 535f, 790f, 24f, 16, new Color(1f, 0.56f, 0.38f));
			MakeButton((Transform)(object)panel, "Reset to idle", 32f, 571f, 210f, 44f, ResetTask);
			saveButton = MakeButton((Transform)(object)panel, "Save as idle", 433f, 571f, 195f, 44f, Save);
			saveText = ((Component)saveButton).GetComponentInChildren<Text>();
			MakeButton((Transform)(object)panel, "Cancel", 646f, 571f, 182f, 44f, Close);
			Label((Transform)(object)panel, "Ctrl + Use to configure  ·  Escape to close", 32f, 623f, 796f, 22f, 15, Beige).alignment = (TextAnchor)4;
			((UnityEvent<string>)(object)targetField.onValueChanged).AddListener((UnityAction<string>)delegate
			{
				RefreshDraft();
			});
			((UnityEvent<string>)(object)radiusField.onValueChanged).AddListener((UnityAction<string>)delegate
			{
				nextStatus = 0f;
				RefreshDraft();
			});
			((UnityEvent<bool>)(object)pauseToggle.onValueChanged).AddListener((UnityAction<bool>)delegate
			{
				RefreshDraft();
			});
			Canvas.ForceUpdateCanvases();
			FitToScreen();
		}

		private void BuildRecipeList()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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_00fe: 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_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = DefaultControls.CreateScrollView(default(Resources));
			((Object)obj).name = "Recipes";
			obj.transform.SetParent((Transform)(object)panel, false);
			Place(obj.GetComponent<RectTransform>(), 32f, 163f, 358f, 334f);
			ScrollRect component = obj.GetComponent<ScrollRect>();
			component.horizontal = false;
			component.movementType = (MovementType)2;
			((Component)component.horizontalScrollbar).gameObject.SetActive(false);
			component.horizontalScrollbar = null;
			component.verticalScrollbarVisibility = (ScrollbarVisibility)2;
			Gui.ApplyScrollRectStyle(component);
			component.content.anchorMin = new Vector2(0f, 1f);
			component.content.anchorMax = new Vector2(1f, 1f);
			component.content.pivot = TopLeft;
			component.content.anchoredPosition = Vector2.zero;
			component.content.sizeDelta = new Vector2(0f, (float)(station.Recipes.Count * 70 + 8));
			for (int i = 0; i < station.Recipes.Count; i++)
			{
				int index = i;
				ProductionRecipe productionRecipe = station.Recipes[i];
				Button val = MakeButton((Transform)(object)component.content, "", 4f, 4 + i * 70, 330f, 64f, delegate
				{
					selected = index;
					RefreshSelection();
				});
				recipeButtons.Add(val);
				Image item = Fill(((Component)val).transform, 2f, 3f, 3f, 58f, Gold);
				recipeMarkers.Add(item);
				Image obj2 = Fill(((Component)val).transform, 12f, 12f, 40f, 40f, Color.white);
				obj2.sprite = productionRecipe.To.m_itemData.GetIcon();
				obj2.preserveAspect = true;
				Label(((Component)val).transform, ProductionRecipe.Local(productionRecipe.To.m_itemData.m_shared.m_name), 64f, 6f, 254f, 28f, 20, Gold);
				Label(((Component)val).transform, "From " + ProductionRecipe.Local(productionRecipe.From.m_itemData.m_shared.m_name), 64f, 33f, 254f, 25f, 16, Beige);
			}
			component.verticalNormalizedPosition = 1f;
		}

		private void RefreshSelection()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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)
			for (int i = 0; i < recipeButtons.Count; i++)
			{
				ColorBlock valheimButtonColorBlock = Gui.ValheimButtonColorBlock;
				if (i == selected)
				{
					((ColorBlock)(ref valheimButtonColorBlock)).normalColor = new Color(1f, 0.81f, 0.48f);
				}
				((Selectable)recipeButtons[i]).colors = valheimButtonColorBlock;
				((Behaviour)recipeMarkers[i]).enabled = i == selected;
			}
			ProductionRecipe productionRecipe = station.Recipes[selected];
			batchText.text = ((productionRecipe.Amount > 1) ? $"Produces {productionRecipe.Amount} per batch. A whole batch must fit below your target." : "Counts nearby storage, finished drops and queued production.");
			nextStatus = 0f;
			RefreshDraft();
		}

		private bool ReadDraft(out TaskRule rule)
		{
			return TaskRule.TryDecode("1|" + station.Recipes[selected].Input + "|" + targetField.text + "|" + radiusField.text + "|" + (pauseToggle.isOn ? "1" : "0"), out rule);
		}

		private void RefreshDraft()
		{
			TaskRule rule;
			bool flag = ReadDraft(out rule);
			((Selectable)saveButton).interactable = flag;
			feedback.text = (flag ? "" : "Enter a target from 0 to 1,000,000 and a radius from 1 to 200.");
			stateText.text = ((!flag) ? "CHECK VALUES" : ((rule.Target == 0) ? "IDLE" : (rule.Paused ? "PAUSED" : "MAINTAIN STOCK")));
			saveText.text = ((!flag) ? "Save task" : ((rule.Target == 0) ? "Save as idle" : (rule.Paused ? "Save paused" : "Start task")));
		}

		private void Save()
		{
			if (!ReadDraft(out var rule))
			{
				RefreshDraft();
			}
			else if (!station.Save(rule))
			{
				feedback.text = "Could not save. Move closer and check ward access.";
			}
			else
			{
				Close();
			}
		}

		private void ResetTask()
		{
			if (!station.Save(null))
			{
				feedback.text = "Could not reset. Move closer and check ward access.";
			}
			else
			{
				Close();
			}
		}

		private void Update()
		{
			if (!IsOpen)
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)root) || !Object.op_Implicit((Object)(object)station) || !station.MayEdit() || Input.GetKeyDown((KeyCode)27))
			{
				Close();
				return;
			}
			FitToScreen();
			if (Time.unscaledTime < nextStatus)
			{
				return;
			}
			nextStatus = Time.unscaledTime + 0.5f;
			if (!ReadDraft(out var rule))
			{
				Text obj = stockText;
				string text = (queueText.text = "—");
				obj.text = text;
				return;
			}
			ProductionRecipe recipe = station.Recipes[selected];
			try
			{
				stockText.text = StockCounter.CountStored(station, recipe, rule.Radius, cache: false).ToString();
				queueText.text = StockCounter.CountQueued(station, recipe, rule.Radius, reservations: false).ToString();
			}
			catch (Exception)
			{
				Text obj2 = stockText;
				string text = (queueText.text = "—");
				obj2.text = text;
				feedback.text = "Stock count unavailable. Automatic pulling stops if a task check fails.";
			}
		}

		private void FitToScreen()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = root.GetComponent<RectTransform>().rect;
			float num = Mathf.Min(new float[3]
			{
				1f,
				(((Rect)(ref rect)).width - 24f) / 860f,
				(((Rect)(ref rect)).height - 24f) / 652f
			});
			((Transform)panel).localScale = Vector3.one * Mathf.Max(0.2f, num);
		}

		private Text Label(Transform parent, string text, float x, float y, float width, float height, int size, Color color, Font font = null)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			Text component = Gui.CreateText(text, parent, TopLeft, TopLeft, Vector2.zero, font ?? Gui.AveriaSerifBold, size, color, true, Color.black, width, height, false).GetComponent<Text>();
			Place(((Graphic)component).rectTransform, x, y, width, height);
			component.alignment = (TextAnchor)3;
			component.horizontalOverflow = (HorizontalWrapMode)0;
			component.verticalOverflow = (VerticalWrapMode)0;
			((Graphic)component).raycastTarget = false;
			return component;
		}

		private Button MakeButton(Transform parent, string text, float x, float y, float width, float height, Action action)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_005c: Expected O, but got Unknown
			Button component = Gui.CreateButton(text, parent, TopLeft, TopLeft, Vector2.zero, width, height).GetComponent<Button>();
			Place(((Component)component).GetComponent<RectTransform>(), x, y, width, height);
			((UnityEvent)component.onClick).AddListener((UnityAction)delegate
			{
				action();
			});
			return component;
		}

		private InputField MakeInput(string name, float x, float y, float width, float height, ContentType type, string value, int limit, int size)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			InputField component = Gui.CreateInputField((Transform)(object)panel, TopLeft, TopLeft, Vector2.zero, type, "0", size, width, height).GetComponent<InputField>();
			((Object)((Component)component).gameObject).name = name;
			Place(((Component)component).GetComponent<RectTransform>(), x, y, width, height);
			component.characterLimit = limit;
			component.SetTextWithoutNotify(value);
			component.textComponent.alignment = (TextAnchor)3;
			return component;
		}

		private static Image Fill(Transform parent, float x, float y, float width, float height, Color color)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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)
			GameObject val = new GameObject("Accent", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			Place(val.GetComponent<RectTransform>(), x, y, width, height);
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = color;
			((Graphic)component).raycastTarget = false;
			return component;
		}

		private static void Place(RectTransform rect, float x, float y, float width, float height)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			Vector2 anchorMin = (rect.anchorMax = TopLeft);
			rect.anchorMin = anchorMin;
			rect.pivot = TopLeft;
			rect.anchoredPosition = new Vector2(x, 0f - y);
			rect.sizeDelta = new Vector2(width, height);
		}
	}
}