feat(launch): compatible with TLauncher.

This commit is contained in:
huanghongxun 2021-10-22 21:00:21 +08:00
parent 06d0fa6e22
commit 610864d674
10 changed files with 1889 additions and 18 deletions

View File

@ -102,19 +102,27 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
if (!gameVersion.isPresent()) return null;
LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(version.resolvePreservingPatches(getGameRepository()));
version.resolve(getGameRepository()).getLibraries().stream().filter(Library::appliesToCurrentEnvironment).forEach(library -> {
Optional<String> libraryVersion = analyzer.getVersion(OPTIFINE);
if (OPTIFINE.matchLibrary(library) && libraryVersion.isPresent()) {
if (GameLibrariesTask.shouldDownloadLibrary(repository, version, library, integrityCheck)) {
tasks.add(installLibraryAsync(gameVersion.get(), version, OPTIFINE.getPatchId(), libraryVersion.get()));
}
for (LibraryAnalyzer.LibraryType type : LibraryAnalyzer.LibraryType.values()) {
Optional<Library> library = analyzer.getLibrary(type);
if (library.isPresent() && GameLibrariesTask.shouldDownloadLibrary(repository, version, library.get(), integrityCheck)) {
tasks.add(downloadMissingLibraryAsync(gameVersion.get(), version, type, library.get()));
}
});
}
return Task.allOf(tasks);
});
}
private Task<?> downloadMissingLibraryAsync(String gameVersion, Version version, LibraryAnalyzer.LibraryType libraryType, Library library) {
switch (libraryType) {
case OPTIFINE:
if (library.hasDownloadURL())
break;
return installLibraryAsync(gameVersion, version, libraryType.getPatchId(), library.getVersion());
}
return Task.completed(null);
}
@Override
public Task<Version> installLibraryAsync(String gameVersion, Version baseVersion, String libraryId, String libraryVersion) {
if (baseVersion.isResolved()) throw new IllegalArgumentException("Version should not be resolved");

View File

@ -48,6 +48,10 @@ public final class LibraryAnalyzer implements Iterable<LibraryAnalyzer.LibraryMa
return Optional.ofNullable(libraries.get(type)).map(Pair::getValue);
}
public Optional<Library> getLibrary(LibraryType type) {
return Optional.ofNullable(libraries.get(type.getPatchId())).map(Pair::getKey);
}
@NotNull
@Override
public Iterator<LibraryMark> iterator() {

View File

@ -29,6 +29,7 @@ import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
import org.jackhuang.hmcl.event.RefreshingVersionsEvent;
import org.jackhuang.hmcl.event.RemoveVersionEvent;
import org.jackhuang.hmcl.event.RenameVersionEvent;
import org.jackhuang.hmcl.game.tlauncher.TLauncherVersion;
import org.jackhuang.hmcl.mod.ModManager;
import org.jackhuang.hmcl.mod.ModpackConfiguration;
import org.jackhuang.hmcl.task.Task;
@ -135,6 +136,10 @@ public class DefaultGameRepository implements GameRepository {
@Override
public File getVersionJar(Version version) {
Version v = version.resolve(this);
File currentVersionJar = new File(getVersionRoot(v.getId()), v.getId() + ".jar");
if (currentVersionJar.exists()) {
return currentVersionJar;
}
String id = Optional.ofNullable(v.getJar()).orElse(v.getId());
return new File(getVersionRoot(id), id + ".jar");
}
@ -149,6 +154,11 @@ public class DefaultGameRepository implements GameRepository {
return gameVersions.get(versionJar);
} else {
Optional<String> gameVersion = GameVersion.minecraftVersion(versionJar);
if (!gameVersion.isPresent()) {
LOG.warning("Cannot find out game version of " + version.getId() + ", primary jar: " + versionJar.toString() + ", jar exists: " + versionJar.exists());
}
gameVersions.put(versionJar, gameVersion);
return gameVersion;
}
@ -173,7 +183,21 @@ public class DefaultGameRepository implements GameRepository {
}
public Version readVersionJson(File file) throws IOException, JsonParseException {
return JsonUtils.fromNonNullJson(FileUtils.readText(file), Version.class);
String jsonText = FileUtils.readText(file);
try {
// Try TLauncher version json format
return JsonUtils.fromNonNullJson(jsonText, TLauncherVersion.class).toVersion();
} catch (JsonParseException ignored) {
}
try {
// Try official version json format
return JsonUtils.fromNonNullJson(jsonText, Version.class);
} catch (JsonParseException ignored) {
}
LOG.warning("Cannot parse version json + " + file.toString() + "\n" + jsonText);
throw new JsonParseException("Version json incorrect");
}
@Override

View File

@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2020 huangyuhui <huanghongxun2008@126.com> and contributors
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -17,7 +17,7 @@
*/
package org.jackhuang.hmcl.game;
import com.google.gson.JsonParseException;
import com.google.gson.*;
import com.google.gson.annotations.SerializedName;
import org.jackhuang.hmcl.util.Constants;
import org.jackhuang.hmcl.util.Immutable;
@ -26,6 +26,7 @@ import org.jackhuang.hmcl.util.gson.TolerableValidationException;
import org.jackhuang.hmcl.util.gson.Validation;
import org.jackhuang.hmcl.util.platform.Architecture;
import org.jackhuang.hmcl.util.platform.OperatingSystem;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
@ -142,6 +143,12 @@ public class Library implements Comparable<Library>, Validation {
);
}
public boolean hasDownloadURL() {
LibraryDownloadInfo temp = getRawDownloadInfo();
if (temp != null) return temp.getUrl() != null;
else return url != null;
}
public List<String> getChecksums() {
return checksums;
}
@ -154,6 +161,7 @@ public class Library implements Comparable<Library>, Validation {
* Hint for how to locate the library file.
* @return null for default, "local" for location in version/&lt;version&gt;/libraries/filename
*/
@Nullable
public String getHint() {
return hint;
}
@ -162,6 +170,7 @@ public class Library implements Comparable<Library>, Validation {
* Available when hint is "local"
* @return the filename of the local library in version/&lt;version&gt;/libraries/$filename
*/
@Nullable
public String getFileName() {
return fileName;
}

View File

@ -85,13 +85,28 @@ public class RuledArgument implements Argument {
@Override
public RuledArgument deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject obj = json.getAsJsonObject();
return new RuledArgument(
context.deserialize(obj.get("rules"), new TypeToken<List<CompatibilityRule>>() {
}.getType()),
obj.get("value").isJsonPrimitive()
? Collections.singletonList(obj.get("value").getAsString())
: context.deserialize(obj.get("value"), new TypeToken<List<String>>() {
}.getType()));
List<CompatibilityRule> rules = context.deserialize(obj.get("rules"), new TypeToken<List<CompatibilityRule>>() {
}.getType());
JsonElement valuesElement;
if (obj.has("values")) {
valuesElement = obj.get("values");
} else if (obj.has("value")) {
valuesElement = obj.get("value");
} else {
throw new JsonParseException("RuledArguments instance does not have either value or values member.");
}
List<String> values;
if (valuesElement.isJsonPrimitive()) {
values = Collections.singletonList(valuesElement.getAsString());
} else {
values = context.deserialize(valuesElement, new TypeToken<List<String>>() {
}.getType());
}
return new RuledArgument(rules, values);
}
}

View File

@ -0,0 +1,23 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game;
public enum VersionJsonType {
OFFICIAL,
TLAUNCHER
}

View File

@ -0,0 +1,67 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game.tlauncher;
import com.google.gson.annotations.SerializedName;
import org.jackhuang.hmcl.game.*;
import org.jackhuang.hmcl.util.Immutable;
import org.jackhuang.hmcl.util.platform.OperatingSystem;
import java.util.List;
import java.util.Map;
@Immutable
public class TLauncherLibrary {
@SerializedName("name")
private final Artifact name;
private final String url;
private final LibraryDownloadInfo artifact;
@SerializedName("classifies") // stupid typo made by TLauncher
private final Map<String, LibraryDownloadInfo> classifiers;
private final ExtractRules extract;
private final Map<OperatingSystem, String> natives;
private final List<CompatibilityRule> rules;
private final List<String> checksums;
public TLauncherLibrary(Artifact name, String url, LibraryDownloadInfo artifact, Map<String, LibraryDownloadInfo> classifiers, ExtractRules extract, Map<OperatingSystem, String> natives, List<CompatibilityRule> rules, List<String> checksums) {
this.name = name;
this.url = url;
this.artifact = artifact;
this.classifiers = classifiers;
this.extract = extract;
this.natives = natives;
this.rules = rules;
this.checksums = checksums;
}
public Library toLibrary() {
return new Library(
name,
url,
new LibrariesDownloadInfo(artifact, classifiers),
checksums,
extract,
natives,
rules,
null,
null
);
}
}

View File

@ -0,0 +1,109 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game.tlauncher;
import com.google.gson.JsonParseException;
import org.jackhuang.hmcl.game.*;
import org.jackhuang.hmcl.util.gson.JsonMap;
import org.jackhuang.hmcl.util.gson.TolerableValidationException;
import org.jackhuang.hmcl.util.gson.Validation;
import org.jetbrains.annotations.Nullable;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
public class TLauncherVersion implements Validation {
private final String id;
private final String minecraftArguments;
private final Arguments arguments;
private final String mainClass;
private final String inheritsFrom;
private final String jar;
private final AssetIndexInfo assetIndex;
private final String assets;
private final Integer complianceLevel;
@Nullable
private final GameJavaVersion javaVersion;
private final List<TLauncherLibrary> libraries;
private final List<CompatibilityRule> compatibilityRules;
private final JsonMap<DownloadType, DownloadInfo> downloads;
private final JsonMap<DownloadType, LoggingInfo> logging;
private final ReleaseType type;
private final Date time;
private final Date releaseTime;
private final Integer minimumLauncherVersion;
private final Integer tlauncherVersion;
public TLauncherVersion(String id, String minecraftArguments, Arguments arguments, String mainClass, String inheritsFrom, String jar, AssetIndexInfo assetIndex, String assets, Integer complianceLevel, @Nullable GameJavaVersion javaVersion, List<TLauncherLibrary> libraries, List<CompatibilityRule> compatibilityRules, JsonMap<DownloadType, DownloadInfo> downloads, JsonMap<DownloadType, LoggingInfo> logging, ReleaseType type, Date time, Date releaseTime, Integer minimumLauncherVersion, Integer tlauncherVersion) {
this.id = id;
this.minecraftArguments = minecraftArguments;
this.arguments = arguments;
this.mainClass = mainClass;
this.inheritsFrom = inheritsFrom;
this.jar = jar;
this.assetIndex = assetIndex;
this.assets = assets;
this.complianceLevel = complianceLevel;
this.javaVersion = javaVersion;
this.libraries = libraries;
this.compatibilityRules = compatibilityRules;
this.downloads = downloads;
this.logging = logging;
this.type = type;
this.time = time;
this.releaseTime = releaseTime;
this.minimumLauncherVersion = minimumLauncherVersion;
this.tlauncherVersion = tlauncherVersion;
}
@Override
public void validate() throws JsonParseException, TolerableValidationException {
Validation.requireNonNull(tlauncherVersion, "Not TLauncher version json format");
}
public Version toVersion() {
return new Version(
false,
id,
null,
null,
minecraftArguments,
arguments,
mainClass,
inheritsFrom,
jar,
assetIndex,
assets,
complianceLevel,
javaVersion,
libraries == null ? null : libraries.stream().map(TLauncherLibrary::toLibrary).collect(Collectors.toList()),
compatibilityRules,
downloads,
logging,
type,
time,
releaseTime,
minimumLauncherVersion,
null,
null,
null
);
}
}

View File

@ -0,0 +1,32 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.util.gson;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializer;
public abstract class GsonSerializerHelper<T> implements JsonSerializer<T>, JsonDeserializer<T> {
protected static void add(JsonObject object, String property, JsonElement value) {
if (value == null) return;
object.add(property, value);
}
}

File diff suppressed because it is too large Load Diff