Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added public/images/icons/OptiFine.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
56 changes: 54 additions & 2 deletions src-tauri/src/instance/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ use crate::instance::helpers::client_json::{replace_native_libraries, McClientIn
use crate::instance::helpers::game_version::{build_game_version_cmp_fn, compare_game_versions};
use crate::instance::helpers::loader::common::{execute_processors, install_mod_loader};
use crate::instance::helpers::loader::forge::InstallProfile;
use crate::instance::helpers::loader::optifine::{
download_optifine_installer, finish_optifine_install,
};
use crate::instance::helpers::misc::{
get_instance_game_config, get_instance_subdir_path_by_id, get_instance_subdir_paths,
refresh_and_update_instances, unify_instance_name,
Expand All @@ -26,7 +29,8 @@ use crate::instance::helpers::server::{
use crate::instance::helpers::world::{load_level_data_from_nbt, load_world_info_from_dir};
use crate::instance::models::misc::{
Instance, InstanceError, InstanceSubdirType, InstanceSummary, LocalModInfo, ModLoader,
ModLoaderStatus, ModLoaderType, ResourcePackInfo, SchematicInfo, ScreenshotInfo, ShaderPackInfo,
ModLoaderStatus, ModLoaderType, OptiFine, ResourcePackInfo, SchematicInfo, ScreenshotInfo,
ShaderPackInfo,
};
use crate::instance::models::world::base::WorldInfo;
use crate::instance::models::world::level::LevelData;
Expand All @@ -35,7 +39,9 @@ use crate::launcher_config::helpers::misc::get_global_game_config;
use crate::launcher_config::models::{GameConfig, GameDirectory, LauncherConfig};
use crate::partial::{PartialError, PartialUpdate};
use crate::resource::helpers::misc::get_source_priority_list;
use crate::resource::models::{GameClientResourceInfo, ModLoaderResourceInfo};
use crate::resource::models::{
GameClientResourceInfo, ModLoaderResourceInfo, OptiFineResourceInfo,
};
use crate::storage::{load_json_async, save_json_async, Storage};
use crate::tasks::commands::schedule_progressive_task_group;
use crate::tasks::download::DownloadParam;
Expand Down Expand Up @@ -862,6 +868,7 @@ pub async fn create_instance(
icon_src: String,
game: GameClientResourceInfo,
mod_loader: ModLoaderResourceInfo,
optifine: Option<OptiFineResourceInfo>,
modpack_path: Option<String>,
is_install_fabric_api: Option<bool>,
) -> SJMCLResult<()> {
Expand All @@ -878,6 +885,11 @@ pub async fn create_instance(
if version_path.exists() {
return Err(InstanceError::ConflictNameError.into());
}
let optifine_info = optifine.as_ref().map(|info| OptiFine {
filename: info.filename.clone(),
version: format!("{}_{}", info.r#type, info.patch),
status: ModLoaderStatus::NotDownloaded,
});

// Create instance config
let instance = Instance {
Expand All @@ -898,6 +910,7 @@ pub async fn create_instance(
version: mod_loader.version.clone(),
branch: mod_loader.branch.clone(),
},
optifine: optifine_info,
description,
icon_src,
starred: false,
Expand Down Expand Up @@ -969,6 +982,7 @@ pub async fn create_instance(
task_params
.extend(get_invalid_assets(&app, &version_info, priority_list[0], assets_dir, false).await?);

// download loader (installer)
if instance.mod_loader.loader_type != ModLoaderType::Unknown {
install_mod_loader(
app.clone(),
Expand All @@ -984,6 +998,16 @@ pub async fn create_instance(
.await?;
}

if let Some(info) = optifine.as_ref() {
download_optifine_installer(
&instance.version,
info,
libraries_dir.to_path_buf(),
&mut task_params,
)
.await?;
}

// If modpack path is provided, install it
if let Some(modpack_path) = modpack_path {
let path = PathBuf::from(modpack_path);
Expand Down Expand Up @@ -1079,13 +1103,41 @@ pub async fn finish_mod_loader_install(app: AppHandle, instance_id: String) -> S
execute_processors(&app, &instance, &client_info, &install_profile).await?;
}

if let Some(optifine) = &instance.optifine {
match optifine.status {
// prevent duplicated installation
ModLoaderStatus::DownloadFailed => {
return Err(InstanceError::ProcessorExecutionFailed.into());
}
ModLoaderStatus::Installing => {
return Err(InstanceError::InstallationDuplicated.into());
}
ModLoaderStatus::Installed => {
return Ok(());
}
_ => {}
}
{
let binding = app.state::<Mutex<HashMap<String, Instance>>>();
let mut state = binding.lock()?;
let instance = state
.get_mut(&instance_id)
.ok_or(InstanceError::InstanceNotFoundByID)?;
instance.optifine.as_mut().unwrap().status = ModLoaderStatus::Installing;
};
finish_optifine_install(&app, &instance, &client_info).await?;
}

let instance = {
let binding = app.state::<Mutex<HashMap<String, Instance>>>();
let mut state = binding.lock()?;
let instance = state
.get_mut(&instance_id)
.ok_or(InstanceError::InstanceNotFoundByID)?;
instance.mod_loader.status = ModLoaderStatus::Installed;
if let Some(optifine) = &mut instance.optifine {
optifine.status = ModLoaderStatus::Installed;
}
instance.clone()
};
instance.save_json_cfg().await?;
Expand Down
32 changes: 23 additions & 9 deletions src-tauri/src/instance/helpers/client_json.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::error::{SJMCLError, SJMCLResult};
use crate::instance::helpers::game_version::compare_game_versions;
use crate::instance::models::misc::{Instance, ModLoaderType};
use crate::launcher_config::models::LauncherConfig;
use crate::resource::models::OptiFineResourceInfo;
use crate::utils::fs::get_app_resource_filepath;
use regex::RegexBuilder;
use serde::{Deserialize, Deserializer, Serialize};
Expand Down Expand Up @@ -306,10 +306,16 @@ pub struct LoggingFile {

pub fn patches_to_info(
patches: &[McClientInfo],
) -> (Option<String>, Option<String>, ModLoaderType) {
) -> (
Option<String>,
Option<String>,
ModLoaderType,
Option<OptiFineResourceInfo>,
) {
let mut loader_type = ModLoaderType::Unknown;
let mut game_version = None;
let mut loader_version = None;
let mut optifine_info: Option<OptiFineResourceInfo> = None;
for patch in patches {
if game_version.is_none() && patch.id == "game" {
game_version = patch.version.clone();
Expand All @@ -320,18 +326,25 @@ pub fn patches_to_info(
loader_version = patch.version.clone();
}
}

if game_version.is_some() && loader_type != ModLoaderType::Unknown {
break;
if patch.id == "optifine" {
optifine_info = Some(OptiFineResourceInfo {
patch: "".to_string(),
filename: "".to_string(),
r#type: patch.version.clone().unwrap_or_default(),
});
}
}

(game_version, loader_version, loader_type)
(game_version, loader_version, loader_type, optifine_info)
}

pub async fn libraries_to_info(
client: &McClientInfo,
) -> (Option<String>, Option<String>, ModLoaderType) {
) -> (
Option<String>,
Option<String>,
ModLoaderType,
Option<OptiFineResourceInfo>,
) {
let game_version: Option<String> = client.client_version.clone();
let mut loader_version: Option<String> = None;
let mut loader_type = ModLoaderType::Unknown;
Expand Down Expand Up @@ -394,7 +407,7 @@ pub async fn libraries_to_info(
}
}

(game_version, loader_version, loader_type)
(game_version, loader_version, loader_type, None)
}

fn rules_is_allowed(rules: &Vec<InstructionRule>, feature: &FeaturesInfo) -> SJMCLResult<bool> {
Expand Down Expand Up @@ -478,6 +491,7 @@ pub async fn replace_native_libraries(

#[cfg(all(target_arch = "aarch64", target_os = "macos"))]
{
use crate::instance::helpers::game_version::compare_game_versions;
if compare_game_versions(app, instance.version.as_str(), "1.20.1", true).await
== Ordering::Greater
{
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/src/instance/helpers/loader/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub async fn install_mod_loader(
.await
}
ModLoaderType::Forge => {
install_forge_loader(priority, game_version, loader, lib_dir, task_params).await
install_forge_loader(priority, game_version, loader, lib_dir.clone(), task_params).await
}
ModLoaderType::NeoForge => {
install_neoforge_loader(priority, loader, lib_dir, task_params).await
Expand Down
21 changes: 7 additions & 14 deletions src-tauri/src/instance/helpers/loader/forge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ pub async fn download_forge_libraries(
app: &AppHandle,
priority: &[SourceType],
instance: &Instance,
client_info: &McClientInfo,
is_retry: bool, // do not modify client info, just download necessary files
client_info: &mut McClientInfo,
) -> SJMCLResult<()> {
let subdirs = get_instance_subdir_paths(
app,
Expand All @@ -109,8 +108,6 @@ pub async fn download_forge_libraries(
};
let mut task_params = vec![];

let mut client_info = client_info.clone();

let installer_coord = format!(
"net.minecraftforge:forge:{}-installer",
instance.mod_loader.version
Expand All @@ -124,6 +121,9 @@ pub async fn download_forge_libraries(
),
None,
)?);
if !installer_path.exists() {
return Err(InstanceError::LoaderInstallerNotFound.into());
}
let file = File::open(&installer_path)?;
let mut archive = ZipArchive::new(file)?;

Expand Down Expand Up @@ -304,14 +304,14 @@ pub async fn download_forge_libraries(
}));
}

let (arguments, minecraft_arguments) = if let Some(v_args) = client_info.arguments {
let (arguments, minecraft_arguments) = if let Some(v_args) = &client_info.arguments {
let nf_args = forge_info
.arguments
.ok_or(InstanceError::ModLoaderVersionParseError)?;

let new_args = LaunchArgumentTemplate {
game: [v_args.game, nf_args.game].concat(),
jvm: [v_args.jvm, nf_args.jvm].concat(),
game: [v_args.game.clone(), nf_args.game.clone()].concat(),
jvm: [v_args.jvm.clone(), nf_args.jvm.clone()].concat(),
};
(Some(new_args), None)
} else {
Expand Down Expand Up @@ -447,13 +447,6 @@ pub async fn download_forge_libraries(
)
.await?;

if !is_retry {
let vjson_path = instance
.version_path
.join(format!("{}.json", instance.name));
fs::write(vjson_path, serde_json::to_vec_pretty(&client_info)?)?;
}

Ok(())
}

Expand Down
1 change: 1 addition & 0 deletions src-tauri/src/instance/helpers/loader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ pub mod common;
pub mod fabric;
pub mod forge;
pub mod neoforge;
pub mod optifine;
14 changes: 4 additions & 10 deletions src-tauri/src/instance/helpers/loader/neoforge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ pub async fn download_neoforge_libraries(
app: &AppHandle,
priority: &[SourceType],
instance: &Instance,
client_info: &McClientInfo,
is_retry: bool, // do not modify client info, just download necessary files
client_info: &mut McClientInfo,
) -> SJMCLResult<()> {
let subdirs = get_instance_subdir_paths(
app,
Expand All @@ -86,8 +85,6 @@ pub async fn download_neoforge_libraries(
};
let mut task_params = vec![];

let mut client_info = client_info.clone();

let name = if instance.mod_loader.version.starts_with("1.20.1-") {
"forge"
} else {
Expand All @@ -107,6 +104,9 @@ pub async fn download_neoforge_libraries(
),
None,
)?);
if !installer_path.exists() {
return Err(InstanceError::LoaderInstallerNotFound.into());
}
let (content, version) = {
let file = File::open(&installer_path)?;
let mut archive = ZipArchive::new(file)?;
Expand Down Expand Up @@ -341,11 +341,5 @@ pub async fn download_neoforge_libraries(
)
.await?;

if !is_retry {
let vjson_path = instance
.version_path
.join(format!("{}.json", instance.name));
fs::write(vjson_path, serde_json::to_vec_pretty(&client_info)?)?;
}
Ok(())
}
Loading
Loading