From 9cfa81c92d54cf1d8f8d8c08916ecabf316358eb Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Sun, 7 Dec 2025 14:57:28 +0100 Subject: [PATCH 01/18] Remove unused packages --- Dalamud/Dalamud.csproj | 3 --- Directory.Packages.props | 3 --- 2 files changed, 6 deletions(-) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 1c16891b7..a13df8cae 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -84,11 +84,8 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/Directory.Packages.props b/Directory.Packages.props index 58e355400..a94aae7c5 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -17,11 +17,8 @@ - - - From 07f9e03010c53e2bda0422b6fada960072ff1657 Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Sun, 7 Dec 2025 15:13:35 +0100 Subject: [PATCH 02/18] Update packages --- Directory.Packages.props | 42 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index a94aae7c5..ec2e7e276 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,35 +6,35 @@ - + - + - + - + - + - + - - - - + + + + - - + + @@ -49,15 +49,15 @@ - - + + - - - - - - - + + + + + + + From 8ed1af30dfa33c892fa1b0446054e512a4d0a760 Mon Sep 17 00:00:00 2001 From: goaaats Date: Sun, 7 Dec 2025 22:55:16 +0100 Subject: [PATCH 03/18] build: 13.0.0.14 --- Dalamud/Dalamud.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index a50f12d79..a4b203406 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -6,7 +6,7 @@ XIV Launcher addon framework - 13.0.0.13 + 13.0.0.14 $(DalamudVersion) $(DalamudVersion) $(DalamudVersion) From d0110f7251d50b2a45fbc51d6a8b03662e7afa54 Mon Sep 17 00:00:00 2001 From: goaaats Date: Mon, 8 Dec 2025 20:03:22 +0100 Subject: [PATCH 04/18] Hardcode HasModifiedGameDataFiles to false for now until XL is fixed --- Dalamud/Data/DataManager.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Dalamud/Data/DataManager.cs b/Dalamud/Data/DataManager.cs index 559bd84dc..f53195a2d 100644 --- a/Dalamud/Data/DataManager.cs +++ b/Dalamud/Data/DataManager.cs @@ -84,8 +84,11 @@ internal sealed class DataManager : IInternalDisposableService, IDataManager dalamud.StartInfo.TroubleshootingPackData); // Don't fail for IndexIntegrityResult.Exception, since the check during launch has a very small timeout - this.HasModifiedGameDataFiles = - tsInfo?.IndexIntegrity is LauncherTroubleshootingInfo.IndexIntegrityResult.Failed; + // this.HasModifiedGameDataFiles = + // tsInfo?.IndexIntegrity is LauncherTroubleshootingInfo.IndexIntegrityResult.Failed; + + // TODO: Put above back when check in XL is fixed + this.HasModifiedGameDataFiles = false; if (this.HasModifiedGameDataFiles) Log.Verbose("Game data integrity check failed!\n{TsData}", dalamud.StartInfo.TroubleshootingPackData); From 5d08170333d4e460b3eeb5197e286df86d5bdffe Mon Sep 17 00:00:00 2001 From: goaaats Date: Mon, 8 Dec 2025 20:03:43 +0100 Subject: [PATCH 05/18] Keep rendering title bar buttons if one is not available clickthrough --- Dalamud/Interface/Windowing/Window.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Interface/Windowing/Window.cs b/Dalamud/Interface/Windowing/Window.cs index b0786fbb5..7ecd5e15c 100644 --- a/Dalamud/Interface/Windowing/Window.cs +++ b/Dalamud/Interface/Windowing/Window.cs @@ -864,7 +864,7 @@ public abstract class Window foreach (var button in this.allButtons) { if (this.internalIsClickthrough && !button.AvailableClickthrough) - return; + continue; Vector2 position = new(titleBarRect.Max.X - padR - buttonSize, titleBarRect.Min.Y + style.FramePadding.Y); padR += buttonSize + style.ItemInnerSpacing.X; From 24caa1cb18f47c705b6706e718a645f3d25c056f Mon Sep 17 00:00:00 2001 From: goaaats Date: Mon, 8 Dec 2025 20:05:14 +0100 Subject: [PATCH 06/18] PresetWindow.IsDefault can be JsonIgnore --- Dalamud/Interface/Windowing/Persistence/PresetModel.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Dalamud/Interface/Windowing/Persistence/PresetModel.cs b/Dalamud/Interface/Windowing/Persistence/PresetModel.cs index f7910e0b2..4ddf55e51 100644 --- a/Dalamud/Interface/Windowing/Persistence/PresetModel.cs +++ b/Dalamud/Interface/Windowing/Persistence/PresetModel.cs @@ -53,6 +53,7 @@ internal class PresetModel /// /// Gets a value indicating whether this preset is in the default state. /// + [JsonIgnore] public bool IsDefault => !this.IsPinned && !this.IsClickThrough && From 2806e59dba4562e75f7721e40fd3d2bdd3935577 Mon Sep 17 00:00:00 2001 From: goaaats Date: Mon, 8 Dec 2025 20:09:31 +0100 Subject: [PATCH 07/18] Also remove borders for dev bar, to prevent themes from causing weirdness --- Dalamud/Interface/Internal/DalamudInterface.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dalamud/Interface/Internal/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs index bf55a5486..b0fbeb6c5 100644 --- a/Dalamud/Interface/Internal/DalamudInterface.cs +++ b/Dalamud/Interface/Internal/DalamudInterface.cs @@ -669,6 +669,8 @@ internal class DalamudInterface : IInternalDisposableService { using var barColor = ImRaii.PushColor(ImGuiCol.WindowBg, new Vector4(0.060f, 0.060f, 0.060f, 0.773f)); barColor.Push(ImGuiCol.MenuBarBg, Vector4.Zero); + barColor.Push(ImGuiCol.Border, Vector4.Zero); + barColor.Push(ImGuiCol.BorderShadow, Vector4.Zero); if (ImGui.BeginMainMenuBar()) { var pluginManager = Service.Get(); From 97df73acea61ddf94c135bc37e4f402b6e5a6cab Mon Sep 17 00:00:00 2001 From: goaaats Date: Mon, 8 Dec 2025 21:00:08 +0100 Subject: [PATCH 08/18] Ensure that we don't catch mouse up events without corresponding mouse down events Fixes an issue wherein the cursor could get locked by the game if WantCaptureMouse becomes true in between down and up events --- .../InputHandler/Win32InputHandler.cs | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.cs b/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.cs index 0b2e27b57..6b26ce37d 100644 --- a/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.cs +++ b/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.cs @@ -7,6 +7,7 @@ using System.Runtime.InteropServices; using System.Text; using Dalamud.Bindings.ImGui; +using Dalamud.Console; using Dalamud.Memory; using Dalamud.Utility; @@ -37,6 +38,8 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler private readonly WndProcDelegate wndProcDelegate; private readonly nint platformNamePtr; + private readonly IConsoleVariable cvLogMouseEvents; + private ViewportHandler viewportHandler; private int mouseButtonsDown; @@ -87,6 +90,11 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler this.cursors[(int)ImGuiMouseCursor.ResizeNwse] = LoadCursorW(default, IDC.IDC_SIZENWSE); this.cursors[(int)ImGuiMouseCursor.Hand] = LoadCursorW(default, IDC.IDC_HAND); this.cursors[(int)ImGuiMouseCursor.NotAllowed] = LoadCursorW(default, IDC.IDC_NO); + + this.cvLogMouseEvents = Service.Get().AddVariable( + "imgui.log_mouse_events", + "Log mouse events to console for debugging", + false); } /// @@ -267,11 +275,23 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler case WM.WM_XBUTTONDOWN: case WM.WM_XBUTTONDBLCLK: { + if (this.cvLogMouseEvents.Value) + { + Log.Verbose( + "Handle MouseDown {Btn} WantCaptureMouse: {Want} mouseButtonsDown: {Down}", + GetButton(msg, wParam), + io.WantCaptureMouse, + this.mouseButtonsDown); + } + var button = GetButton(msg, wParam); if (io.WantCaptureMouse) { if (this.mouseButtonsDown == 0 && GetCapture() == nint.Zero) + { SetCapture(hWndCurrent); + } + this.mouseButtonsDown |= 1 << button; io.AddMouseButtonEvent(button, true); return default(LRESULT); @@ -288,12 +308,28 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler case WM.WM_MBUTTONUP: case WM.WM_XBUTTONUP: { + if (this.cvLogMouseEvents.Value) + { + Log.Verbose( + "Handle MouseUp {Btn} WantCaptureMouse: {Want} mouseButtonsDown: {Down}", + GetButton(msg, wParam), + io.WantCaptureMouse, + this.mouseButtonsDown); + } + var button = GetButton(msg, wParam); - if (io.WantCaptureMouse) + + // Need to check if we captured the button event away from the game here, otherwise the game might get + // a down event but no up event, causing the cursor to get stuck. + // Can happen if WantCaptureMouse becomes true in between down and up + if (io.WantCaptureMouse && (this.mouseButtonsDown & (1 << button)) != 0) { this.mouseButtonsDown &= ~(1 << button); if (this.mouseButtonsDown == 0 && GetCapture() == hWndCurrent) + { ReleaseCapture(); + } + io.AddMouseButtonEvent(button, false); return default(LRESULT); } From e53ccdbcc03a4931e4594491c6250395e5a3a3e5 Mon Sep 17 00:00:00 2001 From: goaaats Date: Tue, 9 Dec 2025 00:18:28 +0100 Subject: [PATCH 09/18] build: 13.0.0.15 --- Dalamud/Dalamud.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index a4b203406..5aca47e0c 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -6,7 +6,7 @@ XIV Launcher addon framework - 13.0.0.14 + 13.0.0.15 $(DalamudVersion) $(DalamudVersion) $(DalamudVersion) From b88a6bb61646d32bf2ca2df54b611f58a81a5e5b Mon Sep 17 00:00:00 2001 From: nebel <9887+nebel@users.noreply.github.com> Date: Wed, 10 Dec 2025 23:12:44 +0900 Subject: [PATCH 10/18] Always pop DalamudStandard style if pushed earlier in Draw --- Dalamud/Interface/Windowing/Window.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Dalamud/Interface/Windowing/Window.cs b/Dalamud/Interface/Windowing/Window.cs index 7ecd5e15c..ed9318e49 100644 --- a/Dalamud/Interface/Windowing/Window.cs +++ b/Dalamud/Interface/Windowing/Window.cs @@ -672,16 +672,13 @@ public abstract class Window Task.FromResult(tex)); } - if (!this.hasError) + if (isErrorStylePushed) { - this.PostDraw(); + Style.StyleModelV1.DalamudStandard.Pop(); } else { - if (isErrorStylePushed) - { - Style.StyleModelV1.DalamudStandard.Pop(); - } + this.PostDraw(); } this.PostHandlePreset(persistence); From 201c9cfcf25c578f3bb2a3964b8674708b35d634 Mon Sep 17 00:00:00 2001 From: goaaats Date: Wed, 10 Dec 2025 01:42:45 +0100 Subject: [PATCH 11/18] Use game window to calculate offsets in fallback mouse position code --- .../ImGuiBackend/InputHandler/Win32InputHandler.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.cs b/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.cs index 6b26ce37d..8417a90e5 100644 --- a/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.cs +++ b/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.cs @@ -494,7 +494,12 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler // (This is the position you can get with ::GetCursorPos() or WM_MOUSEMOVE + ::ClientToScreen(). In theory adding viewport->Pos to a client position would also be the same.) var mousePos = mouseScreenPos; if ((io.ConfigFlags & ImGuiConfigFlags.ViewportsEnable) == 0) - ClientToScreen(focusedWindow, &mousePos); + { + // Use game window, otherwise, positions are calculated based on the focused window which might not be the game. + // Leads to offsets. + ClientToScreen(this.hWnd, &mousePos); + } + io.AddMousePosEvent(mousePos.x, mousePos.y); } From a39763f161b893e5735b0dbe3bd7dde42bb38d5f Mon Sep 17 00:00:00 2001 From: goaaats Date: Wed, 10 Dec 2025 18:32:18 +0100 Subject: [PATCH 12/18] Mark preset dirty when disabling clickthrough for a window --- Dalamud/Interface/Windowing/Window.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dalamud/Interface/Windowing/Window.cs b/Dalamud/Interface/Windowing/Window.cs index ed9318e49..5a79a017a 100644 --- a/Dalamud/Interface/Windowing/Window.cs +++ b/Dalamud/Interface/Windowing/Window.cs @@ -84,7 +84,7 @@ public abstract class Window Click = _ => { this.internalIsClickthrough = false; - this.presetDirty = false; + this.presetDirty = true; ImGui.OpenPopup(AdditionsPopupName); }, Priority = int.MinValue, @@ -905,7 +905,7 @@ public abstract class Window private void DrawErrorMessage() { // TODO: Once window systems are services, offer to reload the plugin - ImGui.TextColoredWrapped(ImGuiColors.DalamudRed,Loc.Localize("WindowSystemErrorOccurred", "An error occurred while rendering this window. Please contact the developer for details.")); + ImGui.TextColoredWrapped(ImGuiColors.DalamudRed, Loc.Localize("WindowSystemErrorOccurred", "An error occurred while rendering this window. Please contact the developer for details.")); ImGuiHelpers.ScaledDummy(5); From 0b55dc3e10b1a43013fee7893ed3dd88762a2f60 Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Thu, 11 Dec 2025 22:59:50 +0100 Subject: [PATCH 13/18] Clear ImDrawListSplitter when disposing SeStringDrawState --- .../ImGuiSeStringRenderer/Internal/SeStringRenderer.cs | 2 +- .../Interface/ImGuiSeStringRenderer/SeStringDrawState.cs | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringRenderer.cs b/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringRenderer.cs index 397502b30..4a8e6517e 100644 --- a/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringRenderer.cs +++ b/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringRenderer.cs @@ -170,7 +170,7 @@ internal class SeStringRenderer : IServiceType // This also does argument validation for drawParams. Do it here. // `using var` makes a struct read-only, but we do want to modify it. - var stateStorage = new SeStringDrawState( + using var stateStorage = new SeStringDrawState( sss, drawParams, ThreadSafety.IsMainThread ? this.colorStackSetMainThread : new(this.colorStackSetMainThread.ColorTypes), diff --git a/Dalamud/Interface/ImGuiSeStringRenderer/SeStringDrawState.cs b/Dalamud/Interface/ImGuiSeStringRenderer/SeStringDrawState.cs index 5601100e9..885508bed 100644 --- a/Dalamud/Interface/ImGuiSeStringRenderer/SeStringDrawState.cs +++ b/Dalamud/Interface/ImGuiSeStringRenderer/SeStringDrawState.cs @@ -10,6 +10,7 @@ using Dalamud.Interface.Utility; using Dalamud.Utility; using FFXIVClientStructs.FFXIV.Component.GUI; + using Lumina.Text.Payloads; using Lumina.Text.ReadOnly; @@ -17,7 +18,7 @@ namespace Dalamud.Interface.ImGuiSeStringRenderer; /// Calculated values from using ImGui styles. [StructLayout(LayoutKind.Sequential)] -public unsafe ref struct SeStringDrawState +public unsafe ref struct SeStringDrawState : IDisposable { private static readonly int ChannelCount = Enum.GetValues().Length; @@ -194,6 +195,9 @@ public unsafe ref struct SeStringDrawState /// Gets the text fragments. internal List Fragments { get; } + /// + public void Dispose() => this.splitter.ClearFreeMemory(); + /// Sets the current channel in the ImGui draw list splitter. /// Channel to switch to. [MethodImpl(MethodImplOptions.AggressiveInlining)] From e100ec2abdc490838f3422bf5fd5cda695a886fd Mon Sep 17 00:00:00 2001 From: goaaats Date: Fri, 12 Dec 2025 00:57:04 +0100 Subject: [PATCH 14/18] build: 13.0.0.16 --- Dalamud/Dalamud.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 5aca47e0c..3ec3c0865 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -6,7 +6,7 @@ XIV Launcher addon framework - 13.0.0.15 + 13.0.0.16 $(DalamudVersion) $(DalamudVersion) $(DalamudVersion) From 2d096d9b334ee485764a1e00589cba65c273af3e Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Sat, 13 Dec 2025 05:05:03 +0100 Subject: [PATCH 15/18] Properly initialize GameInventoryItems (#2504) --- Dalamud/Game/Inventory/GameInventory.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dalamud/Game/Inventory/GameInventory.cs b/Dalamud/Game/Inventory/GameInventory.cs index 535b84372..5390c2707 100644 --- a/Dalamud/Game/Inventory/GameInventory.cs +++ b/Dalamud/Game/Inventory/GameInventory.cs @@ -305,7 +305,8 @@ internal class GameInventory : IInternalDisposableService private GameInventoryItem[] CreateItemsArray(int length) { var items = new GameInventoryItem[length]; - items.Initialize(); + foreach (ref var item in items.AsSpan()) + item = new(); return items; } From a1409096fdc0d882a659f1f84c83fa42646da81d Mon Sep 17 00:00:00 2001 From: goaaats Date: Mon, 15 Dec 2025 21:20:24 +0100 Subject: [PATCH 16/18] Redo SeStringRenderer deprecations --- .../Internal/SeStringRenderer.cs | 3 +-- .../ImGuiSeStringRenderer/SeStringDrawState.cs | 15 ++++----------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringRenderer.cs b/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringRenderer.cs index 4a8e6517e..f161c1868 100644 --- a/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringRenderer.cs +++ b/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringRenderer.cs @@ -162,8 +162,7 @@ internal class SeStringRenderer : IServiceType if (drawParams.Font.HasValue) font = drawParams.Font.Value; - // API14: Remove commented out code - if (ThreadSafety.IsMainThread /* && drawParams.TargetDrawList is null */ && font is null) + if (ThreadSafety.IsMainThread && drawParams.TargetDrawList is null && font is null) font = ImGui.GetFont(); if (font is null) throw new ArgumentException("Specified font is empty."); diff --git a/Dalamud/Interface/ImGuiSeStringRenderer/SeStringDrawState.cs b/Dalamud/Interface/ImGuiSeStringRenderer/SeStringDrawState.cs index 5edf60e9d..dcbe123e7 100644 --- a/Dalamud/Interface/ImGuiSeStringRenderer/SeStringDrawState.cs +++ b/Dalamud/Interface/ImGuiSeStringRenderer/SeStringDrawState.cs @@ -66,17 +66,10 @@ public unsafe ref struct SeStringDrawState : IDisposable this.drawList = ssdp.TargetDrawList.Value; this.ScreenOffset = ssdp.ScreenOffset ?? Vector2.Zero; - // API14: Remove, always throw - if (ThreadSafety.IsMainThread) - { - this.ScreenOffset = ssdp.ScreenOffset ?? ImGui.GetCursorScreenPos(); - this.FontSize = ssdp.FontSize ?? ImGui.GetFontSize(); - } - else - { - throw new ArgumentException( - $"{nameof(ssdp.FontSize)} must be set when specifying a target draw list, as it cannot be fetched from the ImGui state."); - } + this.ScreenOffset = ssdp.ScreenOffset ?? throw new ArgumentException( + $"{nameof(ssdp.ScreenOffset)} must be set when specifying a target draw list, as it cannot be fetched from the ImGui state. (GetCursorScreenPos?)"); + this.FontSize = ssdp.FontSize ?? throw new ArgumentException( + $"{nameof(ssdp.FontSize)} must be set when specifying a target draw list, as it cannot be fetched from the ImGui state."); // this.FontSize = ssdp.FontSize ?? throw new ArgumentException( // $"{nameof(ssdp.FontSize)} must be set when specifying a target draw list, as it cannot be fetched from the ImGui state."); From 20af5b40c74d882a7707906e1be034f3f76ff8d2 Mon Sep 17 00:00:00 2001 From: goaaats Date: Mon, 15 Dec 2025 21:31:25 +0100 Subject: [PATCH 17/18] Make all versioning functions internal, move to separate class --- Dalamud/EntryPoint.cs | 4 +- Dalamud/Game/ChatHandlers.cs | 6 +- Dalamud/Interface/Internal/DalamudCommands.cs | 4 +- .../Interface/Internal/DalamudInterface.cs | 8 +- .../Internal/Windows/BranchSwitcherWindow.cs | 2 +- .../Internal/Windows/ChangelogWindow.cs | 4 +- .../Data/Widgets/SeStringCreatorWidget.cs | 2 +- .../PluginInstaller/PluginInstallerWindow.cs | 8 +- .../Windows/Settings/Tabs/SettingsTabAbout.cs | 2 +- .../Internal/Windows/TitleScreenMenuWindow.cs | 2 +- Dalamud/Networking/Http/HappyHttpClient.cs | 2 +- .../Rpc/Service/ClientHelloService.cs | 2 +- Dalamud/Plugin/Internal/PluginManager.cs | 2 +- Dalamud/Plugin/Internal/Types/LocalPlugin.cs | 2 +- .../Plugin/Internal/Types/PluginRepository.cs | 8 +- Dalamud/Support/BugBait.cs | 2 +- Dalamud/Support/DalamudReleases.cs | 2 +- Dalamud/Support/Troubleshooting.cs | 6 +- Dalamud/Utility/Util.cs | 96 ---------------- Dalamud/Utility/Versioning.cs | 108 ++++++++++++++++++ 20 files changed, 142 insertions(+), 130 deletions(-) create mode 100644 Dalamud/Utility/Versioning.cs diff --git a/Dalamud/EntryPoint.cs b/Dalamud/EntryPoint.cs index 54e25b6f2..d9f6ef172 100644 --- a/Dalamud/EntryPoint.cs +++ b/Dalamud/EntryPoint.cs @@ -192,8 +192,8 @@ public sealed class EntryPoint var dalamud = new Dalamud(info, fs, configuration, mainThreadContinueEvent); Log.Information("This is Dalamud - Core: {GitHash}, CS: {CsGitHash} [{CsVersion}]", - Util.GetScmVersion(), - Util.GetGitHashClientStructs(), + Versioning.GetScmVersion(), + Versioning.GetGitHashClientStructs(), FFXIVClientStructs.ThisAssembly.Git.Commits); dalamud.WaitForUnload(); diff --git a/Dalamud/Game/ChatHandlers.cs b/Dalamud/Game/ChatHandlers.cs index b1b798a8a..279bf46e5 100644 --- a/Dalamud/Game/ChatHandlers.cs +++ b/Dalamud/Game/ChatHandlers.cs @@ -104,7 +104,7 @@ internal partial class ChatHandlers : IServiceType if (this.configuration.PrintDalamudWelcomeMsg) { - chatGui.Print(string.Format(Loc.Localize("DalamudWelcome", "Dalamud {0} loaded."), Util.GetScmVersion()) + chatGui.Print(string.Format(Loc.Localize("DalamudWelcome", "Dalamud {0} loaded."), Versioning.GetScmVersion()) + string.Format(Loc.Localize("PluginsWelcome", " {0} plugin(s) loaded."), pluginManager.InstalledPlugins.Count(x => x.IsLoaded))); } @@ -116,7 +116,7 @@ internal partial class ChatHandlers : IServiceType } } - if (string.IsNullOrEmpty(this.configuration.LastVersion) || !Util.AssemblyVersion.StartsWith(this.configuration.LastVersion)) + if (string.IsNullOrEmpty(this.configuration.LastVersion) || !Versioning.GetAssemblyVersion().StartsWith(this.configuration.LastVersion)) { var linkPayload = chatGui.AddChatLinkHandler( (_, _) => dalamudInterface.OpenPluginInstallerTo(PluginInstallerOpenKind.Changelogs)); @@ -137,7 +137,7 @@ internal partial class ChatHandlers : IServiceType Type = XivChatType.Notice, }); - this.configuration.LastVersion = Util.AssemblyVersion; + this.configuration.LastVersion = Versioning.GetAssemblyVersion(); this.configuration.QueueSave(); } diff --git a/Dalamud/Interface/Internal/DalamudCommands.cs b/Dalamud/Interface/Internal/DalamudCommands.cs index b1fdb5232..3e4a5cec6 100644 --- a/Dalamud/Interface/Internal/DalamudCommands.cs +++ b/Dalamud/Interface/Internal/DalamudCommands.cs @@ -305,12 +305,12 @@ internal class DalamudCommands : IServiceType chatGui.Print(new SeStringBuilder() .AddItalics("Dalamud:") - .AddText($" {Util.GetScmVersion()}") + .AddText($" {Versioning.GetScmVersion()}") .Build()); chatGui.Print(new SeStringBuilder() .AddItalics("FFXIVCS:") - .AddText($" {Util.GetGitHashClientStructs()}") + .AddText($" {Versioning.GetGitHashClientStructs()}") .Build()); } diff --git a/Dalamud/Interface/Internal/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs index b0fbeb6c5..be4228a81 100644 --- a/Dalamud/Interface/Internal/DalamudInterface.cs +++ b/Dalamud/Interface/Internal/DalamudInterface.cs @@ -182,7 +182,7 @@ internal class DalamudInterface : IInternalDisposableService () => Service.GetNullable()?.ToggleDevMenu(), VirtualKey.SHIFT); - if (Util.GetActiveTrack() != "release") + if (Versioning.GetActiveTrack() != "release") { titleScreenMenu.AddEntryCore( Loc.Localize("TSMDalamudDevMenu", "Developer Menu"), @@ -865,7 +865,7 @@ internal class DalamudInterface : IInternalDisposableService } ImGui.MenuItem(this.dalamud.StartInfo.GameVersion?.ToString() ?? "Unknown version", false, false); - ImGui.MenuItem($"D: {Util.GetScmVersion()} CS: {Util.GetGitHashClientStructs()}[{FFXIVClientStructs.ThisAssembly.Git.Commits}]", false, false); + ImGui.MenuItem($"D: {Versioning.GetScmVersion()} CS: {Versioning.GetGitHashClientStructs()}[{FFXIVClientStructs.ThisAssembly.Git.Commits}]", false, false); ImGui.MenuItem($"CLR: {Environment.Version}", false, false); ImGui.EndMenu(); @@ -1076,8 +1076,8 @@ internal class DalamudInterface : IInternalDisposableService { ImGui.PushFont(InterfaceManager.MonoFont); - ImGui.BeginMenu($"{Util.GetActiveTrack() ?? "???"} on {Util.GetGitBranch() ?? "???"}", false); - ImGui.BeginMenu($"{Util.GetScmVersion()}", false); + ImGui.BeginMenu($"{Versioning.GetActiveTrack() ?? "???"} on {Versioning.GetGitBranch() ?? "???"}", false); + ImGui.BeginMenu($"{Versioning.GetScmVersion()}", false); ImGui.BeginMenu(this.FrameCount.ToString("000000"), false); ImGui.BeginMenu(ImGui.GetIO().Framerate.ToString("000"), false); ImGui.BeginMenu($"W:{Util.FormatBytes(GC.GetTotalMemory(false))}", false); diff --git a/Dalamud/Interface/Internal/Windows/BranchSwitcherWindow.cs b/Dalamud/Interface/Internal/Windows/BranchSwitcherWindow.cs index 9cc14ea14..51a9c48a6 100644 --- a/Dalamud/Interface/Internal/Windows/BranchSwitcherWindow.cs +++ b/Dalamud/Interface/Internal/Windows/BranchSwitcherWindow.cs @@ -47,7 +47,7 @@ public class BranchSwitcherWindow : Window this.branches = await client.GetFromJsonAsync>(BranchInfoUrl); Debug.Assert(this.branches != null, "this.branches != null"); - var trackName = Util.GetActiveTrack(); + var trackName = Versioning.GetActiveTrack(); this.selectedBranchIndex = this.branches.IndexOf(x => x.Value.Track == trackName); if (this.selectedBranchIndex == -1) { diff --git a/Dalamud/Interface/Internal/Windows/ChangelogWindow.cs b/Dalamud/Interface/Internal/Windows/ChangelogWindow.cs index b0a910ead..44626ba31 100644 --- a/Dalamud/Interface/Internal/Windows/ChangelogWindow.cs +++ b/Dalamud/Interface/Internal/Windows/ChangelogWindow.cs @@ -147,7 +147,7 @@ internal sealed class ChangelogWindow : Window, IDisposable var pmWantsChangelog = pm?.InstalledPlugins.Any() ?? true; return (string.IsNullOrEmpty(configuration.LastChangelogMajorMinor) || (!WarrantsChangelogForMajorMinor.StartsWith(configuration.LastChangelogMajorMinor) && - Util.AssemblyVersion.StartsWith(WarrantsChangelogForMajorMinor))) && pmWantsChangelog; + Versioning.GetAssemblyVersion().StartsWith(WarrantsChangelogForMajorMinor))) && pmWantsChangelog; } /// @@ -357,7 +357,7 @@ internal sealed class ChangelogWindow : Window, IDisposable { case State.WindowFadeIn: case State.ExplainerIntro: - ImGui.TextWrapped($"Welcome to Dalamud v{Util.GetScmVersion()}!"); + ImGui.TextWrapped($"Welcome to Dalamud v{Versioning.GetScmVersion()}!"); ImGuiHelpers.ScaledDummy(5); ImGui.TextWrapped(ChangeLog); ImGuiHelpers.ScaledDummy(5); diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/SeStringCreatorWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/SeStringCreatorWidget.cs index a88f576f9..e9b4022e4 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/SeStringCreatorWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/SeStringCreatorWidget.cs @@ -144,7 +144,7 @@ internal class SeStringCreatorWidget : IDataWindowWidget new TextEntry(TextEntryType.Macro, " "), ]; - private SeStringParameter[]? localParameters = [Util.GetScmVersion()]; + private SeStringParameter[]? localParameters = [Versioning.GetScmVersion()]; private ReadOnlySeString input; private ClientLanguage? language; private Task? validImportSheetNamesTask; diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs index ac092bd25..3241015fc 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs @@ -302,7 +302,7 @@ internal class PluginInstallerWindow : Window, IDisposable this.profileManagerWidget.Reset(); - if (this.staleDalamudNewVersion == null && !Util.GetActiveTrack().IsNullOrEmpty()) + if (this.staleDalamudNewVersion == null && !Versioning.GetActiveTrack().IsNullOrEmpty()) { Service.Get().GetVersionForCurrentTrack().ContinueWith(t => { @@ -310,7 +310,7 @@ internal class PluginInstallerWindow : Window, IDisposable return; var versionInfo = t.Result; - if (versionInfo.AssemblyVersion != Util.GetScmVersion()) + if (versionInfo.AssemblyVersion != Versioning.GetScmVersion()) { this.staleDalamudNewVersion = versionInfo.AssemblyVersion; } @@ -1670,7 +1670,7 @@ internal class PluginInstallerWindow : Window, IDisposable DrawWarningIcon(); DrawLinesCentered("A new version of Dalamud is available.\n" + "Please restart the game to ensure compatibility with updated plugins.\n" + - $"old: {Util.GetScmVersion()} new: {this.staleDalamudNewVersion}"); + $"old: {Versioning.GetScmVersion()} new: {this.staleDalamudNewVersion}"); ImGuiHelpers.ScaledDummy(10); } @@ -2461,7 +2461,7 @@ internal class PluginInstallerWindow : Window, IDisposable var isOutdated = effectiveApiLevel < PluginManager.DalamudApiLevel; var isIncompatible = manifest.MinimumDalamudVersion != null && - manifest.MinimumDalamudVersion > Util.AssemblyVersionParsed; + manifest.MinimumDalamudVersion > Versioning.GetAssemblyVersionParsed(); var enableInstallButton = this.updateStatus != OperationStatus.InProgress && this.installStatus != OperationStatus.InProgress && diff --git a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs index 74b9b0fd7..4785ceb3c 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs @@ -223,7 +223,7 @@ Contribute at: https://github.com/goatcorp/Dalamud .Select(plugin => $"{plugin.Manifest.Name} by {plugin.Manifest.Author}\n") .Aggregate(string.Empty, (current, next) => $"{current}{next}"); - this.creditsText = string.Format(CreditsTextTempl, typeof(Dalamud).Assembly.GetName().Version, pluginCredits, Util.GetGitHashClientStructs()); + this.creditsText = string.Format(CreditsTextTempl, typeof(Dalamud).Assembly.GetName().Version, pluginCredits, Versioning.GetGitHashClientStructs()); var gameGui = Service.Get(); var playerState = PlayerState.Instance(); diff --git a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs index 69cdc4d28..e14dbc545 100644 --- a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs +++ b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs @@ -503,7 +503,7 @@ internal class TitleScreenMenuWindow : Window, IDisposable lssb.PushEdgeColorType(701).PushColorType(539) .Append(SeIconChar.BoxedLetterD.ToIconChar()) .PopColorType().PopEdgeColorType(); - lssb.Append($" Dalamud: {Util.GetScmVersion()}"); + lssb.Append($" Dalamud: {Versioning.GetScmVersion()}"); lssb.Append($" - {count} {(count != 1 ? "plugins" : "plugin")} loaded"); diff --git a/Dalamud/Networking/Http/HappyHttpClient.cs b/Dalamud/Networking/Http/HappyHttpClient.cs index aeed98695..c6a476fff 100644 --- a/Dalamud/Networking/Http/HappyHttpClient.cs +++ b/Dalamud/Networking/Http/HappyHttpClient.cs @@ -36,7 +36,7 @@ internal class HappyHttpClient : IInternalDisposableService { UserAgent = { - new ProductInfoHeaderValue("Dalamud", Util.AssemblyVersion), + new ProductInfoHeaderValue("Dalamud", Versioning.GetAssemblyVersion()), }, }, }; diff --git a/Dalamud/Networking/Rpc/Service/ClientHelloService.cs b/Dalamud/Networking/Rpc/Service/ClientHelloService.cs index c5a4c851a..ae8319f21 100644 --- a/Dalamud/Networking/Rpc/Service/ClientHelloService.cs +++ b/Dalamud/Networking/Rpc/Service/ClientHelloService.cs @@ -38,7 +38,7 @@ internal sealed class ClientHelloService : IInternalDisposableService return new ClientHelloResponse { ApiVersion = "1.0", - DalamudVersion = Util.GetScmVersion(), + DalamudVersion = Versioning.GetScmVersion(), GameVersion = dalamud.StartInfo.GameVersion?.ToString() ?? "Unknown", ProcessId = Environment.ProcessId, ProcessStartTime = new DateTimeOffset(Process.GetCurrentProcess().StartTime).ToUnixTimeSeconds(), diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index e2eded57c..193a2d45f 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -1790,7 +1790,7 @@ internal class PluginManager : IInternalDisposableService var updates = this.AvailablePlugins .Where(remoteManifest => plugin.Manifest.InternalName == remoteManifest.InternalName) .Where(remoteManifest => plugin.Manifest.InstalledFromUrl == remoteManifest.SourceRepo.PluginMasterUrl || !remoteManifest.SourceRepo.IsThirdParty) - .Where(remoteManifest => remoteManifest.MinimumDalamudVersion == null || Util.AssemblyVersionParsed >= remoteManifest.MinimumDalamudVersion) + .Where(remoteManifest => remoteManifest.MinimumDalamudVersion == null || Versioning.GetAssemblyVersionParsed() >= remoteManifest.MinimumDalamudVersion) .Where(remoteManifest => { var useTesting = this.UseTesting(remoteManifest); diff --git a/Dalamud/Plugin/Internal/Types/LocalPlugin.cs b/Dalamud/Plugin/Internal/Types/LocalPlugin.cs index 0197683ef..1fe18b95b 100644 --- a/Dalamud/Plugin/Internal/Types/LocalPlugin.cs +++ b/Dalamud/Plugin/Internal/Types/LocalPlugin.cs @@ -315,7 +315,7 @@ internal class LocalPlugin : IAsyncDisposable if (!this.CheckPolicy()) throw new PluginPreconditionFailedException($"Unable to load {this.Name} as a load policy forbids it"); - if (this.Manifest.MinimumDalamudVersion != null && this.Manifest.MinimumDalamudVersion > Util.AssemblyVersionParsed) + if (this.Manifest.MinimumDalamudVersion != null && this.Manifest.MinimumDalamudVersion > Versioning.GetAssemblyVersionParsed()) throw new PluginPreconditionFailedException($"Unable to load {this.Name}, Dalamud version is lower than minimum required version {this.Manifest.MinimumDalamudVersion}"); this.State = PluginState.Loading; diff --git a/Dalamud/Plugin/Internal/Types/PluginRepository.cs b/Dalamud/Plugin/Internal/Types/PluginRepository.cs index c5e703e4b..d5c1131af 100644 --- a/Dalamud/Plugin/Internal/Types/PluginRepository.cs +++ b/Dalamud/Plugin/Internal/Types/PluginRepository.cs @@ -59,7 +59,7 @@ internal class PluginRepository }, UserAgent = { - new ProductInfoHeaderValue("Dalamud", Util.AssemblyVersion), + new ProductInfoHeaderValue("Dalamud", Versioning.GetAssemblyVersion()), }, }, }; @@ -164,7 +164,7 @@ internal class PluginRepository } this.PluginMaster = pluginMaster.Where(this.IsValidManifest).ToList().AsReadOnly(); - + // API9 HACK: Force IsHide to false, we should remove that if (!this.IsThirdParty) { @@ -197,7 +197,7 @@ internal class PluginRepository Log.Error("Plugin {PluginName} in {RepoLink} has an invalid Name.", manifest.InternalName, this.PluginMasterUrl); return false; } - + // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (manifest.AssemblyVersion == null) { @@ -224,7 +224,7 @@ internal class PluginRepository request.Headers.CacheControl = new CacheControlHeaderValue { NoCache = true }; using var requestCts = new CancellationTokenSource(TimeSpan.FromSeconds(timeout)); - + return await httpClient.SendAsync(request, requestCts.Token); } } diff --git a/Dalamud/Support/BugBait.cs b/Dalamud/Support/BugBait.cs index 7ce96208c..f0a98ca98 100644 --- a/Dalamud/Support/BugBait.cs +++ b/Dalamud/Support/BugBait.cs @@ -37,7 +37,7 @@ internal static class BugBait Name = plugin.InternalName, Version = isTesting ? plugin.TestingAssemblyVersion?.ToString() : plugin.AssemblyVersion.ToString(), Platform = Util.GetHostPlatform().ToString(), - DalamudHash = Util.GetScmVersion(), + DalamudHash = Versioning.GetScmVersion(), }; if (includeException) diff --git a/Dalamud/Support/DalamudReleases.cs b/Dalamud/Support/DalamudReleases.cs index 603c77487..949ebf94a 100644 --- a/Dalamud/Support/DalamudReleases.cs +++ b/Dalamud/Support/DalamudReleases.cs @@ -38,7 +38,7 @@ internal class DalamudReleases : IServiceType /// The version info for the current track. public async Task GetVersionForCurrentTrack() { - var currentTrack = Util.GetActiveTrack(); + var currentTrack = Versioning.GetActiveTrack(); if (currentTrack.IsNullOrEmpty()) return null; diff --git a/Dalamud/Support/Troubleshooting.cs b/Dalamud/Support/Troubleshooting.cs index 88048c462..de529a29b 100644 --- a/Dalamud/Support/Troubleshooting.cs +++ b/Dalamud/Support/Troubleshooting.cs @@ -69,11 +69,11 @@ public static class Troubleshooting LoadedPlugins = pluginManager?.InstalledPlugins?.Select(x => x.Manifest as LocalPluginManifest)?.OrderByDescending(x => x.InternalName).ToArray(), PluginStates = pluginManager?.InstalledPlugins?.Where(x => !x.IsDev).ToDictionary(x => x.Manifest.InternalName, x => x.IsBanned ? "Banned" : x.State.ToString()), EverStartedLoadingPlugins = pluginManager?.InstalledPlugins.Where(x => x.HasEverStartedLoad).Select(x => x.InternalName).ToList(), - DalamudVersion = Util.GetScmVersion(), - DalamudGitHash = Util.GetGitHash() ?? "Unknown", + DalamudVersion = Versioning.GetScmVersion(), + DalamudGitHash = Versioning.GetGitHash() ?? "Unknown", GameVersion = startInfo.GameVersion?.ToString() ?? "Unknown", Language = startInfo.Language.ToString(), - BetaKey = Util.GetActiveTrack(), + BetaKey = Versioning.GetActiveTrack(), DoPluginTest = configuration.DoPluginTest, LoadAllApiLevels = pluginManager?.LoadAllApiLevels == true, InterfaceLoaded = interfaceManager?.IsReady ?? false, diff --git a/Dalamud/Utility/Util.cs b/Dalamud/Utility/Util.cs index bde113904..0ea5bbcbf 100644 --- a/Dalamud/Utility/Util.cs +++ b/Dalamud/Utility/Util.cs @@ -68,96 +68,10 @@ public static partial class Util ]; private static readonly Type GenericSpanType = typeof(Span<>); - private static string? scmVersionInternal; - private static string? gitHashInternal; - private static string? gitHashClientStructsInternal; - private static string? branchInternal; private static ulong moduleStartAddr; private static ulong moduleEndAddr; - /// - /// Gets the Dalamud version. - /// - [Api13ToDo("Remove. Make both versions here internal. Add an API somewhere.")] - public static string AssemblyVersion { get; } = - Assembly.GetAssembly(typeof(ChatHandlers))!.GetName().Version!.ToString(); - - /// - /// Gets the Dalamud version. - /// - internal static Version AssemblyVersionParsed { get; } = - Assembly.GetAssembly(typeof(ChatHandlers))!.GetName().Version!; - - /// - /// Gets the SCM Version from the assembly, or null if it cannot be found. This method will generally return - /// the git describe output for this build, which will be a raw version if this is a stable build or an - /// appropriately-annotated version if this is *not* stable. Local builds will return a `Local Build` text string. - /// - /// The SCM version of the assembly. - public static string GetScmVersion() - { - if (scmVersionInternal != null) return scmVersionInternal; - - var asm = typeof(Util).Assembly; - var attrs = asm.GetCustomAttributes(); - - return scmVersionInternal = attrs.First(a => a.Key == "SCMVersion").Value - ?? asm.GetName().Version!.ToString(); - } - - /// - /// Gets the git commit hash value from the assembly or null if it cannot be found. Will be null for Debug builds, - /// and will be suffixed with `-dirty` if in release with pending changes. - /// - /// The git hash of the assembly. - public static string? GetGitHash() - { - if (gitHashInternal != null) - return gitHashInternal; - - var asm = typeof(Util).Assembly; - var attrs = asm.GetCustomAttributes(); - - return gitHashInternal = attrs.FirstOrDefault(a => a.Key == "GitHash")?.Value ?? "N/A"; - } - - /// - /// Gets the git hash value from the assembly or null if it cannot be found. - /// - /// The git hash of the assembly. - public static string? GetGitHashClientStructs() - { - if (gitHashClientStructsInternal != null) - return gitHashClientStructsInternal; - - var asm = typeof(Util).Assembly; - var attrs = asm.GetCustomAttributes(); - - gitHashClientStructsInternal = attrs.First(a => a.Key == "GitHashClientStructs").Value; - - return gitHashClientStructsInternal; - } - - /// - /// Gets the Git branch name this version of Dalamud was built from, or null, if this is a Debug build. - /// - /// The branch name. - public static string? GetGitBranch() - { - if (branchInternal != null) - return branchInternal; - - var asm = typeof(Util).Assembly; - var attrs = asm.GetCustomAttributes(); - - var gitBranch = attrs.FirstOrDefault(a => a.Key == "GitBranch")?.Value; - if (gitBranch == null) - return null; - - return branchInternal = gitBranch; - } - /// public static unsafe string DescribeAddress(void* p) => DescribeAddress((nint)p); @@ -693,16 +607,6 @@ public static partial class Util } } - /// - /// Gets the active Dalamud track, if this instance was launched through XIVLauncher and used a version - /// downloaded from webservices. - /// - /// The name of the track, or null. - internal static string? GetActiveTrack() - { - return Environment.GetEnvironmentVariable("DALAMUD_BRANCH"); - } - /// /// Gets a random, inoffensive, human-friendly string. /// diff --git a/Dalamud/Utility/Versioning.cs b/Dalamud/Utility/Versioning.cs new file mode 100644 index 000000000..d3b30b834 --- /dev/null +++ b/Dalamud/Utility/Versioning.cs @@ -0,0 +1,108 @@ +using System.Linq; +using System.Reflection; + +namespace Dalamud.Utility; + +/// +/// Helpers to access Dalamud versioning information. +/// +internal static class Versioning +{ + private static string? scmVersionInternal; + private static string? gitHashInternal; + private static string? gitHashClientStructsInternal; + private static string? branchInternal; + + /// + /// Gets the Dalamud version. + /// + /// The raw Dalamud assembly version. + internal static string GetAssemblyVersion() => + Assembly.GetAssembly(typeof(Versioning))!.GetName().Version!.ToString(); + + /// + /// Gets the Dalamud version. + /// + /// The parsed Dalamud assembly version. + internal static Version GetAssemblyVersionParsed() => + Assembly.GetAssembly(typeof(Versioning))!.GetName().Version!; + + /// + /// Gets the SCM Version from the assembly, or null if it cannot be found. This method will generally return + /// the git describe output for this build, which will be a raw version if this is a stable build or an + /// appropriately-annotated version if this is *not* stable. Local builds will return a `Local Build` text string. + /// + /// The SCM version of the assembly. + internal static string GetScmVersion() + { + if (scmVersionInternal != null) return scmVersionInternal; + + var asm = typeof(Util).Assembly; + var attrs = asm.GetCustomAttributes(); + + return scmVersionInternal = attrs.First(a => a.Key == "SCMVersion").Value + ?? asm.GetName().Version!.ToString(); + } + + /// + /// Gets the git commit hash value from the assembly or null if it cannot be found. Will be null for Debug builds, + /// and will be suffixed with `-dirty` if in release with pending changes. + /// + /// The git hash of the assembly. + internal static string? GetGitHash() + { + if (gitHashInternal != null) + return gitHashInternal; + + var asm = typeof(Util).Assembly; + var attrs = asm.GetCustomAttributes(); + + return gitHashInternal = attrs.FirstOrDefault(a => a.Key == "GitHash")?.Value ?? "N/A"; + } + + /// + /// Gets the git hash value from the assembly or null if it cannot be found. + /// + /// The git hash of the assembly. + internal static string? GetGitHashClientStructs() + { + if (gitHashClientStructsInternal != null) + return gitHashClientStructsInternal; + + var asm = typeof(Util).Assembly; + var attrs = asm.GetCustomAttributes(); + + gitHashClientStructsInternal = attrs.First(a => a.Key == "GitHashClientStructs").Value; + + return gitHashClientStructsInternal; + } + + /// + /// Gets the Git branch name this version of Dalamud was built from, or null, if this is a Debug build. + /// + /// The branch name. + internal static string? GetGitBranch() + { + if (branchInternal != null) + return branchInternal; + + var asm = typeof(Util).Assembly; + var attrs = asm.GetCustomAttributes(); + + var gitBranch = attrs.FirstOrDefault(a => a.Key == "GitBranch")?.Value; + if (gitBranch == null) + return null; + + return branchInternal = gitBranch; + } + + /// + /// Gets the active Dalamud track, if this instance was launched through XIVLauncher and used a version + /// downloaded from webservices. + /// + /// The name of the track, or null. + internal static string? GetActiveTrack() + { + return Environment.GetEnvironmentVariable("DALAMUD_BRANCH"); + } +} From ffd99d57914a9306c47c146257801b607ed2d9b3 Mon Sep 17 00:00:00 2001 From: goaaats Date: Mon, 15 Dec 2025 21:43:52 +0100 Subject: [PATCH 18/18] Add interface to obtain versioning info --- Dalamud/Plugin/DalamudPluginInterface.cs | 25 ++++++++----------- Dalamud/Plugin/IDalamudPluginInterface.cs | 8 +++++- .../Plugin/VersionInfo/DalamudVersionInfo.cs | 11 ++++++++ .../Plugin/VersionInfo/IDalamudVersionInfo.cs | 19 ++++++++++++++ 4 files changed, 47 insertions(+), 16 deletions(-) create mode 100644 Dalamud/Plugin/VersionInfo/DalamudVersionInfo.cs create mode 100644 Dalamud/Plugin/VersionInfo/IDalamudVersionInfo.cs diff --git a/Dalamud/Plugin/DalamudPluginInterface.cs b/Dalamud/Plugin/DalamudPluginInterface.cs index 6fd9064b6..1051f908c 100644 --- a/Dalamud/Plugin/DalamudPluginInterface.cs +++ b/Dalamud/Plugin/DalamudPluginInterface.cs @@ -16,18 +16,15 @@ using Dalamud.Game.Text; using Dalamud.Game.Text.Sanitizer; using Dalamud.Interface; using Dalamud.Interface.Internal; -using Dalamud.Interface.Internal.Windows.PluginInstaller; -using Dalamud.Interface.Internal.Windows.SelfTest; -using Dalamud.Interface.Internal.Windows.Settings; using Dalamud.IoC.Internal; using Dalamud.Plugin.Internal; using Dalamud.Plugin.Internal.AutoUpdate; using Dalamud.Plugin.Internal.Types; using Dalamud.Plugin.Internal.Types.Manifest; using Dalamud.Plugin.Ipc; -using Dalamud.Plugin.Ipc.Exceptions; using Dalamud.Plugin.Ipc.Internal; -using Dalamud.Plugin.Services; +using Dalamud.Plugin.VersionInfo; +using Dalamud.Utility; using Serilog; @@ -204,11 +201,7 @@ internal sealed class DalamudPluginInterface : IDalamudPluginInterface, IDisposa return true; } - /// - /// Gets the plugin the given assembly is part of. - /// - /// The assembly to check. - /// The plugin the given assembly is part of, or null if this is a shared assembly or if this information cannot be determined. + /// public IExposedPlugin? GetPlugin(Assembly assembly) => AssemblyLoadContext.GetLoadContext(assembly) switch { @@ -216,11 +209,7 @@ internal sealed class DalamudPluginInterface : IDalamudPluginInterface, IDisposa var context => this.GetPlugin(context), }; - /// - /// Gets the plugin that loads in the given context. - /// - /// The context to check. - /// The plugin that loads in the given context, or null if this isn't a plugin's context or if this information cannot be determined. + /// public IExposedPlugin? GetPlugin(AssemblyLoadContext context) => Service.Get().InstalledPlugins.FirstOrDefault(p => p.LoadsIn(context)) switch { @@ -228,6 +217,12 @@ internal sealed class DalamudPluginInterface : IDalamudPluginInterface, IDisposa var p => new ExposedPlugin(p), }; + /// + public IDalamudVersionInfo GetDalamudVersion() + { + return new DalamudVersionInfo(Versioning.GetAssemblyVersionParsed(), Versioning.GetActiveTrack()); + } + #region IPC /// diff --git a/Dalamud/Plugin/IDalamudPluginInterface.cs b/Dalamud/Plugin/IDalamudPluginInterface.cs index d1b6977d4..92ecab006 100644 --- a/Dalamud/Plugin/IDalamudPluginInterface.cs +++ b/Dalamud/Plugin/IDalamudPluginInterface.cs @@ -15,7 +15,7 @@ using Dalamud.Plugin.Internal.Types.Manifest; using Dalamud.Plugin.Ipc; using Dalamud.Plugin.Ipc.Exceptions; using Dalamud.Plugin.Ipc.Internal; -using Dalamud.Plugin.Services; +using Dalamud.Plugin.VersionInfo; namespace Dalamud.Plugin; @@ -194,6 +194,12 @@ public interface IDalamudPluginInterface : IServiceProvider /// The plugin that loads in the given context, or null if this isn't a plugin's context or if this information cannot be determined. IExposedPlugin? GetPlugin(AssemblyLoadContext context); + /// + /// Gets information about the version of Dalamud this plugin is loaded into. + /// + /// Class containing version information. + IDalamudVersionInfo GetDalamudVersion(); + /// T GetOrCreateData(string tag, Func dataGenerator) where T : class; diff --git a/Dalamud/Plugin/VersionInfo/DalamudVersionInfo.cs b/Dalamud/Plugin/VersionInfo/DalamudVersionInfo.cs new file mode 100644 index 000000000..c87c012af --- /dev/null +++ b/Dalamud/Plugin/VersionInfo/DalamudVersionInfo.cs @@ -0,0 +1,11 @@ +namespace Dalamud.Plugin.VersionInfo; + +/// +internal class DalamudVersionInfo(Version version, string? track) : IDalamudVersionInfo +{ + /// + public Version Version { get; } = version; + + /// + public string? BetaTrack { get; } = track; +} diff --git a/Dalamud/Plugin/VersionInfo/IDalamudVersionInfo.cs b/Dalamud/Plugin/VersionInfo/IDalamudVersionInfo.cs new file mode 100644 index 000000000..e6b6a9601 --- /dev/null +++ b/Dalamud/Plugin/VersionInfo/IDalamudVersionInfo.cs @@ -0,0 +1,19 @@ +namespace Dalamud.Plugin.VersionInfo; + +/// +/// Interface exposing various information related to Dalamud versioning. +/// +public interface IDalamudVersionInfo +{ + /// + /// Gets the Dalamud version. + /// + Version Version { get; } + + /// + /// Gets the currently used beta track. + /// Please don't tell users to switch branches. They have it bad enough, fix your things instead. + /// Null if this build wasn't launched from XIVLauncher. + /// + string? BetaTrack { get; } +}