diff --git a/pkgs/by-name/hm/hmcl/0002-nix-use-terracotta-from-nix.patch b/pkgs/by-name/hm/hmcl/0002-nix-use-terracotta-from-nix.patch new file mode 100644 index 000000000000..651759ce63f0 --- /dev/null +++ b/pkgs/by-name/hm/hmcl/0002-nix-use-terracotta-from-nix.patch @@ -0,0 +1,43 @@ +From 541d055bf55703aa9e2c5a5e04a397f1d25efe28 Mon Sep 17 00:00:00 2001 +From: Moraxyc +Date: Wed, 29 Oct 2025 00:09:56 +0800 +Subject: [PATCH 2/3] nix: use terracotta from nix + +--- + .../org/jackhuang/hmcl/terracotta/TerracottaNative.java | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/terracotta/TerracottaNative.java b/HMCL/src/main/java/org/jackhuang/hmcl/terracotta/TerracottaNative.java +index 079537978..68954b09e 100644 +--- a/HMCL/src/main/java/org/jackhuang/hmcl/terracotta/TerracottaNative.java ++++ b/HMCL/src/main/java/org/jackhuang/hmcl/terracotta/TerracottaNative.java +@@ -47,7 +47,7 @@ public final class TerracottaNative { + + public TerracottaNative(List links, Path path, FileDownloadTask.IntegrityCheck checking) { + this.links = links; +- this.path = path; ++ this.path = Path.of("@TERRACOTTA_BIN@"); + this.checking = checking; + } + +@@ -130,9 +130,7 @@ public final class TerracottaNative { + + public ITerracottaProvider.Status status() throws IOException { + if (Files.exists(path)) { +- if (DigestUtils.digestToString(checking.getAlgorithm(), path).equalsIgnoreCase(checking.getChecksum())) { +- return ITerracottaProvider.Status.READY; +- } ++ return ITerracottaProvider.Status.READY; + } + + try { +@@ -144,4 +142,4 @@ public final class TerracottaNative { + } + return ITerracottaProvider.Status.NOT_EXIST; + } +-} ++} +\ No newline at end of file +-- +2.51.0 + diff --git a/pkgs/by-name/hm/hmcl/0003-nix-skip-terracotta-existence-check-on-darwin.patch b/pkgs/by-name/hm/hmcl/0003-nix-skip-terracotta-existence-check-on-darwin.patch new file mode 100644 index 000000000000..1df97fffc3d0 --- /dev/null +++ b/pkgs/by-name/hm/hmcl/0003-nix-skip-terracotta-existence-check-on-darwin.patch @@ -0,0 +1,27 @@ +From bcf95a23380424f2ca82649d93e9e0bdf8274b74 Mon Sep 17 00:00:00 2001 +From: Moraxyc +Date: Fri, 31 Oct 2025 14:23:54 +0800 +Subject: [PATCH 3/3] nix: skip terracotta existence check on darwin + +--- + .../org/jackhuang/hmcl/terracotta/provider/MacOSProvider.java | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/terracotta/provider/MacOSProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/terracotta/provider/MacOSProvider.java +index 00626f8b6..59125962d 100644 +--- a/HMCL/src/main/java/org/jackhuang/hmcl/terracotta/provider/MacOSProvider.java ++++ b/HMCL/src/main/java/org/jackhuang/hmcl/terracotta/provider/MacOSProvider.java +@@ -45,10 +45,6 @@ public final class MacOSProvider implements ITerracottaProvider { + public Status status() throws IOException { + assert binary != null; + +- if (!Files.exists(Path.of("/Applications/terracotta.app"))) { +- return Status.NOT_EXIST; +- } +- + return binary.status(); + } + +-- +2.51.0 + diff --git a/pkgs/by-name/hm/hmcl/package.nix b/pkgs/by-name/hm/hmcl/package.nix index 32dced713ba7..29ef808d50a8 100644 --- a/pkgs/by-name/hm/hmcl/package.nix +++ b/pkgs/by-name/hm/hmcl/package.nix @@ -2,18 +2,25 @@ lib, stdenv, fetchurl, + replaceVars, + terracotta, makeDesktopItem, wrapGAppsHook3, copyDesktopItems, imagemagick, jdk, jdk17, - jdk21, - hmclJdk ? jdk, + hmclJdk ? jdk.override { + # Required by jar file + enableJavaFX = true; + }, + buildPackages, + hmclJdkBuild ? buildPackages.jdk.override { + enableJavaFX = true; + }, minecraftJdks ? [ - jdk + hmclJdk jdk17 - jdk21 ], xorg, glib, @@ -45,8 +52,63 @@ stdenv.mkDerivation (finalAttrs: { hash = "sha256-1OVq4ujA2ZHboB7zEk7004kYgl9YcoM4qLq154MZMGo="; }; + # - HMCL prompts users to download prebuilt Terracotta binary for + # multi-user functionality, which is messy and doesn’t work on NixOS. + # - Building from source isn’t feasible because HMCL’s code relies on + # Microsoft OAuth, CurseForge, and other API keys that upstream doesn’t + # allow in custom builds, causing features to break. + # - Our workaround is to compile only the Java files that handle + # Terracotta downloads, package them into a patch jar that overrides + # the original classes, and have it load the original jar. This preserves + # the original jar’s integrity check and avoids modifying the upstream jar. + terracottaNativeJava = fetchurl { + name = "hmcl-terracotta-native-java-${finalAttrs.version}"; + url = "https://raw.githubusercontent.com/HMCL-dev/HMCL/v${finalAttrs.version}/${finalAttrs.terracottaNativeJavaPath}"; + hash = "sha256-sg8gBOMNdITmHeYByYriYp05ja1vtWPF/wuqdGmkgiA="; + }; + macOSProviderJava = fetchurl { + name = "hmcl-macos-provider-java-${finalAttrs.version}"; + url = "https://raw.githubusercontent.com/HMCL-dev/HMCL/v${finalAttrs.version}/${finalAttrs.macOSProviderJavaPath}"; + hash = "sha256-V8FNPPkq6/P3/HKcqKkAy6Ya1kUI3oEMfjEc8XdExgo="; + }; + terracottaNativeJavaPath = "HMCL/src/main/java/org/jackhuang/hmcl/terracotta/TerracottaNative.java"; + macOSProviderJavaPath = "HMCL/src/main/java/org/jackhuang/hmcl/terracotta/provider/MacOSProvider.java"; + dontUnpack = true; + prePatch = '' + install -Dm644 $terracottaNativeJava $terracottaNativeJavaPath + install -Dm644 $macOSProviderJava $macOSProviderJavaPath + ''; + + patches = [ + (replaceVars ./0002-nix-use-terracotta-from-nix.patch { + TERRACOTTA_BIN = lib.getExe terracotta; + }) + ./0003-nix-skip-terracotta-existence-check-on-darwin.patch + ]; + + buildPhase = '' + runHook preBuild + + # Build only classes we modified + javac -cp $src -d out $terracottaNativeJavaPath $macOSProviderJavaPath + + # Extract MANIFEST.MF from original jar + # We need Main-Class, Add-Opens, etc + jar xf $src META-INF/MANIFEST.MF + # Remove last empty line; otherwise file is invalid + sed -i '/^[[:space:]]*$/d' META-INF/MANIFEST.MF + # Let our patch jar be the entrace and load hmcl.jar + echo "Class-Path: $out/lib/hmcl/hmcl.jar" >> META-INF/MANIFEST.MF + + # Package our patch jar + # Reserve link to terracotta by not applying zip; nix cannot detect path from zipped jar + jar cvf0m patch.jar META-INF/MANIFEST.MF -C out . + + runHook postBuild + ''; + dontWrapGApps = true; desktopItems = [ @@ -65,6 +127,7 @@ stdenv.mkDerivation (finalAttrs: { wrapGAppsHook3 copyDesktopItems imagemagick + hmclJdkBuild ]; installPhase = '' @@ -72,6 +135,7 @@ stdenv.mkDerivation (finalAttrs: { mkdir -p $out/{bin,lib/hmcl} cp $src $out/lib/hmcl/hmcl.jar + cp patch.jar $out/lib/hmcl/hmcl-terracotta-patch.jar for n in 16 32 48 64 96 128 256 do @@ -106,15 +170,12 @@ stdenv.mkDerivation (finalAttrs: { alsa-lib ] ); - hmclJdk' = hmclJdk.override { - enableJavaFX = true; # Necessary for hardware acceleration. - }; in '' runHook preFixup - makeBinaryWrapper ${hmclJdk'}/bin/java $out/bin/hmcl \ - --add-flags "-jar $out/lib/hmcl/hmcl.jar" \ + makeBinaryWrapper ${hmclJdk}/bin/java $out/bin/hmcl \ + --add-flags "-jar $out/lib/hmcl/hmcl-terracotta-patch.jar" \ --set LD_LIBRARY_PATH ${libpath} \ --prefix PATH : "${lib.makeBinPath minecraftJdks}"\ ''${gappsWrapperArgs[@]} @@ -129,15 +190,15 @@ stdenv.mkDerivation (finalAttrs: { description = "Minecraft Launcher which is multi-functional, cross-platform and popular"; changelog = "https://docs.hmcl.net/changelog/stable.html"; mainProgram = "hmcl"; - sourceProvenance = with lib.sourceTypes; [ binaryBytecode ]; + sourceProvenance = with lib.sourceTypes; [ + fromSource # Our patch jar is built from source + binaryBytecode + ]; license = lib.licenses.gpl3Only; longDescription = '' Hello Minecraft! Launcher (HMCL) is a free, open-source, and cross-platform Minecraft launcher. It provides comprehensive support for managing multiple game versions and mod loaders, including Forge, NeoForge, Fabric, Quilt, LiteLoader, and OptiFine. - - Note: HMCL manages the Terracotta binary internally. On NixOS, Terracotta-related features - require `programs.nix-ld` to be enabled, as the runtime-downloaded binary is not patched. ''; maintainers = with lib.maintainers; [ daru-san diff --git a/pkgs/by-name/hm/hmcl/update.nix b/pkgs/by-name/hm/hmcl/update.nix index 05cf64efb00f..f58d578b95e1 100644 --- a/pkgs/by-name/hm/hmcl/update.nix +++ b/pkgs/by-name/hm/hmcl/update.nix @@ -36,5 +36,7 @@ writeShellApplication { nix-update hmcl --version="$version" update-source-version hmcl --source-key=icon --ignore-same-version + update-source-version hmcl --source-key=terracottaNativeJava --ignore-same-version + update-source-version hmcl --source-key=macOSProviderJava --ignore-same-version ''; }