Send cvarlist and cmdlist on connect and merge the answer into the autocomplete candidates. Number the server menu from 0, keep suggesting sibling commands while the command name is typed, mask the password in the startup line, ignore venv/, fix README claims.
346 lines
9.5 KiB
Markdown
346 lines
9.5 KiB
Markdown
# QLPyCon - Quake Live Python Console
|
|
|
|
Terminal client for monitoring and controlling Quake Live servers via ZMQ RCON.
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
curl -sSL https://6bit.ch/qlpycon/install.sh | bash
|
|
```
|
|
|
|
Or from a cloned repo:
|
|
|
|
```bash
|
|
git clone https://git.6bit.ch/xbl/qlpycon.git
|
|
cd qlpycon
|
|
./install.sh
|
|
```
|
|
|
|
The installer sets up a virtualenv, installs dependencies, and writes a launcher to `~/.local/bin/qlpycon`.
|
|
|
|
## Configuration
|
|
|
|
Edit `qlpycon.conf` in your install directory. See `qlpycon.conf.example` for all options.
|
|
|
|
```ini
|
|
[connection]
|
|
password = ${QLPYCON_PASSWORD}
|
|
|
|
[servers]
|
|
ffa = 10.13.12.93:28960
|
|
duel = 10.13.12.93:28961
|
|
```
|
|
|
|
## Usage
|
|
|
|
```bash
|
|
qlpycon # pick a server from a menu
|
|
qlpycon ffa # connect by name
|
|
qlpycon --host tcp://10.13.12.93:28960 --password secret # connect directly
|
|
qlpycon --list # list configured servers
|
|
```
|
|
|
|
Without arguments, qlpycon shows the servers from `[servers]` numbered from 0 and connects to the one you select (Up/Down or j/k, Enter or the number key 0-9; q quits). If no servers are configured it connects to `[connection] host`.
|
|
|
|
**Keys in the console:**
|
|
- `Enter`: send the command
|
|
- `Tab`: cycle autocomplete suggestions
|
|
- `Up`/`Down`: command history
|
|
- `PgUp`/`PgDn` or mouse wheel: scroll the output back and forth (the last 2000 lines are kept)
|
|
- Hold `Shift` while selecting text with the mouse (the wheel is reported to qlpycon)
|
|
- `Ctrl-C` twice: quit
|
|
|
|
**Options:**
|
|
- `--host URI`: ZMQ RCON endpoint
|
|
- `--password PASS`: RCON password (or set `QLPYCON_PASSWORD` env var)
|
|
- `--list`: list configured servers and exit
|
|
- `-v` / `-vv`: verbose (INFO) or debug (DEBUG) logging
|
|
- `--json FILE`: log all JSON events to file
|
|
- `--unknown-log FILE`: log unparsed events (default: unknown_events.log)
|
|
|
|
## Features
|
|
|
|
- Real-time kill/death/medal/team switch events
|
|
- Team-aware colorized output with Quake color code support
|
|
- Powerup pickup and carrier kill notifications
|
|
- Server info panel (map, gametype, scores, players)
|
|
- Tab autocomplete for cvars and commands with fuzzy matching; on connect the
|
|
server's own `cvarlist` and `cmdlist` output is read so every cvar and
|
|
command the server knows is suggested, not only the built-in list
|
|
- Argument suggestions for 22 commands (bot names, maps, gametypes)
|
|
- Command history (↑/↓)
|
|
- Output scrollback (PgUp/PgDn) that survives terminal resizes
|
|
|
|
## Architecture
|
|
|
|
```
|
|
main.py - entry point, arg parsing, signal handling
|
|
qlpycon.conf - user configuration
|
|
lib/
|
|
constants.py - weapons, teams, colors, limits
|
|
settings.py - config file loader
|
|
state.py - game state (server info, players, teams)
|
|
network.py - ZMQ connections (RCON DEALER, stats SUB)
|
|
parser.py - JSON event parsing
|
|
formatter.py - message formatting and colorization
|
|
ui.py - curses interface (info / output / input panels)
|
|
cvars.py - built-in cvar/command database and autocomplete
|
|
namelist.py - learns cvar/command names from the server (cvarlist, cmdlist)
|
|
```
|
|
|
|
## License
|
|
|
|
WTFPL
|
|
|
|
|
|
|
|
|
|
# Autocomplete Feature
|
|
|
|
## Overview
|
|
|
|
QLPyCon includes intelligent autocomplete for console variables (cvars) and commands with fuzzy matching support.
|
|
|
|
## Features
|
|
|
|
- **Real-time Suggestions**: Fuzzy matches appear below the input line as you type
|
|
- **Tab Cycling**: Press Tab to cycle through suggestions
|
|
- **Smart Argument Highlighting**: Current argument position highlighted in reverse video
|
|
- **Argument Value Suggestions**: Intelligent suggestions for command arguments (bot names, maps, gametypes, etc.)
|
|
- **Command Signatures**: Automatic display when typing commands with arguments
|
|
- **Fuzzy Matching**: Finds matches even with partial or misspelled input
|
|
- **Smart Scoring**: Best matches appear first (exact > prefix > substring > fuzzy)
|
|
|
|
## Usage
|
|
|
|
Type a partial command (2+ characters) and fuzzy matches appear below the prompt:
|
|
|
|
```
|
|
$ sv_m
|
|
sv_maxclients sv_minrate sv_maxrate sv_timeout sv_floodprotect
|
|
```
|
|
|
|
Press **Tab** to cycle through the suggestions:
|
|
```
|
|
$ sv_m [Tab] → sv_maxclients
|
|
$ sv_maxclients [Tab] → sv_minrate
|
|
$ sv_minrate [Tab] → sv_maxrate
|
|
$ sv_maxrate [Tab] → sv_timeout
|
|
$ sv_timeout [Tab] → sv_floodprotect
|
|
$ sv_floodprotect [Tab] → sv_maxclients (cycles back)
|
|
```
|
|
|
|
**Command signatures with argument highlighting:**
|
|
|
|
When you type a command that has arguments, the signature appears automatically with the **current argument highlighted**:
|
|
|
|
```
|
|
$ addbot
|
|
[<botname>] [skill 1-5] [team] [msec delay] [altname]
|
|
↑ highlighted (currently typing this)
|
|
|
|
$ addbot sarge
|
|
<botname> [[skill 1-5]] [team] [msec delay] [altname]
|
|
↑ highlighted (now typing skill level)
|
|
|
|
$ addbot sarge 5
|
|
<botname> [skill 1-5] [[team]] [msec delay] [altname]
|
|
↑ highlighted (now typing team)
|
|
|
|
$ kick
|
|
[<player>]
|
|
↑ highlighted
|
|
|
|
$ g_gametype
|
|
[<0=FFA 1=Duel 2=TDM 3=CA 4=CTF...>]
|
|
↑ highlighted
|
|
```
|
|
|
|
The highlighted argument (shown with `[[ ]]` above, displayed in reverse video) shows you **exactly what to type next**.
|
|
|
|
Matches update in real-time as you type or delete characters.
|
|
|
|
**Argument value suggestions:**
|
|
|
|
After typing a command with a space, the system suggests valid values for each argument with fuzzy matching:
|
|
|
|
```
|
|
$ addbot
|
|
Anarki Angel Biker Bitterman Bones
|
|
↑ Shows bot names
|
|
|
|
$ addbot sar
|
|
Sarge
|
|
↑ Fuzzy matches 'sar' → 'Sarge'
|
|
|
|
$ addbot Sarge
|
|
1 2 3 4 5
|
|
↑ Shows skill levels (1-5)
|
|
|
|
$ addbot Sarge 4
|
|
red blue free spectator r
|
|
↑ Shows team values
|
|
|
|
$ map
|
|
aerowalk almostlost arenagate asylum battleforged
|
|
↑ Shows map names
|
|
|
|
$ map blood
|
|
bloodrun
|
|
↑ Fuzzy matches 'blood' → 'bloodrun'
|
|
|
|
$ g_gametype
|
|
ffa duel race tdm ca
|
|
↑ Shows gametype values (string names first, then the numbers 0-11)
|
|
|
|
$ callvote
|
|
map map_restart nextmap gametype kick
|
|
↑ Shows vote types
|
|
```
|
|
|
|
The system knows valid values for **22 commands** including:
|
|
- **32 bot names**: Sarge, Ranger, Visor, Xaero, Anarki, etc.
|
|
- **38 maps**: bloodrun, campgrounds, toxicity, aerowalk, etc.
|
|
- **12 game types**: ffa, duel, tdm, ca, ctf, etc. (string and numeric forms)
|
|
- **Vote types**: map, kick, shuffle, teamsize, gametype, etc.
|
|
- **Team values**: red, blue, free, spectator (and r, b, f, s)
|
|
- **Skill levels**: 1-5 for bots
|
|
- **Boolean values**: 0, 1
|
|
- **Common settings**: timelimits, fraglimits, sv_fps values, etc.
|
|
|
|
Arguments with freetext (like player names or custom messages) fall back to showing the signature with highlighting.
|
|
|
|
## Supported Commands
|
|
|
|
Right after connecting, qlpycon sends `cvarlist` and `cmdlist` to the server
|
|
and adds every name from the answer to the autocomplete candidates (the
|
|
listing itself is hidden from the output). The built-in list below is the
|
|
fallback before that answer arrives and the source of signatures and argument
|
|
values.
|
|
|
|
**Built-in cvars and commands:**
|
|
|
|
### Commands with Signatures
|
|
|
|
The following commands show usage help when selected:
|
|
|
|
**Bot commands:**
|
|
- `addbot` - <botname> [skill 1-5] [team] [msec delay] [altname]
|
|
- `removebot` - <botname>
|
|
|
|
**Player management:**
|
|
- `kick` - <player>
|
|
- `kickban` - <player>
|
|
- `ban` - <player>
|
|
- `tempban` - <player> <seconds>
|
|
- `tell` - <player> <message>
|
|
|
|
**Game settings:**
|
|
- `g_gametype` - <0=FFA 1=Duel 2=TDM 3=CA 4=CTF...>
|
|
- `timelimit` - <minutes>
|
|
- `fraglimit` - <frags>
|
|
- `capturelimit` - <captures>
|
|
|
|
**Map & voting:**
|
|
- `map` - <mapname>
|
|
- `callvote` - <vote type> [args...]
|
|
- `say` - <message>
|
|
|
|
### Additional Cvars
|
|
|
|
**Server Configuration:**
|
|
- sv_hostname, sv_maxclients, sv_fps, sv_pure, etc.
|
|
|
|
**Network & ZMQ:**
|
|
- net_port, zmq_rcon_enable, zmq_stats_enable, etc.
|
|
|
|
**QLX (minqlx):**
|
|
- qlx_serverBrandName, qlx_owner, qlx_redditAuth
|
|
|
|
## Technical Details
|
|
|
|
### Fuzzy Matching Algorithm
|
|
|
|
Scoring system (higher = better match):
|
|
- **1000**: Exact match
|
|
- **500+**: Prefix match (prioritizes shorter results)
|
|
- **100-**: Substring match (earlier = better)
|
|
- **50**: Contains all characters in order
|
|
|
|
### Examples:
|
|
|
|
```python
|
|
autocomplete('sv_')
|
|
→ ['sv_fps', 'sv_pure', 'sv_maxrate', 'sv_minrate', 'sv_timeout']
|
|
|
|
autocomplete('time')
|
|
→ ['timelimit', 'sv_timeout']
|
|
|
|
autocomplete('stat')
|
|
→ ['status', 'zmq_stats_enable', 'zmq_stats_ip', 'zmq_stats_password', 'zmq_stats_port']
|
|
```
|
|
|
|
## Customization
|
|
|
|
### Add Your Own Cvars
|
|
|
|
Names the server reports via `cvarlist`/`cmdlist` are picked up automatically.
|
|
To add a signature or argument values, or a name the server does not report,
|
|
edit `cvars.py` and add to the appropriate list:
|
|
|
|
```python
|
|
# Custom cvars
|
|
CUSTOM_CVARS = [
|
|
'my_custom_cvar',
|
|
'another_cvar',
|
|
]
|
|
|
|
# Add to ALL_CVARS
|
|
ALL_CVARS = (
|
|
SERVER_CVARS +
|
|
GAME_CVARS +
|
|
# ...
|
|
CUSTOM_CVARS
|
|
)
|
|
```
|
|
|
|
### Adjust Behavior
|
|
|
|
In `ui.py`, modify:
|
|
|
|
```python
|
|
# Minimum characters before showing suggestions
|
|
if len(current_word) >= 2: # Change to 1 or 3
|
|
|
|
# Maximum suggestions displayed
|
|
suggestions = autocomplete(current_word, max_results=5) # Change limit
|
|
```
|
|
|
|
## Keyboard Shortcuts
|
|
|
|
| Key | Action |
|
|
|-----|--------|
|
|
| **Tab** | Cycle through autocomplete suggestions |
|
|
| **↑** | Previous command in history |
|
|
| **↓** | Next command in history |
|
|
| **←/→** | Move cursor |
|
|
| **Backspace** | Delete (updates suggestions) |
|
|
| **Enter** | Send command |
|
|
|
|
## Notes
|
|
|
|
- Autocomplete starts after typing 2+ characters
|
|
- Suggestions appear on the line below the prompt
|
|
- Up to 5 matches shown at once (best matches first)
|
|
- Suggestions update in real-time as you type
|
|
- History navigation (↑/↓) works normally
|
|
|
|
## Testing Autocomplete
|
|
|
|
```bash
|
|
# Run cvars module directly to test matching
|
|
python3 cvars.py
|
|
|
|
# Output shows test queries and results
|
|
```
|