Implement retail character management screen

This commit is contained in:
Erik 2026-08-14 20:29:19 +02:00
parent 5535d0adac
commit 6cfab727f1
19 changed files with 2435 additions and 6 deletions

View file

@ -10,6 +10,7 @@ using AcDream.Core.Items;
using AcDream.Core.Net;
using AcDream.Core.Net.Messages;
using AcDream.Runtime;
using AcDream.Runtime.Session;
using AcDream.UI.Abstractions;
using Silk.NET.Windowing;
@ -37,6 +38,24 @@ internal sealed class DeferredGameRuntimeStateCommands
}
}
/// <summary>
/// Borrows the current adapter's character-selection projection. The
/// reference is deliberately not cached here: releasing or displacing the
/// exact late binding makes the next read return <see langword="null"/>,
/// while <c>CurrentGameRuntimeAdapter</c> keeps an already-borrowed reference
/// inert if disposal races the render-thread consumer.
/// </summary>
public IRuntimeCharacterSelectionView? CharacterSelection
{
get
{
lock (_gate)
return !_deactivated && _view is not null
? _view.CharacterSelection
: null;
}
}
public IDisposable Bind(
IGameRuntimeView view,
IGameRuntimeCommands commands)
@ -118,6 +137,35 @@ internal sealed class DeferredGameRuntimeStateCommands
generation,
new RuntimeAdvancementCommand(kind, statId, cost)));
// Campaign LA slice LA8: the retained character-management screen uses
// the same generation-capturing late seam as every gameplay panel. The
// screen never receives GameRuntime or WorldSession and cannot retain a
// stale generation across reconnect.
public RuntimeCommandResult CharacterSelectionHighlight(uint characterId) =>
Invoke((commands, generation) =>
commands.CharacterSelection.Highlight(generation, characterId));
public RuntimeCommandResult CharacterSelectionEnter() =>
Invoke((commands, generation) =>
commands.CharacterSelection.Enter(generation));
public RuntimeCommandResult CharacterSelectionRequestDelete() =>
Invoke((commands, generation) =>
commands.CharacterSelection.RequestDelete(generation));
public RuntimeCommandResult CharacterSelectionConfirmDelete() =>
Invoke((commands, generation) =>
commands.CharacterSelection.ConfirmDelete(generation));
public RuntimeCommandResult CharacterSelectionRestore() =>
Invoke((commands, generation) =>
commands.CharacterSelection.Restore(generation));
public RuntimeCommandResult CharacterSelectionCancel() =>
Invoke((commands, generation) =>
commands.CharacterSelection.Cancel(generation));
// ── Campaign FA slice FA4: fellowship page commands ─────────────────
// Same "capture view+commands under one generation" shape as every
// method above — a displaced session (reconnect mid-click) can never