You've already forked AstralRinth
forked from didirus/AstralRinth
fixes (#449)
* fixes * prettier * more bugs * changes * more fixes * prettier, fmt, clippy * fix regressed error * println, console.log * fix imports --------- Co-authored-by: Geometrically <18202329+Geometrically@users.noreply.github.com> Co-authored-by: Jai A <jaiagr+gpg@pm.me>
This commit is contained in:
@@ -229,7 +229,13 @@ async fn import_atlauncher_unmanaged(
|
||||
.await?;
|
||||
|
||||
// Moves .minecraft folder over (ie: overrides such as resourcepacks, mods, etc)
|
||||
copy_dotminecraft(profile_path.clone(), minecraft_folder).await?;
|
||||
let state = State::get().await?;
|
||||
copy_dotminecraft(
|
||||
profile_path.clone(),
|
||||
minecraft_folder,
|
||||
&state.io_semaphore,
|
||||
)
|
||||
.await?;
|
||||
|
||||
if let Some(profile_val) =
|
||||
crate::api::profile::get(&profile_path, None).await?
|
||||
|
||||
@@ -5,11 +5,14 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::{
|
||||
prelude::{ModLoader, ProfilePathId},
|
||||
state::ProfileInstallStage,
|
||||
util::io,
|
||||
util::{
|
||||
fetch::{fetch, write_cached_icon},
|
||||
io,
|
||||
},
|
||||
State,
|
||||
};
|
||||
|
||||
use super::copy_dotminecraft;
|
||||
use super::{copy_dotminecraft, recache_icon};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@@ -31,12 +34,20 @@ pub struct FlameModLoader {
|
||||
pub primary: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct MinecraftInstance {
|
||||
pub name: Option<String>,
|
||||
pub profile_image_path: Option<PathBuf>,
|
||||
pub installed_modpack: Option<InstalledModpack>,
|
||||
pub game_version: String, // Minecraft game version. Non-prioritized, use this if Vanilla
|
||||
}
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
||||
pub struct InstalledModpack {
|
||||
pub thumbnail_url: Option<String>,
|
||||
}
|
||||
|
||||
// Check if folder has a minecraftinstance.json that parses
|
||||
pub async fn is_valid_curseforge(instance_folder: PathBuf) -> bool {
|
||||
@@ -53,9 +64,6 @@ pub async fn import_curseforge(
|
||||
curseforge_instance_folder: PathBuf, // instance's folder
|
||||
profile_path: ProfilePathId, // path to profile
|
||||
) -> crate::Result<()> {
|
||||
// TODO: recache curseforge instance icon
|
||||
let icon: Option<PathBuf> = None;
|
||||
|
||||
// Load minecraftinstance.json
|
||||
let minecraft_instance: String = io::read_to_string(
|
||||
&curseforge_instance_folder.join("minecraftinstance.json"),
|
||||
@@ -72,6 +80,32 @@ pub async fn import_curseforge(
|
||||
.unwrap_or("Unknown".to_string())
|
||||
);
|
||||
|
||||
let state = State::get().await?;
|
||||
// Recache Curseforge Icon if it exists
|
||||
let mut icon = None;
|
||||
|
||||
if let Some(icon_path) = minecraft_instance.profile_image_path.clone() {
|
||||
icon = recache_icon(icon_path).await?;
|
||||
} else if let Some(InstalledModpack {
|
||||
thumbnail_url: Some(thumbnail_url),
|
||||
}) = minecraft_instance.installed_modpack.clone()
|
||||
{
|
||||
let icon_bytes =
|
||||
fetch(&thumbnail_url, None, &state.fetch_semaphore).await?;
|
||||
let filename = thumbnail_url.rsplit('/').last();
|
||||
if let Some(filename) = filename {
|
||||
icon = Some(
|
||||
write_cached_icon(
|
||||
filename,
|
||||
&state.directories.caches_dir(),
|
||||
icon_bytes,
|
||||
&state.io_semaphore,
|
||||
)
|
||||
.await?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Curseforge vanilla profile may not have a manifest.json, so we allow it to not exist
|
||||
if curseforge_instance_folder.join("manifest.json").exists() {
|
||||
// Load manifest.json
|
||||
@@ -146,7 +180,13 @@ pub async fn import_curseforge(
|
||||
}
|
||||
|
||||
// Copy in contained folders as overrides
|
||||
copy_dotminecraft(profile_path.clone(), curseforge_instance_folder).await?;
|
||||
let state = State::get().await?;
|
||||
copy_dotminecraft(
|
||||
profile_path.clone(),
|
||||
curseforge_instance_folder,
|
||||
&state.io_semaphore,
|
||||
)
|
||||
.await?;
|
||||
|
||||
if let Some(profile_val) =
|
||||
crate::api::profile::get(&profile_path, None).await?
|
||||
|
||||
@@ -100,7 +100,13 @@ pub async fn import_gdlauncher(
|
||||
.await?;
|
||||
|
||||
// Copy in contained folders as overrides
|
||||
copy_dotminecraft(profile_path.clone(), gdlauncher_instance_folder).await?;
|
||||
let state = State::get().await?;
|
||||
copy_dotminecraft(
|
||||
profile_path.clone(),
|
||||
gdlauncher_instance_folder,
|
||||
&state.io_semaphore,
|
||||
)
|
||||
.await?;
|
||||
|
||||
if let Some(profile_val) =
|
||||
crate::api::profile::get(&profile_path, None).await?
|
||||
|
||||
@@ -280,7 +280,13 @@ async fn import_mmc_unmanaged(
|
||||
.await?;
|
||||
|
||||
// Moves .minecraft folder over (ie: overrides such as resourcepacks, mods, etc)
|
||||
copy_dotminecraft(profile_path.clone(), minecraft_folder).await?;
|
||||
let state = State::get().await?;
|
||||
copy_dotminecraft(
|
||||
profile_path.clone(),
|
||||
minecraft_folder,
|
||||
&state.io_semaphore,
|
||||
)
|
||||
.await?;
|
||||
|
||||
if let Some(profile_val) =
|
||||
crate::api::profile::get(&profile_path, None).await?
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{
|
||||
fmt,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use io::IOError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -6,7 +9,10 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::{
|
||||
prelude::ProfilePathId,
|
||||
state::Profiles,
|
||||
util::{fetch, io},
|
||||
util::{
|
||||
fetch::{self, IoSemaphore},
|
||||
io,
|
||||
},
|
||||
};
|
||||
|
||||
pub mod atlauncher;
|
||||
@@ -24,6 +30,19 @@ pub enum ImportLauncherType {
|
||||
#[serde(other)]
|
||||
Unknown,
|
||||
}
|
||||
// impl display
|
||||
impl fmt::Display for ImportLauncherType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
ImportLauncherType::MultiMC => write!(f, "MultiMC"),
|
||||
ImportLauncherType::PrismLauncher => write!(f, "PrismLauncher"),
|
||||
ImportLauncherType::ATLauncher => write!(f, "ATLauncher"),
|
||||
ImportLauncherType::GDLauncher => write!(f, "GDLauncher"),
|
||||
ImportLauncherType::Curseforge => write!(f, "Curseforge"),
|
||||
ImportLauncherType::Unknown => write!(f, "Unknown"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return a list of importable instances from a launcher type and base path, by iterating through the folder and checking
|
||||
pub async fn get_importable_instances(
|
||||
@@ -31,12 +50,12 @@ pub async fn get_importable_instances(
|
||||
base_path: PathBuf,
|
||||
) -> crate::Result<Vec<String>> {
|
||||
// Some launchers have a different folder structure for instances
|
||||
let instances_folder = match launcher_type {
|
||||
let instances_subfolder = match launcher_type {
|
||||
ImportLauncherType::GDLauncher
|
||||
| ImportLauncherType::MultiMC
|
||||
| ImportLauncherType::PrismLauncher
|
||||
| ImportLauncherType::ATLauncher => base_path.join("instances"),
|
||||
ImportLauncherType::Curseforge => base_path.join("Instances"),
|
||||
| ImportLauncherType::ATLauncher => "instances",
|
||||
ImportLauncherType::Curseforge => "Instances",
|
||||
ImportLauncherType::Unknown => {
|
||||
return Err(crate::ErrorKind::InputError(
|
||||
"Launcher type Unknown".to_string(),
|
||||
@@ -44,8 +63,13 @@ pub async fn get_importable_instances(
|
||||
.into())
|
||||
}
|
||||
};
|
||||
let instances_folder = base_path.join(instances_subfolder);
|
||||
let mut instances = Vec::new();
|
||||
let mut dir = io::read_dir(&instances_folder).await?;
|
||||
let mut dir = io::read_dir(&instances_folder).await.map_err(| _ | {
|
||||
crate::ErrorKind::InputError(format!(
|
||||
"Invalid {launcher_type} launcher path, could not find '{instances_subfolder}' subfolder."
|
||||
))
|
||||
})?;
|
||||
while let Some(entry) = dir
|
||||
.next_entry()
|
||||
.await
|
||||
@@ -216,6 +240,7 @@ pub async fn recache_icon(
|
||||
async fn copy_dotminecraft(
|
||||
profile_path: ProfilePathId,
|
||||
dotminecraft: PathBuf,
|
||||
io_semaphore: &IoSemaphore,
|
||||
) -> crate::Result<()> {
|
||||
// Get full path to profile
|
||||
let profile_path = profile_path.get_full_path().await?;
|
||||
@@ -236,6 +261,7 @@ async fn copy_dotminecraft(
|
||||
&path.display()
|
||||
))
|
||||
})?),
|
||||
io_semaphore,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
@@ -247,9 +273,13 @@ async fn copy_dotminecraft(
|
||||
#[theseus_macros::debug_pin]
|
||||
#[async_recursion::async_recursion]
|
||||
#[tracing::instrument]
|
||||
async fn copy_dir_to(src: &Path, dst: &Path) -> crate::Result<()> {
|
||||
async fn copy_dir_to(
|
||||
src: &Path,
|
||||
dst: &Path,
|
||||
io_semaphore: &IoSemaphore,
|
||||
) -> crate::Result<()> {
|
||||
if !src.is_dir() {
|
||||
io::copy(src, dst).await?;
|
||||
fetch::copy(src, dst, io_semaphore).await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -273,10 +303,10 @@ async fn copy_dir_to(src: &Path, dst: &Path) -> crate::Result<()> {
|
||||
|
||||
if src_child.is_dir() {
|
||||
// Recurse into sub-directory
|
||||
copy_dir_to(&src_child, &dst_child).await?;
|
||||
copy_dir_to(&src_child, &dst_child, io_semaphore).await?;
|
||||
} else {
|
||||
// Copy file
|
||||
io::copy(&src_child, &dst_child).await?;
|
||||
fetch::copy(&src_child, &dst_child, io_semaphore).await?;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::prelude::ProfilePathId;
|
||||
use crate::state::{ProfileInstallStage, Profiles, SideType};
|
||||
use crate::util::fetch::{fetch_mirrors, write};
|
||||
use crate::util::io;
|
||||
use crate::State;
|
||||
use crate::{profile, State};
|
||||
use async_zip::tokio::read::seek::ZipFileReader;
|
||||
|
||||
use std::io::Cursor;
|
||||
@@ -82,6 +82,7 @@ pub async fn install_zipped_mrpack_files(
|
||||
let version_id = create_pack.description.version_id;
|
||||
let existing_loading_bar = create_pack.description.existing_loading_bar;
|
||||
let profile_path = create_pack.description.profile_path;
|
||||
let icon_exists = icon.is_some();
|
||||
|
||||
let reader: Cursor<&bytes::Bytes> = Cursor::new(&file);
|
||||
|
||||
@@ -186,7 +187,7 @@ pub async fn install_zipped_mrpack_files(
|
||||
let path = profile_path
|
||||
.get_full_path()
|
||||
.await?
|
||||
.join(project.path);
|
||||
.join(&project.path);
|
||||
write(&path, &file, &state.io_semaphore)
|
||||
.await?;
|
||||
}
|
||||
@@ -261,6 +262,14 @@ pub async fn install_zipped_mrpack_files(
|
||||
}
|
||||
}
|
||||
|
||||
// If the icon doesn't exist, we expect icon.png to be a potential icon.
|
||||
// If it doesn't exist, and an override to icon.png exists, cache and use that
|
||||
let potential_icon =
|
||||
profile_path.get_full_path().await?.join("icon.png");
|
||||
if !icon_exists && potential_icon.exists() {
|
||||
profile::edit_icon(&profile_path, Some(&potential_icon)).await?;
|
||||
}
|
||||
|
||||
if let Some(profile_val) =
|
||||
crate::api::profile::get(&profile_path, None).await?
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user