diff --git a/creator-tools/src/main/java/com/skcraft/launcher/creator/server/TestServerBuilder.java b/creator-tools/src/main/java/com/skcraft/launcher/creator/server/TestServerBuilder.java index d8ad19d..2a02ad4 100644 --- a/creator-tools/src/main/java/com/skcraft/launcher/creator/server/TestServerBuilder.java +++ b/creator-tools/src/main/java/com/skcraft/launcher/creator/server/TestServerBuilder.java @@ -11,6 +11,7 @@ import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandlerCollection; +import org.eclipse.jetty.server.handler.ErrorHandler; import org.eclipse.jetty.server.handler.ResourceHandler; import org.eclipse.jetty.server.handler.gzip.GzipHandler; @@ -72,6 +73,8 @@ public class TestServerBuilder { server.setHandler(gzip); gzip.setHandler(contexts); + server.addBean(new ErrorHandler()); + return new TestServer(server); } diff --git a/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java b/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java index 1340cc0..85c816c 100644 --- a/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java +++ b/launcher-builder/src/main/java/com/skcraft/launcher/builder/PackageBuilder.java @@ -12,8 +12,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; -import com.google.common.base.Joiner; -import com.google.common.base.Strings; +import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.io.ByteStreams; import com.google.common.io.CharStreams; @@ -25,10 +24,7 @@ import com.skcraft.launcher.model.loader.InstallProfile; import com.skcraft.launcher.model.loader.LoaderManifest; import com.skcraft.launcher.model.loader.SidedData; import com.skcraft.launcher.model.loader.VersionInfo; -import com.skcraft.launcher.model.minecraft.Library; -import com.skcraft.launcher.model.minecraft.ReleaseList; -import com.skcraft.launcher.model.minecraft.Version; -import com.skcraft.launcher.model.minecraft.VersionManifest; +import com.skcraft.launcher.model.minecraft.*; import com.skcraft.launcher.model.modpack.DownloadableFile; import com.skcraft.launcher.model.modpack.Manifest; import com.skcraft.launcher.util.Environment; @@ -75,6 +71,7 @@ public class PackageBuilder { private File baseDir; private List loaderLibraries = Lists.newArrayList(); + private List installerLibraries = Lists.newArrayList(); private List mavenRepos; private List jarMavens = Lists.newArrayList(); @@ -176,12 +173,9 @@ public class PackageBuilder { } // Copy tweak class arguments - List gameArguments = info.getMinecraftArguments().getGameArguments(); + List gameArguments = info.getMinecraftArguments().getGameArguments(); if (gameArguments != null) { - String args = Joiner.on(' ').join(gameArguments); - String existingArgs = Strings.nullToEmpty(version.getMinecraftArguments()); - - version.setMinecraftArguments(Joiner.on(' ').join(existingArgs, args)); + version.getArguments().getGameArguments().addAll(gameArguments); } // Add libraries @@ -213,7 +207,7 @@ public class PackageBuilder { InstallProfile profile = mapper.readValue(data, InstallProfile.class); // Import the libraries for the installer - loaderLibraries.addAll(profile.getLibraries()); + installerLibraries.addAll(profile.getLibraries()); // Extract the data files List extraFiles = Lists.newArrayList(); @@ -243,7 +237,7 @@ public class PackageBuilder { profile.getData().put("SIDE", SidedData.create("client", "server")); // Add loader manifest to the map - manifest.getLoaders().put(loaderName, new LoaderManifest(profile.getData(), extraFiles)); + manifest.getLoaders().put(loaderName, new LoaderManifest(profile.getLibraries(), profile.getData(), extraFiles)); // Add processors manifest.getTasks().addAll(profile.toProcessorEntries(loaderName)); @@ -266,7 +260,7 @@ public class PackageBuilder { // TODO: Download libraries for different environments -- As of writing, this is not an issue Environment env = Environment.getInstance(); - for (Library library : loaderLibraries) { + for (Library library : Iterables.concat(loaderLibraries, installerLibraries)) { Library.Artifact artifact = library.getArtifact(env); File outputPath = new File(librariesDir, artifact.getPath()); diff --git a/launcher/src/main/java/com/skcraft/launcher/Launcher.java b/launcher/src/main/java/com/skcraft/launcher/Launcher.java index 8b8acca..6b07154 100644 --- a/launcher/src/main/java/com/skcraft/launcher/Launcher.java +++ b/launcher/src/main/java/com/skcraft/launcher/Launcher.java @@ -137,6 +137,15 @@ public final class Launcher { } } + /** + * Get the launcher title. + * + * @return The launcher title. + */ + public String getTitle() { + return tr("launcher.appTitle"); + } + /** * Get the launcher version. * diff --git a/launcher/src/main/java/com/skcraft/launcher/install/ProcessorTask.java b/launcher/src/main/java/com/skcraft/launcher/install/ProcessorTask.java index 0cc89b1..d53795c 100644 --- a/launcher/src/main/java/com/skcraft/launcher/install/ProcessorTask.java +++ b/launcher/src/main/java/com/skcraft/launcher/install/ProcessorTask.java @@ -52,7 +52,7 @@ public class ProcessorTask implements InstallTask { Map outputs = processor.resolveOutputs(resolver); message = "Finding libraries"; - Library execFile = versionManifest.findLibrary(processor.getJar()); + Library execFile = loaderManifest.findLibrary(processor.getJar()); File jar = launcher.getLibraryFile(execFile); JarFile jarFile = new JarFile(jar); @@ -68,7 +68,7 @@ public class ProcessorTask implements InstallTask { int total = processor.getClasspath().size(); for (String libraryName : processor.getClasspath()) { message = "Adding library " + libraryName; - File libraryFile = launcher.getLibraryFile(versionManifest.findLibrary(libraryName)); + File libraryFile = launcher.getLibraryFile(loaderManifest.findLibrary(libraryName)); if (!libraryFile.exists()) { throw new RuntimeException(String.format("Missing library '%s' for processor '%s'", libraryName, processor.getJar())); diff --git a/launcher/src/main/java/com/skcraft/launcher/launch/JavaProcessBuilder.java b/launcher/src/main/java/com/skcraft/launcher/launch/JavaProcessBuilder.java index 726cdbf..dbdaba0 100644 --- a/launcher/src/main/java/com/skcraft/launcher/launch/JavaProcessBuilder.java +++ b/launcher/src/main/java/com/skcraft/launcher/launch/JavaProcessBuilder.java @@ -106,9 +106,6 @@ public class JavaProcessBuilder { command.add("-XX:MaxPermSize=" + String.valueOf(permGen) + "M"); } - command.add("-cp"); - command.add(buildClassPath()); - command.add(mainClass); for (String arg : args) { diff --git a/launcher/src/main/java/com/skcraft/launcher/launch/Runner.java b/launcher/src/main/java/com/skcraft/launcher/launch/Runner.java index 7ffe672..0b40dd7 100644 --- a/launcher/src/main/java/com/skcraft/launcher/launch/Runner.java +++ b/launcher/src/main/java/com/skcraft/launcher/launch/Runner.java @@ -15,9 +15,7 @@ import com.skcraft.concurrency.ProgressObservable; import com.skcraft.launcher.*; import com.skcraft.launcher.auth.Session; import com.skcraft.launcher.install.ZipExtract; -import com.skcraft.launcher.model.minecraft.AssetsIndex; -import com.skcraft.launcher.model.minecraft.Library; -import com.skcraft.launcher.model.minecraft.VersionManifest; +import com.skcraft.launcher.model.minecraft.*; import com.skcraft.launcher.persistence.Persistence; import com.skcraft.launcher.util.Environment; import com.skcraft.launcher.util.Platform; @@ -60,6 +58,7 @@ public class Runner implements Callable, ProgressObservable { private Configuration config; private JavaProcessBuilder builder; private AssetsRoot assetsRoot; + private FeatureList.Mutable featureList; /** * Create a new instance launcher. @@ -75,6 +74,7 @@ public class Runner implements Callable, ProgressObservable { this.instance = instance; this.session = session; this.extractDir = extractDir; + this.featureList = new FeatureList.Mutable(); } /** @@ -132,12 +132,12 @@ public class Runner implements Callable, ProgressObservable { progress = new DefaultProgress(0.9, SharedLocale.tr("runner.collectingArgs")); - addJvmArgs(); + addWindowArgs(); addLibraries(); + addJvmArgs(); addJarArgs(); addProxyArgs(); addServerArgs(); - addWindowArgs(); addPlatformArgs(); addLegacyArgs(); @@ -175,11 +175,6 @@ public class Runner implements Callable, ProgressObservable { builder.getFlags().add("-Xdock:name=Minecraft"); } } - - // Windows arguments - if (getEnvironment().getPlatform() == Platform.WINDOWS) { - builder.getFlags().add("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump"); - } } /** @@ -210,8 +205,6 @@ public class Runner implements Callable, ProgressObservable { tr("runner.missingLibrary", instance.getTitle(), library.getName())); } } - - builder.getFlags().add("-Djava.library.path=" + extractDir.getAbsoluteFile()); } /** @@ -253,14 +246,22 @@ public class Runner implements Callable, ProgressObservable { builder.tryJvmPath(new File(rawJvmPath)); } + List flags = builder.getFlags(); String rawJvmArgs = config.getJvmArgs(); if (!Strings.isNullOrEmpty(rawJvmArgs)) { - List flags = builder.getFlags(); for (String arg : JavaProcessBuilder.splitArgs(rawJvmArgs)) { flags.add(arg); } } + + List javaArguments = versionManifest.getArguments().getJvmArguments(); + StrSubstitutor substitutor = new StrSubstitutor(getCommandSubstitutions()); + for (GameArgument arg : javaArguments) { + if (arg.resolveRules(environment, featureList)) { + flags.add(substitutor.replace(arg.getJoinedValue())); + } + } } /** @@ -271,10 +272,12 @@ public class Runner implements Callable, ProgressObservable { private void addJarArgs() throws JsonProcessingException { List args = builder.getArgs(); - String[] rawArgs = versionManifest.getMinecraftArguments().split(" +"); + List rawArgs = versionManifest.getArguments().getGameArguments(); StrSubstitutor substitutor = new StrSubstitutor(getCommandSubstitutions()); - for (String arg : rawArgs) { - args.add(substitutor.replace(arg)); + for (GameArgument arg : rawArgs) { + if (arg.resolveRules(environment, featureList)) { + args.add(substitutor.replace(arg.getJoinedValue())); + } } } @@ -329,15 +332,10 @@ public class Runner implements Callable, ProgressObservable { * Add window arguments. */ private void addWindowArgs() { - List args = builder.getArgs(); int width = config.getWindowWidth(); - int height = config.getWidowHeight(); if (width >= 10) { - args.add("--width"); - args.add(String.valueOf(width)); - args.add("--height"); - args.add(String.valueOf(height)); + featureList.addFeature("has_custom_resolution", true); } } @@ -373,6 +371,14 @@ public class Runner implements Callable, ProgressObservable { map.put("assets_root", launcher.getAssets().getDir().getAbsolutePath()); map.put("assets_index_name", versionManifest.getAssetId()); + map.put("resolution_width", String.valueOf(config.getWindowWidth())); + map.put("resolution_height", String.valueOf(config.getWidowHeight())); + + map.put("launcher_name", launcher.getTitle()); + map.put("launcher_version", launcher.getVersion()); + map.put("classpath", builder.buildClassPath()); + map.put("natives_directory", extractDir.getAbsolutePath()); + return map; } diff --git a/launcher/src/main/java/com/skcraft/launcher/model/loader/LoaderManifest.java b/launcher/src/main/java/com/skcraft/launcher/model/loader/LoaderManifest.java index d565c8f..9c53586 100644 --- a/launcher/src/main/java/com/skcraft/launcher/model/loader/LoaderManifest.java +++ b/launcher/src/main/java/com/skcraft/launcher/model/loader/LoaderManifest.java @@ -1,5 +1,6 @@ package com.skcraft.launcher.model.loader; +import com.skcraft.launcher.model.minecraft.Library; import com.skcraft.launcher.model.modpack.DownloadableFile; import lombok.AllArgsConstructor; import lombok.Data; @@ -12,6 +13,17 @@ import java.util.Map; @AllArgsConstructor @NoArgsConstructor public class LoaderManifest { + private List libraries; private Map sidedData; private List downloadableFiles; + + public Library findLibrary(String name) { + for (Library library : getLibraries()) { + if (library.getName().equals(name)) { + return library; + } + } + + return null; + } } diff --git a/launcher/src/main/java/com/skcraft/launcher/model/loader/LoaderSubResolver.java b/launcher/src/main/java/com/skcraft/launcher/model/loader/LoaderSubResolver.java index ed16f31..27072dc 100644 --- a/launcher/src/main/java/com/skcraft/launcher/model/loader/LoaderSubResolver.java +++ b/launcher/src/main/java/com/skcraft/launcher/model/loader/LoaderSubResolver.java @@ -2,7 +2,6 @@ package com.skcraft.launcher.model.loader; import com.skcraft.launcher.model.minecraft.Library; import com.skcraft.launcher.model.minecraft.Side; -import com.skcraft.launcher.model.minecraft.VersionManifest; import com.skcraft.launcher.model.modpack.DownloadableFile; import com.skcraft.launcher.model.modpack.Manifest; import com.skcraft.launcher.util.Environment; @@ -30,8 +29,6 @@ public class LoaderSubResolver { } public String transform(String arg) { - VersionManifest version = manifest.getVersionManifest(); - while (true) { char start = arg.charAt(0); int bound = arg.length() - 1; @@ -44,7 +41,7 @@ public class LoaderSubResolver { } } else if (start == '[' && end == ']') { String libraryName = arg.substring(1, bound); - Library library = version.findLibrary(libraryName); + Library library = loader.findLibrary(libraryName); if (library != null) { arg = getPathOf(manifest.getLibrariesLocation(), library.getPath(env)); } else { diff --git a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/FeatureList.java b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/FeatureList.java new file mode 100644 index 0000000..9e0adbb --- /dev/null +++ b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/FeatureList.java @@ -0,0 +1,32 @@ +package com.skcraft.launcher.model.minecraft; + +import com.google.common.collect.Maps; +import lombok.NoArgsConstructor; + +import java.util.Map; + +/** + * List of enabled features for Minecraft feature rules. + */ +@NoArgsConstructor +public class FeatureList { + protected Map features = Maps.newHashMap(); + + public boolean doesMatch(Map features) { + for (Map.Entry entry : features.entrySet()) { + if (!entry.getValue().equals(this.features.get(entry.getKey()))) { + return false; + } + } + + return true; + } + + public static class Mutable extends FeatureList { + public void addFeature(String key, boolean value) { + features.put(key, value); + } + } + + public static final FeatureList EMPTY = new FeatureList(); +} diff --git a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/GameArgument.java b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/GameArgument.java new file mode 100644 index 0000000..9f52c4b --- /dev/null +++ b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/GameArgument.java @@ -0,0 +1,51 @@ +package com.skcraft.launcher.model.minecraft; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.common.base.Joiner; +import com.google.common.collect.Lists; +import com.skcraft.launcher.model.minecraft.mapper.ArgumentValueDeserializer; +import com.skcraft.launcher.util.Environment; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +@NoArgsConstructor +public class GameArgument { + @JsonProperty("value") + @JsonDeserialize(using = ArgumentValueDeserializer.class) + private List values; + private List rules; + + public GameArgument(List values) { + this.values = values; + } + + public GameArgument(String value) { + this.values = Lists.newArrayList(value); + } + + @JsonIgnore + public String getJoinedValue() { + return Joiner.on(' ').join(values); + } + + public boolean resolveRules(Environment environment, FeatureList featureList) { + if (getRules() == null) return true; + + boolean result = false; + + for (Rule rule : rules) { + if (rule.matches(environment, featureList)) { + result = rule.isAllowed(); + } + } + + return result; + } +} diff --git a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Library.java b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Library.java index 363b226..9a039f6 100644 --- a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Library.java +++ b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Library.java @@ -6,12 +6,7 @@ package com.skcraft.launcher.model.minecraft; -import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonValue; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.skcraft.launcher.util.Environment; @@ -20,7 +15,6 @@ import lombok.Data; import java.util.List; import java.util.Map; -import java.util.regex.Pattern; @Data @JsonIgnoreProperties(ignoreUnknown = true) @@ -43,8 +37,8 @@ public class Library { if (getRules() != null) { for (Rule rule : getRules()) { - if (rule.matches(environment)) { - allow = rule.getAction() == Action.ALLOW; + if (rule.matches(environment, FeatureList.EMPTY)) { + allow = rule.isAllowed(); } } } else { @@ -95,6 +89,10 @@ public class Library { if (name != null ? !name.equals(library.name) : library.name != null) return false; + // If libraries have different natives lists, they should be separate. + if (natives != null ? !natives.equals(library.natives) : library.natives != null) + return false; + return true; } @@ -103,38 +101,6 @@ public class Library { return name != null ? name.hashCode() : 0; } - @Data - public static class Rule { - private Action action; - private OS os; - - public boolean matches(Environment environment) { - if (getOs() == null) { - return true; - } else { - return getOs().matches(environment); - } - } - } - - @Data - public static class OS { - private Platform platform; - private Pattern version; - - @JsonProperty("name") - @JsonDeserialize(using = PlatformDeserializer.class) - @JsonSerialize(using = PlatformSerializer.class) - public Platform getPlatform() { - return platform; - } - - public boolean matches(Environment environment) { - return (getPlatform() == null || getPlatform().equals(environment.getPlatform())) && - (getVersion() == null || getVersion().matcher(environment.getPlatformVersion()).matches()); - } - } - @Data public static class Extract { private List exclude; @@ -155,21 +121,6 @@ public class Library { private Map classifiers; } - private enum Action { - ALLOW, - DISALLOW; - - @JsonCreator - public static Action fromJson(String text) { - return valueOf(text.toUpperCase()); - } - - @JsonValue - public String toJson() { - return name().toLowerCase(); - } - } - public static String mavenNameToPath(String mavenName) { List split = Splitter.on(':').splitToList(mavenName); int size = split.size(); diff --git a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/MinecraftArguments.java b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/MinecraftArguments.java index ad5bf34..5a5ba50 100644 --- a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/MinecraftArguments.java +++ b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/MinecraftArguments.java @@ -2,6 +2,9 @@ package com.skcraft.launcher.model.minecraft; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.skcraft.launcher.model.minecraft.mapper.MinecraftArgumentsDeserializer; import lombok.Data; import java.util.List; @@ -10,6 +13,13 @@ import java.util.List; @JsonIgnoreProperties(ignoreUnknown = true) public class MinecraftArguments { @JsonProperty("game") - private List gameArguments; + @JsonTypeInfo(use = JsonTypeInfo.Id.NONE) + @JsonDeserialize(contentUsing = MinecraftArgumentsDeserializer.class) + private List gameArguments; + + @JsonProperty("jvm") + @JsonTypeInfo(use = JsonTypeInfo.Id.NONE) + @JsonDeserialize(contentUsing = MinecraftArgumentsDeserializer.class) + private List jvmArguments; } diff --git a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Rule.java b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Rule.java new file mode 100644 index 0000000..097292f --- /dev/null +++ b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Rule.java @@ -0,0 +1,77 @@ +package com.skcraft.launcher.model.minecraft; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.skcraft.launcher.model.minecraft.mapper.PlatformDeserializer; +import com.skcraft.launcher.model.minecraft.mapper.PlatformSerializer; +import com.skcraft.launcher.util.Environment; +import com.skcraft.launcher.util.Platform; +import lombok.Data; + +import java.util.Map; +import java.util.regex.Pattern; + +@Data +public class Rule { + private Action action; + private OS os; + private Map features; + + private boolean doesOsMatch(Environment environment) { + if (getOs() == null) { + return true; + } else { + return getOs().matches(environment); + } + } + + private boolean doFeaturesMatch(FeatureList match) { + if (getFeatures() == null) return true; + + return match.doesMatch(features); + } + + public boolean matches(Environment environment, FeatureList match) { + return doesOsMatch(environment) && doFeaturesMatch(match); + } + + @JsonIgnore + public boolean isAllowed() { + return action == Action.ALLOW; + } + + @Data + @JsonIgnoreProperties(ignoreUnknown = true) + public static class OS { + private Platform platform; + private Pattern version; + + @JsonProperty("name") + @JsonDeserialize(using = PlatformDeserializer.class) + @JsonSerialize(using = PlatformSerializer.class) + public Platform getPlatform() { + return platform; + } + + public boolean matches(Environment environment) { + return (getPlatform() == null || getPlatform().equals(environment.getPlatform())) && + (getVersion() == null || getVersion().matcher(environment.getPlatformVersion()).matches()); + } + } + + public enum Action { + ALLOW, + DISALLOW; + + @JsonCreator + public static Action fromJson(String text) { + return valueOf(text.toUpperCase()); + } + + @JsonValue + public String toJson() { + return name().toLowerCase(); + } + } +} diff --git a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/VersionManifest.java b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/VersionManifest.java index 6fc8384..95aedb2 100644 --- a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/VersionManifest.java +++ b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/VersionManifest.java @@ -8,6 +8,7 @@ package com.skcraft.launcher.model.minecraft; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.base.Splitter; import lombok.Data; import java.util.Date; @@ -25,8 +26,7 @@ public class VersionManifest { private String assets; private AssetIndex assetIndex; private String type; - private String processArguments; - private String minecraftArguments; + private MinecraftArguments arguments; private String mainClass; private int minimumLauncherVersion; private LinkedHashSet libraries; @@ -48,6 +48,15 @@ public class VersionManifest { return null; } + public void setMinecraftArguments(String minecraftArguments) { + for (String arg : Splitter.on(' ').split(minecraftArguments)) { + this.arguments.getGameArguments().add(new GameArgument(arg)); + } + + // TODO: Possibly do some cheaty side-effects here to add parameters missing from early game versions. + // Either that or use a proper version adapter. + } + @Data @JsonIgnoreProperties(ignoreUnknown = true) public static class Artifact { diff --git a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/ArgumentValueDeserializer.java b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/ArgumentValueDeserializer.java new file mode 100644 index 0000000..64f218e --- /dev/null +++ b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/ArgumentValueDeserializer.java @@ -0,0 +1,35 @@ +package com.skcraft.launcher.model.minecraft.mapper; + +import com.beust.jcommander.internal.Lists; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.exc.InvalidFormatException; +import com.fasterxml.jackson.databind.type.TypeFactory; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +public class ArgumentValueDeserializer extends StdDeserializer> { + protected ArgumentValueDeserializer() { + super(TypeFactory.defaultInstance().constructCollectionType(List.class, String.class)); + } + + @Override + public List deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + if (!jp.hasCurrentToken()) jp.nextToken(); + + if (jp.getCurrentToken() == JsonToken.START_ARRAY) { + String[] allValues = jp.readValueAs(String[].class); + return Arrays.asList(allValues); + } else if (jp.getCurrentToken() == JsonToken.VALUE_STRING) { + String value = jp.readValueAs(String.class); + return Lists.newArrayList(value); + } + + throw new InvalidFormatException("Invalid JSON type for deserializer (not string or array)", null, List.class); + } +} diff --git a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/MinecraftArgumentsDeserializer.java b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/MinecraftArgumentsDeserializer.java new file mode 100644 index 0000000..a6436a2 --- /dev/null +++ b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/MinecraftArgumentsDeserializer.java @@ -0,0 +1,31 @@ +package com.skcraft.launcher.model.minecraft.mapper; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.exc.InvalidFormatException; +import com.skcraft.launcher.model.minecraft.GameArgument; + +import java.io.IOException; + +public class MinecraftArgumentsDeserializer extends StdDeserializer { + protected MinecraftArgumentsDeserializer() { + super(GameArgument.class); + } + + @Override + public GameArgument deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + if (!jp.hasCurrentToken()) jp.nextToken(); + + if (jp.getCurrentToken() == JsonToken.START_OBJECT) { + return jp.readValueAs(GameArgument.class); + } else if (jp.getCurrentToken() == JsonToken.VALUE_STRING) { + String argument = jp.getValueAsString(); + return new GameArgument(argument); + } + + throw new InvalidFormatException("Invalid JSON type for deserializer (not string or object)", null, GameArgument.class); + } +} diff --git a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/PlatformDeserializer.java b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/PlatformDeserializer.java similarity index 95% rename from launcher/src/main/java/com/skcraft/launcher/model/minecraft/PlatformDeserializer.java rename to launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/PlatformDeserializer.java index 5eb8a51..6fd9dc7 100644 --- a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/PlatformDeserializer.java +++ b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/PlatformDeserializer.java @@ -4,7 +4,7 @@ * Please see LICENSE.txt for license information. */ -package com.skcraft.launcher.model.minecraft; +package com.skcraft.launcher.model.minecraft.mapper; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; diff --git a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/PlatformSerializer.java b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/PlatformSerializer.java similarity index 95% rename from launcher/src/main/java/com/skcraft/launcher/model/minecraft/PlatformSerializer.java rename to launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/PlatformSerializer.java index 91a44b1..d703734 100644 --- a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/PlatformSerializer.java +++ b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/mapper/PlatformSerializer.java @@ -4,7 +4,7 @@ * Please see LICENSE.txt for license information. */ -package com.skcraft.launcher.model.minecraft; +package com.skcraft.launcher.model.minecraft.mapper; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; diff --git a/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java b/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java index da923da..2af4d07 100644 --- a/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java +++ b/launcher/src/main/java/com/skcraft/launcher/update/BaseUpdater.java @@ -7,6 +7,7 @@ package com.skcraft.launcher.update; import com.google.common.base.Strings; +import com.google.common.collect.Iterables; import com.skcraft.launcher.AssetsRoot; import com.skcraft.launcher.Instance; import com.skcraft.launcher.Launcher; @@ -14,6 +15,7 @@ import com.skcraft.launcher.LauncherException; import com.skcraft.launcher.dialog.FeatureSelectionDialog; import com.skcraft.launcher.dialog.ProgressDialog; import com.skcraft.launcher.install.*; +import com.skcraft.launcher.model.loader.LoaderManifest; import com.skcraft.launcher.model.minecraft.Asset; import com.skcraft.launcher.model.minecraft.AssetsIndex; import com.skcraft.launcher.model.minecraft.Library; @@ -201,11 +203,17 @@ public abstract class BaseUpdater { } protected void installLibraries(@NonNull Installer installer, - @NonNull VersionManifest versionManifest, + @NonNull Manifest manifest, @NonNull File librariesDir, @NonNull List sources) throws InterruptedException { + VersionManifest versionManifest = manifest.getVersionManifest(); - for (Library library : versionManifest.getLibraries()) { + Iterable allLibraries = versionManifest.getLibraries(); + for (LoaderManifest loader : manifest.getLoaders().values()) { + allLibraries = Iterables.concat(allLibraries, loader.getLibraries()); + } + + for (Library library : allLibraries) { if (library.matches(environment)) { checkInterrupted(); diff --git a/launcher/src/main/java/com/skcraft/launcher/update/Updater.java b/launcher/src/main/java/com/skcraft/launcher/update/Updater.java index 412021b..6977dba 100644 --- a/launcher/src/main/java/com/skcraft/launcher/update/Updater.java +++ b/launcher/src/main/java/com/skcraft/launcher/update/Updater.java @@ -166,7 +166,7 @@ public class Updater extends BaseUpdater implements Callable, Progress } progress = new DefaultProgress(-1, SharedLocale.tr("instanceUpdater.collectingLibraries")); - installLibraries(installer, version, launcher.getLibrariesDir(), librarySources); + installLibraries(installer, manifest, launcher.getLibrariesDir(), librarySources); // Download assets log.info("Enumerating assets to download...");