feat(chat): port retail client command families
Expand the typed client-command boundary across travel, character queries, local UI and layout controls, AFK and consent, emotes, friends, squelch and filters, and fill-components. Preserve retail packet layouts and queue ownership, import the confirmation dialog, and keep authoritative social state in Core. Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
parent
5a45a7ac7f
commit
9ea579bdd0
47 changed files with 6659 additions and 99 deletions
|
|
@ -730,6 +730,10 @@ public sealed class GameWindow : IDisposable
|
|||
public readonly AcDream.Core.Chat.TurbineChatState TurbineChat = new();
|
||||
public readonly AcDream.Core.Combat.CombatState Combat = new();
|
||||
public readonly AcDream.Core.Items.ItemManaState ItemMana = new();
|
||||
public readonly AcDream.Core.Social.FriendsState Friends = new();
|
||||
public readonly AcDream.Core.Social.SquelchState Squelch = new();
|
||||
public IReadOnlyList<(uint Id, uint Amount)> DesiredComponents { get; private set; }
|
||||
= System.Array.Empty<(uint Id, uint Amount)>();
|
||||
// Issue #11 — load static spell metadata from data/spells.csv at startup.
|
||||
// Provides Family for buff stacking (issue #6) + names + icons + tooltips
|
||||
// for the future Spellbook panel. The CSV is copied to bin/<config>/net10.0/data/
|
||||
|
|
@ -757,6 +761,7 @@ public sealed class GameWindow : IDisposable
|
|||
// when no selection. Spec: docs/superpowers/specs/2026-05-15-phase-b7-target-indicator-design.md
|
||||
private AcDream.App.UI.TargetIndicatorPanel? _targetIndicator;
|
||||
private AcDream.UI.Abstractions.Panels.Vitals.VitalsVM? _vitalsVm;
|
||||
private AcDream.UI.Abstractions.Panels.Chat.ChatVM? _retailChatVm;
|
||||
// Phase D.2b — retained host + composition runtime. Null unless ACDREAM_RETAIL_UI=1.
|
||||
private AcDream.App.UI.UiHost? _uiHost;
|
||||
private AcDream.App.UI.RetailUiRuntime? _retailUiRuntime;
|
||||
|
|
@ -2114,6 +2119,7 @@ public sealed class GameWindow : IDisposable
|
|||
coordinatesOnRadar: () => _persistedGameplay.CoordinatesOnRadar,
|
||||
uiLocked: () => _persistedGameplay.LockUI);
|
||||
var retailChatVm = new AcDream.UI.Abstractions.Panels.Chat.ChatVM(Chat, displayLimit: 200);
|
||||
_retailChatVm = retailChatVm;
|
||||
AcDream.App.UI.RetailUiPersistenceBindings? persistence = _settingsStore is null
|
||||
? null
|
||||
: new AcDream.App.UI.RetailUiPersistenceBindings(
|
||||
|
|
@ -2642,7 +2648,17 @@ public sealed class GameWindow : IDisposable
|
|||
onShortcuts: list => Shortcuts = list,
|
||||
playerGuid: () => _playerServerGuid,
|
||||
onUseDone: error => _itemInteractionController?.CompleteUse(error),
|
||||
itemMana: ItemMana);
|
||||
itemMana: ItemMana,
|
||||
onConfirmationRequest: request =>
|
||||
_retailUiRuntime?.ConfirmationDialogs?.Show(
|
||||
request.Message,
|
||||
accepted => session.SendConfirmationResponse(
|
||||
request.Type,
|
||||
request.ContextId,
|
||||
accepted)),
|
||||
friends: Friends,
|
||||
squelch: Squelch,
|
||||
onDesiredComponents: components => DesiredComponents = components);
|
||||
|
||||
// Phase I.7: subscribe to CombatState events and emit
|
||||
// retail-faithful "You hit X for Y damage" chat lines into
|
||||
|
|
@ -2717,7 +2733,62 @@ public sealed class GameWindow : IDisposable
|
|||
var turbineChat = TurbineChat;
|
||||
uint playerGuid = _playerServerGuid;
|
||||
var clientCommandController = new AcDream.App.UI.ClientCommandController(
|
||||
liveSession.SendTeleportToLifestone);
|
||||
new AcDream.App.UI.ClientCommandController.Bindings(
|
||||
TeleportToLifestone: liveSession.SendTeleportToLifestone,
|
||||
TeleportToMarketplace: liveSession.SendTeleportToMarketplace,
|
||||
TeleportToPkArena: liveSession.SendTeleportToPkArena,
|
||||
TeleportToPkLiteArena: liveSession.SendTeleportToPkLiteArena,
|
||||
TeleportToHouse: liveSession.SendTeleportToHouse,
|
||||
TeleportToMansion: liveSession.SendTeleportToMansion,
|
||||
QueryAge: liveSession.SendQueryAge,
|
||||
QueryBirth: liveSession.SendQueryBirth,
|
||||
ToggleFrameRate: ToggleRetailFrameRate,
|
||||
ToggleUiLock: () => SetRetailUiLocked(!_persistedGameplay.LockUI),
|
||||
ShowSystemMessage: text => chat.OnSystemMessage(text, 0u),
|
||||
ShowWeenieError: code => chat.OnWeenieError(code, null),
|
||||
PlayerPublicWeenieBitfield: () =>
|
||||
Objects.Get(_playerServerGuid)?.PublicWeenieBitfield,
|
||||
ClientVersion: () =>
|
||||
typeof(GameWindow).Assembly.GetName().Version?.ToString(3)
|
||||
?? "unknown",
|
||||
CurrentPosition: () => _playerController?.CellPosition,
|
||||
LastOutsideCorpsePosition: () =>
|
||||
LocalPlayer.GetPosition(0x0Eu),
|
||||
ShowConfirmation: (message, completed) =>
|
||||
_retailUiRuntime?.ConfirmationDialogs?.Show(message, completed),
|
||||
Suicide: liveSession.SendSuicide,
|
||||
ClearChat: _ => chat.Clear(),
|
||||
SaveUi: name => _retailUiRuntime?.SaveNamedLayout(name),
|
||||
LoadUi: name => _retailUiRuntime?.RestoreNamedLayout(name),
|
||||
SaveAutoUi: () => _retailUiRuntime?.SaveLayout(),
|
||||
LoadAutoUi: () => _retailUiRuntime?.RestoreLayout(),
|
||||
IsAway: () =>
|
||||
Objects.Get(_playerServerGuid)?.Properties.GetBool(0x6Eu) == true,
|
||||
SetAway: away => SetRetailAway(liveSession, away),
|
||||
SetAwayMessage: liveSession.SendSetAfkMessage,
|
||||
AcceptLootPermits: () => _persistedGameplay.AcceptLootPermits,
|
||||
SetAcceptLootPermits: SetRetailAcceptLootPermits,
|
||||
DisplayConsent: liveSession.SendDisplayConsent,
|
||||
ClearConsent: liveSession.SendClearConsent,
|
||||
RemoveConsent: liveSession.SendRemoveConsent,
|
||||
SendEmote: liveSession.SendEmote,
|
||||
Friends: Friends,
|
||||
AddFriend: liveSession.SendAddFriend,
|
||||
RemoveFriend: liveSession.SendRemoveFriend,
|
||||
ClearFriends: liveSession.SendClearFriends,
|
||||
RequestLegacyFriends: liveSession.SendLegacyFriendsListRequest,
|
||||
Squelch: Squelch,
|
||||
ModifyCharacterSquelch: liveSession.SendModifyCharacterSquelch,
|
||||
ModifyAccountSquelch: liveSession.SendModifyAccountSquelch,
|
||||
ModifyGlobalSquelch: liveSession.SendModifyGlobalSquelch,
|
||||
LastTeller: () => _retailChatVm?.LastIncomingTellSender,
|
||||
ClearDesiredComponents: () =>
|
||||
{
|
||||
liveSession.SendClearDesiredComponents();
|
||||
DesiredComponents = System.Array.Empty<(uint Id, uint Amount)>();
|
||||
},
|
||||
HasOpenVendor: () => false,
|
||||
FillComponentBuyList: (_, _) => { }));
|
||||
_commandBus.Register<AcDream.UI.Abstractions.ExecuteClientCommandCmd>(
|
||||
clientCommandController.Execute);
|
||||
_commandBus.Register<AcDream.UI.Abstractions.SendServerCommandCmd>(cmd =>
|
||||
|
|
@ -11386,6 +11457,46 @@ public sealed class GameWindow : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
private void SetRetailAway(AcDream.Core.Net.WorldSession session, bool away)
|
||||
{
|
||||
session.SendSetAfkMode(away);
|
||||
}
|
||||
|
||||
private void SetRetailAcceptLootPermits(bool enabled)
|
||||
{
|
||||
_persistedGameplay = _persistedGameplay with { AcceptLootPermits = enabled };
|
||||
_settingsVm?.SetGameplay(
|
||||
_settingsVm.GameplayDraft with { AcceptLootPermits = enabled });
|
||||
_settingsStore?.SaveGameplay(_persistedGameplay);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retail <c>ClientCommunicationSystem::DoFrameRate @ 0x005707D0</c>:
|
||||
/// flip the live display flag and persist it through the same settings
|
||||
/// path used by the Display panel.
|
||||
/// </summary>
|
||||
private void ToggleRetailFrameRate()
|
||||
{
|
||||
_persistedDisplay = _persistedDisplay with
|
||||
{
|
||||
ShowFps = !_persistedDisplay.ShowFps,
|
||||
};
|
||||
if (_settingsVm is not null)
|
||||
_settingsVm.SetDisplay(_settingsVm.DisplayDraft with
|
||||
{
|
||||
ShowFps = _persistedDisplay.ShowFps,
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
_settingsStore?.SaveDisplay(_persistedDisplay);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"settings: framerate display save failed: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void SetRetailCombatGameplay(
|
||||
AcDream.UI.Abstractions.Panels.Settings.GameplaySettings gameplay)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue