mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-13 13:56:55 -04:00
Change current directory to run directory for launching scripts
This commit is contained in:
parent
a3fbc9595a
commit
1532893c5f
@ -21,8 +21,10 @@ import org.jackhuang.hmcl.Launcher;
|
|||||||
import org.jackhuang.hmcl.auth.AuthInfo;
|
import org.jackhuang.hmcl.auth.AuthInfo;
|
||||||
import org.jackhuang.hmcl.launch.DefaultLauncher;
|
import org.jackhuang.hmcl.launch.DefaultLauncher;
|
||||||
import org.jackhuang.hmcl.launch.ProcessListener;
|
import org.jackhuang.hmcl.launch.ProcessListener;
|
||||||
|
import org.jackhuang.hmcl.util.CommandBuilder;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
@ -42,10 +44,10 @@ public final class HMCLGameLauncher extends DefaultLauncher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void appendJvmArgs(List<String> result) {
|
protected Map<String, String> getConfigurations() {
|
||||||
super.appendJvmArgs(result);
|
Map<String, String> res = super.getConfigurations();
|
||||||
|
res.put("${launcher_name}", Launcher.NAME);
|
||||||
result.add("-Dminecraft.launcher.version=" + Launcher.VERSION);
|
res.put("${launcher_version}", Launcher.VERSION);
|
||||||
result.add("-Dminecraft.launcher.brand=" + Launcher.NAME);
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -434,7 +434,7 @@ public final class LauncherHelper {
|
|||||||
|
|
||||||
logWindow.show();
|
logWindow.show();
|
||||||
logWindow.onDone.register(() -> {
|
logWindow.onDone.register(() -> {
|
||||||
logWindow.logLine("Commands: " + StringUtils.makeCommand(process.getCommands()), Log4jLevel.INFO);
|
logWindow.logLine("Command: " + new CommandBuilder().addAll(process.getCommands()).toString(), Log4jLevel.INFO);
|
||||||
for (Map.Entry<String, Log4jLevel> entry : logs)
|
for (Map.Entry<String, Log4jLevel> entry : logs)
|
||||||
logWindow.logLine(entry.getKey(), entry.getValue());
|
logWindow.logLine(entry.getKey(), entry.getValue());
|
||||||
});
|
});
|
||||||
|
@ -20,6 +20,7 @@ package org.jackhuang.hmcl.download;
|
|||||||
import org.jackhuang.hmcl.game.Library;
|
import org.jackhuang.hmcl.game.Library;
|
||||||
import org.jackhuang.hmcl.game.Version;
|
import org.jackhuang.hmcl.game.Version;
|
||||||
import org.jackhuang.hmcl.task.TaskResult;
|
import org.jackhuang.hmcl.task.TaskResult;
|
||||||
|
import org.jackhuang.hmcl.util.CommandBuilder;
|
||||||
import org.jackhuang.hmcl.util.StringUtils;
|
import org.jackhuang.hmcl.util.StringUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -93,7 +94,7 @@ public class MaintainTask extends TaskResult<Version> {
|
|||||||
args.add("optifine.OptiFineForgeTweaker");
|
args.add("optifine.OptiFineForgeTweaker");
|
||||||
}
|
}
|
||||||
|
|
||||||
return version.setMinecraftArguments(StringUtils.makeCommand(args));
|
return version.setMinecraftArguments(new CommandBuilder().addAll(args).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,7 +25,6 @@ import java.io.*;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
||||||
import static org.jackhuang.hmcl.util.Pair.pair;
|
import static org.jackhuang.hmcl.util.Pair.pair;
|
||||||
@ -48,8 +47,8 @@ public class DefaultLauncher extends Launcher {
|
|||||||
super(repository, versionId, authInfo, options, listener, daemon);
|
super(repository, versionId, authInfo, options, listener, daemon);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> generateCommandLine(File nativeFolder) throws IOException {
|
private CommandBuilder generateCommandLine(File nativeFolder, boolean enableLoggingInfo) throws IOException {
|
||||||
List<String> res = new LinkedList<>();
|
CommandBuilder res = new CommandBuilder();
|
||||||
|
|
||||||
// Executable
|
// Executable
|
||||||
if (StringUtils.isNotBlank(options.getWrapper()))
|
if (StringUtils.isNotBlank(options.getWrapper()))
|
||||||
@ -58,7 +57,7 @@ public class DefaultLauncher extends Launcher {
|
|||||||
res.add(options.getJava().getBinary().toString());
|
res.add(options.getJava().getBinary().toString());
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(options.getJavaArgs()))
|
if (StringUtils.isNotBlank(options.getJavaArgs()))
|
||||||
res.addAll(StringUtils.tokenize(options.getJavaArgs()));
|
res.addAllWithoutParsing(StringUtils.tokenize(options.getJavaArgs()));
|
||||||
|
|
||||||
// JVM Args
|
// JVM Args
|
||||||
if (!options.isNoGeneratedJVMArgs()) {
|
if (!options.isNoGeneratedJVMArgs()) {
|
||||||
@ -72,7 +71,7 @@ public class DefaultLauncher extends Launcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Map<DownloadType, LoggingInfo> logging = version.getLogging();
|
Map<DownloadType, LoggingInfo> logging = version.getLogging();
|
||||||
if (logging != null) {
|
if (logging != null && enableLoggingInfo) {
|
||||||
LoggingInfo loggingInfo = logging.get(DownloadType.CLIENT);
|
LoggingInfo loggingInfo = logging.get(DownloadType.CLIENT);
|
||||||
if (loggingInfo != null) {
|
if (loggingInfo != null) {
|
||||||
File loggingFile = repository.getLoggingObject(version.getId(), version.getAssetIndex().getId(), loggingInfo);
|
File loggingFile = repository.getLoggingObject(version.getId(), version.getAssetIndex().getId(), loggingInfo);
|
||||||
@ -187,11 +186,10 @@ public class DefaultLauncher extends Launcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(options.getMinecraftArgs()))
|
if (StringUtils.isNotBlank(options.getMinecraftArgs()))
|
||||||
res.addAll(StringUtils.tokenize(options.getMinecraftArgs()));
|
res.addAllWithoutParsing(StringUtils.tokenize(options.getMinecraftArgs()));
|
||||||
|
|
||||||
return res.stream()
|
res.removeIf(it -> getForbiddens().containsKey(it) && getForbiddens().get(it).get());
|
||||||
.filter(it -> !getForbiddens().containsKey(it) || !getForbiddens().get(it).get())
|
return res;
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Boolean> getFeatures() {
|
public Map<String, Boolean> getFeatures() {
|
||||||
@ -224,7 +222,7 @@ public class DefaultLauncher extends Launcher {
|
|||||||
* -Dminecraft.launcher.brand=<Your launcher version>
|
* -Dminecraft.launcher.brand=<Your launcher version>
|
||||||
* -Dlog4j.configurationFile=<Your custom log4j configuration>
|
* -Dlog4j.configurationFile=<Your custom log4j configuration>
|
||||||
*/
|
*/
|
||||||
protected void appendJvmArgs(List<String> result) {
|
protected void appendJvmArgs(CommandBuilder result) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void decompressNatives(File destination) throws NotDecompressingNativesException {
|
public void decompressNatives(File destination) throws NotDecompressingNativesException {
|
||||||
@ -262,18 +260,20 @@ public class DefaultLauncher extends Launcher {
|
|||||||
File nativeFolder = Files.createTempDirectory("minecraft").toFile();
|
File nativeFolder = Files.createTempDirectory("minecraft").toFile();
|
||||||
|
|
||||||
// To guarantee that when failed to generate launch command line, we will not call pre-launch command
|
// To guarantee that when failed to generate launch command line, we will not call pre-launch command
|
||||||
List<String> rawCommandLine = generateCommandLine(nativeFolder);
|
List<String> rawCommandLine = generateCommandLine(nativeFolder, true).asList();
|
||||||
|
|
||||||
decompressNatives(nativeFolder);
|
decompressNatives(nativeFolder);
|
||||||
|
|
||||||
|
File runDirectory = repository.getRunDirectory(version.getId());
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(options.getPreLaunchCommand()))
|
if (StringUtils.isNotBlank(options.getPreLaunchCommand()))
|
||||||
Runtime.getRuntime().exec(options.getPreLaunchCommand()).waitFor();
|
new ProcessBuilder(options.getPreLaunchCommand())
|
||||||
|
.directory(runDirectory).start().waitFor();
|
||||||
|
|
||||||
Process process;
|
Process process;
|
||||||
try {
|
try {
|
||||||
ProcessBuilder builder = new ProcessBuilder(rawCommandLine);
|
ProcessBuilder builder = new ProcessBuilder(rawCommandLine).directory(runDirectory);
|
||||||
builder.directory(repository.getRunDirectory(version.getId()))
|
builder.environment().put("APPDATA", options.getGameDir().getAbsoluteFile().getParent());
|
||||||
.environment().put("APPDATA", options.getGameDir().getAbsoluteFile().getParent());
|
|
||||||
process = builder.start();
|
process = builder.start();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new ProcessCreationException(e);
|
throw new ProcessCreationException(e);
|
||||||
@ -305,14 +305,14 @@ public class DefaultLauncher extends Launcher {
|
|||||||
writer.newLine();
|
writer.newLine();
|
||||||
writer.write("set APPDATA=" + options.getGameDir().getAbsoluteFile().getParent());
|
writer.write("set APPDATA=" + options.getGameDir().getAbsoluteFile().getParent());
|
||||||
writer.newLine();
|
writer.newLine();
|
||||||
writer.write("cd /D %APPDATA%");
|
writer.write(new CommandBuilder().add("cd", "/D", repository.getRunDirectory(version.getId()).getAbsolutePath()).toString());
|
||||||
writer.newLine();
|
writer.newLine();
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotBlank(options.getPreLaunchCommand())) {
|
if (StringUtils.isNotBlank(options.getPreLaunchCommand())) {
|
||||||
writer.write(options.getPreLaunchCommand());
|
writer.write(options.getPreLaunchCommand());
|
||||||
writer.newLine();
|
writer.newLine();
|
||||||
}
|
}
|
||||||
writer.write(StringUtils.makeCommand(generateCommandLine(nativeFolder)));
|
writer.write(generateCommandLine(nativeFolder, false).toString());
|
||||||
}
|
}
|
||||||
if (!scriptFile.setExecutable(true))
|
if (!scriptFile.setExecutable(true))
|
||||||
throw new PermissionException();
|
throw new PermissionException();
|
||||||
|
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher.
|
||||||
|
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.util;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public final class CommandBuilder {
|
||||||
|
private final OperatingSystem os;
|
||||||
|
private List<Item> raw = new LinkedList<>();
|
||||||
|
|
||||||
|
public CommandBuilder() {
|
||||||
|
this(OperatingSystem.CURRENT_OS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandBuilder(OperatingSystem os) {
|
||||||
|
this.os = os;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String parse(String s) {
|
||||||
|
if (OperatingSystem.WINDOWS == os) {
|
||||||
|
return parseWindows(s);
|
||||||
|
} else {
|
||||||
|
return parseBash(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandBuilder add(String... args) {
|
||||||
|
for (String s : args)
|
||||||
|
raw.add(new Item(s, true));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandBuilder addAll(Collection<String> args) {
|
||||||
|
for (String s : args)
|
||||||
|
raw.add(new Item(s, true));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandBuilder addWithoutParsing(String... args) {
|
||||||
|
for (String s : args)
|
||||||
|
raw.add(new Item(s, false));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandBuilder addAllWithoutParsing(Collection<String> args) {
|
||||||
|
for (String s : args)
|
||||||
|
raw.add(new Item(s, false));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeIf(Predicate<String> pred) {
|
||||||
|
return raw.removeIf(i -> pred.test(i.arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.join(" ", raw.stream().map(i -> i.parse ? parse(i.arg) : i.arg).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> asList() {
|
||||||
|
return raw.stream().map(i -> i.arg).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Item {
|
||||||
|
String arg;
|
||||||
|
boolean parse;
|
||||||
|
|
||||||
|
Item(String arg, boolean parse) {
|
||||||
|
this.arg = arg;
|
||||||
|
this.parse = parse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String parseWindows(String s) {
|
||||||
|
if (s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0)
|
||||||
|
if (s.charAt(0) != '"') {
|
||||||
|
// The argument has not been quoted, add quotes.
|
||||||
|
return '"' + s.replace("\\", "\\\\").replace("\"", "\"\"") + '"';
|
||||||
|
} else if (s.endsWith("\"")) {
|
||||||
|
// The argument has already been quoted.
|
||||||
|
return s;
|
||||||
|
} else {
|
||||||
|
// Unmatched quote for the argument.
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String parseBash(String s) {
|
||||||
|
if (s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0)
|
||||||
|
if (s.charAt(0) != '"') {
|
||||||
|
// The argument has not been quoted, add quotes.
|
||||||
|
return '"' + s.replace("\"", "\\\"") + '"';
|
||||||
|
} else if (s.endsWith("\"")) {
|
||||||
|
// The argument has already been quoted.
|
||||||
|
return s;
|
||||||
|
} else {
|
||||||
|
// Unmatched quote for the argument.
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
@ -33,36 +33,6 @@ public final class StringUtils {
|
|||||||
private StringUtils() {
|
private StringUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String makeCommand(List<String> cmd) {
|
|
||||||
StringBuilder cmdbuf = new StringBuilder(120);
|
|
||||||
for (int i = 0; i < cmd.size(); i++) {
|
|
||||||
if (i > 0)
|
|
||||||
cmdbuf.append(' ');
|
|
||||||
String s = cmd.get(i);
|
|
||||||
if (s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0)
|
|
||||||
if (s.charAt(0) != '"') {
|
|
||||||
cmdbuf.append('"');
|
|
||||||
cmdbuf.append(s);
|
|
||||||
if (s.endsWith("\\"))
|
|
||||||
cmdbuf.append("\\");
|
|
||||||
cmdbuf.append('"');
|
|
||||||
} else if (s.endsWith("\""))
|
|
||||||
/*
|
|
||||||
* The argument has already been quoted.
|
|
||||||
*/
|
|
||||||
cmdbuf.append(s);
|
|
||||||
else
|
|
||||||
/*
|
|
||||||
* Unmatched quote for the argument.
|
|
||||||
*/
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
else
|
|
||||||
cmdbuf.append(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cmdbuf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getStackTrace(Throwable throwable) {
|
public static String getStackTrace(Throwable throwable) {
|
||||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||||
throwable.printStackTrace(new PrintStream(stream));
|
throwable.printStackTrace(new PrintStream(stream));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user