Merge commit '74cf3f076eff43755bb4bef62f1c1bb3fc0e6c2a' into feature-clean

This commit is contained in:
2025-05-26 17:59:09 +03:00
497 changed files with 15033 additions and 9421 deletions

View File

@@ -4,18 +4,21 @@ use crate::event::emit::{emit_loading, init_or_edit_loading};
use crate::event::{LoadingBarId, LoadingBarType};
use crate::launcher::download::download_log_config;
use crate::launcher::io::IOError;
use crate::profile::QuickPlayType;
use crate::state::{
Credentials, JavaVersion, ProcessMetadata, ProfileInstallStage,
};
use crate::util::io;
use crate::{process, state as st, State};
use crate::{State, process, state as st};
use chrono::Utc;
use daedalus as d;
use daedalus::minecraft::{LoggingSide, RuleAction, VersionInfo};
use daedalus::modded::LoaderVersion;
use rand::seq::SliceRandom;
use rand::seq::SliceRandom; // AstralRinth
use serde::Deserialize;
use st::Profile;
use std::collections::HashMap;
use std::path::PathBuf;
use tokio::process::Command;
mod args;
@@ -31,11 +34,14 @@ use crate::state::ACTIVE_STATE;
pub fn parse_rules(
rules: &[d::minecraft::Rule],
java_version: &str,
quick_play_type: &QuickPlayType,
minecraft_updated: bool,
) -> bool {
let mut x = rules
.iter()
.map(|x| parse_rule(x, java_version, minecraft_updated))
.map(|x| {
parse_rule(x, java_version, quick_play_type, minecraft_updated)
})
.collect::<Vec<Option<bool>>>();
if rules
@@ -56,26 +62,30 @@ pub fn parse_rules(
pub fn parse_rule(
rule: &d::minecraft::Rule,
java_version: &str,
quick_play_type: &QuickPlayType,
minecraft_updated: bool,
) -> Option<bool> {
use d::minecraft::{Rule, RuleAction};
let res = match rule {
Rule {
os: Some(ref os), ..
} => {
Rule { os: Some(os), .. } => {
crate::util::platform::os_rule(os, java_version, minecraft_updated)
}
Rule {
features: Some(ref features),
features: Some(features),
..
} => {
!features.is_demo_user.unwrap_or(true)
|| features.has_custom_resolution.unwrap_or(false)
|| !features.has_quick_plays_support.unwrap_or(true)
|| !features.is_quick_play_multiplayer.unwrap_or(true)
|| (features.is_quick_play_singleplayer.unwrap_or(false)
&& matches!(
quick_play_type,
QuickPlayType::Singleplayer(_)
))
|| (features.is_quick_play_multiplayer.unwrap_or(false)
&& matches!(quick_play_type, QuickPlayType::Server(..)))
|| !features.is_quick_play_realms.unwrap_or(true)
|| !features.is_quick_play_singleplayer.unwrap_or(true)
}
_ => return Some(true),
};
@@ -288,8 +298,7 @@ pub async fn install_minecraft(
.await?
.ok_or_else(|| {
crate::ErrorKind::LauncherError(format!(
"Java path invalid or non-functional: {:?}",
java_version
"Java path invalid or non-functional: {java_version:?}"
))
})?;
@@ -308,12 +317,11 @@ pub async fn install_minecraft(
)
.await?;
let client_path = state
.directories
.version_dir(&version_jar)
.join(format!("{version_jar}.jar"));
if let Some(processors) = &version_info.processors {
let client_path = state
.directories
.version_dir(&version_jar)
.join(format!("{version_jar}.jar"));
let libraries_dir = state.directories.libraries_dir();
if let Some(ref mut data) = version_info.data {
@@ -398,16 +406,18 @@ pub async fn install_minecraft(
&loading_bar,
30.0 / total_length as f64,
Some(&format!(
"Running forge processor {}/{}",
index, total_length
"Running forge processor {index}/{total_length}"
)),
)?;
}
}
}
let protocol_version = read_protocol_version_from_jar(client_path).await?;
crate::api::profile::edit(&profile.path, |prof| {
prof.install_stage = ProfileInstallStage::Installed;
prof.protocol_version = protocol_version;
async { Ok(()) }
})
@@ -417,6 +427,34 @@ pub async fn install_minecraft(
Ok(())
}
pub async fn read_protocol_version_from_jar(
path: PathBuf,
) -> crate::Result<Option<i32>> {
let zip = async_zip::tokio::read::fs::ZipFileReader::new(path).await?;
let Some(entry_index) = zip
.file()
.entries()
.iter()
.position(|x| matches!(x.filename().as_str(), Ok("version.json")))
else {
return Ok(None);
};
#[derive(Deserialize, Debug)]
struct VersionData {
protocol_version: Option<i32>,
}
let mut data = vec![];
zip.reader_with_entry(entry_index)
.await?
.read_to_end_checked(&mut data)
.await?;
let data: VersionData = serde_json::from_slice(&data)?;
Ok(data.protocol_version)
}
#[tracing::instrument(skip_all)]
#[allow(clippy::too_many_arguments)]
pub async fn launch_minecraft(
@@ -429,6 +467,7 @@ pub async fn launch_minecraft(
credentials: &Credentials,
post_exit_hook: Option<String>,
profile: &Profile,
quick_play_type: &QuickPlayType,
) -> crate::Result<ProcessMetadata> {
if profile.install_stage == ProfileInstallStage::PackInstalling
|| profile.install_stage == ProfileInstallStage::MinecraftInstalling
@@ -584,6 +623,7 @@ pub async fn launch_minecraft(
*memory,
Vec::from(java_args),
&java_version.architecture,
quick_play_type,
version_info
.logging
.as_ref()
@@ -606,6 +646,7 @@ pub async fn launch_minecraft(
&version.type_,
*resolution,
&java_version.architecture,
quick_play_type,
)?
.into_iter()
.collect::<Vec<_>>(),
@@ -637,10 +678,10 @@ pub async fn launch_minecraft(
// check if the regex exists in the file
if !re.is_match(&options_string) {
// The key was not found in the file, so append it
options_string.push_str(&format!("\n{}:{}", key, value));
options_string.push_str(&format!("\n{key}:{value}"));
} else {
let replaced_string = re
.replace_all(&options_string, &format!("{}:{}", key, value))
.replace_all(&options_string, &format!("{key}:{value}"))
.to_string();
options_string = replaced_string;
}
@@ -658,12 +699,10 @@ pub async fn launch_minecraft(
let mut censor_strings = HashMap::new();
let username = whoami::username();
censor_strings
.insert(format!("/{username}/"), "/{COMPUTER_USERNAME}/".to_string());
censor_strings.insert(
format!("/{}/", username),
"/{COMPUTER_USERNAME}/".to_string(),
);
censor_strings.insert(
format!("\\{}\\", username),
format!("\\{username}\\"),
"\\{COMPUTER_USERNAME}\\".to_string(),
);
censor_strings.insert(
@@ -712,6 +751,12 @@ pub async fn launch_minecraft(
// This also spawns the process and prepares the subsequent processes
state
.process_manager
.insert_new_process(&profile.path, command, post_exit_hook)
.insert_new_process(
&profile.path,
command,
post_exit_hook,
state.directories.profile_logs_dir(&profile.path),
version_info.logging.is_some(),
)
.await
}