diff --git a/.gitignore b/.gitignore index 0bf2447e..df65775d 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,6 @@ vendor/ vender/ core/src/game -core/src/api/package # Created by https://www.toptal.com/developers/gitignore/api/git,node,rust,yarn,linux,macos,windows,rust-analyzer,visualstudiocode,intellij+all # Edit at https://www.toptal.com/developers/gitignore?templates=git,node,rust,yarn,linux,macos,windows,rust-analyzer,visualstudiocode,intellij+all diff --git a/core/src/api/package/from.rs b/core/src/api/package/from.rs new file mode 100644 index 00000000..e69de29b diff --git a/core/src/api/package/import/atlauncher.rs b/core/src/api/package/import/atlauncher.rs new file mode 100644 index 00000000..e69de29b diff --git a/core/src/api/package/import/curseforge.rs b/core/src/api/package/import/curseforge.rs new file mode 100644 index 00000000..e69de29b diff --git a/core/src/api/package/import/gdlauncher.rs b/core/src/api/package/import/gdlauncher.rs new file mode 100644 index 00000000..e69de29b diff --git a/core/src/api/package/import/mod.rs b/core/src/api/package/import/mod.rs new file mode 100644 index 00000000..776d3866 --- /dev/null +++ b/core/src/api/package/import/mod.rs @@ -0,0 +1,105 @@ +//! Manages importing data from other launchers. + +use std::{fmt, path::{Path, PathBuf}}; +use serde::{Serialize, Deserialize}; +use crate::{prelude::ClusterPath, utils::io::{self, IOError}}; + +pub mod atlauncher; +pub mod curseforge; +pub mod gdlauncher; +pub mod multibased; + +/// List of launcher types we support importing from. +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] +pub enum ImportType { + /// MultiMC based launchers + MultiMC, + /// Prism Launcher has its own category because it has different logic (also is objectively better than mmc) + PrismLauncher, + /// GDLauncher + GDLauncher, + /// Curseforge's launcher + Curseforge, + /// ATLauncher + ATLauncher, + /// Modrinth app. + Modrinth, + /// Unknown import option (not widely adopted -> probably a custom launcher with a similar file structure to the above) + #[serde(other)] + Unknown, +} + +impl fmt::Display for ImportType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ImportType::MultiMC => write!(f, "MultiMC"), + ImportType::ATLauncher => write!(f, "ATLauncher"), + ImportType::Curseforge => write!(f, "Curseforge"), + ImportType::GDLauncher => write!(f, "GDLauncher"), + ImportType::Modrinth => write!(f, "Modrinth"), + ImportType::PrismLauncher => write!(f, "PrismLauncher"), + ImportType::Unknown => write!(f, "Unknown"), + } + } +} + +pub async fn import_instances(import: ImportType, path: PathBuf) -> crate::Result> { + let instances_path = match import { + ImportType::GDLauncher | ImportType::ATLauncher => "instances".to_string(), + ImportType::Curseforge => "Instances".to_string(), + ImportType::MultiMC => multibased::get_instances_path(path.clone().join("multimc.cfg")).await.unwrap_or_else(|| "instances".to_string()), + ImportType::PrismLauncher => multibased::get_instances_path(path.clone().join("prismlauncher.cfg")).await.unwrap_or_else(|| "instances".to_string()), + ImportType::Modrinth => "Profiles".to_string(), + ImportType::Unknown | ImportType::Unknown => return Err(anyhow::anyhow!("launcher type unknown, cant import").into()), + }; + + let instances_dir = path.join(&instances_path); + let mut instances = Vec::new(); + let mut dir = io::read_dir(&instances_dir).await.map_err(|_| { + anyhow::anyhow!("invalid {import} launcher path, failed to import.") + })?; + + while let Some(e) = dir.next_entry().await.map_err(|e| IOError::with_path(e, &instances_dir))? { + let path = e.path(); + if path.is_dir() { + if is_valid_instance(path.clone(), import).await { + let name = path.file_name(); + if let Some(name) = name { + instances.push(name.to_string_lossy().to_string()); + } + } + } + } + + Ok(instances) +} + +#[tracing::instrument] +#[onelauncher_debug::debugger] +pub async fn import_instance( + cluster_path: ClusterPath, + import: ImportType, + path: PathBuf, + instance_path: String, +) -> crate::Result<()> { + tracing::debug!("importing instance from {instance_path}"); + + tracing::debug!("completed import of instance."); + Ok(()) +} + +/// recursively get a [`Vec`] of all subfiles. +#[onelauncher_debug::debugger] +#[async_recursion::async_recursion] +#[tracing::instrument] +pub async fn sub(path: &Path) -> crate::Result> { + if !path.is_dir() { return Ok(vec![path.to_path_buf()]); } + let mut files = Vec::new(); + let mut dir = io::read_dir(&path).await?; + while let Some(child) = dir.next_entry().await.map_err(|e| IOError::with_path(e, path))? { + let path_child = child.path(); + files.append(&mut sub(&path_child).await?); + } + + Ok(files) +} diff --git a/core/src/api/package/import/multibased.rs b/core/src/api/package/import/multibased.rs new file mode 100644 index 00000000..e69de29b diff --git a/core/src/api/package/mod.rs b/core/src/api/package/mod.rs new file mode 100644 index 00000000..2438e36b --- /dev/null +++ b/core/src/api/package/mod.rs @@ -0,0 +1,5 @@ +//! OneLauncher modpack management + +pub mod from; +pub mod mrpack; +pub mod import; diff --git a/core/src/api/package/mrpack.rs b/core/src/api/package/mrpack.rs new file mode 100644 index 00000000..e69de29b diff --git a/core/src/api/package/zip.rs b/core/src/api/package/zip.rs new file mode 100644 index 00000000..e69de29b diff --git a/package.json b/package.json index 362939b7..ebfd2d92 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@onelauncher/root", "type": "module", - "version": "0.0.0", + "version": "1.0.0", "packageManager": "pnpm@9.0.6", "description": "Next-generation open source Minecraft launcher and tools for interacting with Polyfrost", "license": "MIT", @@ -17,11 +17,13 @@ "dev": "pnpm gui tauri dev", "build": "pnpm gui tauri build", "lint": "eslint . --cache", - "format": "pnpm lint --fix && cargo fmt" + "format": "pnpm lint --fix && cargo fmt", + "release:node": "bumpp -r" }, "devDependencies": { "@flowr/eslint-config": "^3.0.0", "@types/node": "^20.12.7", + "bumpp": "^9.4.0", "eslint": "^8.56.0", "eslint-plugin-solid": "^0.13.2", "typescript": "^5.4.5"