181 lines
7.1 KiB
C#
181 lines
7.1 KiB
C#
using System.IO;
|
|
using AcDream.App.UI;
|
|
using AcDream.App.UI.Layout;
|
|
using AcDream.Content;
|
|
using DatReaderWriter;
|
|
using DatReaderWriter.Options;
|
|
using StringTable = DatReaderWriter.DBObjs.StringTable;
|
|
|
|
namespace AcDream.App.Tests.UI.Layout;
|
|
|
|
/// <summary>
|
|
/// Installed-retail-DAT acceptance gate for LA8. Opt in with
|
|
/// <c>ACDREAM_PROBE_LIVE_MOUNT=1</c>; <c>ACDREAM_DAT_DIR</c> can override the
|
|
/// ordinary Documents/Asheron's Call location. Reads the DATs read-only.
|
|
/// </summary>
|
|
public sealed class CharacterManagementLiveDatTests
|
|
{
|
|
[InstalledDatFact]
|
|
public void EnumTable5_ResolvesAndImportsTheExactRetailScreenAndDialogs()
|
|
{
|
|
string datDirectory = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
|
|
?? Path.Combine(
|
|
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
|
|
"Documents",
|
|
"Asheron's Call");
|
|
using var dats = new DatCollection(datDirectory, DatAccessType.Read);
|
|
|
|
const uint expectedLayoutDid = 0x21000004u;
|
|
uint layoutDid = RetailDataIdResolver.Resolve(
|
|
dats,
|
|
CharacterManagementUiController.RootEnum,
|
|
5u);
|
|
Assert.Equal(expectedLayoutDid, layoutDid);
|
|
Console.WriteLine(
|
|
"[LA8-DAT] category=5 enum=0x10000005 -> DID=0x21000004; "
|
|
+ "selected-root=0x1000039A");
|
|
|
|
ElementInfo rootInfo = Assert.IsType<ElementInfo>(
|
|
LayoutImporter.ImportInfos(
|
|
dats,
|
|
layoutDid,
|
|
CharacterManagementUiController.RootElementId));
|
|
Assert.Equal(800f, rootInfo.Width);
|
|
Assert.Equal(600f, rootInfo.Height);
|
|
Assert.Equal(8, rootInfo.Children.Count);
|
|
Assert.Equal(0x06007576u, rootInfo.StateMedia[""].File);
|
|
ImportedLayout screen = LayoutImporter.Build(
|
|
rootInfo,
|
|
_ => (0u, 0, 0),
|
|
null,
|
|
null,
|
|
new DatStringResolver(dats).Resolve);
|
|
|
|
var list = Assert.IsType<UiTemplateListBox>(screen.FindElement(
|
|
CharacterManagementUiController.ListElementId));
|
|
UiTemplateListEntry template = Assert.Single(list.Templates);
|
|
Assert.Equal(expectedLayoutDid, template.TemplateLayoutId);
|
|
Assert.Equal(0x100003A5u, template.TemplateElementId);
|
|
AssertButton(screen, CharacterManagementUiController.CreateElementId,
|
|
"Create Character");
|
|
AssertButton(screen, CharacterManagementUiController.EnterElementId,
|
|
"ENTER");
|
|
AssertButton(screen, CharacterManagementUiController.DeleteElementId,
|
|
"DELETE");
|
|
AssertButton(screen, CharacterManagementUiController.RestoreElementId,
|
|
"RESTORE");
|
|
Assert.DoesNotContain(
|
|
Descendants(screen.Root),
|
|
static element => element is UiViewport);
|
|
|
|
ElementInfo rowInfo = Assert.IsType<ElementInfo>(
|
|
LayoutImporter.ImportInfos(dats, layoutDid, template.TemplateElementId));
|
|
Assert.Equal(1u, rowInfo.Type);
|
|
Assert.Equal(160f, rowInfo.Width);
|
|
Assert.Equal(16f, rowInfo.Height);
|
|
Assert.Equal(0x40000009u, rowInfo.FontDid);
|
|
Assert.Equal(
|
|
[
|
|
UiButtonStateMachine.Normal,
|
|
UiButtonStateMachine.NormalRollover,
|
|
UiButtonStateMachine.NormalPressed,
|
|
UiButtonStateMachine.Highlight,
|
|
UiButtonStateMachine.HighlightRollover,
|
|
uint.MaxValue,
|
|
],
|
|
rowInfo.States.Keys.Order().ToArray());
|
|
|
|
uint dialogDid = RetailDataIdResolver.Resolve(dats, 2u, 5u);
|
|
Assert.Equal(0x2100003Cu, dialogDid);
|
|
ImportedLayout message = BuildSelected(dats, dialogDid, 0x24u);
|
|
Assert.IsType<UiDialogRoot>(message.Root);
|
|
Assert.IsType<UiText>(message.FindElement(0x3Eu));
|
|
Assert.IsType<UiButton>(message.FindElement(0x26u));
|
|
ImportedLayout delete = BuildSelected(dats, dialogDid, 0x2Cu);
|
|
Assert.IsType<UiDialogRoot>(delete.Root);
|
|
Assert.IsType<UiField>(delete.FindElement(0x2Cu));
|
|
Assert.IsType<UiButton>(delete.FindElement(0x2Eu));
|
|
Assert.IsType<UiButton>(delete.FindElement(0x2Fu));
|
|
|
|
var strings = new DatStringResolver(dats);
|
|
const uint table = 0x23000002u;
|
|
Assert.Equal("DELETE", Resolve(strings, table,
|
|
"ID_CharacterManagement_DeleteCharacterResponse"));
|
|
Assert.Equal("Please Wait", Resolve(strings, table,
|
|
"ID_CharacterManagement_PleaseWait"));
|
|
Assert.Equal("Entering World", Resolve(strings, table,
|
|
"ID_Character_EnteringWorld"));
|
|
string confirmation = Assert.IsType<string>(strings.ResolveTemplate(
|
|
table,
|
|
"ID_CharacterManagement_DeleteCharacterConfirmation",
|
|
new Dictionary<uint, string>
|
|
{
|
|
[DatStringResolver.PlayerVariable] = "Test Character",
|
|
}));
|
|
Assert.Contains("Test Character", confirmation);
|
|
Assert.Contains("'DELETE'", confirmation);
|
|
|
|
StringTable stringTable = Assert.IsType<StringTable>(dats.Get<StringTable>(table));
|
|
var deleteEntry = stringTable.Strings[
|
|
DatStringResolver.ComputeHash(
|
|
"ID_CharacterManagement_DeleteCharacterConfirmation")];
|
|
Assert.Equal([DatStringResolver.PlayerVariable], deleteEntry.Variables);
|
|
}
|
|
|
|
private static ImportedLayout BuildSelected(
|
|
IDatReaderWriter dats,
|
|
uint layoutDid,
|
|
uint rootId)
|
|
{
|
|
ElementInfo info = Assert.IsType<ElementInfo>(
|
|
LayoutImporter.ImportInfos(dats, layoutDid, rootId));
|
|
return LayoutImporter.Build(
|
|
info,
|
|
_ => (0u, 0, 0),
|
|
null,
|
|
null,
|
|
new DatStringResolver(dats).Resolve);
|
|
}
|
|
|
|
private static string Resolve(
|
|
DatStringResolver strings,
|
|
uint table,
|
|
string key) => Assert.IsType<string>(strings.Resolve(
|
|
table,
|
|
DatStringResolver.ComputeHash(key)));
|
|
|
|
private static void AssertButton(
|
|
ImportedLayout layout,
|
|
uint elementId,
|
|
string label) => Assert.Equal(
|
|
label,
|
|
Assert.IsType<UiButton>(layout.FindElement(elementId)).Label);
|
|
|
|
private static IEnumerable<UiElement> Descendants(UiElement root)
|
|
{
|
|
yield return root;
|
|
foreach (UiElement child in root.Children)
|
|
foreach (UiElement descendant in Descendants(child))
|
|
yield return descendant;
|
|
}
|
|
}
|
|
|
|
internal sealed class InstalledDatFactAttribute : FactAttribute
|
|
{
|
|
public InstalledDatFactAttribute()
|
|
{
|
|
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_LIVE_MOUNT") != "1")
|
|
{
|
|
Skip = "Set ACDREAM_PROBE_LIVE_MOUNT=1 to run the installed-DAT LA8 gate.";
|
|
return;
|
|
}
|
|
|
|
string datDirectory = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
|
|
?? Path.Combine(
|
|
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
|
|
"Documents",
|
|
"Asheron's Call");
|
|
if (!File.Exists(Path.Combine(datDirectory, "client_portal.dat")))
|
|
Skip = $"Installed client_portal.dat is required at '{datDirectory}'.";
|
|
}
|
|
}
|