1
0

Updating + Profile Repairs + Performance Improvements (#97)

* repairing

* Main framework for updating

* add jsconfig

* more work

* Improve performance

* Finish updating

* run lint
This commit is contained in:
Geometrically
2023-04-26 10:28:08 -07:00
committed by GitHub
parent c53104c28e
commit f0b8a708a3
48 changed files with 1217 additions and 894 deletions

View File

@@ -1,7 +1,6 @@
//! Authentication flow based on Hydra
use crate::util::fetch::{fetch_advanced, fetch_json};
use async_tungstenite as ws;
use bincode::{Decode, Encode};
use chrono::{prelude::*, Duration};
use futures::prelude::*;
use lazy_static::lazy_static;
@@ -50,14 +49,12 @@ struct ProfileInfoJSON {
}
// Login information
#[derive(Encode, Decode, Serialize, Deserialize, Clone, Debug)]
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Credentials {
#[bincode(with_serde)]
pub id: uuid::Uuid,
pub username: String,
pub access_token: String,
pub refresh_token: String,
#[bincode(with_serde)]
pub expires: DateTime<Utc>,
_ctor_scope: std::marker::PhantomData<()>,
}

View File

@@ -1,11 +1,7 @@
//! Downloader for Minecraft data
use crate::{
event::{
emit::{emit_loading, init_loading, loading_try_for_each_concurrent},
LoadingBarId, LoadingBarType,
},
process::Profile,
event::emit::{emit_loading, loading_try_for_each_concurrent},
state::State,
util::{fetch::*, platform::OsExt},
};
@@ -19,26 +15,17 @@ use daedalus::{
};
use futures::prelude::*;
use tokio::{fs, sync::OnceCell};
use uuid::Uuid;
#[tracing::instrument(skip_all)]
pub async fn download_minecraft(
st: &State,
version: &GameVersionInfo,
profile: &Profile,
loading_bar: Uuid,
) -> crate::Result<()> {
log::info!("Downloading Minecraft version {}", version.id);
let assets_index = download_assets_index(st, version).await?;
let loading_bar = init_loading(
LoadingBarType::MinecraftDownload {
// If we are downloading minecraft for a profile, provide its name and uuid
profile_name: profile.metadata.name.clone(),
profile_uuid: profile.uuid,
},
100.0,
"Downloading Minecraft...",
)
.await?;
tokio::try_join! {
download_client(st, version, Some(&loading_bar)),
download_assets(st, version.assets == "legacy", &assets_index, Some(&loading_bar)),
@@ -54,6 +41,7 @@ pub async fn download_version_info(
st: &State,
version: &GameVersion,
loader: Option<&LoaderVersion>,
force: Option<bool>,
) -> crate::Result<GameVersionInfo> {
let version_id = loader
.map_or(version.id.clone(), |it| format!("{}-{}", version.id, it.id));
@@ -63,7 +51,7 @@ pub async fn download_version_info(
.version_dir(&version_id)
.join(format!("{version_id}.json"));
let res = if path.exists() {
let res = if path.exists() && !force.unwrap_or(false) {
fs::read(path)
.err_into::<crate::Error>()
.await
@@ -90,7 +78,7 @@ pub async fn download_version_info(
pub async fn download_client(
st: &State,
version_info: &GameVersionInfo,
loading_bar: Option<&LoadingBarId>,
loading_bar: Option<&Uuid>,
) -> crate::Result<()> {
let version = &version_info.id;
log::debug!("Locating client for version {version}");
@@ -158,7 +146,7 @@ pub async fn download_assets(
st: &State,
with_legacy: bool,
index: &AssetsIndex,
loading_bar: Option<&LoadingBarId>,
loading_bar: Option<&Uuid>,
) -> crate::Result<()> {
log::debug!("Loading assets");
let num_futs = index.objects.len();
@@ -219,7 +207,7 @@ pub async fn download_libraries(
st: &State,
libraries: &[Library],
version: &str,
loading_bar: Option<&LoadingBarId>,
loading_bar: Option<&Uuid>,
) -> crate::Result<()> {
log::debug!("Loading libraries");

View File

@@ -1,4 +1,6 @@
//! Logic for launching Minecraft
use crate::event::emit::{emit_loading, init_or_edit_loading};
use crate::event::LoadingBarType;
use crate::{
process,
state::{self as st, MinecraftChild},
@@ -8,6 +10,7 @@ use dunce::canonicalize;
use st::Profile;
use std::{path::Path, process::Stdio, sync::Arc};
use tokio::process::Command;
use uuid::Uuid;
mod args;
@@ -48,55 +51,60 @@ macro_rules! processor_rules {
}
}
#[allow(clippy::too_many_arguments)]
#[tracing::instrument(skip_all, fields(path = ?instance_path))]
pub async fn launch_minecraft(
game_version: &str,
loader_version: &Option<d::modded::LoaderVersion>,
instance_path: &Path,
java_install: &Path,
java_args: &[String],
env_args: &[(String, String)],
wrapper: &Option<String>,
memory: &st::MemorySettings,
resolution: &st::WindowSize,
credentials: &auth::Credentials,
post_exit_hook: Option<Command>,
profile: &Profile, // optional ref to Profile for event tracking
) -> crate::Result<Arc<tokio::sync::RwLock<MinecraftChild>>> {
pub async fn install_minecraft(
profile: &Profile,
existing_loading_bar: Option<Uuid>,
) -> crate::Result<()> {
let state = st::State::get().await?;
let instance_path = &canonicalize(instance_path)?;
let instance_path = &canonicalize(&profile.path)?;
let metadata = state.metadata.read().await;
let version = state
.metadata
let version = metadata
.minecraft
.versions
.iter()
.find(|it| it.id == game_version)
.find(|it| it.id == profile.metadata.game_version)
.ok_or(crate::ErrorKind::LauncherError(format!(
"Invalid game version: {game_version}"
"Invalid game version: {}",
profile.metadata.game_version
)))?;
let version_jar =
loader_version.as_ref().map_or(version.id.clone(), |it| {
let version_jar = profile
.metadata
.loader_version
.as_ref()
.map_or(version.id.clone(), |it| {
format!("{}-{}", version.id.clone(), it.id.clone())
});
let mut version_info = download::download_version_info(
&state,
version,
loader_version.as_ref(),
profile.metadata.loader_version.as_ref(),
None,
)
.await?;
let loading_bar = init_or_edit_loading(
existing_loading_bar,
LoadingBarType::MinecraftDownload {
// If we are downloading minecraft for a profile, provide its name and uuid
profile_name: profile.metadata.name.clone(),
profile_uuid: profile.uuid,
},
100.0,
"Downloading Minecraft...",
)
.await?;
download::download_minecraft(&state, &version_info, loading_bar).await?;
st::State::sync().await?;
let client_path = state
.directories
.version_dir(&version_jar)
.join(format!("{version_jar}.jar"));
download::download_minecraft(&state, &version_info, profile).await?;
st::State::sync().await?;
if let Some(processors) = &version_info.processors {
if let Some(ref mut data) = version_info.data {
processor_rules! {
@@ -108,7 +116,7 @@ pub async fn launch_minecraft(
client => client_path.to_string_lossy(),
server => "";
"MINECRAFT_VERSION":
client => game_version,
client => profile.metadata.game_version.clone(),
server => "";
"ROOT":
client => instance_path.to_string_lossy(),
@@ -118,7 +126,21 @@ pub async fn launch_minecraft(
server => "";
}
for processor in processors {
emit_loading(&loading_bar, 0.0, Some("Running forge processors"))
.await?;
let total_length = processors.len();
for (index, processor) in processors.iter().enumerate() {
emit_loading(
&loading_bar,
index as f64 / total_length as f64,
Some(&format!(
"Running forge processor {}/{}",
index, total_length
)),
)
.await?;
if let Some(sides) = &processor.sides {
if !sides.contains(&String::from("client")) {
continue;
@@ -173,6 +195,68 @@ pub async fn launch_minecraft(
}
}
crate::api::profile::edit(&profile.path, |prof| {
prof.installed = true;
async { Ok(()) }
})
.await?;
crate::api::profile::sync(&profile.path).await?;
Ok(())
}
#[allow(clippy::too_many_arguments)]
pub async fn launch_minecraft(
java_install: &Path,
java_args: &[String],
env_args: &[(String, String)],
wrapper: &Option<String>,
memory: &st::MemorySettings,
resolution: &st::WindowSize,
credentials: &auth::Credentials,
post_exit_hook: Option<Command>,
profile: &Profile,
) -> crate::Result<Arc<tokio::sync::RwLock<MinecraftChild>>> {
if !profile.installed {
install_minecraft(profile, None).await?;
}
let state = st::State::get().await?;
let metadata = state.metadata.read().await;
let instance_path = &canonicalize(&profile.path)?;
let version = metadata
.minecraft
.versions
.iter()
.find(|it| it.id == profile.metadata.game_version)
.ok_or(crate::ErrorKind::LauncherError(format!(
"Invalid game version: {}",
profile.metadata.game_version
)))?;
let version_jar = profile
.metadata
.loader_version
.as_ref()
.map_or(version.id.clone(), |it| {
format!("{}-{}", version.id.clone(), it.id.clone())
});
let version_info = download::download_version_info(
&state,
version,
profile.metadata.loader_version.as_ref(),
None,
)
.await?;
let client_path = state
.directories
.version_dir(&version_jar)
.join(format!("{version_jar}.jar"));
let args = version_info.arguments.clone().unwrap_or_default();
let mut command = match wrapper {
Some(hook) => {