Compare commits

...
4 Commits
Author SHA1 Message Date
huangyuhui b5fbc69ee6 Default game arguments 2017-11-03 13:38:20 +08:00
huangyuhui 9d95d3ea66 JVM arguments in minecraft.json supported 2017-11-02 20:21:32 +08:00
huangyuhui 06b3ec8337 Launching 1.13 2017-11-02 19:34:21 +08:00
huangyuhui fabb6b50b4 Prevent launching in path that contains ! 2017-10-31 19:31:22 +08:00
16 changed files with 466 additions and 78 deletions

No files matched your search

@@ -47,7 +47,6 @@ import org.jackhuang.hmcl.ui.LogWindow;
import org.jackhuang.hmcl.ui.MainFrame;
import org.jackhuang.hmcl.util.CrashReporter;
import org.jackhuang.hmcl.util.DefaultPlugin;
import org.jackhuang.hmcl.util.MathUtils;
import org.jackhuang.hmcl.util.ui.MessageBox;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.util.lang.SupportedLocales;
@@ -101,6 +100,11 @@ public final class Main {
public static void main(String[] args) throws IOException {
{
if (new File("").getAbsolutePath().contains("!")) {
MessageBox.show("HMCL cannot run at such path that contains '!'");
return;
}
try {
File file = new File("hmcl.log").getAbsoluteFile();
if (!file.exists() && !file.createNewFile())
@@ -18,6 +18,7 @@
package org.jackhuang.hmcl.util;
import java.util.List;
import java.util.Map;
import org.jackhuang.hmcl.Main;
import org.jackhuang.hmcl.api.auth.UserProfileProvider;
import org.jackhuang.hmcl.api.game.LaunchOptions;
@@ -36,10 +37,10 @@ public class HMCLMinecraftLoader extends MinecraftLoader {
}
@Override
protected void appendJVMArgs(List<String> list) {
super.appendJVMArgs(list);
list.add("-Dminecraft.launcher.version=" + Main.LAUNCHER_VERSION);
list.add("-Dminecraft.launcher.brand=" + Main.LAUNCHER_NAME);
protected Map<String, String> getConfigurations() {
Map<String, String> map = super.getConfigurations();
map.put("${launcher_version}", Main.LAUNCHER_VERSION);
map.put("${launcher_name}", Main.LAUNCHER_NAME);
return map;
}
}
@@ -86,8 +86,6 @@ public abstract class AbstractMinecraftLoader implements IMinecraftLoader {
appendJVMArgs(res);
if (jv == null || !jv.isEarlyAccess()) {
if (OS.os() == OS.WINDOWS)
res.add("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump");
if (jv != null && jv.getParsedVersion() >= JdkVersion.JAVA_17)
res.add("-XX:+UseG1GC");
else
@@ -131,7 +129,6 @@ public abstract class AbstractMinecraftLoader implements IMinecraftLoader {
res.add(a);
}
res.add("-Djava.library.path=" + service.version().getDecompressNativesToLocation(version).getAbsolutePath());
res.add("-Dfml.ignoreInvalidMinecraftCertificates=true");
res.add("-Dfml.ignorePatchDiscrepancies=true");
@@ -150,13 +147,6 @@ public abstract class AbstractMinecraftLoader implements IMinecraftLoader {
HMCLog.log("On making launcher args.");
if (StrUtils.isNotBlank(options.getHeight()) && StrUtils.isNotBlank(options.getWidth())) {
res.add("--height");
res.add(options.getHeight());
res.add("--width");
res.add(options.getWidth());
}
String serverIp = options.getServerIp();
if (StrUtils.isNotBlank(serverIp)) {
String[] args = serverIp.split(":");
@@ -21,8 +21,11 @@ import org.jackhuang.hmcl.api.game.LaunchOptions;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.util.sys.OS;
@@ -30,7 +33,8 @@ import org.jackhuang.hmcl.core.GameException;
import org.jackhuang.hmcl.api.auth.UserProfileProvider;
import org.jackhuang.hmcl.core.version.MinecraftLibrary;
import org.jackhuang.hmcl.core.service.IMinecraftService;
import org.jackhuang.hmcl.core.version.LoggingInfo;
import org.jackhuang.hmcl.core.version.Argument;
import org.jackhuang.hmcl.core.version.Arguments;
/**
*
@@ -40,10 +44,28 @@ public class MinecraftLoader extends AbstractMinecraftLoader {
public MinecraftLoader(LaunchOptions p, IMinecraftService provider, UserProfileProvider lr) throws GameException {
super(p, provider, p.getLaunchVersion(), lr);
if (version.arguments == null)
version.arguments = new Arguments();
if (version.arguments.game == null)
version.arguments.game = getDefaultGameArguments();
if (version.arguments.jvm == null)
version.arguments.jvm = getDefaultJVMArguments();
}
protected List<Argument> getDefaultJVMArguments() {
return Arguments.DEFAULT_JVM_ARGUMENTS;
}
protected List<Argument> getDefaultGameArguments() {
return Arguments.DEFAULT_GAME_ARGUMENTS;
}
@Override
protected void makeSelf(List<String> res) throws GameException {
String game_assets = assetProvider.provide(version, !options.isNotCheckGame());
Map<String, String> configuration = getConfigurations();
StringBuilder library = new StringBuilder("");
ArrayList<MinecraftLibrary> opt = new ArrayList<>();
for (MinecraftLibrary l : version.libraries)
@@ -67,37 +89,44 @@ public class MinecraftLoader extends AbstractMinecraftLoader {
if (!f.exists())
throw new GameException("Minecraft jar does not exist");
library.append(f.getAbsolutePath()).append(File.pathSeparator);
res.add("-cp");
res.add(library.toString().substring(0, library.length() - File.pathSeparator.length()));
String classpath = library.toString().substring(0, library.length() - File.pathSeparator.length());
configuration.put("${classpath}", classpath);
configuration.put("${natives_directory}", service.version().getDecompressNativesToLocation(version).getAbsolutePath());
configuration.put("${game_assets}", game_assets);
res.addAll(Arguments.parseArguments(version.arguments.jvm, configuration));
res.add(version.mainClass);
if (version.minecraftArguments == null)
throw new GameException(new NullPointerException("Minecraft Arguments can not be null."));
String[] splitted = StrUtils.tokenize(version.minecraftArguments);
Map<String, Boolean> features = getFeatures();
String game_assets = assetProvider.provide(version, !options.isNotCheckGame());
res.addAll(Arguments.parseArguments(version.arguments.game, configuration, features));
res.addAll(Arguments.parseStringArguments(Arrays.asList(StrUtils.tokenize(version.minecraftArguments)), configuration));
}
protected Map<String, Boolean> getFeatures() {
Map<String, Boolean> features = new HashMap<>();
features.put("has_custom_resolution", StrUtils.isNotBlank(options.getHeight()) && StrUtils.isNotBlank(options.getWidth()));
return features;
}
for (String t : splitted) {
t = t.replace("${auth_player_name}", lr.getUserName());
t = t.replace("${auth_session}", lr.getSession());
t = t.replace("${auth_uuid}", lr.getUserId());
t = t.replace("${version_name}", options.getVersionName());
t = t.replace("${profile_name}", options.getName());
t = t.replace("${version_type}", options.getType());
t = t.replace("${game_directory}", service.version().getRunDirectory(version.id).getAbsolutePath());
t = t.replace("${game_assets}", game_assets);
t = t.replace("${assets_root}", service.asset().getAssets(version.getAssetsIndex().getId()).getAbsolutePath());
t = t.replace("${auth_access_token}", lr.getAccessToken());
t = t.replace("${user_type}", lr.getUserType());
t = t.replace("${assets_index_name}", version.getAssetsIndex().getId());
t = t.replace("${user_properties}", lr.getUserProperties());
res.add(t);
}
if (res.indexOf("--gameDir") != -1 && res.indexOf("--workDir") != -1) {
res.add("--workDir");
res.add(gameDir.getAbsolutePath());
}
protected Map<String, String> getConfigurations() {
HashMap<String, String> map = new HashMap();
map.put("${auth_player_name}", lr.getUserName());
map.put("${auth_session}", lr.getSession());
map.put("${auth_uuid}", lr.getUserId());
map.put("${version_name}", options.getVersionName());
map.put("${profile_name}", options.getName());
map.put("${version_type}", options.getType());
map.put("${game_directory}", service.version().getRunDirectory(version.id).getAbsolutePath());
map.put("${assets_root}", service.asset().getAssets(version.getAssetsIndex().getId()).getAbsolutePath());
map.put("${auth_access_token}", lr.getAccessToken());
map.put("${user_type}", lr.getUserType());
map.put("${assets_index_name}", version.getAssetsIndex().getId());
map.put("${user_properties}", lr.getUserProperties());
map.put("${resolution_width}", options.getWidth());
map.put("${resolution_height}", options.getHeight());
map.put("${natives_directory}", service.version().getDecompressNativesToLocation(version).getAbsolutePath());
return map;
}
@Override
@@ -112,9 +141,9 @@ public class MinecraftLoader extends AbstractMinecraftLoader {
} catch (IOException e) {
HMCLog.err("Failed to append jvm arguments when searching for asset objects.", e);
}
list.add("-Dminecraft.client.jar=" + version.getJar(service.baseDirectory()).getAbsolutePath());
/*
if (version.logging != null && version.logging.containsKey("client")) {
LoggingInfo logging = version.logging.get("client");
@@ -122,7 +151,7 @@ public class MinecraftLoader extends AbstractMinecraftLoader {
if (file.exists())
list.add(logging.argument.replace("${path}", file.getAbsolutePath()));
}
*/
*/
}
private final IAssetProvider DEFAULT_ASSET_PROVIDER = (t, allow) -> {
@@ -0,0 +1,67 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 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.core.version;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
/**
*
* @author huang
*/
public interface Argument {
/**
* Parse this argument in form: ${key name} or simply a string.
*
* @param keys the parse map
* @param features the map that contains some features such as 'is_demo_user', 'has_custom_resolution'
* @return parsed argument element, empty if this argument is ignored and will not be added.
*/
List<String> toString(Map<String, String> keys, Map<String, Boolean> features);
public static class ArgumentSerializer implements JsonDeserializer<Argument>, JsonSerializer<Argument> {
@Override
public Argument deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json.isJsonPrimitive())
return new StringArgument(json.getAsString());
else
return context.deserialize(json, RuledArgument.class);
}
@Override
public JsonElement serialize(Argument src, Type typeOfSrc, JsonSerializationContext context) {
if (src instanceof StringArgument)
return new JsonPrimitive(((StringArgument) src).argument);
else if (src instanceof RuledArgument)
return context.serialize(src, RuledArgument.class);
else
throw new AssertionError("Unrecognized argument type: " + src);
}
}
}
@@ -0,0 +1,69 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 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.core.version;
import com.google.gson.annotations.SerializedName;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.jackhuang.hmcl.util.CollectionUtils;
/**
*
* @author huang
*/
public class Arguments {
@SerializedName("game")
public List<Argument> game;
@SerializedName("jvm")
public List<Argument> jvm;
public static List<String> parseStringArguments(List<String> arguments, Map<String, String> keys) {
return CollectionUtils.map(arguments, str -> keys.getOrDefault(str, str));
}
public static List<String> parseArguments(List<Argument> arguments, Map<String, String> keys) {
return parseArguments(arguments, keys, Collections.EMPTY_MAP);
}
public static List<String> parseArguments(List<Argument> arguments, Map<String, String> keys, Map<String, Boolean> features) {
return CollectionUtils.flatMap(arguments, arg -> arg.toString(keys, features));
}
public static final List<Argument> DEFAULT_JVM_ARGUMENTS;
public static final List<Argument> DEFAULT_GAME_ARGUMENTS;
static {
List<Argument> jvm = new LinkedList<>();
jvm.add(new RuledArgument(Collections.singletonList(new Rules("allow", new OSRestriction("osx"))), Collections.singletonList("-XstartOnFirstThread")));
jvm.add(new RuledArgument(Collections.singletonList(new Rules("allow", new OSRestriction("windows"))), Collections.singletonList("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump")));
jvm.add(new RuledArgument(Collections.singletonList(new Rules("allow", new OSRestriction("windows", "^10\\."))), Arrays.asList("-Dos.name=Windows 10", "-Dos.version=10.0")));
jvm.add(new StringArgument("-Djava.library.path=${natives_directory}"));
jvm.add(new StringArgument("-Dminecraft.launcher.brand=${launcher_name}"));
jvm.add(new StringArgument("-Dminecraft.launcher.version=${launcher_version}"));
jvm.add(new StringArgument("-cp"));
jvm.add(new StringArgument("${classpath}"));
DEFAULT_JVM_ARGUMENTS = Collections.unmodifiableList(jvm);
List<Argument> game = new LinkedList<>();
game.add(new RuledArgument(Collections.singletonList(new Rules("allow", Collections.singletonMap("has_custom_resolution", true))), Arrays.asList("--width", "${resolution_width}", "--height", "${resolution_height}")));
DEFAULT_GAME_ARGUMENTS = Collections.unmodifiableList(game);
}
}
@@ -54,16 +54,7 @@ public class MinecraftLibrary extends AbstractMinecraftLibrary {
*/
@Override
public boolean allow() {
if (rules != null) {
boolean flag = false;
for (Rules r : rules)
if ("disallow".equals(r.action()))
return false;
else if ("allow".equals(r.action()))
flag = true;
return flag;
} else
return true;
return Rules.allow(rules);
}
private String formatArch(String nati) {
@@ -43,6 +43,8 @@ public class MinecraftVersion implements Cloneable, Comparable<MinecraftVersion>
@SerializedName("minecraftArguments")
public String minecraftArguments;
@SerializedName("arguments")
public Arguments arguments;
@SerializedName("mainClass")
public String mainClass;
@SerializedName("time")
@@ -151,16 +153,16 @@ public class MinecraftVersion implements Cloneable, Comparable<MinecraftVersion>
}
parent = parent.resolve(provider, resolvedSoFar);
MinecraftVersion result = new MinecraftVersion(
this.minecraftArguments != null ? this.minecraftArguments : parent.minecraftArguments,
this.mainClass != null ? this.mainClass : parent.mainClass,
this.time, this.id, this.type, parent.processArguments, this.releaseTime,
this.assets != null ? this.assets : parent.assets,
this.jar != null ? this.jar : parent.jar,
null, this.runDir, parent.minimumLauncherVersion,
this.libraries != null ? ArrayUtils.merge(this.libraries, parent.libraries) : parent.libraries, this.hidden,
this.downloads != null ? this.downloads : parent.downloads,
this.assetIndex != null ? this.assetIndex : parent.assetIndex,
this.logging != null ? this.logging : parent.logging);
this.minecraftArguments != null ? this.minecraftArguments : parent.minecraftArguments,
this.mainClass != null ? this.mainClass : parent.mainClass,
this.time, this.id, this.type, parent.processArguments, this.releaseTime,
this.assets != null ? this.assets : parent.assets,
this.jar != null ? this.jar : parent.jar,
null, this.runDir, parent.minimumLauncherVersion,
this.libraries != null ? ArrayUtils.merge(this.libraries, parent.libraries) : parent.libraries, this.hidden,
this.downloads != null ? this.downloads : parent.downloads,
this.assetIndex != null ? this.assetIndex : parent.assetIndex,
this.logging != null ? this.logging : parent.logging);
return result;
}
@@ -203,7 +205,7 @@ public class MinecraftVersion implements Cloneable, Comparable<MinecraftVersion>
return false;
return Objects.equals(this.id, ((MinecraftVersion) obj).id);
}
public AssetIndexDownloadInfo getAssetsIndex() {
if (assetIndex == null)
assetIndex = new AssetIndexDownloadInfo(assets == null ? AssetsIndex.DEFAULT_ASSET_NAME : assets);
@@ -18,7 +18,8 @@
package org.jackhuang.hmcl.core.version;
import com.google.gson.annotations.SerializedName;
import org.jackhuang.hmcl.util.StrUtils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jackhuang.hmcl.util.sys.OS;
/**
@@ -31,6 +32,26 @@ public class OSRestriction {
private String version;
@SerializedName("name")
public String name;
@SerializedName("arch")
public String arch;
public OSRestriction() {
this(null);
}
public OSRestriction(String name) {
this(name, null);
}
public OSRestriction(String name, String version) {
this(name, version, null);
}
public OSRestriction(String name, String version, String arch) {
this.name = name;
this.version = version;
this.arch = arch;
}
public String getVersion() {
return version;
@@ -49,6 +70,24 @@ public class OSRestriction {
}
public boolean isCurrentOS() {
return StrUtils.isBlank(getName()) || OS.os().name().equalsIgnoreCase(getName());
if (name != null && !OS.os().name().equalsIgnoreCase(name))
return false;
if (version != null) {
try {
Pattern pattern = Pattern.compile(version);
Matcher matcher = pattern.matcher(System.getProperty("os.version"));
if (!matcher.matches())
return false;
} catch (Throwable t) {}
}
if (arch != null) {
try {
Pattern pattern = Pattern.compile(arch);
Matcher matcher = pattern.matcher(System.getProperty("os.arch"));
if (!matcher.matches())
return false;
} catch (Throwable t) {}
}
return true;
}
}
@@ -0,0 +1,81 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 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.core.version;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.jackhuang.hmcl.util.CollectionUtils;
/**
*
* @author huang
*/
public class RuledArgument implements Argument {
public List<Rules> rules;
public List<String> value;
public RuledArgument() {
}
public RuledArgument(List<Rules> rules, List<String> args) {
this.rules = rules;
this.value = args;
}
@Override
public List<String> toString(Map<String, String> keys, Map<String, Boolean> features) {
if (!Rules.allow(rules, features))
return Collections.EMPTY_LIST;
else
return CollectionUtils.map(value, a -> new StringArgument(a).toString(keys, features).get(0));
}
public static class RuledArgumentSerializer implements JsonSerializer<RuledArgument>, JsonDeserializer<RuledArgument> {
@Override
public JsonElement serialize(RuledArgument src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject obj = new JsonObject();
obj.add("rules", context.serialize(src.rules));
obj.add("value", context.serialize(src.value));
return obj;
}
@Override
public RuledArgument deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject obj = json.getAsJsonObject();
RuledArgument a = new RuledArgument();
a.rules = context.deserialize(obj.get("rules"), new TypeToken<List<Rules>>(){}.getType());
if (obj.get("value").isJsonPrimitive())
a.value = Collections.singletonList(obj.get("value").getAsString());
else
a.value = context.<List<String>>deserialize(obj.get("value"), new TypeToken<List<String>>(){}.getType());
return a;
}
}
}
@@ -18,6 +18,9 @@
package org.jackhuang.hmcl.core.version;
import com.google.gson.annotations.SerializedName;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
/**
*
@@ -29,12 +32,50 @@ public class Rules {
private String action;
@SerializedName("os")
private OSRestriction os;
@SerializedName("features")
private Map<String, Boolean> features;
public Rules() {
}
public Rules(String action, OSRestriction os) {
this.action = action;
this.os = os;
}
public Rules(String action, Map<String, Boolean> features) {
this.action = action;
this.features = features;
}
public String action() {
return os == null || os.isCurrentOS() ? action : null;
public String action(Map<String, Boolean> features) {
if (os != null && !os.isCurrentOS()) return null;
if (this.features != null) {
for (Map.Entry<String, Boolean> entry : this.features.entrySet())
if (!features.containsKey(entry.getKey()))
return null;
else
if (!features.get(entry.getKey()).equals(entry.getValue()))
return null;
}
return action;
}
public static boolean allow(Collection<Rules> c) {
return allow(c, Collections.EMPTY_MAP);
}
public static boolean allow(Collection<Rules> c, Map<String, Boolean> features) {
if (c != null) {
boolean flag = false;
for (Rules r : c)
if ("disallow".equals(r.action(features)))
return false;
else if ("allow".equals(r.action(features)))
flag = true;
return flag;
} else
return true;
}
}
@@ -0,0 +1,50 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 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.core.version;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
* @author huang
*/
public class StringArgument implements Argument {
public String argument;
public StringArgument(String argument) {
this.argument = argument;
}
@Override
public List<String> toString(Map<String, String> keys, Map<String, Boolean> features) {
String res = argument;
Pattern pattern = Pattern.compile("\\$\\{(.*?)\\}");
Matcher m = pattern.matcher(argument);
while (m.find()) {
String entry = m.group();
res = res.replace(entry, keys.getOrDefault(entry, entry));
}
return Collections.singletonList(res);
}
}
@@ -20,6 +20,8 @@ package org.jackhuang.hmcl.util;
import org.jackhuang.hmcl.util.lang.SupportedLocales;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.jackhuang.hmcl.core.version.Argument;
import org.jackhuang.hmcl.core.version.RuledArgument;
/**
*
@@ -27,7 +29,10 @@ import com.google.gson.GsonBuilder;
*/
public final class C {
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public static final Gson GSON = new GsonBuilder()
.registerTypeAdapter(RuledArgument.class, new RuledArgument.RuledArgumentSerializer())
.registerTypeAdapter(Argument.class, new Argument.ArgumentSerializer())
.setPrettyPrinting().create();
//http://repo1.maven.org/maven2
public static final String URL_PUBLISH = "http://www.mcbbs.net/thread-142335-1-1.html";
@@ -35,7 +40,7 @@ public final class C {
public static final String URL_FORGE_LIST = "http://files.minecraftforge.net/maven/net/minecraftforge/forge/json";
public static final String URL_LITELOADER_LIST = "http://dl.liteloader.com/versions/versions.json";
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
private C() {
@@ -21,6 +21,8 @@ import org.jackhuang.hmcl.api.func.Predicate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.jackhuang.hmcl.api.func.Function;
/**
*
@@ -31,7 +33,7 @@ public final class CollectionUtils {
private CollectionUtils() {
}
public static <T> ArrayList<T> filter(Collection<T> coll, Predicate<T> p) {
public static <T> List<T> filter(Collection<T> coll, Predicate<T> p) {
ArrayList<T> newColl = new ArrayList<>();
for (T t : coll)
if (p.apply(t))
@@ -39,6 +41,20 @@ public final class CollectionUtils {
return newColl;
}
public static <U, V> List<V> map(Collection<U> coll, Function<U, V> p) {
ArrayList<V> newColl = new ArrayList<>(coll.size());
for (U t : coll)
newColl.add(p.apply(t));
return newColl;
}
public static <U, V> List<V> flatMap(Collection<U> coll, Function<U, Collection<V>> p) {
ArrayList<V> newColl = new ArrayList<>(coll.size());
for (U t : coll)
newColl.addAll(p.apply(t));
return newColl;
}
public static <T> boolean removeIf(Collection<T> coll, Predicate<T> p) {
boolean removed = false;
final Iterator<T> each = coll.iterator();
@@ -154,8 +154,11 @@ public final class StrUtils {
return sb.toString();
}
public static String[] tokenize(String paramString1) {
return tokenize(paramString1, " \t\n\r\f");
public static String[] tokenize(String str) {
if (str == null)
return new String[0];
else
return tokenize(str, " \t\n\r\f");
}
public static String[] tokenize(String str, String delim) {
+1 -1
View File
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
rootProject.name = 'Hello Minecraft!'
rootProject.name = 'Hello Minecraft'
// Find the directories containing a "build.gradle" file in the root directory
// of the project. That is, every directory containing a "build.gradle" will