-
Notifications
You must be signed in to change notification settings - Fork 3
Console Commands
minqlxtended.console_command(cmd) runs the command, and it has finished by the time the call
returns.
minqlxtended.console_command("set g_gravity 200")
minqlxtended.get_cvar("g_gravity") # 200Two kinds of call can't work that way and go to the engine's command buffer instead, taking effect a frame or so later.
Changing the map unloads the game module from inside SV_SpawnServer, and plugins reach
Python through hooks that sit under its vmMain: chat through G_Say, @next_frame and
@delay through G_RunFrame, a vote handler through Cmd_CallVote_f. Running one of these
where it was asked for means returning into code that has just been unloaded. The engine's own
header says as much: EXEC_NOW is "a VM should NEVER use this, because some commands might
cause the VM to be unloaded".
There are seven, taken from the callers of SV_SpawnServer, SV_RestartGameProgs and
SV_Shutdown:
| Command | Handler | Releases the module by |
|---|---|---|
map, devmap
|
SV_Map_f |
SV_SpawnServer |
arena |
SV_Arena_f |
SV_SpawnServer |
map_restart |
SV_MapRestart_f |
SV_RestartGameProgs, or SV_SpawnServer after a latched cvar change |
startRandomMap |
SV_StartRandomMap_f |
formats a map command and runs it with EXEC_NOW
|
killserver |
SV_KillServer_f |
SV_Shutdown |
quit |
Com_Quit_f |
SV_Shutdown |
These go to the command buffer and run from Com_Frame, where nothing of ours is on the stack.
A passed callvote map has always taken that route, which is why votes never crashed when
!map did.
vstr and exec are not on the list despite carrying arbitrary text: Cmd_Vstr_f and
Cmd_Exec_f push it through Cbuf_InsertText and return, so it runs from Com_Frame
whoever asked. That is how the game module changes the map: it sets nextmap and sends
vstr nextmap.
The engine's command text belongs to the game thread, so a @minqlxtended.thread worker's
command is queued for the game thread to hand over on the next frame.
-
Don't read back what a
mapdid.Game.change_map()returns before the map has loaded. Hookmapornew_gameto act on the new one. Everything else, cvar writes included, is readable straight after. -
minqlxtended.redirect_print()captures whatever prints inside the block, and nests. It won't see the output of amap, which runs after the block has closed. -
A command longer than 1023 characters raises
ValueError, that being whatCmd_TokenizeStringaccepts. A worker thread's command arriving while the queue is full raisesEngineStateError.
Game.change_map() is the single place the map command is built, so Plugin.change_map(),
the Game.map and Game.factory setters and a raw console_command("map ...") all get this.
Run these from the server console.
| Command | Prints |
|---|---|
qlx_prof |
Frame cost per probe. See Internals |
qlx_pyperf |
CPython perf trampoline state. See Internals |
qlx_reliable |
How far behind each client is on its 64-slot reliable ring |
qlx_scoreboard |
What the team scoreboard trim is holding back |
qlx_reliable reset and qlx_scoreboard reset zero their counters.