diff --git a/ECommons b/ECommons index 66efcbd9e..db6097144 160000 --- a/ECommons +++ b/ECommons @@ -1 +1 @@ -Subproject commit 66efcbd9eaaaa8f4645a89108d3c6eb042e8cd68 +Subproject commit db60971448d90e9f3345e337fda57d99d36e25f5 diff --git a/RotationSolver.Basic/Actions/ActionTargetInfo.cs b/RotationSolver.Basic/Actions/ActionTargetInfo.cs index 490421b59..8d00b1f11 100644 --- a/RotationSolver.Basic/Actions/ActionTargetInfo.cs +++ b/RotationSolver.Basic/Actions/ActionTargetInfo.cs @@ -179,7 +179,7 @@ private bool IsSpecialAbility(uint iD) /// /// true if the battle character meets the criteria for targeting; otherwise, false. /// - private bool GeneralCheck(IBattleChara gameObject, bool skipStatusProvideCheck) + public bool GeneralCheck(IBattleChara gameObject, bool skipStatusProvideCheck) { if (!gameObject.IsTargetable) return false; diff --git a/RotationSolver.Basic/Configuration/Configs.cs b/RotationSolver.Basic/Configuration/Configs.cs index b24fd3302..9a2f2ea98 100644 --- a/RotationSolver.Basic/Configuration/Configs.cs +++ b/RotationSolver.Basic/Configuration/Configs.cs @@ -110,7 +110,7 @@ public const string Parent = nameof(AddEnemyListToHostile))] private static readonly bool _onlyAttackInEnemyList = false; - [JobConfig, UI("Gemdraughts/Tinctures/Pots", Filter = AutoActionUsage, PvPFilter = JobFilterType.NoJob)] + [JobConfig, UI("Only used automatically if coded into the rotation", Filter = AutoActionUsage, PvPFilter = JobFilterType.NoJob)] private readonly TinctureUseType _TinctureType = TinctureUseType.Nowhere; [ConditionBool, UI("Automatically use Anti-Knockback role actions (Arms Length, Surecast)", Filter = AutoActionUsage)] @@ -316,7 +316,7 @@ public const string PvEFilter = JobFilterType.Tank)] private static readonly bool _autoTankStance = true; - [ConditionBool, UI("Auto provoke non-tank attacking targets", Description = "Automatically use provoke when an enemy is attacking a non-tank member of the party.", + [ConditionBool, UI("Auto provoke when there is another tank in party", Description = "Automatically use provoke when an enemy is attacking a non-tank member of the party while there is more than one tank in party.", Parent = nameof(UseAbility), PvEFilter = JobFilterType.Tank)] private static readonly bool _autoProvokeForTank = true; @@ -391,11 +391,6 @@ public const string [Range(0.100f, 2.500f, ConfigUnitType.Seconds, 0.001f)] public float isFirstAbilityTimer { get; set; } = 0.600f; - [UI("Max Attack Target Count Tracking", Description = "Don't fuck with this if you dont know what it does", - Filter = Extra)] - [Range(8, 100, ConfigUnitType.None, 1)] - public int internalAttackTargetCount { get; set; } = 48; - [UI("Auto turn off RSR when combat is over more for more then...", Parent = nameof(AutoOffAfterCombat))] [Range(0, 600, ConfigUnitType.Seconds)] @@ -468,7 +463,7 @@ public const string Filter = HealingActionCondition, Section = 3)] private static readonly bool _healOutOfCombat = false; - [ConditionBool, UI("Heal solo instance NPCs. (Experimental)", + [ConditionBool, UI("Heal solo instance NPCs", Description = "Experimental.", Filter = HealingActionCondition, Section = 3)] private static readonly bool _friendlyBattleNPCHeal = false; @@ -476,7 +471,7 @@ public const string Filter = HealingActionCondition, Section = 3)] private static readonly bool _friendlyPartyNPCHealRaise = true; - [ConditionBool, UI("Heal/Dance partner your chocobo. (Experimental)", + [ConditionBool, UI("Heal/Dance partner your chocobo", Description = "Experimental.", Filter = HealingActionCondition, Section = 3)] private static readonly bool _chocoboPartyMember = false; diff --git a/RotationSolver.Basic/DataCenter.cs b/RotationSolver.Basic/DataCenter.cs index 9cf66ef64..e95bbcb65 100644 --- a/RotationSolver.Basic/DataCenter.cs +++ b/RotationSolver.Basic/DataCenter.cs @@ -353,9 +353,6 @@ public static IBattleChara[] AllHostileTargets // Check if the target is an enemy. if (!b.IsEnemy()) return false; - // Check if the target is dead. - if (b.CurrentHp <= 1) return false; - // Check if the target is targetable. if (!b.IsTargetable) return false; diff --git a/RotationSolver.Basic/Helpers/ObjectHelper.cs b/RotationSolver.Basic/Helpers/ObjectHelper.cs index 1d6ef23b2..586624735 100644 --- a/RotationSolver.Basic/Helpers/ObjectHelper.cs +++ b/RotationSolver.Basic/Helpers/ObjectHelper.cs @@ -36,8 +36,7 @@ internal static bool CanProvoke(this IGameObject target) { if (target == null) return false; - // Assuming DataCenter.FateId is an ID, not an IGameObject - if (target.DataId == DataCenter.FateId) return false; + if (DataCenter.FateId != 0 && target.FateId() == DataCenter.FateId) return false; //Removed the listed names. if (OtherConfiguration.NoProvokeNames.TryGetValue(Svc.ClientState.TerritoryType, out var ns1)) @@ -194,7 +193,7 @@ internal static bool IsDeathToRaise(this IGameObject obj) internal static bool IsAlive(this IGameObject obj) { - return obj is not IBattleChara b || b.CurrentHp > 1 && obj.IsTargetable; + return obj is not IBattleChara b || b.CurrentHp > 0 && obj.IsTargetable; } /// diff --git a/RotationSolver/Data/UiString.cs b/RotationSolver/Data/UiString.cs index acb3b9968..d1ec321ad 100644 --- a/RotationSolver/Data/UiString.cs +++ b/RotationSolver/Data/UiString.cs @@ -7,6 +7,27 @@ internal enum UiString [Description("The condition set you chose, click to modify.")] ConfigWindow_ConditionSetDesc, + [Description("Condition Set")] + ConfigWindow_ConditionSet, + + [Description("Action Condition")] + ConfigWindow_ActionSet, + + [Description("Trait Condition")] + ConfigWindow_TraitSet, + + [Description("Target Condition")] + ConfigWindow_TargetSet, + + [Description("Rotation Condition")] + ConfigWindow_RotationSet, + + [Description("Named Condition")] + ConfigWindow_NamedSet, + + [Description("Territory Condition")] + ConfigWindow_Territoryset, + [Description("No rotations loaded! Please see the rotations tab!")] ConfigWindow_NoRotation, diff --git a/RotationSolver/UI/ConditionDrawer.cs b/RotationSolver/UI/ConditionDrawer.cs index 2ad0e297c..d79e719ea 100644 --- a/RotationSolver/UI/ConditionDrawer.cs +++ b/RotationSolver/UI/ConditionDrawer.cs @@ -559,13 +559,13 @@ void AddButton() using var popUp = ImRaii.Popup("Popup" + conditionSet.GetHashCode().ToString()); if (popUp) { - AddOneCondition(); - AddOneCondition(); - AddOneCondition(); - AddOneCondition(); - AddOneCondition(); - AddOneCondition(); - AddOneCondition(); + AddOneCondition(UiString.ConfigWindow_ConditionSet.GetDescription()); + AddOneCondition(UiString.ConfigWindow_ActionSet.GetDescription()); + AddOneCondition(UiString.ConfigWindow_TraitSet.GetDescription()); + AddOneCondition(UiString.ConfigWindow_TargetSet.GetDescription()); + AddOneCondition(UiString.ConfigWindow_RotationSet.GetDescription()); + AddOneCondition(UiString.ConfigWindow_NamedSet.GetDescription()); + AddOneCondition(UiString.ConfigWindow_Territoryset.GetDescription()); if (ImGui.Selectable(UiString.ActionSequencer_FromClipboard.GetDescription())) { var str = ImGui.GetClipboardText(); @@ -582,9 +582,9 @@ void AddButton() } } - void AddOneCondition() where T : ICondition + void AddOneCondition(string description) where T : ICondition { - if (ImGui.Selectable(typeof(T).ToString())) + if (ImGui.Selectable(description)) { conditionSet.Conditions.Add(Activator.CreateInstance()); ImGui.CloseCurrentPopup(); diff --git a/RotationSolver/UI/CooldownWindow.cs b/RotationSolver/UI/CooldownWindow.cs index 67f8d380c..3a52ff2dc 100644 --- a/RotationSolver/UI/CooldownWindow.cs +++ b/RotationSolver/UI/CooldownWindow.cs @@ -8,37 +8,42 @@ public override void Draw() { if (DataCenter.RightNowRotation == null) return; - var width = Service.Config.CooldownWindowIconSize; + var config = Service.Config; + var width = config.CooldownWindowIconSize; const float IconSpacingFactor = 6f / 82f; - var count = Math.Max(1, (int)MathF.Floor(ImGui.GetColumnWidth() / (width * (1 + IconSpacingFactor) + ImGui.GetStyle().ItemSpacing.X))); + var style = ImGui.GetStyle(); + var columnWidth = ImGui.GetColumnWidth(); + var count = Math.Max(1, (int)MathF.Floor(columnWidth / (width * (1 + IconSpacingFactor) + style.ItemSpacing.X))); - if (RotationUpdater.AllGroupedActions == null) return; + var allGroupedActions = RotationUpdater.AllGroupedActions; + if (allGroupedActions == null) return; - foreach (var pair in RotationUpdater.AllGroupedActions) + foreach (var pair in allGroupedActions) { - var showItems = pair.OrderBy(a => a.SortKey) - .Where(a => a.IsInCooldown && (a is not IBaseAction b || !b.Info.IsLimitBreak)); - - if (!Service.Config.ShowGcdCooldown) - { - showItems = showItems.Where(i => !(i is IBaseAction a && a.Info.IsGeneralGCD)); - } + var showItems = pair + .Where(a => a.IsInCooldown && (a is not IBaseAction b || !b.Info.IsLimitBreak)) + .Where(a => config.ShowGcdCooldown || !(a is IBaseAction b && b.Info.IsGeneralGCD)) + .Where(a => config.ShowItemsCooldown || !(a is IBaseItem)) + .OrderBy(a => a.SortKey) + .ToList(); if (!showItems.Any()) continue; - if (!Service.Config.ShowItemsCooldown && showItems.Any(i => i is IBaseItem)) continue; - ImGui.Text(pair.Key); + ImGui.Columns(count, null, false); uint itemIndex = 0; foreach (var item in showItems) { - if (itemIndex++ % count != 0) + ControlWindow.DrawIAction(item, width, 1f); + itemIndex++; + if (itemIndex % count != 0) { - ImGui.SameLine(); + ImGui.NextColumn(); } - ControlWindow.DrawIAction(item, width, 1f); } + ImGui.Columns(1); + ImGui.NewLine(); } } } \ No newline at end of file diff --git a/RotationSolver/UI/CtrlWindow.cs b/RotationSolver/UI/CtrlWindow.cs index 1e26798c3..6ae2d29d0 100644 --- a/RotationSolver/UI/CtrlWindow.cs +++ b/RotationSolver/UI/CtrlWindow.cs @@ -12,43 +12,27 @@ internal abstract class CtrlWindow(string name) : Window(name, BaseFlags) public override void PreDraw() { - Vector4 bgColor = Service.Config.IsControlWindowLock - ? Service.Config.ControlWindowLockBg - : Service.Config.ControlWindowUnlockBg; + var config = Service.Config; + Vector4 bgColor = config.IsControlWindowLock + ? config.ControlWindowLockBg + : config.ControlWindowUnlockBg; ImGui.PushStyleColor(ImGuiCol.WindowBg, bgColor); Flags = BaseFlags; - if (Service.Config.IsControlWindowLock) + if (config.IsControlWindowLock) { Flags |= ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove; } ImGui.PushStyleVar(ImGuiStyleVar.WindowBorderSize, 0); - try - { - base.PreDraw(); - } - catch (Exception) - { - - } + base.PreDraw(); } public override void PostDraw() { - try - { - base.PostDraw(); - } - catch (Exception) - { - - } - finally - { - ImGui.PopStyleColor(); - ImGui.PopStyleVar(); - } + base.PostDraw(); + ImGui.PopStyleColor(); + ImGui.PopStyleVar(); } } \ No newline at end of file diff --git a/RotationSolver/UI/FontManager.cs b/RotationSolver/UI/FontManager.cs index ea840a919..223926139 100644 --- a/RotationSolver/UI/FontManager.cs +++ b/RotationSolver/UI/FontManager.cs @@ -22,7 +22,7 @@ public unsafe static ImFontPtr GetFont(float size) var font = lockedHandle.ImFont; // Check if the font pointer is valid - if (new IntPtr(font.NativePtr) == IntPtr.Zero) + if (font.NativePtr == null) { return ImGui.GetFont(); } diff --git a/RotationSolver/UI/ImguiTooltips.cs b/RotationSolver/UI/ImguiTooltips.cs index de9e0b6c0..648f801bd 100644 --- a/RotationSolver/UI/ImguiTooltips.cs +++ b/RotationSolver/UI/ImguiTooltips.cs @@ -23,8 +23,10 @@ internal static class ImguiTooltips /// The text to display in the tooltip. public static void HoveredTooltip(string? text) { - if (!ImGui.IsItemHovered()) return; - ShowTooltip(text); + if (ImGui.IsItemHovered() && !string.IsNullOrEmpty(text)) + { + ShowTooltip(() => ImGui.Text(text)); + } } /// @@ -33,8 +35,10 @@ public static void HoveredTooltip(string? text) /// The text to display in the tooltip. public static void ShowTooltip(string? text) { - if (string.IsNullOrEmpty(text)) return; - ShowTooltip(() => ImGui.Text(text)); + if (!string.IsNullOrEmpty(text)) + { + ShowTooltip(() => ImGui.Text(text)); + } } /// @@ -43,14 +47,14 @@ public static void ShowTooltip(string? text) /// The action to perform to render the tooltip content. public static void ShowTooltip(Action act) { - if (act == null) return; - if (Service.Config == null || !Service.Config.ShowTooltips) return; + if (act == null || Service.Config == null || !Service.Config.ShowTooltips) return; ImGui.SetNextWindowBgAlpha(1); using var color = ImRaii.PushColor(ImGuiCol.BorderShadow, ImGuiColors.DalamudWhite); - ImGui.SetNextWindowSizeConstraints(new Vector2(150, 0) * ImGuiHelpers.GlobalScale, new Vector2(1200, 1500) * ImGuiHelpers.GlobalScale); + var globalScale = ImGuiHelpers.GlobalScale; + ImGui.SetNextWindowSizeConstraints(new Vector2(150, 0) * globalScale, new Vector2(1200, 1500) * globalScale); ImGui.SetWindowPos(TOOLTIP_ID, ImGui.GetIO().MousePos); if (ImGui.Begin(TOOLTIP_ID, TOOLTIP_FLAG)) diff --git a/RotationSolver/UI/NextActionWindow.cs b/RotationSolver/UI/NextActionWindow.cs index 5bb24f853..532a6c319 100644 --- a/RotationSolver/UI/NextActionWindow.cs +++ b/RotationSolver/UI/NextActionWindow.cs @@ -43,8 +43,8 @@ public override void PostDraw() public override unsafe void Draw() { - var width = Service.Config.ControlWindowGCDSize - * Service.Config.ControlWindowNextSizeRatio; + var config = Service.Config; + var width = config.ControlWindowGCDSize * config.ControlWindowNextSizeRatio; DrawGcdCooldown(width, false); var percent = 0f; diff --git a/RotationSolver/UI/RotationConfigWindow.cs b/RotationSolver/UI/RotationConfigWindow.cs index 07efac278..1124bd3a0 100644 --- a/RotationSolver/UI/RotationConfigWindow.cs +++ b/RotationSolver/UI/RotationConfigWindow.cs @@ -14,6 +14,7 @@ using ExCSS; using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game.Fate; +using FFXIVClientStructs.FFXIV.Client.Game.Object; using FFXIVClientStructs.FFXIV.Client.System.Framework; using FFXIVClientStructs.FFXIV.Common.Component.BGCollision; using Lumina.Excel.GeneratedSheets; @@ -2758,7 +2759,7 @@ private static unsafe void DrawTargetData() { ImGui.Text($"Owner: {owner.Name}"); } - + if (target is IBattleChara battleChara) { ImGui.Text($"HP: {battleChara.CurrentHp} / {battleChara.MaxHp}"); @@ -2768,7 +2769,12 @@ private static unsafe void DrawTargetData() ImGui.Text($"Rank: {battleChara.GetObjectNPC()?.Rank.ToString() ?? string.Empty}"); ImGui.Text($"Has Positional: {battleChara.HasPositional()}"); ImGui.Text($"Is Dying: {battleChara.IsDying()}"); + ImGui.Text($"Is Alive: {battleChara.IsAlive()}"); ImGui.Text($"Is Party: {battleChara.IsParty()}"); + ImGui.Text($"Is Enemy: {battleChara.IsEnemy()}"); + ImGui.Text($"Is In EnemiesList: {battleChara.IsInEnemiesList()}"); + ImGui.Text($"Is Attackable: {battleChara.IsAttackable()}"); + ImGui.Text($"CanProvoke: {battleChara.CanProvoke()}"); ImGui.Text($"EventType: {battleChara.GetEventType()}"); ImGui.Text($"NamePlate: {battleChara.GetNamePlateIcon()}"); ImGui.Text($"StatusFlags: {battleChara.StatusFlags}"); diff --git a/RotationSolver/UI/RotationConfigWindowTab.cs b/RotationSolver/UI/RotationConfigWindowTab.cs index fece93903..d553544fa 100644 --- a/RotationSolver/UI/RotationConfigWindowTab.cs +++ b/RotationSolver/UI/RotationConfigWindowTab.cs @@ -17,7 +17,7 @@ internal class TabSkipAttribute : Attribute [AttributeUsage(AttributeTargets.Field)] internal class TabIconAttribute : Attribute { - public uint Icon { get; set; } + public uint Icon { get; init; } } /// @@ -64,10 +64,10 @@ internal enum RotationConfigWindowTab : byte /// public struct IncompatiblePlugin { - public string Name { get; set; } - public string Icon { get; set; } - public string Url { get; set; } - public string Features { get; set; } + public string Name { get; init; } + public string Icon { get; init; } + public string Url { get; init; } + public string Features { get; init; } /// /// Checks if the plugin is installed. @@ -78,12 +78,13 @@ public readonly bool IsInstalled get { var name = this.Name; - return Svc.PluginInterface.InstalledPlugins.Any(x => + var installedPlugins = Svc.PluginInterface.InstalledPlugins; + return installedPlugins.Any(x => (x.Name.Equals(name, StringComparison.OrdinalIgnoreCase) || x.InternalName.Equals(name, StringComparison.OrdinalIgnoreCase)) && x.IsLoaded); } } - public CompatibleType Type { get; set; } + public CompatibleType Type { get; init; } } /// diff --git a/RotationSolver/UI/SearchableCollection.cs b/RotationSolver/UI/SearchableCollection.cs index 75c88d0e1..0f3d571dd 100644 --- a/RotationSolver/UI/SearchableCollection.cs +++ b/RotationSolver/UI/SearchableCollection.cs @@ -1,6 +1,7 @@ using RotationSolver.Basic.Configuration; using RotationSolver.UI.SearchableConfigs; using RotationSolver.UI.SearchableSettings; +using System.Collections.Concurrent; namespace RotationSolver.UI; @@ -15,9 +16,12 @@ internal class SearchableCollection public SearchableCollection() { // Retrieve properties from the Configs class - var properties = typeof(Configs).GetRuntimeProperties(); - var pairs = new List(properties.Count()); - var parents = new Dictionary(properties.Count()); + var properties = typeof(Configs).GetRuntimeProperties().ToArray(); + var pairs = new List(properties.Length); + var parents = new Dictionary(properties.Length); + + // Cache attributes to avoid repeated reflection calls + var attributes = new ConcurrentDictionary(); // Iterate over each property foreach (var property in properties) @@ -93,23 +97,22 @@ public ISearchable[] SearchItems(string searchingText) if (string.IsNullOrEmpty(searchingText)) return Array.Empty(); var results = new HashSet(); - var enumerator = _items.Select(i => i.Searchable) - .SelectMany(GetChildren) - .OrderByDescending(i => Similarity(i.SearchingKeys, searchingText)) - .Select(GetParent) - .Distinct() - .GetEnumerator(); - - int index = 0; - var finalResults = new ISearchable[MaxResultLength]; - while (enumerator.MoveNext() && index < MaxResultLength) + var finalResults = new List(MaxResultLength); + + foreach (var searchable in _items.Select(i => i.Searchable).SelectMany(GetChildren)) { - if (results.Contains(enumerator.Current)) continue; - results.Add(enumerator.Current); - finalResults[index++] = enumerator.Current; + var parent = GetParent(searchable); + if (results.Contains(parent)) continue; + + if (Similarity(searchable.SearchingKeys, searchingText) > 0) + { + results.Add(parent); + finalResults.Add(parent); + if (finalResults.Count >= MaxResultLength) break; + } } - return finalResults; + return finalResults.ToArray(); } private static ISearchable? CreateSearchable(PropertyInfo property) @@ -154,17 +157,16 @@ public ISearchable[] SearchItems(string searchingText) private static IEnumerable GetChildren(ISearchable searchable) { // Include the current searchable item - var myself = new ISearchable[] { searchable }; + yield return searchable; // If the searchable item is a CheckBoxSearch and has children, recursively get all children if (searchable is CheckBoxSearch c && c.Children != null) { - // Use SelectMany to flatten the hierarchy and include the current item - return c.Children.SelectMany(GetChildren).Concat(myself); + foreach (var child in c.Children.SelectMany(GetChildren)) + { + yield return child; + } } - - // Return the current item if there are no children - return myself; } private static ISearchable GetParent(ISearchable searchable) diff --git a/RotationSolver/UI/WelcomeWindow.cs b/RotationSolver/UI/WelcomeWindow.cs index 5c30ecaca..3be3b36b5 100644 --- a/RotationSolver/UI/WelcomeWindow.cs +++ b/RotationSolver/UI/WelcomeWindow.cs @@ -2,13 +2,14 @@ using Dalamud.Interface.Windowing; using ECommons.DalamudServices; using RotationSolver.Data; - using RotationSolver.Updaters; namespace RotationSolver.UI { internal class WelcomeWindow : Window { + private static readonly HttpClient HttpClient = new HttpClient(); + public WelcomeWindow() : base($"Welcome to Rotation Solver Reborn!", BaseFlags) { Size = new Vector2(650, 500); @@ -25,7 +26,7 @@ public WelcomeWindow() : base($"Welcome to Rotation Solver Reborn!", BaseFlags) #if DEBUG private string _assemblyVersion = "6.9.6.9"; //kekw #else - private string _assemblyVersion = typeof(RotationConfigWindow).Assembly.GetName().Version?.ToString() ?? "4.0.5.4"; + private string _assemblyVersion = typeof(RotationConfigWindow).Assembly.GetName().Version?.ToString() ?? "4.0.5.4"; #endif private string _lastSeenChangelog = Service.Config.LastSeenChangelog; @@ -43,29 +44,26 @@ private async Task GetGithubComparison() string url = $"https://api.github.com/repos/{Service.USERNAME}/{Service.REPO}/compare/{comparisonGoal}...{_assemblyVersion}"; try { - using (var client = new HttpClient()) + HttpClient.DefaultRequestHeaders.UserAgent.ParseAdd("RotationSolver"); + HttpClient.DefaultRequestHeaders.Accept.ParseAdd("application/vnd.github.v3+json"); + var response = await HttpClient.GetAsync(url); + if (response.IsSuccessStatusCode) { - client.DefaultRequestHeaders.Add("User-Agent", "RotationSolver"); - client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json"); - var response = await client.GetAsync(url); - if (response.IsSuccessStatusCode) + var content = await response.Content.ReadAsStringAsync(); + var changeLog = JsonConvert.DeserializeObject(content); + if (changeLog != null) { - var content = await response.Content.ReadAsStringAsync(); - var changeLog = JsonConvert.DeserializeObject(content); - if (changeLog != null) - { - _changeLog = changeLog; - } - else - { - Svc.Log.Error("Failed to deserialize GitHub commit comparison."); - } + _changeLog = changeLog; } else { - Svc.Log.Error($"Failed to get comparison: {response.StatusCode}"); + Svc.Log.Error("Failed to deserialize GitHub commit comparison."); } } + else + { + Svc.Log.Error($"Failed to get comparison: {response.StatusCode}"); + } } catch (Exception ex) { @@ -78,36 +76,33 @@ private async Task GetNextMostRecentReleaseTag() var url = $"https://api.github.com/repos/{Service.USERNAME}/{Service.REPO}/releases"; try { - using (var client = new HttpClient()) + HttpClient.DefaultRequestHeaders.UserAgent.ParseAdd("RotationSolver"); + HttpClient.DefaultRequestHeaders.Accept.ParseAdd("application/vnd.github.v3+json"); + var response = await HttpClient.GetAsync(url); + if (response.IsSuccessStatusCode) { - client.DefaultRequestHeaders.Add("User-Agent", "RotationSolver"); - client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json"); - var response = await client.GetAsync(url); - if (response.IsSuccessStatusCode) + var content = await response.Content.ReadAsStringAsync(); + var releases = JsonConvert.DeserializeObject>(content); + var foundLatest = false; + if (releases?.Count > 0) { - var content = await response.Content.ReadAsStringAsync(); - var releases = JsonConvert.DeserializeObject>(content); - var foundLatest = false; - if (releases?.Count > 0) + foreach (var release in releases) { - foreach (var release in releases) + if (release.Prerelease) continue; + if (!foundLatest) { - if (release.Prerelease) continue; - if (!foundLatest) - { - foundLatest = true; - continue; - } - return release.TagName; + foundLatest = true; + continue; } + return release.TagName; } - return "4.1.0.0"; - } - else - { - Svc.Log.Error($"Failed to get releases: {response.StatusCode}"); - return "4.1.0.0"; } + return "4.1.0.0"; + } + else + { + Svc.Log.Error($"Failed to get releases: {response.StatusCode}"); + return "4.1.0.0"; } } catch (Exception ex) @@ -122,7 +117,8 @@ public override void Draw() var windowWidth = ImGui.GetWindowWidth(); // Centered title var text = UiString.WelcomeWindow_Header.GetDescription(); - ImGui.PushFont(FontManager.GetFont(ImGui.GetFontSize() + 10)); + var fontSize = ImGui.GetFontSize(); + ImGui.PushFont(FontManager.GetFont(fontSize + 10)); var textSize = ImGui.CalcTextSize(text).X; ImGuiHelper.DrawItemMiddle(() => { @@ -131,7 +127,7 @@ public override void Draw() ImGui.PopFont(); text = $"Version {_assemblyVersion}"; - ImGui.PushFont(FontManager.GetFont(ImGui.GetFontSize() + 3)); + ImGui.PushFont(FontManager.GetFont(fontSize + 3)); textSize = ImGui.CalcTextSize(text).X; ImGuiHelper.DrawItemMiddle(() => { @@ -140,7 +136,7 @@ public override void Draw() ImGui.PopFont(); text = Service.Config.FirstTimeSetupDone ? UiString.WelcomeWindow_WelcomeBack.GetDescription() : UiString.WelcomeWindow_Welcome.GetDescription(); - ImGui.PushFont(FontManager.GetFont(ImGui.GetFontSize() + 1)); + ImGui.PushFont(FontManager.GetFont(fontSize + 1)); textSize = ImGui.CalcTextSize(text).X; ImGuiHelper.DrawItemMiddle(() => { @@ -153,7 +149,7 @@ public override void Draw() if (!Service.Config.FirstTimeSetupDone) { text = UiString.WelcomeWindow_FirstTime.GetDescription(); - ImGui.PushFont(FontManager.GetFont(ImGui.GetFontSize() + 3)); + ImGui.PushFont(FontManager.GetFont(fontSize + 3)); textSize = ImGui.CalcTextSize(text).X; ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudOrange); ImGui.TextWrapped(text); @@ -176,7 +172,7 @@ public override void Draw() } text = UiString.WelcomeWindow_FirstTime2.GetDescription(); - ImGui.PushFont(FontManager.GetFont(ImGui.GetFontSize() + 2)); + ImGui.PushFont(FontManager.GetFont(fontSize + 2)); textSize = ImGui.CalcTextSize(text).X; ImGuiHelper.DrawItemMiddle(() => { @@ -206,7 +202,7 @@ await Task.Run(async () => DrawChangeLog(); ImGui.Separator(); - ImGui.Text($"Older changelogs are available on GitHub"); + ImGui.Text("Older changelogs are available on GitHub"); if (ImGui.Button("Open GitHub")) { System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = $"https://github.com/{Service.USERNAME}/{Service.REPO}", UseShellExecute = true }); @@ -228,11 +224,18 @@ private void DrawChangeLog() return; } - var commits = changeLog.Commits.OrderByDescending(c => c.CommitData.CommitAuthor.Date).Where(c => !c.CommitData.Message.Contains("Merge pull request")); - List authors = GetAuthorsFromChangeLogs(commits); + var commits = changeLog.Commits + .Where(c => !c.CommitData.Message.Contains("Merge pull request")) + .OrderByDescending(c => c.CommitData.CommitAuthor.Date) + .ToList(); + var authors = GetAuthorsFromChangeLogs(commits); + var commitCount = commits.Count; + var authorCount = authors.Count; + ImGui.PushFont(FontManager.GetFont(ImGui.GetFontSize() + 1)); - ImGui.Text($"You've missed {commits.Count()} changes from {authors.Count()} contributer{(authors.Count() > 1 ? "s" : "")}!"); + ImGui.Text($"You've missed {commitCount} changes from {authorCount} contributer{(authorCount > 1 ? "s" : "")}!"); ImGui.PopFont(); + foreach (var commit in commits) { ImGui.Text($"[{commit.CommitData.CommitAuthor.Date:yyyy-MM-dd}]"); @@ -253,7 +256,7 @@ private void DrawChangeLog() System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = $"https://github.com/{author}", UseShellExecute = true }); } } - //Build file stats + // Build file stats var additions = changeLog.Files.Sum(f => f.Additions); var deletions = changeLog.Files.Sum(f => f.Deletions); var files = changeLog.Files.Count; @@ -268,15 +271,12 @@ private void DrawChangeLog() private List GetAuthorsFromChangeLogs(IEnumerable commits) { - var authors = new List(); + var authors = new HashSet(); foreach (var commit in commits) { - if (!authors.Contains(commit.CommitData.CommitAuthor.Name)) - { - authors.Add(commit.CommitData.CommitAuthor.Name); - } + authors.Add(commit.CommitData.CommitAuthor.Name); } - return authors; + return authors.ToList(); } public override void OnClose() @@ -287,9 +287,10 @@ public override void OnClose() IsOpen = false; base.OnClose(); } + public override bool DrawConditions() { return Svc.ClientState.IsLoggedIn; } } -} +} \ No newline at end of file