Skip to content

Commit 0ade5be

Browse files
committed
Remove the hardcoded game ID from the agent
This allows for the use of alternate package identifiers so that a developer could have more than one copy of the game installed at once.
1 parent 3f0e751 commit 0ade5be

16 files changed

Lines changed: 313 additions & 141 deletions

File tree

mbf-agent/src/handlers/import.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ use std::path::{Path, PathBuf};
33
use crate::{
44
downloads,
55
mod_man::ModManager,
6-
models::response::{self, ImportResultType, Response},
7-
paths,
6+
models::response::{self, ImportResultType, Response}, parameters::PARAMETERS
87
};
98
use anyhow::{anyhow, Context, Result};
109
use log::{debug, info, warn};
@@ -15,8 +14,8 @@ use mbf_zip::ZipFile;
1514
/// # Returns
1615
/// The [Response](requests::Response) to the request (variant `ImportResult`)
1716
pub(super) fn handle_import_mod_url(from_url: String) -> Result<Response> {
18-
std::fs::create_dir_all(paths::MBF_DOWNLOADS)?;
19-
let download_path = Path::new(paths::MBF_DOWNLOADS).join("import_from_url");
17+
std::fs::create_dir_all(&PARAMETERS.mbf_downloads)?;
18+
let download_path = Path::new(&PARAMETERS.mbf_downloads).join("import_from_url");
2019

2120
info!("Downloading {}", from_url);
2221
let filename: Option<String> =
@@ -183,7 +182,7 @@ fn attempt_song_import(from_path: PathBuf) -> Result<ImportResultType> {
183182
let mut zip = ZipFile::open(song_handle).context("Song was invalid ZIP file")?;
184183

185184
if zip.contains_file("info.dat") || zip.contains_file("Info.dat") {
186-
let extract_path = Path::new(paths::CUSTOM_LEVELS)
185+
let extract_path = Path::new(&PARAMETERS.custom_levels)
187186
.join(from_path.file_stem().expect("Must have file stem"));
188187

189188
if extract_path.exists() {

mbf-agent/src/handlers/mod.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ use crate::{
77
mod_man::ModManager,
88
models::{
99
request::Request,
10+
request::RequestEnum,
1011
response::{self, Response},
11-
},
12+
}, parameters::PARAMETERS,
1213
};
1314
use anyhow::{anyhow, Context, Result};
1415
use log::info;
@@ -28,11 +29,11 @@ mod utility;
2829
/// # Returns
2930
/// If successful, a [Response] to be sent back to the frontend.
3031
pub fn handle_request(request: Request) -> Result<Response> {
31-
match request {
32-
Request::GetModStatus {
32+
match request.request {
33+
RequestEnum::GetModStatus {
3334
override_core_mod_url,
3435
} => mod_status::handle_get_mod_status(override_core_mod_url),
35-
Request::Patch {
36+
RequestEnum::Patch {
3637
downgrade_to,
3738
remodding,
3839
manifest_mod,
@@ -47,15 +48,15 @@ pub fn handle_request(request: Request) -> Result<Response> {
4748
override_core_mod_url,
4849
vr_splash_path,
4950
),
50-
Request::GetDowngradedManifest { version } => {
51+
RequestEnum::GetDowngradedManifest { version } => {
5152
patching::handle_get_downgraded_manifest(version)
5253
}
53-
Request::RemoveMod { id } => mod_management::handle_remove_mod(id),
54-
Request::SetModsEnabled { statuses } => mod_management::handle_set_mods_enabled(statuses),
55-
Request::Import { from_path } => import::handle_import(from_path, None),
56-
Request::ImportUrl { from_url } => import::handle_import_mod_url(from_url),
57-
Request::FixPlayerData => utility::handle_fix_player_data(),
58-
Request::QuickFix {
54+
RequestEnum::RemoveMod { id } => mod_management::handle_remove_mod(id),
55+
RequestEnum::SetModsEnabled { statuses } => mod_management::handle_set_mods_enabled(statuses),
56+
RequestEnum::Import { from_path } => import::handle_import(from_path, None),
57+
RequestEnum::ImportUrl { from_url } => import::handle_import_mod_url(from_url),
58+
RequestEnum::FixPlayerData => utility::handle_fix_player_data(),
59+
RequestEnum::QuickFix {
5960
override_core_mod_url,
6061
wipe_existing_mods,
6162
} => utility::handle_quick_fix(override_core_mod_url, wipe_existing_mods),
@@ -70,7 +71,7 @@ pub fn handle_request(request: Request) -> Result<Response> {
7071
/// An `Err` variant is returned on failure, for example if Beat Saber isn't installed or the result from `dumpsys` couldn't be parsed.
7172
fn get_app_version_only() -> Result<String> {
7273
let dumpsys_output = Command::new("dumpsys")
73-
.args(["package", crate::APK_ID])
74+
.args(["package", &PARAMETERS.apk_id])
7475
.output()
7576
.context("Invoking dumpsys")?;
7677
let dumpsys_stdout =

mbf-agent/src/handlers/patching.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::path::Path;
44

55
use log::{info, warn};
66

7-
use crate::{mod_man::ModManager, models::response::Response, patching, paths};
7+
use crate::{mod_man::ModManager, models::response::Response, parameters::PARAMETERS, patching};
88
use anyhow::{anyhow, Context, Result};
99

1010
/// Handles `GetDowngradedManifest` [Requests](requests::Request).
@@ -40,7 +40,7 @@ pub(super) fn handle_patch(
4040
super::mod_status::get_app_info()?.ok_or(anyhow!("Cannot patch when app not installed"))?;
4141
let res_cache = crate::load_res_cache()?;
4242

43-
std::fs::create_dir_all(paths::TEMP)?;
43+
std::fs::create_dir_all(&PARAMETERS.temp)?;
4444

4545
// Either downgrade or just patch the current APK depending on the caller's choice.
4646
let patching_result = if let Some(to_version) = &downgrade_to {
@@ -57,7 +57,7 @@ pub(super) fn handle_patch(
5757
))?;
5858

5959
patching::downgrade_and_mod_apk(
60-
Path::new(paths::TEMP),
60+
Path::new(&PARAMETERS.temp),
6161
&app_info,
6262
version_diffs,
6363
manifest_mod,
@@ -67,7 +67,7 @@ pub(super) fn handle_patch(
6767
.context("Downgrading and patching APK")
6868
} else {
6969
patching::mod_current_apk(
70-
Path::new(paths::TEMP),
70+
Path::new(&PARAMETERS.temp),
7171
&app_info,
7272
manifest_mod,
7373
repatch,
@@ -79,7 +79,7 @@ pub(super) fn handle_patch(
7979
};
8080

8181
// No matter what, make sure that all temporary files are gone.
82-
std::fs::remove_dir_all(paths::TEMP)?;
82+
std::fs::remove_dir_all(&PARAMETERS.temp)?;
8383
if let Some(splash_path) = vr_splash_path {
8484
std::fs::remove_file(splash_path)?;
8585
}

mbf-agent/src/handlers/utility.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use std::path::Path;
44

5-
use crate::{data_fix, mod_man::ModManager, models::response::Response, patching, paths};
5+
use crate::{data_fix, mod_man::ModManager, models::response::Response, parameters::PARAMETERS, patching};
66
use anyhow::{anyhow, Context, Result};
77
use log::{debug, info, warn};
88

@@ -48,21 +48,21 @@ pub(super) fn handle_fix_player_data() -> Result<Response> {
4848
patching::kill_app()?; // Kill app, in case it's still stuck in a hanging state
4949

5050
let mut did_work = false;
51-
if Path::new(paths::DATAKEEPER_PLAYER_DATA).exists() {
51+
if Path::new(&PARAMETERS.datakeeper_player_data).exists() {
5252
info!("Fixing color scheme issues");
53-
data_fix::fix_colour_schemes(paths::DATAKEEPER_PLAYER_DATA)?;
53+
data_fix::fix_colour_schemes(&PARAMETERS.datakeeper_player_data)?;
5454
did_work = true;
5555
}
5656

57-
if Path::new(paths::PLAYER_DATA).exists() {
57+
if Path::new(&PARAMETERS.player_data).exists() {
5858
info!("Backing up player data");
5959
patching::backup_player_data()?;
6060

6161
info!("Removing (potentially faulty) PlayerData.dat in game files");
62-
debug!("(removing {})", paths::PLAYER_DATA);
63-
std::fs::remove_file(paths::PLAYER_DATA).context("Deleting faulty player data")?;
64-
if Path::new(paths::PLAYER_DATA_BAK).exists() {
65-
std::fs::remove_file(paths::PLAYER_DATA_BAK)?;
62+
debug!("(removing {})", &PARAMETERS.player_data);
63+
std::fs::remove_file(&PARAMETERS.player_data).context("Deleting faulty player data")?;
64+
if Path::new(&PARAMETERS.player_data_bak).exists() {
65+
std::fs::remove_file(&PARAMETERS.player_data_bak)?;
6666
}
6767
did_work = true;
6868
} else {

mbf-agent/src/main.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ mod manifest;
66
mod mod_man;
77
mod models;
88
mod patching;
9-
mod paths;
9+
mod parameters;
1010

1111
use anyhow::{Context, Result};
1212
use downloads::DownloadConfig;
1313
use log::{debug, error, warn, Level};
1414
use mbf_res_man::res_cache::ResCache;
1515
use models::{request, response};
16+
use parameters::{init_parameters, PARAMETERS};
1617
use serde::{Deserialize, Serialize};
1718
use std::{
1819
io::{BufRead, BufReader, Write},
@@ -22,9 +23,6 @@ use std::{
2223
sync,
2324
};
2425

25-
/// The ID of the APK file that MBF manages.
26-
pub const APK_ID: &str = "com.beatgames.beatsaber";
27-
2826
#[cfg(feature = "request_timing")]
2927
use log::info;
3028
#[cfg(feature = "request_timing")]
@@ -33,7 +31,7 @@ use std::time::Instant;
3331
/// Attempts to delete legacy directories no longer used by MBF to free up space
3432
/// Logs on failure
3533
pub fn try_delete_legacy_dirs() {
36-
for dir in paths::LEGACY_DIRS {
34+
for dir in &PARAMETERS.legacy_dirs {
3735
if Path::new(dir).exists() {
3836
match std::fs::remove_dir_all(dir) {
3937
Ok(_) => debug!("Successfully removed legacy dir {dir}"),
@@ -62,16 +60,16 @@ pub fn get_dl_cfg() -> &'static DownloadConfig<'static> {
6260
/// Creates a ResCache for downloading files using mbf_res_man
6361
/// This should be reused where possible.
6462
pub fn load_res_cache() -> Result<ResCache<'static>> {
65-
std::fs::create_dir_all(paths::RES_CACHE).expect("Failed to create resource cache folder");
63+
std::fs::create_dir_all(&PARAMETERS.res_cache).expect("Failed to create resource cache folder");
6664
Ok(ResCache::new(
67-
paths::RES_CACHE.into(),
65+
(&PARAMETERS.res_cache).into(),
6866
mbf_res_man::default_agent::get_agent(),
6967
))
7068
}
7169

7270
pub fn get_apk_path() -> Result<Option<String>> {
7371
let pm_output = Command::new("pm")
74-
.args(["path", APK_ID])
72+
.args(["path", &PARAMETERS.apk_id])
7573
.output()
7674
.context("Working out APK path")?;
7775
if 8 > pm_output.stdout.len() {
@@ -153,6 +151,9 @@ fn main() -> Result<()> {
153151
reader.read_line(&mut line)?;
154152
let req: request::Request = serde_json::from_str(&line)?;
155153

154+
// Set the parameters for this instance of the agent
155+
init_parameters(&req.agent_parameters.game_id, req.agent_parameters.ignore_package_id);
156+
156157
// Set a panic hook that writes the panic as a JSON Log
157158
// (we don't do this in catch_unwind as we get an `Any` there, which doesn't implement Display)
158159
panic::set_hook(Box::new(|info| {

mbf-agent/src/mod_man/loaded_mod.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
use std::{collections::HashSet, ffi::{OsStr, OsString}, path::{Path, PathBuf}};
66

7-
use crate::paths;
7+
use crate::parameters::PARAMETERS;
88

99
use super::{util, ModInfo};
1010
use anyhow::{Result, Context};
@@ -84,17 +84,17 @@ impl Mod {
8484
util::copy_files_from_mod_folder(
8585
&self.loaded_from,
8686
&self.manifest().mod_files,
87-
paths::EARLY_MODS,
87+
&PARAMETERS.early_mods,
8888
)?;
8989
util::copy_files_from_mod_folder(
9090
&self.loaded_from,
9191
&self.manifest().library_files,
92-
paths::LIBS,
92+
&PARAMETERS.libs,
9393
)?;
9494
util::copy_files_from_mod_folder(
9595
&self.loaded_from,
9696
&self.manifest().late_mod_files,
97-
paths::LATE_MODS,
97+
&PARAMETERS.late_mods,
9898
)?;
9999

100100
self.copy_file_copies().context("Copying auxillary files")?;
@@ -114,11 +114,11 @@ impl Mod {
114114
// Delete all mod binary files.
115115
util::remove_file_names_from_folder(
116116
self.manifest().mod_files.iter(),
117-
paths::EARLY_MODS,
117+
&PARAMETERS.early_mods,
118118
)?;
119119
util::remove_file_names_from_folder(
120120
self.manifest().late_mod_files.iter(),
121-
paths::LATE_MODS,
121+
&PARAMETERS.late_mods,
122122
)?;
123123
util::remove_file_names_from_folder(
124124
// Only delete libraries not in use (!)
@@ -127,7 +127,7 @@ impl Mod {
127127
.library_files
128128
.iter()
129129
.filter(|lib_file| !retained_libs.contains(OsStr::new(lib_file))),
130-
paths::LIBS,
130+
&PARAMETERS.libs,
131131
)?;
132132

133133
// Delete all file copies.
@@ -198,9 +198,9 @@ impl Mod {
198198
/// destinations.
199199
fn check_if_files_copied(manifest: &ModInfo) -> Result<bool> {
200200
Ok(
201-
util::files_exist_in_dir(paths::EARLY_MODS, manifest.mod_files.iter())?
202-
&& util::files_exist_in_dir(paths::LATE_MODS, manifest.late_mod_files.iter())?
203-
&& util::files_exist_in_dir(paths::LIBS, manifest.library_files.iter())?
201+
util::files_exist_in_dir(&PARAMETERS.early_mods, manifest.mod_files.iter())?
202+
&& util::files_exist_in_dir(&PARAMETERS.late_mods, manifest.late_mod_files.iter())?
203+
&& util::files_exist_in_dir(&PARAMETERS.libs, manifest.library_files.iter())?
204204
&& manifest
205205
.file_copies
206206
.iter()

mbf-agent/src/mod_man/mod.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use mbf_res_man::{
2828
use mbf_zip::ZipFile;
2929
use semver::Version;
3030

31-
use crate::{downloads, paths};
31+
use crate::{downloads, parameters::PARAMETERS};
3232

3333
/// The JSON schema for the `mod.json` file within a qmod.
3434
/// This is the same schema used by QuestPatcher.
@@ -76,7 +76,7 @@ impl<'cache> ModManager<'cache> {
7676
)
7777
.expect("QMOD schema should be a valid JSON schema"),
7878
// Each game version stores its QMODs in a different directory.
79-
qmods_dir: paths::QMODS.replace('$', &game_version),
79+
qmods_dir: (&PARAMETERS.qmods).replace('$', &game_version),
8080
game_version,
8181
res_cache,
8282
mod_repo: None,
@@ -89,10 +89,10 @@ impl<'cache> ModManager<'cache> {
8989

9090
// Wipe all mod directories, if they exist.
9191
let to_remove = [
92-
paths::OLD_QMODS,
93-
paths::LATE_MODS,
94-
paths::EARLY_MODS,
95-
paths::LIBS,
92+
&PARAMETERS.old_qmods,
93+
&PARAMETERS.late_mods,
94+
&PARAMETERS.early_mods,
95+
&PARAMETERS.libs,
9696
&self.qmods_dir,
9797
];
9898
for path in to_remove {
@@ -450,14 +450,14 @@ impl<'cache> ModManager<'cache> {
450450
/// Will do nothing if the old mods directory does not exist.
451451
/// Returns true if any old QMODs were found
452452
fn load_old_qmods(&mut self) -> Result<bool> {
453-
if !Path::new(paths::OLD_QMODS).exists() {
453+
if !Path::new(&PARAMETERS.old_qmods).exists() {
454454
return Ok(false);
455455
}
456456

457457
warn!("Migrating mods from legacy folder");
458458
let mut found_qmod = false;
459459
for stat_result in
460-
std::fs::read_dir(paths::OLD_QMODS).context("Reading old QMODs directory")?
460+
std::fs::read_dir(&PARAMETERS.old_qmods).context("Reading old QMODs directory")?
461461
{
462462
let stat = stat_result?;
463463

@@ -474,7 +474,7 @@ impl<'cache> ModManager<'cache> {
474474
found_qmod = true;
475475
std::fs::remove_file(stat.path()).context("Deleting legacy mod")?;
476476
}
477-
std::fs::remove_dir(paths::OLD_QMODS)?;
477+
std::fs::remove_dir(&PARAMETERS.old_qmods)?;
478478

479479
Ok(found_qmod)
480480
}
@@ -741,13 +741,13 @@ impl<'cache> ModManager<'cache> {
741741
/// and the Packages directory that stores the extracted QMODs for the current game version.
742742
fn create_mods_dir(&self) -> Result<()> {
743743
std::fs::create_dir_all(&self.qmods_dir)?;
744-
std::fs::create_dir_all(paths::LATE_MODS)?;
745-
std::fs::create_dir_all(paths::EARLY_MODS)?;
746-
std::fs::create_dir_all(paths::LIBS)?;
744+
std::fs::create_dir_all(&PARAMETERS.late_mods)?;
745+
std::fs::create_dir_all(&PARAMETERS.early_mods)?;
746+
std::fs::create_dir_all(&PARAMETERS.libs)?;
747747
OpenOptions::new()
748748
.create(true)
749749
.write(true)
750-
.open(paths::MODDATA_NOMEDIA)
750+
.open(&PARAMETERS.moddata_nomedia)
751751
.context("Creating nomedia file")?;
752752

753753
Ok(())

0 commit comments

Comments
 (0)