dmclc5 0.3.2

A minecraft launching library
Documentation
use std::{ffi::OsString, fmt::Display};

use anyhow::{anyhow, Result};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use tokio::fs;

use crate::{minecraft::{login::{Account, AccountConstructor}, version::MinecraftInstallation}, utils::{download, BetterPath}, LauncherContext};

use super::{YggdrasilAccount, YggdrasilUserData};

#[derive(Serialize, Deserialize)]
struct MinecraftUniversalLoginAccount {
    data: Option<YggdrasilUserData>,
    server_id: Option<String>
}

impl Display for MinecraftUniversalLoginAccount {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        if let Some(v) = &self.get_data() {
            write!(f, "{} ({})", v.name, v.server_name)
        } else {
            write!(f, "{} {}", t!("accounts.uninitialized"), t!("accounts.minecraft_universal_login.name"))
        }
    }
}

pub(crate) struct MinecraftUniversalLoginAccountConstructor;

impl AccountConstructor for MinecraftUniversalLoginAccountConstructor {
    fn new(&self) -> Box<dyn Account> {
        Box::new(MinecraftUniversalLoginAccount {
            data: None,
            server_id: None
        })
    }

    fn deserialize(&self, de: &mut dyn erased_serde::Deserializer) -> Option<Box<dyn Account>> {
        Some(Box::new(erased_serde::deserialize::<MinecraftUniversalLoginAccount>(de).ok()?))
    }
}

#[async_trait]
impl YggdrasilAccount for MinecraftUniversalLoginAccount {

    fn is_initialized(&self) -> bool {
        self.data.is_some() && self.server_id.is_some()
    }

    fn get_data(&self) -> &Option<YggdrasilUserData> {
        &self.data
    }

    fn get_data_mut(&mut self) -> &mut Option<YggdrasilUserData> {
        &mut self.data
    }

    fn set_data(&mut self, data: YggdrasilUserData) {
        self.data = Some(data);
    }

    async fn ask_api_url(&mut self, launcher: &LauncherContext) -> Result<String> {
        if self.server_id.is_none() {
            self.server_id = Some(launcher.ui.ask_user_one(&t!("accounts.minecraft_universal_login.serverID"), None).await.ok_or(anyhow!("User cancelled"))?);
        }
        Ok(format!("https://auth.mc-user.com:233/{}", self.server_id.as_ref().unwrap()))
    }

    async fn prepare_launch(&self, version_launch_dir: &BetterPath, _: &LauncherContext) -> Result<()> {
        let path = version_launch_dir / "nide8auth.jar";
        if fs::metadata(&*path).await.is_err() {
            download("https://login.mc-user.com:233/index/jar", path.as_ref()).await?;
        }
        Ok(())
    }

    async fn get_launch_jvmargs(&self, _mc: &MinecraftInstallation, _: &LauncherContext) -> Result<Vec<OsString>> {
        Ok(vec![OsString::from(format!("-javaagent:./nide8auth.jar={}", self.server_id.as_ref().unwrap())), OsString::from("-Dnide8auth.client=true")])
    }
}