Skip to content

Latest commit

 

History

History
156 lines (111 loc) · 6.47 KB

console.md

File metadata and controls

156 lines (111 loc) · 6.47 KB

Console

Everything related to this is in:

  • Console.ts (the text buffer and everything that prints to it)
  • ConsoleOverlay.ts (the client's drop-down drawer and notification lines)
  • Cmd.ts
  • Cvar.ts
  • Key.ts

Text buffer and overlay

common/Console.ts (Con) is the output side and is the same in every realm: the text buffer, Print/DPrint/PrintWarning/ PrintError/PrintSuccess, capturing what a command prints (for rcon) and ClearNotify(). It is one instance per realm, built without dependencies and given a clock and the developer switch through Con.Init(). A realm whose output is shown somewhere else (a server worker prints to the console of the page) hands it over with Con.useDelegate(); everything the shared code prints then goes there instead of into a buffer nobody sees.

client/ConsoleOverlay.ts is what shows the buffer and nothing else: isOpen, forcedup, vislines, the toggle and message mode commands, and the Draw* methods below. Everything on this page called ConsoleOverlay.isOpen, ConsoleOverlay.forcedup, ConsoleOverlay.vislines, ConsoleOverlay.ToggleConsole_f, ConsoleOverlay.DrawNotify, ConsoleOverlay.DrawInput or ConsoleOverlay.DrawConsole is a member of ConsoleOverlay.

Console Frontend

The console is a Quake 3 Arena / Doom 3-style drop-down drawer, not the classic Quake 1 "one of four destinations" model: it's an independent overlay (ConsoleOverlay.isOpen) that can pop open on top of either live gameplay or the menu, renders above everything else on screen, and takes exclusive keyboard focus while open — but doesn't pause the game behind it (world simulation and rendering both keep running; only client-side input routing changes).

  • ConsoleOverlay.isOpen is the single source of truth for whether the drawer is toggled open — independent of Key.destination, which continues to mean "what's active underneath the console" (game, menu, or message; the old console destination value is gone).
  • ConsoleOverlay.ToggleConsole_f (bound to `/~ by default via bind, like any other command) just flips ConsoleOverlay.isOpen and releases pointer lock on open, so mouselook doesn't keep spinning the camera while you type.
  • Key.Event() gives an open console dispatch priority over whichever destination is underneath: Escape closes it first (before touching the menu/game/message logic), and any key it doesn't consume as text (e.g. the toggle key itself) still executes its bound command, via the same Key.consolekeys typable-vs-bound-key split used before.
  • ConsoleOverlay.DrawNotify draws the small recent-lines/chat-composition overlay shown when the console itself is closed (Key.destination === game || message).
  • ConsoleOverlay.DrawInput draws the blinking input-line prompt, gated on ConsoleOverlay.isOpen.
  • ConsoleOverlay.DrawConsole draws the whole panel (background, scrollback, input line) for a given slide height.
  • The slide: ConsoleOverlay.current is how far the console has slid down (0 closed, 100 open) and ConsoleOverlay.Update() moves it toward its target at scr_conspeed lines per second, once per frame; it also decides forcedup, which is true while there is no connected game. ConsoleOverlay.Draw() is what the frame calls, after everything else including the menu, so the interactive console always ends up on top: the drawer while it is slid down, the notify lines otherwise. While the console is forced up and not opened by the player (IsPassiveBackdrop()) nothing of it is drawn, the menu is showing instead.
  • Actual key handling (typing, history, tab-complete, scrollback) happens in Key.Console, exactly as before — only the routing around it changed.

Console Background Customization

By default the engine will render the color-indexed gfx/conback.lmp with the version burned into it.

However, you can provide a gfx/conback.png as a fallback.

Console Variables

Use the Cvar class to register console variables.

SV.maxvelocity = new Cvar('sv_maxvelocity', '2000');

It replaced the old interface:

Host.framerate = Cvar.RegisterVariable('host_framerate', '0');

The new Cvar class gives you a bunch of new features such as flags to control whether it’s read-only, it should be written to the config or whether it’s important to server logic.

You can also provide a description that will be shown in the help for it:

Host.dedicated = new Cvar('dedicated', dedicated ? '1' : '0', Cvar.FLAG.READONLY, 'Set to 1, if running in dedicated server mode.');

Values in boolean will be translated into '1' and '0'.

For all flags, check out Cvar.FLAG.

The old string and value properties remain for now.

Console Commands

The command interface has changed significantly.

Cmd.AddCommand('status', Host.Status_f);
Cmd.AddCommand('map', Host.Map_f);

NOTE: Make sure to always suffix the functions that are supposed to be console command handlers with _f.

We no longer support Cmd.argv, Cmd.client etc. In order to allow parallel servers and asynchroneous processing of commands, we provide context for console commands in this, it will be a ConsoleCommand instance.

The following should give you the idea on the console command structure:

Host.Map_f = function(mapname, ...spawnparms) {
  if (mapname === undefined) {
    Con.Print('Usage: map <map>\n');
    return;
  }

  if (this.client) {
    return;
  }

  /* … */
};

You can see that the command line is parsed and tokens are mapped to the function’s arguments accordingly.

In case you need the full command line, you can use this.args. The name is stored in this.command, the arguments are kept in this.argv for convenient’s sake. If the command arrived through a forward, the issuer is available in this.client, an instance of ServerClient.

In server commands that are invoked by the client on the frontend, use this.forward() to forward the command to the server.

Host.Fly_f = function() {
  if (this.forward()) {
    return;
  }

  /* … */
};

A call to this.forward() will return true, when the command has been forwarded.

It’s also possible to register a console command handler class based on ConsoleCommand. You then have to override run().

For example:

class EchoConsoleCommand extends ConsoleCommand {
  run() {
    Con.Print(`${this.args}\n`);
  }
};

/* … */

Cmd.AddCommand('echo', EchoConsoleCommand);

This is useful when a set of commands share a common prolog or logic.