Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Milestones v0.1.0
plugins/Milestones/Milestones.dll
Decompiled 2 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Milestones.Core; using Milestones.Core.Model; using Milestones.UI; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("Milestones")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Real progress bars for Valheim's achievements, a pinned tracker and progress toasts.")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+dfa0aff01eeb973e2b7a80fc4221d5803de46124")] [assembly: AssemblyProduct("Milestones")] [assembly: AssemblyTitle("Milestones")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] [module: UnverifiableCode] [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; } } } internal sealed class ConfigurationManagerAttributes { public int? Order; public bool? IsAdvanced; public bool? Browsable; public bool? ReadOnly; } namespace Milestones { [BepInPlugin("com.jumpingmushroom.milestones", "Milestones", "0.1.0")] [BepInProcess("valheim.exe")] [BepInProcess("valheim.x86_64")] public sealed class MilestonesPlugin : BaseUnityPlugin { public const string PluginGuid = "com.jumpingmushroom.milestones"; public const string PluginName = "Milestones"; public const string PluginVersion = "0.1.0"; internal static ManualLogSource Log; private static readonly HashSet<string> Warned = new HashSet<string>(); private Harmony _harmony; private void Awake() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; PluginConfig.Bind(((BaseUnityPlugin)this).Config); ConsoleCommands.Register(); Pins.Init(); PinButton.Init(); ListMarks.Init(); TrackerHud.Init(); Toasts.Init(); _harmony = new Harmony("com.jumpingmushroom.milestones"); _harmony.PatchAll(typeof(MilestonesPlugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Milestones 0.1.0 loaded."); } private void Update() { Runtime.Tick(); } private void OnDestroy() { if (_harmony != null) { _harmony.UnpatchSelf(); } } internal static void WarnOnce(string key, Exception e) { if (Warned.Add(key)) { Log.LogWarning((object)(key + ": " + e)); } } } public enum TrackerAnchor { UnderStatusEffects, TopLeft, TopRight, LeftMiddle, RightMiddle, BottomLeft, BottomRight } public enum ToastPosition { TopLeft, Center } public static class PluginConfig { public static ConfigEntry<bool> Enabled; public static ConfigEntry<OverallMode> Overall; public static ConfigEntry<bool> SortObjectives; public static ConfigEntry<bool> HideUnmetNames; public static ConfigEntry<bool> ShowTracker; public static ConfigEntry<TrackerAnchor> Anchor; public static ConfigEntry<float> OffsetX; public static ConfigEntry<float> OffsetY; public static ConfigEntry<float> Scale; public static ConfigEntry<float> Opacity; public static ConfigEntry<float> Width; public static ConfigEntry<int> MaxRowsPerAchievement; public static ConfigEntry<bool> HideWhenInventoryOpen; public static ConfigEntry<bool> AutoUnpinCompleted; public static ConfigEntry<PinnedToastMode> PinnedToasts; public static ConfigEntry<UnpinnedToastMode> UnpinnedToasts; public static ConfigEntry<string> Thresholds; public static ConfigEntry<ToastPosition> ToastAt; public static ConfigEntry<Color> ColorNotStarted; public static ConfigEntry<Color> ColorInProgress; public static ConfigEntry<Color> ColorDone; public static ConfigEntry<bool> Verbose; private static ConfigurationManagerAttributes Attr(int order, bool advanced = false) { return new ConfigurationManagerAttributes { Order = order, IsAdvanced = advanced }; } private static Color Hex(string hex) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) Color result = default(Color); ColorUtility.TryParseHtmlString(hex, ref result); return result; } public static void Bind(ConfigFile cfg) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Expected O, but got Unknown //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Expected O, but got Unknown //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Expected O, but got Unknown //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Expected O, but got Unknown //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Expected O, but got Unknown //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Expected O, but got Unknown //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Expected O, but got Unknown //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Expected O, but got Unknown //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Expected O, but got Unknown //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Expected O, but got Unknown //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Expected O, but got Unknown //IL_03a8: Unknown result type (might be due to invalid IL or missing references) //IL_03b2: Expected O, but got Unknown //IL_03da: Unknown result type (might be due to invalid IL or missing references) //IL_03e4: Expected O, but got Unknown //IL_03f9: Unknown result type (might be due to invalid IL or missing references) //IL_0415: Unknown result type (might be due to invalid IL or missing references) //IL_041f: Expected O, but got Unknown //IL_0434: Unknown result type (might be due to invalid IL or missing references) //IL_0450: Unknown result type (might be due to invalid IL or missing references) //IL_045a: Expected O, but got Unknown //IL_046f: Unknown result type (might be due to invalid IL or missing references) //IL_048b: Unknown result type (might be due to invalid IL or missing references) //IL_0495: Expected O, but got Unknown //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_04c6: Expected O, but got Unknown Enabled = cfg.Bind<bool>("General", "Enabled", true, new ConfigDescription("Master switch. Off restores the vanilla details panel and hides the tracker and toasts.", (AcceptableValueBase)null, new object[1] { Attr(100) })); Overall = cfg.Bind<OverallMode>("General", "OverallMode", OverallMode.Auto, new ConfigDescription("How the overall bar is measured. Count: objectives met out of all (37 / 212). Average: mean fill of every objective. Auto: Count when every objective is 'do this once' (eat every food, kill every creature), Average otherwise.", (AcceptableValueBase)null, new object[1] { Attr(95) })); SortObjectives = cfg.Bind<bool>("General", "SortObjectives", true, new ConfigDescription("Unfinished objectives first, closest to done at the top. Off keeps the game's order.", (AcceptableValueBase)null, new object[1] { Attr(90) })); HideUnmetNames = cfg.Bind<bool>("General", "HideUnmetNames", false, new ConfigDescription("Spoiler guard: unmet objectives keep the game's ??? name but still show their bar and numbers. Useful for Kill every creature and Find every trophy on a first run.", (AcceptableValueBase)null, new object[1] { Attr(85) })); ShowTracker = cfg.Bind<bool>("Tracker", "ShowTracker", true, new ConfigDescription("Show pinned achievements on the HUD.", (AcceptableValueBase)null, new object[1] { Attr(80) })); Anchor = cfg.Bind<TrackerAnchor>("Tracker", "Anchor", TrackerAnchor.UnderStatusEffects, new ConfigDescription("Where the tracker sits. UnderStatusEffects follows the status-effect icons beside the minimap and moves down when they wrap into a second row.", (AcceptableValueBase)null, new object[1] { Attr(78) })); OffsetX = cfg.Bind<float>("Tracker", "OffsetX", 0f, new ConfigDescription("Horizontal nudge in HUD pixels (positive is right).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1000f, 1000f), new object[1] { Attr(76) })); OffsetY = cfg.Bind<float>("Tracker", "OffsetY", 0f, new ConfigDescription("Vertical nudge in HUD pixels (positive is up).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1000f, 1000f), new object[1] { Attr(75) })); Scale = cfg.Bind<float>("Tracker", "Scale", 1f, new ConfigDescription("Size of the tracker.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), new object[1] { Attr(74) })); Opacity = cfg.Bind<float>("Tracker", "Opacity", 0.9f, new ConfigDescription("Opacity of the whole tracker.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), new object[1] { Attr(73) })); Width = cfg.Bind<float>("Tracker", "Width", 260f, new ConfigDescription("Width in HUD pixels before scaling.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(160f, 500f), new object[1] { Attr(72) })); MaxRowsPerAchievement = cfg.Bind<int>("Tracker", "MaxRowsPerAchievement", 4, new ConfigDescription("Objective rows per pinned achievement. Larger ones show the unfinished objectives closest to done, then '+N more'.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), new object[1] { Attr(70) })); HideWhenInventoryOpen = cfg.Bind<bool>("Tracker", "HideWhenInventoryOpen", true, new ConfigDescription("Hide the tracker while the inventory or achievements screen is open.", (AcceptableValueBase)null, new object[1] { Attr(68) })); AutoUnpinCompleted = cfg.Bind<bool>("Tracker", "AutoUnpinCompleted", true, new ConfigDescription("Unpin an achievement 10 seconds after it unlocks. Off keeps it pinned, showing Done.", (AcceptableValueBase)null, new object[1] { Attr(66) })); PinnedToasts = cfg.Bind<PinnedToastMode>("Toasts", "PinnedToasts", PinnedToastMode.ObjectivesAndThresholds, new ConfigDescription("Toasts for pinned achievements.", (AcceptableValueBase)null, new object[1] { Attr(60) })); UnpinnedToasts = cfg.Bind<UnpinnedToastMode>("Toasts", "UnpinnedToasts", UnpinnedToastMode.ThresholdsOnly, new ConfigDescription("Toasts for every other achievement.", (AcceptableValueBase)null, new object[1] { Attr(58) })); Thresholds = cfg.Bind<string>("Toasts", "Thresholds", "25,50,75", new ConfigDescription("Overall percentages that trigger a toast, comma-separated, 1-99.", (AcceptableValueBase)null, new object[1] { Attr(56) })); ToastAt = cfg.Bind<ToastPosition>("Toasts", "ToastPosition", ToastPosition.TopLeft, new ConfigDescription("TopLeft uses the game's pickup-message feed; Center the big centre message.", (AcceptableValueBase)null, new object[1] { Attr(54) })); ColorNotStarted = cfg.Bind<Color>("Colors", "NotStarted", Hex("#7a7a7a"), new ConfigDescription("Bar colour for an objective with no progress.", (AcceptableValueBase)null, new object[1] { Attr(40) })); ColorInProgress = cfg.Bind<Color>("Colors", "InProgress", Hex("#e0a030"), new ConfigDescription("Bar colour for an objective under way.", (AcceptableValueBase)null, new object[1] { Attr(38) })); ColorDone = cfg.Bind<Color>("Colors", "Done", Hex("#5ac85a"), new ConfigDescription("Bar colour for a met objective.", (AcceptableValueBase)null, new object[1] { Attr(36) })); Verbose = cfg.Bind<bool>("Logging", "Verbose", false, new ConfigDescription("Log recomputes, pin changes and toasts to the BepInEx log.", (AcceptableValueBase)null, new object[1] { Attr(5, advanced: true) })); } } } namespace Milestones.UI { internal sealed class Bar : MonoBehaviour { private const float FullSweepSeconds = 0.3f; private Image _fill; private float _target; private float _shown; public static Bar CreateFloating(RectTransform row, float height, float inset) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_0064: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) Bar bar = Build((Transform)(object)row, "MilestonesBar", new Color(1f, 1f, 1f, 0.12f)); RectTransform val = (RectTransform)((Component)bar).transform; val.anchorMin = new Vector2(0f, 0f); val.anchorMax = new Vector2(1f, 0f); val.pivot = new Vector2(0.5f, 0f); val.anchoredPosition = new Vector2(0f, 1f); val.sizeDelta = new Vector2(-2f * inset, height); ((Component)bar).gameObject.AddComponent<LayoutElement>().ignoreLayout = true; return bar; } public static Bar CreateInLayout(Transform parent, float height) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) Bar bar = Build(parent, "MilestonesBar", new Color(0f, 0f, 0f, 0.55f)); LayoutElement obj = ((Component)bar).gameObject.AddComponent<LayoutElement>(); obj.minHeight = height; obj.preferredHeight = height; obj.flexibleWidth = 1f; return bar; } private static Bar Build(Transform parent, string name, Color track) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) RectTransform val = UiUtil.Rect(name, parent); Image obj = ((Component)val).gameObject.AddComponent<Image>(); obj.sprite = UiUtil.White; ((Graphic)obj).color = track; ((Graphic)obj).raycastTarget = false; RectTransform obj2 = UiUtil.Rect("fill", (Transform)(object)val); UiUtil.Stretch(obj2); Image val2 = ((Component)obj2).gameObject.AddComponent<Image>(); val2.sprite = UiUtil.White; val2.type = (Type)3; val2.fillMethod = (FillMethod)0; val2.fillOrigin = 0; val2.fillAmount = 0f; ((Graphic)val2).raycastTarget = false; Bar bar = ((Component)val).gameObject.AddComponent<Bar>(); bar._fill = val2; return bar; } public void Set(float fraction, Color color, bool ease) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) _target = Mathf.Clamp01(fraction); ((Graphic)_fill).color = color; if (!ease) { _shown = _target; _fill.fillAmount = _shown; } } private void Update() { if (_shown != _target) { _shown = Mathf.MoveTowards(_shown, _target, Time.unscaledDeltaTime / 0.3f); _fill.fillAmount = _shown; } } } internal static class DetailsPanel { private enum RowResult { Added, Stop, Failed } private const float ExtraRowHeight = 8f; private static AchievementsGui _gui; private static GridLayoutGroup _grid; private static Vector2 _vanillaCell; private static ProgressRow _header; private static readonly List<ProgressRow> Rows; public static Achievement Current { get; private set; } public static bool Failed { get; private set; } public static event Action<AchievementsGui, Achievement> Opened; static DetailsPanel() { Rows = new List<ProgressRow>(); ProgressCache.Changed += OnChanged; } public static void Open(AchievementsGui gui, Achievement a) { _gui = gui; Current = a; Rows.Clear(); GrowRows(gui); gui.m_achievementDetails.SetActive(true); ProgressCache.Recompute(a); AchievementProgress achievementProgress = ProgressCache.Get(a); _header = new ProgressRow(NewRow(gui), -1); _header.ShowOverall(a, achievementProgress, ease: false); List<int> list; if (PluginConfig.SortObjectives.Value) { list = ObjectiveOrder.Sorted(achievementProgress); } else { list = new List<int>(achievementProgress.Total); for (int i = 0; i < achievementProgress.Total; i++) { list.Add(i); } } ((MonoBehaviour)gui).StartCoroutine(Populate(gui, a, list)); if (DetailsPanel.Opened != null) { DetailsPanel.Opened(gui, a); } } private static IEnumerator Populate(AchievementsGui gui, Achievement a, List<int> order) { int batch = Math.Max(1, gui.m_detailStatsPerFrame); int n = 0; foreach (int item in order) { switch (AddRow(gui, a, item)) { case RowResult.Failed: Fail(gui, a); yield break; case RowResult.Stop: yield break; } int num = n + 1; n = num; if (num == batch) { n = 0; yield return null; } } } private static RowResult AddRow(AchievementsGui gui, Achievement a, int i) { if ((Object)(object)Current != (Object)(object)a || (Object)(object)gui == (Object)null || !gui.m_achievementDetails.activeSelf) { return RowResult.Stop; } try { AchievementProgress achievementProgress = ProgressCache.Get(a); if (i >= achievementProgress.Total) { return RowResult.Stop; } ProgressRow progressRow = new ProgressRow(NewRow(gui), i); progressRow.Show(achievementProgress.Objectives[i], ease: false); Rows.Add(progressRow); return RowResult.Added; } catch (Exception e) { MilestonesPlugin.WarnOnce("details panel", e); return RowResult.Failed; } } private static void Fail(AchievementsGui gui, Achievement a) { MarkFailed(); Abort(gui); gui.OnOpenAchievementDetails(a, true); } public static void MarkFailed() { Failed = true; } private static void GrowRows(AchievementsGui gui) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) GridLayoutGroup component = ((Component)gui.m_achievementDetailsListRoot).GetComponent<GridLayoutGroup>(); if (!((Object)(object)component == (Object)null)) { if ((Object)(object)component != (Object)(object)_grid) { _grid = component; _vanillaCell = component.cellSize; } component.cellSize = new Vector2(_vanillaCell.x, _vanillaCell.y + 8f); } } private static void RestoreRows() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_grid != (Object)null) { _grid.cellSize = _vanillaCell; } } private static AchievementDetailUnlockCondition NewRow(AchievementsGui gui) { AchievementDetailUnlockCondition obj = Object.Instantiate<AchievementDetailUnlockCondition>(gui.m_achievementDetailsElementPrefab, (Transform)(object)gui.m_achievementDetailsListRoot); ((Component)obj).gameObject.SetActive(true); return obj; } private static void OnChanged(Achievement a, AchievementProgress p) { if ((Object)(object)a != (Object)(object)Current || (Object)(object)_gui == (Object)null || !_gui.m_achievementDetails.activeSelf) { return; } if (_header != null && _header.Alive) { _header.ShowOverall(a, p, ease: true); } foreach (ProgressRow row in Rows) { if (row.Alive && row.ObjectiveIndex < p.Total) { row.Show(p.Objectives[row.ObjectiveIndex], ease: true); } } } public static void Closed() { Current = null; _header = null; Rows.Clear(); RestoreRows(); PinButton.Hide(); } public static void Abort(AchievementsGui gui) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) Current = null; foreach (Transform item in (Transform)gui.m_achievementDetailsListRoot) { Object.Destroy((Object)(object)((Component)item).gameObject); } gui.m_achievementDetails.SetActive(false); _header = null; Rows.Clear(); RestoreRows(); PinButton.Hide(); } } internal static class ListMarks { private const string MarkName = "MilestonesPinMark"; public static void Init() { Pins.Changed += delegate { InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance != (Object)null && instance.IsAchievementsPanelOpen) { Apply(instance); } }; } public static void Apply(InventoryGui inv) { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) List<GameObject> achievementsList = inv.m_achievementsPanel.m_achievementsList; List<Achievement> list = AchievementReader.GridOrder(); if (list.Count != achievementsList.Count) { return; } Vector2 val3 = default(Vector2); for (int i = 0; i < achievementsList.Count; i++) { if (!((Object)(object)achievementsList[i] == (Object)null)) { Transform val = achievementsList[i].transform.Find("icon") ?? achievementsList[i].transform; Transform val2 = val.Find("MilestonesPinMark"); bool flag = Pins.Contains(list[i].m_id); if (flag && (Object)(object)val2 == (Object)null) { RectTransform obj = UiUtil.Rect("MilestonesPinMark", val); ((Vector2)(ref val3))..ctor(1f, 1f); obj.anchorMax = val3; obj.anchorMin = val3; obj.pivot = new Vector2(0.5f, 0.5f); obj.anchoredPosition = new Vector2(-6f, -6f); obj.sizeDelta = new Vector2(14f, 14f); Image obj2 = ((Component)obj).gameObject.AddComponent<Image>(); obj2.sprite = UiUtil.White; ((Graphic)obj2).color = PluginConfig.ColorInProgress.Value; ((Graphic)obj2).raycastTarget = false; } else if (!flag && (Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)((Component)val2).gameObject); } } } } } internal static class PinButton { [CompilerGenerated] private static class <>O { public static Action<AchievementsGui, Achievement> <0>__Attach; public static Action <1>__Refresh; public static Action <2>__PollGamepad; public static UnityAction <3>__OnClick; } private static Button _button; private static TMP_Text _label; private static Achievement _for; public static void Init() { DetailsPanel.Opened += Attach; Pins.Changed += Refresh; Runtime.Ticked += PollGamepad; } private static void Attach(AchievementsGui gui, Achievement a) { _for = a; if ((Object)(object)_button == (Object)null) { Create(gui); } if ((Object)(object)_button != (Object)null) { ((Component)_button).gameObject.SetActive(true); } Refresh(); } internal static void Hide() { if ((Object)(object)_button != (Object)null) { ((Component)_button).gameObject.SetActive(false); } } private static Button FindCloseButton(AchievementsGui gui) { Button val = null; Button[] componentsInChildren = gui.m_achievementDetails.GetComponentsInChildren<Button>(true); foreach (Button val2 in componentsInChildren) { if (((Object)val2).name == "MilestonesPin") { continue; } if ((Object)(object)val == (Object)null) { val = val2; } for (int j = 0; j < ((UnityEventBase)val2.onClick).GetPersistentEventCount(); j++) { if (((UnityEventBase)val2.onClick).GetPersistentMethodName(j) == "OnCloseAchievementDetails") { return val2; } } } return val; } private static void Create(AchievementsGui gui) { //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Expected O, but got Unknown //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Expected O, but got Unknown Button val = FindCloseButton(gui); if ((Object)(object)val == (Object)null) { MilestonesPlugin.Log.LogWarning((object)"Milestones: no button in the details panel to clone; pin with 'milestones pin <id>'."); return; } GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)val).transform.parent); ((Object)val2).name = "MilestonesPin"; Component[] componentsInChildren = val2.GetComponentsInChildren<Component>(true); foreach (Component val3 in componentsInChildren) { if (!((Object)(object)val3 == (Object)null)) { if (((object)val3).GetType().Name == "UIInputHint") { Object.Destroy((Object)(object)val3.gameObject); } else if (val3 is UIGamePad || ((object)val3).GetType().Name == "Localize") { Object.Destroy((Object)(object)val3); } } } _button = val2.GetComponent<Button>(); _button.onClick = new ButtonClickedEvent(); ButtonClickedEvent onClick = _button.onClick; object obj = <>O.<3>__OnClick; if (obj == null) { UnityAction val4 = OnClick; <>O.<3>__OnClick = val4; obj = (object)val4; } ((UnityEvent)onClick).AddListener((UnityAction)obj); _label = val2.GetComponentInChildren<TMP_Text>(true); RectTransform val5 = (RectTransform)val2.transform; RectTransform val6 = (RectTransform)((Component)val).transform; Vector2 anchoredPosition = val6.anchoredPosition; Rect rect = val6.rect; val5.anchoredPosition = anchoredPosition - new Vector2(((Rect)(ref rect)).width + 12f, 0f); } private static void OnClick() { if ((Object)(object)_for != (Object)null && (Object)(object)_for == (Object)(object)DetailsPanel.Current) { Pins.Toggle(_for); } } private static void Refresh() { if (!((Object)(object)_button == (Object)null) && !((Object)(object)_for == (Object)null) && !((Object)(object)_label == (Object)null)) { bool flag = Pins.Contains(_for.m_id); _label.text = (flag ? "Unpin" : (Pins.IsFull ? "Unpin one first (3/3)" : ("Pin (" + Pins.Count + "/" + 3 + ")"))); ((Selectable)_button).interactable = flag || !Pins.IsFull; } } private static void PollGamepad() { if (!((Object)(object)DetailsPanel.Current == (Object)null) && !((Object)(object)_for != (Object)(object)DetailsPanel.Current) && ZInput.IsGamepadActive() && ZInput.GetButtonDown("JoyButtonX") && (Object)(object)_button != (Object)null && ((Selectable)_button).interactable) { OnClick(); } } } internal sealed class ProgressRow { public const int Header = -1; public readonly AchievementDetailUnlockCondition Row; public readonly int ObjectiveIndex; private readonly Bar _bar; public bool Alive => (Object)(object)Row != (Object)null; public ProgressRow(AchievementDetailUnlockCondition row, int objectiveIndex) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown Row = row; ObjectiveIndex = objectiveIndex; _bar = Bar.CreateFloating((RectTransform)((Component)row).transform, (objectiveIndex == -1) ? 6f : 4f, 4f); } public void Show(Objective o, bool ease) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) bool flag = PluginConfig.HideUnmetNames.Value && !o.Met; ((TMP_Text)Row.StatName).text = (flag ? "???" : o.Label); ((TMP_Text)Row.Progress).text = Labels.ProgressText(o); Color color = UiUtil.TextColor(o.Met); ((Graphic)Row.StatName).color = color; ((Graphic)Row.Progress).color = color; _bar.Set(o.Fraction, UiUtil.BarColor(o), ease); } public void ShowOverall(Achievement a, AchievementProgress p, bool ease) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) ((TMP_Text)Row.StatName).text = AchievementReader.Name(a); ((TMP_Text)Row.Progress).text = (p.ShowAsCount ? (p.MetCount + " / " + p.Total + " objectives") : Labels.Percent(p.Overall)); Color color = UiUtil.TextColor(p.Unlocked); ((Graphic)Row.StatName).color = color; ((Graphic)Row.Progress).color = color; _bar.Set(p.Overall, UiUtil.BarColor(p.Overall, p.Unlocked), ease); } } internal static class Toasts { private static readonly Dictionary<string, Snapshot> Seen = new Dictionary<string, Snapshot>(); private static ToastRules _rules; private static ToastRules Rules { get { if (_rules == null) { _rules = new ToastRules { Pinned = PluginConfig.PinnedToasts.Value, Unpinned = PluginConfig.UnpinnedToasts.Value, Thresholds = ToastRules.ParseThresholds(PluginConfig.Thresholds.Value) }; } return _rules; } } public static void Init() { Runtime.PlayerSpawned += delegate { Reset(); }; ProgressCache.Changed += OnChanged; PluginConfig.Thresholds.SettingChanged += delegate { _rules = null; }; PluginConfig.PinnedToasts.SettingChanged += delegate { _rules = null; }; PluginConfig.UnpinnedToasts.SettingChanged += delegate { _rules = null; }; PluginConfig.Overall.SettingChanged += delegate { ProgressCache.Clear(); Reset(); }; } private static void Reset() { Seen.Clear(); foreach (Achievement item in AchievementReader.All()) { AchievementProgress achievementProgress = ProgressCache.Get(item); if (achievementProgress != null) { Seen[item.m_id] = Snapshot.Take(achievementProgress); } } } private static void OnChanged(Achievement a, AchievementProgress now) { //IL_0079: 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) Seen.TryGetValue(a.m_id, out var value); Seen[a.m_id] = Snapshot.Take(now); if (value == null || !PluginConfig.Enabled.Value) { return; } string text = ToastDiff.Diff(value, now, AchievementReader.Name(a), Pins.Contains(a.m_id), Rules); if (text != null && !((Object)(object)MessageHud.instance == (Object)null)) { MessageType val = (MessageType)((PluginConfig.ToastAt.Value != ToastPosition.Center) ? 1 : 2); MessageHud.instance.ShowMessage(val, text, 0, (Sprite)null, false, true); if (PluginConfig.Verbose.Value) { MilestonesPlugin.Log.LogInfo((object)("Milestones: toast: " + text)); } } } } internal sealed class TrackerHud : MonoBehaviour { private sealed class LineView { public RectTransform Root; public TextMeshProUGUI Name; public TextMeshProUGUI Value; public Bar Bar; public int ObjectiveIndex = -1; } private sealed class BlockView { public RectTransform Root; public Image Icon; public TextMeshProUGUI Title; public TextMeshProUGUI Overall; public Bar OverallBar; public readonly List<LineView> Lines = new List<LineView>(); public TextMeshProUGUI More; } private const float StatusGap = 26f; private static TrackerHud _instance; private static bool _dirty = true; private RectTransform _panel; private CanvasGroup _group; private Canvas _canvas; private readonly Dictionary<string, BlockView> _blocks = new Dictionary<string, BlockView>(); private TextMeshProUGUI _paused; private float _nextPausedCheck; private readonly Vector3[] _corners = (Vector3[])(object)new Vector3[4]; public static void Init() { Runtime.Ticked += Ensure; Pins.Changed += delegate { _dirty = true; }; ProgressCache.Changed += delegate(Achievement a, AchievementProgress p) { if (Pins.Contains(a.m_id)) { _dirty = true; } }; Runtime.PlayerSpawned += delegate { _dirty = true; }; PluginConfig.MaxRowsPerAchievement.SettingChanged += delegate { Rebuild(); }; } private static void Rebuild() { if ((Object)(object)_instance != (Object)null) { foreach (BlockView value in _instance._blocks.Values) { Object.Destroy((Object)(object)((Component)value.Root).gameObject); } _instance._blocks.Clear(); } _dirty = true; } private static void Ensure() { if ((Object)(object)_instance != (Object)null) { return; } Hud instance = Hud.instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.m_rootObject == (Object)null)) { RectTransform val = UiUtil.Rect("MilestonesTracker", instance.m_rootObject.transform); UiUtil.Stretch(val); TrackerHud trackerHud = ((Component)val).gameObject.AddComponent<TrackerHud>(); try { trackerHud.Build(); } catch (Exception e) { MilestonesPlugin.WarnOnce("tracker", e); Object.Destroy((Object)(object)((Component)val).gameObject); return; } _instance = trackerHud; _dirty = true; } } private void Build() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_013a: Unknown result type (might be due to invalid IL or missing references) _panel = UiUtil.Rect("panel", ((Component)this).transform); _panel.pivot = new Vector2(1f, 1f); Image obj = ((Component)_panel).gameObject.AddComponent<Image>(); obj.sprite = UiUtil.White; ((Graphic)obj).color = new Color(0f, 0f, 0f, 0.6f); ((Graphic)obj).raycastTarget = false; _group = ((Component)_panel).gameObject.AddComponent<CanvasGroup>(); _group.interactable = false; _group.blocksRaycasts = false; VerticalLayoutGroup obj2 = ((Component)_panel).gameObject.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)obj2).padding = new RectOffset(8, 8, 6, 6); ((HorizontalOrVerticalLayoutGroup)obj2).spacing = 6f; ((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false; ContentSizeFitter obj3 = ((Component)_panel).gameObject.AddComponent<ContentSizeFitter>(); obj3.verticalFit = (FitMode)2; obj3.horizontalFit = (FitMode)0; _paused = UiUtil.Text((Transform)(object)_panel, "paused", 13f, (TextAlignmentOptions)513); ((Graphic)_paused).color = new Color(0.7f, 0.7f, 0.7f, 0.8f); ((Component)_paused).gameObject.SetActive(false); _canvas = ((Component)this).GetComponentInParent<Canvas>(); } private void LateUpdate() { //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) try { bool flag = PluginConfig.Enabled.Value && PluginConfig.ShowTracker.Value && Pins.Count > 0 && (Object)(object)Player.m_localPlayer != (Object)null && (!PluginConfig.HideWhenInventoryOpen.Value || !InventoryGui.IsVisible()); if (((Component)_panel).gameObject.activeSelf != flag) { ((Component)_panel).gameObject.SetActive(flag); } if (!flag) { return; } if (_dirty) { _dirty = false; Refresh(); } if (Runtime.Now >= _nextPausedCheck) { _nextPausedCheck = Runtime.Now + 1f; string text = CheatState.PausedReason(); ((Component)_paused).gameObject.SetActive(text != null); if (text != null) { ((TMP_Text)_paused).text = "Achievements paused: " + text; } } _group.alpha = PluginConfig.Opacity.Value; _panel.sizeDelta = new Vector2(PluginConfig.Width.Value, _panel.sizeDelta.y); ((Transform)_panel).localScale = Vector3.one * PluginConfig.Scale.Value; Place(); } catch (Exception e) { MilestonesPlugin.WarnOnce("tracker", e); } } private void Place() { //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_029b: 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_0124: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) TrackerAnchor value = PluginConfig.Anchor.Value; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(PluginConfig.OffsetX.Value, PluginConfig.OffsetY.Value); Vector2 val3 = default(Vector2); Vector2 val2 = default(Vector2); switch (value) { case TrackerAnchor.UnderStatusEffects: { Hud instance = Hud.instance; float num = (((Object)(object)_canvas != (Object)null) ? _canvas.rootCanvas.scaleFactor : 1f); RectTransform statusEffectListRoot = instance.m_statusEffectListRoot; float num2 = ((Transform)statusEffectListRoot).position.x; float num3 = ((Transform)statusEffectListRoot).position.y; foreach (RectTransform statusEffect in instance.m_statusEffects) { if (!((Object)(object)statusEffect == (Object)null) && ((Component)statusEffect).gameObject.activeSelf) { statusEffect.GetWorldCorners(_corners); num2 = Mathf.Max(num2, _corners[2].x); num3 = Mathf.Min(num3, _corners[0].y); } } RectTransform panel = _panel; RectTransform panel2 = _panel; ((Vector2)(ref val3))..ctor(0.5f, 0.5f); panel2.anchorMax = val3; panel.anchorMin = val3; _panel.pivot = new Vector2(1f, 1f); ((Transform)_panel).position = new Vector3(num2 + val.x * num, num3 - 26f * num + val.y * num, 0f); return; } case TrackerAnchor.TopLeft: ((Vector2)(ref val2))..ctor(0f, 1f); break; case TrackerAnchor.TopRight: ((Vector2)(ref val2))..ctor(1f, 1f); break; case TrackerAnchor.LeftMiddle: ((Vector2)(ref val2))..ctor(0f, 0.5f); break; case TrackerAnchor.RightMiddle: ((Vector2)(ref val2))..ctor(1f, 0.5f); break; case TrackerAnchor.BottomLeft: ((Vector2)(ref val2))..ctor(0f, 0f); break; default: ((Vector2)(ref val2))..ctor(1f, 0f); break; } val3 = (_panel.anchorMin = (_panel.anchorMax = val2)); _panel.pivot = val2; Vector2 val6 = default(Vector2); ((Vector2)(ref val6))..ctor((val2.x < 0.5f) ? 16f : ((val2.x > 0.5f) ? (-16f) : 0f), (val2.y < 0.5f) ? 16f : ((val2.y > 0.5f) ? (-16f) : 0f)); _panel.anchoredPosition = val6 + val; } private void Refresh() { HashSet<string> hashSet = new HashSet<string>(Pins.Ids); List<string> list = new List<string>(); foreach (string key in _blocks.Keys) { if (!hashSet.Contains(key)) { list.Add(key); } } foreach (string item in list) { Object.Destroy((Object)(object)((Component)_blocks[item].Root).gameObject); _blocks.Remove(item); } int num = 0; foreach (string id in Pins.Ids) { Achievement val = AchievementReader.ById(id); if ((Object)(object)val == (Object)null) { continue; } AchievementProgress achievementProgress = ProgressCache.Get(val); if (achievementProgress != null) { BlockView value; bool flag = !_blocks.TryGetValue(id, out value); if (flag) { value = NewBlock(val); _blocks[id] = value; } ((Transform)value.Root).SetSiblingIndex(num++); Fill(value, val, achievementProgress, !flag); } } ((TMP_Text)_paused).transform.SetAsLastSibling(); } private BlockView NewBlock(Achievement a) { //IL_01de: Unknown result type (might be due to invalid IL or missing references) BlockView blockView = new BlockView(); blockView.Root = UiUtil.Rect("block_" + a.m_id, (Transform)(object)_panel); VerticalLayoutGroup obj = ((Component)blockView.Root).gameObject.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = 2f; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; RectTransform val = UiUtil.Rect("head", (Transform)(object)blockView.Root); HorizontalLayoutGroup obj2 = ((Component)val).gameObject.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj2).spacing = 6f; ((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false; ((LayoutGroup)obj2).childAlignment = (TextAnchor)3; RectTransform val2 = UiUtil.Rect("icon", (Transform)(object)val); blockView.Icon = ((Component)val2).gameObject.AddComponent<Image>(); ((Graphic)blockView.Icon).raycastTarget = false; blockView.Icon.preserveAspect = true; LayoutElement obj3 = ((Component)val2).gameObject.AddComponent<LayoutElement>(); float preferredWidth = (obj3.minWidth = 20f); obj3.preferredWidth = preferredWidth; preferredWidth = (obj3.minHeight = 20f); obj3.preferredHeight = preferredWidth; blockView.Title = UiUtil.Text((Transform)(object)val, "title", 16f, (TextAlignmentOptions)513); ((Component)blockView.Title).gameObject.AddComponent<LayoutElement>().flexibleWidth = 1f; blockView.Overall = UiUtil.Text((Transform)(object)val, "overall", 14f, (TextAlignmentOptions)516); blockView.OverallBar = Bar.CreateInLayout((Transform)(object)blockView.Root, 6f); for (int i = 0; i < PluginConfig.MaxRowsPerAchievement.Value; i++) { blockView.Lines.Add(NewLine(blockView.Root, i)); } blockView.More = UiUtil.Text((Transform)(object)blockView.Root, "more", 12f, (TextAlignmentOptions)513); ((Graphic)blockView.More).color = new Color(0.7f, 0.7f, 0.7f, 1f); return blockView; } private static LineView NewLine(RectTransform parent, int i) { LineView lineView = new LineView(); lineView.Root = UiUtil.Rect("line" + i, (Transform)(object)parent); VerticalLayoutGroup obj = ((Component)lineView.Root).gameObject.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = 1f; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; RectTransform val = UiUtil.Rect("text", (Transform)(object)lineView.Root); HorizontalLayoutGroup obj2 = ((Component)val).gameObject.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false; lineView.Name = UiUtil.Text((Transform)(object)val, "name", 13f, (TextAlignmentOptions)513); ((Component)lineView.Name).gameObject.AddComponent<LayoutElement>().flexibleWidth = 1f; lineView.Value = UiUtil.Text((Transform)(object)val, "value", 13f, (TextAlignmentOptions)516); lineView.Bar = Bar.CreateInLayout((Transform)(object)lineView.Root, 3f); return lineView; } private static void Fill(BlockView b, Achievement a, AchievementProgress p, bool ease) { //IL_005e: 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_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: 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) b.Icon.sprite = (p.Unlocked ? a.m_icon : a.m_iconLocked); ((TMP_Text)b.Title).text = AchievementReader.Name(a); ((TMP_Text)b.Overall).text = (p.Unlocked ? "Done ✓" : Labels.OverallText(p)); ((Graphic)b.Overall).color = UiUtil.TextColor(p.Unlocked); b.OverallBar.Set(p.Overall, UiUtil.BarColor(p.Overall, p.Unlocked), ease); TrackerRows trackerRows = (p.Unlocked ? new TrackerRows() : ObjectiveOrder.Select(p, b.Lines.Count)); for (int i = 0; i < b.Lines.Count; i++) { LineView lineView = b.Lines[i]; bool flag = i < trackerRows.Indices.Count; ((Component)lineView.Root).gameObject.SetActive(flag); if (!flag) { lineView.ObjectiveIndex = -1; continue; } int num = trackerRows.Indices[i]; Objective objective = p.Objectives[num]; ((TMP_Text)lineView.Name).text = ((PluginConfig.HideUnmetNames.Value && !objective.Met) ? "???" : objective.Label); ((TMP_Text)lineView.Value).text = (objective.HasBar ? (Labels.Amount(Math.Min(objective.Current, objective.Target)) + " / " + Labels.Amount(objective.Target)) : (objective.Met ? "met" : "not met")); Color color = UiUtil.TextColor(objective.Met); ((Graphic)lineView.Name).color = color; ((Graphic)lineView.Value).color = color; lineView.Bar.Set(objective.Fraction, UiUtil.BarColor(objective), ease && lineView.ObjectiveIndex == num); lineView.ObjectiveIndex = num; } ((Component)b.More).gameObject.SetActive(trackerRows.More > 0); ((TMP_Text)b.More).text = "+" + trackerRows.More + " more"; } } internal static class UiUtil { private static Sprite _white; private static Material _outlined; private static TMP_FontAsset _outlinedFor; public static Sprite White { get { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_white != (Object)null) { return _white; } Texture2D val = new Texture2D(4, 4, (TextureFormat)4, false); Color32[] array = (Color32[])(object)new Color32[16]; for (int i = 0; i < array.Length; i++) { array[i] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue); } val.SetPixels32(array); val.Apply(); ((Object)val).hideFlags = (HideFlags)61; _white = Sprite.Create(val, new Rect(0f, 0f, 4f, 4f), new Vector2(0.5f, 0.5f), 4f); ((Object)_white).hideFlags = (HideFlags)61; return _white; } } public static TMP_FontAsset Font { get { Hud instance = Hud.instance; if (!((Object)(object)instance != (Object)null) || !((Object)(object)instance.m_healthText != (Object)null)) { return null; } return instance.m_healthText.font; } } public static RectTransform Rect(string name, Transform parent) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown RectTransform val = (RectTransform)new GameObject(name, new Type[1] { typeof(RectTransform) }) { layer = ((Component)parent).gameObject.layer }.transform; ((Transform)val).SetParent(parent, false); return val; } public static void Stretch(RectTransform rt) { //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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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) rt.anchorMin = Vector2.zero; rt.anchorMax = Vector2.one; rt.offsetMin = Vector2.zero; rt.offsetMax = Vector2.zero; ((Transform)rt).localScale = Vector3.one; } private static Material Outlined(TMP_FontAsset font) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_outlined != (Object)null && (Object)(object)_outlinedFor == (Object)(object)font) { return _outlined; } _outlined = new Material(((TMP_Asset)font).material); _outlined.EnableKeyword(ShaderUtilities.Keyword_Outline); _outlined.SetFloat(ShaderUtilities.ID_OutlineWidth, 0.25f); _outlined.SetColor(ShaderUtilities.ID_OutlineColor, new Color(0f, 0f, 0f, 1f)); ((Object)_outlined).hideFlags = (HideFlags)61; _outlinedFor = font; return _outlined; } public static TextMeshProUGUI Text(Transform parent, string name, float size, TextAlignmentOptions align) { //IL_0054: 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) RectTransform obj = Rect(name, parent); ((Component)obj).gameObject.SetActive(false); TextMeshProUGUI val = ((Component)obj).gameObject.AddComponent<TextMeshProUGUI>(); TMP_FontAsset font = Font; if ((Object)(object)font != (Object)null) { ((TMP_Text)val).font = font; ((TMP_Text)val).fontSharedMaterial = Outlined(font); } ((Component)obj).gameObject.SetActive(true); ((TMP_Text)val).fontSize = size; ((TMP_Text)val).alignment = align; ((TMP_Text)val).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)val).overflowMode = (TextOverflowModes)1; ((Graphic)val).raycastTarget = false; ((Graphic)val).color = new Color(0.9f, 0.9f, 0.9f, 1f); return val; } public static Color BarColor(Objective o) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (!o.Met) { if (!o.Started) { return PluginConfig.ColorNotStarted.Value; } return PluginConfig.ColorInProgress.Value; } return PluginConfig.ColorDone.Value; } public static Color BarColor(float fraction, bool done) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (!done) { if (!(fraction > 0f)) { return PluginConfig.ColorNotStarted.Value; } return PluginConfig.ColorInProgress.Value; } return PluginConfig.ColorDone.Value; } public static Color TextColor(bool done) { //IL_0022: 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) if (!done) { return new Color(0.85f, 0.85f, 0.85f, 1f); } return PluginConfig.ColorDone.Value; } } } namespace Milestones.Patches { [HarmonyPatch(typeof(AchievementsGui), "OnOpenAchievementDetails")] internal static class OpenDetailsPatch { private static bool Prefix(AchievementsGui __instance, Achievement achievement, bool clickable) { if (!PluginConfig.Enabled.Value) { return true; } if (DetailsPanel.Failed) { return true; } if (__instance.m_achievementDetails.activeSelf || !clickable) { return true; } if (achievement.m_isSecret && !achievement.m_unlocked) { return true; } try { DetailsPanel.Open(__instance, achievement); return false; } catch (Exception e) { MilestonesPlugin.WarnOnce("details panel", e); DetailsPanel.MarkFailed(); DetailsPanel.Abort(__instance); return true; } } } [HarmonyPatch(typeof(AchievementsGui), "CloseDetails")] internal static class CloseDetailsPatch { private static void Postfix() { DetailsPanel.Closed(); } } [HarmonyPatch(typeof(InventoryGui), "UpdateAchievementsList")] internal static class UpdateAchievementsListPatch { private static void Postfix(InventoryGui __instance) { if (!PluginConfig.Enabled.Value) { return; } try { ListMarks.Apply(__instance); } catch (Exception e) { MilestonesPlugin.WarnOnce("grid pin marks", e); } } } [HarmonyPatch(typeof(PlayerProfile), "IncrementStat")] internal static class IncrementStatPatch { private static void Postfix(PlayerStatType stat) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) StatEvents.MarkStat(stat); } } [HarmonyPatch(typeof(PlayerProfile), "SetStat")] internal static class SetStatPatch { private static void Postfix(PlayerStatType stat) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) StatEvents.MarkStat(stat); } } [HarmonyPatch(typeof(PlayerProfile), "IncrementStatEnemy")] internal static class IncrementStatEnemyPatch { private static void Postfix() { StatEvents.Mark(StatKind.Enemy); } } [HarmonyPatch(typeof(PlayerProfile), "IncrementStatItemPickup")] internal static class IncrementStatItemPickupPatch { private static void Postfix() { StatEvents.Mark(StatKind.Pickup); } } [HarmonyPatch(typeof(PlayerProfile), "IncrementStatItemCraft")] internal static class IncrementStatItemCraftPatch { private static void Postfix() { StatEvents.Mark(StatKind.Craft); } } [HarmonyPatch(typeof(PlayerProfile), "IncrementStatPickable")] internal static class IncrementStatPickablePatch { private static void Postfix() { StatEvents.Mark(StatKind.Pickable); } } [HarmonyPatch(typeof(PlayerProfile), "IncrementStatFoodEaten")] internal static class IncrementStatFoodEatenPatch { private static void Postfix() { StatEvents.Mark(StatKind.Food); } } [HarmonyPatch(typeof(PlayerProfile), "IncrementStatBuildPiecePlaced")] internal static class IncrementStatBuildPiecePlacedPatch { private static void Postfix() { StatEvents.Mark(StatKind.Piece); } } [HarmonyPatch(typeof(Achievements), "AchievementEvent")] internal static class AchievementEventPatch { private static void Postfix(Achievement ach) { StatEvents.MarkUnlocked(ach); } } } namespace Milestones.Core { internal static class AchievementReader { private static readonly Dictionary<string, string> LabelCache = new Dictionary<string, string>(); internal static void ClearLabels() { LabelCache.Clear(); } public static IEnumerable<Achievement> All() { Achievements instance = Achievements.m_instance; if ((Object)(object)instance == (Object)null) { yield break; } foreach (AchievementList achievementList in instance.m_achievementLists) { if ((Object)(object)achievementList == (Object)null) { continue; } foreach (Achievement achievement in achievementList.m_achievements) { if ((Object)(object)achievement != (Object)null) { yield return achievement; } } } } public static Achievement ById(string id) { foreach (Achievement item in All()) { if (item.m_id == id) { return item; } } return null; } public static Achievement Find(string query) { foreach (Achievement item in All()) { if (string.Equals(item.m_id, query, StringComparison.OrdinalIgnoreCase)) { return item; } } foreach (Achievement item2 in All()) { if (Name(item2).IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0) { return item2; } } return null; } public static string Name(Achievement a) { return Loc(a.m_name); } public static List<Achievement> GridOrder() { List<List<Achievement>> list = new List<List<Achievement>>(); for (int i = 0; i <= 9; i++) { list.Add(new List<Achievement>()); } foreach (Achievement item in All()) { string text = (((Object)(object)item.m_iconLocked != (Object)null) ? ((Object)item.m_iconLocked).name : ""); if (text.Length >= 2 && int.TryParse(text.Substring(0, 2), out var result) && result >= 0 && result <= 9) { list[result].Add(item); } else { list[9].Add(item); } } List<Achievement> list2 = new List<Achievement>(); for (int j = 1; j <= 9; j++) { list2.AddRange(list[j]); } return list2; } public unsafe static List<ObjectiveInput> Read(Achievement a, PlayerProfile profile) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected I4, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Expected I4, but got Unknown //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0158: 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_0166: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) List<ObjectiveInput> list = new List<ObjectiveInput>(); int num = (int)a.m_difficultyRequirement; if (num < 0 || num >= profile.m_playerStats.Length) { return list; } PlayerStats val = profile.m_playerStats[num]; foreach (PlayerStatRequirement item in a.m_statTrigger) { float value; bool hasValue = val.m_stats.TryGetValue(item.m_stat, out value); PlayerStatType stat = item.m_stat; string text = ((object)(*(PlayerStatType*)(&stat))/*cast due to .constrained prefix*/).ToString(); list.Add(new ObjectiveInput { Source = Source.PlayerStat, Key = text, Label = Label("$stat_" + text, text), Op = Op.AtLeast, Target = item.m_amountAboveEquals, HasValue = hasValue, Value = value }); } foreach (EnemyStatRequirement enemyStatsTrigger in a.m_enemyStatsTriggers) { int num2 = (int)enemyStatsTrigger.m_modifier; if (num2 >= 0 && num2 < val.m_enemyStats.Length) { float value2; bool hasValue2 = val.m_enemyStats[num2].TryGetValue(enemyStatsTrigger.m_stat, out value2); list.Add(new ObjectiveInput { Source = Source.Enemy, Key = enemyStatsTrigger.m_stat, Label = Label(enemyStatsTrigger.m_stat, enemyStatsTrigger.m_stat) + ModifierSuffix(enemyStatsTrigger.m_modifier), Op = Map(enemyStatsTrigger.m_operator), Target = enemyStatsTrigger.m_amount, HasValue = hasValue2, Value = value2 }); } } AddDict(list, a.m_itemPickupTriggers, val.m_itemPickupStats, Source.ItemPickup); AddDict(list, a.m_itemCraftTriggers, val.m_itemCraftStats, Source.ItemCraft); AddDict(list, a.m_foodEatenTriggers, val.m_foodEatenStats, Source.FoodEaten); AddDict(list, a.m_pickableTriggers, val.m_pickableStats, Source.Pickable); AddDict(list, a.m_piecePlacedTriggers, val.m_piecesPlacedStats, Source.PiecePlaced); AddDict(list, a.m_knownWorldTriggers, val.m_knownWorlds, Source.KnownWorld); AddDict(list, a.m_knownWorldKeysTriggers, val.m_knownWorldKeys, Source.KnownWorldKey); AddDict(list, a.m_knownCommandsTriggers, val.m_knownCommands, Source.KnownCommand); foreach (Achievement otherAchievementTrigger in a.m_otherAchievementTriggers) { if (!((Object)(object)otherAchievementTrigger == (Object)null)) { list.Add(new ObjectiveInput { Source = Source.OtherAchievement, Key = otherAchievementTrigger.m_id, Label = Loc(otherAchievementTrigger.m_name), Op = Op.AtLeast, Target = 1f, HasValue = true, Value = (otherAchievementTrigger.m_unlocked ? 1f : 0f) }); } } return list; } private static void AddDict(List<ObjectiveInput> list, List<DictStatRequirement> triggers, Dictionary<string, float> dict, Source source) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) foreach (DictStatRequirement trigger in triggers) { float value = 0f; bool hasValue = trigger.m_stat != null && dict.TryGetValue(trigger.m_stat, out value); list.Add(new ObjectiveInput { Source = source, Key = trigger.m_stat, Label = Label(trigger.m_stat, trigger.m_stat), Op = Map(trigger.m_operator), Target = trigger.m_amount, HasValue = hasValue, Value = value }); } } private static Op Map(RequirementOperator op) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected I4, but got Unknown return (op - 1) switch { 0 => Op.AtMost, 1 => Op.Exactly, 2 => Op.NotEqual, _ => Op.AtLeast, }; } private static string ModifierSuffix(KillModifiers m) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected I4, but got Unknown return (m - 1) switch { 0 => " (unarmed)", 1 => " (magic)", 2 => " (ranged)", 3 => " (melee)", _ => "", }; } private static string Label(string token, string fallbackKey) { if (string.IsNullOrEmpty(token)) { return ""; } if (LabelCache.TryGetValue(token, out var value)) { return value; } string text = Loc(token); if (text == token || text.Length == 0 || (text.StartsWith("[") && text.EndsWith("]"))) { text = Labels.Humanize(fallbackKey); } LabelCache[token] = text; return text; } private static string Loc(string token) { if (string.IsNullOrEmpty(token)) { return ""; } return ((Localization.instance != null) ? Localization.instance.Localize(token) : token) ?? token; } } internal static class CheatState { public static string PausedReason() { if ((Object)(object)Achievements.m_instance == (Object)null || (Object)(object)Game.instance == (Object)null) { return null; } if (Achievements.CanGetAchievements(false)) { return null; } if (Game.isModded) { return "a mod set Game.isModded"; } if (Achievements.IsWorldCheated()) { return "world modifiers"; } if (Game.instance.GetPlayerProfile().m_usedCheats) { return "cheats used on this character"; } if ((Object)(object)Player.m_localPlayer != (Object)null && ((Humanoid)Player.m_localPlayer).GetInventory().AnyCheatedItem()) { return "a cheated item in your inventory"; } return "the game's cheat check"; } } internal static class ConsoleCommands { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__0_0; internal void <Register>b__0_0(ConsoleEventArgs args) { if ((Object)(object)Achievements.m_instance == (Object)null || (Object)(object)Game.instance == (Object)null) { Say(args.Context, "Milestones: not in a game."); return; } string text = ((args.Length > 1) ? args[1] : ""); string query = ((args.Length > 2) ? string.Join(" ", args.Args, 2, args.Length - 2) : ""); string text2 = text.ToLowerInvariant(); if (text2 == null || text2.Length != 0) { switch (text2) { case "ui": DumpUi(args.Context); break; case "pin": case "unpin": PinCommand(args.Context, text.ToLowerInvariant() == "pin", query); break; default: Detail(args.Context, string.Join(" ", args.Args, 1, args.Length - 1)); break; } } else { Summary(args.Context); } } } public static void Register() { //IL_0033: 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_0029: Expected O, but got Unknown object obj = <>c.<>9__0_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { if ((Object)(object)Achievements.m_instance == (Object)null || (Object)(object)Game.instance == (Object)null) { Say(args.Context, "Milestones: not in a game."); } else { string text = ((args.Length > 1) ? args[1] : ""); string query = ((args.Length > 2) ? string.Join(" ", args.Args, 2, args.Length - 2) : ""); string text2 = text.ToLowerInvariant(); if (text2 == null || text2.Length != 0) { switch (text2) { case "ui": DumpUi(args.Context); break; case "pin": case "unpin": PinCommand(args.Context, text.ToLowerInvariant() == "pin", query); break; default: Detail(args.Context, string.Join(" ", args.Args, 1, args.Length - 1)); break; } } else { Summary(args.Context); } } }; <>c.<>9__0_0 = val; obj = (object)val; } new ConsoleCommand("milestones", "Milestones: progress (<id|name> | pin <id> | unpin <id> | ui)", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } internal static void Say(Terminal ctx, string line) { if ((Object)(object)ctx != (Object)null) { ctx.AddString(line); } MilestonesPlugin.Log.LogInfo((object)line); } private static void PinCommand(Terminal ctx, bool pin, string query) { Achievement val = AchievementReader.Find(query); if ((Object)(object)val == (Object)null) { Say(ctx, "Milestones: no achievement matches \"" + query + "\"."); return; } bool flag = (pin ? Pins.Pin(val.m_id) : Pins.Unpin(val.m_id)); Say(ctx, "Milestones: " + ((!flag) ? "unchanged " : (pin ? "pinned " : "unpinned ")) + val.m_id + " (" + Pins.Count + "/" + 3 + ")" + ((!flag && pin && Pins.IsFull) ? " — three pins already" : "")); } private static void Summary(Terminal ctx) { Say(ctx, "Milestones: pinned = " + ((Pins.Count == 0) ? "(none)" : string.Join(", ", Pins.Ids))); string text = CheatState.PausedReason(); if (text != null) { Say(ctx, "Milestones: achievements paused: " + text); } int num = 0; foreach (Achievement item in AchievementReader.All()) { AchievementProgress achievementProgress = ProgressCache.Get(item); if (achievementProgress != null) { num++; Say(ctx, string.Format("Milestones: {0} {1} \"{2}\" {3} ({4}/{5} met)", achievementProgress.Unlocked ? "[x]" : "[ ]", item.m_id, AchievementReader.Name(item), Labels.OverallText(achievementProgress), achievementProgress.MetCount, achievementProgress.Total)); } } Say(ctx, "Milestones: " + num + " achievement(s)."); } private static void Detail(Terminal ctx, string query) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) Achievement val = AchievementReader.Find(query); if ((Object)(object)val == (Object)null) { Say(ctx, "Milestones: no achievement matches \"" + query + "\"."); return; } ProgressCache.Recompute(val); AchievementProgress achievementProgress = ProgressCache.Get(val); if (achievementProgress == null) { Say(ctx, "Milestones: no profile loaded."); return; } Say(ctx, string.Format("Milestones: {0} \"{1}\" slot={2} lenient={3} overall={4} {5}", val.m_id, AchievementReader.Name(val), val.m_difficultyRequirement, val.m_lenientBuildAchievement, Labels.OverallText(achievementProgress), achievementProgress.Unlocked ? "UNLOCKED" : "")); foreach (Objective objective in achievementProgress.Objectives) { Say(ctx, string.Format("Milestones: {0} {1} [{2} {3}] {4} {5}", objective.Met ? "[x]" : "[ ]", objective.Label, objective.Source, objective.Key, objective.Op, Labels.ProgressText(objective))); } } private static void DumpUi(Terminal ctx) { InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_achievementsPanel == (Object)null) { Say(ctx, "Milestones: no achievements panel."); return; } Dump(ctx, instance.m_achievementsPanel.m_achievementDetails.transform, 0, 3); if ((Object)(object)instance.m_achievementsPanel.m_achievementDetailsElementPrefab != (Object)null) { Dump(ctx, ((Component)instance.m_achievementsPanel.m_achievementDetailsElementPrefab).transform, 0, 3); } } private static void Dump(Terminal ctx, Transform t, int depth, int maxDepth) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: 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_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: 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_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Expected O, but got Unknown RectTransform val = (RectTransform)(object)((t is RectTransform) ? t : null); StringBuilder stringBuilder = new StringBuilder(); Component[] components = ((Component)t).GetComponents<Component>(); foreach (Component val2 in components) { if ((Object)(object)val2 != (Object)null && !(val2 is Transform)) { stringBuilder.Append(((object)val2).GetType().Name).Append(' '); } } object[] obj = new object[8] { new string(' ', depth * 2), ((Object)t).name, ((Component)t).gameObject.activeSelf, null, null, null, null, null }; object obj2; if (!((Object)(object)val != (Object)null)) { obj2 = "-"; } else { Rect rect = val.rect; obj2 = ((object)((Rect)(ref rect)).size/*cast due to .constrained prefix*/).ToString(); } obj[3] = obj2; obj[4] = (((Object)(object)val != (Object)null) ? ((object)val.anchorMin/*cast due to .constrained prefix*/).ToString() : "-"); obj[5] = (((Object)(object)val != (Object)null) ? ((object)val.anchorMax/*cast due to .constrained prefix*/).ToString() : "-"); obj[6] = (((Object)(object)val != (Object)null) ? ((object)val.anchoredPosition/*cast due to .constrained prefix*/).ToString() : "-"); obj[7] = stringBuilder; Say(ctx, string.Format("Milestones: {0}{1} active={2} size={3} anchors={4}-{5} pos={6} [{7}]", obj)); if (depth >= maxDepth) { return; } foreach (Transform item in t) { Transform t2 = item; Dump(ctx, t2, depth + 1, maxDepth); } } } internal static class Pins { private const string Key = "milestones.pins"; private const float UnpinDelay = 10f; private static PinList _list; private static string _profile; private static Player _owner; private static readonly Dictionary<string, float> UnpinAt; public static IReadOnlyList<string> Ids => _list.Ids; public static int Count => _list.Count; public static bool IsFull => _list.IsFull; public static event Action Changed; static Pins() { _list = new PinList(); UnpinAt = new Dictionary<string, float>(); Runtime.PlayerSpawned += OnPlayerSpawned; StatEvents.Unlocked += OnUnlocked; } public static void Init() { } private static void OnPlayerSpawned(Player p) { string filename = Game.instance.GetPlayerProfile().GetFilename(); if (filename != _profile) { p.m_customData.TryGetValue("milestones.pins", out var value); _list = PinList.Parse(value); _profile = filename; UnpinAt.Clear(); } _owner = p; _list.RemoveWhere((string id) => (Object)(object)AchievementReader.ById(id) == (Object)null); Save(); Raise(); } public static bool Contains(string id) { return _list.Contains(id); } public static bool Toggle(Achievement a) { if (!Contains(a.m_id)) { return Pin(a.m_id); } return Unpin(a.m_id); } public static bool Pin(string id) { if (!_list.Add(id)) { return false; } Save(); Raise(); return true; } public static bool Unpin(string id) { UnpinAt.Remove(id); if (!_list.Remove(id)) { return false; } Save(); Raise(); return true; } public static void Tick(float now) { if (UnpinAt.Count == 0) { return; } string text = null; foreach (KeyValuePair<string, float> item in UnpinAt) { if (now >= item.Value) { text = item.Key; break; } } if (text != null) { Unpin(text); } } private static void OnUnlocked(Achievement a) { if (PluginConfig.AutoUnpinCompleted.Value && Contains(a.m_id)) { UnpinAt[a.m_id] = Runtime.Now + 10f; } } private static void Save() { if (!((Object)(object)_owner == (Object)null)) { if (_list.Count == 0) { _owner.m_customData.Remove("milestones.pins"); } else { _owner.m_customData["milestones.pins"] = _list.Serialize(); } } } private static void Raise() { if (PluginConfig.Verbose.Value) { MilestonesPlugin.Log.LogInfo((object)("Milestones: pins = " + _list.Serialize())); } if (Pins.Changed != null) { Pins.Changed(); } } } internal static class ProgressCache { private sealed class Index { public StatKind Kinds; public readonly HashSet<PlayerStatType> Stats = new HashSet<PlayerStatType>(); } private static readonly Dictionary<string, AchievementProgress> ById = new Dictionary<string, AchievementProgress>(); private static readonly Dictionary<string, Index> Indexes = new Dictionary<string, Index>(); private static readonly HashSet<PlayerStatType> DirtyStats = new HashSet<PlayerStatType>(); public static event Action<Achievement, AchievementProgress> Changed; public static void Clear() { ById.Clear(); Indexes.Clear(); AchievementReader.ClearLabels(); } public static AchievementProgress Get(Achievement a) { if (ById.TryGetValue(a.m_id, out var value)) { return value; } value = Compute(a); if (value != null) { ById[a.m_id] = value; } return value; } public static void Recompute(Achievement a) { AchievementProgress achievementProgress = Compute(a); if (achievementProgress == null) { return; } AchievementProgress value; bool num = ById.TryGetValue(a.m_id, out value); ById[a.m_id] = achievementProgress; if (num && !ProgressCalc.SameValues(value, achievementProgress) && ProgressCache.Changed != null) { if (PluginConfig.Verbose.Value) { MilestonesPlugin.Log.LogInfo((object)("Milestones: " + a.m_id + " → " + Labels.OverallText(achievementProgress))); } ProgressCache.Changed(a, achievementProgress); } } public static void ProcessDirty() { StatKind statKind = StatEvents.Take(DirtyStats); if (statKind == StatKind.None) { return; } foreach (Achievement item in AchievementReader.All()) { if (ById.ContainsKey(item.m_id)) { Index index = IndexOf(item); if ((statKind & StatKind.Unlock) != StatKind.None || (index.Kinds & statKind & ~StatKind.Player) != StatKind.None || ((statKind & StatKind.Player) != StatKind.None && index.Stats.Overlaps(DirtyStats))) { Recompute(item); } } } } public static void RefreshAll() { foreach (Achievement item in AchievementReader.All()) { Recompute(item); } } private static AchievementProgress Compute(Achievement a) { PlayerProfile val = (((Object)(object)Game.instance != (Object)null) ? Game.instance.GetPlayerProfile() : null); if (val == null) { return null; } return ProgressCalc.Compute(a.m_id, AchievementReader.Read(a, val), a.m_unlocked, a.m_lenientBuildAchievement, PluginConfig.Overall.Value); } private static Index IndexOf(Achievement a) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (Indexes.TryGetValue(a.m_id, out var value)) { return value; } value = new Index(); foreach (PlayerStatRequirement item in a.m_statTrigger) { value.Kinds |= StatKind.Player; value.Stats.Add(item.m_stat); } if (a.m_enemyStatsTriggers.Count > 0) { value.Kinds |= StatKind.Enemy; } if (a.m_itemPickupTriggers.Count > 0) { value.Kinds |= StatKind.Pickup; } if (a.m_itemCraftTriggers.Count > 0) { value.Kinds |= StatKind.Craft; } if (a.m_pickableTriggers.Count > 0) { value.Kinds |= StatKind.Pickable; } if (a.m_foodEatenTriggers.Count > 0) { value.Kinds |= StatKind.Food; } if (a.m_piecePlacedTriggers.Count > 0) { value.Kinds |= StatKind.Piece; } Indexes[a.m_id] = value; return value; } } internal static class Runtime { private const float DirtyInterval = 0.25f; private const float SweepInterval = 10f; private static Player _player; private static float _nextDirty; private static float _nextSweep; public static float Now => Time.unscaledTime; public static event Action<Player> PlayerSpawned; public static event Action Ticked; public static void Tick() { try { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)(object)_player && ((Object)(object)localPlayer == (Object)null || (Object)(object)Achievements.m_instance != (Object)null)) { _player = localPlayer; ProgressCache.Clear(); if ((Object)(object)localPlayer != (Object)null) { MilestonesPlugin.Log.LogInfo((object)("Milestones: player spawned; Game.isModded = " + Game.isModded)); if (Runtime.PlayerSpawned != null) { Runtime.PlayerSpawned(localPlayer); } } } if ((Object)(object)_player == (Object)null || !PluginConfig.Enabled.Value) { return; } float now = Now; Pins.Tick(now); if (now >= _nextDirty) { _nextDirty = now + 0.25f; if (StatEvents.Any) { ProgressCache.ProcessDirty(); } } if (now >= _nextSweep) { _nextSweep = now + 10f; ProgressCache.RefreshAll(); } if (Runtime.Ticked != null) { Runtime.Ticked(); } } catch (Exception e) { MilestonesPlugin.WarnOnce("tick", e); } } } [Flags] internal enum StatKind { None = 0, Player = 1, Enemy = 2, Pickup = 4, Craft = 8, Pickable = 0x10, Food = 0x20, Piece = 0x40, Unlock = 0x80, All = 0xFF } internal static class StatEvents { private static StatKind _kinds; private static readonly HashSet<PlayerStatType> Stats = new HashSet<PlayerStatType>(); public static bool Any => _kinds != StatKind.None; public static event Action<Achievement> Unlocked; public static void Mark(StatKind kind) { _kinds |= kind; } public static void MarkStat(PlayerStatType stat) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) _kinds |= StatKind.Player; Stats.Add(stat); } public static void MarkUnlocked(Achievement a) { _kinds |= StatKind.All; if (StatEvents.Unlocked != null) { StatEvents.Unlocked(a); } } public static StatKind Take(HashSet<PlayerStatType> statsOut) { statsOut.Clear(); statsOut.UnionWith(Stats); Stats.Clear(); StatKind kinds = _kinds; _kinds = StatKind.None; return kinds; } } } namespace Milestones.Core.Model { public static class Labels { public const string Check = "✓"; public static string Humanize(string key) { if (string.IsNullOrEmpty(key)) { return ""; } string text = key.TrimStart(new char[1] { '$' }); int num = text.IndexOf('_'); if (key.StartsWith("$") && num >= 0 && num < text.Length - 1) { text = text.Substring(num + 1); } StringBuilder stringBuilder = new StringBuilder(text.Length + 8); for (int i = 0; i < text.Length; i++) { char c = text[i]; if (c == '_') { stringBuilder.Append(' '); continue; } if (i > 0 && char.IsUpper(c) && char.IsLower(text[i - 1])) { stringBuilder.Append(' '); } stringBuilder.Append((stringBuilder.Length == 0) ? char.ToUpperInvariant(c) : char.ToLowerInvariant(c)); } return stringBuilder.ToString(); } public static string Amount(float v) { if (Math.Abs(v) >= 100f) { return Math.Round(v).ToString("0", CultureInfo.InvariantCulture); } return v.ToString("0.#", CultureInfo.InvariantCulture); } public static string Percent(float fraction) { return ((int)Math.Floor(((fraction < 0f) ? 0f : ((fraction > 1f) ? 1f : fraction)) * 100f + 0.0001f)).ToString(CultureInfo.InvariantCulture) + "%"; } public static string ProgressText(Objective o) { if (!o.HasBar) { if (!o.Met) { return "not met"; } return "met"; } float v = Math.Min(o.Current, o.Target); return Amount(v) + " / " + Amount(o.Target) + " " + Percent(o.Fraction); } public static string OverallText(AchievementProgress p) { if (!p.ShowAsCount) { return Percent(p.Overall); } return p.MetCount + " / " + p.Total; } } public enum Op { AtLeast, AtMost, Exactly, NotEqual } public enum Source { PlayerStat, Enemy, ItemPickup, ItemCraft, FoodEaten, Pickable, PiecePlaced, KnownWorld, KnownWorldKey, KnownCommand, OtherAchievement } public enum OverallMode { Auto, Average, Count } public enum PinnedToastMode { ObjectivesAndThresholds, ThresholdsOnly, Off } public enum UnpinnedToastMode { ThresholdsOnly, Off } public sealed class ObjectiveInput { public Source Source; public string Key; public string Label; public Op Op; public float Target; public bool HasValue; public float Value; } public sealed class Objective { public Source Source; public string Key; public string Label; public Op Op; public float Current; public float Target; public bool Met; public bool HasBar; public float Fraction; public bool Started { get { if (!Met) { return Current > 0f; } return true; } } } public sealed class AchievementProgress { public string Id; public List<Objective> Objectives = new List<Objective>(); public int MetCount; public float Overall; public bool ShowAsCount; public bool Unlocked; public int Total => Objectives.Count; } public sealed class TrackerRows { public List<int> Indices = new List<int>(); public int More; } public static class ObjectiveOrder { public static List<int> Sorted(AchievementProgress p) { List<int> list = new List<int>(p.Total); for (int i = 0; i < p.Total; i++) { list.Add(i); } list.Sort(delegate(int a, int b) { Objective objective = p.Objectives[a]; Objective objective2 = p.Objectives[b]; if (objective.Met != objective2.Met) { if (!objective.Met) { return -1; } return 1; } return (!objective.Met && objective.Fraction != objective2.Fraction) ? objective2.Fraction.CompareTo(objective.Fraction) : a.CompareTo(b); }); return list; } public static TrackerRows Select(AchievementProgress p, int max) { TrackerRows trackerRows = new TrackerRows(); if (p.Total <= max) { for (int i = 0; i < p.Total; i++) { trackerRows.Indices.Add(i); } return trackerRows; } int num = 0; foreach (int item in Sorted(p)) { if (p.Objectives[item].Met) { break; } num++; if (trackerRows.Indices.Count < max) { trackerRows.Indices.Add(item); } } trackerRows.More = num - trackerRows.Indices.Count; return trackerRows; } } public sealed class PinList { public const int Max = 3; private readonly List<string> _ids = new List<string>(3); public IReadOnlyList<string> Ids => _ids; public int Count => _ids.Count; public bool IsFull => _ids.Count >= 3; public static PinList Parse(string raw) { PinList pinList = new PinList(); if (string.IsNullOrEmpty(raw)) { return pinList; } string[] array = raw.Split(new char[1] { ',' }); foreach (string text in array) { pinList.Add(text.Trim()); } return pinList; } public string Serialize() { return string.Join(",", _ids); } public bool Contains(string id) { return _ids.Contains(id); } public bool Add(string id) { if (string.IsNullOrEmpty(id) || id.IndexOf(',') >= 0 || IsFull || _ids.Contains(id)) { return false; } _ids.Add(id); return true; } public bool Remove(string id) { return _ids.Remove(id); } public int RemoveWhere(Func<string, bool> drop) { return _ids.RemoveAll((string id) => drop(id)); } } public static class ProgressCalc { public const float LenientFactor = 1.15f; public static Objective Evaluate(ObjectiveInput i) { float num = (i.HasValue ? i.Value : 0f); bool flag = i.HasValue && i.Op switch { Op.AtLeast => num >= i.Target, Op.AtMost => num <= i.Target, Op.Exactly => num == i.Target, _ => num != i.Target, }; bool flag2 = i.Op == Op.AtLeast; float fraction = (flag ? 1f : ((!flag2 || !(i.Target > 0f)) ? 0f : Clamp01(num / i.Target))); return new Objective { Source = i.Source, Key = i.Key, Label = i.Label, Op = i.Op, Current = num, Target = i.Target, Met = flag, HasBar = flag2, Fraction = fraction }; } public static AchievementProgress Compute(string id, IList<ObjectiveInput> inputs, bool unlocked, bool lenient, OverallMode mode) { AchievementProgress achievementProgress = new AchievementProgress { Id = id, Unlocked = unlocked }; bool flag = inputs.Count > 0; float num = 0f; float num2 = 0f; float num3 = 0f; foreach (ObjectiveInput input in inputs) { Objective objective = Evaluate(input); achievementProgress.Objectives.Add(objective); if (objective.Met) { achievementProgress.MetCount++; } num += objective.Fraction; if (objective.Op != Op.AtLeast || objective.Target != 1f) { flag = false; } if (lenient && objective.Source == Source.PlayerStat) { num2 += objective.Target; num3 += Math.Min(objective.Current, objective.Target * 1.15f); } } int count = achievementProgress.Objectives.Count; if (lenient) { achievementProgress.ShowAsCount = false; achievementProgress.Overall = ((num2 > 0f) ? Clamp01(num3 / num2) : 0f); } else { achievementProgress.ShowAsCount = mode == OverallMode.Count || (mode == OverallMode.Auto && flag); if (count == 0) { achievementProgress.Overall = 0f; } else if (achievementProgress.ShowAsCount) { achievementProgress.Overall = (float)achievementProgress.MetCount / (float)count; } else { achievementProgress.Overall = num / (float)count; } } if (unlocked) { achievementProgress.Overall = 1f; } return achievementProgress; } public static bool SameValues(AchievementProgress a, AchievementProgress b) { if (a == null || b == null) { return false; } if (a.Unlocked != b.Unlocked || a.MetCount != b.MetCount || a.Overall != b.Overall || a.Total != b.Total) { return false; } for (int i = 0; i < a.Total; i++) { if (a.Objectives[i].Current != b.Objectives[i].Current || a.Objectives[i].Met != b.Objectives[i].Met) { return false; } } return true; } private static float Clamp01(float v) { if (!(v < 0f)) { if (!(v > 1f)) { return v; } return 1f; } return 0f; } } public sealed class Snapshot { public float Overall; public bool[] Met; public bool Unlocked; public static Snapshot Take(AchievementProgress p) { bool[] array = new bool[p.Total]; for (int i = 0; i < array.Length; i++) { array[i] = p.Objectives[i].Met; } return new Snapshot { Overall = p.Overall, Met = array, Unlocked = p.Unlocked }; } } public sealed class ToastRules { public PinnedToastMode Pinned; public UnpinnedToastMode Unpinned; public int[] Thresholds = new int[0]; public static int[] ParseThresholds(string raw) { SortedSet<int> sortedSet = new SortedSet<int>(); if (!string.IsNullOrEmpty(raw)) { string[] array = raw.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { if (int.TryParse(array[i].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && result >= 1 && result <= 99) { sortedSet.Add(result); } } } int[] array2 = new int[sortedSet.Count]; sortedSet.CopyTo(array2); return array2; } } public static class ToastDiff { private const string Prefix = "Milestones: "; public static string Diff(Snapshot before, AchievementProgress now, string name, bool pinned, ToastRules rules) { if (before == null || now.Unlocked || before.Unlocked) { return null; } bool flag = pinned && rules.Pinned == PinnedToastMode.ObjectivesAndThresholds; bool num = (pinned ? (rules.Pinned != PinnedToastMode.Off) : (rules.Unpinned == UnpinnedToastMode.ThresholdsOnly)); int num2 = 0; if (num) { int num3 = Pct(before.Overall); int num4 = Pct(now.Overall); int[] thresholds = rules.Thresholds; foreach (int num5 in thresholds) { if (num3 < num5 && num4 >= num5) { num2 = num5; } } } List<int> list = new List<int>(); if (flag && before.Met != null && before.Met.Length == now.Total) { for (int j = 0; j < now.Total; j++) { if (!before.Met[j] && now.Objectives[j].Met) { list.Add(j); } } } if (list.Count == 0) { if (num2 <= 0) { return null; } return "Milestones: " + name + " " + num2 + "%"; } string text = ((list.Count == 1) ? now.Objectives[list[0]].Label : (list.Count + " objectives")); string text2 = "Milestones: " + text + " ✓ · " + name + " " + Labels.OverallText(now); if (num2 > 0 && now.ShowAsCount) { text2 = text2 + " · " + num2 + "%"; } return text2; } private static int Pct(float f) { return (int)Math.Floor(Math.Max(0f, Math.Min(1f, f)) * 100f + 0.0001f); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }