fix(chat): /help client-side handler + System dedup + ThatIsNotAValidCommand template
Phase J follow-up after a 2026-04-25 trace where typing /help
produced two identical "Unknown command: help" lines (ACE fires the
text via both GameMessageSystemChat 0xF7E0 and a paired
CommunicationTransientString 0x02EB), and the server's WeenieError
0x0026 trailer rendered cryptically as "WeenieError 0x0026".
Three small changes:
1. WeenieErrorMessages: add 0x0026 ThatIsNotAValidCommand ->
"That is not a valid command." Plus 0x0414 / 0x050F that Phase J
already added are now covered by tests too.
2. ChatLog.OnSystemMessage dedup. Track last system text + arrival
time; if a second identical text shows up within 1 second,
suppress. ACE's two-path send (gag warnings, command errors,
etc.) collapses to a single chat line. Long bursts of repeated
text still skip the duplicates without resetting the timer.
3. Client-side /help and /clear in ChatPanel. Intercepted BEFORE
the parser passes to the server bus:
- /help, /?, /h (case-insensitive) -> render local cheat-sheet
listing acdream's slash prefixes via ChatLog.OnSystemMessage.
Avoids the round-trip to ACE that produced the duplicate
"Unknown command: help" lines AND gives users discoverability.
- /clear, /cls -> drains the chat log so the panel starts empty.
New ChatVM.ShowSystemMessage() + ChatVM.Clear() expose the
minimum surface the panel needs to dispatch client-only feedback
without coupling the panel to ChatLog directly.
12 new tests:
- 3 WeenieErrorMessages template adds (0x0026 / 0x0414 / 0x050F).
- 4 ChatLog dedup cases (immediate dup, different text, triplet,
bookended-by-different-text).
- 5 ChatPanel client-command cases (/help, 3 alias variants,
/clear).
Solution total: 1033 green (243 Core.Net + 130 UI + 660 Core),
0 warnings.
Acceptance: type /help in chat -> local help banner appears, no
server round-trip, no "Unknown command: help" duplicates. Type
/clear -> chat tail empty. Welcome banner + WeenieError-templated
"You are not in an allegiance!" / "You do not belong to a
Fellowship." continue rendering once each.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7726f62528
commit
3501194083
7 changed files with 269 additions and 2 deletions
|
|
@ -94,7 +94,20 @@ public sealed class ChatPanel : IPanel
|
|||
if (renderer.InputTextSubmit("##chatinput", ref _input, InputBufferMaxLen, out var submitted)
|
||||
&& submitted is not null)
|
||||
{
|
||||
var parsed = ChatInputParser.Parse(submitted.Trim(), ChatChannelKind.Say, _vm.LastIncomingTellSender);
|
||||
var trimmed = submitted.Trim();
|
||||
// Phase J follow-up: client-side commands intercepted before
|
||||
// the server-bound parse path. Avoids the /help round-trip
|
||||
// that produced "Unknown command: help" duplicates from
|
||||
// ACE's command-error replies, AND gives users a discoverable
|
||||
// local cheat-sheet of acdream's own slash prefixes.
|
||||
if (TryHandleClientCommand(trimmed))
|
||||
{
|
||||
_input = string.Empty;
|
||||
renderer.End();
|
||||
return;
|
||||
}
|
||||
|
||||
var parsed = ChatInputParser.Parse(trimmed, ChatChannelKind.Say, _vm.LastIncomingTellSender);
|
||||
if (parsed is { } p)
|
||||
{
|
||||
ctx.Commands.Publish(new SendChatCmd(p.Channel, p.TargetName, p.Text));
|
||||
|
|
@ -119,4 +132,56 @@ public sealed class ChatPanel : IPanel
|
|||
CombatLineKind.Error => new Vector4(1.0f, 0.3f, 0.3f, 1.0f),
|
||||
_ => new Vector4(1f, 1f, 1f, 1f),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Phase J follow-up: handle client-side slash commands before
|
||||
/// the parser passes anything to the server bus. Returns true
|
||||
/// when the input was consumed (and the caller should clear the
|
||||
/// buffer + skip the SendChatCmd path); false otherwise.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Recognised client-side commands:
|
||||
/// <list type="bullet">
|
||||
/// <item><c>/help</c>, <c>/?</c>, <c>/h</c> — render the slash-prefix
|
||||
/// cheat-sheet locally. Avoids the server's "Unknown command"
|
||||
/// round-trip when the user just wants to know what they can
|
||||
/// type.</item>
|
||||
/// <item><c>/clear</c>, <c>/cls</c> — drain the chat log so the
|
||||
/// panel starts empty.</item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
private bool TryHandleClientCommand(string trimmed)
|
||||
{
|
||||
if (trimmed.Length == 0) return false;
|
||||
|
||||
if (trimmed.Equals("/help", StringComparison.OrdinalIgnoreCase) ||
|
||||
trimmed.Equals("/?", StringComparison.OrdinalIgnoreCase) ||
|
||||
trimmed.Equals("/h", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_vm.ShowSystemMessage(BuildHelpText());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (trimmed.Equals("/clear", StringComparison.OrdinalIgnoreCase) ||
|
||||
trimmed.Equals("/cls", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_vm.Clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multi-line cheat-sheet text rendered by <c>/help</c>. ImGui's
|
||||
/// <c>Text</c> path flows embedded newlines naturally so this lands
|
||||
/// as one ChatLog entry that visually wraps to several lines.
|
||||
/// </summary>
|
||||
private static string BuildHelpText() =>
|
||||
"acdream chat commands:\n" +
|
||||
" /say (default), /tell <name>, /reply, /general, /trade,\n" +
|
||||
" /fellowship, /allegiance, /patron, /vassals, /monarch,\n" +
|
||||
" /covassals, /lfg, /roleplay, /society, /olthoi\n" +
|
||||
" /help (this), /clear (clear chat tail)\n" +
|
||||
"ACE server commands: prefix with @ (e.g. @acehelp, @acecommands).";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,18 @@ public sealed class ChatVM
|
|||
LastIncomingTellSender = entry.Sender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a client-side system line to the chat log. Used by
|
||||
/// client-handled commands (/help, /clear, future) to surface
|
||||
/// local feedback without round-tripping the server.
|
||||
/// </summary>
|
||||
public void ShowSystemMessage(string text) => _log.OnSystemMessage(text, chatType: 0);
|
||||
|
||||
/// <summary>
|
||||
/// Drain the chat log. Used by the /clear client-side command.
|
||||
/// </summary>
|
||||
public void Clear() => _log.Clear();
|
||||
|
||||
/// <summary>
|
||||
/// Snapshot the tail of the chat log, formatted as display strings,
|
||||
/// oldest-first. Never returns null; returns an empty array if the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue