Skip to main content

wows_data_mgr/
lib.rs

1//! Test helper API for accessing downloaded World of Warships game data.
2//!
3//! Use these functions in integration tests to get VFS access to game builds.
4//! Tests should skip gracefully when game data is unavailable.
5//!
6//! # Example
7//!
8//! ```ignore
9//! use wows_data_mgr::{available_builds, vfs_for_build};
10//!
11//! #[test]
12//! fn test_game_params_load() {
13//!     let builds = available_builds();
14//!     if builds.is_empty() {
15//!         eprintln!("Skipping: no game data available");
16//!         return;
17//!     }
18//!     for build in builds {
19//!         let vfs = vfs_for_build(build).unwrap();
20//!         // test with vfs...
21//!     }
22//! }
23//! ```
24
25pub mod builds;
26pub mod cas;
27#[cfg(feature = "constants")]
28pub mod constants;
29pub mod dump;
30pub mod manifest;
31pub mod registry;
32
33use std::path::PathBuf;
34
35use wowsunpack::game_data;
36use wowsunpack::vfs::VfsPath;
37
38/// Returns the path to the game_data/ directory.
39///
40/// Checks `WOWS_GAME_DATA` env var first, then walks up from the current
41/// directory to find the workspace root (identified by `game_versions.toml`).
42pub fn game_data_dir() -> Option<PathBuf> {
43    if let Ok(dir) = std::env::var("WOWS_GAME_DATA") {
44        let path = PathBuf::from(dir);
45        if path.exists() {
46            return Some(path);
47        }
48    }
49
50    // Walk up from current dir to find repo root
51    let mut dir = std::env::current_dir().ok()?;
52    loop {
53        if dir.join("game_versions.toml").exists() {
54            let data_dir = dir.join("game_data");
55            return Some(data_dir);
56        }
57        if !dir.pop() {
58            return None;
59        }
60    }
61}
62
63/// Returns sorted list of locally available build numbers.
64///
65/// Reads the local registry to find both downloaded builds
66/// (in `game_data/builds/<build>/`) and registered overrides.
67pub fn available_builds() -> Vec<u32> {
68    let Some(data_dir) = game_data_dir() else {
69        return Vec::new();
70    };
71    let reg = registry::load_registry(&data_dir.join("versions.toml"));
72    reg.available_builds()
73}
74
75/// Returns the game root path for a specific build.
76///
77/// For registered overrides, returns the override path.
78/// For downloaded builds, returns `game_data/builds/<build>/`.
79pub fn game_dir_for_build(build: u32) -> Option<PathBuf> {
80    let data_dir = game_data_dir()?;
81    let reg = registry::load_registry(&data_dir.join("versions.toml"));
82    reg.game_dir_for_build(build, &data_dir)
83}
84
85/// Constructs a VFS for a specific build.
86///
87/// Resolves path via [`game_dir_for_build`], then calls
88/// [`wowsunpack::game_data::build_game_vfs`].
89pub fn vfs_for_build(build: u32) -> Option<VfsPath> {
90    let game_dir = game_dir_for_build(build)?;
91    game_data::build_game_vfs(&game_dir).ok()
92}
93
94/// Returns the latest available build number and its VFS.
95pub fn latest_build() -> Option<(u32, VfsPath)> {
96    let builds = available_builds();
97    let build = *builds.last()?;
98    let vfs = vfs_for_build(build)?;
99    Some((build, vfs))
100}