Skip to content

Fix #3540 MultiMC 整合包安装问题 #3547

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions HMCL/src/main/java/org/jackhuang/hmcl/java/JavaManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,23 @@ public static JavaRuntime findSuitableJava(Collection<JavaRuntime> javaRuntimes,
GameJavaVersion suggestedJavaVersion =
(version != null && gameVersion != null && gameVersion.compareTo("1.7.10") >= 0) ? version.getJavaVersion() : null;

if (suggestedJavaVersion != null) {
for (JavaRuntime java : javaRuntimes) {
if (forceX86) {
if (!java.getArchitecture().isX86())
continue;
} else {
if (java.getArchitecture() != Architecture.SYSTEM_ARCH)
continue;
}

// 100% matched.
if (java.getParsedVersion() == suggestedJavaVersion.getMajorVersion()) {
return java;
}
}
}

JavaRuntime mandatory = null;
JavaRuntime suggested = null;
for (JavaRuntime java : javaRuntimes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ private Version getPatch(FabricInfo fabricInfo, String gameVersion, String loade
libraries.add(new Library(Artifact.fromDescriptor(fabricInfo.intermediary.maven), "https://maven.fabricmc.net/", null));
libraries.add(new Library(Artifact.fromDescriptor(fabricInfo.loader.maven), "https://maven.fabricmc.net/", null));

return new Version(LibraryAnalyzer.LibraryType.FABRIC.getPatchId(), loaderVersion, 30000, arguments, mainClass, libraries);
return new Version(LibraryAnalyzer.LibraryType.FABRIC.getPatchId(), loaderVersion, Version.PRIORITY_LOADER, arguments, mainClass, libraries);
}

public static class FabricInfo {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ public void execute() throws Exception {
dependencyManager.checkLibraryCompletionAsync(forgeVersion, true)));

setResult(forgeVersion
.setPriority(30000)
.setPriority(Version.PRIORITY_LOADER)
.setId(LibraryAnalyzer.LibraryType.FORGE.getPatchId())
.setVersion(selfVersion));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public void execute() throws Exception {
}

setResult(installProfile.getVersionInfo()
.setPriority(30000)
.setPriority(Version.PRIORITY_LOADER)
.setId(LibraryAnalyzer.LibraryType.FORGE.getPatchId())
.setVersion(selfVersion));
dependencies.add(dependencyManager.checkLibraryCompletionAsync(installProfile.getVersionInfo(), true));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public boolean isRelyingOnDependencies() {
@Override
public void execute() throws Exception {
Version patch = JsonUtils.fromNonNullJson(downloadTask.getResult(), Version.class)
.setId(MINECRAFT.getPatchId()).setVersion(remote.getGameVersion()).setJar(null).setPriority(0);
.setId(MINECRAFT.getPatchId()).setVersion(remote.getGameVersion()).setJar(null).setPriority(Version.PRIORITY_MC);
setResult(patch);

Version version = new Version(this.version.getId()).addPatch(patch);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ public void execute() throws Exception {
dependencyManager.checkLibraryCompletionAsync(neoForgeVersion, true)));

setResult(neoForgeVersion
.setPriority(30000)
.setPriority(Version.PRIORITY_LOADER)
.setId(LibraryAnalyzer.LibraryType.NEO_FORGE.getPatchId())
.setVersion(selfVersion));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ private Version getPatch(QuiltInfo quiltInfo, String gameVersion, String loaderV
libraries.add(new Library(Artifact.fromDescriptor(quiltInfo.intermediary.maven), getMavenRepositoryByGroup(quiltInfo.intermediary.maven), null));
libraries.add(new Library(Artifact.fromDescriptor(quiltInfo.loader.maven), getMavenRepositoryByGroup(quiltInfo.loader.maven), null));

return new Version(LibraryAnalyzer.LibraryType.QUILT.getPatchId(), loaderVersion, 30000, arguments, mainClass, libraries);
return new Version(LibraryAnalyzer.LibraryType.QUILT.getPatchId(), loaderVersion, Version.PRIORITY_LOADER, arguments, mainClass, libraries);
}

private static String getMavenRepositoryByGroup(String maven) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,15 @@ public File getLibrariesDirectory(Version version) {

@Override
public File getLibraryFile(Version version, Library lib) {
if ("local".equals(lib.getHint()) && lib.getFileName() != null)
return new File(getVersionRoot(version.getId()), "libraries/" + lib.getFileName());
else
return new File(getLibrariesDirectory(version), lib.getPath());
if ("local".equals(lib.getHint())) {
if (lib.getFileName() != null) {
return new File(getVersionRoot(version.getId()), "libraries/" + lib.getFileName());
}

return new File(getVersionRoot(version.getId()), "libraries/" + lib.getArtifact().getFileName());
}

return new File(getLibrariesDirectory(version), lib.getPath());
}

public Path getArtifactFile(Version version, Artifact artifact) {
Expand Down
107 changes: 91 additions & 16 deletions HMCLCore/src/main/java/org/jackhuang/hmcl/game/Library.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,19 @@
*/
package org.jackhuang.hmcl.game;

import com.google.gson.*;
import com.google.gson.JsonParseException;
import com.google.gson.annotations.SerializedName;
import org.jackhuang.hmcl.util.Constants;
import org.jackhuang.hmcl.util.Immutable;
import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.ToStringBuilder;
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;
import java.util.Objects;
import java.util.Optional;
import java.util.*;

/**
* A class that describes a Minecraft dependency.
Expand All @@ -40,13 +38,47 @@
*/
@Immutable
public class Library implements Comparable<Library>, Validation {
/**
* <p>A possible native descriptors can be: [variant-]os[-key]</p>
*
* <p>
* Variant can be empty string, 'native', or 'natives'.
* Key can be empty string, system arch, or system arch bit count.
* </p>
*/
private static final String[] POSSIBLE_NATIVE_DESCRIPTORS;

static {
String[] keys = {
"",
Architecture.SYSTEM_ARCH.name().toLowerCase(Locale.ROOT),
Architecture.SYSTEM_ARCH.getBits().getBit()
}, variants = {"", "native", "natives"};

POSSIBLE_NATIVE_DESCRIPTORS = new String[keys.length * variants.length];
StringBuilder builder = new StringBuilder();
for (int i = 0; i < keys.length; i++) {
for (int j = 0; j < variants.length; j++) {
if (!variants[j].isEmpty()) {
builder.append(variants[j]).append('-');
}
builder.append(OperatingSystem.CURRENT_OS.getCheckedName());
if (!keys[i].isEmpty()) {
builder.append('-').append(keys[i]);
}

POSSIBLE_NATIVE_DESCRIPTORS[i * variants.length + j] = builder.toString();
builder.setLength(0);
}
}
}

@SerializedName("name")
private final Artifact artifact;
private final String url;
private final LibrariesDownloadInfo downloads;
private final ExtractRules extract;
private final Map<OperatingSystem, String> natives;
private final Map<String, String> natives;
private final List<CompatibilityRule> rules;
private final List<String> checksums;

Expand All @@ -64,7 +96,7 @@ public Library(Artifact artifact, String url, LibrariesDownloadInfo downloads) {
this(artifact, url, downloads, null, null, null, null, null, null);
}

public Library(Artifact artifact, String url, LibrariesDownloadInfo downloads, List<String> checksums, ExtractRules extract, Map<OperatingSystem, String> natives, List<CompatibilityRule> rules, String hint, String filename) {
public Library(Artifact artifact, String url, LibrariesDownloadInfo downloads, List<String> checksums, ExtractRules extract, Map<String, String> natives, List<CompatibilityRule> rules, String hint, String filename) {
this.artifact = artifact;
this.url = url;
this.downloads = downloads;
Expand Down Expand Up @@ -93,13 +125,27 @@ public String getVersion() {
}

public String getClassifier() {
if (artifact.getClassifier() == null)
if (natives != null && natives.containsKey(OperatingSystem.CURRENT_OS))
return natives.get(OperatingSystem.CURRENT_OS).replace("${arch}", Architecture.SYSTEM_ARCH.getBits().getBit());
else
return null;
else
if (artifact.getClassifier() == null) {
if (natives != null) {
for (String nativeDescriptor : POSSIBLE_NATIVE_DESCRIPTORS) {
String nd = natives.get(nativeDescriptor);
if (nd != null) {
return nd.replace("${arch}", Architecture.SYSTEM_ARCH.getBits().getBit());
}
}
} else if (downloads != null && downloads.getClassifiers() != null) {
for (String nativeDescriptor : POSSIBLE_NATIVE_DESCRIPTORS) {
LibraryDownloadInfo info = downloads.getClassifiers().get(nativeDescriptor);
if (info != null) {
return nativeDescriptor;
}
}
}

return null;
} else {
return artifact.getClassifier();
}
}

public ExtractRules getExtract() {
Expand All @@ -111,10 +157,17 @@ public boolean appliesToCurrentEnvironment() {
}

public boolean isNative() {
return natives != null && appliesToCurrentEnvironment();
if (!appliesToCurrentEnvironment()) {
return false;
}
if (natives != null) {
return true;
}

return downloads != null && downloads.getClassifiers().keySet().stream().anyMatch(s -> s.startsWith("native"));
}

protected LibraryDownloadInfo getRawDownloadInfo() {
private LibraryDownloadInfo getRawDownloadInfo() {
if (downloads != null) {
if (isNative())
return downloads.getClassifiers().get(getClassifier());
Expand All @@ -125,6 +178,10 @@ protected LibraryDownloadInfo getRawDownloadInfo() {
}
}

public Artifact getArtifact() {
return artifact;
}

public String getPath() {
LibraryDownloadInfo temp = getRawDownloadInfo();
if (temp != null && temp.getPath() != null)
Expand All @@ -137,12 +194,28 @@ public LibraryDownloadInfo getDownload() {
LibraryDownloadInfo temp = getRawDownloadInfo();
String path = getPath();
return new LibraryDownloadInfo(path,
Optional.ofNullable(temp).map(LibraryDownloadInfo::getUrl).orElse(Optional.ofNullable(url).orElse(Constants.DEFAULT_LIBRARY_URL) + path),
computePath(temp, path),
temp != null ? temp.getSha1() : null,
temp != null ? temp.getSize() : 0
);
}

private String computePath(LibraryDownloadInfo raw, String path) {
if (raw != null) {
String url = raw.getUrl();
if (url != null) {
return url;
}
}

String repo = Lang.requireNonNullElse(url, Constants.DEFAULT_LIBRARY_URL);
if (!repo.endsWith("/")) {
repo += '/';
}

return repo + path;
}

public boolean hasDownloadURL() {
LibraryDownloadInfo temp = getRawDownloadInfo();
if (temp != null) return temp.getUrl() != null;
Expand All @@ -159,6 +232,7 @@ public List<CompatibilityRule> getRules() {

/**
* Hint for how to locate the library file.
*
* @return null for default, "local" for location in version/&lt;version&gt;/libraries/filename
*/
@Nullable
Expand All @@ -168,6 +242,7 @@ public String getHint() {

/**
* Available when hint is "local"
*
* @return the filename of the local library in version/&lt;version&gt;/libraries/$filename
*/
@Nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,22 @@
*/
package org.jackhuang.hmcl.game;

import com.google.gson.*;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.platform.Architecture;
import org.jackhuang.hmcl.util.platform.OperatingSystem;

import java.io.IOException;
import java.util.regex.Pattern;

/**
*
* @author huangyuhui
*/
@JsonAdapter(OSRestriction.JsonAdapterImpl.class)
public final class OSRestriction {

private final OperatingSystem name;
Expand Down Expand Up @@ -78,4 +84,49 @@ public boolean allow() {
return true;
}

public static final class JsonAdapterImpl implements TypeAdapterFactory {
@SuppressWarnings("unchecked")
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (type.getRawType() != OSRestriction.class) {
return null;
}

TypeAdapter<OSRestriction> thisDelegate = (TypeAdapter<OSRestriction>) gson.getDelegateAdapter(this, type);

return (TypeAdapter<T>) new TypeAdapter<OSRestriction>() {
@Override
public void write(JsonWriter writer, OSRestriction restriction) throws IOException {
thisDelegate.write(writer, restriction);
}

@Override
public OSRestriction read(JsonReader reader) {
JsonObject element = gson.fromJson(reader, JsonObject.class);

OSRestriction restriction = thisDelegate.fromJsonTree(element);
if (restriction.getName() != null) {
return restriction;
}

JsonElement name = element.getAsJsonObject().get("name");
if (name != null && name.isJsonPrimitive()) {
JsonPrimitive jp = name.getAsJsonPrimitive();
if (jp.isString()) {
String[] parts = jp.getAsString().split("-", 2);
if (parts.length == 2) {
OperatingSystem os = gson.fromJson(new JsonPrimitive(parts[0]), OperatingSystem.class);
Architecture arch = gson.fromJson(new JsonPrimitive(parts[1]), Architecture.class);
if (os != null && arch != null) {
return new OSRestriction(os, restriction.version, arch.getCheckedName());
}
}
}
}

return restriction;
}
};
}
}
}
Loading