wow_wmo/lib.rs
1//! # World of Warcraft WMO (World Map Object) Parser
2//!
3//! This library provides comprehensive support for parsing, editing, validating, and converting
4//! World of Warcraft WMO files across all game expansions from Classic to The War Within.
5//!
6//! ## Features
7//!
8//! - **Parsing**: Read WMO root and group files with full chunk support
9//! - **Validation**: Verify file integrity and format compliance
10//! - **Conversion**: Convert between different WoW expansion formats
11//! - **Editing**: Modify WMO properties, geometry, and metadata
12//! - **Export**: Export to common 3D formats (OBJ/MTL)
13//! - **Type Safety**: Strongly typed structures for all WMO components
14//!
15//! ## Quick Start
16//!
17//! ```no_run
18//! use std::fs::File;
19//! use std::io::BufReader;
20//! use wow_wmo::{parse_wmo, WmoVersion};
21//!
22//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
23//! // Parse a WMO file
24//! let file = File::open("example.wmo")?;
25//! let mut reader = BufReader::new(file);
26//! let wmo = parse_wmo(&mut reader)?;
27//!
28//! // Access WMO data
29//! println!("Version: {:?}", wmo.version);
30//! println!("Groups: {}", wmo.groups.len());
31//! println!("Materials: {}", wmo.materials.len());
32//! # Ok(())
33//! # }
34//! ```
35//!
36//! ## Example: Validating a WMO File
37//!
38//! ```no_run
39//! use std::fs::File;
40//! use std::io::BufReader;
41//! use wow_wmo::{WmoParser, WmoValidator};
42//!
43//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
44//! // Parse the WMO
45//! let file = File::open("building.wmo")?;
46//! let mut reader = BufReader::new(file);
47//! let wmo = WmoParser::new().parse_root(&mut reader)?;
48//!
49//! // Validate it
50//! let validator = WmoValidator::new();
51//! let report = validator.validate_root(&wmo)?;
52//!
53//! if !report.errors.is_empty() {
54//! println!("Validation errors found:");
55//! for error in &report.errors {
56//! println!(" - {:?}", error);
57//! }
58//! }
59//!
60//! if !report.warnings.is_empty() {
61//! println!("Validation warnings:");
62//! for warning in &report.warnings {
63//! println!(" - {:?}", warning);
64//! }
65//! }
66//! # Ok(())
67//! # }
68//! ```
69//!
70//! ## Modules
71//!
72//! - [`chunk`]: Low-level chunk reading/writing functionality
73//! - [`parser`]: WMO root file parser
74//! - [`group_parser`]: WMO group file parser
75//! - [`types`]: Common data types (Vec3, Color, BoundingBox, etc.)
76//! - [`wmo_types`]: WMO root file structures
77//! - [`wmo_group_types`]: WMO group file structures
78//! - [`validator`]: File validation and integrity checking
79//! - [`converter`]: Version conversion between expansions
80//! - [`editor`]: High-level editing API
81//! - [`writer`]: Binary serialization
82//! - [`visualizer`]: 3D export functionality
83//! - [`version`]: Version detection and feature support
84//! - [`error`]: Error types and handling
85//!
86//! ## Supported Formats
87//!
88//! This library supports WMO files from all World of Warcraft expansions:
89//! - Classic (1.12)
90//! - The Burning Crusade (2.4.3)
91//! - Wrath of the Lich King (3.3.5)
92//! - Cataclysm (4.3.4)
93//! - Mists of Pandaria (5.4.8)
94//! - Warlords of Draenor (6.2.4)
95//! - Legion (7.3.5)
96//! - Battle for Azeroth (8.3.7)
97//! - Shadowlands (9.2.7)
98//! - Dragonflight (10.2.0)
99//! - The War Within (11.0+)
100
101pub mod chunk;
102pub mod converter;
103pub mod error;
104pub mod group_parser;
105pub mod parser;
106pub mod types;
107pub mod validator;
108pub mod version;
109pub mod wmo_group_types;
110pub mod wmo_types;
111pub mod writer;
112
113// Additional modules
114pub mod editor;
115pub mod visualizer;
116
117// Test module (only compiled for tests)
118#[cfg(test)]
119mod tests;
120
121pub use converter::WmoConverter;
122pub use editor::WmoEditor;
123pub use error::{Result, WmoError};
124pub use group_parser::WmoGroupParser;
125pub use parser::{WmoParser, chunks};
126pub use types::{BoundingBox, ChunkId, Color, Vec3};
127pub use validator::{ValidationError, ValidationReport, ValidationWarning, WmoValidator};
128pub use version::{WmoFeature, WmoVersion};
129pub use visualizer::WmoVisualizer;
130// Re-export all types from wmo_types
131pub use wmo_types::{
132 WmoDoodadDef, WmoDoodadSet, WmoFlags, WmoGroupInfo, WmoHeader, WmoLight, WmoLightProperties,
133 WmoLightType, WmoMaterial, WmoMaterialFlags, WmoPortal, WmoPortalReference, WmoRoot,
134};
135
136// Re-export all types from wmo_group_types (except WmoGroupFlags which conflicts)
137pub use wmo_group_types::{
138 TexCoord, WmoBatch, WmoBspNode, WmoGroup, WmoGroupFlags, WmoGroupHeader, WmoLiquid,
139 WmoLiquidVertex, WmoMaterialInfo, WmoPlane,
140};
141pub use writer::WmoWriter;
142
143/// Re-export of chunk-related types
144pub use chunk::{Chunk, ChunkHeader};
145
146/// Parse a WMO root file from a reader
147pub fn parse_wmo<R: std::io::Read + std::io::Seek>(reader: &mut R) -> Result<WmoRoot> {
148 let parser = WmoParser::new();
149 parser.parse_root(reader)
150}
151
152/// Parse a WMO group file from a reader
153pub fn parse_wmo_group<R: std::io::Read + std::io::Seek>(
154 reader: &mut R,
155 group_index: u32,
156) -> Result<WmoGroup> {
157 let parser = WmoGroupParser::new();
158 parser.parse_group(reader, group_index)
159}
160
161/// Validate a WMO file from a reader
162pub fn validate_wmo<R: std::io::Read + std::io::Seek>(reader: &mut R) -> Result<bool> {
163 // A simple validation just checks if we can parse the file without errors
164 match parse_wmo(reader) {
165 Ok(_) => Ok(true),
166 Err(e) => {
167 // If it's a format error, return false. Otherwise, propagate the error.
168 match e {
169 WmoError::InvalidFormat(_)
170 | WmoError::InvalidMagic { .. }
171 | WmoError::InvalidVersion(_)
172 | WmoError::MissingRequiredChunk(_) => Ok(false),
173 _ => Err(e),
174 }
175 }
176 }
177}
178
179/// Perform detailed validation on a WMO root file
180pub fn validate_wmo_detailed<R: std::io::Read + std::io::Seek>(
181 reader: &mut R,
182) -> Result<ValidationReport> {
183 let wmo = parse_wmo(reader)?;
184 let validator = WmoValidator::new();
185 validator.validate_root(&wmo)
186}
187
188/// Perform detailed validation on a WMO group file
189pub fn validate_wmo_group_detailed<R: std::io::Read + std::io::Seek>(
190 reader: &mut R,
191 group_index: u32,
192) -> Result<ValidationReport> {
193 let group = parse_wmo_group(reader, group_index)?;
194 let validator = WmoValidator::new();
195 validator.validate_group(&group)
196}
197
198/// Convert a WMO file from one version to another
199pub fn convert_wmo<R, W>(reader: &mut R, writer: &mut W, target_version: WmoVersion) -> Result<()>
200where
201 R: std::io::Read + std::io::Seek,
202 W: std::io::Write + std::io::Seek,
203{
204 let mut wmo = parse_wmo(reader)?;
205
206 // Convert WMO to target version
207 let converter = WmoConverter::new();
208 converter.convert_root(&mut wmo, target_version)?;
209
210 // Write converted WMO
211 let writer_obj = WmoWriter::new();
212 writer_obj.write_root(writer, &wmo, target_version)?;
213
214 Ok(())
215}
216
217/// Convert a WMO group file from one version to another
218pub fn convert_wmo_group<R, W>(
219 reader: &mut R,
220 writer: &mut W,
221 target_version: WmoVersion,
222 group_index: u32,
223) -> Result<()>
224where
225 R: std::io::Read + std::io::Seek,
226 W: std::io::Write + std::io::Seek,
227{
228 // Read root file first to get current version
229 let wmo = parse_wmo(reader)?;
230 let current_version = wmo.version;
231
232 // Now read group file
233 reader.rewind()?;
234 let mut group = parse_wmo_group(reader, group_index)?;
235
236 // Convert group to target version
237 let converter = WmoConverter::new();
238 converter.convert_group(&mut group, target_version, current_version)?;
239
240 // Write converted group
241 let writer_obj = WmoWriter::new();
242 writer_obj.write_group(writer, &group, target_version)?;
243
244 Ok(())
245}