war3parser 0.5.1

A extractor and parser for Warcraft 3 map files
Documentation

war3parser

Crates.io Version docs.rs NPM Version GitHub Actions Workflow Status GitHub Release

war3parser is a library for parsing and extracting Warcraft III map files. It extracts data from MPQ archives and parses common map formats across classic and Reforged versions — the w3i parser covers the full format ladder v8 → v33 (RoC betas through WC3 2.0).

Workspace layout

crates/
  core/   # war3parser        — pure parsing + shared model (no wasm-bindgen by default)
  cli/    # war3parser-cli    — thin CLI over core
  wasm/   # war3parser-wasm   — thin wasm-bindgen glue over core::model::MapSnapshot
Crate Depends on Notes
war3parser (core) pure Rust + optional serde (default); no wasm-bindgen/tsify
war3parser-cli core + serde never pulls wasm-bindgen
war3parser-wasm core + serde-wasm-bindgen thin parse_map / version; hand-maintained war3parser.d.ts

Core module layout:

crates/core/src/
  archive.rs   # War3MapW3x — HM3W header + embedded MPQ access
  formats/     # per-file parsers: w3i (v8→v33), wts, imp, mmp
  model/       # portable API types: MapSnapshot, War3MapMetadata, images
  reader.rs    # bounds-checked little-endian ByteReader
  error.rs     # crate-wide Error

Shared API types (MapSnapshot, War3ImageData, ImportEntry, StringTableEntry, War3MapHeader, …) live in war3parser::model so CLI and WASM do not redefine DTOs.

Features

  • Extract files from MPQ archives (by known name)
  • Parse w3i map info across versions 8 → 33 (RoC betas, ROC, TFT, 1.31+, Reforged, WC3 2.0)
  • Parse wts string tables (comment lines, \n / \r\n, BOM)
  • Parse imp imports, minimap/preview BLP/TGA images
  • Handle protected / headerless maps (no HM3W, truncated optional w3i sections, missing listfile, inflated MPQ table counts, hash entries that wrap around the table)
  • Detect known third-party script modifications (war3parser::modscan)
  • WASM bindings + browser playground

MPQ reader

MPQ reading comes from war3-mpq, a fork of mpq 0.8.1. Upstream trusts values that come straight out of the archive — block-table indices, per-sector offsets, table counts — which map protectors deliberately falsify, and it stops probing the hash table at the end instead of wrapping around, so some files are unreachable by name. Over a 10365-map archive the fixes took readable maps from 9218 to 9746.

It is pulled in under the name mpq, so the source reads the same:

mpq = { package = "war3-mpq", version = "0.9" }

A [patch.crates-io] would have been invisible to anyone installing this crate from the registry — Cargo only honours [patch] from the final workspace root.

Modification detection

modscan recognises injected cheat scripts from literals the injector cannot remove, and reports how the injected menu is triggered in game. It needs only the map at hand — no unmodified copy to diff against. parse_map exposes it as modification; dump-metadata writes modification.json. A None result means "no known signature matched", not "clean": a protected map whose script cannot be read looks the same.

Usage

as a library

cargo add war3parser
use war3parser::prelude::War3MapMetadata;

let buffer = std::fs::read("path/to/map.w3x").unwrap();
let mut metadata = War3MapMetadata::parse(&buffer).unwrap();
metadata.resolve_trigger_strings();

// Portable snapshot shared with the WASM API
let snapshot = metadata.snapshot().unwrap();
println!("{:?}", snapshot.map_info.as_ref().map(|i| &i.name));

metadata.save("out").unwrap();
// or: War3MapMetadata::parse_snapshot(&buffer)

as a CLI

cargo install war3parser-cli
$ war3parser-cli help
A extractor and parser for Warcraft 3 map files

Usage: war3parser-cli <COMMAND>

Commands:
  dump-metadata   Dump metadata from a map file [aliases: d]
  extract-file    Extract a file from a MPQ archive and save it [aliases: x]
  extract-images  Extract images with *.tga and *.blp extensions [aliases: i]
  convert-image   Convert a *tga/blp file to png [aliases: c]
  list-files      List files in a MPQ archive [aliases: l]
  help            Print this message or the help of the given subcommand(s)

Options:
  -h, --help     Print help
  -V, --version  Print version

as WASM

npm install @wesleyel/war3parser
import init, { parse_map, parse_map_result, list_files, extract_file, detect_modification, version }
  from "@wesleyel/war3parser";

await init();
const meta = parse_map(new Uint8Array(buffer));
console.log(version(), meta?.map_info?.name, meta?.strings?.length);

// Why a map failed, instead of a bare `undefined`
const result = parse_map_result(new Uint8Array(buffer));
if (!result.ok) console.warn(result.error);

// Reach into the archive directly
const script = extract_file(new Uint8Array(buffer), "war3map.j");
const files = list_files(new Uint8Array(buffer));
const injected = detect_modification(new Uint8Array(buffer));

parse_map returns:

  • header — HM3W presence/name/max players
  • map_info — full w3i (TRIGSTR-resolved when .wts is present)
  • images — minimap/preview as PNG data URLs
  • importswar3map.imp entries
  • strings — sorted WTS entries
  • files(listfile) paths when available
  • parse_ms — parse duration

get_map_info remains as a compatible alias of parse_map.

Web playground

Live: https://wesleyel.github.io/war3parser/

Local demo (builds WASM first):

just serve-playground
# → http://localhost:5173/

Drop any .w3x / .w3m. Parsing is 100% in-browser; nothing is uploaded.

Static / GitHub Pages build:

just build-playground   # relative base, output: playground/dist-site/
just build-pages        # base=/war3parser/ for GitHub Pages

The playground is Vite + React with a Real World Materials UI. CI deploys it to GitHub Pages on pushes to main (see .github/workflows/pages.yml). Enable Settings → Pages → Source: GitHub Actions once.

w3i version support

The version ladder follows War3Net, the most complete open reference:

Version Era Notes
8–15 RoC beta Legacy layouts (no save count pre-18, no subtitles pre-15)
18 ROC Campaign background, loading screen index
23–24 early TFT Fog, sound environment, game data set; random item tables (24)
25 TFT Global weather
26–27 TFT patches Trailing marker int (26–27), game build version (27)
28 1.31 Script language (JASS/Lua)
31 Reforged Graphics modes, game data version, enemy priorities
32–33 WC3 2.0 Camera zoom limits (32: default+max, 33: +min)
* unknown Future/gap versions parse with the nearest known layout
* protected 0xFF optional-section skip after forces; tolerant truncation

Contributing

Contributions are welcome! Please submit a Pull Request or report an Issue.

License

war3parser is licensed under the MIT License. See the LICENSE file for details.