Skip to content

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:

  1. Ignore if player._Initialized is false — nothing works before data has loaded.
  2. Look up the command; unknown → "This is not a valid command!"
  3. 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.
  4. Fire PlayerCanUseCommand — a single global gate for every command.
  5. Check the minimum argument count.
  6. Check the access flag.
  7. pcall the callback.
  8. On success, log to EVENT_COMMAND with the full argument text. On a false return, 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.lua924 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.