feat(chat): Campaign CH slice CH4 — command registry completion
Brings acdream's / and @ command parsing to parity with the complete
retail registry (130 registered verbs + 22 unregistered GetChannelID
fallback tags = 152 client-parsed verbs), per
docs/research/2026-08-09-chat-retail-command-registry.md.
Parser semantics (retail OnChatCommand/DoCommand):
- : and ; rewrite to "@emote <rest>" before dispatch.
- Verb trailing-comma trim ("@f, hi" == "@f hi") applied at every
verb-lookup site in the catalog and the parser.
- @tell/aliases split the target on the FIRST COMMA, not the first
whitespace token, so multi-word names work ("@tell Aunt Agatha, hi").
- The 22 unregistered GM/faction channel tags (admin, sentinel,
celestialhand, ...) now broadcast for real via a new
RetailChannelTagTable + SendRawChannelCmd bypass, reusing the existing
BuildChatChannel wire builder.
Binding corrections:
- /g, /group, /party -> Fellowship (0x800), not General.
- /rp -> reply alias (retail's own help text confirms "@r or @rp"), not
Roleplay; /role (an acdream invention) deleted.
- /allegiance, /all -> the allegiance management command
(RetailClientCommandCatalog), not a channel verb.
- /house no longer swallows unrecognized subcommands with a local usage
error; they now correctly fall through to ACE.
- @mr/@pr pinned as permanently non-executable (retail registers them
with a null function pointer).
New verbs with real local execution: endurance, speaker, title (silent,
AP-182), chat, notell, join, leave, permit, hslist, index, clist, on,
off, alh/ah (+ "@allegiance hometown"/"ho"), "@allegiance info",
"@house abandon"; a missing-alias sweep across pkl/hou/message_types/
msgtypes/msg_types/rt/send/whisper/w/vassal/covassal/co-vassals/c/
fellows/group/party/guild/gu/cg/ct/clfg/crp/soc/o; the non-retail
inventions gen/cv/lookingforgroup/tr/role/h are deleted. New Core.Net
wire builders (IndexChannels, ListChannels, AddChannel, RemoveChannel,
RecallAllegianceHometown, AllegianceInfoRequest, ListAvailableHouses,
AddPlayerPermission, RemovePlayerPermission, AbandonHouse) are all
parameterless or single-field payloads cross-checked against ACE's
GameAction readers, not guessed.
Deferred (filed as #360/#361/#362, register rows TS-68/TS-69/TS-70):
the ~22 remaining allegiance/house subcommands + standalone @motd
(largest single item, needs its own slice per the doc), the three
still-inert pure-local commands (day/log/render), and the inbound
GameEvent responses for the new outbound requests. All correctly fall
through to ACE server-passthrough rather than being silently swallowed
or faking success.
RetailCommandRegistryConformanceTests pins the complete 152-verb
registry against production: every verb resolves through exactly one
production surface if Implemented, through none if HelpOnly/
ServerPassthrough, and two reverse-direction tests fail the build if
RetailClientCommandCatalog or ChatInputParser ever claims a verb
outside this registry again. Final tally: 138 Implemented / 5
ServerPassthrough / 9 HelpOnly = 152.
Release suite: 12,190 passed / 4 skipped / 0 failed (up from CH3's
11,964/4/0).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
9247d5d5b5
commit
090825e703
23 changed files with 2069 additions and 97 deletions
|
|
@ -122,6 +122,12 @@ internal sealed class LiveSessionCommandRouter : ILiveSessionCommandRouting
|
|||
SendIfActive(() => bindings.SendTalk(command.Text));
|
||||
});
|
||||
commands.Register<SendChatCmd>(command => RouteChat(bindings, command));
|
||||
// Campaign CH slice CH4 (2026-08-09): the 22 unregistered
|
||||
// ChannelSystem::GetChannelID fallback tags — bypasses
|
||||
// ChatChannelKind/ChannelResolver entirely and sends the raw
|
||||
// legacy ChatChannel (0x0147) broadcast directly.
|
||||
commands.Register<SendRawChannelCmd>(
|
||||
command => SendIfActive(() => bindings.SendChannel(command.ChannelId, command.Text)));
|
||||
commands.Register<AddShortcutRuntimeCmd>(
|
||||
command => SendIfActive(() => bindings.AddShortcut(command.Entry)));
|
||||
commands.Register<RemoveShortcutRuntimeCmd>(
|
||||
|
|
@ -464,7 +470,22 @@ internal sealed class LiveSessionCommandRouter : ILiveSessionCommandRouting
|
|||
HasOpenVendor: () => ReadClient(static b => b.HasOpenVendor(), false),
|
||||
FillComponentBuyList: (componentId, targetCount) =>
|
||||
InvokeClient(b => b.FillComponentBuyList(componentId, targetCount)),
|
||||
EnterPkLite: () => InvokeClient(static b => b.EnterPkLite()));
|
||||
EnterPkLite: () => InvokeClient(static b => b.EnterPkLite()),
|
||||
// Campaign CH slice CH4 (2026-08-09): command-registry completion.
|
||||
IsUsingTurbineChat: () => ReadClient(static b => b.IsUsingTurbineChat(), false),
|
||||
SetChatTitle: title => InvokeClient(b => b.SetChatTitle(title)),
|
||||
SetSingleCharacterOption: (optionId, value) =>
|
||||
InvokeClient(b => b.SetSingleCharacterOption(optionId, value)),
|
||||
AddPlayerPermission: name => InvokeClient(b => b.AddPlayerPermission(name)),
|
||||
RemovePlayerPermission: name => InvokeClient(b => b.RemovePlayerPermission(name)),
|
||||
RequestAvailableHouses: houseType => InvokeClient(b => b.RequestAvailableHouses(houseType)),
|
||||
RequestChannelIndex: () => InvokeClient(static b => b.RequestChannelIndex()),
|
||||
RequestChannelList: channelId => InvokeClient(b => b.RequestChannelList(channelId)),
|
||||
JoinGmChannel: channelId => InvokeClient(b => b.JoinGmChannel(channelId)),
|
||||
LeaveGmChannel: channelId => InvokeClient(b => b.LeaveGmChannel(channelId)),
|
||||
RecallAllegianceHometown: () => InvokeClient(static b => b.RecallAllegianceHometown()),
|
||||
RequestAllegianceInfo: name => InvokeClient(b => b.RequestAllegianceInfo(name)),
|
||||
AbandonHouse: () => InvokeClient(static b => b.AbandonHouse()));
|
||||
|
||||
private bool InvokeClient(Action<ClientCommandController.Bindings> invoke)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue