diff --git a/CUSTOM_CREATURES.md b/CUSTOM_CREATURES.md index c04994f..76edba2 100644 --- a/CUSTOM_CREATURES.md +++ b/CUSTOM_CREATURES.md @@ -27,7 +27,8 @@ При обычном запуске `tool.exe`, `run.ps1` или `deploy.ps1` сборщик: -1. читает manifest каждой модели и добавляет все зависимости в `patch-Z.MPQ`; +1. читает manifest каждой модели и размещает retail M2 со всеми зависимостями в loose-каталоге + `Data/Patch-WXL.MPQ`, чтобы WarcraftXL всегда преобразовывал MD21 до загрузки клиентом; 2. генерирует `WXLFileData.csv` для WarcraftXL; 3. дописывает модели в `CreatureModelData.dbc` и `CreatureDisplayInfo.dbc`; 4. сохраняет стабильные ID в `custom-creatures.lock.json`; diff --git a/deploy.ps1 b/deploy.ps1 index 7e47f14..151d756 100644 --- a/deploy.ps1 +++ b/deploy.ps1 @@ -76,11 +76,12 @@ New-Item -ItemType Directory -Path $PackagePath -Force | Out-Null if (-not $SkipDataBuild) { Write-Host '[2/5] Building MPQ patches...' $tool = Join-Path $repoRoot 'tool\target\release\tool.exe' - if (-not (Test-Path -LiteralPath $tool -PathType Leaf)) { - $cargo = Get-Command cargo -ErrorAction SilentlyContinue - if (-not $cargo) { throw 'Cargo was not found and the MPQ builder is not compiled.' } + $cargo = Get-Command cargo -ErrorAction SilentlyContinue + if ($cargo) { & $cargo.Source build --release --manifest-path (Join-Path $repoRoot 'tool\Cargo.toml') if ($LASTEXITCODE -ne 0) { throw 'MPQ builder compilation failed.' } + } elseif (-not (Test-Path -LiteralPath $tool -PathType Leaf)) { + throw 'Cargo was not found and the MPQ builder is not compiled.' } & $tool (Join-Path $repoRoot 'src') $PackagePath diff --git a/tool/src/main.rs b/tool/src/main.rs index efcf911..e55e57b 100644 --- a/tool/src/main.rs +++ b/tool/src/main.rs @@ -43,13 +43,21 @@ fn build_mpq( .default_compression(flags::ZLIB) .listfile_option(ListfileOption::Generate); - let mut archive_names = std::collections::HashSet::new(); + let loose_sources: std::collections::HashSet = creatures + .into_iter() + .flat_map(|generated| generated.assets.iter()) + .filter_map(|(source, _)| source.canonicalize().ok()) + .collect(); + for entry in WalkDir::new(&base) .into_iter() .filter_map(|e| e.ok()) .filter(|e| e.file_type().is_file()) { let full_path = entry.path().canonicalize()?; + if loose_sources.contains(&full_path) { + continue; + } let rel_path = match full_path.strip_prefix(&base) { Ok(p) => p, Err(_) => { @@ -62,17 +70,10 @@ fn build_mpq( continue; } println!(" Adding: {}", archive_path); - archive_names.insert(archive_path.to_ascii_lowercase()); builder = builder.add_file(&full_path, &archive_path); } if let Some(generated) = creatures { - for (source, archive_path) in &generated.assets { - if archive_names.insert(archive_path.to_ascii_lowercase()) { - println!(" Adding generated creature asset: {}", archive_path); - builder = builder.add_file(source, archive_path); - } - } println!(" Adding generated: WXLFileData.csv"); builder = builder.add_file_data(generated.file_data_csv.clone(), "WXLFileData.csv"); println!(" Adding generated: WXLSpellOverrides.tsv"); @@ -94,6 +95,22 @@ fn build_mpq( Ok(()) } +fn stage_loose_assets( + output_dir: &Path, + creatures: &GeneratedCreatures, +) -> Result<(), Box> { + let loose_root = output_dir.join("Data").join("Patch-WXL.MPQ"); + for (source, archive_path) in &creatures.assets { + let destination = loose_root.join(archive_path.replace('/', "\\")); + if let Some(parent) = destination.parent() { + fs::create_dir_all(parent)?; + } + fs::copy(source, &destination)?; + println!("Staging loose modern asset: {}", archive_path); + } + Ok(()) +} + fn main() -> Result<(), Box> { let args: Vec = env::args().collect(); @@ -114,6 +131,10 @@ fn main() -> Result<(), Box> { .to_path_buf(); let generated_creatures = creatures::prepare(&project_root)?; + if let Some(generated) = generated_creatures.as_ref() { + stage_loose_assets(&output_dir, generated)?; + } + let data_dir = src_dir.join("Data"); if !data_dir.exists() { return Err(format!("Data/ not found inside src_dir: {}", src_dir.display()).into());