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,_lodfile 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 filesmerger- Utilities for merging split files into unified structuressplit_set- Split file discovery and path managementchunk_discovery- Discovery phase for fast chunk enumerationchunk_header- ChunkHeader binrw structure (8-byte magic + size)chunk_id- ChunkId type with reversed magic constantsversion- AdtVersion enum and detection logicfile_type- AdtFileType enum (Root, Tex0, Obj0, etc.)error- AdtError types with detailed contextchunks- Chunk structure definitions (MVER, MHDR, MCNK, etc.)
§References
Based on information from:
- WoW.dev ADT Format - Format specification
- TrinityCore - Server reference
- noggit-red - Map editor reference
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