use std::env;
use std::fs::File;
use std::io::BufReader;
use std::path::Path;
use wow_adt::{AdtVersion, ParsedAdt, parse_adt};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
eprintln!("Usage: {} <path_to_adt_file>", args[0]);
eprintln!();
eprintln!("Example:");
eprintln!(" {} Azeroth_32_32.adt", args[0]);
std::process::exit(1);
}
let adt_path = &args[1];
if !Path::new(adt_path).exists() {
eprintln!("Error: File '{adt_path}' does not exist");
std::process::exit(1);
}
println!("Parsing ADT File: {adt_path}");
println!("{}", "=".repeat(50));
let file = File::open(adt_path)?;
let mut reader = BufReader::new(file);
let adt = parse_adt(&mut reader)?;
match adt {
ParsedAdt::Root(root) => {
display_root_adt(&root);
}
ParsedAdt::Tex0(tex) => {
println!("Texture file (Cataclysm+)");
println!(" Version: {:?}", tex.version);
println!(" Total textures: {}", tex.textures.len());
println!(" Chunks with texture data: {}", tex.mcnk_textures.len());
}
ParsedAdt::Obj0(obj) => {
println!("Object file (Cataclysm+)");
println!(" Version: {:?}", obj.version);
println!(" M2 models: {}", obj.models.len());
println!(" WMO objects: {}", obj.wmos.len());
println!(" Chunks with objects: {}", obj.mcnk_objects.len());
}
ParsedAdt::Lod(lod) => {
println!("LOD file (Cataclysm+)");
println!(" Version: {:?}", lod.version);
}
_ => {
println!("Split file (Cataclysm+)");
}
}
println!();
println!("Parsing completed successfully!");
Ok(())
}
fn display_root_adt(adt: &wow_adt::RootAdt) {
println!("Basic Information:");
println!(" Version: {:?}", adt.version);
println!(" Format: {}", get_format_description(adt.version));
let active_chunks = adt.terrain_chunk_count();
println!(" Active terrain chunks: {active_chunks}/256");
println!();
println!("Textures:");
println!(" Total textures: {}", adt.texture_count());
if !adt.textures.is_empty() {
println!(" Sample textures:");
for (i, texture) in adt.textures.iter().take(5).enumerate() {
println!(" {}. {}", i + 1, texture);
}
if adt.textures.len() > 5 {
println!(" ... and {} more", adt.textures.len() - 5);
}
}
println!();
println!("Doodad Models:");
println!(" Total models: {}", adt.model_count());
if !adt.models.is_empty() {
println!(" Sample models:");
for (i, model) in adt.models.iter().take(3).enumerate() {
println!(" {}. {}", i + 1, model);
}
if adt.models.len() > 3 {
println!(" ... and {} more", adt.models.len() - 3);
}
}
println!();
println!("World Map Objects (WMOs):");
println!(" Total WMOs: {}", adt.wmo_count());
if !adt.wmos.is_empty() {
println!(" Sample WMOs:");
for (i, wmo) in adt.wmos.iter().take(3).enumerate() {
println!(" {}. {}", i + 1, wmo);
}
if adt.wmos.len() > 3 {
println!(" ... and {} more", adt.wmos.len() - 3);
}
}
if let Some(mh2o) = &adt.water_data {
let water_chunks = mh2o
.entries
.iter()
.filter(|entry| entry.header.has_liquid())
.count();
if water_chunks > 0 {
println!();
println!("Water Information:");
println!(" Chunks with water: {water_chunks}/256");
for (i, entry) in mh2o.entries.iter().enumerate() {
if let Some(instance) = entry.instances.first() {
println!(" Sample water chunk {i} details:");
println!(" - Liquid type: {}", instance.liquid_type);
println!(
" - Dimensions: {}x{} tiles",
instance.width, instance.height
);
println!(" - Vertex count: {}", instance.vertex_count());
println!(
" - Height range: {:.2} - {:.2}",
instance.min_height_level, instance.max_height_level
);
break;
}
}
}
}
if let Some(mfbo) = &adt.flight_bounds {
println!();
println!("Flight Boundaries (36 bytes, 2 planes × 9 values):");
println!(
" Min plane first 2 values: ({}, {})",
mfbo.min_plane[0], mfbo.min_plane[1]
);
println!(
" Max plane first 2 values: ({}, {})",
mfbo.max_plane[0], mfbo.max_plane[1]
);
println!(" Total values per plane: 9 int16 coordinates");
}
}
fn get_format_description(version: AdtVersion) -> &'static str {
match version {
AdtVersion::VanillaEarly => "Classic World of Warcraft (1.x - Early)",
AdtVersion::VanillaLate => "Classic World of Warcraft (1.x - Late)",
AdtVersion::TBC => "The Burning Crusade (2.x)",
AdtVersion::WotLK => "Wrath of the Lich King (3.x)",
AdtVersion::Cataclysm => "Cataclysm (4.x)",
AdtVersion::MoP => "Mists of Pandaria (5.x)",
}
}