Implement retail character management screen
This commit is contained in:
parent
5535d0adac
commit
6cfab727f1
19 changed files with 2435 additions and 6 deletions
|
|
@ -16,6 +16,7 @@ using AcDream.Core.Selection;
|
|||
using AcDream.Core.Spells;
|
||||
using AcDream.Runtime;
|
||||
using AcDream.Runtime.Gameplay;
|
||||
using AcDream.Runtime.Session;
|
||||
using AcDream.Content;
|
||||
using AcDream.Core.Input;
|
||||
using AcDream.UI.Abstractions;
|
||||
|
|
@ -369,6 +370,21 @@ public sealed record KeyboardRuntimeBindings(
|
|||
InputDispatcher? Dispatcher,
|
||||
string KeyBindingsFilePath);
|
||||
|
||||
/// <summary>
|
||||
/// Borrowed LA7b character-selection projection and its generation-capturing
|
||||
/// typed command routes. App owns no roster, selection, operation, or error
|
||||
/// mirror; an absent view means the current adapter has not bound (or has
|
||||
/// already been released).
|
||||
/// </summary>
|
||||
public sealed record CharacterSelectionRuntimeBindings(
|
||||
Func<IRuntimeCharacterSelectionView?> View,
|
||||
Func<uint, RuntimeCommandResult> Highlight,
|
||||
Func<RuntimeCommandResult> Enter,
|
||||
Func<RuntimeCommandResult> RequestDelete,
|
||||
Func<RuntimeCommandResult> ConfirmDelete,
|
||||
Func<RuntimeCommandResult> Restore,
|
||||
Func<RuntimeCommandResult> Cancel);
|
||||
|
||||
public sealed record RetailUiRuntimeBindings(
|
||||
UiHost Host,
|
||||
RetailUiAssets Assets,
|
||||
|
|
@ -395,7 +411,8 @@ public sealed record RetailUiRuntimeBindings(
|
|||
BufferedUiRegistry? Plugins,
|
||||
RetailUiPersistenceBindings? Persistence,
|
||||
RetailUiProbeBindings Probe,
|
||||
KeyboardRuntimeBindings? Keyboard = null);
|
||||
KeyboardRuntimeBindings? Keyboard = null,
|
||||
CharacterSelectionRuntimeBindings? CharacterSelection = null);
|
||||
|
||||
/// <summary>
|
||||
/// Composition owner for the production retained gameplay UI. GameWindow supplies
|
||||
|
|
@ -483,6 +500,7 @@ public sealed class RetailUiRuntime : IDisposable
|
|||
MountVendor();
|
||||
MountSecureTrade();
|
||||
MountItemCooldowns();
|
||||
MountCharacterManagement();
|
||||
Host.WindowManager.WindowVisibilityChanged += OnWindowVisibilityChanged;
|
||||
BindToolbarPanelButtons();
|
||||
SyncToolbarWindowButtons();
|
||||
|
|
@ -577,6 +595,7 @@ public sealed class RetailUiRuntime : IDisposable
|
|||
public VendorUiController? VendorController { get; private set; }
|
||||
public OptionsPanelController? OptionsPanelController { get; private set; }
|
||||
public SocialPanelController? SocialPanelController { get; private set; }
|
||||
internal CharacterManagementUiController? CharacterManagementController { get; private set; }
|
||||
|
||||
public static RetailUiRuntime Mount(RetailUiRuntimeBindings bindings)
|
||||
{
|
||||
|
|
@ -622,6 +641,7 @@ public sealed class RetailUiRuntime : IDisposable
|
|||
ExternalContainerController?.Tick();
|
||||
SocialPanelController?.Tick();
|
||||
_itemCooldownController?.Tick();
|
||||
CharacterManagementController?.Tick();
|
||||
DialogFactory?.Tick();
|
||||
Host.Tick(deltaSeconds);
|
||||
_automation?.Tick(deltaSeconds);
|
||||
|
|
@ -788,6 +808,7 @@ public sealed class RetailUiRuntime : IDisposable
|
|||
{
|
||||
try
|
||||
{
|
||||
CharacterManagementController?.ResetSession();
|
||||
DialogFactory?.Reset();
|
||||
}
|
||||
finally
|
||||
|
|
@ -3669,6 +3690,144 @@ public sealed class RetailUiRuntime : IDisposable
|
|||
"[M4] retail secure trade panel mounted from LayoutDesc 0x2100000D.");
|
||||
}
|
||||
|
||||
private void MountCharacterManagement()
|
||||
{
|
||||
CharacterSelectionRuntimeBindings? bindings =
|
||||
_bindings.CharacterSelection;
|
||||
if (bindings is null)
|
||||
return;
|
||||
if (DialogFactory is null)
|
||||
{
|
||||
Console.WriteLine(
|
||||
"[UI] character management: retail DialogFactory is unavailable.");
|
||||
return;
|
||||
}
|
||||
|
||||
const uint stringTableId = 0x23000002u;
|
||||
uint layoutId;
|
||||
ImportedLayout? layout;
|
||||
var strings = new DatStringResolver(_bindings.Assets.Dats);
|
||||
lock (_bindings.Assets.DatLock)
|
||||
{
|
||||
// gmCharacterManagementUI's framework call passes enum
|
||||
// 0x10000005 and category/table 5, then selects root 0x1000039A.
|
||||
layoutId = RetailDataIdResolver.Resolve(
|
||||
_bindings.Assets.Dats,
|
||||
CharacterManagementUiController.RootEnum,
|
||||
5u);
|
||||
layout = layoutId == 0u
|
||||
? null
|
||||
: LayoutImporter.Import(
|
||||
_bindings.Assets.Dats,
|
||||
layoutId,
|
||||
CharacterManagementUiController.RootElementId,
|
||||
_bindings.Assets.ResolveSprite,
|
||||
_bindings.Assets.DefaultFont,
|
||||
_bindings.Assets.ResolveFont);
|
||||
}
|
||||
|
||||
if (layout is null)
|
||||
{
|
||||
Console.WriteLine(
|
||||
"[UI] character management: enum-table-5 root could not be imported.");
|
||||
return;
|
||||
}
|
||||
|
||||
string? deleteResponse;
|
||||
string? deleteConfirmationProbe;
|
||||
string? pleaseWait;
|
||||
string? enteringWorld;
|
||||
lock (_bindings.Assets.DatLock)
|
||||
{
|
||||
deleteConfirmationProbe = strings.ResolveTemplate(
|
||||
stringTableId,
|
||||
"ID_CharacterManagement_DeleteCharacterConfirmation",
|
||||
new Dictionary<uint, string>
|
||||
{
|
||||
[DatStringResolver.PlayerVariable] = string.Empty,
|
||||
});
|
||||
deleteResponse = ResolveCharacterManagementString(
|
||||
strings,
|
||||
stringTableId,
|
||||
"ID_CharacterManagement_DeleteCharacterResponse");
|
||||
pleaseWait = ResolveCharacterManagementString(
|
||||
strings,
|
||||
stringTableId,
|
||||
"ID_CharacterManagement_PleaseWait");
|
||||
enteringWorld = ResolveCharacterManagementString(
|
||||
strings,
|
||||
stringTableId,
|
||||
"ID_Character_EnteringWorld");
|
||||
}
|
||||
|
||||
if (deleteConfirmationProbe is null
|
||||
|| deleteResponse is null
|
||||
|| pleaseWait is null
|
||||
|| enteringWorld is null)
|
||||
{
|
||||
Console.WriteLine(
|
||||
"[UI] character management: required retail strings are unavailable.");
|
||||
return;
|
||||
}
|
||||
|
||||
UiElement? ResolveTemplate(uint templateLayoutId, uint templateElementId)
|
||||
{
|
||||
lock (_bindings.Assets.DatLock)
|
||||
{
|
||||
return LayoutImporter.Import(
|
||||
_bindings.Assets.Dats,
|
||||
templateLayoutId,
|
||||
templateElementId,
|
||||
_bindings.Assets.ResolveSprite,
|
||||
_bindings.Assets.DefaultFont,
|
||||
_bindings.Assets.ResolveFont)?.Root;
|
||||
}
|
||||
}
|
||||
|
||||
string ComposeDeleteConfirmation(string characterName)
|
||||
{
|
||||
lock (_bindings.Assets.DatLock)
|
||||
{
|
||||
return NormalizeRetailNewlines(strings.ResolveTemplate(
|
||||
stringTableId,
|
||||
"ID_CharacterManagement_DeleteCharacterConfirmation",
|
||||
new Dictionary<uint, string>
|
||||
{
|
||||
[DatStringResolver.PlayerVariable] = characterName,
|
||||
})!);
|
||||
}
|
||||
}
|
||||
|
||||
CharacterManagementController = CharacterManagementUiController.Bind(
|
||||
Host.Root,
|
||||
layout,
|
||||
ResolveTemplate,
|
||||
DialogFactory,
|
||||
bindings,
|
||||
new CharacterManagementUiController.DialogStrings(
|
||||
ComposeDeleteConfirmation,
|
||||
deleteResponse,
|
||||
pleaseWait,
|
||||
enteringWorld));
|
||||
|
||||
if (CharacterManagementController is null)
|
||||
return;
|
||||
Console.WriteLine(
|
||||
$"[UI] retail character management from enum table 5 "
|
||||
+ $"(0x10000005 -> 0x{layoutId:X8}, root 0x1000039A; flat list, no viewport).");
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
private void MountItemCooldowns()
|
||||
{
|
||||
ItemCooldownAssets? assets;
|
||||
|
|
@ -3712,7 +3871,11 @@ public sealed class RetailUiRuntime : IDisposable
|
|||
}
|
||||
},
|
||||
() => _itemConfirmationController?.Dispose(),
|
||||
() => _gameplayConfirmationController?.Dispose(),
|
||||
() =>
|
||||
{
|
||||
CharacterManagementController?.Dispose();
|
||||
_gameplayConfirmationController?.Dispose();
|
||||
},
|
||||
() => DialogFactory?.Dispose(),
|
||||
_panelUi.Dispose,
|
||||
Host.Dispose);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue