diff --git a/Cargo.lock b/Cargo.lock index dcdcefe7..afd0d8ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2087,6 +2087,7 @@ version = "0.2.10" dependencies = [ "anyhow", "hook_resolvers", + "mint_lib", "patternsleuth", "retour", "windows 0.52.0", @@ -2609,6 +2610,7 @@ dependencies = [ "indexmap 2.1.0", "inventory", "lazy_static", + "mint_lib", "mockall", "modio", "obake", @@ -2641,6 +2643,14 @@ dependencies = [ "zip", ] +[[package]] +name = "mint_lib" +version = "0.2.10" +dependencies = [ + "anyhow", + "steamlocate", +] + [[package]] name = "mio" version = "0.8.9" diff --git a/Cargo.toml b/Cargo.toml index 9da05165..be15396e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = [ + "mint_lib", "hook", "hook_resolvers", ] @@ -14,6 +15,7 @@ edition = "2021" [workspace.dependencies] anyhow = { version = "1.0.75", features = ["backtrace"] } patternsleuth = { git = "https://github.com/trumank/patternsleuth" } +steamlocate = "2.0.0-alpha.0" [package] name = "mint" @@ -45,6 +47,7 @@ image = { version = "0.24.7", default-features = false, features = ["png"] } indexmap = { version = "2.1.0", features = ["serde"] } inventory = "0.3.13" lazy_static = "1.4.0" +mint_lib = { path = "mint_lib" } modio = { git = "https://github.com/trumank/modio-rs.git", branch = "dev", default-features = false, features = ["rustls-tls"] } obake = { version = "1.0.5", features = ["serde"] } opener = "0.6.1" @@ -60,7 +63,7 @@ semver = "1.0.20" serde = { version = "1.0.193", features = ["derive"] } serde_json = "1.0.108" sha2 = "0.10.8" -steamlocate = "2.0.0-alpha.0" +steamlocate.workspace = true task-local-extensions = "0.1.4" tempfile = "3.8.1" thiserror = "1.0.50" diff --git a/hook/Cargo.toml b/hook/Cargo.toml index dcf6ccab..0ddc5e9d 100644 --- a/hook/Cargo.toml +++ b/hook/Cargo.toml @@ -22,3 +22,4 @@ windows = { version = "0.52.0", features = [ "Win32_System_Memory", "Win32_System_Threading", ] } +mint_lib = { path = "../mint_lib" } diff --git a/hook/src/lib.rs b/hook/src/lib.rs index 4ada28db..d256f6bc 100644 --- a/hook/src/lib.rs +++ b/hook/src/lib.rs @@ -3,7 +3,8 @@ use std::{ path::{Path, PathBuf}, }; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result}; +use mint_lib::DRGInstallationType; use retour::static_detour; use windows::Win32::{ Foundation::HMODULE, @@ -46,29 +47,6 @@ extern "system" fn DllMain(dll_module: HMODULE, call_reason: u32, _: *mut ()) -> } } -// TODO refactor crate layout so this can be shared between the hook and integrator -#[derive(Debug)] -pub enum DRGInstallationType { - Steam, - Xbox, -} - -impl DRGInstallationType { - pub fn from_exe_path() -> Result { - let exe_name = std::env::current_exe() - .context("could not determine running exe")? - .file_name() - .context("failed to get exe path")? - .to_string_lossy() - .to_lowercase(); - Ok(match exe_name.as_str() { - "fsd-win64-shipping.exe" => Self::Steam, - "fsd-wingdk-shipping.exe" => Self::Xbox, - _ => bail!("unrecognized exe file name: {exe_name}"), - }) - } -} - unsafe extern "system" fn init(_: usize) { patch().ok(); } diff --git a/mint_lib/Cargo.toml b/mint_lib/Cargo.toml new file mode 100644 index 00000000..2ca43dd5 --- /dev/null +++ b/mint_lib/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "mint_lib" +repository.workspace = true +authors.workspace = true +license.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +anyhow.workspace = true +steamlocate.workspace = true diff --git a/mint_lib/src/lib.rs b/mint_lib/src/lib.rs new file mode 100644 index 00000000..c47ac38d --- /dev/null +++ b/mint_lib/src/lib.rs @@ -0,0 +1,125 @@ +use std::path::{Path, PathBuf}; + +use anyhow::{bail, Context, Result}; + +#[derive(Debug)] +pub enum DRGInstallationType { + Steam, + Xbox, +} + +impl DRGInstallationType { + pub fn from_exe_path() -> Result { + let exe_name = std::env::current_exe() + .context("could not determine running exe")? + .file_name() + .context("failed to get exe path")? + .to_string_lossy() + .to_lowercase(); + Ok(match exe_name.as_str() { + "fsd-win64-shipping.exe" => Self::Steam, + "fsd-wingdk-shipping.exe" => Self::Xbox, + _ => bail!("unrecognized exe file name: {exe_name}"), + }) + } +} + +impl DRGInstallationType { + pub fn from_pak_path>(pak: P) -> Result { + let pak_name = pak + .as_ref() + .file_name() + .context("failed to get pak file name")? + .to_string_lossy() + .to_lowercase(); + Ok(match pak_name.as_str() { + "fsd-windowsnoeditor.pak" => Self::Steam, + "fsd-wingdk.pak" => Self::Xbox, + _ => bail!("unrecognized pak file name: {pak_name}"), + }) + } + pub fn binaries_directory_name(&self) -> &'static str { + match self { + Self::Steam => "Win64", + Self::Xbox => "WinGDK", + } + } + pub fn main_pak_name(&self) -> &'static str { + match self { + Self::Steam => "FSD-WindowsNoEditor.pak", + Self::Xbox => "FSD-WinGDK.pak", + } + } + pub fn hook_dll_name(&self) -> &'static str { + match self { + Self::Steam => "x3daudio1_7.dll", + Self::Xbox => "d3d9.dll", + } + } +} + +#[derive(Debug)] +pub struct DRGInstallation { + pub root: PathBuf, + pub installation_type: DRGInstallationType, +} + +impl DRGInstallation { + /// Returns first DRG installation found. Only supports Steam version + /// TODO locate Xbox version + pub fn find() -> Option { + steamlocate::SteamDir::locate() + .and_then(|mut steamdir| { + steamdir + .app(&548430) + .map(|a| a.path.join("FSD/Content/Paks/FSD-WindowsNoEditor.pak")) + }) + .and_then(|path| Self::from_pak_path(path).ok()) + } + pub fn from_pak_path>(pak: P) -> Result { + let root = pak + .as_ref() + .parent() + .and_then(Path::parent) + .and_then(Path::parent) + .context("failed to get pak parent directory")? + .to_path_buf(); + Ok(Self { + root, + installation_type: DRGInstallationType::from_pak_path(pak)?, + }) + } + pub fn binaries_directory(&self) -> PathBuf { + self.root + .join("Binaries") + .join(self.installation_type.binaries_directory_name()) + } + pub fn paks_path(&self) -> PathBuf { + self.root.join("Content").join("Paks") + } + pub fn main_pak(&self) -> PathBuf { + self.root + .join("Content") + .join("Paks") + .join(self.installation_type.main_pak_name()) + } + pub fn modio_directory(&self) -> Option { + match self.installation_type { + DRGInstallationType::Steam => { + #[cfg(target_os = "windows")] + { + Some(PathBuf::from("C:\\Users\\Public\\mod.io\\2475")) + } + #[cfg(target_os = "linux")] + { + steamlocate::SteamDir::locate().map(|s| { + s.path.join( + "steamapps/compatdata/548430/pfx/drive_c/users/Public/mod.io/2475", + ) + }) + } + } + DRGInstallationType::Xbox => None, + } + } +} diff --git a/src/integrate.rs b/src/integrate.rs index ff212bfb..20db18ef 100644 --- a/src/integrate.rs +++ b/src/integrate.rs @@ -5,6 +5,7 @@ use std::io::{self, BufReader, BufWriter, Cursor, ErrorKind, Read, Seek}; use std::path::{Path, PathBuf}; use anyhow::{Context, Result}; +use mint_lib::DRGInstallation; use repak::PakWriter; use tracing::info; use uasset_utils::splice::{ @@ -12,7 +13,7 @@ use uasset_utils::splice::{ }; use crate::providers::ModInfo; -use crate::{get_pak_from_data, open_file, DRGInstallation}; +use crate::{get_pak_from_data, open_file}; use unreal_asset::{ exports::ExportBaseTrait, diff --git a/src/lib.rs b/src/lib.rs index 39821c30..f15147e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,7 @@ use std::{ path::{Path, PathBuf}, }; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result}; use directories::ProjectDirs; use error::IntegrationError; @@ -70,112 +70,6 @@ impl Dirs { } } -#[derive(Debug)] -pub enum DRGInstallationType { - Steam, - Xbox, -} - -impl DRGInstallationType { - pub fn from_pak_path>(pak: P) -> Result { - let pak_name = pak - .as_ref() - .file_name() - .context("failed to get pak file name")? - .to_string_lossy() - .to_lowercase(); - Ok(match pak_name.as_str() { - "fsd-windowsnoeditor.pak" => Self::Steam, - "fsd-wingdk.pak" => Self::Xbox, - _ => bail!("unrecognized pak file name: {pak_name}"), - }) - } - pub fn binaries_directory_name(&self) -> &'static str { - match self { - Self::Steam => "Win64", - Self::Xbox => "WinGDK", - } - } - pub fn main_pak_name(&self) -> &'static str { - match self { - Self::Steam => "FSD-WindowsNoEditor.pak", - Self::Xbox => "FSD-WinGDK.pak", - } - } - pub fn hook_dll_name(&self) -> &'static str { - match self { - Self::Steam => "x3daudio1_7.dll", - Self::Xbox => "d3d9.dll", - } - } -} - -#[derive(Debug)] -pub struct DRGInstallation { - pub root: PathBuf, - pub installation_type: DRGInstallationType, -} - -impl DRGInstallation { - /// Returns first DRG installation found. Only supports Steam version - /// TODO locate Xbox version - pub fn find() -> Option { - steamlocate::SteamDir::locate() - .and_then(|mut steamdir| { - steamdir - .app(&548430) - .map(|a| a.path.join("FSD/Content/Paks/FSD-WindowsNoEditor.pak")) - }) - .and_then(|path| Self::from_pak_path(path).ok()) - } - pub fn from_pak_path>(pak: P) -> Result { - let root = pak - .as_ref() - .parent() - .and_then(Path::parent) - .and_then(Path::parent) - .context("failed to get pak parent directory")? - .to_path_buf(); - Ok(Self { - root, - installation_type: DRGInstallationType::from_pak_path(pak)?, - }) - } - pub fn binaries_directory(&self) -> PathBuf { - self.root - .join("Binaries") - .join(self.installation_type.binaries_directory_name()) - } - pub fn paks_path(&self) -> PathBuf { - self.root.join("Content").join("Paks") - } - pub fn main_pak(&self) -> PathBuf { - self.root - .join("Content") - .join("Paks") - .join(self.installation_type.main_pak_name()) - } - pub fn modio_directory(&self) -> Option { - match self.installation_type { - DRGInstallationType::Steam => { - #[cfg(target_os = "windows")] - { - Some(PathBuf::from("C:\\Users\\Public\\mod.io\\2475")) - } - #[cfg(target_os = "linux")] - { - steamlocate::SteamDir::locate().map(|s| { - s.path.join( - "steamapps/compatdata/548430/pfx/drive_c/users/Public/mod.io/2475", - ) - }) - } - } - DRGInstallationType::Xbox => None, - } - } -} - /// File::open with the file path included in any error messages pub fn open_file>(path: P) -> Result { std::fs::File::open(&path) diff --git a/src/main.rs b/src/main.rs index d92284f9..e41fbd4f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,13 +5,14 @@ use std::path::PathBuf; use anyhow::{Context, Result}; use clap::{Parser, Subcommand}; +use mint_lib::DRGInstallation; use tracing::{debug, info}; use tracing_appender::non_blocking::WorkerGuard; use tracing_subscriber::filter; use mint::mod_lints::{run_lints, LintId}; use mint::providers::ProviderFactory; -use mint::{gui::gui, providers::ModSpecification, state::State, DRGInstallation}; +use mint::{gui::gui, providers::ModSpecification, state::State}; use mint::{ resolve_ordered_with_provider_init, resolve_unordered_and_integrate_with_provider_init, Dirs, }; diff --git a/src/state/mod.rs b/src/state/mod.rs index 9219c3eb..e6a641b5 100644 --- a/src/state/mod.rs +++ b/src/state/mod.rs @@ -8,12 +8,13 @@ use std::{ }; use anyhow::{bail, Context, Result}; +use mint_lib::DRGInstallation; use serde::{Deserialize, Serialize}; use crate::{ gui::GuiTheme, providers::{ModSpecification, ModStore}, - DRGInstallation, Dirs, + Dirs, }; use self::config::ConfigWrapper;