Thanks to visit codestin.com
Credit goes to lib.rs

#archive #warcraft #blizzard #mopaq

bin+lib mpq-rs

A pure-rust implementation of a MoPaQ archive reader and writer

1 unstable release

Uses new Rust 2024

0.1.0 Oct 15, 2025

#1796 in Parser implementations

MIT license

56KB
1K SLoC

mpq-rs

mpq-rs is a pure-Rust implementation of the MoPaQ archive format used in Blizzard titles such as Warcraft III. The crate lets you inspect MPQ archives, extract files, and build new archives without relying on native libraries.

Features

  • Reads version 1 MPQ archives (classic Warcraft III maps).
  • Extracts files, automatically handling the supported compression schemes.
  • Builds new archives with sensible compression defaults.
  • Operates on any data source that implements Read + Seek.

Warning: the crate does not aim to support "protected" maps that intentionally violate the MPQ specification.

Installation

Add the dependency to your Cargo.toml:

[dependencies]
mpq-rs = { git = "https://github.com/WarRaft/mpq-rs" }

Usage examples

Reading a file from an archive

use std::fs::File;
use std::io::BufReader;
use mpq_rs::Archive;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let file = File::open("maps/example.w3x")?;
    let mut archive = Archive::open(BufReader::new(file))?;

    let script = archive.read_file("war3map.j")?;
    println!("Map script size: {} bytes", script.len());

    Ok(())
}

Listing files via (listfile)

use std::fs::File;
use std::io::BufReader;
use mpq_rs::Archive;

fn list_files(path: &str) -> Result<(), Box<dyn std::error::Error>> {
    let file = File::open(path)?;
    let mut archive = Archive::open(BufReader::new(file))?;

    if let Some(entries) = archive.files() {
        for entry in entries {
            println!("{entry}");
        }
    } else {
        println!("Archive does not contain (listfile)");
    }

    Ok(())
}

Creating an archive

use std::io::Cursor;
use mpq_rs::{Creator, FileOptions};

fn build_archive() -> Result<Vec<u8>, Box<dyn std::error::Error>> {
    let mut buffer = Cursor::new(Vec::new());
    let mut creator = Creator::default();

    creator.add_file(
        "hello.txt",
        "Greetings from MPQ!",
        FileOptions {
            encrypt: false,
            compress: true,
            adjust_key: false,
        },
    );

    creator.write(&mut buffer)?;
    Ok(buffer.into_inner())
}

Test data

Sample Warcraft III maps for experimentation can be found under test-data/maps.

Running tests

cargo test

Dependencies

~1.5MB
~30K SLoC