mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-04-18 18:40:34 +08:00
feat(launch): compatible with TLauncher.
This commit is contained in:
parent
06d0fa6e22
commit
610864d674
@ -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");
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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/<version>/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/<version>/libraries/$filename
|
||||
*/
|
||||
@Nullable
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
}
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
1580
HMCLCore/src/test/resources/game-json/tlauncher.json
Normal file
1580
HMCLCore/src/test/resources/game-json/tlauncher.json
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user