feat(ui): JVM arguments setting
This commit is contained in:
parent
5f5fa4141a
commit
6344d2e985
3 changed files with 97 additions and 4 deletions
|
|
@ -79,6 +79,7 @@ impl Component for ClusterSettings {
|
|||
}
|
||||
.into_element(),
|
||||
)
|
||||
.child(text_row(cluster_id, TextField::JvmArgs, &profile, &global))
|
||||
.child(section_header("GAME"))
|
||||
.child(
|
||||
ToggleRow {
|
||||
|
|
@ -420,6 +421,7 @@ impl Component for ResolutionRow {
|
|||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
enum TextField {
|
||||
JvmArgs,
|
||||
Pre,
|
||||
Wrapper,
|
||||
Post,
|
||||
|
|
@ -428,6 +430,12 @@ enum TextField {
|
|||
impl TextField {
|
||||
fn meta(self) -> (IconType, &'static str, &'static str, &'static str) {
|
||||
match self {
|
||||
Self::JvmArgs => (
|
||||
IconType::Terminal,
|
||||
"JVM Arguments",
|
||||
"Extra arguments passed to Java. Separate them with spaces; quote values containing spaces.",
|
||||
"-XX:+UseG1GC",
|
||||
),
|
||||
Self::Pre => (
|
||||
IconType::FilePlus02,
|
||||
"Pre-Launch Command",
|
||||
|
|
@ -451,6 +459,7 @@ impl TextField {
|
|||
|
||||
fn value(self, profile: &GameSettingsProfile) -> Option<String> {
|
||||
match self {
|
||||
Self::JvmArgs => profile.launch_args.clone(),
|
||||
Self::Pre => profile.hook_pre.clone(),
|
||||
Self::Wrapper => profile.hook_wrapper.clone(),
|
||||
Self::Post => profile.hook_post.clone(),
|
||||
|
|
@ -460,6 +469,7 @@ impl TextField {
|
|||
fn patch(self, value: Patch<String>) -> ProfileUpdate {
|
||||
let mut u = ProfileUpdate::default();
|
||||
match self {
|
||||
Self::JvmArgs => u.launch_args = value,
|
||||
Self::Pre => u.hook_pre = value,
|
||||
Self::Wrapper => u.hook_wrapper = value,
|
||||
Self::Post => u.hook_post = value,
|
||||
|
|
|
|||
|
|
@ -38,6 +38,10 @@ impl Component for SettingsMinecraft {
|
|||
let v = profile.mem_max.map(|m| m.to_string()).unwrap_or_default();
|
||||
move || v
|
||||
});
|
||||
let jvm_args = use_state({
|
||||
let v = profile.launch_args.clone().unwrap_or_default();
|
||||
move || v
|
||||
});
|
||||
let pre_launch_command = use_state({
|
||||
let v = profile.hook_pre.clone().unwrap_or_default();
|
||||
move || v
|
||||
|
|
@ -58,6 +62,7 @@ impl Component for SettingsMinecraft {
|
|||
&width.read(),
|
||||
&height.read(),
|
||||
&memory.read(),
|
||||
&jvm_args.read(),
|
||||
&pre_launch_command.read(),
|
||||
&wrapper_command.read(),
|
||||
&post_exit_command.read(),
|
||||
|
|
@ -89,6 +94,14 @@ impl Component for SettingsMinecraft {
|
|||
"The amount of memory in megabytes allocated for the game.",
|
||||
memory_field(memory),
|
||||
))
|
||||
.child(settings_row(
|
||||
IconType::Terminal,
|
||||
"JVM Arguments",
|
||||
"Extra arguments passed to Java. Separate them with spaces; quote values containing spaces.",
|
||||
TextInput::new(jvm_args)
|
||||
.placeholder("-XX:+UseG1GC")
|
||||
.width(Size::px(220.)),
|
||||
))
|
||||
.child(section_header("PROCESS"))
|
||||
.child(settings_row(
|
||||
IconType::FilePlus02,
|
||||
|
|
@ -118,11 +131,13 @@ impl Component for SettingsMinecraft {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn build_update(
|
||||
fullscreen: bool,
|
||||
width: &str,
|
||||
height: &str,
|
||||
memory: &str,
|
||||
jvm_args: &str,
|
||||
pre: &str,
|
||||
wrapper: &str,
|
||||
post: &str,
|
||||
|
|
@ -144,6 +159,7 @@ fn build_update(
|
|||
force_fullscreen: Patch::Set(fullscreen),
|
||||
resolution,
|
||||
mem_max,
|
||||
launch_args: command_patch(jvm_args),
|
||||
hook_pre: command_patch(pre),
|
||||
hook_wrapper: command_patch(wrapper),
|
||||
hook_post: command_patch(post),
|
||||
|
|
|
|||
|
|
@ -52,14 +52,49 @@ pub fn java_arguments(
|
|||
}
|
||||
|
||||
parsed.push(format!("-Xmx{mem_max}M"));
|
||||
|
||||
if !custom_args.is_empty() {
|
||||
parsed.push(custom_args);
|
||||
}
|
||||
parsed.extend(split_custom_args(&custom_args));
|
||||
|
||||
Ok(parsed)
|
||||
}
|
||||
|
||||
/// Splits a user-entered JVM argument string into individual arguments.
|
||||
///
|
||||
/// Whitespace-separated, with double quotes for values that contain spaces
|
||||
/// (`-Dfoo="a b"`), which is what people expect from every other launcher.
|
||||
/// Pushing the whole string as one argv entry, as this used to, means the JVM
|
||||
/// sees a single unrecognised option as soon as there is more than one.
|
||||
fn split_custom_args(raw: &str) -> Vec<String> {
|
||||
let mut args = Vec::new();
|
||||
let mut current = String::new();
|
||||
let mut quoted = false;
|
||||
let mut started = false;
|
||||
|
||||
for ch in raw.chars() {
|
||||
match ch {
|
||||
'"' => {
|
||||
quoted = !quoted;
|
||||
started = true;
|
||||
}
|
||||
c if c.is_whitespace() && !quoted => {
|
||||
if started {
|
||||
args.push(std::mem::take(&mut current));
|
||||
started = false;
|
||||
}
|
||||
}
|
||||
c => {
|
||||
current.push(c);
|
||||
started = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if started {
|
||||
args.push(current);
|
||||
}
|
||||
|
||||
args
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn minecraft_arguments(
|
||||
version_updated: bool,
|
||||
|
|
@ -415,3 +450,35 @@ where
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::split_custom_args;
|
||||
|
||||
#[test]
|
||||
fn blank_input_contributes_nothing() {
|
||||
assert!(split_custom_args("").is_empty());
|
||||
assert!(split_custom_args(" \t ").is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn each_flag_becomes_its_own_argument() {
|
||||
assert_eq!(
|
||||
split_custom_args("-XX:+UseG1GC -Xms2G"),
|
||||
vec!["-XX:+UseG1GC", "-Xms2G"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn quotes_hold_a_value_with_spaces_together() {
|
||||
assert_eq!(
|
||||
split_custom_args(r#"-Dname="My Server" -Xss1M"#),
|
||||
vec!["-Dname=My Server", "-Xss1M"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_empty_quoted_value_survives() {
|
||||
assert_eq!(split_custom_args(r#"-Dempty="""#), vec!["-Dempty="]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue