acdream/tests/AcDream.App.Tests/UI/Layout/RetailLayoutFixtureGenerator.cs
Erik 66bdae7a83 feat(ui): port retail dialog factory lifecycle
Replace the single mutable confirmation service with retail's property-backed DialogFactory model: fresh DAT roots, context ids, queue groups, priority preemption, callback/close-notice ordering, and context cancellation. Route /die, server confirmation aborts, and guarded item use through focused semantic owners.

Co-Authored-By: Codex <codex@openai.com>
2026-07-13 16:30:05 +02:00

114 lines
4.5 KiB
C#

using System.Runtime.CompilerServices;
using System.Text.Json;
using AcDream.App.UI.Layout;
using DatReaderWriter;
using DatReaderWriter.Options;
using EnumIDMap = DatReaderWriter.DBObjs.EnumIDMap;
namespace AcDream.App.Tests.UI.Layout;
/// <summary>
/// Regenerates every committed retail layout fixture from production portal.dat.
/// The test is inert unless <c>ACDREAM_REGENERATE_UI_FIXTURES=1</c> is set, keeping
/// normal test runs deterministic and dat-independent.
/// </summary>
public sealed class RetailLayoutFixtureGenerator
{
private static readonly (uint Id, string FileName)[] Layouts =
{
(0x21000006u, "chat_21000006.json"),
(0x21000016u, "toolbar_21000016.json"),
(0x21000023u, "inventory_21000023.json"),
(0x21000024u, "paperdoll_21000024.json"),
(0x2100002Eu, "character_2100002E.json"),
(0x2100006Cu, "vitals_2100006C.json"),
(0x21000072u, "powerbar_21000072.json"),
(0x21000073u, "combat_21000073.json"),
(0x21000074u, "radar_21000074.json"),
};
[Fact]
public void RegenerateAllRetailFixtures_WhenExplicitlyRequested()
{
if (!string.Equals(
Environment.GetEnvironmentVariable("ACDREAM_REGENERATE_UI_FIXTURES"),
"1",
StringComparison.Ordinal))
{
return;
}
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
"Documents",
"Asheron's Call");
using var dats = new DatCollection(datDir, DatAccessType.Read);
uint masterDid = (uint)dats.Portal.Header.MasterMapId;
Assert.True(dats.Portal.TryGet<EnumIDMap>(masterDid, out var master));
Assert.True(master!.ClientEnumToID.TryGetValue(5u, out uint uiMapDid));
Assert.True(dats.Portal.TryGet<EnumIDMap>(uiMapDid, out var uiMap));
Assert.True(uiMap!.ClientEnumToID.TryGetValue(2u, out uint dialogsLayoutDid));
var dialogs = LayoutImporter.ImportInfos(
dats,
dialogsLayoutDid,
RetailDialogFactory.RootElementId(RetailDialogType.Confirmation));
Assert.NotNull(dialogs);
var dialogsJson = JsonSerializer.Serialize(dialogs, new JsonSerializerOptions
{
IncludeFields = true,
WriteIndented = true,
});
File.WriteAllText(
Path.Combine(FixtureDirectory(), $"dialogs_{dialogsLayoutDid:X8}.json"),
dialogsJson);
const uint smartboxLayoutDid = 0x2100000Fu;
var fps = LayoutImporter.ImportInfos(
dats,
smartboxLayoutDid,
0x10000047u);
Assert.NotNull(fps);
Assert.Equal(0x4000001Au, fps!.FontDid);
var fpsStrings = new DatStringResolver(dats);
Assert.Equal("FPS: ", fpsStrings.Resolve(0x23000001u, 0x0DCFFF73u, 0));
Assert.Equal("\nDEG: ", fpsStrings.Resolve(0x23000001u, 0x0DCFFF73u, 1));
var fpsJson = JsonSerializer.Serialize(fps, new JsonSerializerOptions
{
IncludeFields = true,
WriteIndented = true,
});
File.WriteAllText(
Path.Combine(FixtureDirectory(), $"smartbox_fps_{smartboxLayoutDid:X8}.json"),
fpsJson);
foreach (var (layoutId, fileName) in Layouts)
{
var info = LayoutImporter.ImportInfos(dats, layoutId);
Assert.NotNull(info);
if (layoutId == CombatUiController.LayoutId)
{
var labels = CombatUiLabels.Resolve(info, new DatStringResolver(dats));
Assert.Equal("Speed", labels.Speed);
Assert.Equal("Power", labels.Power);
Assert.Equal("Repeat Attacks", labels.RepeatAttacks);
Assert.Equal("Auto Target", labels.AutoTarget);
Assert.Equal("Keep in View", labels.KeepInView);
Assert.Equal("High", labels.High);
Assert.Equal("Medium", labels.Medium);
Assert.Equal("Low", labels.Low);
}
var json = JsonSerializer.Serialize(info, new JsonSerializerOptions
{
IncludeFields = true,
WriteIndented = true,
});
File.WriteAllText(Path.Combine(FixtureDirectory(), fileName), json);
}
}
private static string FixtureDirectory([CallerFilePath] string thisFile = "")
=> Path.Combine(Path.GetDirectoryName(thisFile)!, "fixtures");
}