# WebWars — Hedgewars in Your Browser A browser port of [**Hedgewars**](https://hedgewars.org/), the free turn-based artillery game. No downloads, no installs — just open a link and play. This project is built on top of [Hedgewars](https://github.com/hedgewars/hw) (GPL v2), created by Andrey Korotaev (unC0Rr) and the Hedgewars community. The game engine is written in Free Pascal — a language with no native WebAssembly target. What makes this port possible is [**pas2c**](https://github.com/hedgewars/hw/tree/master/tools/pas2c), a Pascal-to-C transpiler written by unC0Rr specifically for the Hedgewars project. pas2c converts the entire engine (~40K lines of Pascal) into C, which I then compile to WebAssembly through Emscripten. Without pas2c, this project simply wouldn't exist. The game server is also theirs — a Haskell binary that handles lobby, rooms, and multiplayer relay. All game assets (graphics, sounds, fonts, maps, 117 Lua scripts) are from the Hedgewars project. I wrote the browser integration layer, the WebSocket gateway, and the web frontend — but the game itself is entirely their work. Huge thanks to unC0Rr and the Hedgewars team for building such a great game and releasing it as free software. **🎮 Play now: [webwars.link](https://webwars.link)** ## Quick Start **Solo (hotseat):** Open [webwars.link](https://webwars.link) — two teams on one keyboard, taking turns. Right-click to pick a weapon, Space to fire, Arrow keys to move. **Custom game:** Open [webwars.link/play.html](https://webwars.link/play.html) to choose a theme (30 options), game style (22 modes like Racer, Shoppa, King), scheme, and weapon set before starting. **Multiplayer:** Open [webwars.link/lobby.html](https://webwars.link/lobby.html) in two browser tabs: 1. Enter a nickname and click Connect 2. One player creates a room, the other joins it 3. Both players add a team, then the room chief starts the game ## How It Works Hedgewars is written in Pascal. I compile it to WebAssembly using this pipeline: ``` Pascal → pas2c (Pascal-to-C) → C → Emscripten → WebAssembly ``` The engine runs natively in the browser at 60fps. Multiplayer uses the real Hedgewars server — a WebSocket gateway bridges browsers to the TCP-based server protocol. ``` Browser (WASM engine) ←WebSocket→ Gateway (Node.js) ←TCP→ Hedgewars Server (Haskell) ``` | Component | Tech | Description | |-----------|------|-------------| | Game engine | WebAssembly (3.97MB) | Full Hedgewars engine compiled from Pascal via C | | Core assets | Preloaded .data (7MB) | Sprites, shaders, fonts, sounds, scripts, Nature theme | | Theme assets | Fetched on demand (~3-7MB) | 29 themes + music loaded dynamically per game | | WS gateway | Node.js | Bridges browser WebSocket to HW server TCP | | Game server | Haskell | Official Hedgewars server (rooms, relay, protocol) | | Admin panel | Flask + Leaflet | Live traffic map, visitor geo, bot detection | ## Building from Source ### Prerequisites - Linux (tested on Ubuntu 22.04) - [Emscripten SDK](https://emscripten.org/docs/getting_started/downloads.html) - Rust with `wasm32-unknown-emscripten` target - Node.js 18+ - GHC 9.4+ and Cabal (for the game server) - CMake 3.20+ ### Build & Run ```bash # 1. Build the WASM engine source ~/emsdk/emsdk_env.sh source ~/.cargo/env mkdir -p build/wasm && cd build/wasm && rm -rf * cmake ../../hedgewars -DBUILD_ENGINE_JS=ON -DNOSERVER=ON \ -DCMAKE_TOOLCHAIN_FILE=$EMSDK/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake make -j$(nproc) cp ../../web/*.html ../../web/*.js bin/ # 2. Build the game server cd ../../hedgewars/gameServer && cabal build # 3. Run all three services ./bin/hedgewars-server & cd gateway && npm install && WS_PORT=8080 HW_HOST=localhost HW_PORT=46631 node src/index.js & cd build/wasm/bin && python3 -m http.server 8081 --bind 0.0.0.0 ``` Open http://localhost:8081 in your browser. ## Project Structure ``` webwars/ ├── hedgewars/ # Hedgewars source (forked, with WASM patches) │ ├── hedgewars/ # Pascal engine source │ ├── project_files/hwc/ # C shims: IPC bridge, main loop wrapper │ ├── project_files/web/ # pre.js / post.js (browser integration) │ └── gameServer/ # Haskell multiplayer server ├── generated/pas2c/ # C source generated by pas2c (62 .c + 64 .h files) ├── dist/ # Final WASM build output (see below) ├── gateway/src/index.js # WebSocket ↔ TCP bridge ├── web/ # Browser frontend (menu, quick play, lobby, game config) ├── admin/ # Admin panel (Flask + Leaflet dashboard) └── scripts/ # Build scripts ``` ### Build Outputs (`dist/`) | File | Size | Checked in? | Description | |------|------|-------------|-------------| | `hwengine.wasm` | 3.8MB | ✅ Yes | Compiled engine (WebAssembly binary) | | `hwengine.js` | 2.2MB | ✅ Yes | Emscripten glue code (loads and runs the WASM) | | `hwengine.data` | 187MB | ❌ Gitignored | Game assets (graphics, sounds, fonts, maps, Lua scripts) | The `.data` file is too large for git. It's generated during the build by Emscripten's `--preload-file` which packages the entire `Data/` directory. Run the build to generate it, or download it from [webwars.link/hwengine.data](https://webwars.link/hwengine.data). The `generated/` directory contains the intermediate C source produced by pas2c — see [`generated/README.md`](generated/README.md) for details. ## What I Built This isn't just "compile and ship." Hedgewars was designed as a desktop app with a Qt/C++ frontend (~95K lines), TCP socket IPC, and OpenGL rendering. None of that works in a browser. Here's what I had to build or rewrite: ### Web Frontend (replaces Qt desktop client) The original Hedgewars client is a full Qt desktop application that handles the lobby, room management, team configuration, and game launch. I replaced all of it with ~1,600 lines of HTML/JS across four files: a lobby page, a quick-play page, a menu page with custom game setup, and a shared config module. The lobby connects to the real Hedgewars server through my WebSocket gateway, implementing the same text-based protocol the Qt client speaks. A key design decision: the game engine loads dynamically into the lobby page via `