You've already forked AstralRinth
forked from didirus/AstralRinth
Add method of storing launcher data, fix forge 1.17+, add launcher settings
This commit is contained in:
@@ -9,6 +9,13 @@ use std::io::{BufRead, BufReader};
|
||||
use std::path::Path;
|
||||
use uuid::Uuid;
|
||||
|
||||
fn get_cp_separator() -> &'static str {
|
||||
match super::download::get_os() {
|
||||
Os::Osx | Os::Linux | Os::Unknown => ":",
|
||||
Os::Windows => ";",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_class_paths(
|
||||
libraries_path: &Path,
|
||||
libraries: &[Library],
|
||||
@@ -42,10 +49,7 @@ pub fn get_class_paths(
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
Ok(class_paths.join(match super::download::get_os() {
|
||||
Os::Osx | Os::Linux | Os::Unknown => ":",
|
||||
Os::Windows => ";",
|
||||
}))
|
||||
Ok(class_paths.join(get_cp_separator()))
|
||||
}
|
||||
|
||||
pub fn get_class_paths_jar<T: AsRef<str>>(
|
||||
@@ -90,13 +94,23 @@ pub fn get_lib_path<T: AsRef<str>>(libraries_path: &Path, lib: T) -> Result<Stri
|
||||
pub fn get_jvm_arguments(
|
||||
arguments: Option<&[Argument]>,
|
||||
natives_path: &Path,
|
||||
libraries_path: &Path,
|
||||
class_paths: &str,
|
||||
version_name: &str,
|
||||
memory: i32,
|
||||
custom_args: Vec<String>,
|
||||
) -> Result<Vec<String>, LauncherError> {
|
||||
let mut parsed_arguments = Vec::new();
|
||||
|
||||
if let Some(args) = arguments {
|
||||
parse_arguments(args, &mut parsed_arguments, |arg| {
|
||||
parse_jvm_argument(arg, natives_path, class_paths)
|
||||
parse_jvm_argument(
|
||||
arg,
|
||||
natives_path,
|
||||
libraries_path,
|
||||
class_paths,
|
||||
version_name,
|
||||
)
|
||||
})?;
|
||||
} else {
|
||||
parsed_arguments.push(format!(
|
||||
@@ -113,13 +127,22 @@ pub fn get_jvm_arguments(
|
||||
parsed_arguments.push(class_paths.to_string());
|
||||
}
|
||||
|
||||
parsed_arguments.push(format!("-Xmx{}M", memory));
|
||||
for arg in custom_args {
|
||||
if !arg.is_empty() {
|
||||
parsed_arguments.push(arg);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(parsed_arguments)
|
||||
}
|
||||
|
||||
fn parse_jvm_argument(
|
||||
argument: &str,
|
||||
natives_path: &Path,
|
||||
libraries_path: &Path,
|
||||
class_paths: &str,
|
||||
version_name: &str,
|
||||
) -> Result<String, LauncherError> {
|
||||
let mut argument = argument.to_string();
|
||||
argument.retain(|c| !c.is_whitespace());
|
||||
@@ -136,8 +159,22 @@ fn parse_jvm_argument(
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
)
|
||||
.replace(
|
||||
"${library_directory}",
|
||||
&*crate::util::absolute_path(libraries_path)
|
||||
.map_err(|_| {
|
||||
LauncherError::InvalidInput(format!(
|
||||
"Specified libraries path {} does not exist",
|
||||
libraries_path.to_string_lossy()
|
||||
))
|
||||
})?
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
)
|
||||
.replace("${classpath_separator}", get_cp_separator())
|
||||
.replace("${launcher_name}", "theseus")
|
||||
.replace("${launcher_version}", env!("CARGO_PKG_VERSION"))
|
||||
.replace("${version_name}", version_name)
|
||||
.replace("${classpath}", class_paths))
|
||||
}
|
||||
|
||||
@@ -151,6 +188,7 @@ pub fn get_minecraft_arguments(
|
||||
game_directory: &Path,
|
||||
assets_directory: &Path,
|
||||
version_type: &VersionType,
|
||||
resolution: (i32, i32),
|
||||
) -> Result<Vec<String>, LauncherError> {
|
||||
if let Some(arguments) = arguments {
|
||||
let mut parsed_arguments = Vec::new();
|
||||
@@ -166,6 +204,7 @@ pub fn get_minecraft_arguments(
|
||||
game_directory,
|
||||
assets_directory,
|
||||
version_type,
|
||||
resolution,
|
||||
)
|
||||
})?;
|
||||
|
||||
@@ -181,6 +220,7 @@ pub fn get_minecraft_arguments(
|
||||
game_directory,
|
||||
assets_directory,
|
||||
version_type,
|
||||
resolution,
|
||||
)?
|
||||
.split(' ')
|
||||
.into_iter()
|
||||
@@ -202,6 +242,7 @@ fn parse_minecraft_argument(
|
||||
game_directory: &Path,
|
||||
assets_directory: &Path,
|
||||
version_type: &VersionType,
|
||||
resolution: (i32, i32),
|
||||
) -> Result<String, LauncherError> {
|
||||
Ok(argument
|
||||
.replace("${auth_access_token}", access_token)
|
||||
@@ -248,7 +289,9 @@ fn parse_minecraft_argument(
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
)
|
||||
.replace("${version_type}", version_type.as_str()))
|
||||
.replace("${version_type}", version_type.as_str())
|
||||
.replace("${resolution_width}", &*resolution.0.to_string())
|
||||
.replace("${resolution_height}", &*resolution.1.to_string()))
|
||||
}
|
||||
|
||||
fn parse_arguments<F>(
|
||||
|
||||
@@ -52,7 +52,10 @@ pub enum LauncherError {
|
||||
DaedalusError(#[from] daedalus::Error),
|
||||
|
||||
#[error("Error while reading metadata: {0}")]
|
||||
MetaError(#[from] crate::meta::MetaError),
|
||||
MetaError(#[from] crate::data::DataError),
|
||||
|
||||
#[error("Java error: {0}")]
|
||||
JavaError(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
|
||||
@@ -75,76 +78,92 @@ pub async fn launch_minecraft(
|
||||
root_dir: &Path,
|
||||
credentials: &Credentials,
|
||||
) -> Result<(), LauncherError> {
|
||||
let metadata = crate::meta::Metadata::get().await?;
|
||||
let metadata = crate::data::Metadata::get().await?;
|
||||
let settings = crate::data::Settings::get().await?;
|
||||
|
||||
let versions_path = crate::util::absolute_path(root_dir.join("versions"))?;
|
||||
let libraries_path = crate::util::absolute_path(root_dir.join("libraries"))?;
|
||||
let assets_path = crate::util::absolute_path(root_dir.join("assets"))?;
|
||||
let legacy_assets_path = crate::util::absolute_path(root_dir.join("resources"))?;
|
||||
|
||||
let version = metadata
|
||||
.minecraft
|
||||
.versions
|
||||
.iter()
|
||||
.find(|x| x.id == version_name)
|
||||
.ok_or_else(|| {
|
||||
LauncherError::InvalidInput(format!("Version {} does not exist", version_name))
|
||||
})?;
|
||||
|
||||
let loader_version = match mod_loader.unwrap_or_default() {
|
||||
ModLoader::Vanilla => None,
|
||||
ModLoader::Forge | ModLoader::Fabric => {
|
||||
let loaders = if mod_loader.unwrap_or_default() == ModLoader::Forge {
|
||||
&metadata
|
||||
.forge
|
||||
.game_versions
|
||||
.iter()
|
||||
.find(|x| x.id == version_name)
|
||||
.ok_or_else(|| {
|
||||
LauncherError::InvalidInput(format!(
|
||||
"Version {} for mod loader Forge does not exist",
|
||||
version_name
|
||||
))
|
||||
})?
|
||||
.loaders
|
||||
} else {
|
||||
&metadata
|
||||
.fabric
|
||||
.game_versions
|
||||
.iter()
|
||||
.find(|x| x.id == version_name)
|
||||
.ok_or_else(|| {
|
||||
LauncherError::InvalidInput(format!(
|
||||
"Version {} for mod loader Fabric does not exist",
|
||||
version_name
|
||||
))
|
||||
})?
|
||||
.loaders
|
||||
};
|
||||
|
||||
let loader = if let Some(version) = loaders.iter().find(|x| x.stable) {
|
||||
Some(version.clone())
|
||||
} else {
|
||||
loaders.first().cloned()
|
||||
};
|
||||
|
||||
Some(loader.ok_or_else(|| {
|
||||
LauncherError::InvalidInput(format!(
|
||||
"No mod loader version found for version {}",
|
||||
version_name
|
||||
))
|
||||
})?)
|
||||
}
|
||||
};
|
||||
|
||||
let version_jar_name = if let Some(loader) = &loader_version {
|
||||
loader.id.clone()
|
||||
} else {
|
||||
version.id.clone()
|
||||
};
|
||||
|
||||
let mut version = download::download_version_info(
|
||||
&versions_path,
|
||||
metadata
|
||||
.minecraft
|
||||
.versions
|
||||
.iter()
|
||||
.find(|x| x.id == version_name)
|
||||
.ok_or_else(|| {
|
||||
LauncherError::InvalidInput(format!("Version {} does not exist", version_name))
|
||||
})?,
|
||||
match mod_loader.unwrap_or_default() {
|
||||
ModLoader::Vanilla => None,
|
||||
ModLoader::Forge | ModLoader::Fabric => {
|
||||
let loaders = if mod_loader.unwrap_or_default() == ModLoader::Forge {
|
||||
&metadata
|
||||
.forge
|
||||
.game_versions
|
||||
.iter()
|
||||
.find(|x| x.id == version_name)
|
||||
.ok_or_else(|| {
|
||||
LauncherError::InvalidInput(format!(
|
||||
"Version {} for mod loader Forge does not exist",
|
||||
version_name
|
||||
))
|
||||
})?
|
||||
.loaders
|
||||
} else {
|
||||
&metadata
|
||||
.fabric
|
||||
.game_versions
|
||||
.iter()
|
||||
.find(|x| x.id == version_name)
|
||||
.ok_or_else(|| {
|
||||
LauncherError::InvalidInput(format!(
|
||||
"Version {} for mod loader Fabric does not exist",
|
||||
version_name
|
||||
))
|
||||
})?
|
||||
.loaders
|
||||
};
|
||||
|
||||
let loader = if let Some(version) =
|
||||
loaders.get(&daedalus::modded::LoaderType::Stable)
|
||||
{
|
||||
Some(version.clone())
|
||||
} else if let Some(version) = loaders.get(&daedalus::modded::LoaderType::Latest) {
|
||||
Some(version.clone())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Some(loader.ok_or_else(|| {
|
||||
LauncherError::InvalidInput(format!(
|
||||
"No mod loader version found for version {}",
|
||||
version_name
|
||||
))
|
||||
})?)
|
||||
}
|
||||
}
|
||||
.as_ref(),
|
||||
version,
|
||||
loader_version.as_ref(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let java_path = if let Some(java) = &version.java_version {
|
||||
if java.major_version == 17 || java.major_version == 16 {
|
||||
settings.java_17_path.as_deref().ok_or_else(|| LauncherError::JavaError("Please install Java 17 or select your Java 17 installation settings before launching this version!".to_string()))?
|
||||
} else {
|
||||
&settings.java_8_path.as_deref().ok_or_else(|| LauncherError::JavaError("Please install Java 8 or select your Java 8 installation settings before launching this version!".to_string()))?
|
||||
}
|
||||
} else {
|
||||
&settings.java_8_path.as_deref().ok_or_else(|| LauncherError::JavaError("Please install Java 8 or select your Java 8 installation settings before launching this version!".to_string()))?
|
||||
};
|
||||
|
||||
let client_path = crate::util::absolute_path(
|
||||
root_dir
|
||||
.join("versions")
|
||||
@@ -249,11 +268,30 @@ pub async fn launch_minecraft(
|
||||
|
||||
let arguments = version.arguments.unwrap_or_default();
|
||||
|
||||
let mut child = Command::new("java")
|
||||
let mut command = Command::new(if let Some(wrapper) = &settings.wrapper_command {
|
||||
wrapper.clone()
|
||||
} else {
|
||||
java_path.to_string()
|
||||
});
|
||||
|
||||
if settings.wrapper_command.is_some() {
|
||||
command.arg(java_path);
|
||||
}
|
||||
|
||||
command
|
||||
.args(args::get_jvm_arguments(
|
||||
arguments.get(&ArgumentType::Jvm).map(|x| x.as_slice()),
|
||||
&natives_path,
|
||||
&libraries_path,
|
||||
&*args::get_class_paths(&libraries_path, version.libraries.as_slice(), &client_path)?,
|
||||
&version_jar_name,
|
||||
settings.memory,
|
||||
settings
|
||||
.custom_java_args
|
||||
.split(" ")
|
||||
.into_iter()
|
||||
.map(|x| x.to_string())
|
||||
.collect(),
|
||||
)?)
|
||||
.arg(version.main_class)
|
||||
.args(args::get_minecraft_arguments(
|
||||
@@ -265,15 +303,16 @@ pub async fn launch_minecraft(
|
||||
root_dir,
|
||||
&assets_path,
|
||||
&version.type_,
|
||||
settings.game_resolution,
|
||||
)?)
|
||||
.current_dir(root_dir)
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit())
|
||||
.spawn()
|
||||
.map_err(|err| LauncherError::ProcessError {
|
||||
inner: err,
|
||||
process: "minecraft".to_string(),
|
||||
})?;
|
||||
.stderr(Stdio::inherit());
|
||||
|
||||
let mut child = command.spawn().map_err(|err| LauncherError::ProcessError {
|
||||
inner: err,
|
||||
process: "minecraft".to_string(),
|
||||
})?;
|
||||
|
||||
child.wait().map_err(|err| LauncherError::ProcessError {
|
||||
inner: err,
|
||||
|
||||
@@ -9,8 +9,10 @@ pub fn parse_rules(rules: &[Rule]) -> bool {
|
||||
pub fn parse_rule(rule: &Rule) -> bool {
|
||||
let result = if let Some(os) = &rule.os {
|
||||
parse_os_rule(os)
|
||||
} else if let Some(features) = &rule.features {
|
||||
features.has_demo_resolution.unwrap_or(false)
|
||||
} else {
|
||||
rule.features.is_none()
|
||||
true
|
||||
};
|
||||
|
||||
match rule.action {
|
||||
|
||||
Reference in New Issue
Block a user