From 6c33cc9831f358eb125b24556bf67499aae0240b Mon Sep 17 00:00:00 2001 From: "Jean-Baptiste L." Date: Fri, 1 May 2026 02:12:01 +0200 Subject: [PATCH] PlaytimeStep: match localized "/playtime" output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The step waits for the chat system message produced by /playtime, but only matched the English string "Total Play Time:". On non-English clients the message never matched and the export pipeline stalled indefinitely. Use the verbatim prefixes from LogMessage row 859 in EN/FR/DE/JP, and strip any combination of colon + whitespace (including the narrow-no-break space FR uses before its colon, and the plain ASCII space JP uses with no colon at all) when extracting the value. The same code path now handles all four languages. EN: "Total Play Time: 1 day, 2 hours, 5 minutes" FR: "Temps de jeu total : 1 jour, 18 heures, 55 minutes" DE: "Gesamtspielzeit: 1 Tag, 2 Stunden, 5 Minuten" JP: "累積プレイ時間 1日2時間5分" Verified live on a French 7.5 client; EN/DE/JP markers and separators were sourced from LogMessage row 859 via xivapi (rather than guessed), so they should match the strings the game actually emits. --- Auracite/Steps/PlaytimeStep.cs | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/Auracite/Steps/PlaytimeStep.cs b/Auracite/Steps/PlaytimeStep.cs index e3378f1..4e49d29 100644 --- a/Auracite/Steps/PlaytimeStep.cs +++ b/Auracite/Steps/PlaytimeStep.cs @@ -1,3 +1,4 @@ +using System; using Dalamud.Game.Chat; using Dalamud.Game.Text; using Dalamud.Game.Text.SeStringHandling; @@ -32,13 +33,41 @@ public string StepDescription() return "Type /playtime into the chat window."; } + // Verbatim prefixes from LogMessage row 859 in the four supported client + // languages. Any whitespace or colon between the prefix and the value is + // stripped at extraction time so the same code path handles all four. + private static readonly string[] PlaytimeMarkers = + { + "Total Play Time", // EN + "Temps de jeu total", // FR + "Gesamtspielzeit", // DE + "累積プレイ時間", // JP — note: no colon between prefix and value + }; + + private static readonly char[] MarkerSeparators = + { + ':', // EN, DE + ' ', // ASCII space + ' ', // NBSP — appears before the colon in FR + ' ', // ideographic space — possible in JP + }; + private void OnChatMessage(IHandleableChatMessage message) { + if (message.LogKind != XivChatType.SystemMessage) return; var msgString = message.Message.ToString(); - if (msgString.Contains("Total Play Time:") && message.LogKind == XivChatType.SystemMessage) + + foreach (var marker in PlaytimeMarkers) { - Plugin.package.playtime = msgString.Split(": ")[1]; // TODO: lol + var markerIdx = msgString.IndexOf(marker, StringComparison.Ordinal); + if (markerIdx < 0) continue; + + var rest = msgString[(markerIdx + marker.Length)..] + .TrimStart(MarkerSeparators) + .TrimEnd(); + Plugin.package.playtime = rest; Completed?.Invoke(); + return; } } }