Skip to content

Commit

Permalink
integrated custom mod states
Browse files Browse the repository at this point in the history
  • Loading branch information
1zun4 committed Dec 27, 2023
1 parent 9b731b5 commit 0607ab6
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 48 deletions.
8 changes: 6 additions & 2 deletions src-tauri/src/app/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ pub struct LoaderMod {
///
/// JSON struct of ModSource (the method to be used for downloading the mod)
///
#[derive(Serialize, Deserialize, Debug)]
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(tag = "type")]
pub enum ModSource {
#[serde(rename = "skip")]
Expand All @@ -232,14 +232,18 @@ pub enum ModSource {
#[serde(rename = "repository")]
#[serde(rename_all = "camelCase")]
Repository { repository: String, artifact: String },
#[serde(rename = "local")]
#[serde(rename_all = "camelCase")]
Local { file_name: String }
}

impl ModSource {
pub fn get_path(&self) -> Result<String> {
Ok(
match self {
ModSource::SkipAd { artifact_name, .. } => format!("{}.jar", artifact_name),
ModSource::Repository { repository: _repository, artifact } => get_maven_artifact_path(artifact)?
ModSource::Repository { repository: _repository, artifact } => get_maven_artifact_path(artifact)?,
ModSource::Local { file_name } => file_name.clone(),
}
)
}
Expand Down
26 changes: 15 additions & 11 deletions src-tauri/src/app/gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use crate::{LAUNCHER_DIRECTORY, minecraft::{launcher::{LauncherData, LaunchingPa
use crate::app::api::{Branches, Changelog, ContentDelivery, News};
use crate::utils::percentage_of_total_memory;

use super::{api::{ApiEndpoints, Build, LoaderMod}, app_data::LauncherOptions};
use super::{api::{ApiEndpoints, Build, LoaderMod, ModSource}, app_data::LauncherOptions};

struct RunnerInstance {
terminator: tokio::sync::oneshot::Sender<()>,
Expand Down Expand Up @@ -98,7 +98,7 @@ async fn request_builds(branch: &str) -> Result<Vec<Build>, String> {
}

#[tauri::command]
async fn request_mods(mc_version: &str, subsystem: &str) -> Result<Vec<LoaderMod>, String> {
async fn request_mods(branch: &str, mc_version: &str, subsystem: &str) -> Result<Vec<LoaderMod>, String> {
let mods = ApiEndpoints::mods(&mc_version, &subsystem)
.await
.map_err(|e| format!("unable to request mods: {:?}", e))?;
Expand Down Expand Up @@ -126,7 +126,7 @@ async fn login_microsoft(window: tauri::Window) -> Result<MinecraftAccount, Stri
}

#[tauri::command]
async fn get_custom_mods(branch: String, mc_version: String) -> Result<Vec<String>, String> {
async fn get_custom_mods(branch: &str, mc_version: &str) -> Result<Vec<LoaderMod>, String> {
let data = LAUNCHER_DIRECTORY.data_dir();
let mod_cache_path = data.join("custom_mods").join(format!("{}-{}", branch, mc_version));

Expand All @@ -138,20 +138,24 @@ async fn get_custom_mods(branch: String, mc_version: String) -> Result<Vec<Strin
let mut mods_read = fs::read_dir(&mod_cache_path).await
.map_err(|e| format!("unable to read custom mods: {:?}", e))?;

while let Some(entry) = mods_read.next_entry().await
.map_err(|e| format!("unable to read custom mods: {:?}", e))? {
if entry.file_type().await
.map_err(|e| format!("unable to read custom mods: {:?}", e))?
.is_file() {
mods.push(entry.file_name().into_string().unwrap());
while let Some(entry) = mods_read.next_entry().await.map_err(|e| format!("unable to read custom mods: {:?}", e))? {
let file_type = entry.file_type().await
.map_err(|e| format!("unable to read custom mods: {:?}", e))?;
let file_name = entry.file_name().to_str().unwrap().to_string();

if file_type.is_file() && file_name.ends_with(".jar") {
// todo: pull name from JAR manifest
let file_name_without_extension = file_name.replace(".jar", "");

mods.push(LoaderMod { required: true, enabled: true, name: file_name_without_extension, source: ModSource::Local { file_name } });
}
}

Ok(mods)
}

#[tauri::command]
async fn install_custom_mod(branch: String, mc_version: String, path: PathBuf) -> Result<(), String> {
async fn install_custom_mod(branch: &str, mc_version: &str, path: PathBuf) -> Result<(), String> {
let data = LAUNCHER_DIRECTORY.data_dir();
let mod_cache_path = data.join("custom_mods").join(format!("{}-{}", branch, mc_version));

Expand All @@ -172,7 +176,7 @@ async fn install_custom_mod(branch: String, mc_version: String, path: PathBuf) -
}

#[tauri::command]
async fn delete_custom_mod(branch: String, mc_version: String, mod_name: String) -> Result<(), String> {
async fn delete_custom_mod(branch: &str, mc_version: &str, mod_name: &str) -> Result<(), String> {
let data = LAUNCHER_DIRECTORY.data_dir();
let mod_cache_path = data.join("custom_mods").join(format!("{}-{}", branch, mc_version));

Expand Down
39 changes: 15 additions & 24 deletions src-tauri/src/minecraft/prelauncher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ pub(crate) async fn launch<D: Send + Sync>(launch_manifest: LaunchManifest, laun
retrieve_and_copy_mods(&data_directory, &launch_manifest, &launch_manifest.mods, &progress, &window).await?;
retrieve_and_copy_mods(&data_directory, &launch_manifest, &additional_mods, &progress, &window).await?;

copy_custom_mods(&data_directory, &launch_manifest, &progress).await?;

info!("Loading version profile...");
let manifest_url = match subsystem {
LoaderSubsystem::Fabric { manifest, .. } => manifest
Expand Down Expand Up @@ -110,10 +108,15 @@ pub(crate) async fn clear_mods(data: &Path, manifest: &LaunchManifest) -> Result

pub async fn retrieve_and_copy_mods(data: &Path, manifest: &LaunchManifest, mods: &Vec<LoaderMod>, progress: &impl ProgressReceiver, window: &Arc<Mutex<tauri::Window>>) -> Result<()> {
let mod_cache_path = data.join("mod_cache");
let mods_path = data.join("gameDir").join(&manifest.build.branch).join("mods");
let mod_custom_path = data.join("custom_mods")
.join(format!("{}-{}", manifest.build.branch, manifest.build.mc_version));
let mods_path = data.join("gameDir")
.join(&manifest.build.branch)
.join("mods");

fs::create_dir_all(&mod_cache_path).await?;
fs::create_dir_all(&mods_path).await?;
fs::create_dir_all(&mod_custom_path).await?;

// Download and copy mods
let max = get_max(mods.len());
Expand All @@ -124,6 +127,13 @@ pub async fn retrieve_and_copy_mods(data: &Path, manifest: &LaunchManifest, mods
continue;
}

if let ModSource::Local { file_name } = &current_mod.source {
// Copy the mod.
fs::copy(mod_custom_path.join(file_name), mods_path.join(file_name)).await?;
progress.progress_update(ProgressUpdate::set_label(format!("Copied custom mod {}", current_mod.name)));
continue;
}

progress.progress_update(ProgressUpdate::set_label(format!("Downloading recommended mod {}", current_mod.name)));

let current_mod_path = mod_cache_path.join(current_mod.source.get_path()?);
Expand Down Expand Up @@ -170,7 +180,8 @@ pub async fn retrieve_and_copy_mods(data: &Path, manifest: &LaunchManifest, mods
}).await?;

fs::write(&current_mod_path, retrieved_bytes).await?;
}
},
_ => warn!("unsupported mod source: {:?}", current_mod.source),
}
}

Expand All @@ -181,23 +192,3 @@ pub async fn retrieve_and_copy_mods(data: &Path, manifest: &LaunchManifest, mods
Ok(())

}

pub async fn copy_custom_mods(data: &Path, manifest: &LaunchManifest, progress: &impl ProgressReceiver) -> Result<()> {
let mod_cache_path = data.join("custom_mods").join(format!("{}-{}", manifest.build.branch, manifest.build.mc_version));
let mods_path = data.join("gameDir").join(&manifest.build.branch).join("mods");

fs::create_dir_all(&mod_cache_path).await?;
fs::create_dir_all(&mods_path).await?;

// Copy all mods from custom_mods to mods
let mut mods_read = fs::read_dir(&mod_cache_path).await?;
while let Some(entry) = mods_read.next_entry().await? {
if entry.file_type().await?.is_file() {
progress.progress_update(ProgressUpdate::set_label(format!("Copied custom mod {}", entry.file_name().to_str().unwrap_or_default())));
fs::copy(entry.path(), mods_path.join(entry.file_name())).await?;
}
}

Ok(())

}
34 changes: 23 additions & 11 deletions src/lib/main/MainScreen.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
let mcVersion = {};
let mods = [];
let customMods = [];
/// Request builds from API server
function requestBuilds() {
Expand Down Expand Up @@ -142,18 +143,32 @@
/// Request mods from API server
function requestMods(branch, mcVersion, subsystem) {
invoke("request_mods", { mcVersion, subsystem })
const branchOptions = options.branchOptions[branch];
invoke("request_mods", { branch, mcVersion, subsystem })
.then(result => {
mods = result;
const branchOptions = options.branchOptions[branch];
if (branchOptions) {
mods.forEach(mod => {
mod.enabled = branchOptions.modStates[mod.name] ?? mod.enabled;
});
}
})
.catch(e => console.error(e));
invoke("get_custom_mods", { branch, mcVersion })
.then(result => {
console.log("Fetched custom mods", result);
customMods = result;
if (branchOptions) {
mods.forEach(mod => {
mod.enabled = branchOptions.customModStates[mod.name] ?? mod.enabled;
});
}
})
.catch(e => console.error(e));
}
// Request branches from API server
Expand Down Expand Up @@ -192,7 +207,7 @@
let build = getBuild();
console.debug("Running build", build);
await invoke("run_client", { buildId: build.buildId, accountData: options.currentAccount, options: options, mods: mods });
await invoke("run_client", { buildId: build.buildId, accountData: options.currentAccount, options: options, mods: [...mods, ...customMods] });
}
listen("client-exited", () => {
Expand Down Expand Up @@ -270,20 +285,17 @@
<ToggleSetting title="Show nightly builds" bind:value={options.showNightlyBuilds} disabled={false} on:change={updateData} />
<SettingWrapper title="Recommended mods">
{#each mods as m}
{#if !m.required}
<ToggleSetting title={m.name} bind:value={m.enabled} disabled={false} on:change={updateModStates} />
{/if}
<ToggleSetting title={m.name} bind:value={m.enabled} disabled={m.required} on:change={updateModStates} />
{/each}
</SettingWrapper>
<SettingWrapper title="Additional mods for nextgen-1.20.4">
<div slot="title-element">
<IconButtonSetting text="Install" icon="icon-plus" />
</div>
<CustomModSetting title="Iris" value={true} />
<CustomModSetting title="Classy Creepers" value={true} />
<CustomModSetting title="Axolotl" value={false} />
<CustomModSetting title="Advanced Snek" value={true} />
{#each customMods as m}
<CustomModSetting title={m.name} value={m.enabled} on:change={updateModStates} />
{/each}
</SettingWrapper>
</SettingsContainer>
{/if}
Expand Down

0 comments on commit 0607ab6

Please sign in to comment.