From 1df962884cf28b38cc459ed6620dc704fa142bad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+CiiLu@users.noreply.github.com> Date: Sat, 11 Oct 2025 21:37:33 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20#4613=20=E4=BF=AE=E5=A4=8D=E6=9C=AC?= =?UTF-8?q?=E5=9C=B0=E5=AE=89=E8=A3=85=E5=8D=87=E7=BA=A7=20Cleanroom=20?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E9=97=AE=E9=A2=98=20(#4625)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../download/DefaultDependencyManager.java | 6 ++ .../cleanroom/CleanroomInstallTask.java | 65 ++++++++++++++++--- 2 files changed, 61 insertions(+), 10 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java index d1a223e9e..455aa622e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java @@ -17,6 +17,7 @@ */ package org.jackhuang.hmcl.download; +import org.jackhuang.hmcl.download.cleanroom.CleanroomInstallTask; import org.jackhuang.hmcl.download.forge.ForgeInstallTask; import org.jackhuang.hmcl.download.game.GameAssetDownloadTask; import org.jackhuang.hmcl.download.game.GameDownloadTask; @@ -182,6 +183,11 @@ public class DefaultDependencyManager extends AbstractDependencyManager { return Task .composeAsync(() -> { + try { + return CleanroomInstallTask.install(this, oldVersion, installer); + } catch (IOException ignore) { + } + try { return NeoForgeInstallTask.install(this, oldVersion, installer); } catch (IOException ignore) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/cleanroom/CleanroomInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/cleanroom/CleanroomInstallTask.java index de2ce3de9..9d9baf252 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/cleanroom/CleanroomInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/cleanroom/CleanroomInstallTask.java @@ -21,30 +21,48 @@ import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.download.UnsupportedInstallationException; import org.jackhuang.hmcl.download.VersionMismatchException; +import org.jackhuang.hmcl.download.forge.ForgeNewInstallProfile; import org.jackhuang.hmcl.download.forge.ForgeNewInstallTask; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.gson.JsonUtils; +import org.jackhuang.hmcl.util.io.CompressingUtils; import java.io.IOException; +import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; import java.util.Collection; import java.util.Collections; +import java.util.Map; +import java.util.Optional; public final class CleanroomInstallTask extends Task { private final DefaultDependencyManager dependencyManager; private final Version version; - private Path installer; private final CleanroomRemoteVersion remote; + private Path installer; private FileDownloadTask dependent; private Task task; + private String selfVersion; public CleanroomInstallTask(DefaultDependencyManager dependencyManager, Version version, CleanroomRemoteVersion remoteVersion) { this.dependencyManager = dependencyManager; this.version = version; this.remote = remoteVersion; + + setSignificance(TaskSignificance.MODERATE); + } + + public CleanroomInstallTask(DefaultDependencyManager dependencyManager, Version version, String selfVersion, Path installer) { + this.dependencyManager = dependencyManager; + this.version = version; + this.selfVersion = selfVersion; + this.remote = null; + this.installer = installer; + setSignificance(TaskSignificance.MODERATE); } @@ -55,14 +73,16 @@ public final class CleanroomInstallTask extends Task { @Override public void preExecute() throws Exception { - installer = Files.createTempFile("cleanroom-installer", ".jar"); + if (installer == null) { + installer = Files.createTempFile("cleanroom-installer", ".jar"); - dependent = new FileDownloadTask( - dependencyManager.getDownloadProvider().injectURLsWithCandidates(remote.getUrls()), - installer, null); - dependent.setCacheRepository(dependencyManager.getCacheRepository()); - dependent.setCaching(true); - dependent.addIntegrityCheckHandler(FileDownloadTask.ZIP_INTEGRITY_CHECK_HANDLER); + dependent = new FileDownloadTask( + dependencyManager.getDownloadProvider().injectURLsWithCandidates(remote.getUrls()), + installer, null); + dependent.setCacheRepository(dependencyManager.getCacheRepository()); + dependent.setCaching(true); + dependent.addIntegrityCheckHandler(FileDownloadTask.ZIP_INTEGRITY_CHECK_HANDLER); + } } @Override @@ -78,7 +98,7 @@ public final class CleanroomInstallTask extends Task { @Override public Collection> getDependents() { - return Collections.singleton(dependent); + return dependent == null ? Collections.emptySet() : Collections.singleton(dependent); } @Override @@ -88,6 +108,31 @@ public final class CleanroomInstallTask extends Task { @Override public void execute() throws IOException, VersionMismatchException, UnsupportedInstallationException { - task = new ForgeNewInstallTask(dependencyManager, version, remote.getSelfVersion(), installer).thenApplyAsync((version) -> version.setId(LibraryAnalyzer.LibraryType.CLEANROOM.getPatchId())); + if (selfVersion == null) { + task = new ForgeNewInstallTask(dependencyManager, version, remote.getSelfVersion(), installer).thenApplyAsync((version) -> version.setId(LibraryAnalyzer.LibraryType.CLEANROOM.getPatchId())); + } else { + task = new ForgeNewInstallTask(dependencyManager, version, selfVersion, installer).thenApplyAsync((version) -> version.setId(LibraryAnalyzer.LibraryType.CLEANROOM.getPatchId())); + } + } + + public static Task install(DefaultDependencyManager dependencyManager, Version version, Path installer) throws IOException, VersionMismatchException { + Optional gameVersion = dependencyManager.getGameRepository().getGameVersion(version); + if (gameVersion.isEmpty()) throw new IOException(); + try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) { + String installProfileText = Files.readString(fs.getPath("install_profile.json")); + Map installProfile = JsonUtils.fromNonNullJson(installProfileText, Map.class); + if (LibraryAnalyzer.LibraryType.CLEANROOM.getPatchId().equals(installProfile.get("profile"))) { + ForgeNewInstallProfile profile = JsonUtils.fromNonNullJson(installProfileText, ForgeNewInstallProfile.class); + if (!gameVersion.get().equals(profile.getMinecraft())) + throw new VersionMismatchException(profile.getMinecraft(), gameVersion.get()); + return new CleanroomInstallTask(dependencyManager, version, modifyVersion(profile.getVersion()), installer); + } else { + throw new IOException(); + } + } + } + + private static String modifyVersion(String version) { + return version.replace("cleanroom-", ""); } }