feat: basic modrinth api implementation
This commit is contained in:
parent
56df69f911
commit
170762fc7b
11 changed files with 465 additions and 49 deletions
|
|
@ -246,10 +246,6 @@ pub async fn remove_user(uuid: Uuid) -> Result<(), String> {
|
|||
|
||||
// #[specta::specta]
|
||||
// #[tauri::command]
|
||||
// pub async fn import_instance() -> Result<(), String> {
|
||||
// onelauncher::api::package::import::import_instance()
|
||||
// pub async fn searchMods(query: String) -> Result<Vec<ModrinthMod>, String> {
|
||||
// // Ok(onelauncher::api::)
|
||||
// }
|
||||
|
||||
// #[specta::specta]
|
||||
// #[tauri::command]
|
||||
// pub async fn
|
||||
|
|
|
|||
20
apps/desktop/src/ui/hooks/useBrowserController.tsx
Normal file
20
apps/desktop/src/ui/hooks/useBrowserController.tsx
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import { type Context, type ParentProps, createContext, useContext } from 'solid-js';
|
||||
|
||||
interface BrowserContextType {
|
||||
getMod: (id: string) => void;
|
||||
getMods: (category: string) => void;
|
||||
};
|
||||
|
||||
const BrowserContext = createContext() as Context<BrowserContextType>;
|
||||
|
||||
export function BrowserContextProvider(props: ParentProps) {
|
||||
return (
|
||||
<BrowserContext.Provider value={{}}>
|
||||
{props.children}
|
||||
</BrowserContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export default function useBrowserController() {
|
||||
return useContext(BrowserContext);
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
function BrowserPage() {
|
||||
return (
|
||||
<div class="flex flex-col gap-y-4">
|
||||
<h1>Browser</h1>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default BrowserPage;
|
||||
|
|
@ -67,14 +67,9 @@ function BrowserMain() {
|
|||
</div>
|
||||
|
||||
<div class="flex flex-col h-full flex-1 gap-4 py-2">
|
||||
{/* eslint-disable-next-line ts/no-use-before-define -- blh */}
|
||||
<For each={_modRowData}>
|
||||
{row => (
|
||||
<>
|
||||
<ModsRow {...row} />
|
||||
<ModsRow {...row} />
|
||||
<ModsRow {...row} />
|
||||
</>
|
||||
<ModsRow {...row} />
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
|
|
@ -83,27 +78,27 @@ function BrowserMain() {
|
|||
);
|
||||
}
|
||||
|
||||
export const modStore: Mod[] = [
|
||||
{
|
||||
id: '1yIQcc2b',
|
||||
name: 'EvergreenHUD',
|
||||
description: 'Improves your heads up display.',
|
||||
author: 'Polyfrost',
|
||||
icon_url: 'https://cdn.modrinth.com/data/1yIQcc2b/icon.png',
|
||||
page_url: 'https://modrinth.com/mod/evergreenhud',
|
||||
provider: Provider.Modrinth,
|
||||
downloads: 281700,
|
||||
ratings: 220,
|
||||
},
|
||||
];
|
||||
// export const modStore: Mod[] = [
|
||||
// {
|
||||
// id: '1yIQcc2b',
|
||||
// name: 'EvergreenHUD',
|
||||
// description: 'Improves your heads up display.',
|
||||
// author: 'Polyfrost',
|
||||
// icon_url: 'https://cdn.modrinth.com/data/1yIQcc2b/icon.png',
|
||||
// page_url: 'https://modrinth.com/mod/evergreenhud',
|
||||
// provider: Provider.Modrinth,
|
||||
// downloads: 281700,
|
||||
// ratings: 220,
|
||||
// },
|
||||
// ];
|
||||
|
||||
const _modRowData: ModsRowProps[] = [
|
||||
{
|
||||
header: 'Highly Endorsed',
|
||||
category: 'endorsed',
|
||||
mods: modStore,
|
||||
},
|
||||
];
|
||||
// const _modRowData: ModsRowProps[] = [
|
||||
// {
|
||||
// header: 'Highly Endorsed',
|
||||
// category: 'endorsed',
|
||||
// mods: modStore,
|
||||
// },
|
||||
// ];
|
||||
|
||||
interface ModsRowProps {
|
||||
header: string;
|
||||
|
|
|
|||
76
crates/core/src/api/package/content/mod.rs
Normal file
76
crates/core/src/api/package/content/mod.rs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
//! **OneLauncher Content Package**
|
||||
//!
|
||||
//! Utilities for searching and downloading content packages to OneLauncher.
|
||||
|
||||
use anyhow::anyhow;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{data::{ManagedPackage, ManagedVersion}, Result};
|
||||
|
||||
mod modrinth;
|
||||
|
||||
/// Providers for content packages
|
||||
#[cfg_attr(feature = "tauri", derive(specta::Type))]
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
|
||||
pub enum Providers {
|
||||
// Curseforge,
|
||||
Modrinth,
|
||||
}
|
||||
|
||||
impl Providers {
|
||||
/// Get the name of the provider
|
||||
pub fn name(&self) -> &str {
|
||||
match self {
|
||||
// Providers::Curseforge => "Curseforge",
|
||||
Providers::Modrinth => "Modrinth",
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the URL of the provider
|
||||
pub fn url(&self) -> &str {
|
||||
match self {
|
||||
// Providers::Curseforge => "https://curseforge.com/",
|
||||
Providers::Modrinth => "https://modrinth.com",
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list(&self) -> Result<Vec<ManagedPackage>> {
|
||||
Ok(match self {
|
||||
// Providers::Curseforge => curseforge::list(),
|
||||
Providers::Modrinth => modrinth::list(),
|
||||
}.await?.into_iter().map(|p| p.into()).collect())
|
||||
}
|
||||
|
||||
pub async fn get(&self, slug_or_id: &str) -> Result<ManagedPackage> {
|
||||
Ok(match self {
|
||||
// Providers::Curseforge => curseforge::get(slug),
|
||||
Providers::Modrinth => modrinth::get(slug_or_id),
|
||||
}.await?.into())
|
||||
}
|
||||
|
||||
pub async fn get_versions(&self, project_id: &str) -> Result<Vec<ManagedVersion>> {
|
||||
Ok(match self {
|
||||
// Providers::Curseforge => curseforge::get_versions(slug),
|
||||
Providers::Modrinth => modrinth::get_versions(project_id),
|
||||
}.await?.into_iter().map(|p| p.into()).collect())
|
||||
}
|
||||
|
||||
pub async fn get_version(&self, version_id: &str) -> Result<ManagedVersion> {
|
||||
Ok(match self {
|
||||
// Providers::Curseforge => curseforge::get_version(slug, version),
|
||||
Providers::Modrinth => modrinth::get_version(version_id),
|
||||
}.await?.into())
|
||||
}
|
||||
|
||||
pub async fn get_version_for_game_version(&self, id: &str, game_version: &str) -> Result<ManagedVersion> {
|
||||
let versions = self.get_versions(id).await?;
|
||||
Ok(versions.into_iter().find(|v| v.game_versions.contains(&game_version.to_string())).ok_or(anyhow!("no game version found"))?) // TODO: error handling
|
||||
}
|
||||
|
||||
// pub async fn search(&self, query: &str) -> Result<Vec<ManagedPackage>> {
|
||||
// match self {
|
||||
// // Providers::Curseforge => curseforge::search(query),
|
||||
// Providers::Modrinth => modrinth::search(query),
|
||||
// }.await
|
||||
// }
|
||||
}
|
||||
273
crates/core/src/api/package/content/modrinth.rs
Normal file
273
crates/core/src/api/package/content/modrinth.rs
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
use crate::package::from::MODRINTH_API_URL;
|
||||
use crate::store::{ManagedVersionFile, PackageFile, PackageSide};
|
||||
use crate::utils::http::fetch;
|
||||
use crate::{State, Result};
|
||||
use crate::data::{ManagedPackage, ManagedVersion, PackageType};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ModrinthPackage {
|
||||
pub slug: String,
|
||||
pub title: String,
|
||||
#[serde(default)]
|
||||
pub description: String,
|
||||
#[serde(default)]
|
||||
pub categories: Vec<String>,
|
||||
#[serde(rename = "client_side")]
|
||||
pub client_side: PackageSide,
|
||||
#[serde(rename = "server_side")]
|
||||
pub server_side: PackageSide,
|
||||
// #[serde(default)]
|
||||
// pub body: String,
|
||||
// #[serde(default)]
|
||||
// pub status: String,
|
||||
// #[serde(default)]
|
||||
// #[serde(rename = "requested_status")]
|
||||
// pub requested_status: String,
|
||||
#[serde(default)]
|
||||
#[serde(rename = "additional_categories")]
|
||||
pub additional_categories: Vec<String>,
|
||||
// #[serde(rename = "issues_url")]
|
||||
// pub issues_url: String,
|
||||
// #[serde(rename = "source_url")]
|
||||
// pub source_url: String,
|
||||
// #[serde(rename = "wiki_url")]
|
||||
// pub wiki_url: String,
|
||||
// #[serde(rename = "discord_url")]
|
||||
// pub discord_url: String,
|
||||
// #[serde(rename = "donation_urls")]
|
||||
// pub donation_urls: Vec<DonationUrl>,
|
||||
// #[serde(rename = "project_type")]
|
||||
// pub project_type: String,
|
||||
pub downloads: u32,
|
||||
#[serde(rename = "icon_url")]
|
||||
pub icon_url: String,
|
||||
// pub color: i64,
|
||||
// #[serde(rename = "thread_id")]
|
||||
// pub thread_id: String,
|
||||
// #[serde(rename = "monetization_status")]
|
||||
// pub monetization_status: String,
|
||||
pub id: String,
|
||||
// pub team: String,
|
||||
// #[serde(rename = "body_url")]
|
||||
// pub body_url: Value,
|
||||
// #[serde(rename = "moderator_message")]
|
||||
// pub moderator_message: Value,
|
||||
pub published: DateTime<Utc>,
|
||||
pub updated: DateTime<Utc>,
|
||||
// pub approved: DateTime<Utc>,
|
||||
// pub queued: String,
|
||||
pub followers: u32,
|
||||
// pub license: License,
|
||||
pub versions: Vec<String>,
|
||||
#[serde(rename = "game_versions")]
|
||||
pub game_versions: Vec<String>,
|
||||
pub loaders: Vec<String>,
|
||||
// pub gallery: Vec<Gallery>,
|
||||
}
|
||||
|
||||
impl From<ModrinthPackage> for ManagedPackage {
|
||||
fn from(value: ModrinthPackage) -> ManagedPackage {
|
||||
ManagedPackage {
|
||||
id: value.id,
|
||||
title: value.title,
|
||||
description: value.description,
|
||||
main: value.slug,
|
||||
versions: value.versions,
|
||||
game_versions: value.game_versions,
|
||||
loaders: value.loaders,
|
||||
icon_url: Some(value.icon_url),
|
||||
created: value.published,
|
||||
updated: value.updated,
|
||||
client: value.client_side,
|
||||
server: value.server_side,
|
||||
downloads: value.downloads,
|
||||
followers: value.followers,
|
||||
categories: value.categories,
|
||||
optional_categories: Some(value.additional_categories),
|
||||
uid: None,
|
||||
package_type: PackageType::Mod,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DonationUrl {
|
||||
pub id: String,
|
||||
pub platform: String,
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct License {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Gallery {
|
||||
pub url: String,
|
||||
pub featured: bool,
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub created: String,
|
||||
pub ordering: i64,
|
||||
}
|
||||
|
||||
macro_rules! format_url {
|
||||
($($arg:tt)*) => {{
|
||||
format!("{}{}", MODRINTH_API_URL, format!($($arg)*))
|
||||
}};
|
||||
}
|
||||
|
||||
pub async fn list() -> Result<Vec<ModrinthPackage>> {
|
||||
Ok(serde_json::from_slice(
|
||||
&fetch(
|
||||
format_url!("/projects_random?count=10").as_str(),
|
||||
None,
|
||||
&State::get().await?.fetch_semaphore
|
||||
).await?
|
||||
)?)
|
||||
}
|
||||
|
||||
pub async fn get(id: &str) -> Result<ModrinthPackage> {
|
||||
Ok(serde_json::from_slice(
|
||||
&fetch(
|
||||
format_url!("/project/{}", id).as_str(),
|
||||
None,
|
||||
&State::get().await?.fetch_semaphore
|
||||
).await?
|
||||
)?)
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct SearchResults {
|
||||
hits: Vec<ModrinthPackage>,
|
||||
}
|
||||
|
||||
pub async fn search(
|
||||
query: &str,
|
||||
) -> Result<Vec<ModrinthPackage>> {
|
||||
// TODO: Fix date_created and date_updated inconsistency (published and updated)
|
||||
let response: SearchResults = serde_json::from_slice(
|
||||
&fetch(
|
||||
format_url!("/search?query={}", query).as_str(),
|
||||
None,
|
||||
&State::get().await?.fetch_semaphore
|
||||
).await?,
|
||||
)?;
|
||||
|
||||
Ok(response.hits)
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ModrinthVersion {
|
||||
#[serde(rename = "game_versions")]
|
||||
pub game_versions: Vec<String>,
|
||||
pub loaders: Vec<String>,
|
||||
pub id: String,
|
||||
#[serde(rename = "project_id")]
|
||||
pub project_id: String,
|
||||
#[serde(rename = "author_id")]
|
||||
pub author_id: String,
|
||||
pub featured: bool,
|
||||
pub name: String,
|
||||
#[serde(rename = "version_number")]
|
||||
pub version_number: String,
|
||||
pub changelog: String,
|
||||
#[serde(rename = "changelog_url")]
|
||||
pub changelog_url: Option<String>,
|
||||
#[serde(rename = "date_published")]
|
||||
pub date_published: DateTime<Utc>,
|
||||
pub downloads: u32,
|
||||
#[serde(rename = "version_type")]
|
||||
pub version_type: String,
|
||||
pub status: String,
|
||||
#[serde(rename = "requested_status")]
|
||||
pub requested_status: Value,
|
||||
pub files: Vec<File>,
|
||||
pub dependencies: Vec<Value>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct File {
|
||||
pub url: String,
|
||||
pub filename: String,
|
||||
pub primary: bool,
|
||||
pub size: u32,
|
||||
#[serde(rename = "file_type")]
|
||||
pub file_type: Option<PackageFile>,
|
||||
}
|
||||
|
||||
impl From<File> for ManagedVersionFile {
|
||||
fn from(value: File) -> Self {
|
||||
ManagedVersionFile {
|
||||
url: value.url,
|
||||
file_name: value.filename,
|
||||
primary: value.primary,
|
||||
size: value.size,
|
||||
file_type: value.file_type,
|
||||
hashes: Default::default(), // TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ModrinthVersion> for ManagedVersion {
|
||||
fn from(value: ModrinthVersion) -> Self {
|
||||
ManagedVersion {
|
||||
id: value.id,
|
||||
package_id: value.project_id,
|
||||
author: value.author_id,
|
||||
name: value.name,
|
||||
|
||||
featured: value.featured,
|
||||
version_id: value.version_number,
|
||||
changelog: value.changelog,
|
||||
changelog_url: value.changelog_url,
|
||||
|
||||
published: value.date_published,
|
||||
downloads: value.downloads,
|
||||
version_type: value.version_type,
|
||||
|
||||
files: value.files.into_iter().map(|f| f.into()).collect(),
|
||||
deps: vec![], // TODO [`ManagedDependency`]?
|
||||
game_versions: value.game_versions,
|
||||
loaders: value.loaders,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_versions(
|
||||
project_id: &str,
|
||||
) -> Result<Vec<ModrinthVersion>> {
|
||||
Ok(serde_json::from_slice(
|
||||
&fetch(
|
||||
format_url!("/project/{}/version", project_id).as_str(),
|
||||
None,
|
||||
&State::get().await?.fetch_semaphore
|
||||
).await?
|
||||
)?)
|
||||
}
|
||||
|
||||
pub async fn get_version(
|
||||
version_id: &str,
|
||||
) -> Result<ModrinthVersion> {
|
||||
Ok(serde_json::from_slice(
|
||||
&fetch(
|
||||
format_url!("/version/{}", version_id).as_str(),
|
||||
None,
|
||||
&State::get().await?.fetch_semaphore
|
||||
).await?
|
||||
)?)
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize};
|
|||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub const MODRINTH_API_URL: &str = "https://api.modrinth.com/v2/";
|
||||
pub const MODRINTH_API_URL: &str = "https://api.modrinth.com/v2";
|
||||
pub const CURSEFORGE_API_URL: &str = "https://api.cursefor";
|
||||
|
||||
#[derive(Serialize, Deserialize, Eq, PartialEq)]
|
||||
|
|
|
|||
|
|
@ -6,3 +6,4 @@ pub mod from;
|
|||
pub mod import;
|
||||
pub mod mrpack;
|
||||
pub mod zip;
|
||||
pub mod content;
|
||||
|
|
@ -368,6 +368,8 @@ pub async fn launch_minecraft(
|
|||
)
|
||||
.current_dir(instance_path.clone());
|
||||
|
||||
println!("command: {:#?}", command);
|
||||
|
||||
// when cargo makes the DYLD_LIBRARY_PATH it breaks Minecraft
|
||||
#[cfg(target_os = "macos")]
|
||||
if std::env::var("CARGO").is_ok() {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ use std::path::{Path, PathBuf};
|
|||
use tokio::io::AsyncReadExt;
|
||||
|
||||
use crate::prelude::IOError;
|
||||
use crate::utils::http::{write_icon, FetchSemaphore, IoSemaphore};
|
||||
use crate::utils::http::{self, write_icon, FetchSemaphore, IoSemaphore};
|
||||
use crate::State;
|
||||
|
||||
use super::{Cluster, PackagePath};
|
||||
|
||||
|
|
@ -83,6 +84,7 @@ pub async fn generate_context(
|
|||
}
|
||||
|
||||
/// Represents types of packages handled by the launcher.
|
||||
#[cfg_attr(feature = "tauri", derive(specta::Type))]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum PackageType {
|
||||
|
|
@ -188,7 +190,7 @@ pub struct ManagedPackage {
|
|||
// Core Metadata
|
||||
pub id: String,
|
||||
pub uid: Option<String>,
|
||||
pub package_type: String,
|
||||
pub package_type: PackageType,
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub main: String,
|
||||
|
|
@ -233,7 +235,7 @@ pub struct ManagedVersion {
|
|||
|
||||
/// Universal interface for managed package files.
|
||||
#[cfg_attr(feature = "tauri", derive(specta::Type))]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
|
||||
pub struct ManagedVersionFile {
|
||||
pub url: String,
|
||||
pub file_name: String,
|
||||
|
|
@ -244,6 +246,24 @@ pub struct ManagedVersionFile {
|
|||
pub hashes: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl ManagedVersionFile {
|
||||
#[tracing::instrument]
|
||||
pub async fn download_to_cluster(
|
||||
&self,
|
||||
cluster: &Cluster,
|
||||
) -> crate::Result<()> {
|
||||
tracing::info!("downloading mod '{}' to cluster '{}'", self.file_name, cluster.meta.name);
|
||||
let path = cluster.get_full_path().await?.join("mods").join(&self.file_name);
|
||||
let state = State::get().await?;
|
||||
|
||||
// TODO: Implement hashes
|
||||
let bytes = http::fetch(&self.url, None, &state.fetch_semaphore).await?;
|
||||
http::write(&path, &bytes, &state.io_semaphore).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Universal interface for managed package dependencies.
|
||||
#[cfg_attr(feature = "tauri", derive(specta::Type))]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
|
|
@ -290,7 +310,7 @@ pub enum PackageSide {
|
|||
|
||||
/// The file type of a [`Package`].
|
||||
#[cfg_attr(feature = "tauri", derive(specta::Type))]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum PackageFile {
|
||||
RequiredPack,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
)]
|
||||
|
||||
use onelauncher::cluster::create::create_cluster;
|
||||
use onelauncher::package::content::{self, Providers};
|
||||
use onelauncher::prelude::*;
|
||||
|
||||
pub async fn authenticate_mc() -> onelauncher::Result<MinecraftCredentials> {
|
||||
|
|
@ -39,7 +40,49 @@ async fn main() -> onelauncher::Result<()> {
|
|||
let _logger = onelauncher::start_logger();
|
||||
let state = State::get().await?;
|
||||
|
||||
if minecraft::users().await?.is_empty() {
|
||||
modrinth().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn modrinth() -> onelauncher::Result<()> {
|
||||
let state = State::get().await?;
|
||||
|
||||
let provider = Providers::Modrinth;
|
||||
|
||||
let result = provider.get("oneconfig").await?;
|
||||
println!("{:#?}", result);
|
||||
|
||||
let managed_version = provider.get_version_for_game_version(&result.id, "1.8.9").await?;
|
||||
println!("{:#?}", result);
|
||||
|
||||
let name = "forge 1.8.9 oneconfig".to_string();
|
||||
let game = "1.8.9".to_string();
|
||||
let loader = Loader::Forge;
|
||||
|
||||
let cluster_path = create_cluster(
|
||||
name.clone(),
|
||||
game,
|
||||
loader,
|
||||
None, // latest
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let cluster = cluster::get(&cluster_path, None).await?.expect("couldnt get cluster");
|
||||
managed_version.files.first().expect("no files found").download_to_cluster(&cluster).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn launch_and_authenticate() -> onelauncher::Result<()> {
|
||||
let state = State::get().await?;
|
||||
|
||||
if minecraft::users().await?.is_empty() {
|
||||
println!("authenticating");
|
||||
authenticate_mc().await?;
|
||||
}
|
||||
|
|
@ -94,5 +137,5 @@ async fn main() -> onelauncher::Result<()> {
|
|||
let mut proc = c_lock.write().await;
|
||||
processor::wait_for(&mut proc).await?;
|
||||
|
||||
Ok(())
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue