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> {
|
pub fn read_version(p: &Path) -> Option<String> {
|
||||||
fs::read_to_string(p).ok()
|
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 tracing::{debug, warn};
|
||||||
|
|
||||||
use crate::common::{Language, read_version};
|
use crate::common::{Language, Platform, read_version};
|
||||||
use crate::dat::DatFile;
|
use crate::dat::DatFile;
|
||||||
use crate::exd::EXD;
|
use crate::exd::EXD;
|
||||||
use crate::exh::EXH;
|
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
|
/// This will return _None_ if the game directory is not valid, but it does not check the validity
|
||||||
/// of each individual file.
|
/// of each individual file.
|
||||||
///
|
///
|
||||||
/// **Note**: None of the repositories are searched, and it's required to call `reload_repositories()`.
|
|
||||||
///
|
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use physis::gamedata::GameData;
|
/// # use physis::common::Platform;
|
||||||
/// GameData::from_existing("$FFXIV/game");
|
/// 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");
|
debug!(directory, "Loading game directory");
|
||||||
|
|
||||||
match is_valid(directory) {
|
match is_valid(directory) {
|
||||||
true => Some(Self {
|
true => {
|
||||||
game_directory: String::from(directory),
|
let mut data = Self {
|
||||||
repositories: vec![],
|
game_directory: String::from(directory),
|
||||||
index_files: HashMap::new(),
|
repositories: vec![],
|
||||||
index2_files: HashMap::new()
|
index_files: HashMap::new(),
|
||||||
}),
|
index2_files: HashMap::new()
|
||||||
|
};
|
||||||
|
data.reload_repositories(platform);
|
||||||
|
Some(data)
|
||||||
|
}
|
||||||
false => {
|
false => {
|
||||||
warn!("Game data is not valid!");
|
warn!("Game data is not valid!");
|
||||||
None
|
None
|
||||||
|
@ -88,23 +91,13 @@ impl GameData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reloads all repository information from disk. This is a fast operation, as it's not actually
|
fn reload_repositories(&mut self, platform: Platform) {
|
||||||
/// 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) {
|
|
||||||
self.repositories.clear();
|
self.repositories.clear();
|
||||||
|
|
||||||
let mut d = PathBuf::from(self.game_directory.as_str());
|
let mut d = PathBuf::from(self.game_directory.as_str());
|
||||||
|
|
||||||
// add initial ffxiv directory
|
// 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);
|
self.repositories.push(base_repository);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +113,7 @@ impl GameData {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
for repository_path in repository_paths {
|
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);
|
self.repositories.push(expansion_repository);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,8 +142,9 @@ impl GameData {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```should_panic
|
/// ```should_panic
|
||||||
/// # use physis::gamedata::GameData;
|
/// # use physis::common::Platform;
|
||||||
/// # let mut game = GameData::from_existing("SquareEnix/Final Fantasy XIV - A Realm Reborn/game").unwrap();
|
/// 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") {
|
/// if game.exists("exd/cid.exl") {
|
||||||
/// println!("Cid really does exist!");
|
/// println!("Cid really does exist!");
|
||||||
/// } else {
|
/// } else {
|
||||||
|
@ -181,7 +175,8 @@ impl GameData {
|
||||||
/// ```should_panic
|
/// ```should_panic
|
||||||
/// # use physis::gamedata::GameData;
|
/// # use physis::gamedata::GameData;
|
||||||
/// # use std::io::Write;
|
/// # 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 data = game.extract("exd/root.exl").unwrap();
|
||||||
///
|
///
|
||||||
/// let mut file = std::fs::File::create("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("valid_sqpack");
|
||||||
d.push("game");
|
d.push("game");
|
||||||
|
|
||||||
GameData::from_existing(d.to_str().unwrap()).unwrap()
|
GameData::from_existing(Platform::Win32, d.to_str().unwrap()).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn repository_ordering() {
|
fn repository_ordering() {
|
||||||
let mut data = common_setup_data();
|
let mut data = common_setup_data();
|
||||||
data.reload_repositories();
|
|
||||||
|
|
||||||
assert_eq!(data.repositories[0].name, "ffxiv");
|
assert_eq!(data.repositories[0].name, "ffxiv");
|
||||||
assert_eq!(data.repositories[1].name, "ex1");
|
assert_eq!(data.repositories[1].name, "ex1");
|
||||||
|
@ -463,7 +457,6 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn repository_and_category_parsing() {
|
fn repository_and_category_parsing() {
|
||||||
let mut data = common_setup_data();
|
let mut data = common_setup_data();
|
||||||
data.reload_repositories();
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
data.parse_repository_category("exd/root.exl").unwrap(),
|
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::BinRead;
|
||||||
use binrw::binrw;
|
use binrw::binrw;
|
||||||
use modular_bitfield::prelude::*;
|
use modular_bitfield::prelude::*;
|
||||||
|
use crate::common::Platform;
|
||||||
use crate::crc::Jamcrc;
|
use crate::crc::Jamcrc;
|
||||||
|
|
||||||
#[binrw]
|
|
||||||
#[brw(repr = u8)]
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
enum PlatformId {
|
|
||||||
Windows,
|
|
||||||
PS3,
|
|
||||||
PS4,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
#[br(magic = b"SqPack")]
|
#[br(magic = b"SqPack")]
|
||||||
pub struct SqPackHeader {
|
pub struct SqPackHeader {
|
||||||
#[br(pad_before = 2)]
|
#[br(pad_before = 2)]
|
||||||
platform_id: PlatformId,
|
platform_id: Platform,
|
||||||
#[br(pad_before = 3)]
|
#[br(pad_before = 3)]
|
||||||
size: u32,
|
size: u32,
|
||||||
version: u32,
|
version: u32,
|
||||||
|
|
21
src/patch.rs
21
src/patch.rs
|
@ -12,7 +12,7 @@ use binrw::BinRead;
|
||||||
use binrw::binrw;
|
use binrw::binrw;
|
||||||
use tracing::{debug, warn};
|
use tracing::{debug, warn};
|
||||||
|
|
||||||
use crate::common::Region;
|
use crate::common::{Platform, Region};
|
||||||
use crate::sqpack::read_data_block_patch;
|
use crate::sqpack::read_data_block_patch;
|
||||||
|
|
||||||
#[binread]
|
#[binread]
|
||||||
|
@ -263,20 +263,11 @@ struct SqpkFileOperationData {
|
||||||
path: String,
|
path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[binrw]
|
fn get_platform_string(id: &Platform) -> &'static str {
|
||||||
#[brw(repr = u16)]
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
enum PlatformId {
|
|
||||||
Windows,
|
|
||||||
PS3,
|
|
||||||
PS4,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_platform_string(id: &PlatformId) -> &'static str {
|
|
||||||
match &id {
|
match &id {
|
||||||
PlatformId::Windows => "win32",
|
Platform::Win32 => "win32",
|
||||||
PlatformId::PS3 => "ps3.d",
|
Platform::PS3 => "ps3.d",
|
||||||
PlatformId::PS4 => "ps4.d",
|
Platform::PS4 => "ps4.d",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +275,7 @@ fn get_platform_string(id: &PlatformId) -> &'static str {
|
||||||
#[br(big)]
|
#[br(big)]
|
||||||
struct SqpkTargetInfo {
|
struct SqpkTargetInfo {
|
||||||
#[br(pad_before = 3)]
|
#[br(pad_before = 3)]
|
||||||
platform: PlatformId,
|
platform: Platform,
|
||||||
region: Region,
|
region: Region,
|
||||||
#[br(map = | x : u16 | x == 1)]
|
#[br(map = | x : u16 | x == 1)]
|
||||||
is_debug: bool,
|
is_debug: bool,
|
||||||
|
|
|
@ -4,8 +4,9 @@
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::cmp::Ordering::{Greater, Less};
|
use std::cmp::Ordering::{Greater, Less};
|
||||||
use std::path::{Path, PathBuf};
|
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};
|
use crate::repository::RepositoryType::{Base, Expansion};
|
||||||
|
|
||||||
/// The type of repository, discerning game data from expansion data.
|
/// The type of repository, discerning game data from expansion data.
|
||||||
|
@ -27,6 +28,8 @@ pub enum RepositoryType {
|
||||||
pub struct Repository {
|
pub struct Repository {
|
||||||
/// The folder name, such as "ex1".
|
/// The folder name, such as "ex1".
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
/// The platform this repository is designed for.
|
||||||
|
pub platform: Platform,
|
||||||
/// The type of repository, such as "base game" or "expansion".
|
/// The type of repository, such as "base game" or "expansion".
|
||||||
pub repo_type: RepositoryType,
|
pub repo_type: RepositoryType,
|
||||||
/// The version of the game data.
|
/// The version of the game data.
|
||||||
|
@ -125,7 +128,7 @@ pub fn string_to_category(string: &str) -> Option<Category> {
|
||||||
impl Repository {
|
impl Repository {
|
||||||
/// Creates a new base `Repository`, from an existing directory. This may return `None` if
|
/// 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.
|
/// 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);
|
let path = Path::new(dir);
|
||||||
if path.metadata().is_err() {
|
if path.metadata().is_err() {
|
||||||
return None;
|
return None;
|
||||||
|
@ -137,6 +140,7 @@ impl Repository {
|
||||||
let version = read_version(d.as_path());
|
let version = read_version(d.as_path());
|
||||||
Some(Repository {
|
Some(Repository {
|
||||||
name: "ffxiv".to_string(),
|
name: "ffxiv".to_string(),
|
||||||
|
platform,
|
||||||
repo_type: Base,
|
repo_type: Base,
|
||||||
version,
|
version,
|
||||||
})
|
})
|
||||||
|
@ -144,7 +148,7 @@ impl Repository {
|
||||||
|
|
||||||
/// Creates a new expansion `Repository`, from an existing directory. This may return `None` if
|
/// 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.
|
/// 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);
|
let path = Path::new(dir);
|
||||||
if path.metadata().is_err() {
|
if path.metadata().is_err() {
|
||||||
return None;
|
return None;
|
||||||
|
@ -158,6 +162,7 @@ impl Repository {
|
||||||
|
|
||||||
Some(Repository {
|
Some(Repository {
|
||||||
name,
|
name,
|
||||||
|
platform,
|
||||||
repo_type: Expansion {
|
repo_type: Expansion {
|
||||||
number: expansion_number,
|
number: expansion_number,
|
||||||
},
|
},
|
||||||
|
@ -207,6 +212,7 @@ impl Repository {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use crate::common::Platform;
|
||||||
|
|
||||||
use crate::repository::Repository;
|
use crate::repository::Repository;
|
||||||
|
|
||||||
|
@ -216,7 +222,7 @@ mod tests {
|
||||||
d.push("resources/tests");
|
d.push("resources/tests");
|
||||||
d.push("ffxiv");
|
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!(repository.is_some());
|
||||||
assert_eq!(repository.unwrap().version.unwrap(), "2012.01.01.0000.0000");
|
assert_eq!(repository.unwrap().version.unwrap(), "2012.01.01.0000.0000");
|
||||||
}
|
}
|
||||||
|
@ -227,7 +233,7 @@ mod tests {
|
||||||
d.push("resources/tests");
|
d.push("resources/tests");
|
||||||
d.push("ex1");
|
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!(repository.is_some());
|
||||||
assert_eq!(repository.unwrap().version.unwrap(), "2012.01.01.0000.0000");
|
assert_eq!(repository.unwrap().version.unwrap(), "2012.01.01.0000.0000");
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ use walkdir::WalkDir;
|
||||||
use physis::patch::apply_patch;
|
use physis::patch::apply_patch;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use physis::common::Platform;
|
||||||
use physis::fiin::FileInfo;
|
use physis::fiin::FileInfo;
|
||||||
use physis::index;
|
use physis::index;
|
||||||
|
|
||||||
|
@ -28,9 +29,7 @@ fn test_gamedata_extract() {
|
||||||
let game_dir = env::var("FFXIV_GAME_DIR").unwrap();
|
let game_dir = env::var("FFXIV_GAME_DIR").unwrap();
|
||||||
|
|
||||||
let mut gamedata =
|
let mut gamedata =
|
||||||
physis::gamedata::GameData::from_existing(format!("{}/game", game_dir).as_str()).unwrap();
|
physis::gamedata::GameData::from_existing(Platform::Win32, format!("{}/game", game_dir).as_str()).unwrap();
|
||||||
|
|
||||||
gamedata.reload_repositories();
|
|
||||||
|
|
||||||
assert!(gamedata.extract("exd/root.exl").is_some());
|
assert!(gamedata.extract("exd/root.exl").is_some());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue