Merge pull request #2475 from goatcorp/api14-rollup
Some checks failed
Build Dalamud / Build on Windows (push) Has been cancelled
Build Dalamud / Check API Compatibility (push) Has been cancelled
Build Dalamud / Deploy dalamud-distrib staging (push) Has been cancelled

[api14] Rollup changes from master
This commit is contained in:
goat 2025-11-29 19:39:18 +01:00 committed by GitHub
commit a31dda7865
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 77 additions and 46 deletions

View file

@ -108,11 +108,6 @@ internal sealed class DalamudConfiguration : IInternalDisposableService
/// </summary> /// </summary>
public bool DoPluginTest { get; set; } = false; public bool DoPluginTest { get; set; } = false;
/// <summary>
/// Gets or sets a key to opt into Dalamud staging builds.
/// </summary>
public string? DalamudBetaKey { get; set; } = null;
/// <summary> /// <summary>
/// Gets or sets a list of custom repos. /// Gets or sets a list of custom repos.
/// </summary> /// </summary>
@ -278,11 +273,6 @@ internal sealed class DalamudConfiguration : IInternalDisposableService
/// </summary> /// </summary>
public bool IsResumeGameAfterPluginLoad { get; set; } = false; public bool IsResumeGameAfterPluginLoad { get; set; } = false;
/// <summary>
/// Gets or sets the kind of beta to download when <see cref="DalamudBetaKey"/> matches the server value.
/// </summary>
public string? DalamudBetaKind { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether any plugin should be loaded when the game is started. /// Gets or sets a value indicating whether any plugin should be loaded when the game is started.
/// It is reset immediately when read. /// It is reset immediately when read.

View file

@ -41,7 +41,7 @@ internal sealed class DataManager : IInternalDisposableService, IDataManager
try try
{ {
Log.Verbose("Starting data load..."); Log.Verbose("Starting data load...");
using (Timings.Start("Lumina Init")) using (Timings.Start("Lumina Init"))
{ {
var luminaOptions = new LuminaOptions var luminaOptions = new LuminaOptions
@ -53,12 +53,25 @@ internal sealed class DataManager : IInternalDisposableService, IDataManager
DefaultExcelLanguage = this.Language.ToLumina(), DefaultExcelLanguage = this.Language.ToLumina(),
}; };
this.GameData = new( try
Path.Combine(Path.GetDirectoryName(Environment.ProcessPath)!, "sqpack"),
luminaOptions)
{ {
StreamPool = new(), this.GameData = new(
}; Path.Combine(Path.GetDirectoryName(Environment.ProcessPath)!, "sqpack"),
luminaOptions)
{
StreamPool = new(),
};
}
catch (Exception ex)
{
Log.Error(ex, "Lumina GameData init failed");
Util.Fatal(
"Dalamud could not read required game data files. This likely means your game installation is corrupted or incomplete.\n\n" +
"Please repair your installation by right-clicking the login button in XIVLauncher and choosing \"Repair game files\".",
"Dalamud");
return;
}
Log.Information("Lumina is ready: {0}", this.GameData.DataPath); Log.Information("Lumina is ready: {0}", this.GameData.DataPath);
@ -71,7 +84,7 @@ internal sealed class DataManager : IInternalDisposableService, IDataManager
dalamud.StartInfo.TroubleshootingPackData); dalamud.StartInfo.TroubleshootingPackData);
this.HasModifiedGameDataFiles = this.HasModifiedGameDataFiles =
tsInfo?.IndexIntegrity is LauncherTroubleshootingInfo.IndexIntegrityResult.Failed or LauncherTroubleshootingInfo.IndexIntegrityResult.Exception; tsInfo?.IndexIntegrity is LauncherTroubleshootingInfo.IndexIntegrityResult.Failed or LauncherTroubleshootingInfo.IndexIntegrityResult.Exception;
if (this.HasModifiedGameDataFiles) if (this.HasModifiedGameDataFiles)
Log.Verbose("Game data integrity check failed!\n{TsData}", dalamud.StartInfo.TroubleshootingPackData); Log.Verbose("Game data integrity check failed!\n{TsData}", dalamud.StartInfo.TroubleshootingPackData);
} }
@ -130,7 +143,7 @@ internal sealed class DataManager : IInternalDisposableService, IDataManager
#region Lumina Wrappers #region Lumina Wrappers
/// <inheritdoc/> /// <inheritdoc/>
public ExcelSheet<T> GetExcelSheet<T>(ClientLanguage? language = null, string? name = null) where T : struct, IExcelRow<T> public ExcelSheet<T> GetExcelSheet<T>(ClientLanguage? language = null, string? name = null) where T : struct, IExcelRow<T>
=> this.Excel.GetSheet<T>(language?.ToLumina(), name); => this.Excel.GetSheet<T>(language?.ToLumina(), name);
/// <inheritdoc/> /// <inheritdoc/>
@ -138,7 +151,7 @@ internal sealed class DataManager : IInternalDisposableService, IDataManager
=> this.Excel.GetSubrowSheet<T>(language?.ToLumina(), name); => this.Excel.GetSubrowSheet<T>(language?.ToLumina(), name);
/// <inheritdoc/> /// <inheritdoc/>
public FileResource? GetFile(string path) public FileResource? GetFile(string path)
=> this.GetFile<FileResource>(path); => this.GetFile<FileResource>(path);
/// <inheritdoc/> /// <inheritdoc/>
@ -161,7 +174,7 @@ internal sealed class DataManager : IInternalDisposableService, IDataManager
: Task.FromException<T>(new FileNotFoundException("The file could not be found.")); : Task.FromException<T>(new FileNotFoundException("The file could not be found."));
/// <inheritdoc/> /// <inheritdoc/>
public bool FileExists(string path) public bool FileExists(string path)
=> this.GameData.FileExists(path); => this.GameData.FileExists(path);
#endregion #endregion

View file

@ -113,7 +113,7 @@ internal sealed unsafe class DalamudAtkTweaks : IInternalDisposableService
private void AtkUnitBaseReceiveGlobalEventDetour(AtkUnitBase* thisPtr, AtkEventType eventType, int eventParam, AtkEvent* atkEvent, AtkEventData* atkEventData) private void AtkUnitBaseReceiveGlobalEventDetour(AtkUnitBase* thisPtr, AtkEventType eventType, int eventParam, AtkEvent* atkEvent, AtkEventData* atkEventData)
{ {
// 3 == Close // 3 == Close
if (eventType == AtkEventType.InputReceived && WindowSystem.HasAnyWindowSystemFocus && atkEventData != null && *(int*)atkEventData == 3 && this.configuration.IsFocusManagementEnabled) if (eventType == AtkEventType.InputReceived && WindowSystem.ShouldInhibitAtkCloseEvents && atkEventData != null && *(int*)atkEventData == 3 && this.configuration.IsFocusManagementEnabled)
{ {
Log.Verbose($"Cancelling global event SendHotkey command due to WindowSystem {WindowSystem.FocusedWindowSystemNamespace}"); Log.Verbose($"Cancelling global event SendHotkey command due to WindowSystem {WindowSystem.FocusedWindowSystemNamespace}");
return; return;
@ -124,7 +124,7 @@ internal sealed unsafe class DalamudAtkTweaks : IInternalDisposableService
private void AgentHudOpenSystemMenuDetour(AgentHUD* thisPtr, AtkValue* atkValueArgs, uint menuSize) private void AgentHudOpenSystemMenuDetour(AgentHUD* thisPtr, AtkValue* atkValueArgs, uint menuSize)
{ {
if (WindowSystem.HasAnyWindowSystemFocus && this.configuration.IsFocusManagementEnabled) if (WindowSystem.ShouldInhibitAtkCloseEvents && this.configuration.IsFocusManagementEnabled)
{ {
Log.Verbose($"Cancelling OpenSystemMenu due to WindowSystem {WindowSystem.FocusedWindowSystemNamespace}"); Log.Verbose($"Cancelling OpenSystemMenu due to WindowSystem {WindowSystem.FocusedWindowSystemNamespace}");
return; return;

View file

@ -182,7 +182,7 @@ internal class DalamudInterface : IInternalDisposableService
() => Service<DalamudInterface>.GetNullable()?.ToggleDevMenu(), () => Service<DalamudInterface>.GetNullable()?.ToggleDevMenu(),
VirtualKey.SHIFT); VirtualKey.SHIFT);
if (!configuration.DalamudBetaKind.IsNullOrEmpty()) if (Util.GetActiveTrack() != "release")
{ {
titleScreenMenu.AddEntryCore( titleScreenMenu.AddEntryCore(
Loc.Localize("TSMDalamudDevMenu", "Developer Menu"), Loc.Localize("TSMDalamudDevMenu", "Developer Menu"),

View file

@ -1175,6 +1175,7 @@ internal partial class InterfaceManager : IInternalDisposableService
WindowSystem.HasAnyWindowSystemFocus = false; WindowSystem.HasAnyWindowSystemFocus = false;
WindowSystem.FocusedWindowSystemNamespace = string.Empty; WindowSystem.FocusedWindowSystemNamespace = string.Empty;
WindowSystem.ShouldInhibitAtkCloseEvents = false;
if (this.IsDispatchingEvents) if (this.IsDispatchingEvents)
{ {

View file

@ -6,7 +6,6 @@ using System.Net.Http.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using Dalamud.Configuration.Internal;
using Dalamud.Interface.Colors; using Dalamud.Interface.Colors;
using Dalamud.Interface.Utility; using Dalamud.Interface.Utility;
using Dalamud.Interface.Windowing; using Dalamud.Interface.Windowing;
@ -15,6 +14,8 @@ using Dalamud.Utility;
using Newtonsoft.Json; using Newtonsoft.Json;
using Serilog;
namespace Dalamud.Interface.Internal.Windows; namespace Dalamud.Interface.Internal.Windows;
/// <summary> /// <summary>
@ -47,7 +48,7 @@ public class BranchSwitcherWindow : Window
Debug.Assert(this.branches != null, "this.branches != null"); Debug.Assert(this.branches != null, "this.branches != null");
var trackName = Util.GetActiveTrack(); var trackName = Util.GetActiveTrack();
this.selectedBranchIndex = this.branches.IndexOf(x => x.Value.Track != trackName); this.selectedBranchIndex = this.branches.IndexOf(x => x.Value.Track == trackName);
if (this.selectedBranchIndex == -1) if (this.selectedBranchIndex == -1)
{ {
this.selectedBranchIndex = 0; this.selectedBranchIndex = 0;
@ -86,12 +87,9 @@ public class BranchSwitcherWindow : Window
if (ImGui.Button("Pick & Restart"u8)) if (ImGui.Button("Pick & Restart"u8))
{ {
var config = Service<DalamudConfiguration>.Get(); var newTrackName = pickedBranch.Key;
config.DalamudBetaKind = pickedBranch.Key; var newTrackKey = pickedBranch.Value.Key;
config.DalamudBetaKey = pickedBranch.Value.Key; Log.Verbose("Switching to branch {Branch} with key {Key}", newTrackName, newTrackKey);
// If we exit immediately, we need to write out the new config now
config.ForceSave();
var appData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); var appData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
var xlPath = Path.Combine(appData, "XIVLauncher", "current", "XIVLauncher.exe"); var xlPath = Path.Combine(appData, "XIVLauncher", "current", "XIVLauncher.exe");
@ -104,8 +102,8 @@ public class BranchSwitcherWindow : Window
UseShellExecute = false, UseShellExecute = false,
}; };
ps.ArgumentList.Add($"--dalamud-beta-kind={config.DalamudBetaKind}"); ps.ArgumentList.Add($"--dalamud-beta-kind={newTrackName}");
ps.ArgumentList.Add($"--dalamud-beta-key={(config.DalamudBetaKey.IsNullOrEmpty() ? "invalid" : config.DalamudBetaKey)}"); ps.ArgumentList.Add($"--dalamud-beta-key={(newTrackKey.IsNullOrEmpty() ? "invalid" : newTrackKey)}");
Process.Start(ps); Process.Start(ps);
Environment.Exit(0); Environment.Exit(0);

View file

@ -302,8 +302,7 @@ internal class PluginInstallerWindow : Window, IDisposable
this.profileManagerWidget.Reset(); this.profileManagerWidget.Reset();
var config = Service<DalamudConfiguration>.Get(); if (this.staleDalamudNewVersion == null && !Util.GetActiveTrack().IsNullOrEmpty())
if (this.staleDalamudNewVersion == null && !config.DalamudBetaKind.IsNullOrEmpty())
{ {
Service<DalamudReleases>.Get().GetVersionForCurrentTrack().ContinueWith(t => Service<DalamudReleases>.Get().GetVersionForCurrentTrack().ContinueWith(t =>
{ {
@ -311,10 +310,10 @@ internal class PluginInstallerWindow : Window, IDisposable
return; return;
var versionInfo = t.Result; var versionInfo = t.Result;
if (versionInfo.AssemblyVersion != Util.GetScmVersion() && if (versionInfo.AssemblyVersion != Util.GetScmVersion())
versionInfo.Track != "release" && {
string.Equals(versionInfo.Key, config.DalamudBetaKey, StringComparison.OrdinalIgnoreCase))
this.staleDalamudNewVersion = versionInfo.AssemblyVersion; this.staleDalamudNewVersion = versionInfo.AssemblyVersion;
}
}); });
} }
} }

View file

@ -226,6 +226,16 @@ public abstract class Window
/// </summary> /// </summary>
public bool AllowClickthrough { get; set; } = true; public bool AllowClickthrough { get; set; } = true;
/// <summary>
/// Gets a value indicating whether this window is pinned.
/// </summary>
public bool IsPinned => this.internalIsPinned;
/// <summary>
/// Gets a value indicating whether this window is click-through.
/// </summary>
public bool IsClickthrough => this.internalIsClickthrough;
/// <summary> /// <summary>
/// Gets or sets a list of available title bar buttons. /// Gets or sets a list of available title bar buttons.
/// ///

View file

@ -60,6 +60,12 @@ public class WindowSystem
/// </summary> /// </summary>
public string? Namespace { get; set; } public string? Namespace { get; set; }
/// <summary>
/// Gets or sets a value indicating whether ATK close events should be inhibited while any window has focus.
/// Does not respect windows that are pinned or clickthrough.
/// </summary>
internal static bool ShouldInhibitAtkCloseEvents { get; set; }
/// <summary> /// <summary>
/// Add a window to this <see cref="WindowSystem"/>. /// Add a window to this <see cref="WindowSystem"/>.
/// The window system doesn't own your window, it just renders it /// The window system doesn't own your window, it just renders it
@ -130,7 +136,7 @@ public class WindowSystem
window.DrawInternal(flags, persistence); window.DrawInternal(flags, persistence);
} }
var focusedWindow = this.windows.FirstOrDefault(window => window.IsFocused && window.RespectCloseHotkey); var focusedWindow = this.windows.FirstOrDefault(window => window.IsFocused);
this.HasAnyFocus = focusedWindow != default; this.HasAnyFocus = focusedWindow != default;
if (this.HasAnyFocus) if (this.HasAnyFocus)
@ -155,6 +161,11 @@ public class WindowSystem
} }
} }
ShouldInhibitAtkCloseEvents |= this.windows.Any(w => w.IsFocused &&
w.RespectCloseHotkey &&
!w.IsPinned &&
!w.IsClickthrough);
if (hasNamespace) if (hasNamespace)
ImGui.PopID(); ImGui.PopID();
} }

View file

@ -3,6 +3,7 @@ using System.Threading.Tasks;
using Dalamud.Configuration.Internal; using Dalamud.Configuration.Internal;
using Dalamud.Networking.Http; using Dalamud.Networking.Http;
using Dalamud.Utility;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -15,7 +16,7 @@ namespace Dalamud.Support;
internal class DalamudReleases : IServiceType internal class DalamudReleases : IServiceType
{ {
private const string VersionInfoUrl = "https://kamori.goats.dev/Dalamud/Release/VersionInfo?track={0}"; private const string VersionInfoUrl = "https://kamori.goats.dev/Dalamud/Release/VersionInfo?track={0}";
private readonly HappyHttpClient httpClient; private readonly HappyHttpClient httpClient;
private readonly DalamudConfiguration config; private readonly DalamudConfiguration config;
@ -30,20 +31,24 @@ internal class DalamudReleases : IServiceType
this.httpClient = httpClient; this.httpClient = httpClient;
this.config = config; this.config = config;
} }
/// <summary> /// <summary>
/// Get the latest version info for the current track. /// Get the latest version info for the current track.
/// </summary> /// </summary>
/// <returns>The version info for the current track.</returns> /// <returns>The version info for the current track.</returns>
public async Task<DalamudVersionInfo> GetVersionForCurrentTrack() public async Task<DalamudVersionInfo?> GetVersionForCurrentTrack()
{ {
var url = string.Format(VersionInfoUrl, [this.config.DalamudBetaKind]); var currentTrack = Util.GetActiveTrack();
if (currentTrack.IsNullOrEmpty())
return null;
var url = string.Format(VersionInfoUrl, [currentTrack]);
var response = await this.httpClient.SharedHttpClient.GetAsync(url); var response = await this.httpClient.SharedHttpClient.GetAsync(url);
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync(); var content = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<DalamudVersionInfo>(content); return JsonConvert.DeserializeObject<DalamudVersionInfo>(content);
} }
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "laziness")] [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "laziness")]
public class DalamudVersionInfo public class DalamudVersionInfo
{ {

View file

@ -73,7 +73,7 @@ public static class Troubleshooting
DalamudGitHash = Util.GetGitHash() ?? "Unknown", DalamudGitHash = Util.GetGitHash() ?? "Unknown",
GameVersion = startInfo.GameVersion?.ToString() ?? "Unknown", GameVersion = startInfo.GameVersion?.ToString() ?? "Unknown",
Language = startInfo.Language.ToString(), Language = startInfo.Language.ToString(),
BetaKey = configuration.DalamudBetaKey, BetaKey = Util.GetActiveTrack(),
DoPluginTest = configuration.DoPluginTest, DoPluginTest = configuration.DoPluginTest,
LoadAllApiLevels = pluginManager?.LoadAllApiLevels == true, LoadAllApiLevels = pluginManager?.LoadAllApiLevels == true,
InterfaceLoaded = interfaceManager?.IsReady ?? false, InterfaceLoaded = interfaceManager?.IsReady ?? false,

View file

@ -6,6 +6,10 @@
<PlatformTarget>x64</PlatformTarget> <PlatformTarget>x64</PlatformTarget>
<Platforms>x64</Platforms> <Platforms>x64</Platforms>
<LangVersion>13.0</LangVersion> <LangVersion>13.0</LangVersion>
<!-- Disable Intel CET. Causes crashes on unpatched Windows 10 systems. -->
<!-- https://github.com/dotnet/runtime/issues/108589 -->
<CETCompat>false</CETCompat>
</PropertyGroup> </PropertyGroup>
<!-- Code analysis settings for all Dalamud projects. --> <!-- Code analysis settings for all Dalamud projects. -->

@ -1 +1 @@
Subproject commit 0769d1f180f859688f47a7a99610e9ce10da946c Subproject commit e5f586630ef06fa48d5dc0d8c0fa679323093c77