mirror of
https://github.com/SKCraft/Launcher.git
synced 2025-01-05 19:09:03 +01:00
Update launcher/runner component to new models
- Fix game arguments being missing from version manifest due to new format - Update Runner to use more substitutions & support new argument model - Move loader/installer libraries to their own section to avoid runtime conflicts - Implement some basic feature matching for arguments
This commit is contained in:
parent
410031a86f
commit
86247c98a9
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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<Library> loaderLibraries = Lists.newArrayList();
|
||||
private List<Library> installerLibraries = Lists.newArrayList();
|
||||
private List<String> mavenRepos;
|
||||
private List<URL> jarMavens = Lists.newArrayList();
|
||||
|
||||
@ -176,12 +173,9 @@ public class PackageBuilder {
|
||||
}
|
||||
|
||||
// Copy tweak class arguments
|
||||
List<String> gameArguments = info.getMinecraftArguments().getGameArguments();
|
||||
List<GameArgument> 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<DownloadableFile> 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());
|
||||
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -52,7 +52,7 @@ public class ProcessorTask implements InstallTask {
|
||||
Map<String, String> 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()));
|
||||
|
@ -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) {
|
||||
|
@ -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<Process>, 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<Process>, ProgressObservable {
|
||||
this.instance = instance;
|
||||
this.session = session;
|
||||
this.extractDir = extractDir;
|
||||
this.featureList = new FeatureList.Mutable();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -132,12 +132,12 @@ public class Runner implements Callable<Process>, 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<Process>, 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<Process>, 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<Process>, ProgressObservable {
|
||||
builder.tryJvmPath(new File(rawJvmPath));
|
||||
}
|
||||
|
||||
List<String> flags = builder.getFlags();
|
||||
String rawJvmArgs = config.getJvmArgs();
|
||||
if (!Strings.isNullOrEmpty(rawJvmArgs)) {
|
||||
List<String> flags = builder.getFlags();
|
||||
|
||||
for (String arg : JavaProcessBuilder.splitArgs(rawJvmArgs)) {
|
||||
flags.add(arg);
|
||||
}
|
||||
}
|
||||
|
||||
List<GameArgument> 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<Process>, ProgressObservable {
|
||||
private void addJarArgs() throws JsonProcessingException {
|
||||
List<String> args = builder.getArgs();
|
||||
|
||||
String[] rawArgs = versionManifest.getMinecraftArguments().split(" +");
|
||||
List<GameArgument> 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<Process>, ProgressObservable {
|
||||
* Add window arguments.
|
||||
*/
|
||||
private void addWindowArgs() {
|
||||
List<String> 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<Process>, 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;
|
||||
}
|
||||
|
||||
|
@ -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<Library> libraries;
|
||||
private Map<String, SidedData> sidedData;
|
||||
private List<DownloadableFile> downloadableFiles;
|
||||
|
||||
public Library findLibrary(String name) {
|
||||
for (Library library : getLibraries()) {
|
||||
if (library.getName().equals(name)) {
|
||||
return library;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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<String, Boolean> features = Maps.newHashMap();
|
||||
|
||||
public boolean doesMatch(Map<String, Boolean> features) {
|
||||
for (Map.Entry<String, Boolean> 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();
|
||||
}
|
@ -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<String> values;
|
||||
private List<Rule> rules;
|
||||
|
||||
public GameArgument(List<String> 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;
|
||||
}
|
||||
}
|
@ -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<String> exclude;
|
||||
@ -155,21 +121,6 @@ public class Library {
|
||||
private Map<String, Artifact> 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<String> split = Splitter.on(':').splitToList(mavenName);
|
||||
int size = split.size();
|
||||
|
@ -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<String> gameArguments;
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
|
||||
@JsonDeserialize(contentUsing = MinecraftArgumentsDeserializer.class)
|
||||
private List<GameArgument> gameArguments;
|
||||
|
||||
@JsonProperty("jvm")
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
|
||||
@JsonDeserialize(contentUsing = MinecraftArgumentsDeserializer.class)
|
||||
private List<GameArgument> jvmArguments;
|
||||
}
|
||||
|
||||
|
@ -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<String, Boolean> 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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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<Library> 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 {
|
||||
|
@ -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<List<String>> {
|
||||
protected ArgumentValueDeserializer() {
|
||||
super(TypeFactory.defaultInstance().constructCollectionType(List.class, String.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> 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);
|
||||
}
|
||||
}
|
@ -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<GameArgument> {
|
||||
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);
|
||||
}
|
||||
}
|
@ -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;
|
@ -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;
|
@ -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<URL> sources) throws InterruptedException {
|
||||
VersionManifest versionManifest = manifest.getVersionManifest();
|
||||
|
||||
for (Library library : versionManifest.getLibraries()) {
|
||||
Iterable<Library> allLibraries = versionManifest.getLibraries();
|
||||
for (LoaderManifest loader : manifest.getLoaders().values()) {
|
||||
allLibraries = Iterables.concat(allLibraries, loader.getLibraries());
|
||||
}
|
||||
|
||||
for (Library library : allLibraries) {
|
||||
if (library.matches(environment)) {
|
||||
checkInterrupted();
|
||||
|
||||
|
@ -166,7 +166,7 @@ public class Updater extends BaseUpdater implements Callable<Instance>, 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...");
|
||||
|
Loading…
Reference in New Issue
Block a user