Skip to content

Commit

Permalink
Update mod installer to use traits
Browse files Browse the repository at this point in the history
  • Loading branch information
RedstoneWizard08 committed Mar 21, 2023
1 parent ef4ea34 commit a48fb5f
Show file tree
Hide file tree
Showing 7 changed files with 257 additions and 240 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions cli/src/commands/mods/install.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
use wormhole_common::{installer::mods::ModInstaller, instances::Instance};
use wormhole_common::{installer::{spacedock::SpaceDockModInstaller, mods::ModInstaller}, instances::Instance};

pub async fn install_mod(id: i32, instance_id: i32, verbose: bool) {
if verbose {
println!("Creating mod installer...");
}

let instance = Instance::from_id(instance_id).unwrap();
let installer = ModInstaller::new(instance.install_path);
let installer = SpaceDockModInstaller::new(instance.install_path);

if verbose {
println!("Installing mod...");
}

installer.install_from_spacedock(id, instance_id).await;
installer.install(id, instance_id).await;

if verbose {
println!("Mod installed!");
Expand Down
1 change: 1 addition & 0 deletions common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ tokio-stream = { version = "0.1.12", features = ["tokio-util", "fs", "net", "syn
rusqlite = { version = "0.28.0", features = ["bundled"] }
rand = "0.8.5"
zip = "0.6.4"
async-trait = "0.1.67"
3 changes: 2 additions & 1 deletion common/src/installer/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod bepinex;
pub mod mods;
pub mod bepinex;
pub mod spacedock;
pub mod spacewarp;
239 changes: 6 additions & 233 deletions common/src/installer/mods.rs
Original file line number Diff line number Diff line change
@@ -1,236 +1,9 @@
use std::{
fs::{self, File},
io,
path::PathBuf,
};
use std::path::PathBuf;
use async_trait::async_trait;

use crate::{
instances::{Instance, InstanceMod, KSPGame},
mods::spacedock::SpaceDockAPI,
util::{copy_dir_all, get_data_dir},
};
#[async_trait]
pub trait ModInstaller {
fn new(install_path: PathBuf) -> Self;

use rand::{distributions::Alphanumeric, thread_rng, Rng};
use zip::ZipArchive;

pub struct ModInstaller {
pub install_path: PathBuf,
}

impl ModInstaller {
pub fn new(install_path: PathBuf) -> Self {
return Self { install_path };
}

pub async fn install_from_spacedock(&self, id: i32, instance_id: i32) {
let api = SpaceDockAPI::new();
let url = api.get_mod_download(id).await;

let tmp_name = thread_rng()
.sample_iter(&Alphanumeric)
.take(10)
.map(char::from)
.collect::<String>();

let response = reqwest::get(url)
.await
.expect("Could not download the mod!");

let body = response.bytes().await.expect("Could not read the mod!");
let out_path = &self.install_path.join(format!(".{}.mod.zip", tmp_name));

let mut out_file = File::create(out_path).expect("Could not create the mod file!");

io::copy(&mut body.as_ref(), &mut out_file).expect("Could not copy the mod to the file!");

let mod_tmp_path = &self.install_path.join(format!(".{}.mod_tmp", tmp_name));

if mod_tmp_path.exists() {
fs::remove_dir_all(mod_tmp_path).expect("Could not delete the mod tmp folder!");
}

fs::create_dir_all(mod_tmp_path).expect("Could not create the mod tmp folder!");

let zip_file = File::open(out_path).unwrap();
let mut zip = ZipArchive::new(zip_file).unwrap();
let zip_size = zip.len();

let mut files: Vec<String> = Vec::new();

for i in 0..zip_size {
let file = zip.by_index(i).unwrap();
let name = file.name().to_string();

files.push(name.clone());
}

zip.extract(mod_tmp_path)
.expect("Could not extract the mod!");

fs::remove_file(out_path).expect("Could not delete the mod file!");

let mod_info = api.get_mod(id).await;

if let Some(game_id) = mod_info.game_id {
if let Some(game) = KSPGame::from_id(game_id) {
let instance = Instance::from_id(instance_id);

if let Some(mut instance) = instance {
let mut instance_mod = InstanceMod {
id: mod_info.id.unwrap(),
name: mod_info.name.unwrap(),
paths: Vec::new(),
};

if game.eq(&KSPGame::KSP2) {
let bep_in_ex_dir = mod_tmp_path.join("BepInEx");

if bep_in_ex_dir.exists() {
if instance.is_active() {
copy_dir_all(
bep_in_ex_dir.clone(),
self.install_path.join("BepInEx"),
)
.expect("Could not move the BepInEx folder!");
} else {
copy_dir_all(
bep_in_ex_dir.clone(),
get_data_dir()
.join("instances")
.join(instance.id.to_string())
.join("BepInEx"),
)
.expect("Could not move the BepInEx folder!");
}

for file in bep_in_ex_dir.read_dir().unwrap() {
let file = file.unwrap();

if file.file_name() == "plugins" || file.file_name() == "config" {
for file2 in file.path().read_dir().unwrap() {
let file2 = file2.unwrap();

instance_mod.paths.push(
"BepInEx/".to_string()
+ file.file_name().into_string().unwrap().as_str()
+ "/"
+ file2.file_name().into_string().unwrap().as_str(),
);
}
}

instance_mod.paths.push(
"BepInEx/".to_string()
+ file.file_name().into_string().unwrap().as_str(),
);
}
} else {
if instance.is_active() {
copy_dir_all(
mod_tmp_path,
self.install_path.join("BepInEx").join("plugins"),
)
.expect("Could not move the BepInEx folder!");
} else {
copy_dir_all(
bep_in_ex_dir.clone(),
get_data_dir()
.join("instances")
.join(instance.id.to_string())
.join("BepInEx")
.join("plugins"),
)
.expect("Could not move the BepInEx folder!");
}

if bep_in_ex_dir.exists() && bep_in_ex_dir.is_dir() {
for file in bep_in_ex_dir.read_dir().unwrap() {
let file = file.unwrap();

instance_mod.paths.push(
"BepInEx/plugins/".to_string()
+ file.file_name().into_string().unwrap().as_str(),
);
}
}
}
} else {
let mod_contents =
fs::read_dir(mod_tmp_path).expect("Could not read the mod tmp folder!");

let files = mod_contents
.filter_map(|entry| entry.ok())
.collect::<Vec<_>>();

let files_strs = files
.iter()
.map(|entry| entry.file_name().into_string().unwrap())
.collect::<Vec<_>>();

if files_strs.contains(&"GameData".to_string()) {
if instance.is_active() {
copy_dir_all(mod_tmp_path, self.install_path.clone())
.expect("Could not move the GameData folder!");
} else {
copy_dir_all(
mod_tmp_path,
get_data_dir()
.join("instances")
.join(instance.id.to_string()),
)
.expect("Could not move the GameData folder!");
}

for file in mod_tmp_path.read_dir().unwrap() {
let file = file.unwrap();

if file.file_name() == "GameData" {
for file2 in file.path().read_dir().unwrap() {
let file2 = file2.unwrap();

instance_mod.paths.push(
"GameData/".to_string()
+ file2.file_name().into_string().unwrap().as_str(),
);
}
}

instance_mod
.paths
.push(file.file_name().into_string().unwrap());
}
} else {
if instance.is_active() {
copy_dir_all(mod_tmp_path, self.install_path.join("GameData"))
.expect("Could not move the GameData folder!");
} else {
copy_dir_all(
mod_tmp_path,
get_data_dir()
.join("instances")
.join(instance.id.to_string())
.join("GameData"),
)
.expect("Could not move the GameData folder!");
}

for file in mod_tmp_path.read_dir().unwrap() {
let file = file.unwrap();

instance_mod.paths.push(
"GameData/".to_string()
+ file.file_name().into_string().unwrap().as_str(),
);
}
}
}

instance.mods.push(instance_mod);
instance.save();
}
}
}

fs::remove_dir_all(mod_tmp_path).expect("Could not delete the mod tmp folder!");
}
async fn install(&self, id: i32, instance_id: i32);
}
Loading

0 comments on commit a48fb5f

Please sign in to comment.