using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Eremite; using Eremite.Buildings; using Eremite.Buildings.UI; using Eremite.Characters; using Eremite.Characters.Villagers; using Eremite.MapObjects; using Eremite.MapObjects.UI; using Eremite.Model; using Eremite.Model.Configs; using Eremite.Model.Meta; using Eremite.Model.State; using Eremite.Services; using Eremite.Services.Monitors; using Eremite.View.HUD; using Eremite.View.HUD.Monitors; using Eremite.View.HUD.TradeRoutes; using Eremite.View.Menu.Pick; using Eremite.View.UI; using HarmonyLib; using Microsoft.CodeAnalysis; using StockAlert.Config; using StockAlert.Core.Models; using StockAlert.Game; using StockAlert.Game.Discovery; using StockAlert.Infrastructure.Bootstrap; using StockAlert.Infrastructure.Plugin; using StockAlert.UI.HUD; using StockAlert.UI.Panels; using StockAlert.UI.World; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("StockAlert")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+83db0f3a9403369fd5cb6d6c1db7f7fe789d8f9b")] [assembly: AssemblyProduct("StockAlert")] [assembly: AssemblyTitle("StockAlert")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.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.1.8"; } } namespace StockAlert.UI.World { internal static class BuilderStatusIndicators { private sealed class BuilderIndicator { private readonly GameObject _iconObject; private readonly SpriteRenderer _renderer; private readonly Transform _transform; public BuilderIndicator(Villager villager) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) _iconObject = new GameObject("BuilderStatusIcon"); _renderer = _iconObject.AddComponent(); ((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(); } public void Show(Sprite sprite) { if (!((Object)(object)_renderer == (Object)null) && !((Object)(object)sprite == (Object)null)) { if ((Object)(object)_renderer.sprite != (Object)(object)sprite) { _renderer.sprite = sprite; } UpdateScale(sprite); if (!((Renderer)_renderer).enabled) { ((Renderer)_renderer).enabled = true; } } } private void UpdateScale(Sprite sprite) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_transform == (Object)null) && !((Object)(object)sprite == (Object)null)) { Bounds bounds = sprite.bounds; Vector3 size = ((Bounds)(ref bounds)).size; float num = Mathf.Max(size.x, size.y); if (num <= 0.001f) { _transform.localScale = Vector3.one; return; } float num2 = 0.5f / num; _transform.localScale = Vector3.one * num2; } } public void Destroy() { if ((Object)(object)_iconObject != (Object)null) { Object.Destroy((Object)(object)_iconObject); } } } private sealed class BillboardToCamera : MonoBehaviour { private void LateUpdate() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; if ((Object)(object)main != (Object)null) { ((Component)this).transform.forward = ((Component)main).transform.forward; } } } private static readonly Dictionary ActiveIndicators = new Dictionary(); 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 seenVillagers = new HashSet(); foreach (Villager builderVillager in GetBuilderVillagers()) { if ((Object)(object)builderVillager == (Object)null || !builderVillager.IsAlive()) { continue; } ActorView actorView = ((Actor)builderVillager).ActorView; if ((Object)(object)actorView == (Object)null) { continue; } seenVillagers.Add(((Actor)builderVillager).Id); Sprite val = (IsVillagerIdle(builderVillager) ? _idleSprite : _builderSprite); if (!((Object)(object)val == (Object)null)) { if (!ActiveIndicators.TryGetValue(((Actor)builderVillager).Id, out var value)) { value = new BuilderIndicator(builderVillager); ActiveIndicators[((Actor)builderVillager).Id] = value; } value.Show(val); } } List list = ActiveIndicators.Keys.Where((int id) => !seenVillagers.Contains(id)).ToList(); foreach (int item in list) { ActiveIndicators[item].Destroy(); ActiveIndicators.Remove(item); } } } 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 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 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 GetIdleBuilderRaceIds() { HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (Villager builderVillager in GetBuilderVillagers()) { if (!((Object)(object)builderVillager == (Object)null) && builderVillager.IsAlive() && IsVillagerIdle(builderVillager)) { if (!string.IsNullOrWhiteSpace(builderVillager.Race)) { hashSet.Add(builderVillager.Race); } RaceModel raceModel = builderVillager.raceModel; if (!string.IsNullOrWhiteSpace((raceModel != null) ? ((SO)raceModel).Name : null)) { hashSet.Add(((SO)builderVillager.raceModel).Name); } } } return hashSet; } private static string GetRaceDisplayName(Villager villager, int count) { return ((Object)(object)villager.raceModel != (Object)null) ? villager.raceModel.GetDisplayNameFor(count) : villager.Race; } private static IEnumerable GetBuilderVillagers() { Settings settings = GameAPI.GetSettings(); object obj; if (settings == null) { obj = null; } else { ProfessionModel defaultProfession = settings.DefaultProfession; obj = ((defaultProfession != null) ? ((SO)defaultProfession).Name : null); } string builderProfession = (string)obj; if (string.IsNullOrWhiteSpace(builderProfession)) { yield break; } if (_piVillagersService == null) { _piVillagersService = typeof(GameMB).GetProperty("VillagersService", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } object villagersService = _piVillagersService?.GetValue(null, null); if (villagersService == null) { yield break; } if ((object)_piVillagers == null) { _piVillagers = villagersService.GetType().GetProperty("Villagers", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } if (!(_piVillagers?.GetValue(villagersService, null) is IDictionary villagers)) { yield break; } foreach (DictionaryEntry item in villagers) { object value = item.Value; Villager villager = (Villager)((value is Villager) ? value : null); if (villager != null && string.Equals(((Actor)villager).Profession, builderProfession, StringComparison.OrdinalIgnoreCase)) { yield return villager; } } } private static bool IsVillagerIdle(Villager villager) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Invalid comparison between Unknown and I4 try { if ((object)_fiActorBrain == null) { _fiActorBrain = typeof(Actor).GetField("brain", BindingFlags.Instance | BindingFlags.NonPublic); } object obj = _fiActorBrain?.GetValue(villager); if (obj == null) { return false; } if ((object)_fiBrainStack == null) { _fiBrainStack = obj.GetType().GetField("stack", BindingFlags.Instance | BindingFlags.NonPublic); } if (!(_fiBrainStack?.GetValue(obj) is Stack stack) || stack.Count == 0) { return false; } ActorTask val = stack.Peek(); return val != null && (int)val.WorkStatus == 0; } catch (Exception) { return false; } } private static bool EnsureSprites() { if ((Object)(object)_idleSprite == (Object)null) { _idleSprite = FindHudSprite("/HUD/GoodsHUD/SacrificeMarker/Content") ?? GameAPI.GetSettings()?.monitorsConfig?.noBuildersIcon; } if ((Object)(object)_builderSprite == (Object)null) { _builderSprite = FindBuilderHudSprite() ?? GameAPI.GetSettings()?.monitorsConfig?.noBuildersIcon; } return (Object)(object)_idleSprite != (Object)null && (Object)(object)_builderSprite != (Object)null; } private static Sprite FindBuilderHudSprite() { RacesStatsHUD val = Object.FindObjectOfType(); 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(true); return (componentInChildren != null) ? componentInChildren.sprite : null; } private static Sprite FindHudSprite(string path) { if (string.IsNullOrWhiteSpace(path)) { return null; } GameObject val = GameObject.Find(path); if ((Object)(object)val == (Object)null) { return null; } Image component = val.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.sprite != (Object)null) { return component.sprite; } Image componentInChildren = val.GetComponentInChildren(true); return (componentInChildren != null) ? componentInChildren.sprite : null; } private static Transform FindDescendantByName(Transform root, string name) { if ((Object)(object)root == (Object)null) { return null; } for (int i = 0; i < root.childCount; i++) { Transform child = root.GetChild(i); if (string.Equals(((Object)child).name, name, StringComparison.Ordinal)) { return child; } Transform val = FindDescendantByName(child, name); if ((Object)(object)val != (Object)null) { return val; } } return null; } } internal static class BuildingAlertIndicators { private readonly struct IndicatorSnapshot : IEquatable { 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 productGoodIds) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) Active = active; Color = color; ShowProductIcons = ConfigManager.ShowBuildingSpecificItemIndicators; ProductIconScale = ConfigManager.BuildingShortageIconScale; ProductGoodsKey = ((productGoodIds == null || productGoodIds.Count == 0) ? string.Empty : string.Join("|", productGoodIds.Select(BuildProductGoodsKey))); } public bool Equals(IndicatorSnapshot other) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) int result; if (Active == other.Active) { Color color = Color; if (((Color)(ref color)).Equals(other.Color) && ShowProductIcons == other.ShowProductIcons && Mathf.Approximately(ProductIconScale, other.ProductIconScale)) { result = (string.Equals(ProductGoodsKey, other.ProductGoodsKey, StringComparison.Ordinal) ? 1 : 0); goto IL_0060; } } result = 0; goto IL_0060; IL_0060: return (byte)result != 0; } private static string BuildProductGoodsKey(string goodId) { GoodInfo goodInfo = Discovery.Goods.FirstOrDefault((GoodInfo g) => string.Equals(g.Id, goodId, StringComparison.OrdinalIgnoreCase)); return goodId + ((goodInfo != null && goodInfo.IsIngredientBlocked) ? ":blocked" : ":normal"); } } private const int MaxProductIcons = 4; private const int ProductIconGridRows = 2; private const 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 BorderRedColor = new Color(0.62f, 0.04f, 0.04f, 1f); private static readonly Dictionary LastApplied = new Dictionary(); private static Sprite _solidSprite; public static void Refresh() { if (!ConfigManager.ShowBuildingAlertIndicators) { RestoreVanilla(); return; } Settings settings = GameAPI.GetSettings(); HashSet lowGoods = new HashSet(from g in Discovery.Goods where g.IsBelowThreshold select g.Id, StringComparer.OrdinalIgnoreCase); HashSet blockedIngredientGoods = new HashSet(Discovery.BlockedIngredientGoods, StringComparer.OrdinalIgnoreCase); HashSet seenBuildings = new HashSet(); foreach (IWorkshop recipeBuilding in GetRecipeBuildings()) { ProductionBuilding @base = recipeBuilding.Base; if (!((Object)(object)@base == (Object)null)) { seenBuildings.Add(((Building)@base).Id); ApplyIndicatorState(@base, recipeBuilding, lowGoods, blockedIngredientGoods, settings); } } foreach (ProductionBuilding gatheringSourceBuilding in GameAPI.GetGatheringSourceBuildings()) { if (!((Object)(object)gatheringSourceBuilding == (Object)null)) { seenBuildings.Add(((Building)gatheringSourceBuilding).Id); ApplyGatheringIndicatorState(gatheringSourceBuilding, blockedIngredientGoods); } } List list = LastApplied.Keys.Where((int id) => !seenBuildings.Contains(id)).ToList(); foreach (int item in list) { RemoveProductIcons(item); LastApplied.Remove(item); } } public static void RefreshForView(ProductionBuildingView buildingView) { if (!ConfigManager.ShowBuildingAlertIndicators || (Object)(object)buildingView == (Object)null) { return; } IWorkshop val = GetRecipeBuildings().FirstOrDefault((Func)delegate(IWorkshop w) { object obj; if (w == null) { obj = null; } else { ProductionBuilding @base = w.Base; obj = ((@base != null) ? ((Building)@base).BuildingView : null); } return obj == buildingView; }); if (!((Object)(object)((val != null) ? val.Base : null) == (Object)null)) { Settings settings = GameAPI.GetSettings(); HashSet lowGoods = new HashSet(from g in Discovery.Goods where g.IsBelowThreshold select g.Id, StringComparer.OrdinalIgnoreCase); HashSet blockedIngredientGoods = new HashSet(Discovery.BlockedIngredientGoods, StringComparer.OrdinalIgnoreCase); ApplyIndicatorState(val.Base, val, lowGoods, blockedIngredientGoods, settings); } } public static void RestoreVanilla() { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) foreach (IWorkshop recipeBuilding in GetRecipeBuildings()) { ProductionBuilding @base = recipeBuilding.Base; if ((Object)(object)@base == (Object)null) { continue; } BuildingView buildingView = ((Building)@base).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) { continue; } MakeIconClickThrough(val); bool active = ((Building)@base).BuildingState != null && ((Building)@base).BuildingState.finished && !((Building)@base).BuildingState.isSleeping && @base.CountWorkers() == 0; val.SetActive(active); foreach (SpriteRenderer baseIconRenderer in GetBaseIconRenderers(val)) { baseIconRenderer.color = WhiteColor; } DestroyProductIcons(val); } LastApplied.Clear(); } private static IEnumerable GetRecipeBuildings() { foreach (IWorkshop recipeBuilding in GameAPI.GetRecipeBuildings()) { yield return recipeBuilding; } } private static void ApplyIndicatorState(ProductionBuilding building, IWorkshop workshop, HashSet lowGoods, HashSet blockedIngredientGoods, Settings settings) { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: 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_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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) 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 enabledLowRecipeGoods = GetEnabledLowRecipeGoods(workshop, lowGoods); bool flag = enabledLowRecipeGoods.Count > 0; bool flag2 = workshop.Recipes.Any((WorkshopRecipeState r) => IsEnabledGatheringSupplyRecipe(r, blockedIngredientGoods, settings)); bool flag3 = flag || flag2; bool flag4 = false; Color color = WhiteColor; if (num == 0) { flag4 = true; color = (flag3 ? RedColor : WhiteColor); } else if (flag3 && num < num2) { flag4 = true; color = YellowColor; } ApplySnapshot(((Building)building).Id, val, flag4, color, (flag4 && flag && ConfigManager.ShowBuildingSpecificItemIndicators) ? enabledLowRecipeGoods : null); } } private static void ApplyGatheringIndicatorState(ProductionBuilding building, HashSet blockedIngredientGoods) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) BuildingView buildingView = ((Building)building).BuildingView; object obj; if (buildingView == null) { obj = null; } else { Transform transform = ((Component)buildingView).transform; if (transform == null) { obj = null; } else { Transform obj2 = transform.Find("ToRotate/UI/NoWorkersIcon"); obj = ((obj2 != null) ? ((Component)obj2).gameObject : null); } } GameObject val = (GameObject)obj; if (!((Object)(object)val == (Object)null)) { MakeIconClickThrough(val); int num = building.CountWorkers(); WorkplaceModel[] workplaces = building.Workplaces; int num2 = ((workplaces != null) ? workplaces.Length : 0); bool flag = HasRelevantGatheringRecipe(building, blockedIngredientGoods); bool active = false; Color color = WhiteColor; if (num == 0) { active = true; color = (flag ? RedColor : WhiteColor); } else if (flag && num < num2) { active = true; color = YellowColor; } ApplySnapshot(((Building)building).Id, val, active, color, null); } } private static bool HasRelevantGatheringRecipe(ProductionBuilding building, HashSet blockedIngredientGoods) { if ((Object)(object)((building != null) ? ((Building)building).BuildingModel : null) == (Object)null || blockedIngredientGoods == null || blockedIngredientGoods.Count == 0) { return false; } List recipeStates = GetRecipeStates(building); if (recipeStates == null || recipeStates.Count == 0) { return false; } foreach (string blockedIngredientGood in blockedIngredientGoods) { if (string.IsNullOrWhiteSpace(blockedIngredientGood)) { continue; } Settings settings = GameAPI.GetSettings(); GoodModel val = ((settings != null) ? settings.GetGood(blockedIngredientGood) : null); if ((Object)(object)val == (Object)null || !((Building)building).BuildingModel.IsSourceOf(val)) { continue; } foreach (RecipeState item in recipeStates) { if (item == null || !item.active || !RecipeProducesGood(building, item, blockedIngredientGood)) { continue; } return true; } } return false; } private static List 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 productGoodIds) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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)) { return; } icon.SetActive(active); foreach (SpriteRenderer baseIconRenderer in GetBaseIconRenderers(icon)) { baseIconRenderer.color = color; } ApplyProductIcons(buildingId, icon, active ? productGoodIds : null); LastApplied[buildingId] = indicatorSnapshot; } private static Color GetCurrentIconColor(GameObject icon) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)icon == (Object)null) { return Color.clear; } SpriteRenderer val = GetBaseIconRenderers(icon).FirstOrDefault(); return ((Object)(object)val != (Object)null) ? val.color : Color.clear; } private static List GetEnabledLowRecipeGoods(IWorkshop workshop, HashSet lowGoods) { List list = new List(); if (((workshop != null) ? workshop.Recipes : null) == null || lowGoods == null || lowGoods.Count == 0) { return list; } foreach (WorkshopRecipeState recipe in workshop.Recipes) { if (IsEnabledLowRecipe(recipe, lowGoods) && !list.Any((string g) => string.Equals(g, recipe.productName, StringComparison.OrdinalIgnoreCase))) { list.Add(recipe.productName); if (list.Count >= 4) { break; } } } return list; } private static void ApplyProductIcons(int buildingId, GameObject icon, IReadOnlyList productGoodIds) { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0241: 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 r) => (Object)(object)((r != null) ? r.sprite : null) != (Object)null)); if ((Object)(object)val == (Object)null) { DestroyProductIcons(icon); return; } GameObject orCreateProductIconsRoot = GetOrCreateProductIconsRoot(icon); if ((Object)(object)orCreateProductIconsRoot == (Object)null) { return; } Vector2 rendererSizeInIconSpace = GetRendererSizeInIconSpace(icon.transform, val); float num = Mathf.Max(0.01f, rendererSizeInIconSpace.y * ConfigManager.BuildingShortageIconScale); float num2 = num / 2.08f; float num3 = num2 * 0.08f; float num4 = Mathf.Max(rendererSizeInIconSpace.x * 0.55f + num2 * 0.5f, num2 * 1.15f); int num5 = 0; int i; for (i = 0; i < productGoodIds.Count; i++) { GoodInfo goodInfo = Discovery.Goods.FirstOrDefault((GoodInfo g) => string.Equals(g.Id, productGoodIds[i], StringComparison.OrdinalIgnoreCase)); Sprite val2 = goodInfo?.Icon; if (!((Object)(object)val2 == (Object)null)) { GameObject orCreateProductIcon = GetOrCreateProductIcon(orCreateProductIconsRoot, num5); SpriteRenderer component = orCreateProductIcon.GetComponent(); if (!((Object)(object)component == (Object)null)) { component.sprite = val2; component.color = WhiteColor; ((Renderer)component).sortingLayerName = ((Renderer)val).sortingLayerName; ((Renderer)component).sortingOrder = ((Renderer)val).sortingOrder + 1; ApplyProductIconBorder(orCreateProductIcon, val2, goodInfo.IsIngredientBlocked, val); int num6 = num5 % 2; int num7 = num5 / 2; float num8 = ((num6 == 0) ? ((num2 + num3) * 0.5f) : ((0f - (num2 + num3)) * 0.5f)); orCreateProductIcon.transform.localPosition = new Vector3(num4 + (float)num7 * (num2 + num3), num8, 0f); orCreateProductIcon.transform.localRotation = Quaternion.identity; orCreateProductIcon.transform.localScale = Vector3.one * GetScaleForHeight(val2, num2); orCreateProductIcon.SetActive(true); num5++; } } } for (int j = num5; j < orCreateProductIconsRoot.transform.childCount; j++) { ((Component)orCreateProductIconsRoot.transform.GetChild(j)).gameObject.SetActive(false); } orCreateProductIconsRoot.SetActive(num5 > 0); if (num5 == 0) { DestroyProductIcons(icon); LastApplied.Remove(buildingId); } } private static GameObject GetOrCreateProductIconsRoot(GameObject icon) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_004b: 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_006d: Unknown result type (might be due to invalid IL or missing references) Transform val = icon.transform.Find("StockAlertProductIcons"); if ((Object)(object)val != (Object)null) { return ((Component)val).gameObject; } GameObject val2 = new GameObject("StockAlertProductIcons"); val2.transform.SetParent(icon.transform, false); val2.transform.localPosition = Vector3.zero; val2.transform.localRotation = Quaternion.identity; val2.transform.localScale = Vector3.one; return val2; } private static GameObject GetOrCreateProductIcon(GameObject root, int index) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown while (root.transform.childCount <= index) { GameObject val = new GameObject("ProductIcon"); val.transform.SetParent(root.transform, false); SpriteRenderer val2 = val.AddComponent(); ((Renderer)val2).material = new Material(Shader.Find("Sprites/Default")); } return ((Component)root.transform.GetChild(index)).gameObject; } private static void ApplyProductIconBorder(GameObject productIcon, Sprite sprite, bool active, SpriteRenderer baseRenderer) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) GameObject orCreateProductIconBorder = GetOrCreateProductIconBorder(productIcon); if (!((Object)(object)orCreateProductIconBorder == (Object)null)) { orCreateProductIconBorder.SetActive(active); if (active && !((Object)(object)sprite == (Object)null)) { Bounds bounds = sprite.bounds; Vector3 size = ((Bounds)(ref bounds)).size; float num = Mathf.Max(size.y * 0.08f, 0.01f); float num2 = size.x + num * 2f; float num3 = size.y + num * 2f; Transform obj = orCreateProductIconBorder.transform.Find("Top"); ConfigureBorderPart((obj != null) ? ((Component)obj).GetComponent() : null, 0f, num3 * 0.5f - num * 0.5f, num2, num, baseRenderer); Transform obj2 = orCreateProductIconBorder.transform.Find("Bottom"); ConfigureBorderPart((obj2 != null) ? ((Component)obj2).GetComponent() : null, 0f, (0f - num3) * 0.5f + num * 0.5f, num2, num, baseRenderer); Transform obj3 = orCreateProductIconBorder.transform.Find("Left"); ConfigureBorderPart((obj3 != null) ? ((Component)obj3).GetComponent() : null, (0f - num2) * 0.5f + num * 0.5f, 0f, num, num3, baseRenderer); Transform obj4 = orCreateProductIconBorder.transform.Find("Right"); ConfigureBorderPart((obj4 != null) ? ((Component)obj4).GetComponent() : null, num2 * 0.5f - num * 0.5f, 0f, num, num3, baseRenderer); } } } private static GameObject GetOrCreateProductIconBorder(GameObject productIcon) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)productIcon == (Object)null) { return null; } Transform val = productIcon.transform.Find("IngredientBlockedBorder"); if ((Object)(object)val != (Object)null) { return ((Component)val).gameObject; } GameObject val2 = new GameObject("IngredientBlockedBorder"); val2.transform.SetParent(productIcon.transform, false); val2.transform.localPosition = Vector3.zero; val2.transform.localRotation = Quaternion.identity; val2.transform.localScale = Vector3.one; CreateBorderPart(val2.transform, "Top"); CreateBorderPart(val2.transform, "Bottom"); CreateBorderPart(val2.transform, "Left"); CreateBorderPart(val2.transform, "Right"); val2.SetActive(false); return val2; } private static void CreateBorderPart(Transform parent, string name) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown GameObject val = new GameObject(name); val.transform.SetParent(parent, false); SpriteRenderer val2 = val.AddComponent(); val2.sprite = GetSolidSprite(); ((Renderer)val2).material = new Material(Shader.Find("Sprites/Default")); } private static void ConfigureBorderPart(SpriteRenderer renderer, float x, float y, float width, float height, SpriteRenderer baseRenderer) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)renderer == (Object)null)) { renderer.color = BorderRedColor; ((Renderer)renderer).sortingLayerName = ((Renderer)baseRenderer).sortingLayerName; ((Renderer)renderer).sortingOrder = ((Renderer)baseRenderer).sortingOrder + 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 Vector2 GetRendererSizeInIconSpace(Transform iconTransform, SpriteRenderer renderer) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)iconTransform == (Object)null || (Object)(object)((renderer != null) ? renderer.sprite : null) == (Object)null) { return Vector2.one; } Bounds bounds = renderer.sprite.bounds; Vector3 size = ((Bounds)(ref bounds)).size; Vector3 val = iconTransform.InverseTransformVector(((Component)renderer).transform.TransformVector(new Vector3(size.x, 0f, 0f))); float magnitude = ((Vector3)(ref val)).magnitude; val = iconTransform.InverseTransformVector(((Component)renderer).transform.TransformVector(new Vector3(0f, size.y, 0f))); float magnitude2 = ((Vector3)(ref val)).magnitude; return new Vector2(Mathf.Max(0.01f, magnitude), Mathf.Max(0.01f, magnitude2)); } private static float GetScaleForHeight(Sprite sprite, float targetHeight) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) float num; if (sprite == null) { num = 0f; } else { Bounds bounds = sprite.bounds; num = ((Bounds)(ref bounds)).size.y; } float num2 = num; return (num2 > 0.001f) ? (targetHeight / num2) : 1f; } private static Sprite GetSolidSprite() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_solidSprite != (Object)null) { return _solidSprite; } Texture2D val = new Texture2D(4, 4, (TextureFormat)5, false) { filterMode = (FilterMode)0, wrapMode = (TextureWrapMode)1, hideFlags = (HideFlags)61 }; val.SetPixels(Enumerable.Repeat(Color.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 GetBaseIconRenderers(GameObject icon) { return from r in icon.GetComponentsInChildren(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 @base = recipeBuilding.Base; if (((@base != null) ? new int?(((Building)@base).Id) : null) != buildingId) { continue; } BuildingView buildingView = ((Building)recipeBuilding.Base).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 icon = (GameObject)obj; DestroyProductIcons(icon); 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 bool ColorsEqual(Color a, Color b) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) return Mathf.Approximately(a.r, b.r) && Mathf.Approximately(a.g, b.g) && Mathf.Approximately(a.b, b.b) && Mathf.Approximately(a.a, b.a); } private static void MakeIconClickThrough(GameObject icon) { if ((Object)(object)icon == (Object)null) { return; } Graphic[] componentsInChildren = icon.GetComponentsInChildren(true); foreach (Graphic val in componentsInChildren) { val.raycastTarget = false; } Selectable[] componentsInChildren2 = icon.GetComponentsInChildren(true); foreach (Selectable val2 in componentsInChildren2) { val2.interactable = false; } GraphicRaycaster[] componentsInChildren3 = icon.GetComponentsInChildren(true); foreach (GraphicRaycaster val3 in componentsInChildren3) { ((Behaviour)val3).enabled = false; } EventTrigger[] componentsInChildren4 = icon.GetComponentsInChildren(true); foreach (EventTrigger val4 in componentsInChildren4) { ((Behaviour)val4).enabled = false; } Component[] componentsInChildren5 = icon.GetComponentsInChildren(true); foreach (Component val5 in componentsInChildren5) { Type type = ((object)val5)?.GetType(); if (type == null) { continue; } string name = type.Name; if (name.IndexOf("Collider", StringComparison.Ordinal) >= 0) { PropertyInfo property = type.GetProperty("enabled"); if (property != null && property.CanWrite) { property.SetValue(val5, false, null); } } } } private static bool IsEnabledLowRecipe(WorkshopRecipeState recipeState, HashSet lowGoods) { if (recipeState == null || !((RecipeState)recipeState).active || string.IsNullOrWhiteSpace(recipeState.productName) || !lowGoods.Contains(recipeState.productName)) { return false; } return true; } private static bool IsEnabledGatheringSupplyRecipe(WorkshopRecipeState recipeState, HashSet blockedIngredientGoods, Settings settings) { if (recipeState == null || !((RecipeState)recipeState).active || blockedIngredientGoods == null || blockedIngredientGoods.Count == 0 || string.IsNullOrWhiteSpace(recipeState.productName) || !blockedIngredientGoods.Contains(recipeState.productName)) { return false; } WorkshopRecipeModel val = ((settings != null) ? settings.GetWorkshopRecipe(((RecipeState)recipeState).model) : null); return val?.requiredGoods == null || val.requiredGoods.Length == 0; } } [HarmonyPatch(typeof(ProductionBuildingView), "ShowWorkers")] internal static class BuildingAlertIndicatorsViewPatch { [HarmonyPostfix] private static void ShowWorkersPostfix(ProductionBuildingView __instance) { if (!((Object)(object)__instance == (Object)null) && GameAPI.IsGameActive()) { BuildingAlertIndicators.RefreshForView(__instance); } } } internal sealed class IdleBuilderRaceMenuMarker : MonoBehaviour { private RacesMenuSlot _slot; private GameObject _markerObject; private Image _markerImage; private float _nextRefreshTime; public static void Attach(RacesMenuSlot slot) { if (!((Object)(object)slot == (Object)null)) { IdleBuilderRaceMenuMarker component = ((Component)slot).GetComponent(); if ((Object)(object)component == (Object)null) { component = ((Component)slot).gameObject.AddComponent(); 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) { Hide(); return; } RaceModel race = _slot.GetRace(); if ((Object)(object)race == (Object)null || !BuilderStatusIndicators.HasIdleBuilderOfRace(race)) { Hide(); return; } Sprite idleBuilderSprite = BuilderStatusIndicators.GetIdleBuilderSprite(); if ((Object)(object)idleBuilderSprite == (Object)null) { Hide(); return; } EnsureMarker(); if (!((Object)(object)_markerImage == (Object)null)) { _markerImage.sprite = idleBuilderSprite; _markerObject.SetActive(true); } } private void EnsureMarker() { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_markerObject != (Object)null) && !((Object)(object)_slot == (Object)null)) { Transform obj = ((Component)_slot).transform.Find("Content"); RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null); if ((Object)(object)val == (Object)null) { val = ((Component)_slot).GetComponent(); } 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(); ((Graphic)_markerImage).raycastTarget = false; _markerImage.preserveAspect = true; RectTransform component = _markerObject.GetComponent(); 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 currentNews = GameAPI.GetCurrentNews(); News val = ((IEnumerable)currentNews).FirstOrDefault((Func)((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 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 Markers = new Dictionary(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 trackedItemLocations = GameAPI.GetTrackedItemLocations(_trackedGoodId); HashSet seen = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (TrackedItemLocation item in trackedItemLocations.Where((TrackedItemLocation l) => l != null && !string.IsNullOrWhiteSpace(l.Key))) { UpsertMarker(item, val, val2); seen.Add(item.Key); } List list = Markers.Keys.Where((string key) => !seen.Contains(key)).ToList(); foreach (string item2 in list) { if (Markers.TryGetValue(item2, out var value) && (Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } Markers.Remove(item2); } } private static void UpsertMarker(TrackedItemLocation location, Sprite icon, GameObject template) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) Vector3 markerWorldPosition = GetMarkerWorldPosition(location); if (!Markers.TryGetValue(location.Key, out var value) || (Object)(object)value == (Object)null) { value = Object.Instantiate(template, template.transform.parent); ((Object)value).name = "StockAlertItemLocator_" + location.Key; Markers[location.Key] = value; } ApplyVisuals(value, icon, location); ApplyTarget(value, markerWorldPosition); value.SetActive(true); } private static void ApplyVisuals(GameObject marker, Sprite icon, TrackedItemLocation location) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) Transform obj = marker.transform.Find("Icon"); object obj2 = ((obj != null) ? ((Component)obj).GetComponent() : null); if (obj2 == null) { Transform obj3 = marker.transform.Find("Mask/Icon"); obj2 = ((obj3 != null) ? ((Component)obj3).GetComponent() : 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() : null); if ((Object)(object)val3 != (Object)null) { ((Graphic)val3).raycastTarget = false; } Image[] componentsInChildren = marker.GetComponentsInChildren(true); foreach (Image val4 in componentsInChildren) { ((Graphic)val4).raycastTarget = false; } ApplyAmountBadge(marker, location); } private static void ApplyAmountBadge(GameObject marker, TrackedItemLocation location) { GameObject orCreateAmountBadge = GetOrCreateAmountBadge(marker); if ((Object)(object)orCreateAmountBadge == (Object)null) { return; } bool flag = location != null && location.Amount > 0 && location.Key.StartsWith("building:", StringComparison.OrdinalIgnoreCase); orCreateAmountBadge.SetActive(flag); if (flag) { TextMeshProUGUI componentInChildren = orCreateAmountBadge.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { ((TMP_Text)componentInChildren).text = location.Amount.ToString(); } } } private static GameObject GetOrCreateAmountBadge(GameObject marker) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) Transform val = marker.transform.Find("StockAlertAmountBadge"); if ((Object)(object)val != (Object)null) { return ((Component)val).gameObject; } RectTransform val2 = marker.GetComponent() ?? marker.GetComponentInChildren(true); if ((Object)(object)val2 == (Object)null) { return null; } GameObject val3 = new GameObject("StockAlertAmountBadge", new Type[1] { typeof(RectTransform) }); RectTransform component = val3.GetComponent(); ((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(); ((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(); ((TMP_Text)component3).font = TMP_Settings.defaultFontAsset; ((TMP_Text)component3).fontSize = 15f; ((TMP_Text)component3).enableAutoSizing = false; ((TMP_Text)component3).fontStyle = (FontStyles)1; ((TMP_Text)component3).alignment = (TextAlignmentOptions)514; ((Graphic)component3).color = new Color(1f, 0.99f, 0.9f, 1f); ((Graphic)component3).raycastTarget = false; ((TMP_Text)component3).margin = new Vector4(1f, 0f, 1f, 0f); ((TMP_Text)component3).fontSharedMaterial = ((TMP_Text)component3).fontMaterial; ((TMP_Text)component3).outlineWidth = 0.25f; ((TMP_Text)component3).outlineColor = Color32.op_Implicit(new Color(0.05f, 0.05f, 0.05f, 1f)); return val3; } private static void ApplyTarget(GameObject marker, Vector3 worldPosition) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) WorldIndicator val = marker.GetComponent(); if ((Object)(object)val == (Object)null) { val = marker.GetComponentInChildren(true); } if (val != null) { val.SetTarget(worldPosition); } } private static Vector3 GetMarkerWorldPosition(TrackedItemLocation location) { //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) Object source = location.Source; Component val = (Component)(object)((source is Component) ? source : null); if (val != null && (Object)(object)val != (Object)null) { Renderer[] array = (from renderer in val.GetComponentsInChildren(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 i = 1; i < array.Length; i++) { ((Bounds)(ref bounds)).Encapsulate(array[i].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)Resources.FindObjectsOfTypeAll()).FirstOrDefault((Func)IsSceneObject); object obj2 = ((obj != null) ? ((Component)obj).gameObject : null); if (obj2 == null) { LakeIndicator? obj3 = ((IEnumerable)Resources.FindObjectsOfTypeAll()).FirstOrDefault((Func)IsSceneObject); obj2 = ((obj3 != null) ? ((Component)obj3).gameObject : null); if (obj2 == null) { OreIndicator? obj4 = ((IEnumerable)Resources.FindObjectsOfTypeAll()).FirstOrDefault((Func)IsSceneObject); obj2 = ((obj4 != null) ? ((Component)obj4).gameObject : null); if (obj2 == null) { BuildingIndicator? obj5 = ((IEnumerable)Resources.FindObjectsOfTypeAll()).FirstOrDefault((Func)IsSceneObject); obj2 = ((obj5 != null) ? ((Component)obj5).gameObject : null); } } } _template = (GameObject)obj2; return _template; } private static bool IsSceneObject(Component component) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) int result; if ((Object)(object)component != (Object)null) { Scene scene = component.gameObject.scene; result = (((Scene)(ref scene)).IsValid() ? 1 : 0); } else { result = 0; } return (byte)result != 0; } } internal sealed class QueuedWorkerSlotCompanion : MonoBehaviour { private static readonly List Instances = new List(); 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() != (Object)null)) { ((Component)slot).gameObject.AddComponent().Initialize(slot); } } public static void ClearAll() { QueuedWorkerSlotCompanion[] array = Instances.ToArray(); for (int i = 0; i < array.Length; i++) { array[i]?.Hide(); } } private void Initialize(BuildingWorkerSlot slot) { _slot = slot; Instances.Add(this); EnsureUi(); Refresh(); } private void OnDestroy() { Instances.Remove(this); } private void Update() { if (!(Time.unscaledTime < _nextRefreshTime)) { _nextRefreshTime = Time.unscaledTime + 0.25f; Refresh(); } } private void Refresh() { if ((Object)(object)_slot == (Object)null) { Hide(); return; } if (!ConfigManager.EnableQueuedWorkerAssignments) { Hide(); return; } if (!TryGetContext(out var building, out var _, out var workplaceIndex)) { Hide(); return; } if (IsBuildingRemoved(building)) { WorkerAssignmentQueue.ClearQueuedRace(building, workplaceIndex); Hide(); return; } RaceModel queuedRace = WorkerAssignmentQueue.GetQueuedRace(building, workplaceIndex); if ((Object)(object)queuedRace == (Object)null) { Hide(); return; } EnsureUi(); _queuedIconImage.sprite = queuedRace.roundIcon; ((Graphic)_queuedIconImage).material = null; _queuedIconObject.SetActive(true); } private bool TryGetContext(out ProductionBuilding building, out WorkplaceModel workplace, out int workplaceIndex) { building = null; workplace = null; workplaceIndex = -1; if ((Object)(object)_slot == (Object)null) { return false; } if ((object)_fiBuilding == null) { _fiBuilding = typeof(BuildingWorkerSlot).GetField("building", BindingFlags.Instance | BindingFlags.NonPublic); } if ((object)_fiWorkplace == null) { _fiWorkplace = typeof(BuildingWorkerSlot).GetField("workplace", BindingFlags.Instance | BindingFlags.NonPublic); } object? obj = _fiBuilding?.GetValue(_slot); building = (ProductionBuilding)((obj is ProductionBuilding) ? obj : null); object? obj2 = _fiWorkplace?.GetValue(_slot); workplace = (WorkplaceModel)((obj2 is WorkplaceModel) ? obj2 : null); if ((Object)(object)building == (Object)null || workplace == null) { return false; } workplaceIndex = building.GetIndexOf(workplace); return workplaceIndex >= 0; } private void EnsureUi() { //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_queuedIconObject != (Object)null) { return; } if ((object)_fiRaceIcon == null) { _fiRaceIcon = typeof(BuildingWorkerSlot).GetField("raceIcon", BindingFlags.Instance | BindingFlags.NonPublic); } object? obj = _fiRaceIcon?.GetValue(_slot); Image val = (Image)((obj is Image) ? obj : null); if (!((Object)(object)val == (Object)null)) { _queuedIconObject = Object.Instantiate(((Component)val).gameObject, ((Component)val).transform.parent, false); ((Object)_queuedIconObject).name = "QueuedWorkerIcon"; _queuedIconImage = _queuedIconObject.GetComponent(); _queuedIconButton = _queuedIconObject.GetComponent