feat:移除了弹窗,服务器添加sls
This commit is contained in:
277
packages/app-lib/src/api/pack/import/atlauncher.rs
Normal file
277
packages/app-lib/src/api/pack/import/atlauncher.rs
Normal file
@ -0,0 +1,277 @@
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
State,
|
||||
install::{InstallPhaseDetails, InstallProgressReporter},
|
||||
pack::{
|
||||
self,
|
||||
import::{self, finish_import},
|
||||
install_from::CreatePackDescription,
|
||||
},
|
||||
prelude::ModLoader,
|
||||
state::{
|
||||
AppliedContentSetPatch, EditInstance, InstanceInstallStage,
|
||||
InstanceLink,
|
||||
},
|
||||
util::io,
|
||||
};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ATInstance {
|
||||
pub id: String, // minecraft version id ie: 1.12.1, not a name
|
||||
pub launcher: ATLauncher,
|
||||
pub java_version: ATJavaVersion,
|
||||
}
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ATLauncher {
|
||||
pub name: String,
|
||||
pub pack: String,
|
||||
pub version: String, // ie: 1.6
|
||||
pub loader_version: ATLauncherLoaderVersion,
|
||||
|
||||
pub modrinth_project: Option<ATLauncherModrinthProject>,
|
||||
pub modrinth_version: Option<ATLauncherModrinthVersion>,
|
||||
pub modrinth_manifest: Option<pack::install_from::PackFormat>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ATJavaVersion {
|
||||
pub major_version: u8,
|
||||
pub component: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ATLauncherLoaderVersion {
|
||||
pub r#type: String,
|
||||
pub version: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ATLauncherModrinthProject {
|
||||
pub id: String,
|
||||
pub slug: String,
|
||||
pub project_type: String,
|
||||
pub team: String,
|
||||
pub client_side: Option<String>,
|
||||
pub server_side: Option<String>,
|
||||
pub categories: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ATLauncherModrinthVersion {
|
||||
pub id: String,
|
||||
pub project_id: String,
|
||||
pub name: String,
|
||||
pub version_number: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ATLauncherModrinthVersionFile {
|
||||
pub hashes: HashMap<String, String>,
|
||||
pub url: String,
|
||||
pub filename: String,
|
||||
pub primary: bool,
|
||||
pub size: u64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ATLauncherModrinthVersionDependency {
|
||||
pub project_id: Option<String>,
|
||||
pub version_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ATLauncherMod {
|
||||
pub name: String,
|
||||
pub version: String,
|
||||
pub file: String,
|
||||
|
||||
pub modrinth_project: Option<ATLauncherModrinthProject>,
|
||||
pub modrinth_version: Option<ATLauncherModrinthVersion>,
|
||||
}
|
||||
|
||||
// Check if folder has a instance.json that parses
|
||||
pub async fn is_valid_atlauncher(instance_folder: PathBuf) -> bool {
|
||||
let instance = serde_json::from_str::<ATInstance>(
|
||||
&io::read_any_encoding_to_string(
|
||||
&instance_folder.join("instance.json"),
|
||||
)
|
||||
.await
|
||||
.unwrap_or(("".into(), encoding_rs::UTF_8))
|
||||
.0,
|
||||
);
|
||||
|
||||
if let Err(e) = instance {
|
||||
tracing::warn!(
|
||||
"Could not parse instance.json at {}: {}",
|
||||
instance_folder.display(),
|
||||
e
|
||||
);
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
|
||||
pub async fn import_atlauncher_dir(
|
||||
atlauncher_base_path: PathBuf,
|
||||
atlauncher_instance_path: PathBuf,
|
||||
instance_id: &str,
|
||||
reporter: InstallProgressReporter,
|
||||
details: InstallPhaseDetails,
|
||||
symlink: bool,
|
||||
) -> crate::Result<()> {
|
||||
let atinstance = serde_json::from_str::<ATInstance>(
|
||||
&io::read_any_encoding_to_string(
|
||||
&atlauncher_instance_path.join("instance.json"),
|
||||
)
|
||||
.await
|
||||
.unwrap_or(("".into(), encoding_rs::UTF_8))
|
||||
.0,
|
||||
)?;
|
||||
|
||||
let icon_path_primary = atlauncher_instance_path.join("instance.png");
|
||||
let safe_pack_name = atinstance
|
||||
.launcher
|
||||
.pack
|
||||
.replace(|c: char| !c.is_alphanumeric(), "")
|
||||
.to_lowercase();
|
||||
let icon_path_secondary = atlauncher_base_path
|
||||
.join("configs")
|
||||
.join("images")
|
||||
.join(safe_pack_name + ".png");
|
||||
let icon = match (icon_path_primary.exists(), icon_path_secondary.exists())
|
||||
{
|
||||
(true, _) => import::recache_icon(icon_path_primary).await?,
|
||||
(_, true) => import::recache_icon(icon_path_secondary).await?,
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let description = CreatePackDescription {
|
||||
icon,
|
||||
override_title: Some(atinstance.launcher.name.clone()),
|
||||
project_id: None,
|
||||
version_id: None,
|
||||
instance_id: instance_id.to_string(),
|
||||
source_filename: None,
|
||||
};
|
||||
|
||||
let backup_name = format!(
|
||||
"ATLauncher-{}",
|
||||
atlauncher_instance_path
|
||||
.file_name()
|
||||
.map(|name| name.to_string_lossy())
|
||||
.unwrap_or_default()
|
||||
);
|
||||
let minecraft_folder = atlauncher_instance_path;
|
||||
|
||||
import_atlauncher_unmanaged(
|
||||
instance_id,
|
||||
minecraft_folder,
|
||||
backup_name,
|
||||
description,
|
||||
atinstance,
|
||||
reporter,
|
||||
details,
|
||||
symlink,
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn import_atlauncher_unmanaged(
|
||||
instance_id: &str,
|
||||
minecraft_folder: PathBuf,
|
||||
backup_name: String,
|
||||
description: CreatePackDescription,
|
||||
atinstance: ATInstance,
|
||||
reporter: InstallProgressReporter,
|
||||
details: InstallPhaseDetails,
|
||||
symlink: bool,
|
||||
) -> crate::Result<()> {
|
||||
let mod_loader = format!(
|
||||
"\"{}\"",
|
||||
atinstance.launcher.loader_version.r#type.to_lowercase()
|
||||
);
|
||||
let mod_loader: ModLoader = serde_json::from_str::<ModLoader>(&mod_loader)
|
||||
.map_err(|_| {
|
||||
crate::ErrorKind::InputError(format!(
|
||||
"Could not parse mod loader type: {mod_loader}"
|
||||
))
|
||||
})?;
|
||||
|
||||
let game_version = atinstance.id;
|
||||
|
||||
let loader_version = if mod_loader != ModLoader::Vanilla {
|
||||
crate::launcher::get_loader_version_from_profile(
|
||||
&game_version,
|
||||
mod_loader,
|
||||
Some(&atinstance.launcher.loader_version.version),
|
||||
)
|
||||
.await?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let link = match (&description.project_id, &description.version_id) {
|
||||
(Some(project_id), Some(version_id)) => {
|
||||
Some(InstanceLink::ModrinthModpack {
|
||||
project_id: project_id.clone(),
|
||||
version_id: version_id.clone(),
|
||||
})
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
crate::api::instance::edit(
|
||||
instance_id,
|
||||
EditInstance {
|
||||
install_stage: Some(InstanceInstallStage::PackInstalling),
|
||||
name: Some(
|
||||
description
|
||||
.override_title
|
||||
.clone()
|
||||
.unwrap_or_else(|| backup_name.to_string()),
|
||||
),
|
||||
icon_path: Some(
|
||||
description
|
||||
.icon
|
||||
.clone()
|
||||
.map(|x| x.to_string_lossy().to_string()),
|
||||
),
|
||||
link,
|
||||
content_set_patch: Some(AppliedContentSetPatch {
|
||||
source_kind: None,
|
||||
game_version: Some(game_version.clone()),
|
||||
protocol_version: Some(None),
|
||||
loader: Some(mod_loader),
|
||||
loader_version: Some(loader_version.clone().map(|x| x.id)),
|
||||
}),
|
||||
..EditInstance::default()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Moves .minecraft folder over (ie: overrides such as resourcepacks, mods, etc)
|
||||
let state = State::get().await?;
|
||||
finish_import(
|
||||
instance_id,
|
||||
minecraft_folder,
|
||||
&state.io_semaphore,
|
||||
reporter,
|
||||
details,
|
||||
symlink,
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user