Crate wow_adt

Crate wow_adt 

Source
Expand description

Two-pass parser for World of Warcraft ADT terrain files using binrw.

This library implements a clean, type-safe parser for ADT (A Dungeon Terrain) files from World of Warcraft using the binrw serialization framework. It supports all ADT format versions from Vanilla (1.12.1) through Mists of Pandaria (5.4.8).

§Architecture

The parser follows a two-pass architecture:

Pass 1 (Discovery): Fast chunk enumeration without parsing chunk data. Identifies version, file type, and chunk locations for selective parsing.

Pass 2 (Parse): Type-safe extraction of chunk data into binrw-derived structures with automatic offset resolution.

§Supported Versions

  • Vanilla (1.x) - Basic terrain chunks (MVER, MHDR, MCNK)
  • The Burning Crusade (2.x) - Flight boundaries (MFBO chunk)
  • Wrath of the Lich King (3.x) - Enhanced water/lava system (MH2O chunk)
  • Cataclysm (4.x) - Split file architecture, texture amplifiers (MAMP chunk)
  • Mists of Pandaria (5.x) - Texture parameters (MTXP chunk)

Version detection is automatic based on chunk presence and structure analysis.

§Quick Start

use std::fs::File;
use std::io::BufReader;
use wow_adt::{parse_adt, ParsedAdt};

// Parse any ADT file with automatic version detection
let file = File::open("world/maps/azeroth/azeroth_32_32.adt")?;
let mut reader = BufReader::new(file);
let adt = parse_adt(&mut reader)?;

// Access terrain data based on file type
match adt {
    ParsedAdt::Root(root) => {
        println!("Version: {:?}", root.version);
        println!("Terrain chunks: {}", root.mcnk_chunks.len());
        println!("Textures: {}", root.textures.len());

        // Access water data (WotLK+)
        if let Some(water) = &root.water_data {
            for (idx, entry) in water.entries.iter().enumerate() {
                if entry.header.has_liquid() {
                    println!("Chunk {} has {} water layer(s)",
                        idx, entry.instances.len());
                }
            }
        }
    }
    ParsedAdt::Tex0(tex) => {
        println!("Texture file with {} entries", tex.textures.len());
    }
    ParsedAdt::Obj0(obj) => {
        println!("Object file with {} models", obj.models.len());
    }
    _ => {}
}

§Example: Fast Chunk Discovery

use std::fs::File;
use wow_adt::{discover_chunks, ChunkId};

let mut file = File::open("terrain.adt")?;
let discovery = discover_chunks(&mut file)?;

println!("Total chunks: {}", discovery.total_chunks);

// Check for specific chunks without full parsing
if discovery.has_chunk(ChunkId::MH2O) {
    println!("File contains advanced water (WotLK+)");
}

// Selective parsing: only parse specific chunks
for chunk_id in discovery.chunk_types() {
    println!("Found chunk: {}", chunk_id.as_str());
}

§Example: Building ADT Files

use wow_adt::builder::AdtBuilder;
use wow_adt::{AdtVersion, DoodadPlacement};

let adt = AdtBuilder::new()
    .with_version(AdtVersion::WotLK)
    .add_texture("terrain/grass_01.blp")
    .add_texture("terrain/dirt_01.blp")
    .add_model("doodad/tree_01.m2")
    .add_doodad_placement(DoodadPlacement {
        name_id: 0,
        unique_id: 1,
        position: [1000.0, 1000.0, 100.0],
        rotation: [0.0, 0.0, 0.0],
        scale: 1024,
        flags: 0,
    })
    .build()?;

adt.write_to_file("world/maps/custom/custom_32_32.adt")?;

§Example: Loading Split Files (Cataclysm+)

use wow_adt::AdtSet;

// Load complete split file set (automatically discovers _tex0, _obj0, _lod files)
let adt_set = AdtSet::load_from_path("World/Maps/Azeroth/Azeroth_30_30.adt")?;

// Check if complete set
if adt_set.is_complete() {
    println!("Complete Cataclysm+ split file set");
    println!("Version: {:?}", adt_set.version());
}

// Merge split files into unified structure
let merged = adt_set.merge()?;
println!("Merged {} MCNK chunks", merged.mcnk_chunks.len());
println!("Textures: {}", merged.textures.len());
println!("Models: {}", merged.models.len());

§Features

  • Automatic version detection - Identifies WoW client version from chunk analysis
  • Split file support - Cataclysm+ _tex0, _obj0, _obj1, _lod file handling
  • Type-safe parsing - binrw derives for zero-overhead serialization
  • Fast discovery - <10ms chunk inventory for selective parsing
  • Builder API - Fluent builder for programmatically constructing ADT files

§Modules

  • adt_set - High-level API for loading complete split file sets (Cataclysm+)
  • api - Core parser API (parse_adt, ParsedAdt enum)
  • builder - Fluent builder API for constructing ADT files
  • merger - Utilities for merging split files into unified structures
  • split_set - Split file discovery and path management
  • chunk_discovery - Discovery phase for fast chunk enumeration
  • chunk_header - ChunkHeader binrw structure (8-byte magic + size)
  • chunk_id - ChunkId type with reversed magic constants
  • version - AdtVersion enum and detection logic
  • file_type - AdtFileType enum (Root, Tex0, Obj0, etc.)
  • error - AdtError types with detailed context
  • chunks - Chunk structure definitions (MVER, MHDR, MCNK, etc.)

§References

Based on information from:

Re-exports§

pub use adt_set::AdtSet;
pub use api::AdtMetadata;
pub use api::LodAdt;
pub use api::McnkChunkObject;
pub use api::McnkChunkTexture;
pub use api::Obj0Adt;
pub use api::ObjectAdt;
pub use api::ParsedAdt;
pub use api::RootAdt;
pub use api::Tex0Adt;
pub use api::TextureAdt;
pub use api::parse_adt;
pub use api::parse_adt_with_metadata;
pub use builder::AdtBuilder;
pub use builder::BuiltAdt;
pub use chunk_discovery::ChunkDiscovery;
pub use chunk_discovery::ChunkLocation;
pub use chunk_discovery::discover_chunks;
pub use chunk_header::ChunkHeader;
pub use chunk_id::ChunkId;
pub use combined_alpha_map::CombinedAlphaMap;
pub use error::AdtError;
pub use error::Result;
pub use file_type::AdtFileType;
pub use version::AdtVersion;
pub use chunks::AlphaFormat;
pub use chunks::AlphaMap;
pub use chunks::DepthOnlyVertex;
pub use chunks::DoodadPlacement;
pub use chunks::HeightDepthVertex;
pub use chunks::HeightUvDepthVertex;
pub use chunks::HeightUvVertex;
pub use chunks::LiquidType;
pub use chunks::LiquidVertexFormat;
pub use chunks::MampChunk;
pub use chunks::McalChunk;
pub use chunks::MccvChunk;
pub use chunks::McinChunk;
pub use chunks::McinEntry;
pub use chunks::MclqChunk;
pub use chunks::MclyChunk;
pub use chunks::MclyFlags;
pub use chunks::MclyLayer;
pub use chunks::McnkChunk;
pub use chunks::McnkFlags;
pub use chunks::McnkHeader;
pub use chunks::McnrChunk;
pub use chunks::McrfChunk;
pub use chunks::McseChunk;
pub use chunks::McshChunk;
pub use chunks::McvtChunk;
pub use chunks::MddfChunk;
pub use chunks::MfboChunk;
pub use chunks::Mh2oAttributes;
pub use chunks::Mh2oChunk;
pub use chunks::Mh2oEntry;
pub use chunks::Mh2oHeader;
pub use chunks::Mh2oInstance;
pub use chunks::MhdrChunk;
pub use chunks::MmdxChunk;
pub use chunks::MmidChunk;
pub use chunks::ModfChunk;
pub use chunks::MtexChunk;
pub use chunks::MtxpChunk;
pub use chunks::MverChunk;
pub use chunks::MwidChunk;
pub use chunks::MwmoChunk;
pub use chunks::SoundEmitter;
pub use chunks::TextureHeightParams;
pub use chunks::UvMapEntry;
pub use chunks::VertexColor;
pub use chunks::VertexNormal;
pub use chunks::WmoPlacement;

Modules§

adt_set
High-level API for loading complete ADT split file sets.
api
High-level parser API for ADT terrain files.
builder
Builder API for programmatically constructing ADT terrain files.
chunk_discovery
Fast chunk discovery phase for two-pass parsing
chunk_header
ADT chunk header parsing
chunk_id
chunks
ADT chunk structure definitions.
combined_alpha_map
error
Error types for ADT file parsing and validation.
file_type
ADT file type detection and classification.
merger
Merge split ADT files into unified RootAdt structure.
split_set
Split ADT file set discovery and management.
version