Decompiled source of DSPTaskMaster v1.0.0
DSPTaskMaster.dll
Decompiled 11 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; using crecheng.DSPModSave; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("DSPTaskMaster")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+608014d1e2701a8d53e480d0e42ed9b204d8d3e2")] [assembly: AssemblyProduct("DSPTaskMaster")] [assembly: AssemblyTitle("DSPTaskMaster")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DSPTaskMaster { public class Alerts { private enum State { Below, Met, Behind } private class Track { public State Confirmed; public State Pending; public float PendingSince; } private const float ReachedDelay = 2f; private const float ProblemDelay = 10f; private readonly Dictionary<TodoItem, Track> _tracks = new Dictionary<TodoItem, Track>(); private float _clock; public void Reset() { _tracks.Clear(); } public void Check(List<TodoItem> items) { _clock += 1f; if (_tracks.Count > 0) { HashSet<TodoItem> hashSet = new HashSet<TodoItem>(items); List<TodoItem> list = new List<TodoItem>(); foreach (TodoItem key in _tracks.Keys) { if (!hashSet.Contains(key)) { list.Add(key); } } foreach (TodoItem item in list) { _tracks.Remove(item); } } foreach (TodoItem item2 in items) { if (item2.Type == TaskType.Manual) { continue; } State state = (item2.IsCompleted ? ((!item2.IsBehind()) ? State.Met : State.Behind) : State.Below); if (!_tracks.TryGetValue(item2, out var value)) { _tracks[item2] = new Track { Confirmed = state, Pending = state, PendingSince = _clock }; continue; } if (state == value.Confirmed) { value.Pending = state; continue; } if (state != value.Pending) { value.Pending = state; value.PendingSince = _clock; } float num = ((state == State.Met) ? 2f : 10f); if (!(_clock - value.PendingSince < num)) { State confirmed = value.Confirmed; value.Confirmed = state; Announce(item2, confirmed, state); } } } private static void Announce(TodoItem item, State old, State now) { Plugin instance = Plugin.Instance; if (!instance.AlertsEnabled.Value) { return; } string text = null; if (now == State.Met && old == State.Below) { text = ((item.Type == TaskType.Research) ? ("TaskMaster: " + item.Description + " done") : ("TaskMaster: " + item.Description + " reached (" + TaskText.ShortValue(item) + ")")); } else if (item.Type == TaskType.Surplus && instance.AlertBehind.Value) { if (now == State.Below) { text = "TaskMaster: " + item.Description + " dropped below target (" + TaskText.FmtSigned(item.CurrentAmount) + " /min)"; } } else if (item.Type == TaskType.ProductionTarget && instance.AlertBehind.Value) { if (now == State.Met && old == State.Behind) { text = "TaskMaster: " + item.Description + " is back on track"; } else { switch (now) { case State.Behind: text = "TaskMaster: " + item.Description + " is behind: " + TaskText.Fmt(item.ActualAmount) + " / " + TaskText.Fmt(item.TargetAmount) + " /min"; break; case State.Below: text = "TaskMaster: " + item.Description + " dropped below target (" + TaskText.ShortValue(item) + " /min)"; break; } } } if (text == null) { return; } try { UIRealtimeTip.Popup(text, true, 0); } catch (Exception ex) { instance.Log.LogWarning((object)("Could not show alert: " + ex.Message)); } } } public static class GameStyle { public static readonly Color OverlayPanel = new Color(0.08f, 0.1f, 0.14f, 1f); public static readonly Color ButtonColor = new Color(1f, 1f, 1f, 0.12f); public static readonly Color SubtleButtonColor = new Color(1f, 1f, 1f, 0.07f); public static readonly Color AccentButtonColor = new Color(0.35f, 0.72f, 1f, 0.45f); public static readonly Color FieldColor = new Color(0f, 0f, 0f, 0.35f); public static readonly Color RowColor = new Color(0f, 0f, 0f, 0.28f); public static readonly Color RowDoneColor = new Color(0f, 0f, 0f, 0.14f); public static readonly Color BarBackground = new Color(0f, 0f, 0f, 0.45f); public static readonly Color TextColor = new Color(0.92f, 0.95f, 1f, 1f); public static readonly Color MutedText = new Color(0.62f, 0.68f, 0.76f, 1f); public static readonly Color IconColor = new Color(0.85f, 0.9f, 1f, 0.9f); private static bool _initialized; private static Font _fallbackFont; private static bool _naviSearched; private static Sprite _naviSprite; public static Font Font { get; private set; } public static Sprite PanelSprite { get; private set; } public static Sprite ButtonSprite { get; private set; } public static Sprite CloseSprite { get; private set; } public static void Init() { if (_initialized) { return; } _initialized = true; try { UIGame val = UIRoot.instance?.uiGame; if ((Object)(object)val != (Object)null) { Text[] componentsInChildren = ((Component)val).GetComponentsInChildren<Text>(true); foreach (Text val2 in componentsInChildren) { if ((Object)(object)val2.font != (Object)null && ((Object)val2.font).name != "Arial") { Font = val2.font; break; } } UIItemPicker itemPicker = val.itemPicker; if ((Object)(object)itemPicker != (Object)null) { RectTransform pickerTrans = itemPicker.pickerTrans; object panelSprite; if (pickerTrans == null) { panelSprite = null; } else { Image component = ((Component)pickerTrans).GetComponent<Image>(); panelSprite = ((component != null) ? component.sprite : null); } PanelSprite = (Sprite)panelSprite; UIButton typeButton = itemPicker.typeButton1; object buttonSprite; if (typeButton == null) { buttonSprite = null; } else { Image component2 = ((Component)typeButton).GetComponent<Image>(); buttonSprite = ((component2 != null) ? component2.sprite : null); } ButtonSprite = (Sprite)buttonSprite; } FindWindowAssets((Component)(object)val.controlPanelWindow); if ((Object)(object)CloseSprite == (Object)null) { FindWindowAssets((Component)(object)val.statWindow); } } } catch (Exception ex) { Plugin.Instance.Log.LogWarning((object)("GameStyle: could not read game UI assets: " + ex.Message)); } ManualLogSource log = Plugin.Instance.Log; string[] obj = new string[8] { "GameStyle: font=", null, null, null, null, null, null, null }; Font font = Font; obj[1] = ((font != null) ? ((Object)font).name : null) ?? "Arial (fallback)"; obj[2] = ", panel="; Sprite panelSprite2 = PanelSprite; obj[3] = ((panelSprite2 != null) ? ((Object)panelSprite2).name : null) ?? "none"; obj[4] = ", button="; Sprite buttonSprite2 = ButtonSprite; obj[5] = ((buttonSprite2 != null) ? ((Object)buttonSprite2).name : null) ?? "none"; obj[6] = ", close="; Sprite closeSprite = CloseSprite; obj[7] = ((closeSprite != null) ? ((Object)closeSprite).name : null) ?? "none"; log.LogInfo((object)string.Concat(obj)); } private static void FindWindowAssets(Component root) { if ((Object)(object)root == (Object)null || !((Object)(object)CloseSprite == (Object)null)) { return; } Button[] componentsInChildren = root.GetComponentsInChildren<Button>(true); foreach (Button val in componentsInChildren) { if (((Object)val).name.IndexOf("close", StringComparison.OrdinalIgnoreCase) < 0) { continue; } Image[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<Image>(true); foreach (Image val2 in componentsInChildren2) { if ((Object)(object)val2.sprite != (Object)null) { CloseSprite = val2.sprite; break; } } if ((Object)(object)CloseSprite != (Object)null) { break; } } } public static Image CreateWindowBackground(GameObject go) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) Image obj = go.AddComponent<Image>(); ((Graphic)obj).color = OverlayPanel; ((Graphic)obj).raycastTarget = true; return obj; } public static void StyleIconButton(Button btn, float iconSize) { //IL_0021: 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_0057: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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_00b3: 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_00c1: Unknown result type (might be due to invalid IL or missing references) Image component = ((Component)btn).GetComponent<Image>(); component.sprite = null; ((Graphic)component).color = new Color(0f, 0f, 0f, 0f); Text componentInChildren = ((Component)btn).GetComponentInChildren<Text>(); if ((Object)(object)CloseSprite != (Object)null) { if ((Object)(object)componentInChildren != (Object)null) { ((Behaviour)componentInChildren).enabled = false; } GameObject val = new GameObject("Icon"); val.transform.SetParent(((Component)btn).transform, false); Image val2 = val.AddComponent<Image>(); val2.sprite = CloseSprite; ((Graphic)val2).color = IconColor; ((Graphic)val2).raycastTarget = false; RectTransform rectTransform = ((Graphic)val2).rectTransform; Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0.5f, 0.5f); rectTransform.pivot = val3; Vector2 anchorMin = (rectTransform.anchorMax = val3); rectTransform.anchorMin = anchorMin; rectTransform.sizeDelta = new Vector2(iconSize, iconSize); ((Selectable)btn).targetGraphic = (Graphic)(object)val2; } else if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.text = "×"; componentInChildren.fontSize = Mathf.RoundToInt(iconSize * 1.4f); ((Graphic)componentInChildren).color = IconColor; ((Selectable)btn).targetGraphic = (Graphic)(object)componentInChildren; } } public static Sprite GetNavigationSprite() { if (_naviSearched) { return _naviSprite; } _naviSearched = true; try { UIControlPanelPlanetEntry[] array = Resources.FindObjectsOfTypeAll<UIControlPanelPlanetEntry>(); for (int i = 0; i < array.Length; i++) { UIButton navigationButton = array[i].navigationButton; if ((Object)(object)navigationButton == (Object)null) { continue; } Image[] componentsInChildren = ((Component)navigationButton).GetComponentsInChildren<Image>(true); foreach (Image val in componentsInChildren) { if (!((Object)(object)((Component)val).gameObject == (Object)(object)((Component)navigationButton).gameObject) && !((Object)(object)val.sprite == (Object)null)) { _naviSprite = val.sprite; break; } } if ((Object)(object)_naviSprite != (Object)null) { break; } } } catch (Exception ex) { Plugin.Instance.Log.LogWarning((object)("GameStyle: could not find the navigation icon: " + ex.Message)); } ManualLogSource log = Plugin.Instance.Log; Sprite naviSprite = _naviSprite; log.LogInfo((object)("GameStyle: navigation icon=" + (((naviSprite != null) ? ((Object)naviSprite).name : null) ?? "none (using text)"))); return _naviSprite; } public static Font GetFont() { if ((Object)(object)Font != (Object)null) { return Font; } if ((Object)(object)_fallbackFont == (Object)null) { _fallbackFont = Resources.GetBuiltinResource<Font>("Arial.ttf"); } return _fallbackFont; } public static void ApplyPanel(Image img) { ApplySprite(img, PanelSprite); } public static void ApplyButton(Image img) { ApplySprite(img, ButtonSprite); } private static void ApplySprite(Image img, Sprite sprite) { //IL_001c: 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) if (!((Object)(object)img == (Object)null) && !((Object)(object)sprite == (Object)null)) { img.sprite = sprite; img.type = (Type)((sprite.border != Vector4.zero) ? 1 : 0); } } } public enum TaskType { Manual, InventoryTarget, ProductionTarget, Research, Building, Sphere, Surplus } [Serializable] public class TodoItem { public string Description; public bool IsCompleted; public TaskType Type; public int ItemId; public int TargetAmount; public long CurrentAmount; public long ActualAmount; public int PlanetId; [NonSerialized] public long TotalAmount; [NonSerialized] public string StatusText; public const float ActualOkRatio = 0.9f; public bool IsBehind() { if (Type == TaskType.ProductionTarget && IsCompleted) { return (float)ActualAmount < (float)TargetAmount * 0.9f; } return false; } public bool IsBelowCapacity() { if (Type == TaskType.ProductionTarget && CurrentAmount > 0) { return (float)ActualAmount < (float)Math.Min(CurrentAmount, TargetAmount) * 0.9f; } return false; } public TodoItem(string desc, TaskType type, int itemId, int target, int planetId = 0) { Description = desc; Type = type; ItemId = itemId; TargetAmount = target; CurrentAmount = 0L; PlanetId = planetId; } } public class ItemDefinition { public int Id; public Sprite Icon; public string Name { get { ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items)?.Select(Id); if (val != null) { try { string text = Localization.Translate(((Proto)val).name); if (!string.IsNullOrEmpty(text)) { return text; } } catch { } string name = ((Proto)val).name; if (!string.IsNullOrEmpty(name)) { return name; } return "Unknown Item"; } return "Unknown Item"; } } } [BepInPlugin("com.jules.dsp.taskmaster", "DSP TaskMaster", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin, IModCanSave { public static Plugin Instance; private List<TodoItem> _todoItems = new List<TodoItem>(); private Type _inputTypeCache; private MethodInfo _getKeyMethodCache; private MethodInfo _getKeyDownMethodCache; private bool _inputReflectionFailed; private float _checkTimer; private bool _itemsLoaded; private List<ItemDefinition> _cachedItems; private int _lastPlanetId; private int _lastLocalId = -1; public ConfigEntry<float> WindowX; public ConfigEntry<float> WindowY; public ConfigEntry<float> WindowWidth; public ConfigEntry<float> WindowHeight; public ConfigEntry<bool> AlertsEnabled; public ConfigEntry<bool> AlertBehind; public ConfigEntry<bool> OverlayEnabled; public ConfigEntry<float> OverlayX; public ConfigEntry<float> OverlayY; private readonly Alerts _alerts = new Alerts(); public ManualLogSource Log => ((BaseUnityPlugin)this).Logger; private void Awake() { Instance = this; WindowX = ((BaseUnityPlugin)this).Config.Bind<float>("Window", "X", 0f, "Left edge relative to the screen center (UI units). Set Width to 0 to reset."); WindowY = ((BaseUnityPlugin)this).Config.Bind<float>("Window", "Y", 0f, "Top edge relative to the screen center (UI units)."); WindowWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Window", "Width", 0f, "Window width in UI units. 0 = automatic (fits screen size)."); WindowHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Window", "Height", 0f, "Window height in UI units. 0 = automatic (fits screen size)."); AlertsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Alerts", "Enabled", true, "Show an on-screen message when a tracked task reaches its target."); AlertBehind = ((BaseUnityPlugin)this).Config.Bind<bool>("Alerts", "Behind", true, "Also alert when a production task falls behind or drops below its target."); OverlayEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Overlay", "Enabled", true, "Show a small list of open tasks at the screen edge while the window is closed."); OverlayX = ((BaseUnityPlugin)this).Config.Bind<float>("Overlay", "X", 0f, "Right edge offset from the screen's right edge (UI units, negative = left). 0/0 = default position."); OverlayY = ((BaseUnityPlugin)this).Config.Bind<float>("Overlay", "Y", 0f, "Top edge offset from the screen's top edge (UI units, negative = down). 0/0 = default position."); ((Component)this).gameObject.AddComponent<UIManager>(); DSPModSavePlugin.AddModSaveManually((BaseUnityPlugin)(object)this); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin com.jules.dsp.taskmaster is loaded!"); } public void TryLoadItems() { if (_itemsLoaded || GameMain.mainPlayer == null) { return; } _cachedItems = new List<ItemDefinition>(); bool flag = false; try { if ((Object)(object)LDB.items != (Object)null && ((ProtoSet<ItemProto>)(object)LDB.items).dataArray != null) { ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray; foreach (ItemProto val in dataArray) { if (val != null && ((Proto)val).ID > 0) { flag = true; Sprite val2 = val.iconSprite; if ((Object)(object)val2 == (Object)null && !string.IsNullOrEmpty(val.IconPath)) { val2 = Resources.Load<Sprite>(val.IconPath); } _cachedItems.Add(new ItemDefinition { Id = ((Proto)val).ID, Icon = val2 }); } } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Error loading item database: " + ex.Message)); } if (!flag) { _itemsLoaded = true; _cachedItems.Add(new ItemDefinition { Id = 1101 }); _cachedItems.Add(new ItemDefinition { Id = 1104 }); _cachedItems.Add(new ItemDefinition { Id = 1105 }); _cachedItems.Add(new ItemDefinition { Id = 1131 }); } else { _itemsLoaded = true; } } public List<ItemDefinition> GetCachedItems() { return _cachedItems; } public int GetCurrentPlanetId() { if (GameMain.localPlanet != null) { return GameMain.localPlanet.id; } return 0; } public bool IsOnPlanet() { return GameMain.localPlanet != null; } public int GetDisplayPlanetId() { int currentPlanetId = GetCurrentPlanetId(); if (currentPlanetId == 0) { return _lastPlanetId; } return currentPlanetId; } public string GetPlanetName(int planetId) { if (planetId == 0) { return null; } try { GameData data = GameMain.data; object obj; if (data == null) { obj = null; } else { GalaxyData galaxy = data.galaxy; obj = ((galaxy != null) ? galaxy.PlanetById(planetId) : null); } PlanetData val = (PlanetData)obj; if (val != null) { return val.displayName; } } catch { } return "Planet " + planetId; } public void Export(BinaryWriter w) { SaveManager.Write(w, _todoItems, GetDisplayPlanetId()); } public void Import(BinaryReader r) { try { int lastPlanetId; List<TodoItem> list = SaveManager.Read(r, out lastPlanetId); SetTodoItems(list, lastPlanetId); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Loaded {list.Count} tasks from save."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Could not read tasks from save: " + ex.Message)); SetTodoItems(new List<TodoItem>()); } } public void IntoOtherSave() { SetTodoItems(new List<TodoItem>()); } public List<TodoItem> GetTodoItems() { return _todoItems; } public void SetTodoItems(List<TodoItem> items, int lastPlanetId = 0) { _todoItems = items ?? new List<TodoItem>(); _lastPlanetId = lastPlanetId; _lastLocalId = -1; _alerts.Reset(); if ((Object)(object)UIManager.Instance != (Object)null) { UIManager.Instance.RefreshUI(); } } private void Update() { bool flag = false; if (!_inputReflectionFailed) { try { if (_inputTypeCache == null) { _inputTypeCache = Type.GetType("UnityEngine.Input, UnityEngine.InputLegacyModule"); if (_inputTypeCache == null) { _inputTypeCache = Type.GetType("UnityEngine.Input, UnityEngine.CoreModule"); } if (_inputTypeCache == null) { _inputTypeCache = Type.GetType("UnityEngine.Input, UnityEngine"); } } if (_inputTypeCache != null) { if (_getKeyMethodCache == null) { _getKeyMethodCache = _inputTypeCache.GetMethod("GetKey", new Type[1] { typeof(KeyCode) }); } if (_getKeyDownMethodCache == null) { _getKeyDownMethodCache = _inputTypeCache.GetMethod("GetKeyDown", new Type[1] { typeof(KeyCode) }); } if (_getKeyMethodCache != null && _getKeyDownMethodCache != null) { bool flag2 = (bool)_getKeyMethodCache.Invoke(null, new object[1] { (object)(KeyCode)308 }); bool flag3 = (bool)_getKeyMethodCache.Invoke(null, new object[1] { (object)(KeyCode)307 }); if ((flag2 || flag3) && (bool)_getKeyDownMethodCache.Invoke(null, new object[1] { (object)(KeyCode)116 })) { flag = true; } } else { ((BaseUnityPlugin)this).Logger.LogError((object)"Input reflection failed: method cache is null"); _inputReflectionFailed = true; } } else { ((BaseUnityPlugin)this).Logger.LogError((object)"Input reflection failed: _inputTypeCache is null"); _inputReflectionFailed = true; } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Error reading input via reflection: " + ex.Message)); _inputReflectionFailed = true; } } if (flag && (Object)(object)UIManager.Instance != (Object)null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"ToggleWindow called via shortcut!"); UIManager.Instance.ToggleWindow(); } int currentPlanetId = GetCurrentPlanetId(); if (currentPlanetId != _lastLocalId) { _lastLocalId = currentPlanetId; if (currentPlanetId != 0) { _lastPlanetId = currentPlanetId; } CheckTargets(); if ((Object)(object)UIManager.Instance != (Object)null) { UIManager.Instance.OnLocalPlanetChanged(); UIManager.Instance.RefreshUI(); } } _checkTimer += Time.deltaTime; if (_checkTimer >= 1f) { _checkTimer = 0f; if (!_itemsLoaded) { TryLoadItems(); } CheckTargets(); _alerts.Check(_todoItems); if ((Object)(object)UIManager.Instance != (Object)null) { UIManager.Instance.UpdateValues(); UIManager.Instance.UpdateOverlay(); } } } private void CheckTargets() { if (_todoItems.Count == 0) { return; } bool flag = false; bool flag2 = false; HashSet<int> hashSet = new HashSet<int>(); foreach (TodoItem todoItem in _todoItems) { try { switch (todoItem.Type) { case TaskType.InventoryTarget: UpdateInventoryTask(todoItem); break; case TaskType.Research: UpdateResearchTask(todoItem); break; case TaskType.Building: UpdateBuildingTask(todoItem); break; case TaskType.Sphere: UpdateSphereTask(todoItem); break; case TaskType.Surplus: UpdateSurplusTask(todoItem); break; case TaskType.ProductionTarget: flag = true; if (todoItem.PlanetId == 0) { flag2 = true; } else { hashSet.Add(todoItem.PlanetId); } break; } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not update task '" + todoItem.Description + "': " + ex.Message)); } } if (!flag || GameMain.data == null || GameMain.data.factories == null) { return; } Dictionary<int, Dictionary<int, long>> dictionary = new Dictionary<int, Dictionary<int, long>>(); Dictionary<int, Dictionary<int, long>> dictionary2 = new Dictionary<int, Dictionary<int, long>>(); PlanetFactory[] factories = GameMain.data.factories; FactoryProductionStat[] array = GameMain.data.statistics?.production?.factoryStatPool; for (int i = 0; i < factories.Length && i < GameMain.data.factoryCount; i++) { PlanetFactory val = factories[i]; if (val == null) { continue; } int planetId = val.planetId; if (!flag2 && !hashSet.Contains(planetId)) { continue; } try { dictionary[planetId] = CalculateCapacity(val); } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"Capacity calculation failed for planet {planetId}: {ex2.Message}"); dictionary[planetId] = new Dictionary<int, long>(); } Dictionary<int, long> dictionary3 = (dictionary2[planetId] = new Dictionary<int, long>()); if (array == null || val.index < 0 || val.index >= array.Length || array[val.index] == null) { continue; } foreach (TodoItem todoItem2 in _todoItems) { if (todoItem2.Type == TaskType.ProductionTarget && !dictionary3.ContainsKey(todoItem2.ItemId) && (todoItem2.PlanetId == 0 || todoItem2.PlanetId == planetId)) { dictionary3[todoItem2.ItemId] = GetProducedLastMinute(array[val.index], todoItem2.ItemId); } } } foreach (TodoItem todoItem3 in _todoItems) { if (todoItem3.Type == TaskType.ProductionTarget) { todoItem3.CurrentAmount = SumForItem(dictionary, todoItem3); todoItem3.ActualAmount = SumForItem(dictionary2, todoItem3); todoItem3.IsCompleted = todoItem3.TargetAmount > 0 && todoItem3.CurrentAmount >= todoItem3.TargetAmount; } } } private void UpdateInventoryTask(TodoItem item) { if (GameMain.mainPlayer != null && GameMain.mainPlayer.package != null) { item.CurrentAmount = GameMain.mainPlayer.package.GetItemCount(item.ItemId); item.IsCompleted = item.TargetAmount > 0 && item.CurrentAmount >= item.TargetAmount; } } private static void UpdateResearchTask(TodoItem item) { //IL_0028: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) GameHistoryData history = GameMain.history; if (history != null && history.techStates != null) { if (history.techStates.TryGetValue(item.ItemId, out var value)) { item.IsCompleted = value.unlocked; item.TotalAmount = value.hashNeeded; item.CurrentAmount = (value.unlocked ? value.hashNeeded : value.hashUploaded); } if (item.IsCompleted) { item.StatusText = "Done"; } else if (history.currentTech == item.ItemId) { item.StatusText = "Researching"; } else if (IsInTechQueue(history, item.ItemId)) { item.StatusText = "In queue"; } else { item.StatusText = "Not queued"; } } } private static bool IsInTechQueue(GameHistoryData history, int techId) { int[] techQueue = history.techQueue; if (techQueue == null) { return false; } for (int i = 0; i < history.techQueueLength && i < techQueue.Length; i++) { if (techQueue[i] == techId) { return true; } } return false; } private static void UpdateBuildingTask(TodoItem item) { long num = 0L; foreach (PlanetFactory factory in GetFactories(item.PlanetId)) { EntityData[] entityPool = factory.entityPool; if (entityPool == null) { continue; } for (int i = 1; i < factory.entityCursor && i < entityPool.Length; i++) { if (entityPool[i].id == i && entityPool[i].protoId == item.ItemId) { num++; } } } item.CurrentAmount = num; item.IsCompleted = item.TargetAmount > 0 && num >= item.TargetAmount; } private static void UpdateSphereTask(TodoItem item) { DysonSphere dysonSphere = GetDysonSphere(item.ItemId); long num = ((dysonSphere != null) ? (dysonSphere.energyGenCurrentTick * 60) : 0); item.CurrentAmount = num / 1000000; item.IsCompleted = item.TargetAmount > 0 && item.CurrentAmount >= item.TargetAmount; } private static void UpdateSurplusTask(TodoItem item) { GetMadeAndUsed(item.PlanetId, item.ItemId, out var made, out var used); item.ActualAmount = made; item.TotalAmount = used; item.CurrentAmount = made - used; item.IsCompleted = item.TargetAmount > 0 && item.CurrentAmount >= item.TargetAmount; } public static void GetMadeAndUsed(int planetId, int itemId, out long made, out long used) { made = 0L; used = 0L; FactoryProductionStat[] array = GameMain.data?.statistics?.production?.factoryStatPool; if (array == null) { return; } foreach (PlanetFactory factory in GetFactories(planetId)) { if (factory.index >= 0 && factory.index < array.Length && array[factory.index] != null) { made += GetProducedLastMinute(array[factory.index], itemId); used += GetConsumedLastMinute(array[factory.index], itemId); } } } public static DysonSphere GetDysonSphere(int starId) { DysonSphere[] array = GameMain.data?.dysonSpheres; GameData data = GameMain.data; object obj; if (data == null) { obj = null; } else { GalaxyData galaxy = data.galaxy; obj = ((galaxy != null) ? galaxy.StarById(starId) : null); } StarData val = (StarData)obj; if (array == null || val == null || val.index < 0 || val.index >= array.Length) { return null; } return array[val.index]; } public static string GetStarName(int starId) { GameData data = GameMain.data; object obj; if (data == null) { obj = null; } else { GalaxyData galaxy = data.galaxy; obj = ((galaxy != null) ? galaxy.StarById(starId) : null); } StarData val = (StarData)obj; if (val == null) { return "Star " + starId; } return val.displayName; } public static IEnumerable<PlanetFactory> GetFactories(int planetId) { GameData data = GameMain.data; if (data == null || data.factories == null) { yield break; } for (int i = 0; i < data.factories.Length && i < data.factoryCount; i++) { PlanetFactory val = data.factories[i]; if (val != null && (planetId == 0 || val.planetId == planetId)) { yield return val; } } } private static long SumForItem(Dictionary<int, Dictionary<int, long>> perPlanet, TodoItem item) { long num = 0L; foreach (KeyValuePair<int, Dictionary<int, long>> item2 in perPlanet) { if ((item.PlanetId == 0 || item2.Key == item.PlanetId) && item2.Value.TryGetValue(item.ItemId, out var value)) { num += value; } } return num; } internal static long GetProducedLastMinute(FactoryProductionStat stat, int itemId) { return GetStatTotal(stat, itemId, 1); } internal static long GetConsumedLastMinute(FactoryProductionStat stat, int itemId) { return GetStatTotal(stat, itemId, 8); } private static long GetStatTotal(FactoryProductionStat stat, int itemId, int totalIndex) { int[] productIndices = stat.productIndices; if (productIndices == null || itemId <= 0 || itemId >= productIndices.Length) { return 0L; } int num = productIndices[itemId]; if (num <= 0 || stat.productPool == null || num >= stat.productPool.Length) { return 0L; } ProductStat val = stat.productPool[num]; if (val == null || val.total == null || val.total.Length <= totalIndex) { return 0L; } return val.total[totalIndex]; } private static void AddRate(Dictionary<int, double> totals, int itemId, double perMinute) { if (itemId > 0 && !(perMinute <= 0.0)) { if (totals.ContainsKey(itemId)) { totals[itemId] += perMinute; } else { totals[itemId] = perMinute; } } } private static Dictionary<int, long> CalculateCapacity(PlanetFactory factory) { Dictionary<int, double> dictionary = new Dictionary<int, double>(); FactorySystem factorySystem = factory.factorySystem; if (factorySystem == null) { return new Dictionary<int, long>(); } if (factorySystem.assemblerPool != null) { for (int i = 1; i < factorySystem.assemblerCursor; i++) { ref AssemblerComponent reference = ref factorySystem.assemblerPool[i]; if (reference.id == i && reference.recipeId > 0 && reference.recipeExecuteData != null) { AddRecipeOutput(dictionary, reference.recipeExecuteData, Math.Max(reference.speed, reference.speedOverride), reference.extraSpeed); } } } if (factorySystem.labPool != null) { for (int j = 1; j < factorySystem.labCursor; j++) { ref LabComponent reference2 = ref factorySystem.labPool[j]; if (reference2.id == j && !reference2.researchMode && reference2.recipeId > 0 && reference2.recipeExecuteData != null) { AddRecipeOutput(dictionary, reference2.recipeExecuteData, Math.Max(reference2.speed, reference2.speedOverride), reference2.extraSpeed); } } } if (factorySystem.minerPool != null) { float miningSpeed = ((GameMain.history != null) ? GameMain.history.miningSpeedScale : 1f); for (int k = 1; k < factorySystem.minerCursor; k++) { ref MinerComponent reference3 = ref factorySystem.minerPool[k]; if (reference3.id == k) { int productId; double perMinute = MinerRatePerMinute(ref reference3, factory.veinPool, miningSpeed, out productId); AddRate(dictionary, productId, perMinute); } } } BeltComponent[] array = factory.cargoTraffic?.beltPool; if (factorySystem.fractionatorPool != null && array != null) { for (int l = 1; l < factorySystem.fractionatorCursor; l++) { ref FractionatorComponent reference4 = ref factorySystem.fractionatorPool[l]; if (reference4.id == l && reference4.productId > 0) { int num = 0; if (reference4.belt0 > 0 && !reference4.isOutput0 && reference4.belt0 < array.Length) { num = Math.Max(num, array[reference4.belt0].speed); } if (reference4.belt1 > 0 && !reference4.isOutput1 && reference4.belt1 < array.Length) { num = Math.Max(num, array[reference4.belt1].speed); } if (reference4.belt2 > 0 && !reference4.isOutput2 && reference4.belt2 < array.Length) { num = Math.Max(num, array[reference4.belt2].speed); } if (num > 0) { double num2 = Math.Min((double)num * 6.0, 30.0); double num3 = ((reference4.fluidInputCount > 0 && reference4.fluidInputCargoCount > 0.0001f) ? Math.Max(1.0, (double)reference4.fluidInputCount / (double)reference4.fluidInputCargoCount) : 1.0); int num4 = ((reference4.fluidInputCount > 0) ? (reference4.fluidInputInc / reference4.fluidInputCount) : 0); double num5 = Cargo.accTableMilli[Mathf.Clamp(num4, 0, 10)]; AddRate(dictionary, reference4.productId, num2 * num3 * 60.0 * (double)reference4.produceProb * (1.0 + num5)); } } } } Dictionary<int, long> dictionary2 = new Dictionary<int, long>(dictionary.Count); foreach (KeyValuePair<int, double> item in dictionary) { long num6 = (long)(item.Value + 0.5); if (num6 > 0) { dictionary2[item.Key] = num6; } } return dictionary2; } private static void AddRecipeOutput(Dictionary<int, double> totals, RecipeExecuteData recipe, int speed, int extraSpeed) { if (recipe.products == null || recipe.productCounts == null) { return; } double num = CyclesPerMinute(recipe, speed, extraSpeed); if (!(num <= 0.0)) { for (int i = 0; i < recipe.products.Length && i < recipe.productCounts.Length; i++) { AddRate(totals, recipe.products[i], num * (double)recipe.productCounts[i]); } } } internal static double MinerRatePerMinute(ref MinerComponent m, VeinData[] veinPool, float miningSpeed, out int productId) { //IL_0079: 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_007f: 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_0093: Expected I4, but got Unknown productId = m.productId; if (m.period <= 0) { return 0.0; } int num = ((m.veinCount > 0 && m.veins != null && m.veins.Length != 0) ? m.veins[0] : 0); bool flag = veinPool != null && num > 0 && num < veinPool.Length; if (productId == 0 && flag) { productId = veinPool[num].productId; } if (productId <= 0) { return 0.0; } EMinerType type = m.type; double num2; switch (type - 1) { case 1: num2 = m.veinCount; break; case 2: num2 = (flag ? ((float)veinPool[num].amount * VeinData.oilSpeedMultiplier) : 0f); break; case 0: num2 = 1.0; break; default: return 0.0; } return (double)m.speed * (double)miningSpeed * num2 / (double)m.period * 3600.0; } internal static double CyclesPerMinute(RecipeExecuteData recipe, int speed, int extraSpeed) { if (recipe == null || recipe.timeSpend <= 0 || speed <= 0) { return 0.0; } double num = 3600.0 * (double)speed / (double)recipe.timeSpend; if (extraSpeed > 0 && recipe.extraTimeSpend > 0) { num += 3600.0 * (double)extraSpeed / (double)recipe.extraTimeSpend; } return num; } } public class MachineGroup { public int BuildingId; public int Count; public double TotalRate; public RecipeExecuteData Recipe; public int Veins; public bool Planned; public double RatePerMachine { get { if (Count <= 0) { return 0.0; } return TotalRate / (double)Count; } } public double RatePerVein { get { if (Veins <= 0) { return 0.0; } return TotalRate / (double)Veins; } } } public class InputReport { public int ItemId; public double NeededPerMin; public long MadePerMin; public long UsedPerMin; public int ImportStations; public long ImportStock; public long ImportIncoming; public MachineGroup Makers; public int MakersPlaced; public bool IsImported => ImportStations > 0; public long AvailablePerMin => Math.Max(MadePerMin, UsedPerMin); } public class ProductionReport { public int Machines; public int Working; public int MissingInput; public int OutputFull; public int LowPower; public int NoPower; public int Idle; public int Depleted; public readonly Dictionary<int, int> MissingItems = new Dictionary<int, int>(); public MachineGroup Main; public RecipeProto PlannedRecipe; public readonly List<InputReport> Inputs = new List<InputReport>(); } public static class ProductionInsight { public static ProductionReport Analyze(TodoItem task) { //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Invalid comparison between Unknown and I4 ProductionReport productionReport = new ProductionReport(); List<PlanetFactory> list = Plugin.GetFactories(task.PlanetId).ToList(); Dictionary<int, Dictionary<long, MachineGroup>> dictionary = new Dictionary<int, Dictionary<long, MachineGroup>>(); Dictionary<int, int> dictionary2 = new Dictionary<int, int>(); foreach (PlanetFactory item in list) { FactorySystem factorySystem = item.factorySystem; if (factorySystem == null) { continue; } if (factorySystem.assemblerPool != null) { for (int i = 1; i < factorySystem.assemblerCursor; i++) { ref AssemblerComponent reference = ref factorySystem.assemblerPool[i]; if (reference.id == i && reference.recipeId > 0 && reference.recipeExecuteData != null) { int buildingId = GetBuildingId(item, reference.entityId); dictionary2[buildingId] = ((!dictionary2.TryGetValue(buildingId, out var value)) ? 1 : (value + 1)); AddMachine(dictionary, buildingId, reference.recipeId, reference.recipeExecuteData, Math.Max(reference.speed, reference.speedOverride), reference.extraSpeed); if (Makes(reference.recipeExecuteData, task.ItemId)) { Classify(productionReport, item, reference.recipeExecuteData, reference.replicating, reference.time, reference.served, reference.pcId); } } } } if (factorySystem.labPool != null) { for (int j = 1; j < factorySystem.labCursor; j++) { ref LabComponent reference2 = ref factorySystem.labPool[j]; if (reference2.id == j && !reference2.researchMode && reference2.recipeId > 0 && reference2.recipeExecuteData != null) { int buildingId2 = GetBuildingId(item, reference2.entityId); dictionary2[buildingId2] = ((!dictionary2.TryGetValue(buildingId2, out var value2)) ? 1 : (value2 + 1)); AddMachine(dictionary, buildingId2, reference2.recipeId, reference2.recipeExecuteData, Math.Max(reference2.speed, reference2.speedOverride), reference2.extraSpeed); if (Makes(reference2.recipeExecuteData, task.ItemId)) { Classify(productionReport, item, reference2.recipeExecuteData, reference2.replicating, reference2.time, reference2.served, reference2.pcId); } } } } if (factorySystem.minerPool == null) { continue; } float miningSpeed = ((GameMain.history != null) ? GameMain.history.miningSpeedScale : 1f); for (int k = 1; k < factorySystem.minerCursor; k++) { ref MinerComponent reference3 = ref factorySystem.minerPool[k]; if (reference3.id != k) { continue; } int productId; double num = Plugin.MinerRatePerMinute(ref reference3, item.veinPool, miningSpeed, out productId); if (productId > 0) { int buildingId3 = GetBuildingId(item, reference3.entityId); MachineGroup machineGroup = GetGroup(dictionary, productId, buildingId3, 0, null); machineGroup.Count++; machineGroup.TotalRate += num; if ((int)reference3.type == 2) { machineGroup.Veins += reference3.veinCount; } if (productId == task.ItemId) { ClassifyMiner(productionReport, item, ref reference3); } } } } productionReport.Main = MainGroup(dictionary, task.ItemId); if (productionReport.Main == null && productionReport.Machines == 0 && task.CurrentAmount <= 0) { productionReport.PlannedRecipe = PickRecipe(task.ItemId); productionReport.Main = PlannedGroup(productionReport.PlannedRecipe, task.ItemId, dictionary2); if (productionReport.Main == null) { productionReport.PlannedRecipe = null; } } if (productionReport.Main == null || task.TargetAmount <= 0) { return productionReport; } RecipeExecuteData recipe = productionReport.Main.Recipe; if (recipe == null) { return productionReport; } int num2 = ProductCount(recipe, task.ItemId); if (num2 <= 0 || recipe.requires == null || recipe.requireCounts == null) { return productionReport; } FactoryProductionStat[] array = GameMain.data?.statistics?.production?.factoryStatPool; for (int l = 0; l < recipe.requires.Length && l < recipe.requireCounts.Length; l++) { int num3 = recipe.requires[l]; InputReport inputReport = new InputReport { ItemId = num3, NeededPerMin = (double)task.TargetAmount * (double)recipe.requireCounts[l] / (double)num2, Makers = MainGroup(dictionary, num3) }; if (dictionary.TryGetValue(num3, out var value3)) { inputReport.MakersPlaced = value3.Values.Sum((MachineGroup g) => g.Count); } foreach (PlanetFactory item2 in list) { if (array != null && item2.index >= 0 && item2.index < array.Length && array[item2.index] != null) { inputReport.MadePerMin += Plugin.GetProducedLastMinute(array[item2.index], num3); inputReport.UsedPerMin += Plugin.GetConsumedLastMinute(array[item2.index], num3); } AddImports(inputReport, item2); } if (inputReport.Makers == null && !inputReport.IsImported) { inputReport.Makers = PlannedGroup(PickRecipe(num3), num3, dictionary2); } productionReport.Inputs.Add(inputReport); } return productionReport; } private static void AddImports(InputReport input, PlanetFactory factory) { //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_005d: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Invalid comparison between Unknown and I4 //IL_008b: 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_00aa: Unknown result type (might be due to invalid IL or missing references) StationComponent[] array = factory.transport?.stationPool; if (array == null) { return; } for (int i = 1; i < factory.transport.stationCursor && i < array.Length; i++) { StationComponent val = array[i]; if (val == null || val.id != i || !val.isStellar || val.storage == null) { continue; } StationStore[] storage = val.storage; foreach (StationStore val2 in storage) { if (val2.itemId == input.ItemId && (int)val2.remoteLogic == 2) { input.ImportStations++; input.ImportStock += val2.count; if (val2.remoteOrder > 0) { input.ImportIncoming += val2.remoteOrder; } } } } } private static RecipeProto PickRecipe(int itemId) { ItemProto item = ((ProtoSet<ItemProto>)(object)LDB.items)?.Select(itemId); if (item == null) { return null; } List<RecipeProto> list = new List<RecipeProto>(); if (item.maincraft != null) { list.Add(item.maincraft); } if (item.recipes != null) { list.AddRange(item.recipes.Where((RecipeProto r) => r != null && r != item.maincraft)); } list = list.Where((RecipeProto r) => RunsInMachine(r.Type) && ProductCount(r.Results, r.ResultCounts, itemId) > 0).ToList(); if (list.Count == 0) { return null; } GameHistoryData history = GameMain.history; return ((IEnumerable<RecipeProto>)list).FirstOrDefault((Func<RecipeProto, bool>)((RecipeProto r) => history == null || history.RecipeUnlocked(((Proto)r).ID))) ?? list[0]; } private static MachineGroup PlannedGroup(RecipeProto recipe, int itemId, Dictionary<int, int> buildings) { //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Expected O, but got Unknown if (recipe == null || (Object)(object)LDB.items == (Object)null) { return null; } ItemProto val = (from kv in buildings select (proto: ((ProtoSet<ItemProto>)(object)LDB.items).Select(kv.Key), count: kv.Value) into b where BuildingSpeed(b.proto, recipe.Type) > 0 orderby b.count descending select b.proto).FirstOrDefault(); if (val == null && ((ProtoSet<ItemProto>)(object)LDB.items).dataArray != null) { GameHistoryData history = GameMain.history; List<ItemProto> source = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray.Where((ItemProto p) => p != null && p.CanBuild && BuildingSpeed(p, recipe.Type) > 0).ToList(); val = (from p in source where history == null || history.ItemUnlocked(((Proto)p).ID) orderby BuildingSpeed(p, recipe.Type) descending select p).FirstOrDefault() ?? source.OrderBy((ItemProto p) => BuildingSpeed(p, recipe.Type)).FirstOrDefault(); } if (val == null) { return null; } if (recipe.TimeSpend <= 0) { return null; } double num = 3600.0 * (double)BuildingSpeed(val, recipe.Type) / ((double)recipe.TimeSpend * 10000.0); RecipeExecuteData value; return new MachineGroup { BuildingId = ((Proto)val).ID, Count = 1, Planned = true, Recipe = (RecipeExecuteData)((RecipeProto.recipeExecuteData != null && RecipeProto.recipeExecuteData.TryGetValue(((Proto)recipe).ID, out value)) ? ((object)value) : ((object)new RecipeExecuteData(recipe.Items, recipe.ItemCounts, recipe.Results, recipe.ResultCounts, recipe.TimeSpend * 10000, 0, recipe.productive))), TotalRate = num * (double)ProductCount(recipe.Results, recipe.ResultCounts, itemId) }; } private static bool RunsInMachine(ERecipeType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 if ((int)type != 1 && (int)type != 2 && (int)type != 3 && (int)type != 4 && (int)type != 5) { return (int)type == 15; } return true; } private static int BuildingSpeed(ItemProto building, ERecipeType type) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //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) PrefabDesc val = building?.prefabDesc; if (val == null) { return 0; } if ((int)type == 15) { if (!val.isLab) { return 0; } return val.labAssembleSpeed; } if (!val.isAssembler || val.assemblerRecipeType != type) { return 0; } return val.assemblerSpeed; } public static int BuildingsNeeded(double perMinute, MachineGroup group) { if (group == null || group.RatePerMachine <= 0.0) { return 0; } return (int)Math.Ceiling(perMinute / group.RatePerMachine - 0.001); } private static int GetBuildingId(PlanetFactory factory, int entityId) { EntityData[] entityPool = factory.entityPool; if (entityPool == null || entityId <= 0 || entityId >= entityPool.Length) { return 0; } return entityPool[entityId].protoId; } private static bool Makes(RecipeExecuteData recipe, int itemId) { return ProductCount(recipe, itemId) > 0; } private static int ProductCount(RecipeExecuteData recipe, int itemId) { return ProductCount(recipe.products, recipe.productCounts, itemId); } private static int ProductCount(int[] products, int[] productCounts, int itemId) { if (products == null || productCounts == null) { return 0; } for (int i = 0; i < products.Length && i < productCounts.Length; i++) { if (products[i] == itemId) { return productCounts[i]; } } return 0; } private static void AddMachine(Dictionary<int, Dictionary<long, MachineGroup>> makers, int buildingId, int recipeId, RecipeExecuteData recipe, int speed, int extraSpeed) { if (recipe.products != null && recipe.productCounts != null) { double num = Plugin.CyclesPerMinute(recipe, speed, extraSpeed); for (int i = 0; i < recipe.products.Length && i < recipe.productCounts.Length; i++) { MachineGroup machineGroup = GetGroup(makers, recipe.products[i], buildingId, recipeId, recipe); machineGroup.Count++; machineGroup.TotalRate += num * (double)recipe.productCounts[i]; } } } private static MachineGroup GetGroup(Dictionary<int, Dictionary<long, MachineGroup>> makers, int itemId, int buildingId, int recipeId, RecipeExecuteData recipe) { long key = ((long)buildingId << 32) | (uint)recipeId; if (!makers.TryGetValue(itemId, out var value)) { value = (makers[itemId] = new Dictionary<long, MachineGroup>()); } if (!value.TryGetValue(key, out var value2)) { MachineGroup obj = new MachineGroup { BuildingId = buildingId, Recipe = recipe }; value2 = (value[key] = obj); } return value2; } private static void ClassifyMiner(ProductionReport report, PlanetFactory factory, ref MinerComponent m) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Invalid comparison between Unknown and I4 report.Machines++; double num = PowerRatio(factory, m.pcId); if ((int)m.type != 1 && m.veinCount == 0) { report.Depleted++; } else if ((int)m.workstate == -2 || m.speedDamper < 0.99f) { report.OutputFull++; } else if (num <= 0.1) { report.NoPower++; } else if (num < 1.0) { report.LowPower++; } else { report.Working++; } } private static MachineGroup MainGroup(Dictionary<int, Dictionary<long, MachineGroup>> makers, int itemId) { if (!makers.TryGetValue(itemId, out var value) || value.Count == 0) { return null; } return value.Values.OrderByDescending((MachineGroup g) => g.Count).First(); } private static void Classify(ProductionReport report, PlanetFactory factory, RecipeExecuteData recipe, bool replicating, int time, int[] served, int pcId) { report.Machines++; double num = PowerRatio(factory, pcId); if (replicating) { if (num >= 1.0) { report.Working++; } else if (num > 0.1) { report.LowPower++; } else { report.NoPower++; } return; } if (time >= recipe.timeSpend) { report.OutputFull++; return; } bool flag = false; if (served != null && recipe.requires != null && recipe.requireCounts != null) { for (int i = 0; i < recipe.requireCounts.Length && i < served.Length && i < recipe.requires.Length; i++) { if (served[i] < recipe.requireCounts[i]) { flag = true; int key = recipe.requires[i]; report.MissingItems[key] = ((!report.MissingItems.TryGetValue(key, out var value)) ? 1 : (value + 1)); } } } if (flag) { report.MissingInput++; } else if (num >= 1.0) { report.Idle++; } else if (num > 0.1) { report.LowPower++; } else { report.NoPower++; } } private static double PowerRatio(PlanetFactory factory, int pcId) { PowerSystem powerSystem = factory.powerSystem; if (powerSystem == null || powerSystem.consumerPool == null || pcId <= 0 || pcId >= powerSystem.consumerPool.Length) { return 0.0; } int networkId = powerSystem.consumerPool[pcId].networkId; if (networkId <= 0 || powerSystem.netPool == null || networkId >= powerSystem.netPool.Length || powerSystem.netPool[networkId] == null) { return 0.0; } return powerSystem.netPool[networkId].consumerRatio; } } public static class SaveManager { private const int FormatVersion = 1; public static void Write(BinaryWriter w, List<TodoItem> tasks, int lastPlanetId) { w.Write(1); w.Write(lastPlanetId); w.Write(tasks.Count); foreach (TodoItem task in tasks) { w.Write(task.Description ?? ""); w.Write(task.IsCompleted); w.Write((int)task.Type); w.Write(task.ItemId); w.Write(task.TargetAmount); w.Write(task.CurrentAmount); w.Write(task.ActualAmount); w.Write(task.PlanetId); } } public static List<TodoItem> Read(BinaryReader r, out int lastPlanetId) { int num = r.ReadInt32(); if (num < 1 || num > 1) { throw new InvalidDataException($"Unsupported task data version {num}"); } lastPlanetId = r.ReadInt32(); int num2 = r.ReadInt32(); List<TodoItem> list = new List<TodoItem>(num2); for (int i = 0; i < num2; i++) { string desc = r.ReadString(); bool isCompleted = r.ReadBoolean(); TaskType type = (TaskType)r.ReadInt32(); int itemId = r.ReadInt32(); int target = r.ReadInt32(); TodoItem item = new TodoItem(desc, type, itemId, target) { IsCompleted = isCompleted, CurrentAmount = r.ReadInt64(), ActualAmount = r.ReadInt64(), PlanetId = r.ReadInt32() }; list.Add(item); } return list; } } public class TaskOverlay { private enum Tone { Info, Problem, Done, Muted } private class Row { public TodoItem Task; public GameObject Go; public CanvasGroup Group; public Image Edge; public Image Icon; public Text Name; public Text Status; public RectTransform Fill; public Image FillImage; public RectTransform Tick; public Text Left; public Text Right; public bool Problem; public float DoneSince; } private const int MaxRows = 5; private const float Width = 270f; private const float HeaderHeight = 22f; private const float RowHeight = 42f; private const float DoneShowSeconds = 4f; private const float DoneFadeSeconds = 1f; private const float ReasonRefreshSeconds = 3f; private static readonly Color Accent = new Color(0.35f, 0.72f, 1f, 0.9f); private static readonly Color AccentSoft = new Color(0.35f, 0.72f, 1f, 0.16f); private static readonly Color HeaderText = new Color(0.81f, 0.9f, 1f, 1f); private static readonly Color Line = new Color(0.63f, 0.8f, 1f, 0.18f); private static readonly Color RowSeparator = new Color(1f, 1f, 1f, 0.05f); private static readonly Color Lag = new Color(0.95f, 0.6f, 0.2f, 1f); private static readonly Color Met = new Color(0.35f, 0.8f, 0.4f, 1f); private static readonly Color Below = new Color(0.55f, 0.65f, 0.8f, 1f); private static readonly Color ResearchColor = new Color(0.88f, 0.76f, 0.25f, 1f); private GameObject _root; private RectTransform _rootRt; private Canvas _canvas; private bool _dragged; private Text _headerRight; private readonly Dictionary<TodoItem, Row> _rows = new Dictionary<TodoItem, Row>(); private readonly Dictionary<TodoItem, (long value, float time, double rate)> _research = new Dictionary<TodoItem, (long, float, double)>(); private readonly Dictionary<TodoItem, (float time, string tag)> _reasons = new Dictionary<TodoItem, (float, string)>(); public void Hide() { if ((Object)(object)_root != (Object)null && _root.activeSelf) { _root.SetActive(false); } } public void Update() { Plugin instance = Plugin.Instance; if (!instance.OverlayEnabled.Value || !IsInGame() || UIManager.Instance.IsWindowOpen) { Hide(); ClearDoneRows(); return; } int planetId = instance.GetDisplayPlanetId(); List<TodoItem> visible = (from t in instance.GetTodoItems() where t.Type != TaskType.Manual where t.PlanetId == 0 || (planetId != 0 && t.PlanetId == planetId) select t).ToList(); List<TodoItem> list = (from t in visible where !t.IsCompleted orderby t.IsBelowCapacity() descending, TaskText.Progress(t) select t).ToList(); foreach (TodoItem item in _reasons.Keys.Where((TodoItem t) => !visible.Contains(t)).ToList()) { _reasons.Remove(item); } foreach (TodoItem item2 in _research.Keys.Where((TodoItem t) => !visible.Contains(t)).ToList()) { _research.Remove(item2); } List<TodoItem> shown = list.Take(5).ToList(); foreach (Row value2 in _rows.Values) { if (value2.Task.IsCompleted && visible.Contains(value2.Task) && !shown.Contains(value2.Task)) { shown.Add(value2.Task); } } if (shown.Count == 0) { Hide(); } else { if ((Object)(object)_root == (Object)null && !Build()) { return; } if (!_root.activeSelf) { _root.SetActive(true); } foreach (TodoItem item3 in _rows.Keys.Where((TodoItem t) => !shown.Contains(t)).ToList()) { Object.Destroy((Object)(object)_rows[item3].Go); _rows.Remove(item3); } int num = 1; foreach (TodoItem item4 in shown) { if (!_rows.TryGetValue(item4, out var value)) { value = CreateRow(item4); _rows[item4] = value; } value.Go.transform.SetSiblingIndex(num++); UpdateRow(value); } string arg = ((planetId != 0) ? instance.GetPlanetName(planetId) : "Global"); _headerRight.text = $"{arg} · {list.Count} open"; } } private void ClearDoneRows() { foreach (TodoItem item in _rows.Keys.Where((TodoItem t) => t.IsCompleted).ToList()) { Object.Destroy((Object)(object)_rows[item].Go); _rows.Remove(item); } } private static bool IsInGame() { if (DSPGame.IsMenuDemo || !GameMain.isRunning || GameMain.mainPlayer == null) { return false; } UIGame val = UIRoot.instance?.uiGame; if ((Object)(object)val == (Object)null || val.hideAllUI0 || val.hideAllUI1) { return false; } if ((Object)(object)val.starmap != (Object)null && ((ManualBehaviour)val.starmap).active) { return false; } if ((Object)(object)val.dysonEditor != (Object)null && ((ManualBehaviour)val.dysonEditor).active) { return false; } return !UIItemPicker.isOpened; } private void UpdateRow(Row row) { //IL_004f: 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_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) TodoItem task = row.Task; float unscaledTime = Time.unscaledTime; if (task.IsCompleted && row.DoneSince <= 0f) { row.DoneSince = unscaledTime; } if (!task.IsCompleted) { row.DoneSince = 0f; } float num = TaskText.Progress(task); row.Fill.anchorMax = new Vector2(num, 1f); row.Right.text = TaskText.OverlayValue(task); row.Left.text = LeftText(task); bool flag = task.Type == TaskType.ProductionTarget && task.TargetAmount > 0 && task.IsBelowCapacity(); ((Component)row.Tick).gameObject.SetActive(flag); if (flag) { float num2 = Mathf.Clamp01((float)task.ActualAmount / (float)task.TargetAmount); row.Tick.anchorMin = new Vector2(num2, 0f); row.Tick.anchorMax = new Vector2(num2, 1f); } string text; Tone tone; if (!task.IsCompleted) { (text, tone) = StatusTag(task); } else { text = "Done"; tone = Tone.Done; } row.Problem = tone == Tone.Problem; SetStatus(row, text, tone); ((Graphic)row.FillImage).color = (task.IsCompleted ? Met : ((task.Type == TaskType.Research) ? ResearchColor : (row.Problem ? Lag : Below))); ((Behaviour)row.Edge).enabled = row.Problem; } private string LeftText(TodoItem task) { switch (task.Type) { case TaskType.ProductionTarget: return TaskText.Fmt(task.ActualAmount) + " actual"; case TaskType.Research: return ResearchEta(task); case TaskType.Surplus: return TaskText.Fmt(task.ActualAmount) + " made, " + TaskText.Fmt(task.TotalAmount) + " used"; case TaskType.Building: { long num = task.TargetAmount - task.CurrentAmount; if (num <= 0) { return ""; } return TaskText.Fmt(num) + " to go"; } default: return ""; } } private (string, Tone) StatusTag(TodoItem task) { switch (task.Type) { case TaskType.ProductionTarget: if (task.CurrentAmount <= 0) { return ("No machines", Tone.Problem); } if (!task.IsBelowCapacity()) { return ("Producing", Tone.Info); } return (ProblemReason(task), Tone.Problem); case TaskType.Research: if (task.StatusText == "Researching") { return ("Researching", Tone.Info); } return (task.StatusText ?? "Not queued", Tone.Muted); case TaskType.Building: return ("Building", Tone.Info); case TaskType.Surplus: if (task.CurrentAmount >= 0) { return ("Surplus", Tone.Info); } return ("Deficit", Tone.Problem); case TaskType.Sphere: return ("Sphere", Tone.Info); default: return ("Collecting", Tone.Info); } } private string ProblemReason(TodoItem task) { float unscaledTime = Time.unscaledTime; if (_reasons.TryGetValue(task, out (float, string) value) && unscaledTime - value.Item1 < 3f) { return value.Item2; } string text = "Slow"; try { ProductionReport productionReport = ProductionInsight.Analyze(task); (int, string) tuple = new List<(int, string)> { (productionReport.MissingInput, "Missing input"), (productionReport.OutputFull, "Backed up"), (productionReport.NoPower, "No power"), (productionReport.LowPower, "Low power"), (productionReport.Depleted, "Ore depleted") }.OrderByDescending<(int, string), int>(((int count, string tag) x) => x.count).First(); if (tuple.Item1 > 0) { text = tuple.Item2; } } catch (Exception ex) { Plugin.Instance.Log.LogWarning((object)("Overlay: could not analyze '" + task.Description + "': " + ex.Message)); } _reasons[task] = (unscaledTime, text); return text; } private string ResearchEta(TodoItem task) { float unscaledTime = Time.unscaledTime; if (task.StatusText != "Researching" || task.TotalAmount <= 0) { _research.Remove(task); return ""; } if (_research.TryGetValue(task, out (long, float, double) value)) { float num = unscaledTime - value.Item2; if (num < 0.5f) { return FormatEta(task, value.Item3); } double num2 = (double)(task.CurrentAmount - value.Item1) / (double)num; if (num2 < 0.0) { num2 = 0.0; } double num3 = ((value.Item3 > 0.0) ? (value.Item3 * 0.8 + num2 * 0.2) : num2); _research[task] = (task.CurrentAmount, unscaledTime, num3); return FormatEta(task, num3); } _research[task] = (task.CurrentAmount, unscaledTime, 0.0); return ""; } private static string FormatEta(TodoItem task, double hashesPerSecond) { if (hashesPerSecond <= 0.0) { return ""; } double num = (double)(task.TotalAmount - task.CurrentAmount) / hashesPerSecond; if (num < 60.0) { return "<1 min left"; } if (num < 3600.0) { return $"~{(int)Math.Ceiling(num / 60.0)} min left"; } return $"~{num / 3600.0:0.#} h left"; } private static void SetStatus(Row row, string text, Tone tone) { //IL_002d: 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_004f: 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) row.Status.text = text.ToUpperInvariant(); switch (tone) { case Tone.Problem: ((Graphic)row.Status).color = Lag; break; case Tone.Done: ((Graphic)row.Status).color = Met; break; case Tone.Muted: ((Graphic)row.Status).color = GameStyle.MutedText; break; default: ((Graphic)row.Status).color = Accent; break; } } public void Animate() { if ((Object)(object)_root == (Object)null || !_root.activeSelf) { return; } float unscaledTime = Time.unscaledTime; List<TodoItem> list = null; foreach (Row value in _rows.Values) { if (value.DoneSince > 0f) { float num = unscaledTime - value.DoneSince; value.Group.alpha = ((num < 4f) ? 1f : Mathf.Clamp01(1f - (num - 4f) / 1f)); if (num >= 5f) { (list ?? (list = new List<TodoItem>())).Add(value.Task); } } else { value.Group.alpha = 1f; } } if (list == null) { return; } foreach (TodoItem item in list) { Object.Destroy((Object)(object)_rows[item].Go); _rows.Remove(item); } if (_rows.Count == 0) { Hide(); } } private bool Build() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_008e: 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_00aa: 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_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown Canvas val = UIRoot.instance?.overlayCanvas; if ((Object)(object)val == (Object)null) { return false; } GameStyle.Init(); _root = new GameObject("TaskMasterOverlay"); _root.layer = LayerMask.NameToLayer("UI"); _rootRt = _root.AddComponent<RectTransform>(); ((Transform)_rootRt).SetParent(((Component)val).transform, false); _canvas = val; RectTransform rootRt = _rootRt; RectTransform rootRt2 = _rootRt; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(1f, 1f); rootRt2.anchorMax = val2; rootRt.anchorMin = val2; _rootRt.pivot = new Vector2(1f, 1f); _rootRt.sizeDelta = new Vector2(270f, 0f); _rootRt.anchoredPosition = LoadPosition(); ((Graphic)GameStyle.CreateWindowBackground(_root)).raycastTarget = true; VerticalLayoutGroup obj = _root.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)obj).padding = new RectOffset(0, 0, 0, 2); ((HorizontalOrVerticalLayoutGroup)obj).spacing = 0f; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true; _root.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2; BuildHeader(); BuildFrame(); EventTrigger et = _root.AddComponent<EventTrigger>(); AddTrigger(et, (EventTriggerType)5, delegate(BaseEventData data) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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) PointerEventData val3 = (PointerEventData)data; float num = (((Object)(object)_canvas != (Object)null && _canvas.scaleFactor > 0f) ? _canvas.scaleFactor : 1f); RectTransform rootRt3 = _rootRt; rootRt3.anchoredPosition += val3.delta / num; }); AddTrigger(et, (EventTriggerType)2, delegate { _dragged = false; }); AddTrigger(et, (EventTriggerType)13, delegate { _dragged = true; }); AddTrigger(et, (EventTriggerType)14, delegate { SavePosition(); }); AddTrigger(et, (EventTriggerType)4, delegate(BaseEventData data) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown PointerEventData val3 = (PointerEventData)data; if (!_dragged && !val3.dragging && !IsOnHeader(val3)) { UIManager.Instance.ToggleWindow(); } }); _root.AddComponent<OverlayAnimator>().Overlay = this; return true; } private void BuildHeader() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: 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) //IL_00d5: 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_0134: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Header"); val.transform.SetParent((Transform)(object)_rootRt, false); val.AddComponent<RectTransform>(); LayoutElement obj = val.AddComponent<LayoutElement>(); obj.minHeight = 22f; obj.preferredHeight = 22f; Stretch(((Graphic)NewImage("Strip", val.transform, AccentSoft)).rectTransform, 0f, 0f, 0f, 0f); RectTransform rectTransform = ((Graphic)NewImage("Line", val.transform, Line)).rectTransform; rectTransform.anchorMin = new Vector2(0f, 0f); rectTransform.anchorMax = new Vector2(1f, 0f); rectTransform.pivot = new Vector2(0.5f, 0f); rectTransform.sizeDelta = new Vector2(0f, 1f); Text obj2 = NewText("Title", val.transform, "TASKS", 11, HeaderText, (TextAnchor)3); obj2.fontStyle = (FontStyle)1; Stretch(((Graphic)obj2).rectTransform, 10f, 0f, 0f, 0f); _headerRight = NewText("Planet", val.transform, "", 10, GameStyle.MutedText, (TextAnchor)5); Stretch(((Graphic)_headerRight).rectTransform, 60f, 10f, 0f, 0f); } private void BuildFrame() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_011d: 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_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) Vector2[] array = (Vector2[])(object)new Vector2[4] { new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0f, 0f), new Vector2(1f, 0f) }; foreach (Vector2 val in array) { GameObject val2 = new GameObject("Corner"); val2.transform.SetParent((Transform)(object)_rootRt, false); RectTransform obj = val2.AddComponent<RectTransform>(); Vector2 val3 = (obj.pivot = val); Vector2 anchorMin = (obj.anchorMax = val3); obj.anchorMin = anchorMin; obj.anchoredPosition = new Vector2((float)((val.x != 0f) ? 1 : (-1)), (float)((val.y != 0f) ? 1 : (-1))); obj.sizeDelta = new Vector2(10f, 10f); val2.AddComponent<LayoutElement>().ignoreLayout = true; Image obj2 = NewImage("H", val2.transform, Accent); ((Graphic)obj2).rectTransform.anchorMin = new Vector2(0f, val.y); ((Graphic)obj2).rectTransform.anchorMax = new Vector2(1f, val.y); ((Graphic)obj2).rectTransform.pivot = new Vector2(0.5f, val.y); ((Graphic)obj2).rectTransform.sizeDelta = new Vector2(0f, 2f); Image obj3 = NewImage("V", val2.transform, Accent); ((Graphic)obj3).rectTransform.anchorMin = new Vector2(val.x, 0f); ((Graphic)obj3).rectTransform.anchorMax = new Vector2(val.x, 1f); ((Graphic)obj3).rectTransform.pivot = new Vector2(val.x, 0.5f); ((Graphic)obj3).rectTransform.sizeDelta = new Vector2(2f, 0f); } } private Row CreateRow(TodoItem task) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_008e: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0178: 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_01ca: 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_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_0382: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03b0: Unknown result type (might be due to invalid IL or missing references) //IL_03c4: Unknown result type (might be due to invalid IL or missing references) //IL_03de: Unknown result type (might be due to invalid IL or missing references) //IL_03fa: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_0424: Unknown result type (might be due to invalid IL or missing references) //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_044d: Unknown result type (might be due to invalid IL or missing references) //IL_0463: Unknown result type (might be due to invalid IL or missing references) //IL_0489: Unknown result type (might be due to invalid IL or missing references) //IL_04a3: Unknown result type (might be due to invalid IL or missing references) //IL_04b9: Unknown result type (might be due to invalid IL or missing references) //IL_04be: Unknown result type (might be due to invalid IL or missing references) //IL_04bf: Unknown result type (might be due to invalid IL or missing references) //IL_04c6: Unknown result type (might be due to invalid IL or missing references) //IL_04d8: Unknown result type (might be due to invalid IL or missing references) //IL_0501: Unknown result type (might be due to invalid IL or missing references) //IL_051b: Unknown result type (might be due to invalid IL or missing references) //IL_052b: Unknown result type (might be due to invalid IL or missing references) //IL_054d: Unknown result type (might be due to invalid IL or missing references) //IL_0573: Unknown result type (might be due to invalid IL or missing references) //IL_0588: Unknown result type (might be due to invalid IL or missing references) //IL_059d: Unknown result type (might be due to invalid IL or missing references) //IL_05b2: Unknown result type (might be due to invalid IL or missing references) //IL_05c6: Unknown result type (might be due to invalid IL or missing references) //IL_05e8: Unknown result type (might be due to invalid IL or missing references) //IL_060e: Unknown result type (might be due to invalid IL or missing references) //IL_0623: Unknown result type (might be due to invalid IL or missing references) //IL_0638: Unknown result type (might be due to invalid IL or missing references) //IL_064d: Unknown result type (might be due to invalid IL or missing references) //IL_0661: Unknown result type (might be due to invalid IL or missing references) Row row = new Row { Task = task }; row.Go = new GameObject("Row"); row.Go.transform.SetParent((Transform)(object)_rootRt, false); row.Go.AddComponent<RectTransform>(); LayoutElement obj = row.Go.AddComponent<LayoutElement>(); obj.minHeight = 42f; obj.preferredHeight = 42f; row.Group = row.Go.AddComponent<CanvasGroup>(); row.Group.blocksRaycasts = false; row.Edge = NewImage("Edge", row.Go.transform, Lag); RectTransform rectTransform = ((Graphic)row.Edge).rectTransform; rectTransform.anchorMin = new Vector2(0f, 0f); rectTransform.anchorMax = new Vector2(0f, 1f); rectTransform.pivot = new Vector2(0f, 0.5f); rectTransform.offsetMin = new Vector2(0f, 5f); rectTransform.offsetMax = new Vector2(2f, -5f); RectTransform rectTransform2 = ((Graphic)NewImage("Separator", row.Go.transform, RowSeparator)).rectTransform; rectTransform2.anchorMin = new Vector2(0f, 1f); rectTransform2.anchorMax = new Vector2(1f, 1f); rectTransform2.pivot = new Vector2(0.5f, 1f); rectTransform2.sizeDelta = new Vector2(-16f, 1f); Image val = NewImage("Slot", row.Go.transform, new Color(1f, 1f, 1f, 0.06f)); RectTransform rectTransform3 = ((Graphic)val).rectTransform; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0f, 0.5f); rectTransform3.anchorMax = val2; rectTransform3.anchorMin = val2; rectTransform3.pivot = new Vector2(0f, 0.5f); rectTransform3.anchoredPosition = new Vector2(10f, 0f); rectTransform3.sizeDelta = new Vector2(28f, 28f); row.Icon = NewImage("Icon", ((Component)val).transform, Color.white); Stretch(((Graphic)row.Icon).rectTransform, 3f, 3f, 3f, 3f); Sprite taskIcon = UIManager.GetTaskIcon(task); row.Icon.sprite = taskIcon; ((Graphic)row.Icon).color = (((Object)(object)taskIcon != (Object)null) ? Color.white : Color.gray); row.Name = NewText("Name", row.Go.transform, TaskText.ShortName(task), 12, GameStyle.TextColor, (TextAnchor)3); row.Name.horizontalOverflow = (HorizontalWrapMode)0; RectTransform rectTransform4 = ((Graphic)row.Name).rectTransform; rectTransform4.anchorMin = new Vector2(0f, 1f); rectTransform4.anchorMax = new Vector2(1f, 1f); rectTransform4.pivot = new Vector2(0f, 1f); rectTransform4.anchoredPosition = new Vector2(46f, -4f); rectTransform4.sizeDelta = new Vector2(-146f, 15f); row.Status = NewText("Status", row.Go.transform, "", 10, HeaderText, (TextAnchor)5); row.Status.fontStyle = (FontStyle)1; RectTransform rectTransform5 = ((Graphic)row.Status).rectTransform; ((Vector2)(ref val2))..ctor(1f, 1f); rectTransform5.anchorMax = val2; rectTransform5.anchorMin = val2; rectTransform5.pivot = new Vector2(1f, 1f); rectTransform5.anchoredPosition = new Vector2(-10f, -4f); rectTransform5.sizeDelta = new Vector2(90f, 15f); Image val3 = NewImage("Bar", row.Go.transform, GameStyle.BarBackground); RectTransform rectTransform6 = ((Graphic)val3).rectTransform; rectTransform6.anchorMin = new Vector2(0f, 1f); rectTransform6.anchorMax = new Vector2(1f, 1f); rectTransform6.pivot = new Vector2(0f, 1f); rectTransform6.anchoredPosition = new Vector2(46f, -22f); rectTransform6.sizeDelta = new Vector2(-56f, 4f); row.FillImage = NewImage("Fill", ((Component)val3).transform, Below); row.Fill = ((Graphic)row.FillImage).rectTransform; row.Fill.anchorMin = Vector2.zero; row.Fill.anchorMax = new Vector2(0f, 1f); val2 = (row.Fill.offsetMin = (row.Fill.offsetMax = Vector2.zero)); Image val5 = NewImage("Tick", ((Component)val3).transform, Color.white); row.Tick = ((Graphic)val5).rectTransform; row.Tick.pivot = new Vector2(0.5f, 0.5f); row.Tick.sizeDelta = new Vector2(2f, 4f); row.Tick.anchoredPosition = Vector2.zero; row.Left = NewText("Left", row.Go.transform, "", 10, GameStyle.MutedText, (TextAnchor)3); RectTransform rectTransform7 = ((Graphic)row.Left).rectTransform; rectTransform7.anchorMin = new Vector2(0f, 1f); rectTransform7.anchorMax = new Vector2(1f, 1f); rectTransform7.pivot = new Vector2(0f, 1f); rectTransform7.anchoredPosition = new Vector2(46f, -27f); rectTransform7.sizeDelta = new Vector2(-56f, 13f); row.Right = NewText("Right", row.Go.transform, "", 10, GameStyle.MutedText, (TextAnchor)5); RectTransform rectTransform8 = ((Graphic)row.Right).rectTransform; rectTransform8.anchorMin = new Vector2(0f, 1f); rectTransform8.anchorMax = new Vector2(1f, 1f); rectTransform8.pivot = new Vector2(0f, 1f); rectTransform8.anchoredPosition = new Vector2(46f, -27f); rectTransform8.sizeDelta = new Vector2(-56f, 13f); return row; } private static Image NewImage(string name, Transform parent, Color color) { //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_0019: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); Image obj = val.AddComponent<Image>(); ((Graphic)obj).color = color; ((Graphic)obj).raycastTarget = false; return obj; } private static Text NewText(string name, Transform parent, string text, int size, Color color, TextAnchor align) { //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_0032: 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) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); Text obj = val.AddComponent<Text>(); obj.font = GameStyle.GetFont(); obj.text = text; obj.fontSize = size; ((Graphic)obj).color = color; obj.alignment = align; obj.horizontalOverflow = (HorizontalWrapMode)1; obj.verticalOverflow = (VerticalWrapMode)1; ((Graphic)obj).raycastTarget = false; return obj; } private static void Stretch(RectTransform rt, float left, float right, float top, float bottom) { //IL_0001: 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_001a: 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) rt.anchorMin = Vector2.zero; rt.anchorMax = Vector2.one; rt.offsetMin = new Vector2(left, bottom); rt.offsetMax = new Vector2(0f - right, 0f - top); } private bool IsOnHeader(PointerEventData pd) { //IL_0007: 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) Vector2 val = default(Vector2); if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(_rootRt, pd.position, pd.pressEventCamera, ref val)) { return false; } return val.y > -22f; } private static void AddTrigger(EventTrigger et, EventTriggerType type, UnityAction<BaseEventData> action) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown Entry val = new Entry { eventID = type }; ((UnityEvent<BaseEventData>)(object)val.callback).AddListener(action); et.triggers.Add(val); } private Vector2 LoadPosition() { //IL_0040: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) Plugin instance = Plugin.Instance; if (instance.OverlayX.Value != 0f || instance.OverlayY.Value != 0f) { return new Vector2(instance.OverlayX.Value, instance.OverlayY.Value); } Transform transform = ((Component)_canvas).transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); float num; if ((Object)(object)val != (Object)null) { Rect rect = val.rect; if (((Rect)(ref rect)).height > 0f) { rect = val.rect; num = ((Rect)(ref rect)).height; goto IL_008a; } } num = 1080f; goto IL_008a; IL_008a: float num2 = num; return new Vector2(-12f, (0f - num2) * 0.3f); } private void SavePosition() { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_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) //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_0032: 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_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) //IL_004d: 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_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_007f: 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) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)_canvas).transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val != (Object)null) { Rect rect = val.rect; Vector2 size = ((Rect)(ref rect)).size; Vector2 anchoredPosition = _rootRt.anchoredPosition; float x = anchoredPosition.x; float num = 0f - size.x; rect = _rootRt.rect; anchoredPosition.x = Mathf.Clamp(x, num + ((Rect)(ref rect)).width, 0f); float y = anchoredPosition.y; float num2 = 0f - size.y; rect = _rootRt.rect; anchoredPosition.y = Mathf.Clamp(y, num2 + ((Rect)(ref rect)).height, 0f); _rootRt.anchoredPosition = anchoredPosition; } Plugin.Instance.OverlayX.Value = _rootRt.anchoredPosition.x; Plugin.Instance.OverlayY.Value = _rootRt.anchoredPosition.y; } } public class OverlayAnimator : MonoBehaviour { public TaskOverlay Overlay; private void Update() { try { Overlay?.Animate(); } catch (Exception ex) { Plugin.Instance.Log.LogWarning((object)("Overlay animation failed: " + ex.Message)); ((Behaviour)this).enabled = false; } } } public static class TaskText { private static readonly CultureInfo Inv = CultureInfo.InvariantCulture; public static string Fmt(long value) { if (value < 0) { return "-" + Fmt(-value); } if (value >= 1000000000) { return ((double)value / 1000000000.0).ToString("0.##", Inv) + "G"; } if (value >= 1000000) { return ((double)value / 1000000.0).ToString((value >= 10000000) ? "0.#" : "0.##", Inv) + "M"; } if (value >= 100000) { return ((double)value / 1000.0).ToString("0.#", Inv) + "k"; } return value.ToString("N0", Inv); } public static string FmtSigned(long value) { if (value <= 0) { return Fmt(value); } return "+" + Fmt(value); } public static string FmtRate(double perMinute) { if (perMinute >= 100.0) { return Fmt((long)(perMinute + 0.5)); } return perMinute.ToString("0.#", Inv); } public static string FmtPower(long megawatts) { if (megawatts >= 1000000) { return ((double)megawatts / 1000000.0).ToString("0.##", Inv) + " TW"; } if (megawatts >= 1000) { return ((double)megawatts / 1000.0).ToString("0.##", Inv) + " GW"; } return megawatts.ToString("N0", Inv) + " MW"; } public static float Progress(TodoItem item) { if (item.Type == TaskType.Research) { if (item.IsCompleted) { return 1f; } if (item.TotalAmount <= 0) { return 0f; } return Mathf.Clamp01((float)item.CurrentAmount / (float)item.TotalAmount); } if (item.TargetAmount <= 0) { return 0f; } return Mathf.Clamp01((float)item.CurrentAmount / (float)item.TargetAmount); } public static string ProgressLine(TodoItem item) { int num = (int)(Progress(item) * 100f); switch (item.Type) { case TaskType.ProductionTarget: if (item.TargetAmount <= 0) { return "No target set"; } return $"Cap {Fmt(item.CurrentAmount)} / {Fmt(item.TargetAmount)} /min [{num}%]"; case TaskType.Research: if (item.IsCompleted) { return "Unlocked"; } if (item.TotalAmount <= 0) { return "Not started"; } return $"{Fmt(item.CurrentAmount)} / {Fmt(item.TotalAmount)} hashes [{num}%]"; case TaskType.Building: return $"{Fmt(item.CurrentAmount)} / {Fmt(item.TargetAmount)} placed [{num}%]"; case TaskType.Sphere: return $"{FmtPower(item.CurrentAmount)} / {FmtPower(item.TargetAmount)} [{num}%]"; case TaskType.Surplus: return $"Surplus {FmtSigned(item.CurrentAmount)} / {FmtSigned(item.TargetAmount)} /min [{num}%]"; default: if (item.TargetAmount <= 0) { return "No target set"; } return $"{Fmt(item.CurrentAmount)} / {Fmt(item.TargetAmount)} [{num}%]"; } } public static string ShortName(TodoItem item) { switch (item.Type) { case TaskType.InventoryTarget: case TaskType.ProductionTarget: return new ItemDefinition { Id = item.ItemId }.Name; case TaskType.Surplus: return new ItemDefinition { Id = item.ItemId }.Name + " surplus"; case TaskType.Research: return StripPrefix(item.Description, "Research "); default: return item.Description; } } private static string StripPrefix(string text, string prefix) { string text2; if (text == null || !text.StartsWith(prefix)) { text2 = text; if (text2 == null) { return ""; } } else { text2 = text.Substring(prefix.Length); } return text2; } public static string OverlayValue(TodoItem item) { return item.Type switch { TaskType.ProductionTarget => Fmt(item.CurrentAmount) + " / " + Fmt(item.TargetAmount) + " /min", TaskType.Research => (int)(Progress(item) * 100f) + "%", TaskType.Building => Fmt(item.CurrentAmount) + " / " + Fmt(item.TargetAmount) + " placed", TaskType.Sphere => FmtPower(item.CurrentAmount) + " / " + FmtPower(item.TargetAmount), TaskType.Surplus => FmtSigned(item.CurrentAmount) + " / " + FmtSigned(item.TargetAmount) + " /min", _ => Fmt(item.CurrentAmount) + " / " + Fmt(i