изменил структуру

This commit is contained in:
2026-03-28 13:44:26 +04:00
parent e71f9608c3
commit e4a0cc2c36
513 changed files with 99 additions and 72 deletions
+76 -36
View File
@@ -1,51 +1,47 @@
use std::env;
use std::error::Error;
use std::path::PathBuf;
use std::fs;
use std::path::{Path, PathBuf};
use walkdir::WalkDir;
use wow_mpq::compression::flags;
use wow_mpq::{ArchiveBuilder, FormatVersion, ListfileOption};
fn main() -> Result<(), Box<dyn Error>> {
// Read arguments
let args: Vec<String> = env::args().collect();
/// Checks if a directory name looks like a WoW locale folder (e.g. ruRU, enUS, deDE).
fn is_locale_dir(name: &str) -> bool {
if name.len() != 4 {
return false;
}
let b = name.as_bytes();
b[0].is_ascii_lowercase()
&& b[1].is_ascii_lowercase()
&& b[2].is_ascii_uppercase()
&& b[3].is_ascii_uppercase()
}
if args.len() != 3 {
eprintln!("Usage: mpq-builder <input_dir> <output.MPQ>");
std::process::exit(1);
fn build_mpq(input_dir: &Path, output_path: &Path) -> Result<(), Box<dyn Error>> {
let mut output = output_path.to_path_buf();
output.set_extension("MPQ");
if let Some(parent) = output.parent() {
fs::create_dir_all(parent)?;
}
let input_dir = PathBuf::from(&args[1]);
let mut output_file = PathBuf::from(&args[2]);
output_file.set_extension("MPQ");
if !input_dir.exists() {
return Err("Input directory does not exist".into());
}
// Normalize base path (important for Windows)
let base = input_dir.canonicalize()?;
println!("Packing: {} -> {}", base.display(), output.display());
println!("Input directory: {}", base.display());
println!("Output file: {}", output_file.display());
// Configure MPQ builder
let mut builder = ArchiveBuilder::new()
.version(FormatVersion::V2)
.block_size(7) // 64KB sectors
.block_size(7) // 64 KB sectors
.default_compression(flags::ZLIB)
.listfile_option(ListfileOption::Generate);
// Walk directory
for entry in WalkDir::new(&base)
.into_iter()
.filter_map(|e| e.ok())
.filter(|e| e.file_type().is_file())
{
// Canonicalize each file path to avoid StripPrefixError.
let full_path = entry.path().canonicalize()?;
// Safely compute relative path
let rel_path = match full_path.strip_prefix(&base) {
Ok(p) => p,
Err(_) => {
@@ -53,19 +49,63 @@ fn main() -> Result<(), Box<dyn Error>> {
continue;
}
};
// Convert to MPQ-style path (forward slashes)
let archive_path = rel_path.to_string_lossy().replace("\\", "/");
println!("Adding: {}", archive_path);
let archive_path = rel_path.to_string_lossy().replace('\\', "/");
println!(" Adding: {}", archive_path);
builder = builder.add_file(&full_path, &archive_path);
}
// Build archive
builder.build(&output_file)?;
println!("MPQ archive created: {}", output_file.display());
builder.build(&output)?;
println!("Created: {}", output.display());
Ok(())
}
fn main() -> Result<(), Box<dyn Error>> {
let args: Vec<String> = env::args().collect();
if args.len() != 3 {
eprintln!("Usage: tool <src_dir> <output_dir>");
eprintln!();
eprintln!(" src_dir — root of source tree (must contain Data/)");
eprintln!(" output_dir — destination root; MPQs are placed mirroring the src structure");
std::process::exit(1);
}
let src_dir = PathBuf::from(&args[1]);
let output_dir = PathBuf::from(&args[2]);
let data_dir = src_dir.join("Data");
if !data_dir.exists() {
return Err(format!("Data/ not found inside src_dir: {}", src_dir.display()).into());
}
for entry in fs::read_dir(&data_dir)? {
let entry = entry?;
let path = entry.path();
if !path.is_dir() {
continue;
}
let name = entry.file_name().to_string_lossy().to_string();
if is_locale_dir(&name) {
// e.g. ruRU/ — iterate its immediate subdirs, each is a patch source
for sub in fs::read_dir(&path)? {
let sub = sub?;
let sub_path = sub.path();
if !sub_path.is_dir() {
continue;
}
let sub_name = sub.file_name().to_string_lossy().to_string();
let output_mpq = output_dir.join("Data").join(&name).join(&sub_name);
build_mpq(&sub_path, &output_mpq)?;
}
} else {
// Regular patch dir, e.g. patch-4/ or patch-Z/
let output_mpq = output_dir.join("Data").join(&name);
build_mpq(&path, &output_mpq)?;
}
}
println!("\nAll MPQ archives built successfully.");
Ok(())
}