Change current directory to run directory for launching scripts

This commit is contained in:
huangyuhui 2018-07-16 19:51:12 +08:00
parent a3fbc9595a
commit 1532893c5f
6 changed files with 150 additions and 54 deletions

View File

@ -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;
} }
} }

View File

@ -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());
}); });

View File

@ -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

View File

@ -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=&lt;Your launcher version&gt; * -Dminecraft.launcher.brand=&lt;Your launcher version&gt;
* -Dlog4j.configurationFile=&lt;Your custom log4j configuration&gt; * -Dlog4j.configurationFile=&lt;Your custom log4j configuration&gt;
*/ */
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();

View File

@ -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;
}
}

View File

@ -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));