Merge campaign-newline-fix: retail source-level escape normalization

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

# Conflicts:
#	docs/architecture/retail-divergence-register.md
This commit is contained in:
Erik 2026-08-17 14:21:10 +02:00
commit 70f7f72d62
16 changed files with 610 additions and 117 deletions

View file

@ -3010,10 +3010,10 @@ public sealed class RetailUiRuntime : IDisposable
});
if (text is null) return 0u; // no invented English
// The authored text stores its blank line as a literal
// "\n\n" two-character escape (live-probed) — same
// convention DatWidgetFactory/IndicatorDetailText already
// unescape for other DAT-authored strings.
text = text.Replace("\\n", "\n", StringComparison.Ordinal);
// "\n\n" two-character escape (live-probed), decoded at
// the string source (DatStringResolver →
// RetailStringEscapes, 2026-08-17 systemic round) —
// `text` arrives with real line breaks.
try
{
return DialogFactory.MakeWait(text, queueKey: 0x10000001u);
@ -4368,13 +4368,13 @@ public sealed class RetailUiRuntime : IDisposable
{
lock (_bindings.Assets.DatLock)
{
return NormalizeRetailNewlines(strings.ResolveTemplate(
stringTableId,
"ID_CharacterManagement_DeleteCharacterConfirmation",
new Dictionary<uint, string>
{
[DatStringResolver.PlayerVariable] = characterName,
})!);
return strings.ResolveTemplate(
stringTableId,
"ID_CharacterManagement_DeleteCharacterConfirmation",
new Dictionary<uint, string>
{
[DatStringResolver.PlayerVariable] = characterName,
})!;
}
}
@ -4390,16 +4390,16 @@ public sealed class RetailUiRuntime : IDisposable
confirmExit));
}
// Escape decoding (the DAT's literal two-character "\n" and friends)
// happens at the string source since the 2026-08-17 systemic round —
// DatStringResolver → RetailStringEscapes, retail's own placement — so
// this is a plain key-hash resolve. The former NormalizeRetailNewlines
// consumer copy is retired (double-decoding corrupts an authored "\\n").
private static string? ResolveCharacterManagementString(
DatStringResolver strings,
uint tableId,
string key) =>
strings.Resolve(tableId, DatStringResolver.ComputeHash(key)) is { } value
? NormalizeRetailNewlines(value)
: null;
private static string NormalizeRetailNewlines(string value) =>
value.Replace("\\n", "\n", StringComparison.Ordinal);
strings.Resolve(tableId, DatStringResolver.ComputeHash(key));
private void ConfigureCharacterCreation()
{