using System.Collections.Frozen;
using AcDream.Core.Chat;
namespace AcDream.Runtime.Chat;
///
/// Campaign CH slice CH4 (2026-08-09): /help <verb> text for
/// every retail-registry verb — originally chat aliases and channel verbs
/// (), the null-func help-only nodes (retail
/// registers these with NO handler; typing them bare reaches the server,
/// only @help <verb> shows anything locally), and the
/// allegiance/house command overviews (the per-subcommand detail lives
/// here too, even though most subcommands are not yet locally executed —
/// see TS-68). Corrected at the consolidated-review round
/// (2026-08-10), SHOULD-FIX 1: the sentence above previously claimed
/// this table covers only verbs
/// "doesn't dispatch directly" — that framing is now FALSE and was itself
/// an overclaim-by-omission: (see
/// its own remarks, and the "Catalog leaf-verb Detail extraction" region
/// below) supplies retail Detail_HelpType text for 42 of the catalog's OWN
/// dispatched leaf verbs too, which ChatCommandRouter now prefers
/// over the catalog's acdream-authored summaries. This table is the single
/// /help <verb> retail-text source for BOTH catalog-dispatched
/// and non-catalog verbs;
/// is now purely the fallback for the catalog verbs not yet extracted.
///
///
/// The named constants above (,
/// , , ,
/// , , ,
/// , , ,
/// ) are verbatim retail text recovered from
/// docs/research/named-retail/acclient_2013_pseudo_c.txt by the
/// recipe in the command-registry doc §5 (scan each Help*
/// function's byte extent for push imm32 into .rdata). Entries
/// that could not be recovered this way (@render's option list) are NOT
/// fabricated — they are simply absent from this table; the lookup falls
/// through to a generic "no detailed help" line rather than guess.
///
///
///
/// Corrected 2026-08-09 at the CH4 REJECT-review, SHOULD-FIX 7: the
/// paragraph above previously claimed "every entry" was verbatim retail
/// text, which was FALSE and directly contradicted 's
/// own inline comment a few dozen lines below it. The ~35 CHANNEL
/// one-liners in ("Sends text to your Fellowship
/// channel.", etc.) are acdream-authored SUMMARIES, not individually
/// hand-extracted retail strings — retail's own per-channel help text was
/// not recovered this slice.
///
///
///
/// Campaign CH user-gate round 2, item 3 (2026-08-09): the user
/// caught that /help death printed an acdream META-MESSAGE ("This is
/// a retail help-topic group; acdream has not yet extracted its exact
/// retail listing text…") instead of retail's real listing — this was the
/// class-doc overclaim's SHARP end. All 7 HelpXxxGroup nodes were
/// resolved that round: ,
/// , , and
/// were COMPLETE verbatim listings;
/// , , and
/// were left PARTIAL with an UNVERIFIED
/// note. 7 of the ~35 channel one-liners (a/guild/gu, general/cg, trade/ct,
/// lfg/clfg, roleplay/crp, society/soc, olthoi/o) were verbatim too; the
/// rest (fellowship/monarch/patron/vassals/covassal family, as standalone
/// /help f-style lookups) still route through the unresolved
/// mechanism below and remain acdream summaries — that part of the gap is
/// unchanged this round; see ByVerb and
/// RetailCommandHelpTableTests.ChannelVerb_StillAcdreamSummary_UnresolvedChannelHackFamily
/// for the record of exactly which verbs. (Those verbs' OWN standalone help
/// registration was never confirmed independently of the group-listing
/// mechanism decoded below, so they are left untouched rather than
/// speculatively upgraded.)
///
///
///
/// Round 4 (2026-08-10): the 3 PARTIAL groups are now COMPLETE, and the
/// meta-notice text itself is GONE from every user-visible string. The
/// blocker was never really HelpStupidChannelHack @0x0056f290's own
/// code — the fragments Binary Ninja renders as vtable-slot dereferences
/// (&ClientCommunicationSystem::`vftable'.RecvNotice_StartBarberNotice
/// etc.) are the SAME pooled/mislabeled-data artifact this campaign has hit
/// before (AP-186's own precedent): they are DATA pointers into
/// .rdata, not real vtable dispatch, and dereferencing their actual
/// operand addresses (found by reading HelpStupidChannelHack's own
/// disassembly for the push imm32 immediately preceding each
/// constructor call, since BN's line-grouped rendering hides the true
/// instruction order) resolves cleanly: the function builds
/// "@" + tag + " - Sends a broadcast to your " + ChannelName + ".\n"
/// where tag is a single character sliced out of a shared wide
/// literal U"fvpca" (reading a WIDE string through a NARROW
/// char* naturally truncates to one character at the first zero high
/// byte — the "hack" the function's own retail name calls out) and
/// ChannelName comes from ChannelSystem::GetChannelName's own
/// literal switch table (also swept directly, not guessed:
/// data_0x7d0478="Allegiance", plus "Co-vassals"/"Monarch"/"Patron"/
/// "Vassals"/"Fellowship" already visible in that function's straight-line
/// decompiled body). See through
/// for the six resolved lines and
/// their per-line address citations.
///
///
/// With that decoded, (which is ENTIRELY
/// six HelpStupidChannelHack calls, confirmed by reading
/// HelpChannelsGroup's Detail branch directly) is now a COMPLETE
/// verbatim listing. needed one more
/// piece: its "@reply" entry does not call a per-tag summary — it calls
/// ClientCommunicationSystem::HelpReply @0x00577A50 with
/// Summary_HelpType, and that function (read directly, not assumed)
/// unconditionally concatenates THREE lines regardless of which tag it was
/// passed (reply, then pr, then mr) — a genuine retail quirk, ported
/// faithfully per CLAUDE.md's "do not fix the decompiled code" rule; see
/// //
/// .
/// (retail's HelpAllGroup, the "lists all commands" topic) is a
/// straight-line concatenation of EVERY other group's Detail branch plus a
/// handful of its own short one-liners (all swept directly from
/// 0x0057E7F0-0x0057EBA0) — including a CONFIRMED retail
/// duplicate (the saveui/loadui short-summary pair appears twice with no
/// conditional between the two occurrences, ported as-is) and one line
/// (@say) whose own retail literal has NO trailing newline, unlike
/// every sibling line — also ported as-is; retail's own output runs
/// @say straight into @tell with no line break. Zero
/// remaining UNVERIFIED notes in any of the three former PARTIAL groups.
/// Closes ISSUES.md #364.
///
///
///
/// The meta-marker sweep. Every honesty marker that had leaked into
/// USER-VISIBLE text — the "[IMPLEMENTED]"/"[IMPLEMENTED, also @x]" tags
/// littered through /,
/// the "NOT YET IMPLEMENTED in acdream" sentences appended to
/// ///,
/// and the "Subcommands NOT marked [IMPLEMENTED]…" trailer on both overview
/// blocks — is now GONE from the strings themselves. Per CLAUDE.md, honesty
/// markers belong in code comments and the divergence register, never in
/// text a player can read. Every one of those consts is now checked against
/// the raw retail data dump the pseudo-C file itself carries for long
/// consolidated string tables (e.g. char const data_7dfb58[0x879] =
/// "@allegiance boot …) — those blocks are ALREADY fully decoded by
/// Binary Ninja with no BN artifact to work around, so they were read
/// directly rather than re-swept, and confirmed the "[IMPLEMENTED]" tags
/// were 100% acdream additions with no retail counterpart (not even a
/// stray character). and also picked
/// up MORE retail text than they had before while their meta tails were
/// being removed — the prior extractions had silently dropped extra
/// sentences/paragraphs present in the same data block (data_7df7f8
/// and data_7da300 respectively); 's previous
/// text was entirely acdream-authored ("Forwards to the client's
/// render-option surface…") and is replaced with the REAL retail usage
/// string (render_option_usage @ 0x0079B878, found by
/// grepping the pseudo-C for a literal @render string instead of
/// trusting the earlier "not decodable" note).
///
///
///
/// messagetypes is now a real construction, not an acdream
/// summary. Retail's HelpMessageTypes @0x0056E5D0 really does
/// build its text at runtime — but by walking a FIXED whitelist
/// (LogTextTypeEnumMapper::IsLegalChannel @0x006AFF40, 14 ids) and a
/// FIXED per-id name table (LogTextTypeEnumMapper::LogTextTypeToString
/// @0x006AFF90, a literal switch), joined with ", "
/// (data_0x794334) and wrapped in "Squelch channels are as
/// follows:\n %s\n" (gmCCommunicationSystem::GetListofSquelchChannels
/// @0x00589EB0 /
/// gmCCommunicationSystem::ConvertSQToPString @0x00589A80's
/// arg3!=0 "enumerate every legal channel" branch — the
/// SquelchInfo it iterates is a SYNTHETIC all-squelched object built
/// solely to walk every legal id, not the player's actual squelch state).
/// Since the whitelist and the name table are both fixed, the output is
/// itself a compile-time constant — but
/// PORTS the construction (the ordered id/name table +
/// 's exact join/prefix logic) rather
/// than hand-authoring the already-known joined string, so a future
/// whitelist change is a one-line table edit instead of a re-derivation.
///
///
///
/// Campaign CH user-gate round 3 (2026-08-10), findings (b)/(c): the
/// round 2 pass extracted the individual STRINGS byte-exact but never
/// traced ClientCommunicationSystem::DoHelp @0x0057f9e0's complete
/// PRINT SEQUENCE — so the CONTENT was right while the SHAPE (how many
/// transcript entries, in what order, with what wrapping) was still
/// acdream-invented. Traced this round via a byte-sweep of DoHelp's own
/// range (0x57f9e0-0x57fe7e) plus every Summary-branch it calls into
/// (HelpEmote/HelpSquelch/HelpStatusGroup/HelpTextGroup/HelpAllGroup),
/// against the PDB-paired C:\Users\erikn\Downloads\acclient.exe
/// (verified MATCH). DoHelp ALWAYS prints via exactly two
/// AddTextToScroll calls (never one concatenated blob), both typed
/// 0 (informational):
///
/// the SAME line, unconditionally —
/// for the bare listing AND for every successful /help <verb>
/// lookup;
/// bare /help: (13 items,
/// straight-line concatenation of 8 inline literals plus 5 delegated to
/// each group's own Summary_HelpType branch, in DoHelp's exact source
/// order). /help <verb> when the verb resolves:
/// immediately followed by the
/// verb's own Detail-branch text (e.g. ) —
/// ONE string, no blank line between the prefix and the listing, because
/// retail's own handler call APPENDS into the same accumulator the
/// prefix was built into (ClientCommunicationSystem::DoHelp,
/// arg2>0 branch, the eax_35(2, var_18, &var_10) call).
///
/// When the verb does NOT resolve, DoHelp prints ONE entry,
/// , typed 0x1A (ClientLocal) —
/// retail routes that type to the SpewBox exclusively, never the chat
/// window (docs/research/2026-08-09-chat-retail-interface-text.md
/// §2.1/§2.2).
///
///
///
/// Issue #363 (2026-08-10):ChatCommandRouter now routes this
/// fallback (and every other 0x1A command-refusal call site) through
/// IChatCommandFeedback.ShowInterfaceText — an optional hook the host
/// wires to RuntimeCommunicationState.AddText, the same SpewBox
/// chokepoint every other producer of interface text uses. The retained
/// ChatVM implements this four-member feedback seam without entering
/// command-routing code. Closes ISSUES.md #367 and retires register row
/// AP-186.
///
///
public static class RetailCommandHelpTable
{
// acclient_2013_pseudo_c.txt:1030771 (data_7dae40).
public const string Tell =
"@tell , - Sends a long-distance, private message to the specified character. Note that you must put a comma after the character's name.";
// acclient_2013_pseudo_c.txt:1030742/1030745.
public const string Reply =
"@reply - Sends the text to the last person who @tell'd you. You may also use @r or @rp.";
// acclient_2013_pseudo_c.txt:1030753/1030757.
public const string Retell =
"@retell - Sends the text to the last person you @tell'd. You may also use @rt.";
// acclient_2013_pseudo_c.txt:394980 (data_0x7e11e0). RE-SWEPT byte-exact
// Campaign CH user-gate round 3 (2026-08-10) via sweep_weenie_strings.py
// --range 0x57f9e0 0x57fe7e --ascii-only against the PDB-paired
// C:\Users\erikn\Downloads\acclient.exe (verified MATCH). The ORIGINAL
// extraction dropped the leading blank line and the trailing double
// newline that are part of retail's own literal — this is DoHelp's
// OWN, always-first scroll entry (a dedicated AddTextToScroll call,
// never concatenated with what follows), printed unconditionally both
// for the bare /help listing and for every successful /help
// lookup. See the class remarks for the complete print-sequence trace.
public const string HelpPrefixNote =
"\nNote: You may substitute a forward slash (/) for the at symbol (@).\n\n";
// acclient_2013_pseudo_c.txt:395087 (data_0x7e1178), swept alongside
// HelpPrefixNote above. DoHelp's arg2>0 (verb-specified) branch builds
// this as the START of its second scroll entry, then the resolved
// verb's own Detail-branch handler APPENDS its listing directly onto
// the SAME accumulator (ClientCommunicationSystem::DoHelp, the
// `eax_35(2, var_18, &var_10)` call) -- so the retail-faithful port is
// string concatenation with NO separator, not two entries. The literal
// text "" is NOT a format placeholder -- the decomp shows a
// straight PStringBase construction with no sprintf/substitution call
// between this literal and its use, so retail never actually inserts
// the real verb name here. Ported verbatim per CLAUDE.md's "do not fix
// the decompiled code" rule, even though it reads like an unfinished
// dev message.
public const string ForMoreInformationPrefix =
"For more information, type @help .\n";
// acclient_2013_pseudo_c.txt:395052 (u"Unknown command", UTF-16LE) --
// DoHelp's fallback when the verb hash lookup fails, or resolves to an
// entry with no registered help callback. Retail types this 0x1A
// (ClientLocal) -- SpewBox-only; see the class remarks' routing note --
// ChatCommandRouter routes it through IChatCommandFeedback.ShowInterfaceText
// (issue #363), closing #367.
public const string UnknownCommand = "Unknown command";
// @mr/@pr are registered with a NULL function pointer in the 2013
// build (verified at 0x00583041/0x005830C1 — arg3 is 0), so they never
// execute locally in retail OR acdream — typing one sends the literal
// text to the server. CH4 REJECT-review SHOULD-FIX 7 (2026-08-09):
// the strings below were previously FABRICATED acdream summaries; the
// real retail-registered help function (HelpReply @0x00577A50) is
// shared across @reply/@r/@rp/@mr/@pr and IS the source of a per-verb
// detail line for each, extracted verbatim below —
// acclient_2013_pseudo_c.txt:1030734 (data_7daa08) for @mr,
// acclient_2013_pseudo_c.txt:1030738 (data_7daa80) for @pr. Retail's
// own strings have a double space before "you" — confirmed byte-level,
// not a typo. (HelpReply's full concatenation across all 5 shared
// verbs is more involved than a single-string extraction can safely
// confirm from the pseudo-C alone — a BN decomp string-temporary
// pattern reuses the output-parameter stack slot, which risks a
// misread; only the two per-verb detail lines requested by the review
// are pinned here, not a full re-derivation of HelpReply's output.)
public const string MonarchReply =
"@mr - Sends the text to the last person who used @m to send you a message. This only works for monarchs.";
public const string PatronReply =
"@pr - Sends the text to the last vassal who used @p to send you a message.";
// acclient_2013_pseudo_c.txt:1031093 (char const data_7de280[0x77] =
// "@day - A…\n", 0) -- BN already fully decodes this consolidated data
// block, no vtable-slot artifact to work around; read directly rather
// than re-swept. Round 4 (2026-08-10): dropped the acdream
// "NOT YET IMPLEMENTED in acdream" tail -- honesty markers belong in
// comments/the register, never in text a player can read (CLAUDE.md).
// acdream's client-side "@day" implementation status, if any, is
// tracked in the divergence register, not here. Shared with
// StatusGroupDetail's own "@day" line -- same data block, same text.
public const string DayLine =
"@day - A toggle that lightens the outdoor landscape. Note that this command may take several seconds to take effect. \n";
public const string Day = DayLine;
// acclient_2013_pseudo_c.txt:1031192-1031198 (char const
// data_7df7f8[0x2ca] = "@log - …\n" "@log AClog.txt - …\n" "@log
// - …\n", 0) -- read directly off the pseudo-C's own consolidated data
// dump. Round 4 (2026-08-10): the prior extraction had silently
// dropped the middle sentence ("Choose the file you are copying to by
// naming it in the command.") and BOTH trailing paragraphs (the
// AClog.txt example and the "stop the process" line) in addition to
// carrying the "NOT YET IMPLEMENTED" meta tail -- all three retail
// sentences are restored here, verbatim, with no acdream commentary.
public const string Log =
"@log - Echoes chat text to a logfile. All the information that appears in your chat window after you type this command will be copied into a text file. Choose the file you are copying to by naming it in the command. If this file already exists, it will add the additional text to the end of it. To turn off logging, simply retype @log.\n"
+ "@log AClog.txt - Echoes chat text to a log file named Aclog.txt in your Asheron's Call directory. After you use this command, all the information that appears in your chat window will be written to a file in your Asheron's Call directory named Aclog.txt.\n"
+ "@log - If you are currently copying the text in your chat window to a logfile, this command will stop the process.\n";
// Round 4 (2026-08-10): the prior text here ("Forwards to the client's
// render-option surface (retail: SmartBox::HandleRenderOption). NOT YET
// IMPLEMENTED in acdream…") was entirely acdream-authored, not retail
// text -- the class remarks previously (incorrectly) called @render's
// option list "not decodable". A direct grep for a literal "@render"
// string in the pseudo-C finds it: `char const render_option_usage[0x98]
// @ 0x0079B878 = "Usage:\n@render