mirror of
https://github.com/SKCraft/Launcher.git
synced 2025-01-07 19:29: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.Server;
|
||||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||||
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
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.ResourceHandler;
|
||||||
import org.eclipse.jetty.server.handler.gzip.GzipHandler;
|
import org.eclipse.jetty.server.handler.gzip.GzipHandler;
|
||||||
|
|
||||||
@ -72,6 +73,8 @@ public class TestServerBuilder {
|
|||||||
server.setHandler(gzip);
|
server.setHandler(gzip);
|
||||||
gzip.setHandler(contexts);
|
gzip.setHandler(contexts);
|
||||||
|
|
||||||
|
server.addBean(new ErrorHandler());
|
||||||
|
|
||||||
return new TestServer(server);
|
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.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.ObjectWriter;
|
import com.fasterxml.jackson.databind.ObjectWriter;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.base.Strings;
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
import com.google.common.io.CharStreams;
|
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.LoaderManifest;
|
||||||
import com.skcraft.launcher.model.loader.SidedData;
|
import com.skcraft.launcher.model.loader.SidedData;
|
||||||
import com.skcraft.launcher.model.loader.VersionInfo;
|
import com.skcraft.launcher.model.loader.VersionInfo;
|
||||||
import com.skcraft.launcher.model.minecraft.Library;
|
import com.skcraft.launcher.model.minecraft.*;
|
||||||
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.modpack.DownloadableFile;
|
import com.skcraft.launcher.model.modpack.DownloadableFile;
|
||||||
import com.skcraft.launcher.model.modpack.Manifest;
|
import com.skcraft.launcher.model.modpack.Manifest;
|
||||||
import com.skcraft.launcher.util.Environment;
|
import com.skcraft.launcher.util.Environment;
|
||||||
@ -75,6 +71,7 @@ public class PackageBuilder {
|
|||||||
private File baseDir;
|
private File baseDir;
|
||||||
|
|
||||||
private List<Library> loaderLibraries = Lists.newArrayList();
|
private List<Library> loaderLibraries = Lists.newArrayList();
|
||||||
|
private List<Library> installerLibraries = Lists.newArrayList();
|
||||||
private List<String> mavenRepos;
|
private List<String> mavenRepos;
|
||||||
private List<URL> jarMavens = Lists.newArrayList();
|
private List<URL> jarMavens = Lists.newArrayList();
|
||||||
|
|
||||||
@ -176,12 +173,9 @@ public class PackageBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy tweak class arguments
|
// Copy tweak class arguments
|
||||||
List<String> gameArguments = info.getMinecraftArguments().getGameArguments();
|
List<GameArgument> gameArguments = info.getMinecraftArguments().getGameArguments();
|
||||||
if (gameArguments != null) {
|
if (gameArguments != null) {
|
||||||
String args = Joiner.on(' ').join(gameArguments);
|
version.getArguments().getGameArguments().addAll(gameArguments);
|
||||||
String existingArgs = Strings.nullToEmpty(version.getMinecraftArguments());
|
|
||||||
|
|
||||||
version.setMinecraftArguments(Joiner.on(' ').join(existingArgs, args));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add libraries
|
// Add libraries
|
||||||
@ -213,7 +207,7 @@ public class PackageBuilder {
|
|||||||
InstallProfile profile = mapper.readValue(data, InstallProfile.class);
|
InstallProfile profile = mapper.readValue(data, InstallProfile.class);
|
||||||
|
|
||||||
// Import the libraries for the installer
|
// Import the libraries for the installer
|
||||||
loaderLibraries.addAll(profile.getLibraries());
|
installerLibraries.addAll(profile.getLibraries());
|
||||||
|
|
||||||
// Extract the data files
|
// Extract the data files
|
||||||
List<DownloadableFile> extraFiles = Lists.newArrayList();
|
List<DownloadableFile> extraFiles = Lists.newArrayList();
|
||||||
@ -243,7 +237,7 @@ public class PackageBuilder {
|
|||||||
profile.getData().put("SIDE", SidedData.create("client", "server"));
|
profile.getData().put("SIDE", SidedData.create("client", "server"));
|
||||||
|
|
||||||
// Add loader manifest to the map
|
// 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
|
// Add processors
|
||||||
manifest.getTasks().addAll(profile.toProcessorEntries(loaderName));
|
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
|
// TODO: Download libraries for different environments -- As of writing, this is not an issue
|
||||||
Environment env = Environment.getInstance();
|
Environment env = Environment.getInstance();
|
||||||
|
|
||||||
for (Library library : loaderLibraries) {
|
for (Library library : Iterables.concat(loaderLibraries, installerLibraries)) {
|
||||||
Library.Artifact artifact = library.getArtifact(env);
|
Library.Artifact artifact = library.getArtifact(env);
|
||||||
File outputPath = new File(librariesDir, artifact.getPath());
|
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.
|
* Get the launcher version.
|
||||||
*
|
*
|
||||||
|
@ -52,7 +52,7 @@ public class ProcessorTask implements InstallTask {
|
|||||||
Map<String, String> outputs = processor.resolveOutputs(resolver);
|
Map<String, String> outputs = processor.resolveOutputs(resolver);
|
||||||
|
|
||||||
message = "Finding libraries";
|
message = "Finding libraries";
|
||||||
Library execFile = versionManifest.findLibrary(processor.getJar());
|
Library execFile = loaderManifest.findLibrary(processor.getJar());
|
||||||
File jar = launcher.getLibraryFile(execFile);
|
File jar = launcher.getLibraryFile(execFile);
|
||||||
|
|
||||||
JarFile jarFile = new JarFile(jar);
|
JarFile jarFile = new JarFile(jar);
|
||||||
@ -68,7 +68,7 @@ public class ProcessorTask implements InstallTask {
|
|||||||
int total = processor.getClasspath().size();
|
int total = processor.getClasspath().size();
|
||||||
for (String libraryName : processor.getClasspath()) {
|
for (String libraryName : processor.getClasspath()) {
|
||||||
message = "Adding library " + libraryName;
|
message = "Adding library " + libraryName;
|
||||||
File libraryFile = launcher.getLibraryFile(versionManifest.findLibrary(libraryName));
|
File libraryFile = launcher.getLibraryFile(loaderManifest.findLibrary(libraryName));
|
||||||
if (!libraryFile.exists()) {
|
if (!libraryFile.exists()) {
|
||||||
throw new RuntimeException(String.format("Missing library '%s' for processor '%s'",
|
throw new RuntimeException(String.format("Missing library '%s' for processor '%s'",
|
||||||
libraryName, processor.getJar()));
|
libraryName, processor.getJar()));
|
||||||
|
@ -106,9 +106,6 @@ public class JavaProcessBuilder {
|
|||||||
command.add("-XX:MaxPermSize=" + String.valueOf(permGen) + "M");
|
command.add("-XX:MaxPermSize=" + String.valueOf(permGen) + "M");
|
||||||
}
|
}
|
||||||
|
|
||||||
command.add("-cp");
|
|
||||||
command.add(buildClassPath());
|
|
||||||
|
|
||||||
command.add(mainClass);
|
command.add(mainClass);
|
||||||
|
|
||||||
for (String arg : args) {
|
for (String arg : args) {
|
||||||
|
@ -15,9 +15,7 @@ import com.skcraft.concurrency.ProgressObservable;
|
|||||||
import com.skcraft.launcher.*;
|
import com.skcraft.launcher.*;
|
||||||
import com.skcraft.launcher.auth.Session;
|
import com.skcraft.launcher.auth.Session;
|
||||||
import com.skcraft.launcher.install.ZipExtract;
|
import com.skcraft.launcher.install.ZipExtract;
|
||||||
import com.skcraft.launcher.model.minecraft.AssetsIndex;
|
import com.skcraft.launcher.model.minecraft.*;
|
||||||
import com.skcraft.launcher.model.minecraft.Library;
|
|
||||||
import com.skcraft.launcher.model.minecraft.VersionManifest;
|
|
||||||
import com.skcraft.launcher.persistence.Persistence;
|
import com.skcraft.launcher.persistence.Persistence;
|
||||||
import com.skcraft.launcher.util.Environment;
|
import com.skcraft.launcher.util.Environment;
|
||||||
import com.skcraft.launcher.util.Platform;
|
import com.skcraft.launcher.util.Platform;
|
||||||
@ -60,6 +58,7 @@ public class Runner implements Callable<Process>, ProgressObservable {
|
|||||||
private Configuration config;
|
private Configuration config;
|
||||||
private JavaProcessBuilder builder;
|
private JavaProcessBuilder builder;
|
||||||
private AssetsRoot assetsRoot;
|
private AssetsRoot assetsRoot;
|
||||||
|
private FeatureList.Mutable featureList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance launcher.
|
* Create a new instance launcher.
|
||||||
@ -75,6 +74,7 @@ public class Runner implements Callable<Process>, ProgressObservable {
|
|||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.extractDir = extractDir;
|
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"));
|
progress = new DefaultProgress(0.9, SharedLocale.tr("runner.collectingArgs"));
|
||||||
|
|
||||||
addJvmArgs();
|
addWindowArgs();
|
||||||
addLibraries();
|
addLibraries();
|
||||||
|
addJvmArgs();
|
||||||
addJarArgs();
|
addJarArgs();
|
||||||
addProxyArgs();
|
addProxyArgs();
|
||||||
addServerArgs();
|
addServerArgs();
|
||||||
addWindowArgs();
|
|
||||||
addPlatformArgs();
|
addPlatformArgs();
|
||||||
addLegacyArgs();
|
addLegacyArgs();
|
||||||
|
|
||||||
@ -175,11 +175,6 @@ public class Runner implements Callable<Process>, ProgressObservable {
|
|||||||
builder.getFlags().add("-Xdock:name=Minecraft");
|
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()));
|
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));
|
builder.tryJvmPath(new File(rawJvmPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<String> flags = builder.getFlags();
|
||||||
String rawJvmArgs = config.getJvmArgs();
|
String rawJvmArgs = config.getJvmArgs();
|
||||||
if (!Strings.isNullOrEmpty(rawJvmArgs)) {
|
if (!Strings.isNullOrEmpty(rawJvmArgs)) {
|
||||||
List<String> flags = builder.getFlags();
|
|
||||||
|
|
||||||
for (String arg : JavaProcessBuilder.splitArgs(rawJvmArgs)) {
|
for (String arg : JavaProcessBuilder.splitArgs(rawJvmArgs)) {
|
||||||
flags.add(arg);
|
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 {
|
private void addJarArgs() throws JsonProcessingException {
|
||||||
List<String> args = builder.getArgs();
|
List<String> args = builder.getArgs();
|
||||||
|
|
||||||
String[] rawArgs = versionManifest.getMinecraftArguments().split(" +");
|
List<GameArgument> rawArgs = versionManifest.getArguments().getGameArguments();
|
||||||
StrSubstitutor substitutor = new StrSubstitutor(getCommandSubstitutions());
|
StrSubstitutor substitutor = new StrSubstitutor(getCommandSubstitutions());
|
||||||
for (String arg : rawArgs) {
|
for (GameArgument arg : rawArgs) {
|
||||||
args.add(substitutor.replace(arg));
|
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.
|
* Add window arguments.
|
||||||
*/
|
*/
|
||||||
private void addWindowArgs() {
|
private void addWindowArgs() {
|
||||||
List<String> args = builder.getArgs();
|
|
||||||
int width = config.getWindowWidth();
|
int width = config.getWindowWidth();
|
||||||
int height = config.getWidowHeight();
|
|
||||||
|
|
||||||
if (width >= 10) {
|
if (width >= 10) {
|
||||||
args.add("--width");
|
featureList.addFeature("has_custom_resolution", true);
|
||||||
args.add(String.valueOf(width));
|
|
||||||
args.add("--height");
|
|
||||||
args.add(String.valueOf(height));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,6 +371,14 @@ public class Runner implements Callable<Process>, ProgressObservable {
|
|||||||
map.put("assets_root", launcher.getAssets().getDir().getAbsolutePath());
|
map.put("assets_root", launcher.getAssets().getDir().getAbsolutePath());
|
||||||
map.put("assets_index_name", versionManifest.getAssetId());
|
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;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.skcraft.launcher.model.loader;
|
package com.skcraft.launcher.model.loader;
|
||||||
|
|
||||||
|
import com.skcraft.launcher.model.minecraft.Library;
|
||||||
import com.skcraft.launcher.model.modpack.DownloadableFile;
|
import com.skcraft.launcher.model.modpack.DownloadableFile;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@ -12,6 +13,17 @@ import java.util.Map;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class LoaderManifest {
|
public class LoaderManifest {
|
||||||
|
private List<Library> libraries;
|
||||||
private Map<String, SidedData> sidedData;
|
private Map<String, SidedData> sidedData;
|
||||||
private List<DownloadableFile> downloadableFiles;
|
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.Library;
|
||||||
import com.skcraft.launcher.model.minecraft.Side;
|
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.DownloadableFile;
|
||||||
import com.skcraft.launcher.model.modpack.Manifest;
|
import com.skcraft.launcher.model.modpack.Manifest;
|
||||||
import com.skcraft.launcher.util.Environment;
|
import com.skcraft.launcher.util.Environment;
|
||||||
@ -30,8 +29,6 @@ public class LoaderSubResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String transform(String arg) {
|
public String transform(String arg) {
|
||||||
VersionManifest version = manifest.getVersionManifest();
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
char start = arg.charAt(0);
|
char start = arg.charAt(0);
|
||||||
int bound = arg.length() - 1;
|
int bound = arg.length() - 1;
|
||||||
@ -44,7 +41,7 @@ public class LoaderSubResolver {
|
|||||||
}
|
}
|
||||||
} else if (start == '[' && end == ']') {
|
} else if (start == '[' && end == ']') {
|
||||||
String libraryName = arg.substring(1, bound);
|
String libraryName = arg.substring(1, bound);
|
||||||
Library library = version.findLibrary(libraryName);
|
Library library = loader.findLibrary(libraryName);
|
||||||
if (library != null) {
|
if (library != null) {
|
||||||
arg = getPathOf(manifest.getLibrariesLocation(), library.getPath(env));
|
arg = getPathOf(manifest.getLibrariesLocation(), library.getPath(env));
|
||||||
} else {
|
} 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;
|
package com.skcraft.launcher.model.minecraft;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
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.Joiner;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.skcraft.launcher.util.Environment;
|
import com.skcraft.launcher.util.Environment;
|
||||||
@ -20,7 +15,6 @@ import lombok.Data;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
@ -43,8 +37,8 @@ public class Library {
|
|||||||
|
|
||||||
if (getRules() != null) {
|
if (getRules() != null) {
|
||||||
for (Rule rule : getRules()) {
|
for (Rule rule : getRules()) {
|
||||||
if (rule.matches(environment)) {
|
if (rule.matches(environment, FeatureList.EMPTY)) {
|
||||||
allow = rule.getAction() == Action.ALLOW;
|
allow = rule.isAllowed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -95,6 +89,10 @@ public class Library {
|
|||||||
if (name != null ? !name.equals(library.name) : library.name != null)
|
if (name != null ? !name.equals(library.name) : library.name != null)
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,38 +101,6 @@ public class Library {
|
|||||||
return name != null ? name.hashCode() : 0;
|
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
|
@Data
|
||||||
public static class Extract {
|
public static class Extract {
|
||||||
private List<String> exclude;
|
private List<String> exclude;
|
||||||
@ -155,21 +121,6 @@ public class Library {
|
|||||||
private Map<String, Artifact> classifiers;
|
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) {
|
public static String mavenNameToPath(String mavenName) {
|
||||||
List<String> split = Splitter.on(':').splitToList(mavenName);
|
List<String> split = Splitter.on(':').splitToList(mavenName);
|
||||||
int size = split.size();
|
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.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
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 lombok.Data;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -10,6 +13,13 @@ import java.util.List;
|
|||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public class MinecraftArguments {
|
public class MinecraftArguments {
|
||||||
@JsonProperty("game")
|
@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.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -25,8 +26,7 @@ public class VersionManifest {
|
|||||||
private String assets;
|
private String assets;
|
||||||
private AssetIndex assetIndex;
|
private AssetIndex assetIndex;
|
||||||
private String type;
|
private String type;
|
||||||
private String processArguments;
|
private MinecraftArguments arguments;
|
||||||
private String minecraftArguments;
|
|
||||||
private String mainClass;
|
private String mainClass;
|
||||||
private int minimumLauncherVersion;
|
private int minimumLauncherVersion;
|
||||||
private LinkedHashSet<Library> libraries;
|
private LinkedHashSet<Library> libraries;
|
||||||
@ -48,6 +48,15 @@ public class VersionManifest {
|
|||||||
return null;
|
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
|
@Data
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public static class Artifact {
|
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.
|
* 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.core.JsonParser;
|
||||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
@ -4,7 +4,7 @@
|
|||||||
* Please see LICENSE.txt for license information.
|
* 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.JsonGenerator;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
@ -7,6 +7,7 @@
|
|||||||
package com.skcraft.launcher.update;
|
package com.skcraft.launcher.update;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
import com.skcraft.launcher.AssetsRoot;
|
import com.skcraft.launcher.AssetsRoot;
|
||||||
import com.skcraft.launcher.Instance;
|
import com.skcraft.launcher.Instance;
|
||||||
import com.skcraft.launcher.Launcher;
|
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.FeatureSelectionDialog;
|
||||||
import com.skcraft.launcher.dialog.ProgressDialog;
|
import com.skcraft.launcher.dialog.ProgressDialog;
|
||||||
import com.skcraft.launcher.install.*;
|
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.Asset;
|
||||||
import com.skcraft.launcher.model.minecraft.AssetsIndex;
|
import com.skcraft.launcher.model.minecraft.AssetsIndex;
|
||||||
import com.skcraft.launcher.model.minecraft.Library;
|
import com.skcraft.launcher.model.minecraft.Library;
|
||||||
@ -201,11 +203,17 @@ public abstract class BaseUpdater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void installLibraries(@NonNull Installer installer,
|
protected void installLibraries(@NonNull Installer installer,
|
||||||
@NonNull VersionManifest versionManifest,
|
@NonNull Manifest manifest,
|
||||||
@NonNull File librariesDir,
|
@NonNull File librariesDir,
|
||||||
@NonNull List<URL> sources) throws InterruptedException {
|
@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)) {
|
if (library.matches(environment)) {
|
||||||
checkInterrupted();
|
checkInterrupted();
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ public class Updater extends BaseUpdater implements Callable<Instance>, Progress
|
|||||||
}
|
}
|
||||||
|
|
||||||
progress = new DefaultProgress(-1, SharedLocale.tr("instanceUpdater.collectingLibraries"));
|
progress = new DefaultProgress(-1, SharedLocale.tr("instanceUpdater.collectingLibraries"));
|
||||||
installLibraries(installer, version, launcher.getLibrariesDir(), librarySources);
|
installLibraries(installer, manifest, launcher.getLibrariesDir(), librarySources);
|
||||||
|
|
||||||
// Download assets
|
// Download assets
|
||||||
log.info("Enumerating assets to download...");
|
log.info("Enumerating assets to download...");
|
||||||
|
Loading…
Reference in New Issue
Block a user