mirror of
https://github.com/redstrate/Physis.git
synced 2025-04-20 11:47:46 +00:00
Unify Platform enums, use it in GameData API and yet more simplifying
So we had a couple copies of a Platform enum, so now there's a public one in the common module. It wasn't possible to specify what platform the GameData is, so now it's part of initialization. While I'm at it, remove the stupid reload_repositories() requirement and make that a private part of the API.
This commit is contained in:
parent
5c66c51713
commit
e146b31bd4
6 changed files with 56 additions and 66 deletions
|
@ -57,3 +57,12 @@ pub enum Region {
|
|||
pub fn read_version(p: &Path) -> Option<String> {
|
||||
fs::read_to_string(p).ok()
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
#[brw(repr = u16)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Platform {
|
||||
Win32,
|
||||
PS3,
|
||||
PS4,
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::path::PathBuf;
|
|||
|
||||
use tracing::{debug, warn};
|
||||
|
||||
use crate::common::{Language, read_version};
|
||||
use crate::common::{Language, Platform, read_version};
|
||||
use crate::dat::DatFile;
|
||||
use crate::exd::EXD;
|
||||
use crate::exh::EXH;
|
||||
|
@ -63,24 +63,27 @@ impl GameData {
|
|||
/// This will return _None_ if the game directory is not valid, but it does not check the validity
|
||||
/// of each individual file.
|
||||
///
|
||||
/// **Note**: None of the repositories are searched, and it's required to call `reload_repositories()`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use physis::gamedata::GameData;
|
||||
/// GameData::from_existing("$FFXIV/game");
|
||||
/// # use physis::common::Platform;
|
||||
/// use physis::gamedata::GameData;
|
||||
/// GameData::from_existing(Platform::Win32, "$FFXIV/game");
|
||||
/// ```
|
||||
pub fn from_existing(directory: &str) -> Option<GameData> {
|
||||
pub fn from_existing(platform: Platform, directory: &str) -> Option<GameData> {
|
||||
debug!(directory, "Loading game directory");
|
||||
|
||||
match is_valid(directory) {
|
||||
true => Some(Self {
|
||||
true => {
|
||||
let mut data = Self {
|
||||
game_directory: String::from(directory),
|
||||
repositories: vec![],
|
||||
index_files: HashMap::new(),
|
||||
index2_files: HashMap::new()
|
||||
}),
|
||||
};
|
||||
data.reload_repositories(platform);
|
||||
Some(data)
|
||||
}
|
||||
false => {
|
||||
warn!("Game data is not valid!");
|
||||
None
|
||||
|
@ -88,23 +91,13 @@ impl GameData {
|
|||
}
|
||||
}
|
||||
|
||||
/// Reloads all repository information from disk. This is a fast operation, as it's not actually
|
||||
/// reading any dat files yet.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```should_panic
|
||||
/// # use physis::gamedata::GameData;
|
||||
/// let mut game = GameData::from_existing("$FFXIV/game").unwrap();
|
||||
/// game.reload_repositories();
|
||||
/// ```
|
||||
pub fn reload_repositories(&mut self) {
|
||||
fn reload_repositories(&mut self, platform: Platform) {
|
||||
self.repositories.clear();
|
||||
|
||||
let mut d = PathBuf::from(self.game_directory.as_str());
|
||||
|
||||
// add initial ffxiv directory
|
||||
if let Some(base_repository) = Repository::from_existing_base(d.to_str().unwrap()) {
|
||||
if let Some(base_repository) = Repository::from_existing_base(platform.clone(), d.to_str().unwrap()) {
|
||||
self.repositories.push(base_repository);
|
||||
}
|
||||
|
||||
|
@ -120,7 +113,7 @@ impl GameData {
|
|||
.collect();
|
||||
|
||||
for repository_path in repository_paths {
|
||||
if let Some(expansion_repository) = Repository::from_existing_expansion(repository_path.path().to_str().unwrap()) {
|
||||
if let Some(expansion_repository) = Repository::from_existing_expansion(platform.clone(), repository_path.path().to_str().unwrap()) {
|
||||
self.repositories.push(expansion_repository);
|
||||
}
|
||||
}
|
||||
|
@ -149,8 +142,9 @@ impl GameData {
|
|||
/// # Example
|
||||
///
|
||||
/// ```should_panic
|
||||
/// # use physis::gamedata::GameData;
|
||||
/// # let mut game = GameData::from_existing("SquareEnix/Final Fantasy XIV - A Realm Reborn/game").unwrap();
|
||||
/// # use physis::common::Platform;
|
||||
/// use physis::gamedata::GameData;
|
||||
/// # let mut game = GameData::from_existing(Platform::Win32, "SquareEnix/Final Fantasy XIV - A Realm Reborn/game").unwrap();
|
||||
/// if game.exists("exd/cid.exl") {
|
||||
/// println!("Cid really does exist!");
|
||||
/// } else {
|
||||
|
@ -181,7 +175,8 @@ impl GameData {
|
|||
/// ```should_panic
|
||||
/// # use physis::gamedata::GameData;
|
||||
/// # use std::io::Write;
|
||||
/// # let mut game = GameData::from_existing("SquareEnix/Final Fantasy XIV - A Realm Reborn/game").unwrap();
|
||||
/// use physis::common::Platform;
|
||||
/// # let mut game = GameData::from_existing(Platform::Win32, "SquareEnix/Final Fantasy XIV - A Realm Reborn/game").unwrap();
|
||||
/// let data = game.extract("exd/root.exl").unwrap();
|
||||
///
|
||||
/// let mut file = std::fs::File::create("root.exl").unwrap();
|
||||
|
@ -447,13 +442,12 @@ mod tests {
|
|||
d.push("valid_sqpack");
|
||||
d.push("game");
|
||||
|
||||
GameData::from_existing(d.to_str().unwrap()).unwrap()
|
||||
GameData::from_existing(Platform::Win32, d.to_str().unwrap()).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn repository_ordering() {
|
||||
let mut data = common_setup_data();
|
||||
data.reload_repositories();
|
||||
|
||||
assert_eq!(data.repositories[0].name, "ffxiv");
|
||||
assert_eq!(data.repositories[1].name, "ex1");
|
||||
|
@ -463,7 +457,6 @@ mod tests {
|
|||
#[test]
|
||||
fn repository_and_category_parsing() {
|
||||
let mut data = common_setup_data();
|
||||
data.reload_repositories();
|
||||
|
||||
assert_eq!(
|
||||
data.parse_repository_category("exd/root.exl").unwrap(),
|
||||
|
|
12
src/index.rs
12
src/index.rs
|
@ -8,22 +8,14 @@ use std::io::SeekFrom;
|
|||
use binrw::BinRead;
|
||||
use binrw::binrw;
|
||||
use modular_bitfield::prelude::*;
|
||||
use crate::common::Platform;
|
||||
use crate::crc::Jamcrc;
|
||||
|
||||
#[binrw]
|
||||
#[brw(repr = u8)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum PlatformId {
|
||||
Windows,
|
||||
PS3,
|
||||
PS4,
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
#[br(magic = b"SqPack")]
|
||||
pub struct SqPackHeader {
|
||||
#[br(pad_before = 2)]
|
||||
platform_id: PlatformId,
|
||||
platform_id: Platform,
|
||||
#[br(pad_before = 3)]
|
||||
size: u32,
|
||||
version: u32,
|
||||
|
|
21
src/patch.rs
21
src/patch.rs
|
@ -12,7 +12,7 @@ use binrw::BinRead;
|
|||
use binrw::binrw;
|
||||
use tracing::{debug, warn};
|
||||
|
||||
use crate::common::Region;
|
||||
use crate::common::{Platform, Region};
|
||||
use crate::sqpack::read_data_block_patch;
|
||||
|
||||
#[binread]
|
||||
|
@ -263,20 +263,11 @@ struct SqpkFileOperationData {
|
|||
path: String,
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
#[brw(repr = u16)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum PlatformId {
|
||||
Windows,
|
||||
PS3,
|
||||
PS4,
|
||||
}
|
||||
|
||||
fn get_platform_string(id: &PlatformId) -> &'static str {
|
||||
fn get_platform_string(id: &Platform) -> &'static str {
|
||||
match &id {
|
||||
PlatformId::Windows => "win32",
|
||||
PlatformId::PS3 => "ps3.d",
|
||||
PlatformId::PS4 => "ps4.d",
|
||||
Platform::Win32 => "win32",
|
||||
Platform::PS3 => "ps3.d",
|
||||
Platform::PS4 => "ps4.d",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,7 +275,7 @@ fn get_platform_string(id: &PlatformId) -> &'static str {
|
|||
#[br(big)]
|
||||
struct SqpkTargetInfo {
|
||||
#[br(pad_before = 3)]
|
||||
platform: PlatformId,
|
||||
platform: Platform,
|
||||
region: Region,
|
||||
#[br(map = | x : u16 | x == 1)]
|
||||
is_debug: bool,
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
use std::cmp::Ordering;
|
||||
use std::cmp::Ordering::{Greater, Less};
|
||||
use std::path::{Path, PathBuf};
|
||||
use binrw::binrw;
|
||||
|
||||
use crate::common::read_version;
|
||||
use crate::common::{Platform, read_version};
|
||||
use crate::repository::RepositoryType::{Base, Expansion};
|
||||
|
||||
/// The type of repository, discerning game data from expansion data.
|
||||
|
@ -27,6 +28,8 @@ pub enum RepositoryType {
|
|||
pub struct Repository {
|
||||
/// The folder name, such as "ex1".
|
||||
pub name: String,
|
||||
/// The platform this repository is designed for.
|
||||
pub platform: Platform,
|
||||
/// The type of repository, such as "base game" or "expansion".
|
||||
pub repo_type: RepositoryType,
|
||||
/// The version of the game data.
|
||||
|
@ -125,7 +128,7 @@ pub fn string_to_category(string: &str) -> Option<Category> {
|
|||
impl Repository {
|
||||
/// Creates a new base `Repository`, from an existing directory. This may return `None` if
|
||||
/// the directory is invalid, e.g. a version file is missing.
|
||||
pub fn from_existing_base(dir: &str) -> Option<Repository> {
|
||||
pub fn from_existing_base(platform: Platform, dir: &str) -> Option<Repository> {
|
||||
let path = Path::new(dir);
|
||||
if path.metadata().is_err() {
|
||||
return None;
|
||||
|
@ -137,6 +140,7 @@ impl Repository {
|
|||
let version = read_version(d.as_path());
|
||||
Some(Repository {
|
||||
name: "ffxiv".to_string(),
|
||||
platform,
|
||||
repo_type: Base,
|
||||
version,
|
||||
})
|
||||
|
@ -144,7 +148,7 @@ impl Repository {
|
|||
|
||||
/// Creates a new expansion `Repository`, from an existing directory. This may return `None` if
|
||||
/// the directory is invalid, e.g. a version file is missing.
|
||||
pub fn from_existing_expansion(dir: &str) -> Option<Repository> {
|
||||
pub fn from_existing_expansion(platform: Platform, dir: &str) -> Option<Repository> {
|
||||
let path = Path::new(dir);
|
||||
if path.metadata().is_err() {
|
||||
return None;
|
||||
|
@ -158,6 +162,7 @@ impl Repository {
|
|||
|
||||
Some(Repository {
|
||||
name,
|
||||
platform,
|
||||
repo_type: Expansion {
|
||||
number: expansion_number,
|
||||
},
|
||||
|
@ -207,6 +212,7 @@ impl Repository {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::PathBuf;
|
||||
use crate::common::Platform;
|
||||
|
||||
use crate::repository::Repository;
|
||||
|
||||
|
@ -216,7 +222,7 @@ mod tests {
|
|||
d.push("resources/tests");
|
||||
d.push("ffxiv");
|
||||
|
||||
let repository = Repository::from_existing_base(d.to_str().unwrap());
|
||||
let repository = Repository::from_existing_base(Platform::Win32, d.to_str().unwrap());
|
||||
assert!(repository.is_some());
|
||||
assert_eq!(repository.unwrap().version.unwrap(), "2012.01.01.0000.0000");
|
||||
}
|
||||
|
@ -227,7 +233,7 @@ mod tests {
|
|||
d.push("resources/tests");
|
||||
d.push("ex1");
|
||||
|
||||
let repository = Repository::from_existing_expansion(d.to_str().unwrap());
|
||||
let repository = Repository::from_existing_expansion(Platform::Win32, d.to_str().unwrap());
|
||||
assert!(repository.is_some());
|
||||
assert_eq!(repository.unwrap().version.unwrap(), "2012.01.01.0000.0000");
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ use walkdir::WalkDir;
|
|||
use physis::patch::apply_patch;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use physis::common::Platform;
|
||||
use physis::fiin::FileInfo;
|
||||
use physis::index;
|
||||
|
||||
|
@ -28,9 +29,7 @@ fn test_gamedata_extract() {
|
|||
let game_dir = env::var("FFXIV_GAME_DIR").unwrap();
|
||||
|
||||
let mut gamedata =
|
||||
physis::gamedata::GameData::from_existing(format!("{}/game", game_dir).as_str()).unwrap();
|
||||
|
||||
gamedata.reload_repositories();
|
||||
physis::gamedata::GameData::from_existing(Platform::Win32, format!("{}/game", game_dir).as_str()).unwrap();
|
||||
|
||||
assert!(gamedata.extract("exd/root.exl").is_some());
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue