Skip to content

About

GHost++, the Warcraft III game hosting bot rewritten in Rust

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

ghostpp-rs

A Rust rewrite of the classic Warcraft III hosting bot GHost++.

Release License

English | 繁體中文

ghostpp-rs targets Warcraft III 1.26–1.28 on PVPGN servers (private realms / gaming platforms). The original C++ single-threaded 50 ms select loop is replaced with a tokio async actor architecture, while the protocol layer is ported byte-for-byte against the C++ original.

Features

  • PVPGN login — CD key decoding, XSHA1 password hashing and checkRevision (exe hash) implemented in pure Rust (embedded bncsutil port), no external C libraries
  • Hosting & lobby — STARTADVEX3 advertising with 3-second refresh, player joins / slot management, free team/colour/race/handicap switching, HCL mode-string encoding
  • Map downloads — MAPCHECK / STARTDOWNLOAD / MAPPART sliding-window transfer with live progress in the lobby
  • Full in-game loop — load synchronization, action batching with adjustable latency (5–500 ms), keepalive desync detection, lag screen (tolerance auto-scaled from latency)
  • Autohost — continuous auto-hosting and auto-start when the lobby fills
  • GProxy++ reliable reconnects — send buffering with ACK trimming, players kept alive through disconnects, buffered resend on reconnect, safe removal on timeout
  • Spoofcheck — identity verification via the sc whisper (sent automatically by GProxy); in-game admin commands always require verification and check permissions against the verified realm
  • Database — both SQLite (default, zero-config) and PostgreSQL built in, switched by a single db_url; admins / bans / game & player records
  • Replay saving — every game is saved as a .w3g (zlib segmented packed container, playable directly in the W3 client)
  • Status endpoint — optional read-only GET /status JSON (games, phase, players) for external managers, isolated from the game loop
  • i18n — all user-visible messages go through a language catalog (Traditional Chinese and English built in, switched by one bot_language line)
  • Commands — 31 battle.net whisper commands + 30+ in-game commands, see COMMANDS.md

Architecture

main ─┬─ BotCore     (event loop: command dispatch, permissions, autohost, db)
      ├─ BnetActor   (one per PVPGN connection: login state machine, anti-flood queue, refresh)
      ├─ GameActor   (one per game: lobby / downloads / in-game loop / GProxy buffers / replay)
      │    └─ PlayerConn (one per player: read/write task pair, framed codec)
      ├─ listener (host_port) and reconnect listener (GProxy)
      └─ console (stdin commands)

Actors communicate exclusively via mpsc messages (events up, commands down) with no shared mutable state. The protocol codecs (src/core/) are ported function-by-function against the C++ source, with the critical traps (string null terminators, integer widths, packet ordering) annotated with their corresponding C++ locations.

Downloads

Prebuilt binaries for every tagged release are published on the Releases page:

Platform Artifact Notes
Windows x64 ghostpp-rs-windows-x64.exe
macOS (Apple Silicon) ghostpp-rs-macos-arm64
Linux x64 ghostpp-rs-linux-x64 glibc distros (Debian, Ubuntu, Fedora, …)
Linux ARM64 ghostpp-rs-linux-arm64-musl fully static — runs on any ARM64 distro, including Alpine

Building from source

All four platforms above are built and verified by CI.

Requirements: Rust (stable) and CMake ≥ 4.1 (stormlib-sys uses it to build the bundled StormLib C++ source), plus a platform C/C++ toolchain:

  • Windows — MSVC build tools. If building with the VS2026 toolchain, also run cargo update -p cmake (older versions of the cmake crate aren't compatible with VS2026).

  • Linux — C/C++ toolchain and the zlib / bzip2 dev packages (linked by StormLib).

    Debian/Ubuntu:

    sudo apt install build-essential cmake zlib1g-dev libbz2-dev
    

    Fedora/RHEL:

    sudo dnf install gcc-c++ cmake zlib-devel bzip2-devel
    
  • macOS — Xcode Command Line Tools and CMake (brew install cmake); zlib and bzip2 ship with the SDK. Verified on Apple Silicon by CI.

cargo build --release

Runtime setup

For copyright reasons the repository contains no Blizzard game files. The one exception is maps/Empty.w3x, a blank 16KB map committed as a test fixture so the MPQ parsing test runs on a fresh clone. To run, supply locally:

  1. lib/ — War3 installation files (war3.exe/warcraft.exe, Storm.dll, game.dll) used by checkRevision to compute the exe hash
  2. maps/ — the map files to host (.w3x/.w3m)
  3. config/
    • ghost.toml — main settings (ports, latency, replays, database, language file, …)
    • bnet.toml — PVPGN server, account credentials, CD keys, root admins (see bnet.toml.example; this file holds secrets and is gitignored)
    • map.toml — current map settings
cargo run --release

On startup the bot logs in to PVPGN and (if autohost is enabled) starts hosting automatically; or host manually by whispering !pub <game name>. See COMMANDS.md for command usage.

Key settings (config/ghost.toml)

Key Description
db_url sqlite://ghost.db (default) or postgres://user:pass@host/db
bot_language language file; config/language.toml (zh-TW) / config/language_en.toml
bot_latency action interval in ms (5–500; adjustable at runtime with !latency)
bot_reconnect / bot_reconnectport GProxy++ reconnect toggle and port
bot_savereplays / bot_replaypath automatic replay saving
autohost_gamename / autohost_maxgames / autohost_startplayers autohosting
status_bind / status_allow read-only GET /status JSON endpoint (games, phase, players) and the IPs/CIDRs allowed to read it; blank bind = disabled

Status endpoint

Set status_bind (e.g. 0.0.0.0:6200) to serve a read-only JSON snapshot of all games at GET /status. Only peers listed in status_allow (IPs / CIDR blocks; blank = loopback only) can connect; others are closed without a reply. There is no TLS or token, so also restrict the port in your firewall.

{
  "bot": "MyHostBot", "version": "0.1.12", "started_at": 1759480000,
  "lobby_players": 3, "ingame_players": 10,
  "games": [{
    "host_counter": 10, "name": "dota #10", "map": "Maps\\Download\\dota.w3x",
    "phase": "playing", "created_at": 1759481000, "started_at": 1759481300, "open_slots": 0,
    "players": [{ "name": "Alice", "slot": 0, "team": 0, "colour": 0, "observer": false, "reconnecting": false }]
  }]
}
  • phase: lobby (countdown included) / loading / playing; players lists human players only
  • bot is the instance's bnet account name. With several instances, poll each one separately and key games by (bot, started_at, host_counter); instances on one host need distinct status_bind ports
  • started_at (top level) changes when the bot restarts; host_counter restarts from 1 with it
  • If status_bind cannot be bound, the error is logged and the bot keeps running without the endpoint
  • Updates land within about a second of the change
  • Polling clients should reuse the connection (keep-alive), send the last ETag back as If-None-Match (an unchanged board answers 304 with no body), and send Accept-Encoding: gzip
  • Treat unknown fields as optional; fields may be added but are not renamed or removed

Credits & license

This project is a rewrite of GHost++ (originally by Trevor Hogan); all protocol knowledge and behavioral semantics derive from the original project. Licensed under the Apache License 2.0.

About

GHost++, the Warcraft III game hosting bot rewritten in Rust

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages