diff --git a/src/KitsuneCommand/Features/ChatCommandService.cs b/src/KitsuneCommand/Features/ChatCommandService.cs index 7a252c3..1b3ac4b 100644 --- a/src/KitsuneCommand/Features/ChatCommandService.cs +++ b/src/KitsuneCommand/Features/ChatCommandService.cs @@ -163,6 +163,16 @@ public bool TryHandleCommand(string playerId, int entityId, string playerName, s HandleBloodMoonVote(playerId, entityId, playerName); return true; + // ── Help / discovery ───────────────────────────────── + // Always available regardless of feature toggles. If a server + // disables every group, /help still works and just reports + // back that nothing's enabled — which is itself useful info. + case "help": + case "commands": + case "?": + HandleHelp(entityId, settings); + return true; + default: return false; // Not a recognized command } @@ -715,6 +725,67 @@ private void HandleBloodMoonVote(string playerId, int entityId, string playerNam } } + // ─── Help ────────────────────────────────────────────────────── + + /// + /// Lists the commands available to the calling player. Only enabled + /// feature groups are shown — running `/help` on a server with the + /// store turned off shouldn't tell the player to try `/buy`. + /// + /// Each Reply() is a separate `pm` to the player's chat, so we can + /// safely emit one line per group without worrying about message + /// length truncation. + /// + private void HandleHelp(int entityId, ChatCommandSettings settings) + { + var p = settings.Prefix; + Reply(entityId, "Available commands:"); + + var anyEnabled = false; + + if (settings.HomeEnabled) + { + Reply(entityId, $" HOME: {p}home [name], {p}sethome , {p}delhome , {p}homes"); + anyEnabled = true; + } + if (settings.TeleportEnabled) + { + Reply(entityId, $" TELEPORT: {p}tp , {p}cities"); + anyEnabled = true; + } + if (settings.PointsEnabled) + { + Reply(entityId, $" POINTS: {p}points, {p}signin"); + anyEnabled = true; + } + if (settings.StoreEnabled) + { + Reply(entityId, $" STORE: {p}shop, {p}buy "); + anyEnabled = true; + } + if (settings.VipEnabled) + { + Reply(entityId, $" VIP: {p}vip"); + anyEnabled = true; + } + if (settings.TicketEnabled) + { + Reply(entityId, $" TICKETS: {p}ticket , {p}ticket , {p}tickets"); + anyEnabled = true; + } + + // Blood Moon Vote has its own enable check inside the feature + // (rather than a settings.BloodMoonVoteEnabled flag here), so we + // surface it unconditionally; the feature itself replies with a + // "disabled" message if a player tries to vote while it's off. + Reply(entityId, $" BLOOD MOON: {p}skipbm (alias: {p}voteskip)"); + + if (!anyEnabled) + { + Reply(entityId, "(All optional feature groups are currently disabled on this server.)"); + } + } + // ─── Helpers ─────────────────────────────────────────────────── ///