1
Fork 0
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:
Joshua Goins 2024-04-15 19:40:34 -04:00
parent 5c66c51713
commit e146b31bd4
6 changed files with 56 additions and 66 deletions

View file

@ -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,
}

View file

@ -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(),

View file

@ -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,

View file

@ -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,

View file

@ -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");
}

View file

@ -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());
}