Decompiled source of StockAlert v1.2.4

StockAlert.dll

Decompiled 4 days ago
using System;
using System.Collections;
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 System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Eremite;
using Eremite.Buildings;
using Eremite.Buildings.UI;
using Eremite.Characters;
using Eremite.Characters.Villagers;
using Eremite.MapObjects;
using Eremite.MapObjects.UI;
using Eremite.Model;
using Eremite.Model.Configs;
using Eremite.Model.Effects;
using Eremite.Model.Meta;
using Eremite.Model.Orders;
using Eremite.Model.State;
using Eremite.Services;
using Eremite.Services.Monitors;
using Eremite.View;
using Eremite.View.HUD;
using Eremite.View.HUD.Conditions;
using Eremite.View.HUD.Monitors;
using Eremite.View.HUD.Perks;
using Eremite.View.HUD.Rainpunk;
using Eremite.View.HUD.TradeRoutes;
using Eremite.View.Menu.Pick;
using Eremite.View.UI;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using StockAlert.Config;
using StockAlert.Core.Models;
using StockAlert.Game;
using StockAlert.Game.Discovery;
using StockAlert.Infrastructure.Bootstrap;
using StockAlert.Infrastructure.Plugin;
using StockAlert.UI.HUD;
using StockAlert.UI.Panels;
using StockAlert.UI.World;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("StockAlert")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+d3ea5b21dc2e5f81c74dbea46e19dbb07e087adc")]
[assembly: AssemblyProduct("StockAlert")]
[assembly: AssemblyTitle("StockAlert")]
[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]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[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 StockAlert
{
	public static class StockAlertInfo
	{
		public const string Id = "com.stockalert.ats";

		public const string Name = "StockAlert";

		public const string Version = "1.2.4";
	}
}
namespace StockAlert.UI.World
{
	internal static class BuilderStatusIndicators
	{
		public readonly struct BuilderDemandCounts
		{
			public int OpenSlots { get; }

			public int ConstructionSites { get; }

			public BuilderDemandCounts(int openSlots, int constructionSites)
			{
				OpenSlots = openSlots;
				ConstructionSites = constructionSites;
			}
		}

		private sealed class BuilderIndicator
		{
			private readonly GameObject _iconObject;

			private readonly SpriteRenderer _renderer;

			private readonly Transform _transform;

			public BuilderIndicator(Villager villager)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Expected O, but got Unknown
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Expected O, but got Unknown
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
				_iconObject = new GameObject("BuilderStatusIcon");
				_renderer = _iconObject.AddComponent<SpriteRenderer>();
				((Renderer)_renderer).material = new Material(Shader.Find("Sprites/Default"));
				((Renderer)_renderer).sortingLayerName = "UI";
				((Renderer)_renderer).sortingOrder = 5000;
				_iconObject.transform.SetParent(((Component)((Actor)villager).ActorView).transform, false);
				_iconObject.transform.localPosition = new Vector3(0f, 1.6f, 0f);
				_transform = _iconObject.transform;
				_transform.localScale = Vector3.one;
				_iconObject.AddComponent<BillboardToCamera>();
			}

			public void Show(Sprite sprite)
			{
				if (!((Object)(object)_renderer == (Object)null) && !((Object)(object)sprite == (Object)null))
				{
					if ((Object)(object)_renderer.sprite != (Object)(object)sprite)
					{
						_renderer.sprite = sprite;
					}
					UpdateScale(sprite);
					if (!((Renderer)_renderer).enabled)
					{
						((Renderer)_renderer).enabled = true;
					}
				}
			}

			private void UpdateScale(Sprite sprite)
			{
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_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_0030: 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_0075: 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_005a: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_transform == (Object)null) && !((Object)(object)sprite == (Object)null))
				{
					Bounds bounds = sprite.bounds;
					Vector3 size = ((Bounds)(ref bounds)).size;
					float num = Mathf.Max(size.x, size.y);
					if (num <= 0.001f)
					{
						_transform.localScale = Vector3.one;
						return;
					}
					float num2 = 0.5f / num;
					_transform.localScale = Vector3.one * num2;
				}
			}

			public void Destroy()
			{
				if ((Object)(object)_iconObject != (Object)null)
				{
					Object.Destroy((Object)(object)_iconObject);
				}
			}
		}

		private sealed class BillboardToCamera : MonoBehaviour
		{
			private void LateUpdate()
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				Camera main = Camera.main;
				if ((Object)(object)main != (Object)null)
				{
					((Component)this).transform.forward = ((Component)main).transform.forward;
				}
			}
		}

		private static readonly Dictionary<int, BuilderIndicator> ActiveIndicators = new Dictionary<int, BuilderIndicator>();

		private static PropertyInfo _piVillagersService;

		private static PropertyInfo _piVillagers;

		private static FieldInfo _fiActorBrain;

		private static FieldInfo _fiBrainStack;

		private static Sprite _idleSprite;

		private static Sprite _builderSprite;

		public static void Refresh()
		{
			if (!ConfigManager.ShowBuilderStatusIcons || !GameAPI.IsGameActive())
			{
				Clear();
			}
			else
			{
				if (!EnsureSprites())
				{
					return;
				}
				HashSet<int> seenVillagers = new HashSet<int>();
				foreach (Villager builderVillager in GetBuilderVillagers())
				{
					if ((Object)(object)builderVillager == (Object)null || !builderVillager.IsAlive())
					{
						continue;
					}
					ActorView actorView = ((Actor)builderVillager).ActorView;
					if ((Object)(object)actorView == (Object)null)
					{
						continue;
					}
					bool isIdle = IsVillagerIdle(builderVillager);
					Sprite statusSprite = GetStatusSprite(isIdle);
					if (!((Object)(object)statusSprite == (Object)null))
					{
						seenVillagers.Add(((Actor)builderVillager).Id);
						if (!ActiveIndicators.TryGetValue(((Actor)builderVillager).Id, out var value))
						{
							value = new BuilderIndicator(builderVillager);
							ActiveIndicators[((Actor)builderVillager).Id] = value;
						}
						value.Show(statusSprite);
					}
				}
				List<int> list = ActiveIndicators.Keys.Where((int id) => !seenVillagers.Contains(id)).ToList();
				foreach (int item in list)
				{
					ActiveIndicators[item].Destroy();
					ActiveIndicators.Remove(item);
				}
			}
		}

		private static Sprite GetStatusSprite(bool isIdle)
		{
			if (isIdle)
			{
				return ConfigManager.ShowIdleBuilderStatusIcons ? _idleSprite : null;
			}
			return ConfigManager.ShowBusyBuilderStatusIcons ? _builderSprite : null;
		}

		public static void Clear()
		{
			foreach (BuilderIndicator value in ActiveIndicators.Values)
			{
				value.Destroy();
			}
			ActiveIndicators.Clear();
		}

		public static int GetIdleBuilderCount()
		{
			return GetBuilderVillagers().Count((Villager villager) => (Object)(object)villager != (Object)null && villager.IsAlive() && IsVillagerIdle(villager));
		}

		public static BuilderDemandCounts GetBuilderDemandCounts()
		{
			int num = 0;
			int num2 = 0;
			foreach (Building constructionBuilding in GameAPI.GetConstructionBuildings())
			{
				if (((constructionBuilding != null) ? constructionBuilding.BuildingState : null) == null || (Object)(object)constructionBuilding.BuildingModel == (Object)null || constructionBuilding.IsFinished() || constructionBuilding.HasInternalBuilders || !GameAPI.CanConstructionUseBuilders(constructionBuilding))
				{
					continue;
				}
				BuildingState buildingState = constructionBuilding.BuildingState;
				int maxBuilders = constructionBuilding.BuildingModel.maxBuilders;
				if (maxBuilders > 0)
				{
					int num3 = maxBuilders - Math.Max(0, buildingState.builders);
					if (num3 > 0)
					{
						num2++;
						num += num3;
					}
				}
			}
			return new BuilderDemandCounts(num, num2);
		}

		public static bool HasIdleBuilderOfRace(string raceName)
		{
			if (string.IsNullOrWhiteSpace(raceName))
			{
				return false;
			}
			return GetIdleBuilderRaceIds().Contains(raceName);
		}

		public static bool HasIdleBuilderOfRace(RaceModel race)
		{
			if ((Object)(object)race == (Object)null || string.IsNullOrWhiteSpace(((SO)race).Name))
			{
				return false;
			}
			return GetIdleBuilderRaceIds().Contains(((SO)race).Name);
		}

		public static Sprite GetIdleBuilderSprite()
		{
			EnsureSprites();
			return _idleSprite;
		}

		public static IReadOnlyList<string> GetIdleBuilderRaceSummaries()
		{
			return (from villager in GetBuilderVillagers()
				where (Object)(object)villager != (Object)null && villager.IsAlive() && IsVillagerIdle(villager)
				group villager by villager.Race into @group
				orderby GetRaceDisplayName(@group.First(), @group.Count())
				select $"{GetRaceDisplayName(@group.First(), 1)}: {@group.Count()}").ToList();
		}

		private static HashSet<string> GetIdleBuilderRaceIds()
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			foreach (Villager builderVillager in GetBuilderVillagers())
			{
				if (!((Object)(object)builderVillager == (Object)null) && builderVillager.IsAlive() && IsVillagerIdle(builderVillager))
				{
					if (!string.IsNullOrWhiteSpace(builderVillager.Race))
					{
						hashSet.Add(builderVillager.Race);
					}
					RaceModel raceModel = builderVillager.raceModel;
					if (!string.IsNullOrWhiteSpace((raceModel != null) ? ((SO)raceModel).Name : null))
					{
						hashSet.Add(((SO)builderVillager.raceModel).Name);
					}
				}
			}
			return hashSet;
		}

		private static string GetRaceDisplayName(Villager villager, int count)
		{
			return ((Object)(object)villager.raceModel != (Object)null) ? villager.raceModel.GetDisplayNameFor(count) : villager.Race;
		}

		private static IEnumerable<Villager> GetBuilderVillagers()
		{
			Settings settings = GameAPI.GetSettings();
			object obj;
			if (settings == null)
			{
				obj = null;
			}
			else
			{
				ProfessionModel defaultProfession = settings.DefaultProfession;
				obj = ((defaultProfession != null) ? ((SO)defaultProfession).Name : null);
			}
			string builderProfession = (string)obj;
			if (string.IsNullOrWhiteSpace(builderProfession))
			{
				yield break;
			}
			if (_piVillagersService == null)
			{
				_piVillagersService = typeof(GameMB).GetProperty("VillagersService", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			}
			object villagersService = _piVillagersService?.GetValue(null, null);
			if (villagersService == null)
			{
				yield break;
			}
			if ((object)_piVillagers == null)
			{
				_piVillagers = villagersService.GetType().GetProperty("Villagers", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			if (!(_piVillagers?.GetValue(villagersService, null) is IDictionary villagers))
			{
				yield break;
			}
			foreach (DictionaryEntry item in villagers)
			{
				object value = item.Value;
				Villager villager = (Villager)((value is Villager) ? value : null);
				if (villager != null && string.Equals(((Actor)villager).Profession, builderProfession, StringComparison.OrdinalIgnoreCase))
				{
					yield return villager;
				}
			}
		}

		private static bool IsVillagerIdle(Villager villager)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Invalid comparison between Unknown and I4
			try
			{
				if ((object)_fiActorBrain == null)
				{
					_fiActorBrain = typeof(Actor).GetField("brain", BindingFlags.Instance | BindingFlags.NonPublic);
				}
				object obj = _fiActorBrain?.GetValue(villager);
				if (obj == null)
				{
					return false;
				}
				if ((object)_fiBrainStack == null)
				{
					_fiBrainStack = obj.GetType().GetField("stack", BindingFlags.Instance | BindingFlags.NonPublic);
				}
				if (!(_fiBrainStack?.GetValue(obj) is Stack<ActorTask> { Count: not 0 } stack))
				{
					return false;
				}
				ActorTask val = stack.Peek();
				return val != null && (int)val.WorkStatus == 0;
			}
			catch (Exception)
			{
				return false;
			}
		}

		private static bool EnsureSprites()
		{
			if ((Object)(object)_idleSprite == (Object)null)
			{
				_idleSprite = FindHudSprite("/HUD/GoodsHUD/SacrificeMarker/Content") ?? GameAPI.GetSettings()?.monitorsConfig?.noBuildersIcon;
			}
			if ((Object)(object)_builderSprite == (Object)null)
			{
				_builderSprite = FindBuilderHudSprite() ?? GameAPI.GetSettings()?.monitorsConfig?.noBuildersIcon;
			}
			return (Object)(object)_idleSprite != (Object)null && (Object)(object)_builderSprite != (Object)null;
		}

		private static Sprite FindBuilderHudSprite()
		{
			RacesStatsHUD val = Object.FindObjectOfType<RacesStatsHUD>();
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Transform val2 = FindDescendantByName(((Component)val).transform, "BuildersIcon");
			if ((Object)(object)val2 == (Object)null)
			{
				return null;
			}
			Image componentInChildren = ((Component)val2).GetComponentInChildren<Image>(true);
			return (componentInChildren != null) ? componentInChildren.sprite : null;
		}

		private static Sprite FindHudSprite(string path)
		{
			if (string.IsNullOrWhiteSpace(path))
			{
				return null;
			}
			GameObject val = GameObject.Find(path);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Image component = val.GetComponent<Image>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.sprite != (Object)null)
			{
				return component.sprite;
			}
			Image componentInChildren = val.GetComponentInChildren<Image>(true);
			return (componentInChildren != null) ? componentInChildren.sprite : null;
		}

		private static Transform FindDescendantByName(Transform root, string name)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			for (int i = 0; i < root.childCount; i++)
			{
				Transform child = root.GetChild(i);
				if (string.Equals(((Object)child).name, name, StringComparison.Ordinal))
				{
					return child;
				}
				Transform val = FindDescendantByName(child, name);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}
	}
	internal static class BuildingAlertIndicators
	{
		private readonly struct IndicatorSnapshot : IEquatable<IndicatorSnapshot>
		{
			public bool Active { get; }

			public Color Color { get; }

			public bool ShowProductIcons { get; }

			public float ProductIconScale { get; }

			public string ProductGoodsKey { get; }

			public IndicatorSnapshot(bool active, Color color, IReadOnlyList<string> productGoodIds)
			{
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				Active = active;
				Color = color;
				ShowProductIcons = ConfigManager.ShowBuildingSpecificItemIndicators;
				ProductIconScale = ConfigManager.BuildingShortageIconScale;
				ProductGoodsKey = ((productGoodIds == null || productGoodIds.Count == 0) ? string.Empty : string.Join("|", productGoodIds.Select(BuildProductGoodsKey)));
			}

			public bool Equals(IndicatorSnapshot other)
			{
				//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)
				int result;
				if (Active == other.Active)
				{
					Color color = Color;
					if (((Color)(ref color)).Equals(other.Color) && ShowProductIcons == other.ShowProductIcons && Mathf.Approximately(ProductIconScale, other.ProductIconScale))
					{
						result = (string.Equals(ProductGoodsKey, other.ProductGoodsKey, StringComparison.Ordinal) ? 1 : 0);
						goto IL_0060;
					}
				}
				result = 0;
				goto IL_0060;
				IL_0060:
				return (byte)result != 0;
			}

			private static string BuildProductGoodsKey(string goodId)
			{
				GoodInfo goodInfo = Discovery.Goods.FirstOrDefault((GoodInfo g) => string.Equals(g.Id, goodId, StringComparison.OrdinalIgnoreCase));
				return goodId + ((goodInfo != null && goodInfo.IsIngredientBlocked) ? ":blocked" : ":normal");
			}
		}

		private const int MaxProductIcons = 4;

		private const int ProductIconGridRows = 2;

		private const int ProductIconSortingOrderOffset = 100;

		private const float ProductIconForwardOffset = -0.05f;

		private const float ProductIconBorderThicknessScale = 0.08f;

		private const string ProductIconBorderRootName = "IngredientBlockedBorder";

		private const string ProductIconsRootName = "StockAlertProductIcons";

		private static readonly Color WhiteColor = Color.white;

		private static readonly Color RedColor = new Color(1f, 0.25f, 0.25f, 1f);

		private static readonly Color YellowColor = new Color(1f, 0.85f, 0.2f, 1f);

		private static readonly Color GreyColor = new Color(0.48f, 0.48f, 0.48f, 1f);

		private static readonly Color BorderRedColor = new Color(0.62f, 0.04f, 0.04f, 1f);

		private static readonly Dictionary<int, IndicatorSnapshot> LastApplied = new Dictionary<int, IndicatorSnapshot>();

		private static Sprite _solidSprite;

		public static void Refresh()
		{
			if (!ConfigManager.ShowBuildingAlertIndicators)
			{
				RestoreVanilla();
				return;
			}
			Settings settings = GameAPI.GetSettings();
			HashSet<string> lowGoods = new HashSet<string>(from g in Discovery.Goods
				where g.IsBelowThreshold
				select g.Id, StringComparer.OrdinalIgnoreCase);
			HashSet<string> blockedIngredientGoods = new HashSet<string>(Discovery.BlockedIngredientGoods, StringComparer.OrdinalIgnoreCase);
			HashSet<int> seenBuildings = new HashSet<int>();
			foreach (IWorkshop recipeBuilding in GetRecipeBuildings())
			{
				ProductionBuilding val = recipeBuilding.Base;
				if (!((Object)(object)val == (Object)null))
				{
					seenBuildings.Add(((Building)val).Id);
					ApplyIndicatorState(val, recipeBuilding, lowGoods, blockedIngredientGoods, settings);
				}
			}
			foreach (ProductionBuilding gatheringSourceBuilding in GameAPI.GetGatheringSourceBuildings())
			{
				if (!((Object)(object)gatheringSourceBuilding == (Object)null))
				{
					seenBuildings.Add(((Building)gatheringSourceBuilding).Id);
					ApplyGatheringIndicatorState(gatheringSourceBuilding, blockedIngredientGoods);
				}
			}
			foreach (Farm farmBuilding in GameAPI.GetFarmBuildings())
			{
				if (!((Object)(object)farmBuilding == (Object)null))
				{
					seenBuildings.Add(((Building)farmBuilding).Id);
					ApplyFarmIndicatorState(farmBuilding);
				}
			}
			foreach (RainCatcher rainCatcherBuilding in GameAPI.GetRainCatcherBuildings())
			{
				if (!((Object)(object)rainCatcherBuilding == (Object)null))
				{
					seenBuildings.Add(((Building)rainCatcherBuilding).Id);
					ApplyRainCatcherIndicatorState(rainCatcherBuilding);
				}
			}
			List<int> list = LastApplied.Keys.Where((int id) => !seenBuildings.Contains(id)).ToList();
			foreach (int item in list)
			{
				RemoveProductIcons(item);
				LastApplied.Remove(item);
			}
		}

		public static void RefreshForView(ProductionBuildingView buildingView)
		{
			if (!ConfigManager.ShowBuildingAlertIndicators || (Object)(object)buildingView == (Object)null)
			{
				return;
			}
			IWorkshop val = GetRecipeBuildings().FirstOrDefault((Func<IWorkshop, bool>)delegate(IWorkshop w)
			{
				object obj;
				if (w == null)
				{
					obj = null;
				}
				else
				{
					ProductionBuilding obj2 = w.Base;
					obj = ((obj2 != null) ? ((Building)obj2).BuildingView : null);
				}
				return obj == buildingView;
			});
			if ((Object)(object)((val != null) ? val.Base : null) == (Object)null)
			{
				RainCatcher val2 = ((IEnumerable<RainCatcher>)GameAPI.GetRainCatcherBuildings()).FirstOrDefault((Func<RainCatcher, bool>)((RainCatcher b) => (object)((b != null) ? ((Building)b).BuildingView : null) == buildingView));
				if ((Object)(object)val2 != (Object)null)
				{
					ApplyRainCatcherIndicatorState(val2);
				}
				return;
			}
			Settings settings = GameAPI.GetSettings();
			HashSet<string> lowGoods = new HashSet<string>(from g in Discovery.Goods
				where g.IsBelowThreshold
				select g.Id, StringComparer.OrdinalIgnoreCase);
			HashSet<string> blockedIngredientGoods = new HashSet<string>(Discovery.BlockedIngredientGoods, StringComparer.OrdinalIgnoreCase);
			ApplyIndicatorState(val.Base, val, lowGoods, blockedIngredientGoods, settings);
		}

		public static void RestoreVanilla()
		{
			HashSet<int> hashSet = new HashSet<int>();
			foreach (IWorkshop recipeBuilding in GetRecipeBuildings())
			{
				ProductionBuilding val = recipeBuilding.Base;
				if (!((Object)(object)val == (Object)null) && hashSet.Add(((Building)val).Id))
				{
					RestoreVanillaFor(val);
				}
			}
			foreach (ProductionBuilding gatheringSourceBuilding in GameAPI.GetGatheringSourceBuildings())
			{
				if ((Object)(object)gatheringSourceBuilding != (Object)null && hashSet.Add(((Building)gatheringSourceBuilding).Id))
				{
					RestoreVanillaFor(gatheringSourceBuilding);
				}
			}
			foreach (Farm farmBuilding in GameAPI.GetFarmBuildings())
			{
				if ((Object)(object)farmBuilding != (Object)null && hashSet.Add(((Building)farmBuilding).Id))
				{
					RestoreVanillaFor((ProductionBuilding)(object)farmBuilding);
				}
			}
			foreach (RainCatcher rainCatcherBuilding in GameAPI.GetRainCatcherBuildings())
			{
				if ((Object)(object)rainCatcherBuilding != (Object)null && hashSet.Add(((Building)rainCatcherBuilding).Id))
				{
					RestoreVanillaFor((ProductionBuilding)(object)rainCatcherBuilding);
				}
			}
			LastApplied.Clear();
		}

		private static IEnumerable<IWorkshop> GetRecipeBuildings()
		{
			foreach (IWorkshop recipeBuilding in GameAPI.GetRecipeBuildings())
			{
				yield return recipeBuilding;
			}
		}

		private static void ApplyIndicatorState(ProductionBuilding building, IWorkshop workshop, HashSet<string> lowGoods, HashSet<string> blockedIngredientGoods, Settings settings)
		{
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: 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_012c: 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_0131: Unknown result type (might be due to invalid IL or missing references)
			BuildingView buildingView = ((Building)building).BuildingView;
			object obj;
			if (buildingView == null)
			{
				obj = null;
			}
			else
			{
				Transform transform = ((Component)buildingView).transform;
				if (transform == null)
				{
					obj = null;
				}
				else
				{
					Transform obj2 = transform.Find("ToRotate/UI/NoWorkersIcon");
					obj = ((obj2 != null) ? ((Component)obj2).gameObject : null);
				}
			}
			GameObject val = (GameObject)obj;
			if (!((Object)(object)val == (Object)null))
			{
				MakeIconClickThrough(val);
				int num = building.CountWorkers();
				WorkplaceModel[] workplaces = building.Workplaces;
				int num2 = ((workplaces != null) ? workplaces.Length : 0);
				List<string> enabledLowRecipeGoods = GetEnabledLowRecipeGoods(workshop, lowGoods);
				bool flag = enabledLowRecipeGoods.Count > 0;
				bool flag2 = flag && HasCraftableEnabledLowRecipe(workshop, lowGoods, settings);
				bool flag3 = workshop.Recipes.Any((WorkshopRecipeState r) => IsEnabledGatheringSupplyRecipe(r, blockedIngredientGoods, settings));
				bool flag4 = flag || flag3;
				bool flag5 = flag && !flag2 && !flag3;
				bool flag6 = false;
				Color color = WhiteColor;
				if (num == 0)
				{
					flag6 = true;
					color = (flag5 ? GreyColor : (flag4 ? RedColor : WhiteColor));
				}
				else if (flag4 && num < num2)
				{
					flag6 = true;
					color = (flag5 ? GreyColor : YellowColor);
				}
				ApplySnapshot(((Building)building).Id, val, flag6, color, (flag6 && flag && ConfigManager.ShowBuildingSpecificItemIndicators) ? enabledLowRecipeGoods : null);
			}
		}

		private static void ApplyGatheringIndicatorState(ProductionBuilding building, HashSet<string> blockedIngredientGoods)
		{
			//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_008c: 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_0091: 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_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)
			BuildingView buildingView = ((Building)building).BuildingView;
			object obj;
			if (buildingView == null)
			{
				obj = null;
			}
			else
			{
				Transform transform = ((Component)buildingView).transform;
				if (transform == null)
				{
					obj = null;
				}
				else
				{
					Transform obj2 = transform.Find("ToRotate/UI/NoWorkersIcon");
					obj = ((obj2 != null) ? ((Component)obj2).gameObject : null);
				}
			}
			GameObject val = (GameObject)obj;
			if (!((Object)(object)val == (Object)null))
			{
				MakeIconClickThrough(val);
				int num = building.CountWorkers();
				WorkplaceModel[] workplaces = building.Workplaces;
				int num2 = ((workplaces != null) ? workplaces.Length : 0);
				bool flag = HasRelevantGatheringRecipe(building, blockedIngredientGoods);
				bool active = false;
				Color color = WhiteColor;
				if (num == 0)
				{
					active = true;
					color = (flag ? RedColor : WhiteColor);
				}
				else if (flag && num < num2)
				{
					active = true;
					color = YellowColor;
				}
				ApplySnapshot(((Building)building).Id, val, active, color, null);
			}
		}

		private static void ApplyFarmIndicatorState(Farm farm)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			BuildingView buildingView = ((Building)farm).BuildingView;
			object obj;
			if (buildingView == null)
			{
				obj = null;
			}
			else
			{
				Transform transform = ((Component)buildingView).transform;
				if (transform == null)
				{
					obj = null;
				}
				else
				{
					Transform obj2 = transform.Find("ToRotate/UI/NoWorkersIcon");
					obj = ((obj2 != null) ? ((Component)obj2).gameObject : null);
				}
			}
			GameObject val = (GameObject)obj;
			if (!((Object)(object)val == (Object)null))
			{
				MakeIconClickThrough(val);
				int num = ((ProductionBuilding)farm).CountWorkers();
				WorkplaceModel[] workplaces = ((ProductionBuilding)farm).Workplaces;
				int num2 = ((workplaces != null) ? workplaces.Length : 0);
				bool flag = GameAPI.HasFarmFieldWork(farm);
				bool active = false;
				Color color = WhiteColor;
				if (num == 0)
				{
					active = true;
					color = (flag ? RedColor : WhiteColor);
				}
				else if (flag && num < num2)
				{
					active = true;
					color = YellowColor;
				}
				ApplySnapshot(((Building)farm).Id, val, active, color, null);
			}
		}

		private static void ApplyRainCatcherIndicatorState(RainCatcher rainCatcher)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			BuildingView buildingView = ((Building)rainCatcher).BuildingView;
			object obj;
			if (buildingView == null)
			{
				obj = null;
			}
			else
			{
				Transform transform = ((Component)buildingView).transform;
				if (transform == null)
				{
					obj = null;
				}
				else
				{
					Transform obj2 = transform.Find("ToRotate/UI/NoWorkersIcon");
					obj = ((obj2 != null) ? ((Component)obj2).gameObject : null);
				}
			}
			GameObject val = (GameObject)obj;
			if (!((Object)(object)val == (Object)null))
			{
				MakeIconClickThrough(val);
				int num = ((ProductionBuilding)rainCatcher).CountWorkers();
				WorkplaceModel[] workplaces = ((ProductionBuilding)rainCatcher).Workplaces;
				int num2 = ((workplaces != null) ? workplaces.Length : 0);
				bool flag = GameAPI.CanRainCatcherFillWaterTank(rainCatcher);
				bool active = false;
				Color color = WhiteColor;
				if (num == 0)
				{
					active = true;
					color = (flag ? RedColor : WhiteColor);
				}
				else if (flag && num < num2)
				{
					active = true;
					color = YellowColor;
				}
				ApplySnapshot(((Building)rainCatcher).Id, val, active, color, null);
			}
		}

		private static bool HasRelevantGatheringRecipe(ProductionBuilding building, HashSet<string> blockedIngredientGoods)
		{
			if ((Object)(object)((building != null) ? ((Building)building).BuildingModel : null) == (Object)null || blockedIngredientGoods == null || blockedIngredientGoods.Count == 0)
			{
				return false;
			}
			List<RecipeState> recipeStates = GetRecipeStates(building);
			if (recipeStates == null || recipeStates.Count == 0)
			{
				return false;
			}
			foreach (string blockedIngredientGood in blockedIngredientGoods)
			{
				if (string.IsNullOrWhiteSpace(blockedIngredientGood))
				{
					continue;
				}
				Settings settings = GameAPI.GetSettings();
				GoodModel val = ((settings != null) ? settings.GetGood(blockedIngredientGood) : null);
				if ((Object)(object)val == (Object)null || !((Building)building).BuildingModel.IsSourceOf(val))
				{
					continue;
				}
				foreach (RecipeState item in recipeStates)
				{
					if (item == null || !item.active || !RecipeProducesGood(building, item, blockedIngredientGood))
					{
						continue;
					}
					return true;
				}
			}
			return false;
		}

		private static List<RecipeState> GetRecipeStates(ProductionBuilding building)
		{
			GathererHut val = (GathererHut)(object)((building is GathererHut) ? building : null);
			if (val == null)
			{
				return ((Camp)(((building is Camp) ? building : null)?)).state?.recipes;
			}
			return val.state?.recipes;
		}

		private static bool RecipeProducesGood(ProductionBuilding building, RecipeState recipeState, string blockedGood)
		{
			GathererHut val = (GathererHut)(object)((building is GathererHut) ? building : null);
			if (val == null)
			{
				Camp val2 = (Camp)(object)((building is Camp) ? building : null);
				if (val2 != null)
				{
					CampRecipeModel recipeModel = val2.GetRecipeModel(recipeState);
					return string.Equals((recipeModel != null) ? ((RecipeModel)recipeModel).GetProducedGood() : null, blockedGood, StringComparison.OrdinalIgnoreCase);
				}
				return false;
			}
			GathererHutRecipeModel recipeModel2 = val.GetRecipeModel(recipeState);
			return string.Equals((recipeModel2 != null) ? ((RecipeModel)recipeModel2).GetProducedGood() : null, blockedGood, StringComparison.OrdinalIgnoreCase);
		}

		private static void ApplySnapshot(int buildingId, GameObject icon, bool active, Color color, IReadOnlyList<string> productGoodIds)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			IndicatorSnapshot indicatorSnapshot = new IndicatorSnapshot(active, color, productGoodIds);
			bool activeSelf = icon.activeSelf;
			Color currentIconColor = GetCurrentIconColor(icon);
			if (LastApplied.TryGetValue(buildingId, out var value) && value.Equals(indicatorSnapshot) && activeSelf == active && ColorsEqual(currentIconColor, color))
			{
				if (active && productGoodIds != null && productGoodIds.Count > 0)
				{
					RefreshProductIconRenderOrder(icon);
				}
				return;
			}
			icon.SetActive(active);
			foreach (SpriteRenderer baseIconRenderer in GetBaseIconRenderers(icon))
			{
				baseIconRenderer.color = color;
			}
			ApplyProductIcons(buildingId, icon, active ? productGoodIds : null);
			LastApplied[buildingId] = indicatorSnapshot;
		}

		private static Color GetCurrentIconColor(GameObject icon)
		{
			//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_0032: 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_003a: 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)
			if ((Object)(object)icon == (Object)null)
			{
				return Color.clear;
			}
			SpriteRenderer val = GetBaseIconRenderers(icon).FirstOrDefault();
			return ((Object)(object)val != (Object)null) ? val.color : Color.clear;
		}

		private static List<string> GetEnabledLowRecipeGoods(IWorkshop workshop, HashSet<string> lowGoods)
		{
			List<string> list = new List<string>();
			if (((workshop != null) ? workshop.Recipes : null) == null || lowGoods == null || lowGoods.Count == 0)
			{
				return list;
			}
			foreach (WorkshopRecipeState recipe in workshop.Recipes)
			{
				if (IsEnabledLowRecipe(recipe, lowGoods) && !list.Any((string g) => string.Equals(g, recipe.productName, StringComparison.OrdinalIgnoreCase)))
				{
					list.Add(recipe.productName);
					if (list.Count >= 4)
					{
						break;
					}
				}
			}
			return list;
		}

		private static bool HasCraftableEnabledLowRecipe(IWorkshop workshop, HashSet<string> lowGoods, Settings settings)
		{
			if (((workshop != null) ? workshop.Recipes : null) == null || lowGoods == null || lowGoods.Count == 0 || (Object)(object)settings == (Object)null)
			{
				return false;
			}
			foreach (WorkshopRecipeState recipe in workshop.Recipes)
			{
				if (IsEnabledLowRecipe(recipe, lowGoods))
				{
					WorkshopRecipeModel workshopRecipe = settings.GetWorkshopRecipe(((RecipeState)recipe).model);
					if ((Object)(object)workshopRecipe != (Object)null && Discovery.CanRecipeContinue(workshop, workshopRecipe))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static void ApplyProductIcons(int buildingId, GameObject icon, IReadOnlyList<string> productGoodIds)
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: 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_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)icon == (Object)null || productGoodIds == null || productGoodIds.Count == 0)
			{
				DestroyProductIcons(icon);
				return;
			}
			SpriteRenderer val = GetBaseIconRenderers(icon).FirstOrDefault((Func<SpriteRenderer, bool>)((SpriteRenderer r) => (Object)(object)((r != null) ? r.sprite : null) != (Object)null));
			if ((Object)(object)val == (Object)null)
			{
				DestroyProductIcons(icon);
				return;
			}
			GameObject orCreateProductIconsRoot = GetOrCreateProductIconsRoot(icon);
			if ((Object)(object)orCreateProductIconsRoot == (Object)null)
			{
				return;
			}
			Vector2 rendererSizeInIconSpace = GetRendererSizeInIconSpace(icon.transform, val);
			float num = Mathf.Max(0.01f, rendererSizeInIconSpace.y * ConfigManager.BuildingShortageIconScale);
			float num2 = num / 2.08f;
			float num3 = num2 * 0.08f;
			float num4 = Mathf.Max(rendererSizeInIconSpace.x * 0.55f + num2 * 0.5f, num2 * 1.15f);
			int num5 = 0;
			int i;
			for (i = 0; i < productGoodIds.Count; i++)
			{
				GoodInfo goodInfo = Discovery.Goods.FirstOrDefault((GoodInfo g) => string.Equals(g.Id, productGoodIds[i], StringComparison.OrdinalIgnoreCase));
				Sprite val2 = goodInfo?.Icon;
				if (!((Object)(object)val2 == (Object)null))
				{
					GameObject orCreateProductIcon = GetOrCreateProductIcon(orCreateProductIconsRoot, num5);
					SpriteRenderer component = orCreateProductIcon.GetComponent<SpriteRenderer>();
					if (!((Object)(object)component == (Object)null))
					{
						component.sprite = val2;
						component.color = WhiteColor;
						ConfigureProductIconRenderer(component, val, 1);
						ApplyProductIconBorder(orCreateProductIcon, val2, goodInfo.IsIngredientBlocked, val);
						int num6 = num5 % 2;
						int num7 = num5 / 2;
						float num8 = ((num6 == 0) ? ((num2 + num3) * 0.5f) : ((0f - (num2 + num3)) * 0.5f));
						orCreateProductIcon.transform.localPosition = new Vector3(num4 + (float)num7 * (num2 + num3), num8, 0f);
						orCreateProductIcon.transform.localRotation = Quaternion.identity;
						orCreateProductIcon.transform.localScale = Vector3.one * GetScaleForHeight(val2, num2);
						orCreateProductIcon.SetActive(true);
						num5++;
					}
				}
			}
			for (int num9 = num5; num9 < orCreateProductIconsRoot.transform.childCount; num9++)
			{
				((Component)orCreateProductIconsRoot.transform.GetChild(num9)).gameObject.SetActive(false);
			}
			orCreateProductIconsRoot.SetActive(num5 > 0);
			if (num5 == 0)
			{
				DestroyProductIcons(icon);
				LastApplied.Remove(buildingId);
			}
		}

		private static GameObject GetOrCreateProductIconsRoot(GameObject icon)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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)
			Transform val = icon.transform.Find("StockAlertProductIcons");
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).gameObject;
			}
			GameObject val2 = new GameObject("StockAlertProductIcons");
			val2.transform.SetParent(icon.transform, false);
			val2.transform.localPosition = new Vector3(0f, 0f, -0.05f);
			val2.transform.localRotation = Quaternion.identity;
			val2.transform.localScale = Vector3.one;
			return val2;
		}

		private static GameObject GetOrCreateProductIcon(GameObject root, int index)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			while (root.transform.childCount <= index)
			{
				GameObject val = new GameObject("ProductIcon");
				val.transform.SetParent(root.transform, false);
				SpriteRenderer val2 = val.AddComponent<SpriteRenderer>();
				((Renderer)val2).material = new Material(Shader.Find("Sprites/Default"));
			}
			return ((Component)root.transform.GetChild(index)).gameObject;
		}

		private static void RefreshProductIconRenderOrder(GameObject icon)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			SpriteRenderer val = GetBaseIconRenderers(icon).FirstOrDefault((Func<SpriteRenderer, bool>)((SpriteRenderer r) => (Object)(object)((r != null) ? r.sprite : null) != (Object)null));
			object obj;
			if (icon == null)
			{
				obj = null;
			}
			else
			{
				Transform transform = icon.transform;
				obj = ((transform != null) ? transform.Find("StockAlertProductIcons") : null);
			}
			Transform val2 = (Transform)obj;
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null))
			{
				val2.localPosition = new Vector3(val2.localPosition.x, val2.localPosition.y, -0.05f);
				SpriteRenderer[] componentsInChildren = ((Component)val2).GetComponentsInChildren<SpriteRenderer>(true);
				foreach (SpriteRenderer val3 in componentsInChildren)
				{
					int offset = ((!IsBorderPart(((Component)val3).transform)) ? 1 : 2);
					ConfigureProductIconRenderer(val3, val, offset);
				}
			}
		}

		private static void ApplyProductIconBorder(GameObject productIcon, Sprite sprite, bool active, SpriteRenderer baseRenderer)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			GameObject orCreateProductIconBorder = GetOrCreateProductIconBorder(productIcon);
			if (!((Object)(object)orCreateProductIconBorder == (Object)null))
			{
				orCreateProductIconBorder.SetActive(active);
				if (active && !((Object)(object)sprite == (Object)null))
				{
					Bounds bounds = sprite.bounds;
					Vector3 size = ((Bounds)(ref bounds)).size;
					float num = Mathf.Max(size.y * 0.08f, 0.01f);
					float num2 = size.x + num * 2f;
					float num3 = size.y + num * 2f;
					Transform obj = orCreateProductIconBorder.transform.Find("Top");
					ConfigureBorderPart((obj != null) ? ((Component)obj).GetComponent<SpriteRenderer>() : null, 0f, num3 * 0.5f - num * 0.5f, num2, num, baseRenderer);
					Transform obj2 = orCreateProductIconBorder.transform.Find("Bottom");
					ConfigureBorderPart((obj2 != null) ? ((Component)obj2).GetComponent<SpriteRenderer>() : null, 0f, (0f - num3) * 0.5f + num * 0.5f, num2, num, baseRenderer);
					Transform obj3 = orCreateProductIconBorder.transform.Find("Left");
					ConfigureBorderPart((obj3 != null) ? ((Component)obj3).GetComponent<SpriteRenderer>() : null, (0f - num2) * 0.5f + num * 0.5f, 0f, num, num3, baseRenderer);
					Transform obj4 = orCreateProductIconBorder.transform.Find("Right");
					ConfigureBorderPart((obj4 != null) ? ((Component)obj4).GetComponent<SpriteRenderer>() : null, num2 * 0.5f - num * 0.5f, 0f, num, num3, baseRenderer);
				}
			}
		}

		private static GameObject GetOrCreateProductIconBorder(GameObject productIcon)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)productIcon == (Object)null)
			{
				return null;
			}
			Transform val = productIcon.transform.Find("IngredientBlockedBorder");
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).gameObject;
			}
			GameObject val2 = new GameObject("IngredientBlockedBorder");
			val2.transform.SetParent(productIcon.transform, false);
			val2.transform.localPosition = Vector3.zero;
			val2.transform.localRotation = Quaternion.identity;
			val2.transform.localScale = Vector3.one;
			CreateBorderPart(val2.transform, "Top");
			CreateBorderPart(val2.transform, "Bottom");
			CreateBorderPart(val2.transform, "Left");
			CreateBorderPart(val2.transform, "Right");
			val2.SetActive(false);
			return val2;
		}

		private static void CreateBorderPart(Transform parent, string name)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			SpriteRenderer val2 = val.AddComponent<SpriteRenderer>();
			val2.sprite = GetSolidSprite();
			((Renderer)val2).material = new Material(Shader.Find("Sprites/Default"));
		}

		private static void ConfigureBorderPart(SpriteRenderer renderer, float x, float y, float width, float height, SpriteRenderer baseRenderer)
		{
			//IL_0010: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)renderer == (Object)null))
			{
				renderer.color = BorderRedColor;
				ConfigureProductIconRenderer(renderer, baseRenderer, 2);
				((Component)renderer).transform.localPosition = new Vector3(x, y, 0f);
				((Component)renderer).transform.localRotation = Quaternion.identity;
				((Component)renderer).transform.localScale = new Vector3(width, height, 1f);
			}
		}

		private static void ConfigureProductIconRenderer(SpriteRenderer renderer, SpriteRenderer baseRenderer, int offset)
		{
			if (!((Object)(object)renderer == (Object)null) && !((Object)(object)baseRenderer == (Object)null))
			{
				if ((Object)(object)((Renderer)baseRenderer).sharedMaterial != (Object)null)
				{
					((Renderer)renderer).sharedMaterial = ((Renderer)baseRenderer).sharedMaterial;
				}
				((Renderer)renderer).sortingLayerID = ((Renderer)baseRenderer).sortingLayerID;
				((Renderer)renderer).sortingOrder = ((Renderer)baseRenderer).sortingOrder + 100 + offset;
			}
		}

		private static bool IsBorderPart(Transform transform)
		{
			return (Object)(object)((transform != null) ? transform.parent : null) != (Object)null && string.Equals(((Object)transform.parent).name, "IngredientBlockedBorder", StringComparison.Ordinal);
		}

		private static Vector2 GetRendererSizeInIconSpace(Transform iconTransform, SpriteRenderer renderer)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)iconTransform == (Object)null || (Object)(object)((renderer != null) ? renderer.sprite : null) == (Object)null)
			{
				return Vector2.one;
			}
			Bounds bounds = renderer.sprite.bounds;
			Vector3 size = ((Bounds)(ref bounds)).size;
			Vector3 val = iconTransform.InverseTransformVector(((Component)renderer).transform.TransformVector(new Vector3(size.x, 0f, 0f)));
			float magnitude = ((Vector3)(ref val)).magnitude;
			val = iconTransform.InverseTransformVector(((Component)renderer).transform.TransformVector(new Vector3(0f, size.y, 0f)));
			float magnitude2 = ((Vector3)(ref val)).magnitude;
			return new Vector2(Mathf.Max(0.01f, magnitude), Mathf.Max(0.01f, magnitude2));
		}

		private static float GetScaleForHeight(Sprite sprite, float targetHeight)
		{
			//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_0014: Unknown result type (might be due to invalid IL or missing references)
			float num;
			if (sprite == null)
			{
				num = 0f;
			}
			else
			{
				Bounds bounds = sprite.bounds;
				num = ((Bounds)(ref bounds)).size.y;
			}
			float num2 = num;
			return (num2 > 0.001f) ? (targetHeight / num2) : 1f;
		}

		private static Sprite GetSolidSprite()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_003f: Expected O, but got Unknown
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_solidSprite != (Object)null)
			{
				return _solidSprite;
			}
			Texture2D val = new Texture2D(4, 4, (TextureFormat)5, false)
			{
				filterMode = (FilterMode)0,
				wrapMode = (TextureWrapMode)1,
				hideFlags = (HideFlags)61
			};
			val.SetPixels(Enumerable.Repeat<Color>(Color.white, 16).ToArray());
			val.Apply(false, true);
			_solidSprite = Sprite.Create(val, new Rect(0f, 0f, 4f, 4f), new Vector2(0.5f, 0.5f), 4f);
			return _solidSprite;
		}

		private static IEnumerable<SpriteRenderer> GetBaseIconRenderers(GameObject icon)
		{
			return from r in icon.GetComponentsInChildren<SpriteRenderer>(true)
				where (Object)(object)r != (Object)null && !IsProductIconTransform(((Component)r).transform)
				select r;
		}

		private static bool IsProductIconTransform(Transform transform)
		{
			while ((Object)(object)transform != (Object)null)
			{
				if (string.Equals(((Object)transform).name, "StockAlertProductIcons", StringComparison.Ordinal))
				{
					return true;
				}
				transform = transform.parent;
			}
			return false;
		}

		private static void RemoveProductIcons(int buildingId)
		{
			foreach (IWorkshop recipeBuilding in GetRecipeBuildings())
			{
				if (recipeBuilding == null)
				{
					continue;
				}
				ProductionBuilding obj = recipeBuilding.Base;
				if (((obj != null) ? new int?(((Building)obj).Id) : ((int?)null)) != buildingId)
				{
					continue;
				}
				BuildingView buildingView = ((Building)recipeBuilding.Base).BuildingView;
				object obj2;
				if (buildingView == null)
				{
					obj2 = null;
				}
				else
				{
					Transform transform = ((Component)buildingView).transform;
					if (transform == null)
					{
						obj2 = null;
					}
					else
					{
						Transform obj3 = transform.Find("ToRotate/UI/NoWorkersIcon");
						obj2 = ((obj3 != null) ? ((Component)obj3).gameObject : null);
					}
				}
				GameObject icon = (GameObject)obj2;
				DestroyProductIcons(icon);
				return;
			}
			foreach (Farm farmBuilding in GameAPI.GetFarmBuildings())
			{
				if (farmBuilding == null || ((Building)farmBuilding).Id != buildingId)
				{
					continue;
				}
				BuildingView buildingView2 = ((Building)farmBuilding).BuildingView;
				object obj4;
				if (buildingView2 == null)
				{
					obj4 = null;
				}
				else
				{
					Transform transform2 = ((Component)buildingView2).transform;
					if (transform2 == null)
					{
						obj4 = null;
					}
					else
					{
						Transform obj5 = transform2.Find("ToRotate/UI/NoWorkersIcon");
						obj4 = ((obj5 != null) ? ((Component)obj5).gameObject : null);
					}
				}
				GameObject icon2 = (GameObject)obj4;
				DestroyProductIcons(icon2);
				break;
			}
		}

		private static void DestroyProductIcons(GameObject icon)
		{
			object obj;
			if (icon == null)
			{
				obj = null;
			}
			else
			{
				Transform transform = icon.transform;
				obj = ((transform != null) ? transform.Find("StockAlertProductIcons") : null);
			}
			Transform val = (Transform)obj;
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val).gameObject);
			}
		}

		private static void RestoreVanillaFor(ProductionBuilding building)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			BuildingView buildingView = ((Building)building).BuildingView;
			object obj;
			if (buildingView == null)
			{
				obj = null;
			}
			else
			{
				Transform transform = ((Component)buildingView).transform;
				if (transform == null)
				{
					obj = null;
				}
				else
				{
					Transform obj2 = transform.Find("ToRotate/UI/NoWorkersIcon");
					obj = ((obj2 != null) ? ((Component)obj2).gameObject : null);
				}
			}
			GameObject val = (GameObject)obj;
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			MakeIconClickThrough(val);
			bool active = ((Building)building).BuildingState != null && ((Building)building).BuildingState.finished && !((Building)building).BuildingState.isSleeping && building.CountWorkers() == 0;
			val.SetActive(active);
			foreach (SpriteRenderer baseIconRenderer in GetBaseIconRenderers(val))
			{
				baseIconRenderer.color = WhiteColor;
			}
			DestroyProductIcons(val);
		}

		private static bool ColorsEqual(Color a, Color b)
		{
			//IL_0001: 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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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)
			return Mathf.Approximately(a.r, b.r) && Mathf.Approximately(a.g, b.g) && Mathf.Approximately(a.b, b.b) && Mathf.Approximately(a.a, b.a);
		}

		private static void MakeIconClickThrough(GameObject icon)
		{
			if ((Object)(object)icon == (Object)null)
			{
				return;
			}
			Graphic[] componentsInChildren = icon.GetComponentsInChildren<Graphic>(true);
			foreach (Graphic val in componentsInChildren)
			{
				val.raycastTarget = false;
			}
			Selectable[] componentsInChildren2 = icon.GetComponentsInChildren<Selectable>(true);
			foreach (Selectable val2 in componentsInChildren2)
			{
				val2.interactable = false;
			}
			GraphicRaycaster[] componentsInChildren3 = icon.GetComponentsInChildren<GraphicRaycaster>(true);
			foreach (GraphicRaycaster val3 in componentsInChildren3)
			{
				((Behaviour)val3).enabled = false;
			}
			EventTrigger[] componentsInChildren4 = icon.GetComponentsInChildren<EventTrigger>(true);
			foreach (EventTrigger val4 in componentsInChildren4)
			{
				((Behaviour)val4).enabled = false;
			}
			Component[] componentsInChildren5 = icon.GetComponentsInChildren<Component>(true);
			foreach (Component val5 in componentsInChildren5)
			{
				Type type = ((object)val5)?.GetType();
				if (type == null)
				{
					continue;
				}
				string name = type.Name;
				if (name.IndexOf("Collider", StringComparison.Ordinal) >= 0)
				{
					PropertyInfo property = type.GetProperty("enabled");
					if (property != null && property.CanWrite)
					{
						property.SetValue(val5, false, null);
					}
				}
			}
		}

		private static bool IsEnabledLowRecipe(WorkshopRecipeState recipeState, HashSet<string> lowGoods)
		{
			if (recipeState == null || !((RecipeState)recipeState).active || string.IsNullOrWhiteSpace(recipeState.productName) || !lowGoods.Contains(recipeState.productName))
			{
				return false;
			}
			return true;
		}

		private static bool IsEnabledGatheringSupplyRecipe(WorkshopRecipeState recipeState, HashSet<string> blockedIngredientGoods, Settings settings)
		{
			if (recipeState == null || !((RecipeState)recipeState).active || blockedIngredientGoods == null || blockedIngredientGoods.Count == 0 || string.IsNullOrWhiteSpace(recipeState.productName) || !blockedIngredientGoods.Contains(recipeState.productName))
			{
				return false;
			}
			WorkshopRecipeModel val = ((settings != null) ? settings.GetWorkshopRecipe(((RecipeState)recipeState).model) : null);
			return val?.requiredGoods == null || val.requiredGoods.Length == 0;
		}
	}
	[HarmonyPatch(typeof(ProductionBuildingView), "ShowWorkers")]
	internal static class BuildingAlertIndicatorsViewPatch
	{
		[HarmonyPostfix]
		private static void ShowWorkersPostfix(ProductionBuildingView __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && GameAPI.IsGameActive())
			{
				BuildingAlertIndicators.RefreshForView(__instance);
			}
		}
	}
	internal sealed class IdleBuilderRaceMenuMarker : MonoBehaviour
	{
		private RacesMenuSlot _slot;

		private GameObject _markerObject;

		private Image _markerImage;

		private float _nextRefreshTime;

		public static void Attach(RacesMenuSlot slot)
		{
			if (!((Object)(object)slot == (Object)null))
			{
				IdleBuilderRaceMenuMarker component = ((Component)slot).GetComponent<IdleBuilderRaceMenuMarker>();
				if ((Object)(object)component == (Object)null)
				{
					component = ((Component)slot).gameObject.AddComponent<IdleBuilderRaceMenuMarker>();
					component.Initialize(slot);
				}
				else
				{
					component.Initialize(slot);
				}
			}
		}

		private void Initialize(RacesMenuSlot slot)
		{
			_slot = slot;
			CleanupLegacyMarkers();
			Refresh();
		}

		private void OnEnable()
		{
			Refresh();
		}

		private void Update()
		{
			if (!(Time.unscaledTime < _nextRefreshTime))
			{
				_nextRefreshTime = Time.unscaledTime + 0.25f;
				Refresh();
			}
		}

		private void Refresh()
		{
			if ((Object)(object)_slot == (Object)null || !ConfigManager.ShowBuilderStatusIcons || !ConfigManager.ShowIdleBuilderStatusIcons)
			{
				Hide();
				return;
			}
			RaceModel race = _slot.GetRace();
			if ((Object)(object)race == (Object)null || !BuilderStatusIndicators.HasIdleBuilderOfRace(race))
			{
				Hide();
				return;
			}
			Sprite idleBuilderSprite = BuilderStatusIndicators.GetIdleBuilderSprite();
			if ((Object)(object)idleBuilderSprite == (Object)null)
			{
				Hide();
				return;
			}
			EnsureMarker();
			if (!((Object)(object)_markerImage == (Object)null))
			{
				_markerImage.sprite = idleBuilderSprite;
				_markerObject.SetActive(true);
			}
		}

		private void EnsureMarker()
		{
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: 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_0143: 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)
			if (!((Object)(object)_markerObject != (Object)null) && !((Object)(object)_slot == (Object)null))
			{
				Transform obj = ((Component)_slot).transform.Find("Content");
				RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)_slot).GetComponent<RectTransform>();
				}
				if (!((Object)(object)val == (Object)null))
				{
					_markerObject = new GameObject("StockAlertIdleBuilderRaceMarker", new Type[3]
					{
						typeof(RectTransform),
						typeof(CanvasRenderer),
						typeof(Image)
					});
					_markerObject.transform.SetParent((Transform)(object)val, false);
					_markerImage = _markerObject.GetComponent<Image>();
					((Graphic)_markerImage).raycastTarget = false;
					_markerImage.preserveAspect = true;
					RectTransform component = _markerObject.GetComponent<RectTransform>();
					component.anchorMin = new Vector2(0f, 0.5f);
					component.anchorMax = new Vector2(0f, 0.5f);
					component.pivot = new Vector2(0.5f, 0.5f);
					component.sizeDelta = new Vector2(22f, 22f);
					component.anchoredPosition = new Vector2(-2f, 0f);
					_markerObject.transform.SetAsLastSibling();
					_markerObject.SetActive(false);
				}
			}
		}

		private void CleanupLegacyMarkers()
		{
			if (!((Object)(object)_slot == (Object)null))
			{
				Transform val = ((Component)_slot).transform.Find("Content");
				if (!((Object)(object)val == (Object)null))
				{
					DestroyChild(val, "IdleBuilderRaceMarker");
					DestroyChild(val, "StockAlertIdleBuilderRaceMarker");
					_markerObject = null;
					_markerImage = null;
				}
			}
		}

		private static void DestroyChild(Transform parent, string childName)
		{
			Transform val = parent.Find(childName);
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val).gameObject);
			}
		}

		private void Hide()
		{
			if ((Object)(object)_markerObject != (Object)null)
			{
				_markerObject.SetActive(false);
			}
		}
	}
	internal static class IdleBuildersAlert
	{
		public const string AlertPrefix = "You have idle builders:";

		private static News _activeNews;

		private static string _lastContent;

		public static void Refresh()
		{
			if (!ConfigManager.ShowIdleBuildersAlert || !GameAPI.IsGameActive())
			{
				Clear();
				return;
			}
			int idleBuilderCount = BuilderStatusIndicators.GetIdleBuilderCount();
			if (idleBuilderCount <= 0)
			{
				Clear();
				return;
			}
			string content = BuildContent(idleBuilderCount);
			List<News> currentNews = GameAPI.GetCurrentNews();
			News val = ((IEnumerable<News>)currentNews).FirstOrDefault((Func<News, bool>)((News news) => news != null && news.content == content));
			if (val != null)
			{
				_activeNews = val;
				_lastContent = content;
				return;
			}
			if (_activeNews != null)
			{
				GameAPI.RemoveNews(_activeNews);
				_activeNews = null;
			}
			if (!(_lastContent == content) || !currentNews.Any((News news) => news != null && news.content != null && news.content.StartsWith("You have idle builders:")))
			{
				_activeNews = GameAPI.PublishNews(content, null, (AlertSeverity)1);
				_lastContent = content;
			}
		}

		public static void Clear()
		{
			if (_activeNews != null)
			{
				GameAPI.RemoveNews(_activeNews);
				_activeNews = null;
			}
			_lastContent = null;
		}

		private static string BuildContent(int count)
		{
			IReadOnlyList<string> idleBuilderRaceSummaries = BuilderStatusIndicators.GetIdleBuilderRaceSummaries();
			if (idleBuilderRaceSummaries.Count == 0)
			{
				return string.Format("{0} {1}", "You have idle builders:", count);
			}
			string arg = string.Join("\n", idleBuilderRaceSummaries);
			return string.Format("{0} {1}\n{2}", "You have idle builders:", count, arg);
		}
	}
	internal static class ItemLocatorOverlay
	{
		private const float MarkerHeightOffset = 0.55f;

		private static readonly Dictionary<string, GameObject> Markers = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase);

		private static string _trackedGoodId;

		private static GameObject _template;

		private static string _lastToggledGoodId;

		private static int _lastToggleFrame = -1;

		public static bool IsTracking => !string.IsNullOrWhiteSpace(_trackedGoodId);

		public static void Toggle(string goodId)
		{
			if (!string.IsNullOrWhiteSpace(goodId) && (_lastToggleFrame != Time.frameCount || !string.Equals(_lastToggledGoodId, goodId, StringComparison.OrdinalIgnoreCase)))
			{
				_lastToggleFrame = Time.frameCount;
				_lastToggledGoodId = goodId;
				if (string.Equals(_trackedGoodId, goodId, StringComparison.OrdinalIgnoreCase))
				{
					Clear();
					return;
				}
				_trackedGoodId = goodId;
				Refresh();
			}
		}

		public static void Clear()
		{
			_trackedGoodId = null;
			foreach (GameObject value in Markers.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
			}
			Markers.Clear();
		}

		public static void Refresh()
		{
			if (!GameAPI.IsGameActive() || string.IsNullOrWhiteSpace(_trackedGoodId))
			{
				Clear();
				return;
			}
			Settings settings = GameAPI.GetSettings();
			Sprite val = ((settings != null) ? settings.GetGood(_trackedGoodId) : null)?.icon;
			if ((Object)(object)val == (Object)null)
			{
				Clear();
				return;
			}
			GameObject val2 = ResolveTemplate();
			if ((Object)(object)val2 == (Object)null)
			{
				Clear();
				return;
			}
			List<TrackedItemLocation> trackedItemLocations = GameAPI.GetTrackedItemLocations(_trackedGoodId);
			HashSet<string> seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			foreach (TrackedItemLocation item in trackedItemLocations.Where((TrackedItemLocation l) => l != null && !string.IsNullOrWhiteSpace(l.Key)))
			{
				UpsertMarker(item, val, val2);
				seen.Add(item.Key);
			}
			List<string> list = Markers.Keys.Where((string key) => !seen.Contains(key)).ToList();
			foreach (string item2 in list)
			{
				if (Markers.TryGetValue(item2, out var value) && (Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
				Markers.Remove(item2);
			}
		}

		private static void UpsertMarker(TrackedItemLocation location, Sprite icon, GameObject template)
		{
			//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_0071: Unknown result type (might be due to invalid IL or missing references)
			Vector3 markerWorldPosition = GetMarkerWorldPosition(location);
			if (!Markers.TryGetValue(location.Key, out var value) || (Object)(object)value == (Object)null)
			{
				value = Object.Instantiate<GameObject>(template, template.transform.parent);
				((Object)value).name = "StockAlertItemLocator_" + location.Key;
				Markers[location.Key] = value;
			}
			ApplyVisuals(value, icon, location);
			ApplyTarget(value, markerWorldPosition);
			value.SetActive(true);
		}

		private static void ApplyVisuals(GameObject marker, Sprite icon, TrackedItemLocation location)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			Transform obj = marker.transform.Find("Icon");
			object obj2 = ((obj != null) ? ((Component)obj).GetComponent<Image>() : null);
			if (obj2 == null)
			{
				Transform obj3 = marker.transform.Find("Mask/Icon");
				obj2 = ((obj3 != null) ? ((Component)obj3).GetComponent<Image>() : null);
			}
			Image val = (Image)obj2;
			if ((Object)(object)val != (Object)null)
			{
				val.sprite = icon;
				val.preserveAspect = true;
				((Graphic)val).color = Color.white;
				((Graphic)val).raycastTarget = false;
			}
			Transform val2 = marker.transform.Find("Grade");
			if ((Object)(object)val2 != (Object)null)
			{
				((Component)val2).gameObject.SetActive(false);
			}
			Transform obj4 = marker.transform.Find("BG");
			Image val3 = ((obj4 != null) ? ((Component)obj4).GetComponent<Image>() : null);
			if ((Object)(object)val3 != (Object)null)
			{
				((Graphic)val3).raycastTarget = false;
			}
			Image[] componentsInChildren = marker.GetComponentsInChildren<Image>(true);
			foreach (Image val4 in componentsInChildren)
			{
				((Graphic)val4).raycastTarget = false;
			}
			ApplyAmountBadge(marker, location);
		}

		private static void ApplyAmountBadge(GameObject marker, TrackedItemLocation location)
		{
			GameObject orCreateAmountBadge = GetOrCreateAmountBadge(marker);
			if ((Object)(object)orCreateAmountBadge == (Object)null)
			{
				return;
			}
			bool flag = location != null && location.Amount > 0 && location.Key.StartsWith("building:", StringComparison.OrdinalIgnoreCase);
			orCreateAmountBadge.SetActive(flag);
			if (flag)
			{
				TextMeshProUGUI componentInChildren = orCreateAmountBadge.GetComponentInChildren<TextMeshProUGUI>(true);
				if ((Object)(object)componentInChildren != (Object)null)
				{
					((TMP_Text)componentInChildren).text = location.Amount.ToString();
				}
			}
		}

		private static GameObject GetOrCreateAmountBadge(GameObject marker)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Expected O, but got Unknown
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: 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_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			Transform val = marker.transform.Find("StockAlertAmountBadge");
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).gameObject;
			}
			RectTransform val2 = marker.GetComponent<RectTransform>() ?? marker.GetComponentInChildren<RectTransform>(true);
			if ((Object)(object)val2 == (Object)null)
			{
				return null;
			}
			GameObject val3 = new GameObject("StockAlertAmountBadge", new Type[1] { typeof(RectTransform) });
			RectTransform component = val3.GetComponent<RectTransform>();
			((Transform)component).SetParent((Transform)(object)val2, false);
			component.anchorMin = new Vector2(1f, 0f);
			component.anchorMax = new Vector2(1f, 0f);
			component.pivot = new Vector2(1f, 0f);
			component.anchoredPosition = new Vector2(8f, -8f);
			component.sizeDelta = new Vector2(32f, 20f);
			GameObject val4 = new GameObject("Text", new Type[2]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI)
			});
			RectTransform component2 = val4.GetComponent<RectTransform>();
			((Transform)component2).SetParent((Transform)(object)component, false);
			component2.anchorMin = Vector2.zero;
			component2.anchorMax = Vector2.one;
			component2.offsetMin = Vector2.zero;
			component2.offsetMax = Vector2.zero;
			TextMeshProUGUI component3 = val4.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component3).font = TMP_Settings.defaultFontAsset;
			((TMP_Text)component3).fontSize = 15f;
			((TMP_Text)component3).enableAutoSizing = false;
			((TMP_Text)component3).fontStyle = (FontStyles)1;
			((TMP_Text)component3).alignment = (TextAlignmentOptions)514;
			((Graphic)component3).color = new Color(1f, 0.99f, 0.9f, 1f);
			((Graphic)component3).raycastTarget = false;
			((TMP_Text)component3).margin = new Vector4(1f, 0f, 1f, 0f);
			((TMP_Text)component3).fontSharedMaterial = ((TMP_Text)component3).fontMaterial;
			((TMP_Text)component3).outlineWidth = 0.25f;
			((TMP_Text)component3).outlineColor = Color32.op_Implicit(new Color(0.05f, 0.05f, 0.05f, 1f));
			return val3;
		}

		private static void ApplyTarget(GameObject marker, Vector3 worldPosition)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			WorldIndicator val = marker.GetComponent<WorldIndicator>();
			if ((Object)(object)val == (Object)null)
			{
				val = marker.GetComponentInChildren<WorldIndicator>(true);
			}
			if (val != null)
			{
				val.SetTarget(worldPosition);
			}
		}

		private static Vector3 GetMarkerWorldPosition(TrackedItemLocation location)
		{
			//IL_00c7: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			Object source = location.Source;
			Component val = (Component)(object)((source is Component) ? source : null);
			if (val != null && (Object)(object)val != (Object)null)
			{
				Renderer[] array = (from renderer in val.GetComponentsInChildren<Renderer>(true)
					where (Object)(object)renderer != (Object)null && !IsLocatorRenderer(((Component)renderer).transform)
					select renderer).ToArray();
				if (array.Length != 0)
				{
					Bounds bounds = array[0].bounds;
					for (int num = 1; num < array.Length; num++)
					{
						((Bounds)(ref bounds)).Encapsulate(array[num].bounds);
					}
					return new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).max.y + 0.55f, ((Bounds)(ref bounds)).center.z);
				}
			}
			return location.FallbackPosition + new Vector3(0f, 0.55f, 0f);
		}

		private static bool IsLocatorRenderer(Transform transform)
		{
			while ((Object)(object)transform != (Object)null)
			{
				if (((Object)transform).name.StartsWith("StockAlertItemLocator_", StringComparison.Ordinal))
				{
					return true;
				}
				transform = transform.parent;
			}
			return false;
		}

		private static GameObject ResolveTemplate()
		{
			if ((Object)(object)_template != (Object)null)
			{
				return _template;
			}
			DepositIndicator? obj = ((IEnumerable<DepositIndicator>)Resources.FindObjectsOfTypeAll<DepositIndicator>()).FirstOrDefault((Func<DepositIndicator, bool>)IsSceneObject);
			object obj2 = ((obj != null) ? ((Component)obj).gameObject : null);
			if (obj2 == null)
			{
				LakeIndicator? obj3 = ((IEnumerable<LakeIndicator>)Resources.FindObjectsOfTypeAll<LakeIndicator>()).FirstOrDefault((Func<LakeIndicator, bool>)IsSceneObject);
				obj2 = ((obj3 != null) ? ((Component)obj3).gameObject : null);
				if (obj2 == null)
				{
					OreIndicator? obj4 = ((IEnumerable<OreIndicator>)Resources.FindObjectsOfTypeAll<OreIndicator>()).FirstOrDefault((Func<OreIndicator, bool>)IsSceneObject);
					obj2 = ((obj4 != null) ? ((Component)obj4).gameObject : null);
					if (obj2 == null)
					{
						BuildingIndicator? obj5 = ((IEnumerable<BuildingIndicator>)Resources.FindObjectsOfTypeAll<BuildingIndicator>()).FirstOrDefault((Func<BuildingIndicator, bool>)IsSceneObject);
						obj2 = ((obj5 != null) ? ((Component)obj5).gameObject : null);
					}
				}
			}
			_template = (GameObject)obj2;
			return _template;
		}

		private static bool IsSceneObject(Component component)
		{
			//IL_0010: 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)
			int result;
			if ((Object)(object)component != (Object)null)
			{
				Scene scene = component.gameObject.scene;
				result = (((Scene)(ref scene)).IsValid() ? 1 : 0);
			}
			else
			{
				result = 0;
			}
			return (byte)result != 0;
		}
	}
	internal sealed class QueuedWorkerSlotCompanion : MonoBehaviour
	{
		private static readonly List<QueuedWorkerSlotCompanion> Instances = new List<QueuedWorkerSlotCompanion>();

		private static FieldInfo _fiBuilding;

		private static FieldInfo _fiWorkplace;

		private static FieldInfo _fiRaceIcon;

		private static PropertyInfo _piIsRemoved;

		private static PropertyInfo _piReactiveValue;

		private BuildingWorkerSlot _slot;

		private GameObject _queuedIconObject;

		private Image _queuedIconImage;

		private Button _queuedIconButton;

		private float _nextRefreshTime;

		public static void Attach(BuildingWorkerSlot slot)
		{
			if (!((Object)(object)slot == (Object)null) && !((Object)(object)((Component)slot).GetComponent<QueuedWorkerSlotCompanion>() != (Object)null))
			{
				((Component)slot).gameObject.AddComponent<QueuedWorkerSlotCompanion>().Initialize(slot);
			}
		}

		public static void ClearAll()
		{
			QueuedWorkerSlotCompanion[] array = Instances.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				array[i]?.Hide();
			}
		}

		private void Initialize(BuildingWorkerSlot slot)
		{
			_slot = slot;
			Instances.Add(this);
			EnsureUi();
			Refresh();
		}

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

		private void Update()
		{
			if (!(Time.unscaledTime < _nextRefreshTime))
			{
				_nextRefreshTime = Time.unscaledTime + 0.25f;
				Refresh();
			}
		}

		private void Refresh()
		{
			if ((Object)(object)_slot == (Object)null)
			{
				Hide();
				return;
			}
			if (!ConfigManager.EnableQueuedWorkerAssignments)
			{
				Hide();
				return;
			}
			if (!TryGetContext(out var building, out var _, out var workplaceIndex))
			{
				Hide();
				return;
			}
			if (IsBuildingRemoved(building))
			{
				WorkerAssignmentQueue.ClearQueuedRace(building, workplaceIndex);
				Hide();
				return;
			}
			RaceModel queuedRace = WorkerAssignmentQueue.GetQueuedRace(building, workplaceIndex);
			if ((Object)(object)queuedRace == (Object)null)
			{
				Hide();
				return;
			}
			EnsureUi();
			_queuedIconImage.sprite = queuedRace.roundIcon;
			((Graphic)_queuedIconImage).material = null;
			_queuedIconObject.SetActive(true);
		}

		private bool TryGetContext(out ProductionBuilding building, out WorkplaceModel workplace, out int workplaceIndex)
		{
			building = null;
			workplace = null;
			workplaceIndex = -1;
			if ((Object)(object)_slot == (Object)null)
			{
				return false;
			}
			if ((object)_fiBuilding == null)
			{
				_fiBuilding = typeof(BuildingWorkerSlot).GetField("building", BindingFlags.Instance | BindingFlags.NonPublic);
			}
			if ((object)_fiWorkplace == null)
			{
				_fiWorkplace = typeof(BuildingWorkerSlot).GetField("workplace", BindingFlags.Instance | BindingFlags.NonPublic);
			}
			object? obj = _fiBuilding?.GetValue(_slot);
			building = (ProductionBuilding)((obj is ProductionBuilding) ? obj : null);
			object? obj2 = _fiWorkplace?.GetValue(_slot);
			workplace = (WorkplaceModel)((obj2 is WorkplaceModel) ? obj2 : null);
			if ((Object)(object)building == (Object)null || workplace == null)
			{
				return false;
			}
			workplaceIndex = building.GetIndexOf(workplace);
			return workplaceIndex >= 0;
		}

		private void EnsureUi()
		{
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Expected O, but got Unknown
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: 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_0169: 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)
			if ((Object)(object)_queuedIconObject != (Object)null)
			{
				return;
			}
			if ((object)_fiRaceIcon == null)
			{
				_fiRaceIcon = typeof(BuildingWorkerSlot).GetField("raceIcon", BindingFlags.Instance | BindingFlags.NonPublic);
			}
			object? obj = _fiRaceIcon?.GetValue(_slot);
			Image val = (Image)((obj is Image) ? obj : null);
			if (!((Object)(object)val == (Object)null))
			{
				_queuedIconObject = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)val).transform.parent, false);
				((Object)_queuedIconObject).name = "QueuedWorkerIcon";
				_queuedIconImage = _queuedIconObject.GetComponent<Image>();
				_queuedIconButton = _queuedIconObject.GetComponent<Button>();
				if ((Object)(object)_queuedIconButton == (Object)null)
				{
					_queuedIconButton = _queuedIconObject.AddComponent<Button>();
				}
				((UnityEventBase)_queuedIconButton.onClick).RemoveAllListeners();
				((UnityEvent)_queuedIconButton.onClick).AddListener(new UnityAction(OpenQueueMenu));
				RectTransform component = _queuedIconObject.GetComponent<RectTransform>();
				Rect rect = component.rect;
				float num;
				if (!(((Rect)(ref rect)).width > 0f))
				{
					num = Mathf.Max(32f, component.sizeDelta.x);
				}
				else
				{
					rect = component.rect;
					num = ((Rect)(ref rect)).width;
				}
				float num2 = num;
				component.anchoredPosition += new Vector2(0f - (num2 + 8f), 0f);
				_queuedIconObject.SetActive(false);
			}
		}

		private void OpenQueueMenu()
		{
			if (!ConfigManager.EnableQueuedWorkerAssignments || !TryGetContext(out var building, out var workplace, out var _))
			{
				return;
			}
			RacesMenu val = FindRacesMenu();
			if (!((Object)(object)val == (Object)null))
			{
				val.SetUp(_queuedIconObject.GetComponent<RectTransform>(), (Building)(object)building, (Action<RaceModel>)delegate(RaceModel race)
				{
					WorkerAssignmentQueue.SetQueuedRace(building, workplace, race);
				}, (Action)delegate
				{
					WorkerAssignmentQueue.ClearQueuedRace(building, workplace);
				});
			}
		}

		private static RacesMenu FindRacesMenu()
		{
			return ((IEnumerable<RacesMenu>)Resources.FindObjectsOfTypeAll<RacesMenu>()).FirstOrDefault((Func<RacesMenu, bool>)delegate(RacesMenu menu)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				int result;
				if ((Object)(object)menu != (Object)null)
				{
					Scene scene = ((Component)menu).gameObject.scene;
					result = (((Scene)(ref scene)).IsValid() ? 1 : 0);
				}
				else
				{
					result = 0;
				}
				return (byte)result != 0;
			});
		}

		private static bool IsBuildingRemoved(ProductionBuilding building)
		{
			try
			{
				if ((object)_piIsRemoved == null)
				{
					_piIsRemoved = typeof(Building).GetProperty("IsRemoved", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				object obj = _piIsRemoved?.GetValue(building, null);
				if (obj == null)
				{
					return false;
				}
				if ((object)_piReactiveValue == null)
				{
					_piReactiveValue = obj.GetType().GetProperty("Value", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				object obj2 = _piReactiveValue?.GetValue(obj, null);
				bool flag = default(bool);
				int num;
				if (obj2 is bool)
				{
					flag = (bool)obj2;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			catch (Exception)
			{
				return false;
			}
		}

		private void Hide()
		{
			if ((Object)(object)_queuedIconObject != (Object)null)
			{
				_queuedIconObject.SetActive(false);
			}
		}
	}
	internal static class TimedOrdersAlert
	{
		private const int OneMinuteThreshold = 60;

		private const int ThirtySecondsThreshold = 30;

		private static readonly HashSet<string> FiredAlerts = new HashSet<string>(StringComparer.Ordinal);

		private static readonly Dictionary<string, News> ActiveNews = new Dictionary<string, News>(StringComparer.Ordinal);

		public static void Refresh()
		{
			if (!ConfigManager.TimedOrdersAlert || !GameAPI.IsGameActive())
			{
				Clear();
				return;
			}
			List<GameAPI.TimedOrderInfo> activeTimedOrders = GameAPI.GetActiveTimedOrders();
			HashSet<int> activeOrderIds = new HashSet<int>(activeTimedOrders.Select((GameAPI.TimedOrderInfo order) => order.Id));
			ClearInactive(activeOrderIds);
			foreach (GameAPI.TimedOrderInfo item in activeTimedOrders)
			{
				if (item.TimeLeft <= 30f)
				{
					Fire(item, 30, "30 seconds", (AlertSeverity)3);
				}
				else if (item.TimeLeft <= 60f)
				{
					Fire(item, 60, "1 minute", (AlertSeverity)2);
				}
			}
		}

		public static void Clear()
		{
			foreach (News item in ActiveNews.Values.ToList())
			{
				GameAPI.RemoveNews(item);
			}
			ActiveNews.Clear();
			FiredAlerts.Clear();
		}

		private static void Fire(GameAPI.TimedOrderInfo order, int threshold, string label, AlertSeverity severity)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			string key = GetKey(order.Id, threshold);
			if (FiredAlerts.Add(key))
			{
				if (threshold == 30)
				{
					RemoveNews(GetKey(order.Id, 60));
				}
				string content = "Timed order: " + order.DisplayName + " has " + label + " left.";
				ActiveNews[key] = GameAPI.PublishNews(content, null, severity);
			}
		}

		private static void ClearInactive(HashSet<int> activeOrderIds)
		{
			foreach (string item in ActiveNews.Keys.ToList())
			{
				if (!TryGetOrderId(item, out var orderId) || !activeOrderIds.Contains(orderId))
				{
					RemoveNews(item);
				}
			}
			FiredAlerts.RemoveWhere((string key) => !TryGetOrderId(key, out var orderId2) || !activeOrderIds.Contains(orderId2));
		}

		private static void RemoveNews(string key)
		{
			if (ActiveNews.TryGetValue(key, out var value))
			{
				GameAPI.RemoveNews(value);
				ActiveNews.Remove(key);
			}
		}

		private static string GetKey(int orderId, int threshold)
		{
			return orderId + ":" + threshold;
		}

		private static bool TryGetOrderId(string key, out int orderId)
		{
			orderId = 0;
			int num = key?.IndexOf(':') ?? (-1);
			return num > 0 && int.TryParse(key.Substring(0, num), out orderId);
		}
	}
	internal sealed class TrackedGoodClickTarget : MonoBehaviour, IPointerClickHandler, IEventSystemHandler
	{
		public string GoodId;

		public static void Attach(Component target, string goodId)
		{
			if (!((Object)(object)target == (Object)null) && !string.IsNullOrWhiteSpace(goodId))
			{
				TrackedGoodClickTarget trackedGoodClickTarget = target.GetComponent<TrackedGoodClickTarget>();
				if ((Object)(object)trackedGoodClickTarget == (Object)null)
				{
					trackedGoodClickTarget = target.gameObject.AddComponent<TrackedGoodClickTarget>();
				}
				trackedGoodClickTarget.GoodId = goodId;
			}
		}

		public void OnPointerClick(PointerEventData eventData)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (eventData != null && (int)eventData.button == 0 && IsModifierPressed() && !string.IsNullOrWhiteSpace(GoodId))
			{
				ItemLocatorOverlay.Toggle(GoodId);
				((AbstractEventData)eventData).Use();
			}
		}

		private static bool IsModifierPressed()
		{
			Keyboard current = Keyboard.current;
			if (current != null)
			{
				return ((ButtonControl)current.leftCtrlKey).isPressed || ((ButtonControl)current.rightCtrlKey).isPressed || current.ctrlKey.isPressed;
			}
			return Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305);
		}
	}
	internal static class WarehouseHaulerIndicators
	{
		private sealed class WarehouseHaulerIndicator
		{
			private const float MarkerHeightOffset = 0.45f;

			private readonly Storage _storage;

			private readonly GameObject _root;

			private readonly SpriteRenderer _iconRenderer;

			private readonly TextMeshPro _countText;

			public WarehouseHaulerIndicator(Storage storage)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Expected O, but got Unknown
				//IL_002a: 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_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_0056: Expected O, but got Unknown
				//IL_0083: 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_009e: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cf: Expected O, but got Unknown
				//IL_0108: Unknown result type (might be due to invalid IL or missing references)
				//IL_010e: Expected O, but got Unknown
				//IL_013b: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b6: 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)
				_storage = storage;
				_root = new GameObject("StockAlertWarehouseHaulers");
				_root.transform.localScale = Vector3.one * 0.62f;
				_root.AddComponent<BillboardToCamera>();
				GameObject val = new GameObject("Icon");
				val.transform.SetParent(_root.transform, false);
				val.transform.localPosition = new Vector3(-0.12f, 0f, 0f);
				val.transform.localScale = Vector3.one * 1.5f;
				_iconRenderer = val.AddComponent<SpriteRenderer>();
				((Renderer)_iconRenderer).material = new Material(Shader.Find("Sprites/Default"));
				_iconRenderer.sprite = GetHaulerSprite();
				((Renderer)_iconRenderer).sortingLayerName = "UI";
				((Renderer)_iconRenderer).sortingOrder = 5100;
				GameObject val2 = new GameObject("Count");
				val2.transform.SetParent(_root.transform, false);
				val2.transform.localPosition = new Vector3(0.26f, -0.03f, 0f);
				_countText = val2.AddComponent<TextMeshPro>();
				((TMP_Text)_countText).font = TMP_Settings.defaultFontAsset;
				((TMP_Text)_countText).alignment = (TextAlignmentOptions)514;
				((TMP_Text)_countText).textWrappingMode = (TextWrappingModes)0;
				((TMP_Text)_countText).fontSize = 5f;
				((TMP_Text)_countText).fontStyle = (FontStyles)1;
				((Graphic)_countText).color = Color.white;
				((TMP_Text)_countText).outlineColor = Color32.op_Implicit(Color.black);
				((TMP_Text)_countText).outlineWidth = 0.25f;
				_countText.renderer.sortingLayerName = "UI";
				_countText.renderer.sortingOrder = 5101;
			}

			public void Show(int haulers)
			{
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_root == (Object)null))
				{
					if ((Object)(object)_countText != (Object)null)
					{
						((TMP_Text)_countText).text = haulers.ToString();
						((Behaviour)_countText).enabled = true;
					}
					if ((Object)(object)_iconRenderer != (Object)null)
					{
						_iconRenderer.sprite = GetHaulerSprite();
					}
					_root.transform.position = GetMarkerWorldPosition(_storage);
					if (!_root.activeSelf)
					{
						_root.SetActive(true);
					}
				}
			}

			private static Vector3 GetMarkerWorldPosition(Storage storage)
			{
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0150: 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_00f1: 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_011f: Unknown result type (might be due to invalid IL or missing references)
				//IL_012b: 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_0147: Unknown result type (might be due to invalid IL or missing references)
				//IL_014c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c7: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
				object obj;
				if (storage == null)
				{
					obj = null;
				}
				else
				{
					BuildingView buildingView = ((Building)storage).BuildingView;
					if (buildingView == null)
					{
						obj = null;
					}
					else
					{
						Transform transform = ((Component)buildingView).transform;
						obj = ((transform != null) ? transform.Find("ToRotate/UI/NoWorkersIcon") : null);
					}
				}
				Transform val = (Transform)obj;
				if ((Object)(object)val != (Object)null)
				{
					return val.position;
				}
				Renderer[] array = (((Object)(object)((storage != null) ? ((Building)storage).BuildingView : null) != (Object)null) ? (from renderer in ((Component)((Building)storage).BuildingView).GetComponentsInChildren<Renderer>(true)
					where (Object)(object)renderer != (Object)null && !IsHaulerIndicatorRenderer(((Component)renderer).transform)
					select renderer).ToArray() : Array.Empty<Renderer>());
				if (array.Length == 0)
				{
					return ((Object)(object)((storage != null) ? ((Building)storage).BuildingView : null) != (Object)null) ? (((Component)((Building)storage).BuildingView).transform.position + new Vector3(0f, 2.4f, 0f)) : Vector3.zero;
				}
				Bounds bounds = array[0].bounds;
				for (int num = 1; num < array.Length; num++)
				{
					((Bounds)(ref bounds)).Encapsulate(array[num].bounds);
				}
				return new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).max.y + 0.45f, ((Bounds)(ref bounds)).center.z);
			}

			private static bool IsHaulerIndicatorRenderer(Transform transform)
			{
				while ((Object)(object)transform != (Object)null)
				{
					if (string.Equals(((Object)transform).name, "StockAlertWarehouseHaulers", StringComparison.Ordinal))
					{
						return true;
					}
					transform = transform.parent;
				}
				return false;
			}

			public void Destroy()
			{
				if ((Object)(object)_root != (Object)null)
				{
					Object.Destroy((Object)(object)_root);
				}
			}
		}

		private sealed class BillboardToCamera : MonoBehaviour
		{
			private void LateUpdate()
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				Camera main = Camera.main;
				if ((Object)(object)main != (Object)null)
				{
					((Component)this).transform.forward = ((Component)main).transform.forward;
				}
			}
		}

		private static readonly Dictionary<int, WarehouseHaulerIndicator> ActiveIndicators = new Dictionary<int, WarehouseHaulerIndicator>();

		private static readonly FieldInfo LakePanelRetrieveButtonField = typeof(LakePanel).GetField("retrieveButton", BindingFlags.Instance | BindingFlags.NonPublic);

		private static Sprite _haulerSprite;

		private static Sprite _fallbackHaulerSprite;

		public static void Refresh()
		{
			if (!GameAPI.IsGameActive())
			{
				Clear();
				return;
			}
			HashSet<int> seenStorages = new HashSet<int>();
			foreach (Storage storageBuilding in GameAPI.GetStorageBuildings())
			{
				if ((Object)(object)((storageBuilding != null) ? ((Building)storageBuilding).BuildingView : null) == (Object)null || ((Building)storageBuilding).BuildingState == null || !((Building)storageBuilding).BuildingState.finished || ((Building)storageBuilding).BuildingState.isSleeping)
				{
					continue;
				}
				int num = ((ProductionBuilding)storageBuilding).CountWorkers();
				if (num > 0)
				{
					seenStorages.Add(((Building)storageBuilding).Id);
					if (!ActiveIndicators.TryGetValue(((Building)storageBuilding).Id, out var value))
					{
						value = new WarehouseHaulerIndicator(storageBuilding);
						ActiveIndicators[((Building)storageBuilding).Id] = value;
					}
					value.Show(num);
				}
			}
			List<int> list = ActiveIndicators.Keys.Where((int id) => !seenStorages.Contains(id)).ToList();
			foreach (int item in list)
			{
				ActiveIndicators[item].Destroy();
				ActiveIndicators.Remove(item);
			}
		}

		public static void Clear()
		{
			foreach (WarehouseHaulerIndicator value in ActiveIndicators.Values)
			{
				value.Destroy();
			}
			ActiveIndicators.Clear();
		}

		private static Sprite GetHaulerSprite()
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_haulerSprite != (Object)null)
			{
				return _haulerSprite;
			}
			_haulerSprite = TryGetPondNetsSprite();
			if ((Obje