hmcl: add patch jar to fix terracotta
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
From 541d055bf55703aa9e2c5a5e04a397f1d25efe28 Mon Sep 17 00:00:00 2001
|
||||
From: Moraxyc <i@qaq.li>
|
||||
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<URI> 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
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
From bcf95a23380424f2ca82649d93e9e0bdf8274b74 Mon Sep 17 00:00:00 2001
|
||||
From: Moraxyc <i@qaq.li>
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
'';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user