# 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 [] [skill 1-5] [team] [msec delay] [altname] ↑ highlighted (currently typing this) $ addbot sarge [[skill 1-5]] [team] [msec delay] [altname] ↑ highlighted (now typing skill level) $ addbot sarge 5 [skill 1-5] [[team]] [msec delay] [altname] ↑ highlighted (now typing team) $ kick [] ↑ 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` - [skill 1-5] [team] [msec delay] [altname] - `removebot` - **Player management:** - `kick` - - `kickban` - - `ban` - - `tempban` - - `tell` - **Game settings:** - `g_gametype` - <0=FFA 1=Duel 2=TDM 3=CA 4=CTF...> - `timelimit` - - `fraglimit` - - `capturelimit` - **Map & voting:** - `map` - - `callvote` - [args...] - `say` - ### 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 ```