Decompiled source of StockAlert v1.2.6
StockAlert.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
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.Controller.Buildings; 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.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("StockAlert")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+1549a8b51e2e45eb49390cb6978a96fb90b3c5b2")] [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.6"; } } 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_0060: 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_0047: 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_001b: 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() || (Object)(object)((Actor)builderVillager).ActorView == (Object)null) { continue; } Sprite statusSprite = GetStatusSprite(IsVillagerIdle(builderVillager)); 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); } } foreach (int item in ActiveIndicators.Keys.Where((int id) => !seenVillagers.Contains(id)).ToList()) { ActiveIndicators[item].Destroy(); ActiveIndicators.Remove(item); } } } private static Sprite GetStatusSprite(bool isIdle) { if (isIdle) { if (!ConfigManager.ShowIdleBuilderStatusIcons) { return null; } return _idleSprite; } if (!ConfigManager.ShowBusyBuilderStatusIcons) { return null; } return _builderSprite; } 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) { if (!((Object)(object)villager.raceModel != (Object)null)) { return villager.Race; } return villager.raceModel.GetDisplayNameFor(count); } 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 obj2 = _piVillagersService?.GetValue(null, null); if (obj2 == null) { yield break; } if ((object)_piVillagers == null) { _piVillagers = obj2.GetType().GetProperty("Villagers", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } if (!(_piVillagers?.GetValue(obj2, null) is IDictionary dictionary)) { yield break; } foreach (DictionaryEntry item in dictionary) { object? value = item.Value; Villager val = (Villager)((value is Villager) ? value : null); if (val != null && string.Equals(((Actor)val).Profession, builderProfession, StringComparison.OrdinalIgnoreCase)) { yield return val; } } } private static bool IsVillagerIdle(Villager villager) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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; } if ((Object)(object)_idleSprite != (Object)null) { return (Object)(object)_builderSprite != (Object)null; } return false; } 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); if (componentInChildren == null) { return null; } return componentInChildren.sprite; } 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); if (componentInChildren == null) { return null; } return componentInChildren.sprite; } 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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_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) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (Active == other.Active) { Color color = Color; if (((Color)(ref color)).Equals(other.Color) && ShowProductIcons == other.ShowProductIcons && Mathf.Approximately(ProductIconScale, other.ProductIconScale)) { return string.Equals(ProductGoodsKey, other.ProductGoodsKey, StringComparison.Ordinal); } } return false; } 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 (Mine mineBuilding in GameAPI.GetMineBuildings()) { if (!((Object)(object)mineBuilding == (Object)null)) { seenBuildings.Add(((Building)mineBuilding).Id); ApplyMineIndicatorState(mineBuilding, 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); } } foreach (int item in LastApplied.Keys.Where((int id) => !seenBuildings.Contains(id)).ToList()) { 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 (Mine mineBuilding in GameAPI.GetMineBuildings()) { if ((Object)(object)mineBuilding != (Object)null && hashSet.Add(((Building)mineBuilding).Id)) { RestoreVanillaFor((ProductionBuilding)(object)mineBuilding); } } 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: 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_00ef: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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_0113: 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> demandedRecipeGoods = GetDemandedRecipeGoods(workshop, lowGoods); bool flag = demandedRecipeGoods.Count > 0; bool flag2 = flag && HasCraftableDemandedRecipe(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) ? demandedRecipeGoods : null); } } private static void ApplyGatheringIndicatorState(ProductionBuilding building, HashSet<string> blockedIngredientGoods) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) 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 ApplyMineIndicatorState(Mine mine, 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_00a9: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) BuildingView buildingView = ((Building)mine).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)mine).CountWorkers(); WorkplaceModel[] workplaces = ((ProductionBuilding)mine).Workplaces; int num2 = ((workplaces != null) ? workplaces.Length : 0); List<string> relevantMineGoods = GetRelevantMineGoods(mine, blockedIngredientGoods); bool flag = relevantMineGoods.Count > 0; bool flag2 = false; Color color = WhiteColor; if (num == 0) { flag2 = true; color = (flag ? RedColor : WhiteColor); } else if (flag && num < num2) { flag2 = true; color = YellowColor; } ApplySnapshot(((Building)mine).Id, val, flag2, color, (flag2 && flag && ConfigManager.ShowBuildingSpecificItemIndicators) ? relevantMineGoods : null); } } private static void ApplyFarmIndicatorState(Farm farm) { //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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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)) { return true; } } } return false; } private static List<string> GetRelevantMineGoods(Mine mine, HashSet<string> blockedIngredientGoods) { List<string> list = new List<string>(); if (mine?.state?.recipes == null || blockedIngredientGoods == null || blockedIngredientGoods.Count == 0) { return list; } foreach (RecipeState recipe in mine.state.recipes) { if (recipe != null && recipe.active && mine.CanGather(recipe)) { MineRecipeModel recipeModel = mine.GetRecipeModel(recipe); string text = ((recipeModel != null) ? ((RecipeModel)recipeModel).GetProducedGood() : null); if (!string.IsNullOrWhiteSpace(text) && blockedIngredientGoods.Contains(text) && mine.GetChargesLeft(text) > 0 && !list.Contains<string>(text, StringComparer.OrdinalIgnoreCase)) { list.Add(text); } } } return list; } 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_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_0009: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)icon == (Object)null) { return Color.clear; } SpriteRenderer val = GetBaseIconRenderers(icon).FirstOrDefault(); if (!((Object)(object)val != (Object)null)) { return Color.clear; } return val.color; } private static List<string> GetDemandedRecipeGoods(IWorkshop workshop, HashSet<string> lowGoods) { List<string> list = new List<string>(); if (((workshop != null) ? workshop.Recipes : null) == null) { return list; } foreach (WorkshopRecipeState recipe in workshop.Recipes) { if (IsDemandedRecipe(workshop, 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 HasCraftableDemandedRecipe(IWorkshop workshop, HashSet<string> lowGoods, Settings settings) { if (((workshop != null) ? workshop.Recipes : null) == null || (Object)(object)settings == (Object)null) { return false; } foreach (WorkshopRecipeState recipe in workshop.Recipes) { if (IsDemandedRecipe(workshop, 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) 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) / 2.08f; float num2 = num * 0.08f; float num3 = Mathf.Max(rendererSizeInIconSpace.x * 0.55f + num * 0.5f, num * 1.15f); int num4 = 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, num4); 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 num5 = num4 % 2; int num6 = num4 / 2; float num7 = ((num5 == 0) ? ((num + num2) * 0.5f) : ((0f - (num + num2)) * 0.5f)); orCreateProductIcon.transform.localPosition = new Vector3(num3 + (float)num6 * (num + num2), num7, 0f); orCreateProductIcon.transform.localRotation = Quaternion.identity; orCreateProductIcon.transform.localScale = Vector3.one * GetScaleForHeight(val2, num); orCreateProductIcon.SetActive(true); num4++; } } } for (int num8 = num4; num8 < orCreateProductIconsRoot.transform.childCount; num8++) { ((Component)orCreateProductIconsRoot.transform.GetChild(num8)).gameObject.SetActive(false); } orCreateProductIconsRoot.SetActive(num4 > 0); if (num4 == 0) { DestroyProductIcons(icon); LastApplied.Remove(buildingId); } } private static GameObject GetOrCreateProductIconsRoot(GameObject icon) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0052: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown 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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_0037: Expected O, but got Unknown while (root.transform.childCount <= index) { GameObject val = new GameObject("ProductIcon"); val.transform.SetParent(root.transform, false); ((Renderer)val.AddComponent<SpriteRenderer>()).material = new Material(Shader.Find("Sprites/Default")); } return ((Component)root.transform.GetChild(index)).gameObject; } private static void RefreshProductIconRenderOrder(GameObject icon) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) 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 obj2 in componentsInChildren) { int offset = ((!IsBorderPart(((Component)obj2).transform)) ? 1 : 2); ConfigureProductIconRenderer(obj2, val, offset); } } } private static void ApplyProductIconBorder(GameObject productIcon, Sprite sprite, bool active, SpriteRenderer baseRenderer) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_0031: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown 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_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown GameObject val = new GameObject(name); val.transform.SetParent(parent, false); SpriteRenderer obj = val.AddComponent<SpriteRenderer>(); obj.sprite = GetSolidSprite(); ((Renderer)obj).material = new Material(Shader.Find("Sprites/Default")); } private static void ConfigureBorderPart(SpriteRenderer renderer, float x, float y, float width, float height, SpriteRenderer baseRenderer) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0053: 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) { if ((Object)(object)((transform != null) ? transform.parent : null) != (Object)null) { return string.Equals(((Object)transform.parent).name, "IngredientBlockedBorder", StringComparison.Ordinal); } return false; } private static Vector2 GetRendererSizeInIconSpace(Transform iconTransform, SpriteRenderer renderer) { //IL_001d: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_00ad: 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_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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; if (!(num2 > 0.001f)) { return 1f; } return targetHeight / num2; } private static Sprite GetSolidSprite() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown 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 icon; if (buildingView == null) { icon = null; } else { Transform transform = ((Component)buildingView).transform; if (transform == null) { icon = null; } else { Transform obj2 = transform.Find("ToRotate/UI/NoWorkersIcon"); icon = ((obj2 != null) ? ((Component)obj2).gameObject : null); } } DestroyProductIcons((GameObject)icon); return; } foreach (Farm farmBuilding in GameAPI.GetFarmBuildings()) { if (farmBuilding == null || ((Building)farmBuilding).Id != buildingId) { continue; } BuildingView buildingView2 = ((Building)farmBuilding).BuildingView; object icon2; if (buildingView2 == null) { icon2 = null; } else { Transform transform2 = ((Component)buildingView2).transform; if (transform2 == null) { icon2 = null; } else { Transform obj3 = transform2.Find("ToRotate/UI/NoWorkersIcon"); icon2 = ((obj3 != null) ? ((Component)obj3).gameObject : null); } } DestroyProductIcons((GameObject)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_008a: 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_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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) if (Mathf.Approximately(a.r, b.r) && Mathf.Approximately(a.g, b.g) && Mathf.Approximately(a.b, b.b)) { return Mathf.Approximately(a.a, b.a); } return false; } private static void MakeIconClickThrough(GameObject icon) { if ((Object)(object)icon == (Object)null) { return; } Graphic[] componentsInChildren = icon.GetComponentsInChildren<Graphic>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].raycastTarget = false; } Selectable[] componentsInChildren2 = icon.GetComponentsInChildren<Selectable>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].interactable = false; } GraphicRaycaster[] componentsInChildren3 = icon.GetComponentsInChildren<GraphicRaycaster>(true); for (int i = 0; i < componentsInChildren3.Length; i++) { ((Behaviour)componentsInChildren3[i]).enabled = false; } EventTrigger[] componentsInChildren4 = icon.GetComponentsInChildren<EventTrigger>(true); for (int i = 0; i < componentsInChildren4.Length; i++) { ((Behaviour)componentsInChildren4[i]).enabled = false; } Component[] componentsInChildren5 = icon.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren5) { Type type = ((object)val)?.GetType(); if (!(type == null) && type.Name.IndexOf("Collider", StringComparison.Ordinal) >= 0) { PropertyInfo property = type.GetProperty("enabled"); if (property != null && property.CanWrite) { property.SetValue(val, false, null); } } } } private static bool IsDemandedRecipe(IWorkshop workshop, WorkshopRecipeState recipeState, HashSet<string> lowGoods) { if (recipeState == null || !((RecipeState)recipeState).active || string.IsNullOrWhiteSpace(recipeState.productName)) { return false; } if (lowGoods == null || !lowGoods.Contains(recipeState.productName)) { return IsBelowLocalRecipeLimit(workshop, recipeState); } return true; } private static bool IsBelowLocalRecipeLimit(IWorkshop workshop, WorkshopRecipeState recipeState) { if ((Object)(object)((workshop != null) ? workshop.Base : null) == (Object)null || recipeState == null || !recipeState.isLimitLocal || recipeState.limit <= 0 || string.IsNullOrWhiteSpace(recipeState.productName)) { return false; } return GetCombinedStoredAmount(workshop.Base, recipeState.productName) < recipeState.limit; } private static int GetCombinedStoredAmount(ProductionBuilding building, string goodId) { if ((Object)(object)building == (Object)null || string.IsNullOrWhiteSpace(goodId)) { return 0; } int storedAmount = GameAPI.GetStoredAmount(null, goodId); BuildingStorage productionStorage = building.ProductionStorage; int num = ((productionStorage != null) ? productionStorage.GetAmount(goodId) : 0); return storedAmount + num; } 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); if (val?.requiredGoods != null) { return val.requiredGoods.Length == 0; } return true; } } [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 static class ForestEaterDirectionOverlay { private sealed class PathMarker { private readonly GameObject _root; private readonly LineRenderer _pathLine; private readonly LineRenderer _leftHead; private readonly LineRenderer _rightHead; public PathMarker(int index, Material material) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown _root = new GameObject("StockAlertForestEaterDirection_" + index); _pathLine = CreateLine("Path", material, 0.18f); _leftHead = CreateLine("ArrowLeft", material, 0.18f); _rightHead = CreateLine("ArrowRight", material, 0.18f); } public void SetPath(List<Vector3> points) { if (!((Object)(object)_root == (Object)null) && points != null && points.Count >= 2) { _root.SetActive(true); _pathLine.positionCount = points.Count; _pathLine.SetPositions(points.ToArray()); SetArrowHead(points); } } public void Destroy() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } } private LineRenderer CreateLine(string name, Material material, float width) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(_root.transform, false); LineRenderer obj = val.AddComponent<LineRenderer>(); obj.useWorldSpace = true; ((Renderer)obj).material = material; obj.startColor = new Color(1f, 0.9f, 0.15f, 0.92f); obj.endColor = new Color(1f, 0.75f, 0.05f, 0.92f); obj.startWidth = width; obj.endWidth = width; obj.numCapVertices = 4; obj.numCornerVertices = 4; obj.textureMode = (LineTextureMode)0; return obj; } private void SetArrowHead(List<Vector3> points) { //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_0023: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_00a2: 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_00b9: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012b: 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) //IL_0136: Unknown result type (might be due to invalid IL or missing references) Vector3 val = points[0]; Vector3 val2 = ((points.Count > 1) ? points[1] : points[points.Count - 1]); Vector3 val3 = val2 - val; val3.y = 0f; if (((Vector3)(ref val3)).sqrMagnitude < 0.001f) { val3 = points[points.Count - 1] - points[0]; val3.y = 0f; } if (((Vector3)(ref val3)).sqrMagnitude < 0.001f) { _leftHead.positionCount = 0; _rightHead.positionCount = 0; return; } ((Vector3)(ref val3)).Normalize(); Vector3 val4 = default(Vector3); ((Vector3)(ref val4))..ctor(0f - val3.z, 0f, val3.x); Vector3 val5 = val2; Vector3 val6 = val5 - val3 * 0.55f; _leftHead.positionCount = 2; _leftHead.SetPosition(0, val5); _leftHead.SetPosition(1, val6 + val4 * 0.35f); _rightHead.positionCount = 2; _rightHead.SetPosition(0, val5); _rightHead.SetPosition(1, val6 - val4 * 0.35f); } } private const float LineHeight = 1.25f; private const float LineWidth = 0.18f; private const float ArrowLength = 0.55f; private const float ArrowWidth = 0.35f; private static readonly Dictionary<int, PathMarker> Markers = new Dictionary<int, PathMarker>(); private static Material _lineMaterial; public static void Refresh() { if (!ConfigManager.ShowForestEaterDirection || !GameAPI.IsGameActive()) { Clear(); return; } List<GameAPI.ForestEaterDirectionInfo> forestEaterDirections = GameAPI.GetForestEaterDirections(); HashSet<int> seen = new HashSet<int>(); foreach (GameAPI.ForestEaterDirectionInfo item in forestEaterDirections) { if (item != null && TryBuildPath(item, out var points)) { seen.Add(item.Index); if (!Markers.TryGetValue(item.Index, out var value) || value == null) { value = new PathMarker(item.Index, GetLineMaterial()); Markers[item.Index] = value; } value.SetPath(points); } } foreach (int item2 in Markers.Keys.Where((int key) => !seen.Contains(key)).ToList()) { Markers[item2]?.Destroy(); Markers.Remove(item2); } } public static void Clear() { foreach (PathMarker value in Markers.Values) { value?.Destroy(); } Markers.Clear(); } private static bool TryBuildPath(GameAPI.ForestEaterDirectionInfo direction, out List<Vector3> points) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) points = new List<Vector3>(); if (direction == null) { return false; } List<Vector2Int> currentPath = direction.CurrentPath; if (currentPath != null && currentPath.Count > 0) { int num = currentPath.IndexOf(direction.Current); if (num < 0) { num = 0; } for (int i = num; i < currentPath.Count; i++) { AddPoint(points, currentPath[i]); } } Vector3 val; if (points.Count == 0) { AddPoint(points, direction.Current); AddPoint(points, direction.Target); } else { val = points[points.Count - 1] - ToWorld(direction.Target); if (((Vector3)(ref val)).sqrMagnitude > 0.05f) { AddPoint(points, direction.Target); } } if (points.Count >= 2) { val = points[0] - points[points.Count - 1]; return ((Vector3)(ref val)).sqrMagnitude > 0.05f; } return false; } private static void AddPoint(List<Vector3> points, Vector2Int field) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ToWorld(field); if (points.Count != 0) { Vector3 val2 = points[points.Count - 1] - val; if (!(((Vector3)(ref val2)).sqrMagnitude > 0.05f)) { return; } } points.Add(val); } private static Vector3 ToWorld(Vector2Int field) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) return VectorExtensions.ToWorld(field) + new Vector3(0.5f, 1.25f, 0.5f); } private static Material GetLineMaterial() { //IL_002b: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_lineMaterial != (Object)null) { return _lineMaterial; } _lineMaterial = new Material(Shader.Find("GUI/Text Shader") ?? Shader.Find("Sprites/Default")) { name = "StockAlertForestEaterDirectionMaterial", renderQueue = 4000 }; _lineMaterial.SetInt("_ZTest", 8); _lineMaterial.SetInt("_ZWrite", 0); _lineMaterial.color = new Color(1f, 0.9f, 0.15f, 0.9f); return _lineMaterial; } } internal static class HearthLevelDownAlert { private static readonly List<News> ActiveAlerts = new List<News>(); public static void Fire(Hearth hearth, int previousLevel, int currentLevel) { if (ConfigManager.HearthLevelDownAlert && GameAPI.IsGameActive() && !((Object)(object)hearth == (Object)null)) { string displayName = GetDisplayName(hearth); string text = FormatLevel(previousLevel); string text2 = FormatLevel(currentLevel); string content = displayName + " decreased from " + text + " to " + text2 + "."; string description = "Check housing, decorations, and service buildings inside the Hearth's range."; News val = GameAPI.PublishNews(content, description, (AlertSeverity)2); if (val != null) { ActiveAlerts.Add(val); } } } public static void Refresh() { if (!ConfigManager.HearthLevelDownAlert || !GameAPI.IsGameActive()) { Clear(); } } public static void Clear() { foreach (News item in ActiveAlerts.ToList()) { GameAPI.RemoveNews(item); } ActiveAlerts.Clear(); } private static string GetDisplayName(Hearth hearth) { BuildingModel buildingModel = ((Building)hearth).BuildingModel; object obj; if (buildingModel == null) { obj = null; } else { LocaText displayName = buildingModel.displayName; obj = ((displayName != null) ? displayName.Text : null); } string text = (string)obj; if (!string.IsNullOrWhiteSpace(text)) { return text; } if (!hearth.IsMainHearth()) { return "Hearth"; } return "Ancient Hearth"; } private static string FormatLevel(int levelIndex) { if (levelIndex < 0) { return "level 0"; } return "level " + (levelIndex + 1); } } 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) 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); } foreach (string item2 in Markers.Keys.Where((string key) => !seen.Contains(key)).ToList()) { 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_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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_0055: 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); for (int i = 0; i < componentsInChildren.Length; i++) { ((Graphic)componentsInChildren[i]).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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: 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_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0123: 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_0180: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: 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_001c: 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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_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) if ((Object)(object)component != (Object)null) { Scene scene = component.gameObject.scene; return ((Scene)(ref scene)).IsValid(); } return false; } } internal static class MissionObjectiveLoadAlert { private static News _activeNews; public static void Fire() { if (!ConfigManager.MissionObjectiveLoadAlert || !GameAPI.IsGameActive()) { Clear(); return; } Clear(); _activeNews = GameAPI.PublishNews("Save loaded: check mission objective.", "Review your settlement objective before unpausing or making changes.", (AlertSeverity)1); } public static void Clear() { if (_activeNews != null) { GameAPI.RemoveNews(_activeNews); _activeNews = null; } } } 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_00e8: Unknown r