Skip to content

Commit

Permalink
fix: detect custom bsmanager paths
Browse files Browse the repository at this point in the history
  • Loading branch information
ChecksumDev committed Aug 17, 2023
1 parent ff39d80 commit 9f4ed2f
Showing 1 changed file with 88 additions and 26 deletions.
114 changes: 88 additions & 26 deletions apps/gui/src-tauri/src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,34 @@
use std::io::Error;
use std::{io::Error, path::Path};

use crate::{structs, utils, DATABASE};
use directories::{BaseDirs, UserDirs};
use entity::prelude::*;
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, Set, ActiveModelTrait, ModelTrait};
use serde::{Deserialize, Serialize};
use minreq::post;
use forge_lib::structs::v1::{unpack_v1_forgemod, ForgeModTypes};
use minreq::post;
use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, ModelTrait, QueryFilter, Set};
use serde::{Deserialize, Serialize};

static STEAM_PATH: &str = r"C:\Program Files (x86)\Steam\steamapps\common\Beat Saber";
static OCULUS_PATH: &str =
r"C:\Program Files\Oculus\Software\Software\hyperbolic-magnetism-beat-saber";

#[tauri::command]
pub async fn get_instances() -> Vec<structs::Instance> {
let db = DATABASE.get().await.clone();
let db = DATABASE.get().await.clone();

Instances::find().all(&db).await.unwrap().into_iter().map(|f| {
structs::Instance {
Instances::find()
.all(&db)
.await
.unwrap()
.into_iter()
.map(|f| structs::Instance {
name: f.name,
path: f.path,
version: f.version,
is_modded: f.is_modded,
is_running: false,
}
}).collect()
})
.collect()
}

#[tauri::command]
Expand Down Expand Up @@ -73,6 +77,25 @@ pub async fn detect_instances(save: bool) -> Vec<structs::Instance> {
if bsm_config["installation_folder"].as_str().is_none() {
let bs_manager = documents_dir.join("BSManager").join("BSInstances");

for entry in std::fs::read_dir(bs_manager).unwrap() {
let entry = entry.unwrap();
let path = entry.path();

if path.is_dir() {
instances.push(structs::Instance {
name: path.file_name().unwrap().to_str().unwrap().to_string(),
path: path.to_str().unwrap().to_string(),
version: utils::get_game_version(path.to_str().unwrap().to_string()),
is_modded: false,
is_running: false,
});
}
}
} else {
let base_path = bsm_config["installation_folder"].as_str().unwrap(); // this is the base path for bs manager, not including BSManager
let mut bs_manager = Path::new(base_path).join("BSManager");
bs_manager.push("BSInstances");

for entry in std::fs::read_dir(bs_manager).unwrap() {
let entry = entry.unwrap();
let path = entry.path();
Expand Down Expand Up @@ -102,7 +125,13 @@ pub async fn detect_instances(save: bool) -> Vec<structs::Instance> {
..Default::default()
};

if Instances::find().filter(entity::instances::Column::Name.eq(&f.name)).one(&db).await.unwrap().is_none() {
if Instances::find()
.filter(entity::instances::Column::Name.eq(&f.name))
.one(&db)
.await
.unwrap()
.is_none()
{
Instances::insert(am).exec(&db).await.unwrap();
}
});
Expand All @@ -118,16 +147,21 @@ pub async fn add_instance(name: String) -> Result<structs::Instance, Box<dyn std
// file selection is done natively so no path is passed in
// rfd cannot be used as tauri depends on a diffrent linked version of gtk3 than rfd, and we cant link both versions.
let uder = UserDirs::new().unwrap();
let path = native_dialog::FileDialog::new().set_location(uder.home_dir()).show_open_single_dir()?.ok_or_else(|| Error::new(std::io::ErrorKind::NotFound, "Directory Not found"))?;
let path = native_dialog::FileDialog::new()
.set_location(uder.home_dir())
.show_open_single_dir()?
.ok_or_else(|| Error::new(std::io::ErrorKind::NotFound, "Directory Not found"))?;
let db = DATABASE.get().await.clone();
entity::instances::ActiveModel {
entity::instances::ActiveModel {
name: Set(name.clone()),
path: Set(path.to_str().unwrap().to_string()),
version: Set(utils::get_game_version(path.to_str().unwrap().to_string())),
is_modded: Set(false),
..Default::default()
}.insert(&db).await?;

}
.insert(&db)
.await?;

Ok(structs::Instance {
name,
path: path.to_str().unwrap().to_string(),
Expand All @@ -140,55 +174,83 @@ pub async fn add_instance(name: String) -> Result<structs::Instance, Box<dyn std
#[tauri::command]
pub async fn remove_instance(name: String) -> Result<bool, Box<dyn std::error::Error>> {
let db = DATABASE.get().await.clone();
if let Some(i) = Instances::find().filter(entity::instances::Column::Name.eq(name)).one(&db).await? {
if let Some(i) = Instances::find()
.filter(entity::instances::Column::Name.eq(name))
.one(&db)
.await?
{
i.delete(&db).await?;
return Ok(true);
}
Ok(false)
}

#[tauri::command]
pub async fn install_mod(instance_id: i32, mod_id: String, mod_version: String, api_url: String) -> anyhow::Result<()> {
pub async fn install_mod(
instance_id: i32,
mod_id: String,
mod_version: String,
api_url: String,
) -> anyhow::Result<()> {
let db = DATABASE.get().await.clone();
let instance = Instances::find_by_id(instance_id).one(&db).await?.unwrap();

let fm_res = post("https://staging-api.beatforge.net/graphql")
.with_body(format!("{{
.with_body(format!(
"{{
mods {{
mod(id: \"{}\") {{
versions {{
downloadUrl
}}
}}
}}
}}", mod_id)).send()?.json::<serde_json::Value>()?.as_object().unwrap().get("data").unwrap().as_array().unwrap();

}}",
mod_id
))
.send()?
.json::<serde_json::Value>()?
.as_object()
.unwrap()
.get("data")
.unwrap()
.as_array()
.unwrap();

let mut fm_bin = Vec::new();
let forgemod = unpack_v1_forgemod(fm_bin.as_slice()).map_err(|e| anyhow::anyhow!("Failed to unpack forge mod: {}", e))?;
let forgemod = unpack_v1_forgemod(fm_bin.as_slice())
.map_err(|e| anyhow::anyhow!("Failed to unpack forge mod: {}", e))?;

match forgemod {
ForgeModTypes::Mod(m) => {
let artifact_data = m.data.artifact_data;
let artifact_name = m.manifest.inner.artifact.unwrap();
let artifact_name = artifact_name.file_name().unwrap().to_str().unwrap();
let includes = m.data.includes_data;

for i in &includes {
if (i.dest.starts_with("..") || i.dest.starts_with("/")) && !i.dest.starts_with("../") {
if (i.dest.starts_with("..") || i.dest.starts_with("/"))
&& !i.dest.starts_with("../")
{
return Err(anyhow::anyhow!("Invalid include path: {}", i.dest));
}
}

std::fs::write(format!("{}\\Plugins\\{}", instance.path, artifact_name), artifact_data)?;
std::fs::write(
format!("{}\\Plugins\\{}", instance.path, artifact_name),
artifact_data,
)?;

includes.iter().for_each(|i| {
std::fs::write(format!("{}\\{}", instance.path, i.dest), &*i.data).unwrap();
})
},
}
_ => {
return Err(anyhow::anyhow!("TODO: other types of mods are not supported yet."));
return Err(anyhow::anyhow!(
"TODO: other types of mods are not supported yet."
));
}
}

Ok(())
}
}

0 comments on commit 9f4ed2f

Please sign in to comment.