From 32b2a891b2c80c3b0da70602bfd69271401e3364 Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Sun, 28 Jun 2026 15:56:58 +0200 Subject: [PATCH 1/4] Fix nullable warnings --- PrefPro/DalamudApi.cs | 60 +++++++++++++++++++--------------------- PrefPro/GenderHandler.cs | 2 +- PrefPro/StringHandler.cs | 6 ++-- 3 files changed, 33 insertions(+), 35 deletions(-) diff --git a/PrefPro/DalamudApi.cs b/PrefPro/DalamudApi.cs index 11d8cb3..22bd348 100644 --- a/PrefPro/DalamudApi.cs +++ b/PrefPro/DalamudApi.cs @@ -1,6 +1,4 @@ -using Dalamud.Game; -using Dalamud.Game.ClientState.Objects; -using Dalamud.IoC; +using Dalamud.IoC; using Dalamud.Plugin; using Dalamud.Plugin.Services; @@ -10,32 +8,32 @@ public class DalamudApi { public static void Initialize(IDalamudPluginInterface pluginInterface) => pluginInterface.Create(); - // [PluginService] public static IAetheryteList AetheryteList { get; private set; } = null; - // [PluginService] public static IBuddyList BuddyList { get; private set; } = null; - // [PluginService] public static IChatGui ChatGui { get; private set; } = null; - [PluginService] public static IClientState ClientState { get; private set; } = null; - [PluginService] public static ICommandManager CommandManager { get; private set; } = null; - // [PluginService] public static ICondition Condition { get; private set; } = null; - [PluginService] public static IDalamudPluginInterface PluginInterface { get; private set; } = null; - // [PluginService] public static IDataManager DataManager { get; private set; } = null; - // [PluginService] public static IDtrBar DtrBar { get; private set; } = null; - // [PluginService] public static IFateTable FateTable { get; private set; } = null; - // [PluginService] public static IFlyTextGui FlyTextGui { get; private set; } = null; - [PluginService] public static IFramework Framework { get; private set; } = null; - // [PluginService] public static IGameGui GameGui { get; private set; } = null; - [PluginService] public static IGameConfig GameConfig { get; private set; } = null; - // [PluginService] public static IGameNetwork GameNetwork { get; private set; } = null; - // [PluginService] public static IGamepadState GamePadState { get; private set; } = null; - // [PluginService] public static IJobGauges JobGauges { get; private set; } = null; - // [PluginService] public static IKeyState KeyState { get; private set; } = null; - // [PluginService] public static ILibcFunction LibcFunction { get; private set; } = null; - [PluginService] public static IObjectTable ObjectTable { get; private set; } = null; - // [PluginService] public static IPartyFinderGui PartyFinderGui { get; private set; } = null; - // [PluginService] public static IPartyList PartyList { get; private set; } = null; - [PluginService] public static ISigScanner SigScanner { get; private set; } = null; - // [PluginService] public static ITargetManager TargetManager { get; private set; } = null; - // [PluginService] public static IToastGui ToastGui { get; private set; } = null; - [PluginService] public static IGameInteropProvider Hooks { get; private set; } = null; - [PluginService] public static IPluginLog PluginLog { get; private set; } = null; - // [PluginService] public static ITitleScreenMenu TitleScreenMenu { get; private set; } = null; + // [PluginService] public static IAetheryteList AetheryteList { get; private set; } = null!; + // [PluginService] public static IBuddyList BuddyList { get; private set; } = null; ! + // [PluginService] public static IChatGui ChatGui { get; private set; } = null!; + [PluginService] public static IClientState ClientState { get; private set; } = null!; + [PluginService] public static ICommandManager CommandManager { get; private set; } = null!; + // [PluginService] public static ICondition Condition { get; private set; } = null!; + [PluginService] public static IDalamudPluginInterface PluginInterface { get; private set; } = null!; + // [PluginService] public static IDataManager DataManager { get; private set; } = null!; + // [PluginService] public static IDtrBar DtrBar { get; private set; } = null!; + // [PluginService] public static IFateTable FateTable { get; private set; } = null!; + // [PluginService] public static IFlyTextGui FlyTextGui { get; private set; } = null!; + [PluginService] public static IFramework Framework { get; private set; } = null!; + // [PluginService] public static IGameGui GameGui { get; private set; } = null!; + [PluginService] public static IGameConfig GameConfig { get; private set; } = null!; + // [PluginService] public static IGameNetwork GameNetwork { get; private set; } = null!; + // [PluginService] public static IGamepadState GamePadState { get; private set; } = null!; + // [PluginService] public static IJobGauges JobGauges { get; private set; } = null!; + // [PluginService] public static IKeyState KeyState { get; private set; } = null!; + // [PluginService] public static ILibcFunction LibcFunction { get; private set; } = null!; + [PluginService] public static IObjectTable ObjectTable { get; private set; } = null!; + // [PluginService] public static IPartyFinderGui PartyFinderGui { get; private set; } = null!; + // [PluginService] public static IPartyList PartyList { get; private set; } = null!; + [PluginService] public static ISigScanner SigScanner { get; private set; } = null!; + // [PluginService] public static ITargetManager TargetManager { get; private set; } = null!; + // [PluginService] public static IToastGui ToastGui { get; private set; } = null!; + [PluginService] public static IGameInteropProvider Hooks { get; private set; } = null!; + [PluginService] public static IPluginLog PluginLog { get; private set; } = null!; + // [PluginService] public static ITitleScreenMenu TitleScreenMenu { get; private set; } = null!; } \ No newline at end of file diff --git a/PrefPro/GenderHandler.cs b/PrefPro/GenderHandler.cs index 72a3ca2..fa64b51 100644 --- a/PrefPro/GenderHandler.cs +++ b/PrefPro/GenderHandler.cs @@ -104,7 +104,7 @@ private void SetLuaVarGender(nint poolBase, int gender) private int GetCutVoGenderDetour(nint a1, nint a2) { - var originalRet = _getCutVoGenderHook.Original(a1, a2); + var originalRet = _getCutVoGenderHook!.Original(a1, a2); if (!_configuration.Enabled) return originalRet; diff --git a/PrefPro/StringHandler.cs b/PrefPro/StringHandler.cs index 7f6243a..f331ead 100644 --- a/PrefPro/StringHandler.cs +++ b/PrefPro/StringHandler.cs @@ -122,7 +122,7 @@ private bool FormatStringDetour(TextModule* thisPtr, CStringPointer input, StdDe } } fixed (byte* newInput = sb.GetViewAsSpan()) - return _formatStringHook.Original(thisPtr, newInput, localParameters, output); + return _formatStringHook!.Original(thisPtr, newInput, localParameters, output); } catch (Exception ex) { @@ -137,14 +137,14 @@ private bool FormatStringDetour(TextModule* thisPtr, CStringPointer input, StdDe } else { - var result = _formatStringHook.Original(thisPtr, input, localParameters, output); + var result = _formatStringHook!.Original(thisPtr, input, localParameters, output); raceParam.IntValue = oldRace; genderParam.IntValue = oldGender; return result; } originalFormatString: - return _formatStringHook.Original(thisPtr, input, localParameters, output); + return _formatStringHook!.Original(thisPtr, input, localParameters, output); } public void RefreshConfig() From 1752685b2c9a885965edc5062a5b36301f9635db Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Sun, 28 Jun 2026 15:57:33 +0200 Subject: [PATCH 2/4] Remove Microsoft.Extensions.ObjectPool from csproj It's provided by the Dalamud.NET.Sdk now. :) --- PrefPro/PrefPro.csproj | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/PrefPro/PrefPro.csproj b/PrefPro/PrefPro.csproj index 502bcb5..af4bb3a 100644 --- a/PrefPro/PrefPro.csproj +++ b/PrefPro/PrefPro.csproj @@ -1,4 +1,4 @@ - + 1.3.0.3 @@ -25,10 +25,6 @@ pdbonly - - - - From 1ecdea2a139356151e1253fb5d5e8ff9928a1801 Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Sun, 28 Jun 2026 16:04:44 +0200 Subject: [PATCH 3/4] Process nested payloads --- PrefPro/StringHandler.cs | 140 ++++++++++++++++++++++++++++----------- 1 file changed, 101 insertions(+), 39 deletions(-) diff --git a/PrefPro/StringHandler.cs b/PrefPro/StringHandler.cs index f331ead..121e4c8 100644 --- a/PrefPro/StringHandler.cs +++ b/PrefPro/StringHandler.cs @@ -1,5 +1,4 @@ using System; -using System.Text; using Dalamud.Hooking; using Dalamud.Utility; using FFXIVClientStructs.FFXIV.Client.System.String; @@ -74,7 +73,7 @@ private bool FormatStringDetour(TextModule* thisPtr, CStringPointer input, StdDe if (!_configuration.Enabled) goto originalFormatString; - var seString = input.AsReadOnlySeStringSpan(); + var seString = input.AsReadOnlySeString(); if (seString.IsEmpty || seString.IsTextOnly()) goto originalFormatString; @@ -104,23 +103,9 @@ private bool FormatStringDetour(TextModule* thisPtr, CStringPointer input, StdDe { foreach (var payload in seString) { - if (nameConfig.ApplyFull && ShouldHandleStringPayload(payload)) - { - sb.Append(nameConfig.NameFull); - } - else if (nameConfig.ApplyFirst && ShouldHandleSplitPayload(payload, 1)) - { - sb.Append(nameConfig.NameFirst); - } - else if (nameConfig.ApplyLast && ShouldHandleSplitPayload(payload, 2)) - { - sb.Append(nameConfig.NameLast); - } - else - { - sb.Append(payload); - } + sb.Append(ProcessPayload(payload)); } + fixed (byte* newInput = sb.GetViewAsSpan()) return _formatStringHook!.Original(thisPtr, newInput, localParameters, output); } @@ -188,25 +173,14 @@ private static NameHandlerConfig CreateConfig(Configuration config, string playe else { data.Apply = true; - - var nameFull = GetNameText(playerName, config.Name, config.FullName); - var nameFirst = GetNameText(playerName, config.Name, config.FirstName); - var nameLast = GetNameText(playerName, config.Name, config.LastName); - - data.NameFull = MakePayload(nameFull); - data.NameFirst = MakePayload(nameFirst); - data.NameLast = MakePayload(nameLast); + data.NameFull = GetNameText(playerName, config.Name, config.FullName); + data.NameFirst = GetNameText(playerName, config.Name, config.FirstName); + data.NameLast = GetNameText(playerName, config.Name, config.LastName); } return data; } - private static ReadOnlySePayload MakePayload(string text) - { - var bytes = Encoding.UTF8.GetBytes(text); - return new ReadOnlySePayload(ReadOnlySePayloadType.Text, macroCode: default, bytes); - } - private static string GetNameText(string playerName, string configName, NameSetting setting) { switch (setting) @@ -225,8 +199,96 @@ private static string GetNameText(string playerName, string configName, NameSett } } - // - private static bool ShouldHandleStringPayload(ReadOnlySePayloadSpan payload) + private ReadOnlySePayload ProcessPayload(ReadOnlySePayload input) + { + if (input.Type == ReadOnlySePayloadType.Macro) + { + using var rssb = new RentedSeStringBuilder(); + + if (_nameHandlerConfig.ApplyFull && ShouldHandleStringPayload(input)) + { + rssb.Builder + .BeginMacro(MacroCode.String) + .AppendStringExpression(_nameHandlerConfig.NameFull) + .EndMacro(); + } + else if (_nameHandlerConfig.ApplyFirst && ShouldHandleSplitPayload(input, 1)) + { + rssb.Builder + .BeginMacro(MacroCode.String) + .AppendStringExpression(_nameHandlerConfig.NameFirst) + .EndMacro(); + } + else if (_nameHandlerConfig.ApplyLast && ShouldHandleSplitPayload(input, 2)) + { + rssb.Builder + .BeginMacro(MacroCode.String) + .AppendStringExpression(_nameHandlerConfig.NameLast) + .EndMacro(); + } + else + { + rssb.Builder.BeginMacro(input.MacroCode); + + foreach (var expr in input) + { + ProcessExpression(rssb.Builder, expr); + } + + rssb.Builder.EndMacro(); + } + + foreach (var outPayload in rssb.Builder.ToReadOnlySeString()) + { + return outPayload; + } + } + + return input; + } + + private void ProcessExpression(SeStringBuilder builder, ReadOnlySeExpression expr) + { + if (expr.TryGetInt(out var intExpr)) + { + builder.AppendIntExpression(intExpr); + } + else if (expr.TryGetString(out var s)) + { + using var rssb = new RentedSeStringBuilder(); + + foreach (var payload in s) + { + rssb.Builder.Append(ProcessPayload(payload)); + } + + builder.AppendStringExpression(rssb.Builder.ToReadOnlySeString().AsSpan()); + } + else if (expr.TryGetPlaceholderExpression(out var expressionType)) + { + builder.AppendNullaryExpression((ExpressionType)expressionType); + } + else if (expr.TryGetParameterExpression(out expressionType, out var e1)) + { + builder.BeginUnaryExpression((ExpressionType)expressionType); + ProcessExpression(builder, e1); + builder.EndExpression(); + } + else if (expr.TryGetBinaryExpression(out expressionType, out e1, out var e2)) + { + builder.BeginBinaryExpression((ExpressionType)expressionType); + ProcessExpression(builder, e1); + ProcessExpression(builder, e2); + builder.EndExpression(); + } + else + { + throw new Exception($"Could not process expression {expr}"); + } + } + + // + private static bool ShouldHandleStringPayload(ReadOnlySePayload payload) { return payload.Type == ReadOnlySePayloadType.Macro && payload.MacroCode == MacroCode.String @@ -237,8 +299,8 @@ private static bool ShouldHandleStringPayload(ReadOnlySePayloadSpan payload) && gstrIndex == 1; } - // , ,index)> - private static bool ShouldHandleSplitPayload(ReadOnlySePayloadSpan payload, int splitIndex) + // , ,index)> + private static bool ShouldHandleSplitPayload(ReadOnlySePayload payload, int splitIndex) { if (payload.Type == ReadOnlySePayloadType.Macro && payload.MacroCode == MacroCode.Split @@ -261,9 +323,9 @@ public class NameHandlerConfig public bool ApplyFull; public bool ApplyFirst; public bool ApplyLast; - public ReadOnlySePayload? NameFull; - public ReadOnlySePayload? NameFirst; - public ReadOnlySePayload? NameLast; + public string? NameFull; + public string? NameFirst; + public string? NameLast; public static readonly NameHandlerConfig None = new() { From a5fb5c74437f4ce5e3f879ce7adfec0622ebc731 Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Sun, 28 Jun 2026 16:20:27 +0200 Subject: [PATCH 4/4] Bump .NET version for CI builds --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index eec99ae..ecf25f2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: '9.x.x' + dotnet-version: '10.x.x' - name: Restore dependencies run: dotnet restore - name: Download Dalamud