# Commands Player-only (no console support yet). Every command is gated by a Hytale permission node. ## Permissions | Command | Required permission | |---|---| | `/ban` | `networkstaff.ban` | | `/tempban` | `networkstaff.tempban` | | `/mute` | `networkstaff.mute` | | `/tempmute` | `networkstaff.tempmute` | | `/kick` | `networkstaff.kick` | | `/warn` | `networkstaff.warn` | | `/unban` | `networkstaff.unban` | | `/unmute` | `networkstaff.unmute` | | `/sc` | `networkstaff.chat` (also required to *receive* staff chat) | | `/lookup` | `networkstaff.lookup` | | `/history` | `networkstaff.history` | | `/staffui` | `networkstaff.ui` | Grant `networkstaff.*` to give a group everything. Without the relevant node, Hytale's command system blocks the call before our handler runs - the user sees the standard `You do not have permission for this command.` message. Permissions are wired via `AbstractCommand.requirePermission(node)` in each command's constructor. We also override `canGeneratePermission()` to return false so Hytale doesn't auto-generate a different permission name and gate on that instead. Receiving staff chat also requires `networkstaff.chat`, so a moderator who can read it can also send to it. If you want separate read/send permissions later, split the check in [StaffChatService.java](../src/main/java/net/kewwbec/staff/service/StaffChatService.java) into two nodes. ## Punishments ### /ban <player> <reason> Permanent ban. Active across all servers in the network within a few hundred ms. Online target is disconnected immediately with the reason. ### /tempban <player> <duration> <reason> Time-limited ban. Duration syntax: `30s`, `5m`, `2h`, `7d`, `1w`. Expires automatically (the active-ban query filters by `expires_at`). ### /mute <player> <reason> Permanent mute. Cancels `PlayerChatEvent` for the target on every server. Loaded into a per-server in-memory cache on the target's connect so chat enforcement doesn't hit MySQL on every message. ### /tempmute <player> <duration> <reason> Time-limited mute. Same duration syntax as tempban. ### /kick <player> <reason> One-shot disconnect. Recorded in history but doesn't persist beyond that (the target can rejoin immediately). ### /warn <player> <reason> Recorded in history and shown to the target as a message if they're online. No connection or chat impact. ### /unban <player> Revokes any active ban or tempban for the player. Marks the punishment row as `active=0`, fills `revoked_at` / `revoked_by_*`. Original row stays in history. ### /unmute <player> Same as unban but for mutes. Also clears the entry from the mute cache on any server where the player is online. ## Staff chat ### /sc Toggles **staff chat mode** for you. No arguments. (Hytale command args are single-token, so a multi-word `/sc ` doesn't work; the toggle is the workaround.) When ON: - Anything you type into world chat is intercepted, the regular chat event is cancelled, and the message is broadcast on the cross-server staff chat channel. - Other players who have `networkstaff.chat` see it; nobody else does. - Run `/sc` again to turn it off. When OFF: regular chat behaves normally. System events (a ban issued, an unban) also post a line on this channel automatically. The toggle state lives in memory on this server only and is cleared when you disconnect. If you log into a different server, you'll need to re-toggle. ## Lookup ### /lookup <player> Shows: - Player's last-known name and UUID - Online status (and which server they're on, if any) - First-seen and last-seen timestamps - Any active ban - Any active mute If the player has never connected, only the name/UUID lookup happens via online players and may return nothing. ### /history <player> Last 20 punishment entries for the player, most recent first. Each entry shows id, state (`ACTIVE` / `EXPIRED` / `REVOKED`), type, who issued it, when, and the reason. ## UI ### /staffui Opens the Staff Hub page. From there: Player Lookup -> select player -> Detail page with action buttons. See [07_UI.md](07_UI.md) for the page flow and how to add new screens. ## Common error cases | Error message | Cause | |---|---| | "You do not have permission for this command." | Caller lacks the relevant `networkstaff.` node. Add it (or `networkstaff.*`) to their group. Hytale's command system enforces this before our handler runs. | | "No player found with that name (online or in history)." | Name doesn't match any online player or any name in `staff_players_seen`. | | "Database error: ..." | MySQL query failed. Check NetworkCore connection (`/networkcore status`). | | "Bad duration. Use 30s, 5m, 2h, 7d, 1w." | Duration string didn't parse. Last char must be `s`/`m`/`h`/`d`/`w`, prefix must be a positive integer. |