fix game part
This commit is contained in:
parent
25d154f83f
commit
d32baadf27
|
@ -28,6 +28,7 @@ android {
|
|||
|
||||
dependencies {
|
||||
implementation 'org.nanohttpd:nanohttpd:2.3.1'
|
||||
implementation 'com.github.steveice10:opennbt:1.4'
|
||||
implementation 'org.apache.commons:commons-lang3:3.12.0'
|
||||
implementation 'org.jenkins-ci:constant-pool-scanner:1.2'
|
||||
implementation 'com.google.code.gson:gson:2.9.0'
|
||||
|
|
|
@ -47,10 +47,7 @@ public final class Arguments {
|
|||
}
|
||||
|
||||
public Arguments addGameArguments(List<String> gameArguments) {
|
||||
List<Argument> list = new ArrayList<>();
|
||||
for (String arg : gameArguments) {
|
||||
list.add(new StringArgument(arg));
|
||||
}
|
||||
List<Argument> list = gameArguments.stream().map(StringArgument::new).collect(Collectors.toList());
|
||||
return new Arguments(Lang.merge(getGame(), list), getJvm());
|
||||
}
|
||||
|
||||
|
@ -59,10 +56,7 @@ public final class Arguments {
|
|||
}
|
||||
|
||||
public Arguments addJVMArguments(List<String> jvmArguments) {
|
||||
List<Argument> list = new ArrayList<>();
|
||||
for (String arg : jvmArguments) {
|
||||
list.add(new StringArgument(arg));
|
||||
}
|
||||
List<Argument> list = jvmArguments.stream().map(StringArgument::new).collect(Collectors.toList());
|
||||
return new Arguments(getGame(), Lang.merge(getJvm(), list));
|
||||
}
|
||||
|
||||
|
@ -78,11 +72,7 @@ public final class Arguments {
|
|||
}
|
||||
|
||||
public static List<String> parseStringArguments(List<String> arguments, Map<String, String> keys) {
|
||||
List<String> list = new ArrayList<>();
|
||||
for (String arg : arguments) {
|
||||
list.addAll(new StringArgument(arg).toString(keys, Collections.emptyMap()));
|
||||
}
|
||||
return list;
|
||||
return arguments.stream().filter(Objects::nonNull).flatMap(str -> new StringArgument(str).toString(keys, Collections.emptyMap()).stream()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static List<String> parseArguments(List<Argument> arguments, Map<String, String> keys) {
|
||||
|
@ -90,11 +80,7 @@ public final class Arguments {
|
|||
}
|
||||
|
||||
public static List<String> parseArguments(List<Argument> arguments, Map<String, String> keys, Map<String, Boolean> features) {
|
||||
List<String> list = new ArrayList<>();
|
||||
for (Argument arg : arguments) {
|
||||
list.addAll(arg.toString(keys, Collections.emptyMap()));
|
||||
}
|
||||
return list;
|
||||
return arguments.stream().filter(Objects::nonNull).flatMap(arg -> arg.toString(keys, features).stream()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static final List<Argument> DEFAULT_JVM_ARGUMENTS;
|
||||
|
|
|
@ -11,6 +11,7 @@ import com.google.gson.JsonSerializer;
|
|||
import com.google.gson.annotations.JsonAdapter;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.file.Path;
|
||||
|
||||
@JsonAdapter(Artifact.Serializer.class)
|
||||
public final class Artifact {
|
||||
|
@ -100,8 +101,8 @@ public final class Artifact {
|
|||
|
||||
public String getPath() { return path; }
|
||||
|
||||
public String getPath(String root) {
|
||||
return root + "/" + path;
|
||||
public Path getPath(Path root) {
|
||||
return root.resolve(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,16 +22,16 @@ public final class CompatibilityRule {
|
|||
this.features = features;
|
||||
}
|
||||
|
||||
public Action getAppliedAction(Map<String, Boolean> supportedFeatures) {
|
||||
public Optional<Action> getAppliedAction(Map<String, Boolean> supportedFeatures) {
|
||||
if (os != null && !os.allow())
|
||||
return null;
|
||||
return Optional.empty();
|
||||
|
||||
if (features != null)
|
||||
for (Map.Entry<String, Boolean> entry : features.entrySet())
|
||||
if (!Objects.equals(supportedFeatures.get(entry.getKey()), entry.getValue()))
|
||||
return null;
|
||||
return Optional.empty();
|
||||
|
||||
return action;
|
||||
return Optional.ofNullable(action);
|
||||
}
|
||||
|
||||
public static boolean appliesToCurrentEnvironment(Collection<CompatibilityRule> rules) {
|
||||
|
@ -44,9 +44,9 @@ public final class CompatibilityRule {
|
|||
|
||||
Action action = Action.DISALLOW;
|
||||
for (CompatibilityRule rule : rules) {
|
||||
Action thisAction = rule.getAppliedAction(features);
|
||||
if (thisAction != null)
|
||||
action = thisAction;
|
||||
Optional<Action> thisAction = rule.getAppliedAction(features);
|
||||
if (thisAction.isPresent())
|
||||
action = thisAction.get();
|
||||
}
|
||||
|
||||
return action == Action.ALLOW;
|
||||
|
|
|
@ -6,11 +6,11 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
// Todo : fix
|
||||
public final class CrashReportAnalyzer {
|
||||
|
||||
private CrashReportAnalyzer() {
|
||||
|
@ -142,7 +142,7 @@ public final class CrashReportAnalyzer {
|
|||
public static String findCrashReport(String log) throws IOException, InvalidPathException {
|
||||
Matcher matcher = CRASH_REPORT_LOCATION_PATTERN.matcher(log);
|
||||
if (matcher.find()) {
|
||||
return FileUtils.readText(matcher.group("location"));
|
||||
return FileUtils.readText(Paths.get(matcher.group("location")));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import static com.tungsten.fclcore.util.Logging.LOG;
|
|||
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.tungsten.fclcore.download.MaintainTask;
|
||||
import com.tungsten.fclcore.download.game.VersionJsonSaveTask;
|
||||
import com.tungsten.fclcore.event.Event;
|
||||
import com.tungsten.fclcore.event.EventBus;
|
||||
import com.tungsten.fclcore.event.GameJsonParseFailedEvent;
|
||||
|
@ -15,6 +17,7 @@ import com.tungsten.fclcore.event.RenameVersionEvent;
|
|||
import com.tungsten.fclcore.game.tlauncher.TLauncherVersion;
|
||||
import com.tungsten.fclcore.mod.ModManager;
|
||||
import com.tungsten.fclcore.mod.ModpackConfiguration;
|
||||
import com.tungsten.fclcore.task.Task;
|
||||
import com.tungsten.fclcore.util.Lang;
|
||||
import com.tungsten.fclcore.util.ToStringBuilder;
|
||||
import com.tungsten.fclcore.util.gson.JsonUtils;
|
||||
|
@ -26,6 +29,7 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
@ -40,12 +44,11 @@ import java.util.stream.Stream;
|
|||
/**
|
||||
* An implementation of classic Minecraft game repository.
|
||||
*/
|
||||
// Todo : fix
|
||||
public class DefaultGameRepository implements GameRepository {
|
||||
|
||||
private File baseDirectory;
|
||||
protected Map<String, Version> versions;
|
||||
private ConcurrentHashMap<File, String> gameVersions = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<File, Optional<String>> gameVersions = new ConcurrentHashMap<>();
|
||||
|
||||
public DefaultGameRepository(File baseDirectory) {
|
||||
this.baseDirectory = baseDirectory;
|
||||
|
@ -94,8 +97,8 @@ public class DefaultGameRepository implements GameRepository {
|
|||
return new File(getLibrariesDirectory(version), lib.getPath());
|
||||
}
|
||||
|
||||
public String getArtifactFile(Version version, Artifact artifact) {
|
||||
return artifact.getPath(getBaseDirectory() + "/libraries");
|
||||
public Path getArtifactFile(Version version, Artifact artifact) {
|
||||
return artifact.getPath(getBaseDirectory().toPath().resolve("libraries"));
|
||||
}
|
||||
|
||||
public GameDirectoryType getGameDirectoryType(String id) {
|
||||
|
@ -119,7 +122,7 @@ public class DefaultGameRepository implements GameRepository {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getGameVersion(Version version) {
|
||||
public Optional<String> getGameVersion(Version version) {
|
||||
// This implementation may cause multiple flows against the same version entering
|
||||
// this function, which is accepted because GameVersion::minecraftVersion should
|
||||
// be consistent.
|
||||
|
@ -127,9 +130,9 @@ public class DefaultGameRepository implements GameRepository {
|
|||
if (gameVersions.containsKey(versionJar)) {
|
||||
return gameVersions.get(versionJar);
|
||||
} else {
|
||||
String gameVersion = GameVersion.minecraftVersion(versionJar);
|
||||
Optional<String> gameVersion = GameVersion.minecraftVersion(versionJar);
|
||||
|
||||
if (gameVersion == null) {
|
||||
if (!gameVersion.isPresent()) {
|
||||
LOG.warning("Cannot find out game version of " + version.getId() + ", primary jar: " + versionJar.toString() + ", jar exists: " + versionJar.exists());
|
||||
}
|
||||
|
||||
|
@ -220,7 +223,7 @@ public class DefaultGameRepository implements GameRepository {
|
|||
if (EventBus.EVENT_BUS.fireEvent(new RemoveVersionEvent(this, id)) == Event.Result.DENY)
|
||||
return false;
|
||||
if (!versions.containsKey(id))
|
||||
return FileUtils.deleteDirectoryQuietly(getVersionRoot(id).getAbsolutePath());
|
||||
return FileUtils.deleteDirectoryQuietly(getVersionRoot(id));
|
||||
File file = getVersionRoot(id);
|
||||
if (!file.exists())
|
||||
return true;
|
||||
|
@ -232,15 +235,15 @@ public class DefaultGameRepository implements GameRepository {
|
|||
try {
|
||||
versions.remove(id);
|
||||
|
||||
// remove json files first to ensure FCL will not recognize this folder as a valid version.
|
||||
List<File> jsons = FileUtils.listFilesByExtension(removedFile.getAbsolutePath(), "json");
|
||||
for (File json : jsons) {
|
||||
if (!json.delete())
|
||||
LOG.warning("Unable to delete file " + json);
|
||||
}
|
||||
// remove json files first to ensure HMCL will not recognize this folder as a valid version.
|
||||
List<File> jsons = FileUtils.listFilesByExtension(removedFile, "json");
|
||||
jsons.forEach(f -> {
|
||||
if (!f.delete())
|
||||
LOG.warning("Unable to delete file " + f);
|
||||
});
|
||||
// remove the version from version list regardless of whether the directory was removed successfully or not.
|
||||
try {
|
||||
FileUtils.deleteDirectory(removedFile.getAbsolutePath());
|
||||
FileUtils.deleteDirectory(removedFile);
|
||||
} catch (IOException e) {
|
||||
LOG.log(Level.WARNING, "Unable to remove version folder: " + file, e);
|
||||
}
|
||||
|
@ -306,20 +309,33 @@ public class DefaultGameRepository implements GameRepository {
|
|||
}
|
||||
|
||||
if (!id.equals(version.getId())) {
|
||||
String from = id;
|
||||
String to = version.getId();
|
||||
String fromDir = getVersionRoot(from).getAbsolutePath();
|
||||
String toDir = getVersionRoot(to).getAbsolutePath();
|
||||
FileUtils.rename(fromDir, to);
|
||||
try {
|
||||
String from = id;
|
||||
String to = version.getId();
|
||||
Path fromDir = getVersionRoot(from).toPath();
|
||||
Path toDir = getVersionRoot(to).toPath();
|
||||
Files.move(fromDir, toDir);
|
||||
|
||||
String fromJson = toDir + "/" + from + ".json";
|
||||
String fromJar = toDir + "/" + from + ".jar";
|
||||
String toJsonName = to + ".json";
|
||||
String toJarName = to + ".jar";
|
||||
Path fromJson = toDir.resolve(from + ".json");
|
||||
Path fromJar = toDir.resolve(from + ".jar");
|
||||
Path toJson = toDir.resolve(to + ".json");
|
||||
Path toJar = toDir.resolve(to + ".jar");
|
||||
|
||||
FileUtils.rename(fromJson, toJsonName);
|
||||
if (new File(fromJar).exists())
|
||||
FileUtils.rename(fromJar, toJarName);
|
||||
try {
|
||||
Files.move(fromJson, toJson);
|
||||
if (Files.exists(fromJar))
|
||||
Files.move(fromJar, toJar);
|
||||
} catch (IOException e) {
|
||||
// recovery
|
||||
Lang.ignoringException(() -> Files.move(toJson, fromJson));
|
||||
Lang.ignoringException(() -> Files.move(toJar, fromJar));
|
||||
Lang.ignoringException(() -> Files.move(toDir, fromDir));
|
||||
throw e;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOG.log(Level.WARNING, "Ignoring version " + version.getId() + " because version id does not match folder name " + id + ", and we cannot correct it.", e);
|
||||
return Stream.empty();
|
||||
}
|
||||
}
|
||||
|
||||
return Stream.of(version);
|
||||
|
@ -360,7 +376,7 @@ public class DefaultGameRepository implements GameRepository {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getActualAssetDirectory(String version, String assetId) {
|
||||
public Path getActualAssetDirectory(String version, String assetId) {
|
||||
try {
|
||||
return reconstructAssets(version, assetId);
|
||||
} catch (IOException | JsonParseException e) {
|
||||
|
@ -370,16 +386,16 @@ public class DefaultGameRepository implements GameRepository {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getAssetDirectory(String version, String assetId) {
|
||||
return getBaseDirectory() + "/assets";
|
||||
public Path getAssetDirectory(String version, String assetId) {
|
||||
return getBaseDirectory().toPath().resolve("assets");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAssetObject(String version, String assetId, String name) throws IOException {
|
||||
public Optional<Path> getAssetObject(String version, String assetId, String name) throws IOException {
|
||||
try {
|
||||
AssetObject assetObject = getAssetIndex(version, assetId).getObjects().get(name);
|
||||
if (assetObject == null) return null;
|
||||
return getAssetObject(version, assetId, assetObject);
|
||||
if (assetObject == null) return Optional.empty();
|
||||
return Optional.of(getAssetObject(version, assetId, assetObject));
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
|
@ -388,21 +404,25 @@ public class DefaultGameRepository implements GameRepository {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getAssetObject(String version, String assetId, AssetObject obj) {
|
||||
return getAssetDirectory(version, assetId) + "/objects/" + obj.getLocation();
|
||||
public Path getAssetObject(String version, String assetId, AssetObject obj) {
|
||||
return getAssetObject(version, getAssetDirectory(version, assetId), obj);
|
||||
}
|
||||
|
||||
public Path getAssetObject(String version, Path assetDir, AssetObject obj) {
|
||||
return assetDir.resolve("objects").resolve(obj.getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIndexFile(String version, String assetId) {
|
||||
return getAssetDirectory(version, assetId) + "/indexes/" + assetId + ".json";
|
||||
public Path getIndexFile(String version, String assetId) {
|
||||
return getAssetDirectory(version, assetId).resolve("indexes").resolve(assetId + ".json");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLoggingObject(String version, String assetId, LoggingInfo loggingInfo) {
|
||||
return getAssetDirectory(version, assetId) + "/log_configs/" + loggingInfo.getFile().getId();
|
||||
public Path getLoggingObject(String version, String assetId, LoggingInfo loggingInfo) {
|
||||
return getAssetDirectory(version, assetId).resolve("log_configs").resolve(loggingInfo.getFile().getId());
|
||||
}
|
||||
|
||||
protected String reconstructAssets(String version, String assetId) throws IOException, JsonParseException {
|
||||
protected Path reconstructAssets(String version, String assetId) throws IOException, JsonParseException {
|
||||
Path assetsDir = getAssetDirectory(version, assetId);
|
||||
Path indexFile = getIndexFile(version, assetId);
|
||||
Path virtualRoot = assetsDir.resolve("virtual").resolve(assetId);
|
||||
|
@ -439,6 +459,15 @@ public class DefaultGameRepository implements GameRepository {
|
|||
return assetsDir;
|
||||
}
|
||||
|
||||
public Task<Version> saveAsync(Version version) {
|
||||
this.gameVersions.remove(getVersionJar(version));
|
||||
if (version.isResolvedPreservingPatches()) {
|
||||
return new VersionJsonSaveTask(this, MaintainTask.maintainPreservingPatches(this, version));
|
||||
} else {
|
||||
return new VersionJsonSaveTask(this, version);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLoaded() {
|
||||
return versions != null;
|
||||
}
|
||||
|
|
|
@ -23,12 +23,7 @@ public final class ExtractRules {
|
|||
}
|
||||
|
||||
public boolean shouldExtract(String path) {
|
||||
for (String s : exclude) {
|
||||
if (path.startsWith(s)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return exclude.stream().noneMatch(path::startsWith);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package com.tungsten.fclcore.game;
|
||||
|
||||
/**
|
||||
* Determines where game runs in and game files such as mods.
|
||||
*/
|
||||
public enum GameDirectoryType {
|
||||
/**
|
||||
* .minecraft
|
||||
|
|
|
@ -4,10 +4,18 @@ import com.tungsten.fclcore.task.Task;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Supports operations on versioning.
|
||||
*
|
||||
* Note that game repository will not do any operations which need connection with Internet, if do,
|
||||
* see {@link com.tungsten.fclcore.download.DependencyManager}
|
||||
*/
|
||||
public interface GameRepository extends VersionProvider {
|
||||
|
||||
/**
|
||||
|
@ -105,7 +113,7 @@ public interface GameRepository extends VersionProvider {
|
|||
* @param version version
|
||||
* @return game version, or empty if an error occurred in detection.
|
||||
*/
|
||||
String getGameVersion(Version version);
|
||||
Optional<String> getGameVersion(Version version);
|
||||
|
||||
/**
|
||||
* Detect game version.
|
||||
|
@ -116,7 +124,7 @@ public interface GameRepository extends VersionProvider {
|
|||
* @param versionId id of version
|
||||
* @return game version, or empty if an error occurred in detection.
|
||||
*/
|
||||
default String getGameVersion(String versionId) throws VersionNotFoundException {
|
||||
default Optional<String> getGameVersion(String versionId) throws VersionNotFoundException {
|
||||
return getGameVersion(getVersion(versionId));
|
||||
}
|
||||
|
||||
|
@ -149,7 +157,7 @@ public interface GameRepository extends VersionProvider {
|
|||
* @param assetId the asset id, you can find it in {@link AssetIndexInfo#getId()} {@link Version#getAssetIndex()}
|
||||
* @return the actual asset directory
|
||||
*/
|
||||
String getActualAssetDirectory(String version, String assetId);
|
||||
Path getActualAssetDirectory(String version, String assetId);
|
||||
|
||||
/**
|
||||
* Get the asset directory according to the asset id.
|
||||
|
@ -158,7 +166,7 @@ public interface GameRepository extends VersionProvider {
|
|||
* @param assetId the asset id, you can find it in {@link AssetIndexInfo#getId()} {@link Version#getAssetIndex()}
|
||||
* @return the asset directory
|
||||
*/
|
||||
String getAssetDirectory(String version, String assetId);
|
||||
Path getAssetDirectory(String version, String assetId);
|
||||
|
||||
/**
|
||||
* Get the file that given asset object refers to
|
||||
|
@ -169,7 +177,7 @@ public interface GameRepository extends VersionProvider {
|
|||
* @throws IOException if I/O operation fails.
|
||||
* @return the file that given asset object refers to
|
||||
*/
|
||||
String getAssetObject(String version, String assetId, String name) throws IOException;
|
||||
Optional<Path> getAssetObject(String version, String assetId, String name) throws IOException;
|
||||
|
||||
/**
|
||||
* Get the file that given asset object refers to
|
||||
|
@ -179,7 +187,7 @@ public interface GameRepository extends VersionProvider {
|
|||
* @param obj the asset object, you can find it in {@link AssetIndex#getObjects()}
|
||||
* @return the file that given asset object refers to
|
||||
*/
|
||||
String getAssetObject(String version, String assetId, AssetObject obj);
|
||||
Path getAssetObject(String version, String assetId, AssetObject obj);
|
||||
|
||||
/**
|
||||
* Get asset index that assetId represents
|
||||
|
@ -196,7 +204,7 @@ public interface GameRepository extends VersionProvider {
|
|||
* @param version the id of specific version that is relevant to {@code assetId}
|
||||
* @param assetId the asset id, you can find it in {@link AssetIndexInfo#getId()} {@link Version#getAssetIndex()}
|
||||
*/
|
||||
String getIndexFile(String version, String assetId);
|
||||
Path getIndexFile(String version, String assetId);
|
||||
|
||||
/**
|
||||
* Get logging object
|
||||
|
@ -206,7 +214,7 @@ public interface GameRepository extends VersionProvider {
|
|||
* @param loggingInfo the logging info
|
||||
* @return the file that loggingInfo refers to
|
||||
*/
|
||||
String getLoggingObject(String version, String assetId, LoggingInfo loggingInfo);
|
||||
Path getLoggingObject(String version, String assetId, LoggingInfo loggingInfo);
|
||||
|
||||
default List<String> getClasspath(Version version) {
|
||||
List<String> classpath = new ArrayList<>();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.tungsten.fclcore.game;
|
||||
|
||||
import static com.tungsten.fclcore.util.Lang.tryCast;
|
||||
import static com.tungsten.fclcore.util.Logging.LOG;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
|
@ -23,18 +24,17 @@ import java.util.logging.Level;
|
|||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
// Todo : fix
|
||||
public final class GameVersion {
|
||||
private GameVersion() {
|
||||
}
|
||||
|
||||
private static String getVersionFromJson(File versionJson) {
|
||||
private static Optional<String> getVersionFromJson(Path versionJson) {
|
||||
try {
|
||||
Map<?, ?> version = JsonUtils.fromNonNullJson(FileUtils.readText(versionJson), Map.class);
|
||||
return (String) version.get("name");
|
||||
return tryCast(version.get("name"), String.class);
|
||||
} catch (IOException | JsonParseException e) {
|
||||
LOG.log(Level.WARNING, "Failed to parse version.json", e);
|
||||
return null;
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,9 +70,9 @@ public final class GameVersion {
|
|||
return Optional.empty();
|
||||
}
|
||||
|
||||
public static String minecraftVersion(File file) {
|
||||
public static Optional<String> minecraftVersion(File file) {
|
||||
if (file == null || !file.exists() || !file.isFile() || !file.canRead())
|
||||
return null;
|
||||
return Optional.empty();
|
||||
|
||||
try (FileSystem gameJar = CompressingUtils.createReadOnlyZipFileSystem(file.toPath())) {
|
||||
Path versionJson = gameJar.getPath("version.json");
|
||||
|
|
|
@ -9,7 +9,6 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
// Todo : add and delete some options
|
||||
public class LaunchOptions implements Serializable {
|
||||
|
||||
private File gameDir;
|
||||
|
@ -34,7 +33,7 @@ public class LaunchOptions implements Serializable {
|
|||
private boolean noGeneratedJVMArgs;
|
||||
private String preLaunchCommand;
|
||||
private String postExitCommand;
|
||||
private ProcessPriority processPriority = ProcessPriority.HIGH;
|
||||
private ProcessPriority processPriority = ProcessPriority.NORMAL;
|
||||
private boolean daemon;
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,7 +13,11 @@ import org.jetbrains.annotations.Nullable;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* A class that describes a Minecraft dependency.
|
||||
*/
|
||||
public class Library implements Comparable<Library>, Validation {
|
||||
|
||||
@SerializedName("name")
|
||||
|
@ -108,15 +112,8 @@ public class Library implements Comparable<Library>, Validation {
|
|||
public LibraryDownloadInfo getDownload() {
|
||||
LibraryDownloadInfo temp = getRawDownloadInfo();
|
||||
String path = getPath();
|
||||
String finalUrl = UrlConstants.DEFAULT_LIBRARY_URL + path;
|
||||
if (temp != null) {
|
||||
finalUrl = temp.getUrl();
|
||||
}
|
||||
else if (url != null) {
|
||||
finalUrl = url + path;
|
||||
}
|
||||
return new LibraryDownloadInfo(path,
|
||||
finalUrl,
|
||||
Optional.ofNullable(temp).map(LibraryDownloadInfo::getUrl).orElse(Optional.ofNullable(url).orElse(UrlConstants.DEFAULT_LIBRARY_URL) + path),
|
||||
temp != null ? temp.getSha1() : null,
|
||||
temp != null ? temp.getSize() : 0
|
||||
);
|
||||
|
|
|
@ -41,14 +41,12 @@ public class RuledArgument implements Argument {
|
|||
|
||||
@Override
|
||||
public List<String> toString(Map<String, String> keys, Map<String, Boolean> features) {
|
||||
if (CompatibilityRule.appliesToCurrentEnvironment(rules, features) && value != null) {
|
||||
List<String> list = new ArrayList<>();
|
||||
for (String v : value) {
|
||||
StringArgument stringArgument = new StringArgument(v);
|
||||
list.add(stringArgument.toString(keys, features).get(0));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
if (CompatibilityRule.appliesToCurrentEnvironment(rules, features) && value != null)
|
||||
return value.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(StringArgument::new)
|
||||
.map(str -> str.toString(keys, features).get(0))
|
||||
.collect(Collectors.toList());
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.lang.reflect.Type;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
@ -34,7 +33,7 @@ public final class StringArgument implements Argument {
|
|||
Matcher m = pattern.matcher(argument);
|
||||
while (m.find()) {
|
||||
String entry = m.group();
|
||||
res = res.replace(entry, keys.get(entry) == null ? entry : Objects.requireNonNull(keys.get(entry)));
|
||||
res = res.replace(entry, keys.getOrDefault(entry, entry));
|
||||
}
|
||||
return Collections.singletonList(res);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import com.tungsten.fclcore.util.gson.Validation;
|
|||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
@ -20,6 +19,7 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -98,12 +98,12 @@ public class Version implements Comparable<Version>, Validation {
|
|||
this.patches = Lang.copyList(patches);
|
||||
}
|
||||
|
||||
public String getMinecraftArguments() {
|
||||
return minecraftArguments;
|
||||
public Optional<String> getMinecraftArguments() {
|
||||
return Optional.ofNullable(minecraftArguments);
|
||||
}
|
||||
|
||||
public Arguments getArguments() {
|
||||
return arguments;
|
||||
public Optional<Arguments> getArguments() {
|
||||
return Optional.ofNullable(arguments);
|
||||
}
|
||||
|
||||
public String getMainClass() {
|
||||
|
@ -161,11 +161,11 @@ public class Version implements Comparable<Version>, Validation {
|
|||
}
|
||||
|
||||
public boolean isHidden() {
|
||||
return hidden;
|
||||
return hidden == null ? false : hidden;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return root;
|
||||
return root == null ? false : root;
|
||||
}
|
||||
|
||||
public boolean isResolved() {
|
||||
|
@ -246,7 +246,7 @@ public class Version implements Comparable<Version>, Validation {
|
|||
type == null ? parent.type : type,
|
||||
time == null ? parent.time : time,
|
||||
releaseTime == null ? parent.releaseTime : releaseTime,
|
||||
Math.max(minimumLauncherVersion, parent.minimumLauncherVersion),
|
||||
Lang.merge(minimumLauncherVersion, parent.minimumLauncherVersion, Math::max),
|
||||
hidden,
|
||||
true,
|
||||
isPatch ? parent.patches : Lang.merge(Lang.merge(parent.patches, Collections.singleton(toPatch())), patches));
|
||||
|
@ -381,22 +381,8 @@ public class Version implements Comparable<Version>, Validation {
|
|||
}
|
||||
|
||||
public Version addPatches(@Nullable List<Version> additional) {
|
||||
Set<String> patchIds = new HashSet<>();
|
||||
if (additional != null) {
|
||||
for (Version v : additional) {
|
||||
patchIds.add(v.getId());
|
||||
}
|
||||
}
|
||||
List<Version> oldPatches = null;
|
||||
if (this.patches != null) {
|
||||
oldPatches = new ArrayList<>();
|
||||
for (Version v : this.patches) {
|
||||
if (!patchIds.contains(v.getId())) {
|
||||
oldPatches.add(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
List<Version> patches = Lang.merge(oldPatches, additional);
|
||||
Set<String> patchIds = additional == null ? Collections.emptySet() : additional.stream().map(Version::getId).collect(Collectors.toSet());
|
||||
List<Version> patches = Lang.merge(this.patches == null ? null : this.patches.stream().filter(patch -> !patchIds.contains(patch.getId())).collect(Collectors.toList()), additional);
|
||||
return new Version(resolved, id, version, priority, minecraftArguments, arguments, mainClass, inheritsFrom, jar, assetIndex, assets, complianceLevel, javaVersion, libraries, compatibilityRules, downloads, logging, type, time, releaseTime, minimumLauncherVersion, hidden, root, patches);
|
||||
}
|
||||
|
||||
|
@ -405,29 +391,12 @@ public class Version implements Comparable<Version>, Validation {
|
|||
}
|
||||
|
||||
public Version removePatchById(String patchId) {
|
||||
List<Version> newPatches = null;
|
||||
if (patches != null) {
|
||||
newPatches = new ArrayList<>();
|
||||
for (Version p : patches) {
|
||||
if (!patchId.equals(p.getId())) {
|
||||
newPatches.add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Version(resolved, id, version, priority, minecraftArguments, arguments, mainClass, inheritsFrom, jar, assetIndex, assets, complianceLevel, javaVersion, libraries, compatibilityRules, downloads, logging, type, time, releaseTime, minimumLauncherVersion, hidden, root, newPatches);
|
||||
return new Version(resolved, id, version, priority, minecraftArguments, arguments, mainClass, inheritsFrom, jar, assetIndex, assets, complianceLevel, javaVersion, libraries, compatibilityRules, downloads, logging, type, time, releaseTime, minimumLauncherVersion, hidden, root,
|
||||
patches == null ? null : patches.stream().filter(patch -> !patchId.equals(patch.getId())).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
public boolean hasPatch(String patchId) {
|
||||
boolean has = false;
|
||||
if (patches != null) {
|
||||
for (Version patch : patches) {
|
||||
if (patch.getId().equals(patchId)) {
|
||||
has = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return has;
|
||||
return patches != null && patches.stream().anyMatch(patch -> patchId.equals(patch.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,8 +4,10 @@ import com.tungsten.fclcore.util.StringUtils;
|
|||
import com.tungsten.fclcore.util.platform.CommandBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class VersionLibraryBuilder {
|
||||
private final Version version;
|
||||
|
@ -19,9 +21,9 @@ public final class VersionLibraryBuilder {
|
|||
public VersionLibraryBuilder(Version version) {
|
||||
this.version = version;
|
||||
this.libraries = new ArrayList<>(version.getLibraries());
|
||||
this.mcArgs = version.getMinecraftArguments() != null ? StringUtils.tokenize(version.getMinecraftArguments()) : null;
|
||||
this.game = new ArrayList<>(version.getArguments().getGame() != null ? version.getArguments().getGame() : Arguments.DEFAULT_GAME_ARGUMENTS);
|
||||
this.jvm = new ArrayList<>(version.getArguments().getJvm() != null ? version.getArguments().getJvm() : Arguments.DEFAULT_JVM_ARGUMENTS);
|
||||
this.mcArgs = version.getMinecraftArguments().map(StringUtils::tokenize).map(ArrayList::new).orElse(null);
|
||||
this.game = version.getArguments().map(Arguments::getGame).map(ArrayList::new).orElseGet(ArrayList::new);
|
||||
this.jvm = new ArrayList<>(version.getArguments().map(Arguments::getJvm).orElse(Arguments.DEFAULT_JVM_ARGUMENTS));
|
||||
this.useMcArgs = mcArgs != null;
|
||||
}
|
||||
|
||||
|
@ -30,38 +32,22 @@ public final class VersionLibraryBuilder {
|
|||
if (useMcArgs) {
|
||||
// The official launcher will not parse the "arguments" property when it detects the presence of "mcArgs".
|
||||
// The "arguments" property with the "rule" is simply ignored here.
|
||||
for (Argument arg : this.game) {
|
||||
List<String> argStr = arg.toString(new HashMap<>(), new HashMap<>());
|
||||
this.mcArgs.addAll(argStr);
|
||||
}
|
||||
this.mcArgs.addAll(this.game.stream().map(arg -> arg.toString(new HashMap<>(), new HashMap<>())).flatMap(Collection::stream).collect(Collectors.toList()));
|
||||
ret = ret.setArguments(null);
|
||||
|
||||
// Since $ will be escaped in linux, and our maintain of minecraftArgument will not cause escaping,
|
||||
// so we regenerate the minecraftArgument without escaping.
|
||||
ret = ret.setMinecraftArguments(new CommandBuilder().addAllWithoutParsing(mcArgs).toString());
|
||||
} else {
|
||||
if (ret.getArguments() != null) {
|
||||
ret = ret.setArguments(ret.getArguments().withGame(game));
|
||||
if (jvmChanged) {
|
||||
ret = ret.setArguments(ret.getArguments().withJvm(jvm));
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = ret.setArguments(new Arguments(game, jvmChanged ? jvm : null));
|
||||
}
|
||||
ret = ret.setArguments(ret.getArguments()
|
||||
.map(args -> args.withGame(game))
|
||||
.map(args -> jvmChanged ? args.withJvm(jvm) : args).orElse(new Arguments(game, jvmChanged ? jvm : null)));
|
||||
}
|
||||
return ret.setLibraries(libraries);
|
||||
}
|
||||
|
||||
public boolean hasTweakClass(String tweakClass) {
|
||||
boolean match = false;
|
||||
for (Argument argument : game) {
|
||||
if (argument.toString().equals(tweakClass)) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return useMcArgs && mcArgs.contains(tweakClass) || match;
|
||||
return useMcArgs && mcArgs.contains(tweakClass) || game.stream().anyMatch(arg -> arg.toString().equals(tweakClass));
|
||||
}
|
||||
|
||||
public void removeTweakClass(String target) {
|
||||
|
|
|
@ -1,18 +1,7 @@
|
|||
package com.tungsten.fclcore.game;
|
||||
|
||||
import com.github.steveice10.opennbt.NBTIO;
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.LongTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
||||
import com.tungsten.fclcore.util.io.FileUtils;
|
||||
|
||||
import org.jackhuang.hmcl.util.*;
|
||||
import org.jackhuang.hmcl.util.io.CompressingUtils;
|
||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||
import org.jackhuang.hmcl.util.io.Unzipper;
|
||||
import org.jackhuang.hmcl.util.io.Zipper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
|
Loading…
Reference in New Issue