Chat and Commands¶
The player's entire interface to the framework. Almost everything a player does, they do by typing.
Sources: libraries/sv_commands.lua (the registry), sv_commands.lua (58 KB — the 66
implementations), libraries/sv_chatbox.lua, libraries/cl_chatbox.lua (924 lines),
libraries/sh_help.lua.
1. The command registry¶
cider.command.add(command, access, arguments, callback, category, help, tip, unpack)
| Parameter | Meaning |
|---|---|
command |
Name, invoked as /name |
access |
Required access flag (single character) |
arguments |
Minimum argument count |
callback |
function(player, ...); return false, message to fail |
category |
Help category — registering one auto-generates the help entry |
help |
Usage string |
tip |
Longer explanation |
unpack |
Pass arguments unpacked rather than as a copied table |
Registering a command automatically registers its help text (cider.help.add), so help
cannot drift from the command list. That is a genuinely good idea and is preserved — in the
new design, help is generated from the command's declared parameters and XML docs, so it
cannot drift at all.
The unpack flag exists because "some callbacks remove arguments from the table, and we
don't want to lose them" — callbacks mutate their own argument list. A symptom of untyped
variadic arguments, and it disappears entirely with typed parameters.
2. Dispatch¶
One console command for the entire game: concommand.Add("cider", …).
/door buy becomes cider door buy.
cider.command.consoleCommand executes, in order:
- Ignore if
player._Initializedis false — nothing works before data has loaded. - Look up the command; unknown → "This is not a valid command!"
- Repair Valve's argument mangling: replace
" ' "→"'"and" : "→":". The tokeniser inserted spaces around quotes and colons, so every argument is string-patched on the way in. - Fire
PlayerCanUseCommand— a single global gate for every command. - Check the minimum argument count.
- Check the access flag.
pcallthe callback.- On success, log to
EVENT_COMMANDwith the full argument text. On afalsereturn, notify the player with the failure message. On a Lua error,ErrorNoHalt— the server survives; the player gets nothing.
Everything a client can ask the server to do arrives here as an array of strings with no
type or range validation (D-02). Every command re-implements its
own parsing, its own target lookup, and its own rate limiting via ad-hoc _Next* timestamps.
Design note: the shape is right — one authenticated, logged, access-gated entry point with a global veto hook. The new design keeps that shape with typed parameters, declarative access requirements, declarative rate limits, and automatic help generation. See Architecture/07_NETWORKING.md.
3. Chat routing¶
libraries/sv_chatbox.lua is 37 lines and does one thing well:
cider.chatBox.add(recipientFilter, player, filter, text)
cider.chatBox.addInRadius(player, filter, text, position, radius)
filter is the channel name — the client uses it to colour, prefix and optionally hide the
line. addInRadius builds a RecipientFilter by distance test. Two functions cover every
chat channel in the game.
The client side is libraries/cl_chatbox.lua — 924 lines, the largest client file: a
complete custom chat client with channel filters, command autocomplete and custom rendering.
Proximity¶
| Setting | Default |
|---|---|
Talk Radius |
256 units |
Local Voice |
true |
Both IC text and voice are proximity-limited. Talking to someone requires being near them, which is the single most important thing the chat system does for the game's feel.
4. Channels¶
| Command | Channel | Notes |
|---|---|---|
| (none) | IC speech | 256 unit radius |
/y |
Yell | Larger radius |
/w |
Whisper | Smaller radius |
/me |
Emote | Third-person action |
/action |
Action | Roleplay action |
/globalaction |
Global action | Moderator only |
/ooc or // |
Out of character | 60 s cooldown |
/looc or .// |
Local OOC | Proximity-limited OOC |
/advert |
Advertisement | $60, 150 s cooldown |
/radio |
Radio | Recipients filtered by the officials plugin |
/pm |
Private message | Direct |
/a |
Admin chat | Access a |
/m |
Moderator chat | Access m |
/details |
Character description |
The friction on /ooc and /advert is deliberate: breaking character costs a minute, and
advertising costs money. Both preserved.
5. The full command table¶
All 66 commands, from sv_commands.lua. The Acc column is the required character access
flag (b = everyone, m = moderator, a = admin, s = superadmin); Min is the minimum
argument count.
Communication¶
| Command | Acc | Min | Line | Purpose |
|---|---|---|---|---|
/y |
b | 1 | 669 | Yell |
/me |
b | 1 | 680 | Emote |
/w |
b | 1 | 689 | Whisper |
/advert |
b | 1 | 700 | Advertise ($60, 150 s) |
/pm |
b | 2 | 502 | Private message |
/radio |
b | 1 | 1234 | Radio |
/action |
b | 1 | 1362 | Roleplay action |
/globalaction |
m | 1 | 1372 | Server-wide action |
/ooc |
b | 1 | 1382 | Out of character |
/looc |
b | 1 | 1393 | Local OOC |
/a |
a | 1 | 1502 | Admin chat |
/m |
m | 1 | 1514 | Moderator chat |
/details |
b | 0 | 1338 | Character description |
/note |
b | 1 | 586 | Write a physical note (max 2) |
Inventory, items and economy¶
| Command | Acc | Min | Line | Purpose |
|---|---|---|---|---|
/inventory |
b | 2 | 742 | Use / drop / destroy / sell |
/container |
b | 2 | 848 | Container interaction |
/drop |
b | 0 | 934 | Drop held item |
/holster |
b | 0 | 903 | Holster weapon |
/manufacture |
b | 1 | 1097 | Craft — pay Cost × Batch |
/givemoney |
b | 1 | 521 | Give money to a player |
/dropmoney |
b | 1 | 545 | Drop money as a world item |
Property¶
| Command | Acc | Min | Line | Purpose |
|---|---|---|---|---|
/door |
b | 1 | 939 | Buy, sell, lock, access |
/entity |
b | 2 | 1068 | The same for any ownable entity |
/setmaster |
s | 1 | 1406 | Link a door to a master |
/seal |
s | 0 | 1424 | Seal / unseal |
/setname |
s | 1 | 1447 | Name an entity |
/setowner |
s | 1 | 1461 | Force ownership |
Jobs and identity¶
| Command | Acc | Min | Line | Purpose |
|---|---|---|---|---|
/team |
b | 1 | 724 | Apply for a job |
/job |
b | 0 | 623 | Job info |
/clan |
b | 0 | 635 | Set clan tag |
/gender |
b | 1 | 651 | Set gender |
/demote |
b | 2 | 479 | Demote a subordinate |
/mutiny |
b | 1 | 1261 | Vote to depose a leader |
/setteam |
a | 2 | 100 | Admin: force a job |
Law enforcement¶
| Command | Acc | Min | Line | Purpose |
|---|---|---|---|---|
/warrant |
b | 1 | 1145 | Issue a warrant |
/unwarrant |
b | 1 | 1189 | Revoke a warrant |
/arrest |
s | 1 | 114 | Admin arrest |
/unarrest |
s | 1 | 124 | Admin release |
/awarrant |
s | 2 | 134 | Admin warrant |
Roleplay affordances¶
| Command | Acc | Min | Line | Purpose |
|---|---|---|---|---|
/sleep |
b | 0 | 1226 | Fall asleep (5 s still) |
/trip |
b | 0 | 1241 | Trip over |
/fallover |
b | 0 | 1253 | Fall over |
/fuck |
b | 0 | 6 | Swear |
Four commands whose entire purpose is to let you do something pointless. They cost nothing and they are a large part of why the framework feels like a place rather than a system.
Administration¶
| Command | Acc | Min | Line | Purpose |
|---|---|---|---|---|
/knockout, /wakeup |
s | 1 | 18, 29 | Knock out / wake a player |
/knockoutall, /wakeupall |
s | 0 | 46, 59 | …everyone |
/tie, /untie |
s | 1 | 66, 76 | Tie / untie |
/spawn |
s | 1 | 89 | Force respawn |
/give |
s | 2 | 149 | Give a weapon |
/giveammo |
s | 2 | 161 | Give ammunition |
/giveitem |
s | 2 | 199 | Give an item |
/setmodel |
a | 2 | 241 | Set player model |
/invisible |
a | 0 | 171 | Toggle invisibility |
/notify, /notifyall |
a | 3, 2 | 252, 273 | Send notifications |
/giveaccess, /takeaccess |
s | 2 | 295, 309 | Grant / revoke flags |
/blacklist |
m | 5 | 373 | Blacklist from a thing |
/unblacklist |
m | 3 | 405 | Remove a blacklist |
/blacklistlist |
m | 1 | 427 | Inspect blacklists |
/donator |
s | 1 | 1308 | Set donator tier |
/save |
s | 0 | 496 | Force a save |
/restartmap |
m | 0 | 323 | Restart the map |
The admin surface is substantial and it all funnels through the same registry, access check and log. Every command is logged with its full argument text. Server operators need this; it is not optional.
6. Notification levels¶
ply:Notify(message, level):
| Level | Presentation |
|---|---|
nil |
Chat message |
0 |
Water drip |
1 |
Failure buzzer |
2 |
"Bip" |
3 |
"Tic" |
Four distinct sounds for four distinct meanings. Failure has its own noise, so a player knows they were refused without reading. Preserve the taxonomy; the sounds themselves are Source 1 assets and will be replaced.
7. Client extension hooks¶
cl_init.lua exposes hooks specifically so plugins can extend the HUD without touching it:
| Hook | Purpose |
|---|---|
DrawBottomBars(bar) |
Add a status bar — used by hunger, stamina, flashlight |
DrawTopText(text) |
Add a line of top-of-screen text |
AdjustESPLines(lines, ent, pos, dist, lookingat) |
Add lines to the entity ESP overlay |
OpenChatBox / CloseChatBox |
React to chat focus |
AdjustESPLines is the important one. Looking at a door shows its name, owner and status
because cl_entity.lua contributes lines to a shared overlay — and any plugin can add more.
"Look at a thing, learn about it" is the primary information channel in the game, and the new
UI architecture treats it as a first-class system rather than a HUD detail. See
Architecture/11_UI_ARCHITECTURE.md.
8. What survives¶
Survives: one authenticated, logged, access-gated entry point; a global CanUseCommand
veto; help generated from registration; return false, message as the failure convention;
proximity-limited IC speech and voice; the channel set; friction on OOC and adverts;
notification levels including a distinct failure sound; commands whose only purpose is
roleplay; the extensible bottom-bar and ESP-line hooks; logging every command with arguments.
Does not survive: stringly-typed variadic arguments; string-patching Valve's tokeniser; per-command ad-hoc rate limiting; a 58 KB file of unrelated handlers; single-character access flags; a 924-line hand-rolled chat client.