feat: env vars for pre-launch command and post-exit command.
This commit is contained in:
@@ -307,7 +307,8 @@ public class HMCLGameRepository extends DefaultGameRepository {
|
|||||||
.setFullscreen(vs.isFullscreen())
|
.setFullscreen(vs.isFullscreen())
|
||||||
.setServerIp(vs.getServerIp())
|
.setServerIp(vs.getServerIp())
|
||||||
.setWrapper(vs.getWrapper())
|
.setWrapper(vs.getWrapper())
|
||||||
.setPrecalledCommand(vs.getPreLaunchCommand())
|
.setPreLaunchCommand(vs.getPreLaunchCommand())
|
||||||
|
.setPostExitCommand(vs.getPostExitCommand())
|
||||||
.setNoGeneratedJVMArgs(vs.isNoJVMArgs())
|
.setNoGeneratedJVMArgs(vs.isNoJVMArgs())
|
||||||
.setNativesDirType(vs.getNativesDirType())
|
.setNativesDirType(vs.getNativesDirType())
|
||||||
.setNativesDir(vs.getNativesDir())
|
.setNativesDir(vs.getNativesDir())
|
||||||
|
|||||||
@@ -269,6 +269,24 @@ public final class VersionSetting implements Cloneable {
|
|||||||
preLaunchCommandProperty.set(preLaunchCommand);
|
preLaunchCommandProperty.set(preLaunchCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final StringProperty postExitCommand = new SimpleStringProperty(this, "postExitCommand", "");
|
||||||
|
|
||||||
|
public StringProperty postExitCommandProperty() {
|
||||||
|
return postExitCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command that will be executed after game exits.
|
||||||
|
* Operating system relevant.
|
||||||
|
*/
|
||||||
|
public String getPostExitCommand() {
|
||||||
|
return postExitCommand.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPostExitCommand(String postExitCommand) {
|
||||||
|
this.postExitCommand.set(postExitCommand);
|
||||||
|
}
|
||||||
|
|
||||||
// options
|
// options
|
||||||
|
|
||||||
private final StringProperty javaArgsProperty = new SimpleStringProperty(this, "javaArgs", "");
|
private final StringProperty javaArgsProperty = new SimpleStringProperty(this, "javaArgs", "");
|
||||||
@@ -602,6 +620,7 @@ public final class VersionSetting implements Cloneable {
|
|||||||
minMemoryProperty.addListener(listener);
|
minMemoryProperty.addListener(listener);
|
||||||
autoMemory.addListener(listener);
|
autoMemory.addListener(listener);
|
||||||
preLaunchCommandProperty.addListener(listener);
|
preLaunchCommandProperty.addListener(listener);
|
||||||
|
postExitCommand.addListener(listener);
|
||||||
javaArgsProperty.addListener(listener);
|
javaArgsProperty.addListener(listener);
|
||||||
minecraftArgsProperty.addListener(listener);
|
minecraftArgsProperty.addListener(listener);
|
||||||
noJVMArgsProperty.addListener(listener);
|
noJVMArgsProperty.addListener(listener);
|
||||||
@@ -636,6 +655,7 @@ public final class VersionSetting implements Cloneable {
|
|||||||
versionSetting.setMinMemory(getMinMemory());
|
versionSetting.setMinMemory(getMinMemory());
|
||||||
versionSetting.setAutoMemory(isAutoMemory());
|
versionSetting.setAutoMemory(isAutoMemory());
|
||||||
versionSetting.setPreLaunchCommand(getPreLaunchCommand());
|
versionSetting.setPreLaunchCommand(getPreLaunchCommand());
|
||||||
|
versionSetting.setPostExitCommand(getPostExitCommand());
|
||||||
versionSetting.setJavaArgs(getJavaArgs());
|
versionSetting.setJavaArgs(getJavaArgs());
|
||||||
versionSetting.setMinecraftArgs(getMinecraftArgs());
|
versionSetting.setMinecraftArgs(getMinecraftArgs());
|
||||||
versionSetting.setNoJVMArgs(isNoJVMArgs());
|
versionSetting.setNoJVMArgs(isNoJVMArgs());
|
||||||
@@ -673,6 +693,7 @@ public final class VersionSetting implements Cloneable {
|
|||||||
obj.addProperty("height", src.getHeight());
|
obj.addProperty("height", src.getHeight());
|
||||||
obj.addProperty("javaDir", src.getJavaDir());
|
obj.addProperty("javaDir", src.getJavaDir());
|
||||||
obj.addProperty("precalledCommand", src.getPreLaunchCommand());
|
obj.addProperty("precalledCommand", src.getPreLaunchCommand());
|
||||||
|
obj.addProperty("postExitCommand", src.getPostExitCommand());
|
||||||
obj.addProperty("serverIp", src.getServerIp());
|
obj.addProperty("serverIp", src.getServerIp());
|
||||||
obj.addProperty("java", src.getJava());
|
obj.addProperty("java", src.getJava());
|
||||||
obj.addProperty("wrapper", src.getWrapper());
|
obj.addProperty("wrapper", src.getWrapper());
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ public class LaunchOptions implements Serializable {
|
|||||||
private String proxyPass;
|
private String proxyPass;
|
||||||
private boolean noGeneratedJVMArgs;
|
private boolean noGeneratedJVMArgs;
|
||||||
private String preLaunchCommand;
|
private String preLaunchCommand;
|
||||||
|
private String postExitCommand;
|
||||||
private NativesDirectoryType nativesDirType;
|
private NativesDirectoryType nativesDirType;
|
||||||
private String nativesDir;
|
private String nativesDir;
|
||||||
private ProcessPriority processPriority = ProcessPriority.NORMAL;
|
private ProcessPriority processPriority = ProcessPriority.NORMAL;
|
||||||
@@ -199,12 +200,19 @@ public class LaunchOptions implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called command line before launching the game.
|
* Command called before game launches.
|
||||||
*/
|
*/
|
||||||
public String getPreLaunchCommand() {
|
public String getPreLaunchCommand() {
|
||||||
return preLaunchCommand;
|
return preLaunchCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command called after game exits.
|
||||||
|
*/
|
||||||
|
public String getPostExitCommand() {
|
||||||
|
return postExitCommand;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 0 - ./minecraft/versions/<version>/natives
|
* 0 - ./minecraft/versions/<version>/natives
|
||||||
* 1 - custom natives directory
|
* 1 - custom natives directory
|
||||||
@@ -500,8 +508,13 @@ public class LaunchOptions implements Serializable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setPrecalledCommand(String precalledCommand) {
|
public Builder setPreLaunchCommand(String preLaunchCommand) {
|
||||||
options.preLaunchCommand = precalledCommand;
|
options.preLaunchCommand = preLaunchCommand;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setPostExitCommand(String postExitCommand) {
|
||||||
|
options.postExitCommand = postExitCommand;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package org.jackhuang.hmcl.launch;
|
package org.jackhuang.hmcl.launch;
|
||||||
|
|
||||||
import org.jackhuang.hmcl.auth.AuthInfo;
|
import org.jackhuang.hmcl.auth.AuthInfo;
|
||||||
|
import org.jackhuang.hmcl.download.LibraryAnalyzer;
|
||||||
import org.jackhuang.hmcl.game.Argument;
|
import org.jackhuang.hmcl.game.Argument;
|
||||||
import org.jackhuang.hmcl.game.Arguments;
|
import org.jackhuang.hmcl.game.Arguments;
|
||||||
import org.jackhuang.hmcl.game.GameRepository;
|
import org.jackhuang.hmcl.game.GameRepository;
|
||||||
@@ -374,16 +375,9 @@ public class DefaultLauncher extends Launcher {
|
|||||||
File runDirectory = repository.getRunDirectory(version.getId());
|
File runDirectory = repository.getRunDirectory(version.getId());
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(options.getPreLaunchCommand())) {
|
if (StringUtils.isNotBlank(options.getPreLaunchCommand())) {
|
||||||
String versionName = Optional.ofNullable(options.getVersionName()).orElse(version.getId());
|
ProcessBuilder builder = new ProcessBuilder(StringUtils.tokenize(options.getPreLaunchCommand())).directory(runDirectory);
|
||||||
String preLaunchCommand = options.getPreLaunchCommand()
|
builder.environment().putAll(getEnvVars());
|
||||||
.replace("$INST_NAME", versionName)
|
builder.start().waitFor();
|
||||||
.replace("$INST_ID", versionName)
|
|
||||||
.replace("$INST_DIR", repository.getVersionRoot(version.getId()).getAbsolutePath())
|
|
||||||
.replace("$INST_MC_DIR", repository.getRunDirectory(version.getId()).getAbsolutePath())
|
|
||||||
.replace("$INST_JAVA", options.getJava().getBinary().toString());
|
|
||||||
|
|
||||||
new ProcessBuilder(StringUtils.tokenize(preLaunchCommand))
|
|
||||||
.directory(runDirectory).start().waitFor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Process process;
|
Process process;
|
||||||
@@ -394,6 +388,7 @@ public class DefaultLauncher extends Launcher {
|
|||||||
}
|
}
|
||||||
String appdata = options.getGameDir().getAbsoluteFile().getParent();
|
String appdata = options.getGameDir().getAbsoluteFile().getParent();
|
||||||
if (appdata != null) builder.environment().put("APPDATA", appdata);
|
if (appdata != null) builder.environment().put("APPDATA", appdata);
|
||||||
|
builder.environment().putAll(getEnvVars());
|
||||||
process = builder.start();
|
process = builder.start();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new ProcessCreationException(e);
|
throw new ProcessCreationException(e);
|
||||||
@@ -405,6 +400,31 @@ public class DefaultLauncher extends Launcher {
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<String, String> getEnvVars() {
|
||||||
|
String versionName = Optional.ofNullable(options.getVersionName()).orElse(version.getId());
|
||||||
|
Map<String, String> env = new HashMap<>();
|
||||||
|
env.put("INST_NAME", versionName);
|
||||||
|
env.put("INST_ID", versionName);
|
||||||
|
env.put("INST_DIR", repository.getVersionRoot(version.getId()).getAbsolutePath());
|
||||||
|
env.put("INST_MC_DIR", repository.getRunDirectory(version.getId()).getAbsolutePath());
|
||||||
|
env.put("INST_JAVA", options.getJava().getBinary().toString());
|
||||||
|
|
||||||
|
LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(version);
|
||||||
|
if (analyzer.has(LibraryAnalyzer.LibraryType.FORGE)) {
|
||||||
|
env.put("INST_FORGE", "1");
|
||||||
|
}
|
||||||
|
if (analyzer.has(LibraryAnalyzer.LibraryType.LITELOADER)) {
|
||||||
|
env.put("INST_LITELOADER", "1");
|
||||||
|
}
|
||||||
|
if (analyzer.has(LibraryAnalyzer.LibraryType.FABRIC)) {
|
||||||
|
env.put("INST_FABRIC", "1");
|
||||||
|
}
|
||||||
|
if (analyzer.has(LibraryAnalyzer.LibraryType.OPTIFINE)) {
|
||||||
|
env.put("INST_OPTIFINE", "1");
|
||||||
|
}
|
||||||
|
return env;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void makeLaunchScript(File scriptFile) throws IOException {
|
public void makeLaunchScript(File scriptFile) throws IOException {
|
||||||
boolean isWindows = OperatingSystem.WINDOWS == OperatingSystem.CURRENT_OS;
|
boolean isWindows = OperatingSystem.WINDOWS == OperatingSystem.CURRENT_OS;
|
||||||
@@ -432,12 +452,20 @@ public class DefaultLauncher extends Launcher {
|
|||||||
writer.write("@echo off");
|
writer.write("@echo off");
|
||||||
writer.newLine();
|
writer.newLine();
|
||||||
writer.write("set APPDATA=" + options.getGameDir().getAbsoluteFile().getParent());
|
writer.write("set APPDATA=" + options.getGameDir().getAbsoluteFile().getParent());
|
||||||
|
for (Map.Entry<String, String> entry : getEnvVars().entrySet()) {
|
||||||
|
writer.write("set " + entry.getKey() + "=" + entry.getValue());
|
||||||
|
writer.newLine();
|
||||||
|
}
|
||||||
writer.newLine();
|
writer.newLine();
|
||||||
writer.write(new CommandBuilder().add("cd", "/D", repository.getRunDirectory(version.getId()).getAbsolutePath()).toString());
|
writer.write(new CommandBuilder().add("cd", "/D", repository.getRunDirectory(version.getId()).getAbsolutePath()).toString());
|
||||||
writer.newLine();
|
writer.newLine();
|
||||||
} else if (OperatingSystem.CURRENT_OS == OperatingSystem.OSX || OperatingSystem.CURRENT_OS == OperatingSystem.LINUX) {
|
} else if (OperatingSystem.CURRENT_OS == OperatingSystem.OSX || OperatingSystem.CURRENT_OS == OperatingSystem.LINUX) {
|
||||||
writer.write("#!/usr/bin/env bash");
|
writer.write("#!/usr/bin/env bash");
|
||||||
writer.newLine();
|
writer.newLine();
|
||||||
|
for (Map.Entry<String, String> entry : getEnvVars().entrySet()) {
|
||||||
|
writer.write("export " + entry.getKey() + "=" + entry.getValue());
|
||||||
|
writer.newLine();
|
||||||
|
}
|
||||||
writer.write(new CommandBuilder().add("cd", repository.getRunDirectory(version.getId()).getAbsolutePath()).toString());
|
writer.write(new CommandBuilder().add("cd", repository.getRunDirectory(version.getId()).getAbsolutePath()).toString());
|
||||||
writer.newLine();
|
writer.newLine();
|
||||||
}
|
}
|
||||||
@@ -446,6 +474,16 @@ public class DefaultLauncher extends Launcher {
|
|||||||
writer.newLine();
|
writer.newLine();
|
||||||
}
|
}
|
||||||
writer.write(generateCommandLine(nativeFolder).toString());
|
writer.write(generateCommandLine(nativeFolder).toString());
|
||||||
|
writer.newLine();
|
||||||
|
if (StringUtils.isNotBlank(options.getPostExitCommand())) {
|
||||||
|
writer.write(options.getPostExitCommand());
|
||||||
|
writer.newLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isWindows) {
|
||||||
|
writer.write("pause");
|
||||||
|
writer.newLine();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!scriptFile.setExecutable(true))
|
if (!scriptFile.setExecutable(true))
|
||||||
throw new PermissionException();
|
throw new PermissionException();
|
||||||
|
|||||||
Reference in New Issue
Block a user