diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java index 06bff89ec..cd1a01de3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -48,11 +48,13 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.*; import java.util.logging.Level; +import java.util.stream.Collectors; import java.util.stream.Stream; import static org.jackhuang.hmcl.setting.ConfigHolder.config; import static org.jackhuang.hmcl.ui.FXUtils.newImage; import static org.jackhuang.hmcl.util.Logging.LOG; +import static org.jackhuang.hmcl.util.Pair.pair; public class HMCLGameRepository extends DefaultGameRepository { private final Profile profile; @@ -335,6 +337,16 @@ public class HMCLGameRepository extends DefaultGameRepository { ) / 1024 / 1024)) .setMinMemory(vs.getMinMemory()) .setMetaspace(Lang.toIntOrNull(vs.getPermSize())) + .setEnvironmentVariables( + Lang.mapOf(StringUtils.tokenize(vs.getEnvironmentVariables()) + .stream() + .map(it -> { + int idx = it.indexOf('='); + return idx >= 0 ? pair(it.substring(0, idx), it.substring(idx + 1)) : pair(it, ""); + }) + .collect(Collectors.toList()) + ) + ) .setWidth(vs.getWidth()) .setHeight(vs.getHeight()) .setFullscreen(vs.isFullscreen()) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java index bd20b487f..f1ca875ee 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java @@ -341,6 +341,20 @@ public final class VersionSetting implements Cloneable { minecraftArgsProperty.set(minecraftArgs); } + private final StringProperty environmentVariablesProperty = new SimpleStringProperty(this, "environmentVariables", ""); + + public StringProperty environmentVariablesProperty() { + return environmentVariablesProperty; + } + + public String getEnvironmentVariables() { + return environmentVariablesProperty.get(); + } + + public void setEnvironmentVariables(String env) { + environmentVariablesProperty.set(env); + } + private final BooleanProperty noJVMArgsProperty = new SimpleBooleanProperty(this, "noJVMArgs", false); public BooleanProperty noJVMArgsProperty() { @@ -483,7 +497,6 @@ public final class VersionSetting implements Cloneable { widthProperty.set(width); } - private final IntegerProperty heightProperty = new SimpleIntegerProperty(this, "height", 480); public IntegerProperty heightProperty() { @@ -693,6 +706,7 @@ public final class VersionSetting implements Cloneable { postExitCommand.addListener(listener); javaArgsProperty.addListener(listener); minecraftArgsProperty.addListener(listener); + environmentVariablesProperty.addListener(listener); noJVMArgsProperty.addListener(listener); notCheckGameProperty.addListener(listener); notCheckJVMProperty.addListener(listener); @@ -731,6 +745,7 @@ public final class VersionSetting implements Cloneable { versionSetting.setPostExitCommand(getPostExitCommand()); versionSetting.setJavaArgs(getJavaArgs()); versionSetting.setMinecraftArgs(getMinecraftArgs()); + versionSetting.setEnvironmentVariables(getEnvironmentVariables()); versionSetting.setNoJVMArgs(isNoJVMArgs()); versionSetting.setNotCheckGame(isNotCheckGame()); versionSetting.setNotCheckJVM(isNotCheckJVM()); @@ -761,6 +776,7 @@ public final class VersionSetting implements Cloneable { obj.addProperty("usesGlobal", src.isUsesGlobal()); obj.addProperty("javaArgs", src.getJavaArgs()); obj.addProperty("minecraftArgs", src.getMinecraftArgs()); + obj.addProperty("environmentVariables", src.getEnvironmentVariables()); obj.addProperty("maxMemory", src.getMaxMemory() <= 0 ? OperatingSystem.SUGGESTED_MEMORY : src.getMaxMemory()); obj.addProperty("minMemory", src.getMinMemory()); obj.addProperty("autoMemory", src.isAutoMemory()); @@ -819,6 +835,7 @@ public final class VersionSetting implements Cloneable { vs.setUsesGlobal(Optional.ofNullable(obj.get("usesGlobal")).map(JsonElement::getAsBoolean).orElse(false)); vs.setJavaArgs(Optional.ofNullable(obj.get("javaArgs")).map(JsonElement::getAsString).orElse("")); vs.setMinecraftArgs(Optional.ofNullable(obj.get("minecraftArgs")).map(JsonElement::getAsString).orElse("")); + vs.setEnvironmentVariables(Optional.ofNullable(obj.get("environmentVariables")).map(JsonElement::getAsString).orElse("")); vs.setMaxMemory(maxMemoryN); vs.setMinMemory(Optional.ofNullable(obj.get("minMemory")).map(JsonElement::getAsInt).orElse(null)); vs.setAutoMemory(Optional.ofNullable(obj.get("autoMemory")).map(JsonElement::getAsBoolean).orElse(true)); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/AdvancedVersionSettingPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/AdvancedVersionSettingPage.java index ea60bff1c..ea5ecb6ac 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/AdvancedVersionSettingPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/AdvancedVersionSettingPage.java @@ -35,6 +35,7 @@ public final class AdvancedVersionSettingPage extends StackPane implements Decor private final JFXTextField txtJVMArgs; private final JFXTextField txtGameArgs; + private final JFXTextField txtEnvironmentVariables; private final JFXTextField txtMetaspace; private final JFXTextField txtWrapper; private final JFXTextField txtPreLaunchCommand; @@ -132,6 +133,10 @@ public final class AdvancedVersionSettingPage extends StackPane implements Decor txtMetaspace.setValidators(new NumberValidator(i18n("input.number"), true)); pane.addRow(1, new Label(i18n("settings.advanced.java_permanent_generation_space")), txtMetaspace); + txtEnvironmentVariables = new JFXTextField(); + txtEnvironmentVariables.getStyleClass().add("fit-width"); + pane.addRow(2, new Label(i18n("settings.advanced.environment_variables")), txtEnvironmentVariables); + jvmPane.getContent().setAll(pane); } @@ -209,6 +214,7 @@ public final class AdvancedVersionSettingPage extends StackPane implements Decor FXUtils.bindString(txtJVMArgs, versionSetting.javaArgsProperty()); FXUtils.bindString(txtGameArgs, versionSetting.minecraftArgsProperty()); FXUtils.bindString(txtMetaspace, versionSetting.permSizeProperty()); + FXUtils.bindString(txtEnvironmentVariables, versionSetting.environmentVariablesProperty()); FXUtils.bindString(txtWrapper, versionSetting.wrapperProperty()); FXUtils.bindString(txtPreLaunchCommand, versionSetting.preLaunchCommandProperty()); FXUtils.bindEnum(cboRenderer, versionSetting.rendererProperty()); @@ -229,6 +235,7 @@ public final class AdvancedVersionSettingPage extends StackPane implements Decor FXUtils.unbind(txtJVMArgs, versionSetting.javaArgsProperty()); FXUtils.unbind(txtGameArgs, versionSetting.minecraftArgsProperty()); FXUtils.unbind(txtMetaspace, versionSetting.permSizeProperty()); + FXUtils.unbind(txtEnvironmentVariables, versionSetting.environmentVariablesProperty()); FXUtils.unbind(txtWrapper, versionSetting.wrapperProperty()); FXUtils.unbind(txtPreLaunchCommand, versionSetting.preLaunchCommandProperty()); FXUtils.unbind(txtPostExitCommand, versionSetting.postExitCommandProperty()); diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index e2bbf3ab4..d807ad6e9 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -969,6 +969,7 @@ settings.advanced.custom_commands.hint=The following environment variables are p settings.advanced.dont_check_game_completeness=Do not check game integrity settings.advanced.dont_check_jvm_validity=Do not check JVM compatibility settings.advanced.dont_patch_natives=Do not attempt to automatically replace native libraries +settings.advanced.environment_variables=Environment Variables settings.advanced.game_dir.default=Default (.minecraft/) settings.advanced.game_dir.independent=Isolated (.minecraft/versions//, except for assets and libraries) settings.advanced.java_permanent_generation_space=PermGen Space diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 66f7c4594..4b9e64725 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -844,6 +844,7 @@ settings.advanced.custom_commands.hint=自訂命令被調用時將包含如下 settings.advanced.dont_check_game_completeness=不檢查遊戲完整性 settings.advanced.dont_check_jvm_validity=不檢查 JVM 與遊戲的相容性 settings.advanced.dont_patch_natives=不嘗試自動替換本機庫 +settings.advanced.environment_variables=環境變數 settings.advanced.game_dir.default=預設(.minecraft/) settings.advanced.game_dir.independent=各版本獨立(.minecraft/versions/<版本名>/,除 assets、libraries) settings.advanced.java_permanent_generation_space=記憶體永久儲存區域 diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index 24e4586e1..cc520a763 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -842,6 +842,7 @@ settings.advanced.custom_commands.hint=自定义命令被调用时将包含如 settings.advanced.dont_check_game_completeness=不检查游戏完整性 settings.advanced.dont_check_jvm_validity=不检查 JVM 与游戏的兼容性 settings.advanced.dont_patch_natives=不尝试自动替换本地库 +settings.advanced.environment_variables=环境变量 settings.advanced.game_dir.default=默认(.minecraft/) settings.advanced.game_dir.independent=各版本独立(存放在 .minecraft/versions/<版本名>/,除 assets、libraries 外) settings.advanced.java_permanent_generation_space=内存永久保存区域 diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/LaunchOptions.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/LaunchOptions.java index 4775d3d38..40ecbc869 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/LaunchOptions.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/LaunchOptions.java @@ -23,9 +23,7 @@ import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.Serializable; import java.net.Proxy; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import java.util.*; /** * @@ -42,6 +40,7 @@ public class LaunchOptions implements Serializable { private final List overrideJavaArguments = new ArrayList<>(); private final List javaArguments = new ArrayList<>(); private final List javaAgents = new ArrayList<>(0); + private final Map environmentVariables = new LinkedHashMap<>(); private Integer minMemory; private Integer maxMemory; private Integer metaspace; @@ -130,6 +129,10 @@ public class LaunchOptions implements Serializable { return Collections.unmodifiableList(javaAgents); } + public Map getEnvironmentVariables() { + return environmentVariables; + } + /** * The minimum memory that the JVM can allocate. */ @@ -279,43 +282,6 @@ public class LaunchOptions implements Serializable { return options; } - /** - * The game directory - */ - public File getGameDir() { - return options.gameDir; - } - - /** - * The Java Environment that Minecraft runs on. - */ - public JavaVersion getJava() { - return options.java; - } - - /** - * Will shown in the left bottom corner of the main menu of Minecraft. - * null if use the id of launch version. - */ - public String getVersionName() { - return options.versionName; - } - - /** - * Will shown in the left bottom corner of the main menu of Minecraft. - * null if use Version.versionType. - */ - public String getVersionType() { - return options.versionType; - } - - /** - * Don't know what the hell this is. - */ - public String getProfileName() { - return options.profileName; - } - /** * User custom additional minecraft command line arguments. */ @@ -341,123 +307,6 @@ public class LaunchOptions implements Serializable { return options.javaAgents; } - /** - * The minimum memory that the JVM can allocate. - */ - public Integer getMinMemory() { - return options.minMemory; - } - - /** - * The maximum memory that the JVM can allocate. - */ - public Integer getMaxMemory() { - return options.maxMemory; - } - - /** - * The maximum metaspace memory that the JVM can allocate. - * For Java 7 -XX:PermSize and Java 8 -XX:MetaspaceSize - * Containing class instances. - */ - public Integer getMetaspace() { - return options.metaspace; - } - - /** - * The initial game window width - */ - public Integer getWidth() { - return options.width; - } - - /** - * The initial game window height - */ - public Integer getHeight() { - return options.height; - } - - /** - * Is inital game window fullscreen. - */ - public boolean isFullscreen() { - return options.fullscreen; - } - - /** - * The server ip that will connect to when enter game main menu. - */ - public String getServerIp() { - return options.serverIp; - } - - /** - * i.e. optirun - */ - public String getWrapper() { - return options.wrapper; - } - - /** - * Proxy settings - */ - public Proxy getProxy() { - return options.proxy; - } - - /** - * The user name of the proxy, optional. - */ - public String getProxyUser() { - return options.proxyUser; - } - - /** - * The password of the proxy, optional - */ - public String getProxyPass() { - return options.proxyPass; - } - - /** - * Prevent game launcher from generating default JVM arguments like max memory. - */ - public boolean isNoGeneratedJVMArgs() { - return options.noGeneratedJVMArgs; - } - - /** - * Called command line before launching the game. - */ - public String getPreLaunchCommand() { - return options.preLaunchCommand; - } - - public NativesDirectoryType getNativesDirType() { - return options.nativesDirType; - } - - public String getNativesDir() { - return options.nativesDir; - } - - public Renderer getRenderer() { - return options.renderer; - } - - public boolean isUseNativeGLFW() { - return options.useNativeGLFW; - } - - public boolean isUseNativeOpenAL() { - return options.useNativeOpenAL; - } - - public boolean isDaemon() { - return options.daemon; - } - public Builder setGameDir(File gameDir) { options.gameDir = gameDir; return this; @@ -507,6 +356,12 @@ public class LaunchOptions implements Serializable { return this; } + public Builder setEnvironmentVariables(Map env) { + options.environmentVariables.clear(); + options.environmentVariables.putAll(env); + return this; + } + public Builder setMinMemory(Integer minMemory) { options.minMemory = minMemory; return this; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java index 1d0d34997..b5915a7c8 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java @@ -462,7 +462,7 @@ public class DefaultLauncher extends Launcher { private Map getEnvVars() { String versionName = Optional.ofNullable(options.getVersionName()).orElse(version.getId()); - Map env = new HashMap<>(); + Map env = new LinkedHashMap<>(); env.put("INST_NAME", versionName); env.put("INST_ID", versionName); env.put("INST_DIR", repository.getVersionRoot(version.getId()).getAbsolutePath()); @@ -503,6 +503,9 @@ public class DefaultLauncher extends Launcher { if (analyzer.has(LibraryAnalyzer.LibraryType.QUILT)) { env.put("INST_QUILT", "1"); } + + env.putAll(options.getEnvironmentVariables()); + return env; }