From b7451ea9fb109a692dea212f47613d58a1fc1a34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:02:51 +0800 Subject: [PATCH 01/23] =?UTF-8?q?=E6=9A=96=E9=A3=8E=E8=BD=BB=E6=8E=A8?= =?UTF-8?q?=E6=98=A5=E6=B1=9F=E6=B0=B4=20=E5=BC=95=E6=9D=A5=E6=A1=83?= =?UTF-8?q?=E9=A6=99=20=E6=B2=81=E9=B1=BC=E5=84=BF=E8=82=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../download/fabric/FabricInstallTask.java | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricInstallTask.java index b21586201a..0d95200fcb 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricInstallTask.java @@ -129,28 +129,7 @@ private Version getPatch(FabricInfo fabricInfo, String gameVersion, String loade } @JsonSerializable - public static class FabricInfo { - private final LoaderInfo loader; - private final IntermediaryInfo intermediary; - private final JsonObject launcherMeta; - - public FabricInfo(LoaderInfo loader, IntermediaryInfo intermediary, JsonObject launcherMeta) { - this.loader = loader; - this.intermediary = intermediary; - this.launcherMeta = launcherMeta; - } - - public LoaderInfo getLoader() { - return loader; - } - - public IntermediaryInfo getIntermediary() { - return intermediary; - } - - public JsonObject getLauncherMeta() { - return launcherMeta; - } + public record FabricInfo(LoaderInfo loader, IntermediaryInfo intermediary, JsonObject launcherMeta) { } @JsonSerializable From d7ccabcf691b64ed8a4d790d5a7698811ec08b09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:03:25 +0800 Subject: [PATCH 02/23] =?UTF-8?q?=E6=BB=A1=E5=9C=B0=E6=98=A5=E8=8A=B1?= =?UTF-8?q?=E5=BC=80=E6=96=B0=E8=95=8A=20=E5=9B=9B=E6=9C=88=E8=8A=B3?= =?UTF-8?q?=E8=8F=B2=20=E6=99=AF=E8=89=B2=E5=A4=9A=E5=A6=A9=E5=AA=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/image/ornithe.png | Bin 0 -> 63884 bytes HMCL/src/main/resources/assets/img/ornithe.png | Bin 0 -> 2031 bytes .../main/resources/assets/img/ornithe@2x.png | Bin 0 -> 6246 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 HMCL/image/ornithe.png create mode 100644 HMCL/src/main/resources/assets/img/ornithe.png create mode 100644 HMCL/src/main/resources/assets/img/ornithe@2x.png diff --git a/HMCL/image/ornithe.png b/HMCL/image/ornithe.png new file mode 100644 index 0000000000000000000000000000000000000000..ab7c6362415b94a789f0db780165fbe651a11245 GIT binary patch literal 63884 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%0A#1pUw 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 BgM0u0 literal 0 HcmV?d00001 diff --git a/HMCL/src/main/resources/assets/img/ornithe.png b/HMCL/src/main/resources/assets/img/ornithe.png new file mode 100644 index 0000000000000000000000000000000000000000..363b25e65c127a6ebe59e493a0148e3930c679b2 GIT binary patch literal 2031 zcmZ8idpy(YAOCJ`nV3d(CgxU|bV`b9auTy)IVQtGN-lFBV^kVKA{ufzgd$r=qBGZA z^Fz(LY`KggB$Zs2a%pl|zv-OcKfllG^?u&(&-MBI^Sqvq|%*3?m)2;Kz39snkFpnwVp3V@{Q zgcPd(>h*1QgEst%ukUjJ1O^aNc9Fs_5%MeUFV*XIPKx#Z|MCA_3Tyy?8!`YyTA_c? zKp%AHpQ-B|&^!N3%984J154+Ce^ruPTF8pk^H9t|=1Vjqk2#;_dG`n*a1V*qI{4 zpN8yq(WG{xshNTIv8mk_WF-uBuk*vMjJ-)2ODg=8@J406udk}#=4;zWxIbDM{2yO# zTSuQq%ErE8iL2oN&^ED#Z@ZTQiveKDhZJMJ7iD(NI$O(YmoA_{R_(U|1Q-&7R+P9| z_gK9p&Z+%zWd`jIi4~EWMkA(1q&B9Ai1u#;7FOYNn~86D0YS^~KIU zo!+y_q=q$vhx=Bk_?0=c0nf6w>v5*AD=y{anqcMUA?QpCz!&Jl_v88I{Tupal3(rb zy%vwa^3ULhyJ2tegAUY+-eY4`wl37x#WxogSHQC9UgC^W22`Cj8B@Y(MBi-m&DR|r zH;LzWPv!I zspCyG5pg_Bw||XNnJrs-0S0!!$Yo(!dMH@N&aHpk(bE@>xrBRlhHwI)B}Ja}CV$aW zNIVpcw@O&V^(#i$BWx`GjxADFV-Qk6MO4S&Ad!L>1ZkytqOqjjmKbQh4N_42+P{|C z!blz6Uu}obf`hQJCrvj-W;@-Y<+09cw`U&C-^tFI`VDnh=ztz~>c7Ey)Kxb)JVmQ@ zO)ti(A3HsK#wg$c0)RnP#yazM{fWg#DFW|a<3~kbAno4f?6O-Fr`oZ>hDqz`0M)t@ z@`p&9?G+9(GA$`NA?2e6(bA_ke>_U=JsoX!#UnLxEiI~7OWw0dlFKV=NDqPFLr)Ko2bDs2i(;1b1ge8G6_9d12YIoHzQfTnB6VKgW)D2e zl8cnIwjJ2}``t}{g_1{)x?7;y3$d13IEZ`F@)rCapJpK=wXDvC+WTEuAP+z`ZV%hQ zZPquKf4E=0FHJ?eA&W=Bt-XuUfP>zzB4%`88XOi(hvxIJdz{Pc1qCzvoCEO9NLRnWP4kR$TH7M z2Enkv=PGttJl?lOu8f=B<;uI^1_tg19=q>@!!gMp_@(KcN{Qz)*glO@QS(>p=gdsB znYRnOlH&10`fA*exlp`1sWb3P{cOuAdv9S*^bF}gcB;sugB;Mnxa&s&!$e8i#52YLD3)-W@?qMTlTc6m%S1_G+`eYx$3YdM1! z*8aA6_<}=ZzG5Cp??}$^w+}TY=2u@7(@|Gv1%i=B2l*hSP{bq9pT7nt=VANRp z@g+~=Mm=)HaqHs(CHt(#wp#FWQ*vaecx^yugQF02?jtF8;x(DA*k#c1v8FQ|L^IbI zynEuJ-*l2rKXFNR(_?(8`2LM6TXG+~NS;g|i0+9u*dbslSXFc!vzh)>U8Yq<>HEp9 g%TK7xPlyG6LQ4QOZg%eE^!l$wz!Pzm*mH6J1tODym;e9( literal 0 HcmV?d00001 diff --git a/HMCL/src/main/resources/assets/img/ornithe@2x.png b/HMCL/src/main/resources/assets/img/ornithe@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3c80f4413e9b869086acd85b9bed530808cc7dbe GIT binary patch literal 6246 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 literal 0 HcmV?d00001 From 2549445d08f3d52e5401ad24054ddbc7b0a631b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:04:29 +0800 Subject: [PATCH 03/23] =?UTF-8?q?=E6=98=AF=E8=B0=81=E5=B8=B8=E8=AF=B4?= =?UTF-8?q?=E7=A5=9E=E4=BB=99=E7=BE=8E=20=E6=88=91=E7=9C=8B=E4=BA=BA?= =?UTF-8?q?=E9=97=B4=E6=9C=80=E6=9C=89=E6=BB=8B=E5=91=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/src/main/resources/assets/lang/I18N.properties | 2 ++ HMCL/src/main/resources/assets/lang/I18N_zh.properties | 2 ++ HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 2 ++ 3 files changed, 6 insertions(+) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index d3a31603b2..732e96dc19 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -749,6 +749,8 @@ install.installer.not_installed=Not installed install.installer.optifine=OptiFine install.installer.quilt=Quilt install.installer.quilt-api=QSL/QFAPI +install.installer.ornithe=Ornithe +install.installer.ornithe-osl=Ornithe OSL install.installer.version=%s install.installer.external_version=%s (Installed by external process, which cannot be configured) install.installing=Installing diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 4f003327cc..ebb7041443 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -553,6 +553,8 @@ install.installer.not_installed=未安裝 install.installer.optifine=OptiFine install.installer.quilt=Quilt install.installer.quilt-api=QSL/QFAPI +install.installer.ornithe=Ornithe +install.installer.ornithe-osl=Ornithe OSL install.installer.version=%s install.installer.external_version=%s [由外部安裝的版本,無法解除安裝或更換] install.installing=安裝 diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index 38f96a7fe2..ee2f087a12 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -558,6 +558,8 @@ install.installer.not_installed=未安装 install.installer.optifine=OptiFine install.installer.quilt=Quilt install.installer.quilt-api=QSL/QFAPI +install.installer.ornithe=Ornithe +install.installer.ornithe-osl=Ornithe OSL install.installer.version=%s install.installer.external_version=%s (由外部安装的版本,无法卸载或更换) install.installing=安装 From 567b5b12414fe0e24f432115dd4385bfc2f35444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:04:54 +0800 Subject: [PATCH 04/23] =?UTF-8?q?=E4=B8=8D=E5=A6=82=E8=87=AA=E5=9C=A8?= =?UTF-8?q?=E5=8C=96=E4=BD=9C=E8=B0=81=20=E6=B8=B8=E6=88=8F=E7=BA=A2?= =?UTF-8?q?=E5=B0=98=20=E4=B8=80=E5=BF=83=E6=B2=89=E9=86=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/jackhuang/hmcl/setting/VersionIconType.java | 3 ++- .../src/main/java/org/jackhuang/hmcl/mod/ModLoaderType.java | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionIconType.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionIconType.java index dd19336b8c..b2f595a8f5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionIconType.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionIconType.java @@ -37,7 +37,8 @@ public enum VersionIconType { QUILT("/assets/img/quilt.png"), APRIL_FOOLS("/assets/img/april_fools.png"), CLEANROOM("/assets/img/cleanroom.png"), - LEGACY_FABRIC("/assets/img/legacyfabric.png") + LEGACY_FABRIC("/assets/img/legacyfabric.png"), + ORNITHE("/assets/img/ornithe.png") ; // Please append new items at last diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModLoaderType.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModLoaderType.java index c1205803a6..a160076a59 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModLoaderType.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModLoaderType.java @@ -23,6 +23,7 @@ public enum ModLoaderType { CLEANROOM, NEO_FORGED, FABRIC, + ORNITHE, QUILT, LITE_LOADER, LEGACY_FABRIC, From d3cc8059647463b5c136e0ccefad86a52ba88bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:05:14 +0800 Subject: [PATCH 05/23] =?UTF-8?q?=E8=B5=B0=E9=A9=AC=E8=A7=82=E8=8A=B1=20?= =?UTF-8?q?=E5=81=9C=E9=A9=BB=E5=87=A0=E5=9B=9E=20=E6=88=8F=E4=B8=80?= =?UTF-8?q?=E6=9B=B2=20=E9=85=92=E4=B8=80=E6=9D=AF=20=E6=98=A5=E9=A3=8E?= =?UTF-8?q?=E8=BD=BB=E8=BD=BB=E5=90=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java | 4 ++++ .../java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java | 2 ++ 2 files changed, 6 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index 3c738da352..cee45f51f0 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -158,6 +158,10 @@ private void updateSupportedLoaders(ModManager modManager) { supportedLoaders.add(ModLoaderType.FABRIC); } + if (analyzer.has(LibraryAnalyzer.LibraryType.ORNITHE)) { + supportedLoaders.add(ModLoaderType.FABRIC); + } + if (analyzer.has(LibraryAnalyzer.LibraryType.FABRIC) && modManager.hasMod("kilt", ModLoaderType.FABRIC)) { supportedLoaders.add(ModLoaderType.FORGE); supportedLoaders.add(ModLoaderType.NEO_FORGED); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java index bad72233f5..24ffdc62d3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java @@ -477,6 +477,7 @@ final class ModInfoDialog extends JFXDialogLayout { case FABRIC -> i18n("install.installer.fabric"); case LITE_LOADER -> i18n("install.installer.liteloader"); case QUILT -> i18n("install.installer.quilt"); + case ORNITHE -> i18n("install.installer.ornithe"); default -> null; }; if (loaderName == null) @@ -647,6 +648,7 @@ protected void updateControl(ModInfoObject dataItem, boolean empty) { case FABRIC -> content.addTagWarning(i18n("install.installer.fabric")); case LITE_LOADER -> content.addTagWarning(i18n("install.installer.liteloader")); case QUILT -> content.addTagWarning(i18n("install.installer.quilt")); + case ORNITHE -> content.addTagWarning(i18n("install.installer.ornithe")); } } From b63ba395eae3cb019fa9906d494a25f4d8c86259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:05:49 +0800 Subject: [PATCH 06/23] =?UTF-8?q?=E6=9C=88=E5=84=BF=E5=BC=AF=E5=BC=AF=20?= =?UTF-8?q?=E5=8B=BE=E4=BD=8F=E4=BA=86=E5=A4=9C=E6=99=9A=20=E7=92=80?= =?UTF-8?q?=E7=92=A8=20=E5=86=99=E4=B8=8B=E6=B5=AA=E6=BC=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hmcl/download/legacyfabric/LegacyFabricInstallTask.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricInstallTask.java index f2abb9c33a..731ac4935d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricInstallTask.java @@ -80,7 +80,7 @@ public void execute() { } private Version getPatch(FabricInstallTask.FabricInfo legacyFabricInfo, String gameVersion, String loaderVersion) { - JsonObject launcherMeta = legacyFabricInfo.getLauncherMeta(); + JsonObject launcherMeta = legacyFabricInfo.launcherMeta(); Arguments arguments = new Arguments(); String mainClass; @@ -107,8 +107,8 @@ private Version getPatch(FabricInstallTask.FabricInfo legacyFabricInfo, String g } // libraries.add(new Library(Artifact.fromDescriptor(legacyFabricInfo.hashed.maven), getMavenRepositoryByGroup(legacyFabricInfo.hashed.maven), null)); - libraries.add(new Library(Artifact.fromDescriptor(legacyFabricInfo.getIntermediary().getMaven()), getMavenRepositoryByGroup(legacyFabricInfo.getIntermediary().getMaven()), null)); - libraries.add(new Library(Artifact.fromDescriptor(legacyFabricInfo.getLoader().getMaven()), getMavenRepositoryByGroup(legacyFabricInfo.getLoader().getMaven()), null)); + libraries.add(new Library(Artifact.fromDescriptor(legacyFabricInfo.intermediary().getMaven()), getMavenRepositoryByGroup(legacyFabricInfo.intermediary().getMaven()), null)); + libraries.add(new Library(Artifact.fromDescriptor(legacyFabricInfo.loader().getMaven()), getMavenRepositoryByGroup(legacyFabricInfo.loader().getMaven()), null)); return new Version(LibraryAnalyzer.LibraryType.LEGACY_FABRIC.getPatchId(), loaderVersion, Version.PRIORITY_LOADER, arguments, mainClass, libraries); } From e734da46a504aca1f403bac6c7facd23b1abda13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:06:07 +0800 Subject: [PATCH 07/23] =?UTF-8?q?=E6=B4=92=E8=90=BD=E5=A4=9A=E5=B0=91?= =?UTF-8?q?=E6=9C=88=E8=89=B2=E4=BC=B4=E6=88=91=E7=83=9B=E5=85=89=E5=85=B1?= =?UTF-8?q?=E6=9E=95=E7=9C=A0=20=E7=85=A7=E4=BA=AE=E8=B0=81=E7=9A=84?= =?UTF-8?q?=E6=AC=A2=E5=BF=83=20=E8=B0=81=E7=9A=84=E7=AC=91=E9=A2=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jackhuang/hmcl/ui/construct/TaskListPane.java | 8 ++++++++ .../org/jackhuang/hmcl/ui/versions/VersionIconDialog.java | 1 + 2 files changed, 9 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java index 08c390a95e..cd893ec9d0 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java @@ -46,6 +46,8 @@ import org.jackhuang.hmcl.download.neoforge.NeoForgeInstallTask; import org.jackhuang.hmcl.download.neoforge.NeoForgeOldInstallTask; import org.jackhuang.hmcl.download.optifine.OptiFineInstallTask; +import org.jackhuang.hmcl.download.ornithe.OrnitheInstallTask; +import org.jackhuang.hmcl.download.ornithe.OrnitheOSLInstallTask; import org.jackhuang.hmcl.download.quilt.QuiltAPIInstallTask; import org.jackhuang.hmcl.download.quilt.QuiltInstallTask; import org.jackhuang.hmcl.game.HMCLModpackInstallTask; @@ -184,6 +186,10 @@ public void onRunning(Task task) { task.setName(i18n("install.installer.install", i18n("install.installer.fabric"))); } else if (task instanceof FabricAPIInstallTask) { task.setName(i18n("install.installer.install", i18n("install.installer.fabric-api"))); + } else if (task instanceof OrnitheInstallTask) { + task.setName(i18n("install.installer.install", i18n("install.installer.ornithe"))); + } else if (task instanceof OrnitheOSLInstallTask) { + task.setName(i18n("install.installer.install", i18n("install.installer.ornithe-osl"))); } else if (task instanceof QuiltInstallTask) { task.setName(i18n("install.installer.install", i18n("install.installer.quilt"))); } else if (task instanceof QuiltAPIInstallTask) { @@ -455,6 +461,8 @@ private StageNode(String stage) { case "hmcl.install.fabric-api" -> i18n("install.installer.install", i18n("install.installer.fabric-api") + " " + stageValue); case "hmcl.install.legacyfabric" -> i18n("install.installer.install", i18n("install.installer.legacyfabric") + " " + stageValue); case "hmcl.install.legacyfabric-api" -> i18n("install.installer.install", i18n("install.installer.legacyfabric-api") + " " + stageValue); + case "hmcl.install.ornithe" -> i18n("install.installer.install", i18n("install.installer.ornithe") + " " + stageValue); + case "hmcl.install.ornithe-osl" -> i18n("install.installer.install", i18n("install.installer.ornithe-osl") + " " + stageValue); case "hmcl.install.quilt" -> i18n("install.installer.install", i18n("install.installer.quilt") + " " + stageValue); case "hmcl.install.quilt-api" -> i18n("install.installer.install", i18n("install.installer.quilt-api") + " " + stageValue); default -> i18n(stageKey); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionIconDialog.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionIconDialog.java index a48fc63a09..f769d7e24c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionIconDialog.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionIconDialog.java @@ -65,6 +65,7 @@ public VersionIconDialog(Profile profile, String versionId, Runnable onFinish) { createIcon(VersionIconType.CRAFT_TABLE), createIcon(VersionIconType.FABRIC), createIcon(VersionIconType.LEGACY_FABRIC), + createIcon(VersionIconType.ORNITHE), createIcon(VersionIconType.FORGE), createIcon(VersionIconType.CLEANROOM), createIcon(VersionIconType.NEO_FORGE), From ca8eed57ff0d25c54bdfd6794152ee76f21cceb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:06:29 +0800 Subject: [PATCH 08/23] =?UTF-8?q?=E7=83=9F=E7=81=AB=E6=BC=AB=E6=BC=AB=20?= =?UTF-8?q?=E5=8B=BE=E7=94=BB=E7=9D=80=E5=B1=8B=E6=AA=90=20=E4=B8=8E?= =?UTF-8?q?=E8=B0=81=E7=9C=8B=20=E8=BF=99=E4=B8=87=E5=8D=83=E7=BB=9A?= =?UTF-8?q?=E7=83=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jackhuang/hmcl/download/LibraryAnalyzer.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java index f0c1b62ae1..3fa9cb707c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java @@ -219,6 +219,21 @@ protected boolean matchLibrary(Library library, List libraries) { } }, FABRIC_API(true, "fabric-api", "net\\.fabricmc", "fabric-api", null), + ORNITHE(true, "ornithe", "net\\.fabricmc", "fabric-loader", ModLoaderType.ORNITHE) { + @Override + protected boolean matchLibrary(Library library, List libraries) { + if (!super.matchLibrary(library, libraries)) { + return false; + } + for (Library l : libraries) { + if ("net.ornithemc".equals(l.getGroupId())) { + return false; + } + } + return true; + } + }, + ORNITHE_OSL(true, "ornithe-osl", "net\\.ornithemc", "ornithe-api", null), FORGE(true, "forge", "net\\.minecraftforge", "(forge|fmlloader)", ModLoaderType.FORGE) { private final Pattern FORGE_VERSION_MATCHER = Pattern.compile("^([0-9.]+)-(?[0-9.]+)(-([0-9.]+))?$"); From fc57b8a86a6562a10bf6eafd757d1aef75aa0c2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:12:09 +0800 Subject: [PATCH 09/23] =?UTF-8?q?=E5=8C=96=E4=BD=9C=E5=A4=9A=E5=B0=91?= =?UTF-8?q?=E5=9B=9E=E5=BF=86=E8=BD=BB=E6=9F=94=E6=B5=81=E6=B7=8C=E5=9C=A8?= =?UTF-8?q?=E6=8C=87=E5=B0=96=20=E9=9A=BE=E5=BE=97=E5=BF=83=E5=BF=83?= =?UTF-8?q?=E5=BF=B5=E5=BF=B5=20=E6=9C=80=E6=B8=A9=E6=9A=96=E6=98=AF?= =?UTF-8?q?=E4=BA=BA=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../download/ornithe/OrnitheInstallTask.java | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheInstallTask.java diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheInstallTask.java new file mode 100644 index 0000000000..321b95a9d1 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheInstallTask.java @@ -0,0 +1,130 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2020 huangyuhui 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 . + */ +package org.jackhuang.hmcl.download.ornithe; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.jackhuang.hmcl.download.DefaultDependencyManager; +import org.jackhuang.hmcl.download.LibraryAnalyzer; +import org.jackhuang.hmcl.download.UnsupportedInstallationException; +import org.jackhuang.hmcl.game.Arguments; +import org.jackhuang.hmcl.game.Artifact; +import org.jackhuang.hmcl.game.Library; +import org.jackhuang.hmcl.game.Version; +import org.jackhuang.hmcl.task.GetTask; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.gson.JsonUtils; + +import java.io.IOException; +import java.util.*; + +import static org.jackhuang.hmcl.download.UnsupportedInstallationException.FABRIC_NOT_COMPATIBLE_WITH_FORGE; +import static org.jackhuang.hmcl.download.fabric.FabricInstallTask.FabricInfo; + +/** + * Note: Fabric should be installed first. + * + * @author huangyuhui + */ +public final class OrnitheInstallTask extends Task { + + private final DefaultDependencyManager dependencyManager; + private final Version version; + private final OrnitheRemoteVersion remote; + private final GetTask launchMetaTask; + private final List> dependencies = new ArrayList<>(1); + + public OrnitheInstallTask(DefaultDependencyManager dependencyManager, Version version, OrnitheRemoteVersion remoteVersion) { + this.dependencyManager = dependencyManager; + this.version = version; + this.remote = remoteVersion; + + launchMetaTask = new GetTask(dependencyManager.getDownloadProvider().injectURLsWithCandidates(remoteVersion.getUrls())); + launchMetaTask.setCacheRepository(dependencyManager.getCacheRepository()); + } + + @Override + public boolean doPreExecute() { + return true; + } + + @Override + public void preExecute() throws Exception { + if (!Objects.equals("net.minecraft.client.main.Main", version.resolve(dependencyManager.getGameRepository()).getMainClass())) + throw new UnsupportedInstallationException(FABRIC_NOT_COMPATIBLE_WITH_FORGE); + } + + @Override + public Collection> getDependents() { + return Collections.singleton(launchMetaTask); + } + + @Override + public Collection> getDependencies() { + return dependencies; + } + + @Override + public boolean isRelyingOnDependencies() { + return false; + } + + @Override + public void execute() throws IOException { + FabricInfo fabricInfo = JsonUtils.GSON.fromJson(launchMetaTask.getResult(), FabricInfo.class); + if (fabricInfo == null) + throw new IOException("Fabric metadata is invalid"); + + setResult(getPatch(fabricInfo, remote.getGameVersion(), remote.getSelfVersion())); + + dependencies.add(dependencyManager.checkLibraryCompletionAsync(getResult(), true)); + } + + private Version getPatch(FabricInfo fabricInfo, String gameVersion, String loaderVersion) { + JsonObject launcherMeta = fabricInfo.launcherMeta(); + Arguments arguments = new Arguments(); + + String mainClass; + if (!launcherMeta.get("mainClass").isJsonObject()) { + mainClass = launcherMeta.get("mainClass").getAsString(); + } else { + mainClass = launcherMeta.get("mainClass").getAsJsonObject().get("client").getAsString(); + } + + if (launcherMeta.has("launchwrapper")) { + String clientTweaker = launcherMeta.get("launchwrapper").getAsJsonObject().get("tweakers").getAsJsonObject().get("client").getAsJsonArray().get(0).getAsString(); + arguments = arguments.addGameArguments("--tweakClass", clientTweaker); + } + + JsonObject librariesObject = launcherMeta.getAsJsonObject("libraries"); + List libraries = new ArrayList<>(); + + // "common, server" is hard coded in fabric installer. + // Don't know the purpose of ignoring client libraries. + for (String side : new String[]{"common", "server"}) { + for (JsonElement element : librariesObject.getAsJsonArray(side)) { + libraries.add(JsonUtils.GSON.fromJson(element, Library.class)); + } + } + + libraries.add(new Library(Artifact.fromDescriptor(fabricInfo.intermediary().getMaven()), "https://maven.fabricmc.net/", null)); + libraries.add(new Library(Artifact.fromDescriptor(fabricInfo.intermediary().getMaven()), "https://maven.fabricmc.net/", null)); + + return new Version(LibraryAnalyzer.LibraryType.FABRIC.getPatchId(), loaderVersion, Version.PRIORITY_LOADER, arguments, mainClass, libraries); + } +} From 1c08b53a6265ba2dad95ebad97ca1a84c7a2bb7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:12:44 +0800 Subject: [PATCH 10/23] =?UTF-8?q?=E6=98=AF=E6=88=91=E5=BF=83=E8=AF=B4?= =?UTF-8?q?=E4=BA=BA=E9=97=B4=E7=BE=8E=20=E8=8B=A6=E8=BE=A3=E9=85=B8?= =?UTF-8?q?=E7=94=9C=20=E6=9C=80=E6=98=AF=E7=8F=8D=E8=B4=B5=20=E4=BD=95?= =?UTF-8?q?=E5=BF=85=E8=AE=B0=E5=BE=97=E8=87=AA=E6=98=AF=E8=B0=81=E5=A4=A7?= =?UTF-8?q?=E5=8D=83=E4=B8=96=E7=95=8C=20=E7=BB=86=E7=BB=86=E5=9B=9E?= =?UTF-8?q?=E5=91=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ornithe/OrnitheRemoteVersion.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheRemoteVersion.java diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheRemoteVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheRemoteVersion.java new file mode 100644 index 0000000000..3034d43353 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheRemoteVersion.java @@ -0,0 +1,44 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2021 huangyuhui 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 . + */ +package org.jackhuang.hmcl.download.ornithe; + +import org.jackhuang.hmcl.download.DefaultDependencyManager; +import org.jackhuang.hmcl.download.LibraryAnalyzer; +import org.jackhuang.hmcl.download.RemoteVersion; +import org.jackhuang.hmcl.game.Version; +import org.jackhuang.hmcl.task.Task; + +import java.util.List; + +public class OrnitheRemoteVersion extends RemoteVersion { + /** + * Constructor. + * + * @param gameVersion the Minecraft version that this remote version suits. + * @param selfVersion the version string of the remote version. + * @param urls the installer or universal jar original URL. + */ + OrnitheRemoteVersion(String gameVersion, String selfVersion, List urls) { + super(LibraryAnalyzer.LibraryType.ORNITHE.getPatchId(), gameVersion, selfVersion, null, urls); + } + + @Override + public Task getInstallTask(DefaultDependencyManager dependencyManager, Version baseVersion) { + return new OrnitheInstallTask(dependencyManager, baseVersion, this); + } +} From 320cd8cb41c49e1b2ed85e1a28170e50e18091f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:12:59 +0800 Subject: [PATCH 11/23] =?UTF-8?q?=E6=B5=93=E5=A2=A8=E9=87=8D=E5=BD=A9=20?= =?UTF-8?q?=E9=93=AD=E5=BF=83=E5=87=A0=E5=9B=9E=20=E6=A2=A6=E4=B8=80?= =?UTF-8?q?=E6=9B=B2=20=E9=86=89=E4=B8=80=E6=9D=AF=20=E5=90=AC=E9=A3=8E?= =?UTF-8?q?=E9=9D=99=E9=9D=99=E5=90=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../download/ornithe/OrnitheVersionList.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheVersionList.java diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheVersionList.java new file mode 100644 index 0000000000..4c2c979d1f --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheVersionList.java @@ -0,0 +1,80 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2021 huangyuhui 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 . + */ +package org.jackhuang.hmcl.download.ornithe; + +import org.jackhuang.hmcl.download.DownloadProvider; +import org.jackhuang.hmcl.download.VersionList; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.gson.JsonSerializable; +import org.jackhuang.hmcl.util.gson.JsonUtils; +import org.jackhuang.hmcl.util.io.NetworkUtils; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; + +public final class OrnitheVersionList extends VersionList { + private final DownloadProvider downloadProvider; + + public OrnitheVersionList(DownloadProvider downloadProvider) { + this.downloadProvider = downloadProvider; + } + + @Override + public boolean hasType() { + return false; + } + + @Override + public Task refreshAsync() { + return Task.runAsync(() -> { + List gameVersions = getGameVersions(GAME_META_URL); + List loaderVersions = getGameVersions(LOADER_META_URL); + + lock.writeLock().lock(); + + try { + for (String gameVersion : gameVersions) + for (String loaderVersion : loaderVersions) + versions.put(gameVersion, new OrnitheRemoteVersion(gameVersion, loaderVersion, + Collections.singletonList(getLaunchMetaUrl(gameVersion, loaderVersion)))); + } finally { + lock.writeLock().unlock(); + } + }); + } + + private static final String LOADER_META_URL = "https://meta.ornithemc.net/v2/versions/loader"; + private static final String GAME_META_URL = "https://meta.ornithemc.net/v2/versions/game"; + + private List getGameVersions(String metaUrl) throws IOException { + String json = NetworkUtils.doGet(downloadProvider.injectURLWithCandidates(metaUrl)); + return JsonUtils.GSON.fromJson(json, listTypeOf(GameVersion.class)) + .stream().map(GameVersion::version).collect(Collectors.toList()); + } + + private static String getLaunchMetaUrl(String gameVersion, String loaderVersion) { + return String.format("https://meta.ornithemc.net/v2/versions/loader/%s/%s", gameVersion, loaderVersion); + } + + @JsonSerializable + private record GameVersion(String version, String maven, boolean stable) {} +} From 413815d61077ffe61f929ae52524a4f2051cb3d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:13:17 +0800 Subject: [PATCH 12/23] =?UTF-8?q?=E6=9C=88=E5=BD=B1=E5=BC=AF=E5=BC=AF=20?= =?UTF-8?q?=E5=8B=BE=E4=BD=8F=E4=BA=86=E5=A4=9C=E6=99=9A=20=E6=B5=AE?= =?UTF-8?q?=E5=B9=BB=20=E5=88=BB=E4=B8=8B=E6=B5=AA=E6=BC=AB=20=E5=80=92?= =?UTF-8?q?=E6=98=A0=E5=A4=9A=E5=B0=91=E8=90=A4=E5=85=89=E4=BC=B4=E6=88=91?= =?UTF-8?q?=E6=B8=85=E6=AD=8C=E5=85=B1=E6=9E=95=E7=9C=A0=20=E5=94=A4?= =?UTF-8?q?=E8=B5=B7=E8=B0=81=E7=9A=84=E6=80=9D=E7=BB=AA=20=E8=B0=81?= =?UTF-8?q?=E7=9A=84=E7=9C=B7=E6=81=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ornithe/OrnitheOSLVersionList.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheOSLVersionList.java diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheOSLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheOSLVersionList.java new file mode 100644 index 0000000000..b6f9f7696c --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheOSLVersionList.java @@ -0,0 +1,53 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2021 huangyuhui 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 . + */ +package org.jackhuang.hmcl.download.ornithe; + +import org.jackhuang.hmcl.download.DownloadProvider; +import org.jackhuang.hmcl.download.VersionList; +import org.jackhuang.hmcl.mod.RemoteMod; +import org.jackhuang.hmcl.mod.modrinth.ModrinthRemoteModRepository; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.Lang; + +import java.util.Collections; + +public class OrnitheOSLVersionList extends VersionList { + + private final DownloadProvider downloadProvider; + + public OrnitheOSLVersionList(DownloadProvider downloadProvider) { + this.downloadProvider = downloadProvider; + } + + @Override + public boolean hasType() { + return false; + } + + @Override + public Task refreshAsync() { + return Task.runAsync(() -> { + for (RemoteMod.Version modVersion : Lang.toIterable(ModrinthRemoteModRepository.MODS.getRemoteVersionsById(downloadProvider, "P7dR8mSH"))) { + for (String gameVersion : modVersion.getGameVersions()) { + versions.put(gameVersion, new OrnitheOSLRemoteVersion(gameVersion, modVersion.getVersion(), modVersion.getName(), modVersion.getDatePublished(), modVersion, + Collections.singletonList(modVersion.getFile().getUrl()))); + } + } + }); + } +} From 167ddd7141ff8fcf91dd890d6c06afc3235118d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:13:33 +0800 Subject: [PATCH 13/23] =?UTF-8?q?=E7=81=AF=E7=81=AB=E6=BC=AB=E6=BC=AB=20?= =?UTF-8?q?=E7=82=B9=E4=BA=AE=E4=BA=86=E5=B1=8B=E6=AA=90=20=E6=98=AF?= =?UTF-8?q?=E8=B0=81=E7=9C=8B=20=E8=BF=99=E6=BC=AB=E5=A4=A9=E7=81=BF?= =?UTF-8?q?=E7=83=82=20=E6=89=BF=E8=BD=BD=E5=A4=9A=E5=B0=91=E6=95=85?= =?UTF-8?q?=E4=BA=8B=E6=B8=A9=E6=83=85=E6=B5=81=E8=90=BD=E5=88=B0=E5=BF=83?= =?UTF-8?q?=E5=B0=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ornithe/OrnitheOSLInstallTask.java | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheOSLInstallTask.java diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheOSLInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheOSLInstallTask.java new file mode 100644 index 0000000000..8b3fb9dbe5 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheOSLInstallTask.java @@ -0,0 +1,66 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2021 huangyuhui 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 . + */ +package org.jackhuang.hmcl.download.ornithe; + +import org.jackhuang.hmcl.download.DefaultDependencyManager; +import org.jackhuang.hmcl.game.Version; +import org.jackhuang.hmcl.task.FileDownloadTask; +import org.jackhuang.hmcl.task.Task; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Note: Fabric should be installed first. + * + * @author huangyuhui + */ +public final class OrnitheOSLInstallTask extends Task { + + private final DefaultDependencyManager dependencyManager; + private final Version version; + private final OrnitheOSLRemoteVersion remote; + private final List> dependencies = new ArrayList<>(1); + + public OrnitheOSLInstallTask(DefaultDependencyManager dependencyManager, Version version, OrnitheOSLRemoteVersion remoteVersion) { + this.dependencyManager = dependencyManager; + this.version = version; + this.remote = remoteVersion; + } + + @Override + public Collection> getDependencies() { + return dependencies; + } + + @Override + public boolean isRelyingOnDependencies() { + return false; + } + + @Override + public void execute() throws IOException { + dependencies.add(new FileDownloadTask( + remote.getVersion().getFile().getUrl(), + dependencyManager.getGameRepository().getModsDirectory(version.getId()).resolve("ornithe-osl-" + remote.getVersion().getVersion() + ".jar"), + remote.getVersion().getFile().getIntegrityCheck()) + ); + } +} From 5293513db2b5d2451347222d9b2bb8c9c796ef01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:13:53 +0800 Subject: [PATCH 14/23] =?UTF-8?q?=E9=9A=BE=E5=BF=98=E6=BB=B4=E6=BB=B4?= =?UTF-8?q?=E7=82=B9=E7=82=B9=20=E6=9C=80=E7=BE=8E=E5=A5=BD=E6=98=AF?= =?UTF-8?q?=E4=BA=BA=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ornithe/OrnitheOSLRemoteVersion.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheOSLRemoteVersion.java diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheOSLRemoteVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheOSLRemoteVersion.java new file mode 100644 index 0000000000..c9bc1633f7 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheOSLRemoteVersion.java @@ -0,0 +1,67 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2021 huangyuhui 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 . + */ +package org.jackhuang.hmcl.download.ornithe; + +import org.jackhuang.hmcl.download.DefaultDependencyManager; +import org.jackhuang.hmcl.download.LibraryAnalyzer; +import org.jackhuang.hmcl.download.RemoteVersion; +import org.jackhuang.hmcl.game.Version; +import org.jackhuang.hmcl.mod.RemoteMod; +import org.jackhuang.hmcl.task.Task; + +import java.time.Instant; +import java.util.List; + +public class OrnitheOSLRemoteVersion extends RemoteVersion { + private final String fullVersion; + private final RemoteMod.Version version; + + /** + * Constructor. + * + * @param gameVersion the Minecraft version that this remote version suits. + * @param selfVersion the version string of the remote version. + * @param urls the installer or universal jar original URL. + */ + OrnitheOSLRemoteVersion(String gameVersion, String selfVersion, String fullVersion, Instant datePublished, RemoteMod.Version version, List urls) { + super(LibraryAnalyzer.LibraryType.FABRIC_API.getPatchId(), gameVersion, selfVersion, datePublished, urls); + + this.fullVersion = fullVersion; + this.version = version; + } + + @Override + public String getFullVersion() { + return fullVersion; + } + + public RemoteMod.Version getVersion() { + return version; + } + + @Override + public Task getInstallTask(DefaultDependencyManager dependencyManager, Version baseVersion) { + return new OrnitheOSLInstallTask(dependencyManager, baseVersion, this); + } + + @Override + public int compareTo(RemoteVersion o) { + if (!(o instanceof OrnitheOSLRemoteVersion)) return 0; + return -this.getReleaseDate().compareTo(o.getReleaseDate()); + } +} From 85066a10cd9ad3e60342398b1d0c57004afa9222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:14:13 +0800 Subject: [PATCH 15/23] =?UTF-8?q?=E6=9C=88=E5=84=BF=E5=BC=AF=E5=BC=AF=20?= =?UTF-8?q?=E5=8B=BE=E4=BD=8F=E4=BA=86=E5=A4=9C=E6=99=9A=20=E7=92=80?= =?UTF-8?q?=E7=92=A8=20=E5=86=99=E4=B8=8B=E6=B5=AA=E6=BC=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java index a602b2f75e..a9ac9bb670 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java @@ -43,6 +43,7 @@ import org.jackhuang.hmcl.download.liteloader.LiteLoaderRemoteVersion; import org.jackhuang.hmcl.download.neoforge.NeoForgeRemoteVersion; import org.jackhuang.hmcl.download.optifine.OptiFineRemoteVersion; +import org.jackhuang.hmcl.download.ornithe.OrnitheRemoteVersion; import org.jackhuang.hmcl.download.quilt.QuiltAPIRemoteVersion; import org.jackhuang.hmcl.download.quilt.QuiltRemoteVersion; import org.jackhuang.hmcl.setting.VersionIconType; @@ -268,6 +269,8 @@ else if (remoteVersion instanceof CleanroomRemoteVersion) iconType = VersionIconType.CLEANROOM; else if (remoteVersion instanceof NeoForgeRemoteVersion) iconType = VersionIconType.NEO_FORGE; + else if (remoteVersion instanceof OrnitheRemoteVersion) + iconType = VersionIconType.ORNITHE; else if (remoteVersion instanceof LegacyFabricRemoteVersion || remoteVersion instanceof LegacyFabricAPIRemoteVersion) iconType = VersionIconType.LEGACY_FABRIC; else if (remoteVersion instanceof FabricRemoteVersion || remoteVersion instanceof FabricAPIRemoteVersion) From 53e5e06ab28f403486fe56ee4345987d1bf7b72e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:14:23 +0800 Subject: [PATCH 16/23] =?UTF-8?q?=E6=B4=92=E8=90=BD=E5=A4=9A=E5=B0=91?= =?UTF-8?q?=E6=9C=88=E8=89=B2=E4=BC=B4=E6=88=91=E7=83=9B=E5=85=89=E5=85=B1?= =?UTF-8?q?=E6=9E=95=E7=9C=A0=20=E7=85=A7=E4=BA=AE=E8=B0=81=E7=9A=84?= =?UTF-8?q?=E6=AC=A2=E5=BF=83=20=E8=B0=81=E7=9A=84=E7=AC=91=E9=A2=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jackhuang/hmcl/ui/InstallerItem.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java index 7f08e36d55..3d05fa1b39 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java @@ -95,6 +95,7 @@ public InstallerItem(String id, Style style) { case "game" -> VersionIconType.GRASS; case "fabric", "fabric-api" -> VersionIconType.FABRIC; case "legacyfabric", "legacyfabric-api" -> VersionIconType.LEGACY_FABRIC; + case "ornithe", "ornithe-osl" -> VersionIconType.ORNITHE; case "forge" -> VersionIconType.FORGE; case "cleanroom" -> VersionIconType.CLEANROOM; case "liteloader" -> VersionIconType.CHICKEN; @@ -183,6 +184,8 @@ public InstallerItemGroup(String gameVersion, Style style) { InstallerItem cleanroom = new InstallerItem(CLEANROOM, style); InstallerItem legacyfabric = new InstallerItem(LEGACY_FABRIC, style); InstallerItem legacyfabricApi = new InstallerItem(LEGACY_FABRIC_API, style); + InstallerItem ornithe = new InstallerItem(ORNITHE, style); + InstallerItem ornitheOSL = new InstallerItem(ORNITHE_OSL, style); InstallerItem neoForge = new InstallerItem(NEO_FORGE, style); InstallerItem liteLoader = new InstallerItem(LITELOADER, style); InstallerItem optiFine = new InstallerItem(OPTIFINE, style); @@ -191,11 +194,12 @@ public InstallerItemGroup(String gameVersion, Style style) { Map> incompatibleMap = new HashMap<>(); mutualIncompatible(incompatibleMap, forge, fabric, quilt, neoForge, cleanroom, legacyfabric); - addIncompatibles(incompatibleMap, liteLoader, fabric, quilt, neoForge, cleanroom, legacyfabric); - addIncompatibles(incompatibleMap, optiFine, fabric, quilt, neoForge, cleanroom, liteLoader, legacyfabric); - addIncompatibles(incompatibleMap, fabricApi, forge, quiltApi, neoForge, liteLoader, optiFine, cleanroom, legacyfabric, legacyfabricApi); - addIncompatibles(incompatibleMap, quiltApi, forge, fabric, fabricApi, neoForge, liteLoader, optiFine, cleanroom, legacyfabric, legacyfabricApi); - addIncompatibles(incompatibleMap, legacyfabricApi, forge, fabric, fabricApi, neoForge, liteLoader, optiFine, cleanroom, quilt, quiltApi); + addIncompatibles(incompatibleMap, liteLoader, fabric, quilt, neoForge, cleanroom, legacyfabric, ornithe); + addIncompatibles(incompatibleMap, optiFine, fabric, quilt, neoForge, cleanroom, liteLoader, legacyfabric, ornithe); + addIncompatibles(incompatibleMap, fabricApi, forge, quiltApi, neoForge, liteLoader, optiFine, cleanroom, legacyfabric, legacyfabricApi, ornithe, ornitheOSL); + addIncompatibles(incompatibleMap, quiltApi, forge, fabric, fabricApi, neoForge, liteLoader, optiFine, cleanroom, legacyfabric, legacyfabricApi, ornithe, ornitheOSL); + addIncompatibles(incompatibleMap, legacyfabricApi, forge, fabric, fabricApi, neoForge, liteLoader, optiFine, cleanroom, quilt, quiltApi, ornitheOSL, ornithe); + addIncompatibles(incompatibleMap, ornitheOSL, forge, fabric, fabricApi, neoForge, liteLoader, optiFine, cleanroom, quilt, quiltApi, legacyfabric, legacyfabricApi); for (Map.Entry> entry : incompatibleMap.entrySet()) { InstallerItem item = entry.getKey(); @@ -229,7 +233,7 @@ public InstallerItemGroup(String gameVersion, Style style) { game.versionProperty.set(new InstalledState(gameVersion, false, false)); } - InstallerItem[] all = {game, forge, neoForge, liteLoader, optiFine, fabric, fabricApi, quilt, quiltApi, legacyfabric, legacyfabricApi, cleanroom}; + InstallerItem[] all = {game, forge, neoForge, liteLoader, optiFine, fabric, fabricApi, quilt, quiltApi, legacyfabric, legacyfabricApi, ornithe, ornitheOSL, cleanroom}; for (InstallerItem item : all) { if (!item.resolvedStateProperty.isBound()) { @@ -246,9 +250,11 @@ public InstallerItemGroup(String gameVersion, Style style) { if (gameVersion == null) { this.libraries = all; } else if (gameVersion.equals("1.12.2")) { - this.libraries = new InstallerItem[]{game, forge, cleanroom, liteLoader, legacyfabric, legacyfabricApi, optiFine}; + this.libraries = new InstallerItem[]{game, forge, cleanroom, liteLoader, legacyfabric, legacyfabricApi, ornithe, ornitheOSL, optiFine}; + } else if (GameVersionNumber.compare(gameVersion, "1.14.4") <= 0 && GameVersionNumber.compare(gameVersion, "1.13.2") >= 0) { + this.libraries = new InstallerItem[]{game, forge, liteLoader, optiFine, fabric, fabricApi, ornithe, ornitheOSL}; } else if (GameVersionNumber.compare(gameVersion, "1.13.2") <= 0) { - this.libraries = new InstallerItem[]{game, forge, liteLoader, optiFine, legacyfabric, legacyfabricApi}; + this.libraries = new InstallerItem[]{game, forge, liteLoader, optiFine, legacyfabric, legacyfabricApi, ornithe, ornitheOSL}; } else { this.libraries = new InstallerItem[]{game, forge, neoForge, optiFine, fabric, fabricApi, quilt, quiltApi}; } From 18af318917aa2c711955421bf0fdb1034bc7162c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:15:15 +0800 Subject: [PATCH 17/23] =?UTF-8?q?=E7=83=9F=E7=81=AB=E6=BC=AB=E6=BC=AB=20?= =?UTF-8?q?=E5=8B=BE=E7=94=BB=E7=9D=80=E5=B1=8B=E6=AA=90=20=E4=B8=8E?= =?UTF-8?q?=E8=B0=81=E7=9C=8B=20=E8=BF=99=E4=B8=87=E5=8D=83=E7=BB=9A?= =?UTF-8?q?=E7=83=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java | 1 + 1 file changed, 1 insertion(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java index 3d07ed74b6..b907096511 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java @@ -132,6 +132,7 @@ private void setTxtNameWithLoaders() { case LITELOADER -> "LiteLoader"; case QUILT -> "Quilt"; case OPTIFINE -> "OptiFine"; + case ORNITHE -> "Ornithe"; default -> null; }; From 5a2b03db479bf7dddcacfb04a5a1383079baeb6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:16:05 +0800 Subject: [PATCH 18/23] =?UTF-8?q?=E5=8C=96=E4=BD=9C=E5=A4=9A=E5=B0=91?= =?UTF-8?q?=E5=9B=9E=E5=BF=86=E8=BD=BB=E6=9F=94=E6=B5=81=E6=B7=8C=E5=9C=A8?= =?UTF-8?q?=E6=8C=87=E5=B0=96=20=E9=9A=BE=E5=BE=97=E5=BF=83=E5=BF=83?= =?UTF-8?q?=E5=BF=B5=E5=BF=B5=20=E6=9C=80=E6=B8=A9=E6=9A=96=E6=98=AF?= =?UTF-8?q?=E4=BA=BA=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jackhuang/hmcl/ui/versions/InstallerListPage.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java index c8d8791f16..a908c47ae5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java @@ -85,6 +85,11 @@ public void loadVersion(Profile profile, String versionId) { continue; } + // Skip ornithe osl + if (libraryId.equals(LibraryAnalyzer.LibraryType.ORNITHE_OSL.getPatchId())) { + continue; + } + String libraryVersion = analyzer.getVersion(libraryId).orElse(null); if (libraryVersion != null) { From 1a8b2367bc232b31a2d0b9aff52b13728ef325b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:33:25 +0800 Subject: [PATCH 19/23] =?UTF-8?q?=E6=9C=88=E5=84=BF=E5=BC=AF=E5=BC=AF=20?= =?UTF-8?q?=E7=83=9F=E7=81=AB=E6=BC=AB=E6=BC=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hmcl/game/HMCLGameRepository.java | 2 ++ .../org/jackhuang/hmcl/ui/InstallerItem.java | 2 +- .../ui/download/AbstractInstallersPage.java | 1 + .../download/BMCLAPIDownloadProvider.java | 8 +++++++ .../hmcl/download/LibraryAnalyzer.java | 3 ++- .../hmcl/download/MojangDownloadProvider.java | 8 +++++++ .../download/ornithe/OrnitheInstallTask.java | 23 +++++++++++-------- .../ornithe/OrnitheOSLVersionList.java | 2 +- 8 files changed, 37 insertions(+), 12 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java index 2426a1ced2..1687ab82cd 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -324,6 +324,8 @@ else if (libraryAnalyzer.has(LibraryAnalyzer.LibraryType.QUILT)) return VersionIconType.QUILT.getIcon(); else if (libraryAnalyzer.has(LibraryAnalyzer.LibraryType.LEGACY_FABRIC)) return VersionIconType.LEGACY_FABRIC.getIcon(); + else if (libraryAnalyzer.has(LibraryAnalyzer.LibraryType.ORNITHE)) + return VersionIconType.ORNITHE.getIcon(); else if (libraryAnalyzer.has(LibraryAnalyzer.LibraryType.NEO_FORGE)) return VersionIconType.NEO_FORGE.getIcon(); else if (libraryAnalyzer.has(LibraryAnalyzer.LibraryType.FORGE)) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java index 3d05fa1b39..e259f3f169 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java @@ -193,7 +193,7 @@ public InstallerItemGroup(String gameVersion, Style style) { InstallerItem quiltApi = new InstallerItem(QUILT_API, style); Map> incompatibleMap = new HashMap<>(); - mutualIncompatible(incompatibleMap, forge, fabric, quilt, neoForge, cleanroom, legacyfabric); + mutualIncompatible(incompatibleMap, forge, fabric, quilt, neoForge, cleanroom, legacyfabric, ornithe); addIncompatibles(incompatibleMap, liteLoader, fabric, quilt, neoForge, cleanroom, legacyfabric, ornithe); addIncompatibles(incompatibleMap, optiFine, fabric, quilt, neoForge, cleanroom, liteLoader, legacyfabric, ornithe); addIncompatibles(incompatibleMap, fabricApi, forge, quiltApi, neoForge, liteLoader, optiFine, cleanroom, legacyfabric, legacyfabricApi, ornithe, ornitheOSL); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AbstractInstallersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AbstractInstallersPage.java index 4c1d8919b4..f6aa354612 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AbstractInstallersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AbstractInstallersPage.java @@ -60,6 +60,7 @@ public AbstractInstallersPage(WizardController controller, String gameVersion, D library.setOnInstall(() -> { if (!Boolean.TRUE.equals(config().getShownTips().get(FABRIC_QUILT_API_TIP)) && (LibraryAnalyzer.LibraryType.FABRIC_API.getPatchId().equals(libraryId) + || LibraryAnalyzer.LibraryType.ORNITHE_OSL.getPatchId().equals(libraryId) || LibraryAnalyzer.LibraryType.QUILT_API.getPatchId().equals(libraryId) || LibraryAnalyzer.LibraryType.LEGACY_FABRIC_API.getPatchId().equals(libraryId))) { Controllers.dialog(new MessageDialogPane.Builder( diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java index b23a7867f7..47f7d333c2 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java @@ -27,6 +27,8 @@ import org.jackhuang.hmcl.download.liteloader.LiteLoaderBMCLVersionList; import org.jackhuang.hmcl.download.neoforge.NeoForgeBMCLVersionList; import org.jackhuang.hmcl.download.optifine.OptiFineBMCLVersionList; +import org.jackhuang.hmcl.download.ornithe.OrnitheOSLVersionList; +import org.jackhuang.hmcl.download.ornithe.OrnitheVersionList; import org.jackhuang.hmcl.download.quilt.QuiltAPIVersionList; import org.jackhuang.hmcl.download.quilt.QuiltVersionList; import org.jackhuang.hmcl.util.Pair; @@ -55,6 +57,8 @@ public final class BMCLAPIDownloadProvider implements DownloadProvider { private final OptiFineBMCLVersionList optifine; private final QuiltVersionList quilt; private final QuiltAPIVersionList quiltApi; + private final OrnitheVersionList ornithe; + private final OrnitheOSLVersionList ornitheOSL; private final List> replacement; private final List> fallbackReplacement; @@ -72,6 +76,8 @@ public BMCLAPIDownloadProvider(String apiRoot) { this.quiltApi = new QuiltAPIVersionList(this); this.legacyFabric = new LegacyFabricVersionList(this); this.legacyFabricApi = new LegacyFabricAPIVersionList(this); + this.ornithe = new OrnitheVersionList(this); + this.ornitheOSL = new OrnitheOSLVersionList(this); this.replacement = List.of( pair("https://bmclapi2.bangbang93.com", apiRoot), @@ -134,6 +140,8 @@ public VersionList getVersionListById(String id) { case "quilt-api" -> quiltApi; case "legacyfabric" -> legacyFabric; case "legacyfabric-api" -> legacyFabricApi; + case "ornithe" -> ornithe; + case "ornithe-osl" -> ornitheOSL; default -> throw new IllegalArgumentException("Unrecognized version list id: " + id); }; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java index 3fa9cb707c..9b05de0f9b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java @@ -172,7 +172,8 @@ public static boolean isModded(VersionProvider provider, Version version) { return mainClass != null && (LAUNCH_WRAPPER_MAIN.equals(mainClass) || mainClass.startsWith("net.minecraftforge") || mainClass.startsWith("net.neoforged") - || mainClass.startsWith("top.outlands") //Cleanroom + || mainClass.startsWith("top.outlands") // Cleanroom + || mainClass.startsWith("net.ornithemc") || mainClass.startsWith("net.fabricmc") || mainClass.startsWith("org.quiltmc") || mainClass.startsWith("cpw.mods")); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java index 716acbcc39..9e12a80b2f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java @@ -27,6 +27,8 @@ import org.jackhuang.hmcl.download.liteloader.LiteLoaderVersionList; import org.jackhuang.hmcl.download.neoforge.NeoForgeOfficialVersionList; import org.jackhuang.hmcl.download.optifine.OptiFineBMCLVersionList; +import org.jackhuang.hmcl.download.ornithe.OrnitheOSLVersionList; +import org.jackhuang.hmcl.download.ornithe.OrnitheVersionList; import org.jackhuang.hmcl.download.quilt.QuiltAPIVersionList; import org.jackhuang.hmcl.download.quilt.QuiltVersionList; import org.jackhuang.hmcl.util.io.NetworkUtils; @@ -51,6 +53,8 @@ public class MojangDownloadProvider implements DownloadProvider { private final QuiltAPIVersionList quiltApi; private final LegacyFabricVersionList legacyFabric; private final LegacyFabricAPIVersionList legacyFabricApi; + private final OrnitheVersionList ornithe; + private final OrnitheOSLVersionList ornitheOSL; public MojangDownloadProvider() { // If there is no official download channel available, fallback to BMCLAPI. @@ -68,6 +72,8 @@ public MojangDownloadProvider() { this.quiltApi = new QuiltAPIVersionList(this); this.legacyFabric = new LegacyFabricVersionList(this); this.legacyFabricApi = new LegacyFabricAPIVersionList(this); + this.ornithe = new OrnitheVersionList(this); + this.ornitheOSL = new OrnitheOSLVersionList(this); } @Override @@ -95,6 +101,8 @@ public VersionList getVersionListById(String id) { case "quilt-api" -> quiltApi; case "legacyfabric" -> legacyFabric; case "legacyfabric-api" -> legacyFabricApi; + case "ornithe" -> ornithe; + case "ornithe-osl" -> ornitheOSL; default -> throw new IllegalArgumentException("Unrecognized version list id: " + id); }; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheInstallTask.java index 321b95a9d1..f2bb6b2283 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheInstallTask.java @@ -22,19 +22,20 @@ import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.download.UnsupportedInstallationException; +import org.jackhuang.hmcl.download.fabric.FabricInstallTask; import org.jackhuang.hmcl.game.Arguments; import org.jackhuang.hmcl.game.Artifact; import org.jackhuang.hmcl.game.Library; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.GetTask; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.gson.JsonSerializable; import org.jackhuang.hmcl.util.gson.JsonUtils; import java.io.IOException; import java.util.*; import static org.jackhuang.hmcl.download.UnsupportedInstallationException.FABRIC_NOT_COMPATIBLE_WITH_FORGE; -import static org.jackhuang.hmcl.download.fabric.FabricInstallTask.FabricInfo; /** * Note: Fabric should be installed first. @@ -86,17 +87,17 @@ public boolean isRelyingOnDependencies() { @Override public void execute() throws IOException { - FabricInfo fabricInfo = JsonUtils.GSON.fromJson(launchMetaTask.getResult(), FabricInfo.class); - if (fabricInfo == null) + OrnitheInfo ornitheInfo = JsonUtils.GSON.fromJson(launchMetaTask.getResult(), OrnitheInfo.class); + if (ornitheInfo == null) throw new IOException("Fabric metadata is invalid"); - setResult(getPatch(fabricInfo, remote.getGameVersion(), remote.getSelfVersion())); + setResult(getPatch(ornitheInfo, remote.getGameVersion(), remote.getSelfVersion())); dependencies.add(dependencyManager.checkLibraryCompletionAsync(getResult(), true)); } - private Version getPatch(FabricInfo fabricInfo, String gameVersion, String loaderVersion) { - JsonObject launcherMeta = fabricInfo.launcherMeta(); + private Version getPatch(OrnitheInfo ornitheInfo, String gameVersion, String loaderVersion) { + JsonObject launcherMeta = ornitheInfo.launcherMeta(); Arguments arguments = new Arguments(); String mainClass; @@ -122,9 +123,13 @@ private Version getPatch(FabricInfo fabricInfo, String gameVersion, String loade } } - libraries.add(new Library(Artifact.fromDescriptor(fabricInfo.intermediary().getMaven()), "https://maven.fabricmc.net/", null)); - libraries.add(new Library(Artifact.fromDescriptor(fabricInfo.intermediary().getMaven()), "https://maven.fabricmc.net/", null)); + libraries.add(new Library(Artifact.fromDescriptor(ornitheInfo.calamus().getMaven()), "https://maven.ornithemc.net/releases/", null)); + libraries.add(new Library(Artifact.fromDescriptor(ornitheInfo.loader().getMaven()), "https://maven.ornithemc.net/releases/", null)); - return new Version(LibraryAnalyzer.LibraryType.FABRIC.getPatchId(), loaderVersion, Version.PRIORITY_LOADER, arguments, mainClass, libraries); + return new Version(LibraryAnalyzer.LibraryType.ORNITHE.getPatchId(), loaderVersion, Version.PRIORITY_LOADER, arguments, mainClass, libraries); + } + + @JsonSerializable + public record OrnitheInfo(FabricInstallTask.LoaderInfo loader, FabricInstallTask.IntermediaryInfo calamus, JsonObject launcherMeta) { } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheOSLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheOSLVersionList.java index b6f9f7696c..f8d75c0978 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheOSLVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/ornithe/OrnitheOSLVersionList.java @@ -42,7 +42,7 @@ public boolean hasType() { @Override public Task refreshAsync() { return Task.runAsync(() -> { - for (RemoteMod.Version modVersion : Lang.toIterable(ModrinthRemoteModRepository.MODS.getRemoteVersionsById(downloadProvider, "P7dR8mSH"))) { + for (RemoteMod.Version modVersion : Lang.toIterable(ModrinthRemoteModRepository.MODS.getRemoteVersionsById(downloadProvider, "EHGtwpJv"))) { for (String gameVersion : modVersion.getGameVersions()) { versions.put(gameVersion, new OrnitheOSLRemoteVersion(gameVersion, modVersion.getVersion(), modVersion.getName(), modVersion.getDatePublished(), modVersion, Collections.singletonList(modVersion.getFile().getUrl()))); From e23289465f63bb701b2ab1a37e6802bf516d8b67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:50:25 +0800 Subject: [PATCH 20/23] =?UTF-8?q?=E6=9C=88=E5=84=BF=E5=BC=AF=E5=BC=AF=20?= =?UTF-8?q?=E7=83=9F=E7=81=AB=E6=BC=AB=E6=BC=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../versions/AdvancedVersionSettingPage.java | 10 ++++++- .../resources/assets/lang/I18N.properties | 11 ++----- .../resources/assets/lang/I18N_ar.properties | 14 --------- .../resources/assets/lang/I18N_es.properties | 13 -------- .../resources/assets/lang/I18N_ja.properties | 12 -------- .../resources/assets/lang/I18N_lzh.properties | 13 -------- .../resources/assets/lang/I18N_ru.properties | 12 -------- .../resources/assets/lang/I18N_uk.properties | 12 -------- .../resources/assets/lang/I18N_zh.properties | 11 ++----- .../assets/lang/I18N_zh_CN.properties | 11 ++----- .../hmcl/download/LibraryAnalyzer.java | 6 ++++ .../hmcl/launch/DefaultLauncher.java | 26 ++++------------ .../org/jackhuang/hmcl/mod/ModLoaderType.java | 30 ++++++++++++------- .../mod/mcbbs/McbbsModpackExportTask.java | 21 ++++--------- 14 files changed, 51 insertions(+), 151 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/AdvancedVersionSettingPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/AdvancedVersionSettingPage.java index 6db255756f..c4ea031e52 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/AdvancedVersionSettingPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/AdvancedVersionSettingPage.java @@ -27,6 +27,7 @@ import javafx.scene.layout.*; import org.jackhuang.hmcl.game.NativesDirectoryType; import org.jackhuang.hmcl.game.Renderer; +import org.jackhuang.hmcl.mod.ModLoaderType; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.setting.VersionSetting; import org.jackhuang.hmcl.ui.FXUtils; @@ -122,7 +123,14 @@ public AdvancedVersionSettingPage(Profile profile, @Nullable String versionId, V pane.addRow(3, new Label(i18n("settings.advanced.post_exit_command")), txtPostExitCommand); HintPane hintPane = new HintPane(); - hintPane.setText(i18n("settings.advanced.custom_commands.hint")); + StringBuilder sb = new StringBuilder(i18n("settings.advanced.custom_commands.hint")); + for (ModLoaderType type : ModLoaderType.values()) { + if (type.getId() != null) { + sb.append("\n"); + sb.append(i18n("settings.advanced.custon_commands.env",type.getId(),i18n("install.installer." + type.getId().toLowerCase(Locale.ROOT)))); + } + } + hintPane.setText(sb.toString()); GridPane.setColumnSpan(hintPane, 2); pane.addRow(4, hintPane); diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 732e96dc19..67a7f11e9c 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -1319,15 +1319,8 @@ settings.advanced.custom_commands.hint=The following environment variables are p \ · $INST_ID: instance name.\n\ \ · $INST_DIR: absolute path of the instance working directory.\n\ \ · $INST_MC_DIR: absolute path of the game directory.\n\ - \ · $INST_JAVA: java binary used for launch.\n\ - \ · $INST_FORGE: set if Forge is installed.\n\ - \ · $INST_NEOFORGE: set if NeoForge is installed.\n\ - \ · $INST_CLEANROOM: set if Cleanroom is installed.\n\ - \ · $INST_LITELOADER: set if LiteLoader is installed.\n\ - \ · $INST_OPTIFINE: set if OptiFine is installed.\n\ - \ · $INST_FABRIC: set if Fabric is installed.\n\ - \ · $INST_LEGACYFABRIC: set if Legacy Fabric is installed.\n\ - \ · $INST_QUILT: set if Quilt is installed. + \ · $INST_JAVA: java binary used for launch. +settings.advanced.custon_commands.env= \ · $INST_%s: set if %s is installed.; settings.advanced.dont_check_game_completeness=Do not check game integrity settings.advanced.dont_check_jvm_validity=Do not check JVM compatibility settings.advanced.dont_patch_natives=Do not attempt to automatically replace native libraries diff --git a/HMCL/src/main/resources/assets/lang/I18N_ar.properties b/HMCL/src/main/resources/assets/lang/I18N_ar.properties index fe96befb92..44769011ba 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ar.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ar.properties @@ -1303,20 +1303,6 @@ settings.advanced=الإعدادات المتقدمة settings.advanced.modify=تعديل الإعدادات المتقدمة settings.advanced.title=الإعدادات المتقدمة - %s settings.advanced.custom_commands=أوامر مخصصة -settings.advanced.custom_commands.hint=المتغيرات البيئية التالية متاحة:\n\ - \ · $INST_NAME: اسم النسخة.\n\ - \ · $INST_ID: اسم النسخة.\n\ - \ · $INST_DIR: المسار المطلق لمجلد عمل النسخة.\n\ - \ · $INST_MC_DIR: المسار المطلق لمجلد اللعبة.\n\ - \ · $INST_JAVA: ملف Java المستخدم للتشغيل.\n\ - \ · $INST_FORGE: يُضبط إذا كان Forge مثبّتاً.\n\ - \ · $INST_NEOFORGE: يُضبط إذا كان NeoForge مثبّتاً.\n\ - \ · $INST_CLEANROOM: يُضبط إذا كان Cleanroom مثبّتاً.\n\ - \ · $INST_LITELOADER: يُضبط إذا كان LiteLoader مثبّتاً.\n\ - \ · $INST_OPTIFINE: يُضبط إذا كان OptiFine مثبّتاً.\n\ - \ · $INST_FABRIC: يُضبط إذا كان Fabric مثبّتاً.\n\ - \ · $INST_LEGACYFABRIC: يُضبط إذا كان Legacy Fabric مثبّتاً.\n\ - \ · $INST_QUILT: يُضبط إذا كان Quilt مثبّتاً. settings.advanced.dont_check_game_completeness=عدم التحقق من سلامة اللعبة settings.advanced.dont_check_jvm_validity=عدم التحقق من توافق JVM settings.advanced.dont_patch_natives=عدم محاولة استبدال المكتبات الأصلية تلقائياً diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index 9fe2f6d7fd..d488bc1df3 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -1214,19 +1214,6 @@ settings.advanced=Configuración avanzada settings.advanced.modify=Editar configuración avanzada settings.advanced.title=Configuración avanzada - %s settings.advanced.custom_commands=Comandos personalizados -settings.advanced.custom_commands.hint=Se proporcionan las siguientes variables de entorno:\n\ - \ · $INST_NAME: nombre de la instancia.\n\ - \ · $INST_ID: nombre de la instancia.\n\ - \ · $INST_DIR: ruta absoluta del directorio de trabajo de la instancia.\n\ - \ · $INST_MC_DIR: ruta absoluta del directorio del juego.\n\ - \ · $INST_JAVA: binario de java utilizado para la ejecución\n\ - \ · $INST_FORGE: disponible si Forge está instalado.\n\ - \ · $INST_NEOFORGE: disponible si NeoForge está instalado.\n\ - \ · $INST_CLEANROOM: disponible si Cleanroom está instalado.\n\ - \ · $INST_LITELOADER: disponible si LiteLoader está instalado.\n\ - \ · $INST_OPTIFINE: disponible si OptiFine está instalado.\n\ - \ · $INST_FABRIC: disponible si Fabric está instalado.\n\ - \ · $INST_QUILT: disponible si Quilt está instalado. settings.advanced.dont_check_game_completeness=No chequear integridad del juego settings.advanced.dont_check_jvm_validity=No comprobar la compatibilidad con JVM settings.advanced.dont_patch_natives=No intente sustituir automáticamente las bibliotecas nativas diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index 51e4cbbd43..d3ccb517ae 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -744,18 +744,6 @@ settings=設定 settings.advanced=詳細設定 settings.advanced.title=詳細設定 - %s settings.advanced.custom_commands=カスタムコマンド -settings.advanced.custom_commands.hint=カスタムコマンドは、次の環境変数を使用して実行されます。\n \ - \-$ INST_NAME:バージョンの名前\n \ - \-$ INST_ID:バージョンの名前\n \ - \-$ INST_DIR:バージョンの絶対パス\n \ - \-$ INST_MC_DIR:Minecraftの絶対パス\n \ - \-$ INST_JAVA:起動に使用されるJavaバイナリ\n \ - \-$ INST_FORGE:Forgeがインストールされている場合に設定\n \ - \-$ INST_NEOFORGE:NeoForgeがインストールされている場合に設定\n \ - \-$ INST_LITELOADER:LiteLoaderがインストールされている場合に設定\n \ - \-$ INST_OPTIFINE:OptiFineがインストールされている場合に設定\n \ - \-$ INST_FABRIC:ファブリックがインストールされている場合に設定\n \ - \-$ INST_QUILT:ファブリックがインストールされている場合に設定 settings.advanced.dont_check_game_completeness=ゲームファイルをスキャンしない settings.advanced.dont_check_jvm_validity=JVMがゲームを起動できるかどうかを確認しないでください settings.advanced.game_dir.default=標準(.minecraft /) diff --git a/HMCL/src/main/resources/assets/lang/I18N_lzh.properties b/HMCL/src/main/resources/assets/lang/I18N_lzh.properties index 96ab3d777f..b10f562c8c 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_lzh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_lzh.properties @@ -1026,19 +1026,6 @@ settings.advanced=進階置設 settings.advanced.modify=篡進階置設 settings.advanced.title=進階置設 - %s settings.advanced.custom_commands=自定命令 -settings.advanced.custom_commands.hint=自定之令見召,当含下列环境易数:\n\ - \ · $INST_NAME:例名;\n\ - \ · $INST_ID:例名;\n\ - \ · $INST_DIR:現例運行之徑;\n\ - \ · $INST_MC_DIR:現戲案夾之徑;\n\ - \ · $INST_JAVA:戲行所用之爪哇徑;\n\ - \ · $INST_FORGE:倘置鍛,则存此易数;\n\ - \ · $INST_NEOFORGE:倘置新鍛,则存此易数;\n\ - \ · $INST_CLEANROOM:倘置 Cleanroom,则存此易数;\n\ - \ · $INST_LITELOADER:倘置輕載,则存此易数;\n\ - \ · $INST_OPTIFINE:倘置 OptiFine,则存此易数;\n\ - \ · $INST_FABRIC:倘置緞,则存此易数;\n\ - \ · $INST_QUILT:倘置褥,则存此易数。 settings.advanced.dont_check_game_completeness=弗驗案之備否 settings.advanced.dont_check_jvm_validity=弗校爪哇虛機與戲之兼否 settings.advanced.dont_patch_natives=弗圖替府庫 diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index df20bd5705..68fa9a28b8 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -1206,18 +1206,6 @@ settings.advanced=Расширенные настройки settings.advanced.modify=Изменить расширенные настройки settings.advanced.title=Расширенные настройки - %s settings.advanced.custom_commands=Пользовательские команды -settings.advanced.custom_commands.hint=Пользовательские команды выполняются со следующими переменными окружения:\n\ - \ · $INST_NAME: название сборки.\n\ - \ · $INST_ID: название сборки.\n\ - \ · $INST_DIR: абсолютный путь к рабочей папке сборки.\n\ - \ · $INST_MC_DIR: абсолютный путь к текущей папке игры.\n\ - \ · $INST_JAVA: двоичный файл java, используемый для запуска.\n\ - \ · $INST_FORGE: устанавливается, если установлен Forge.\n\ - \ · $INST_NEOFORGE: устанавливается, если установлен NeoForge.\n\ - \ · $INST_LITELOADER: устанавливается, если установлен LiteLoader.\n\ - \ · $INST_OPTIFINE: устанавливается, если установлен OptiFine.\n\ - \ · $INST_FABRIC: устанавливается, если установлен Fabric.\n\ - \ · $INST_QUILT: устанавливается, если установлен Quilt. settings.advanced.dont_check_game_completeness=Не проверять целостность игры settings.advanced.dont_check_jvm_validity=Не проверять совместимость JVM settings.advanced.dont_patch_natives=Не пытайтесь автоматически заменить нативные библиотеки diff --git a/HMCL/src/main/resources/assets/lang/I18N_uk.properties b/HMCL/src/main/resources/assets/lang/I18N_uk.properties index 3726c5abe6..7f2615b751 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_uk.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_uk.properties @@ -1154,18 +1154,6 @@ settings.advanced=Розширені налаштування settings.advanced.modify=Редагувати розширені налаштування settings.advanced.title=Розширені налаштування - %s settings.advanced.custom_commands=Власні команди -settings.advanced.custom_commands.hint=Надано наступні змінні середовища: \n\ - \ · $INST_NAME: назва екземпляра. \n\ - \ · $INST_ID: назва екземпляра. \n\ - \ · $INST_DIR: абсолютний шлях до робочого каталогу екземпляра. \n\ - \ · $INST_MC_DIR: абсолютний шлях до каталогу гри. \n\ - \ · $INST_JAVA: двійковий файл java, що використовується для запуску. \n\ - \ · $INST_FORGE: встановлено, якщо Forge встановлено. \n\ - \ · $INST_NEOFORGE: встановлено, якщо NeoForge встановлено. \n\ - \ · $INST_LITELOADER: встановлено, якщо LiteLoader встановлено. \n\ - \ · $INST_OPTIFINE: встановлено, якщо OptiFine встановлено. \n\ - \ · $INST_FABRIC: встановлено, якщо Fabric встановлено. \n\ - \ · $INST_QUILT: встановлено, якщо Quilt встановлено. settings.advanced.dont_check_game_completeness=Не перевіряти цілісність гри settings.advanced.dont_check_jvm_validity=Не перевіряти сумісність JVM settings.advanced.dont_patch_natives=Не намагатися автоматично замінити нативні бібліотеки diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index ebb7041443..b6bd2879d6 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -1109,15 +1109,8 @@ settings.advanced.custom_commands.hint=自訂指令被呼叫時將包含如下 \ · $INST_ID: 實例名稱;\n\ \ · $INST_DIR: 目前實例執行路徑;\n\ \ · $INST_MC_DIR: 目前遊戲目錄路徑;\n\ - \ · $INST_JAVA: 遊戲執行使用的 Java 路徑;\n\ - \ · $INST_FORGE: 若安裝了 Forge,將會存在本環境變數;\n\ - \ · $INST_NEOFORGE: 若安裝了 NeoForge,將會存在本環境變數;\n\ - \ · $INST_CLEANROOM: 若安裝了 Cleanroom,將會存在本環境變數;\n\ - \ · $INST_LITELOADER: 若安裝了 LiteLoader,將會存在本環境變數;\n\ - \ · $INST_OPTIFINE: 若安裝了 OptiFine,將會存在本環境變數;\n\ - \ · $INST_FABRIC: 若安裝了 Fabric,將會存在本環境變數;\n\ - \ · $INST_LEGACYFABRIC: 若安裝了 Legacy Fabric,將會存在本環境變數;\n\ - \ · $INST_QUILT: 若安裝了 Quilt,將會存在本環境變數。 + \ · $INST_JAVA: 遊戲執行使用的 Java 路徑; +settings.advanced.custon_commands.env= \ · $INST_%s: 若安裝了 %s,將會存在本環境變數。 settings.advanced.dont_check_game_completeness=不檢查遊戲完整性 settings.advanced.dont_check_jvm_validity=不檢查 Java 虛擬機與遊戲的相容性 settings.advanced.dont_patch_natives=不嘗試自動取代本機庫 diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index ee2f087a12..1053d1993f 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -1114,15 +1114,8 @@ settings.advanced.custom_commands.hint=自定义命令被调用时将包含如 \ · $INST_ID: 实例名称;\n\ \ · $INST_DIR: 当前实例运行路径;\n\ \ · $INST_MC_DIR: 当前游戏文件夹路径;\n\ - \ · $INST_JAVA: 游戏运行使用的 Java 路径;\n\ - \ · $INST_FORGE: 若安装了 Forge,将会存在本环境变量;\n\ - \ · $INST_NEOFORGE: 若安装了 NeoForge,将会存在本环境变量;\n\ - \ · $INST_CLEANROOM: 若安装了 Cleanroom,将会存在本环境变量;\n\ - \ · $INST_LITELOADER: 若安装了 LiteLoader,将会存在本环境变量;\n\ - \ · $INST_OPTIFINE: 若安装了 OptiFine,将会存在本环境变量;\n\ - \ · $INST_FABRIC: 若安装了 Fabric,将会存在本环境变量;\n\ - \ · $INST_LEGACYFABRIC: 若安装了 Legacy Fabric,将会存在本环境变量;\n\ - \ · $INST_QUILT: 若安装了 Quilt,将会存在本环境变量。 + \ · $INST_JAVA: 游戏运行使用的 Java 路径; +settings.advanced.custon_commands.env= \ · $INST_%s: 若安装了 %s,将会存在本环境变量; settings.advanced.dont_check_game_completeness=不检查游戏完整性 settings.advanced.dont_check_jvm_validity=不检查 Java 虚拟机与游戏的兼容性 settings.advanced.dont_patch_natives=不尝试自动替换本地库 diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java index 9b05de0f9b..2bbf052f61 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java @@ -54,6 +54,12 @@ public Optional getLibrary(LibraryType type) { return Optional.ofNullable(libraries.get(type.getPatchId())).map(Pair::getKey); } + public Set getLibraries() { + return Arrays.stream(LibraryType.values()) + .filter(this::has) + .collect(Collectors.toSet()); + } + /** * If a library is provided in $.patches, it's structure is so clear that we can do any operation. * Otherwise, we must guess how are these libraries mixed. diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java index 565ddb5db9..2f73c7d1f5 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java @@ -20,6 +20,7 @@ import org.jackhuang.hmcl.auth.AuthInfo; import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.game.*; +import org.jackhuang.hmcl.mod.ModLoaderType; import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.ServerAddress; import org.jackhuang.hmcl.util.StringUtils; @@ -588,30 +589,13 @@ private Map getEnvVars() { } } - if (analyzer.has(LibraryAnalyzer.LibraryType.FORGE)) { - env.put("INST_FORGE", "1"); + for (ModLoaderType type : analyzer.getModLoaders()) { + if (type.getId() != null) env.put("INST_" + type.getId(), "1"); } - if (analyzer.has(LibraryAnalyzer.LibraryType.CLEANROOM)) { - env.put("INST_CLEANROOM", "1"); - } - if (analyzer.has(LibraryAnalyzer.LibraryType.NEO_FORGE)) { - env.put("INST_NEOFORGE", "1"); - } - if (analyzer.has(LibraryAnalyzer.LibraryType.LITELOADER)) { - env.put("INST_LITELOADER", "1"); - } - if (analyzer.has(LibraryAnalyzer.LibraryType.FABRIC)) { - env.put("INST_FABRIC", "1"); - } - if (analyzer.has(LibraryAnalyzer.LibraryType.OPTIFINE)) { + + if (analyzer.getVersion(LibraryAnalyzer.LibraryType.OPTIFINE).isPresent()) { env.put("INST_OPTIFINE", "1"); } - if (analyzer.has(LibraryAnalyzer.LibraryType.QUILT)) { - env.put("INST_QUILT", "1"); - } - if (analyzer.has(LibraryAnalyzer.LibraryType.LEGACY_FABRIC)) { - env.put("INST_LEGACYFABRIC", "1"); - } env.putAll(options.getEnvironmentVariables()); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModLoaderType.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModLoaderType.java index a160076a59..9efee90063 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModLoaderType.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModLoaderType.java @@ -18,14 +18,24 @@ package org.jackhuang.hmcl.mod; public enum ModLoaderType { - UNKNOWN, - FORGE, - CLEANROOM, - NEO_FORGED, - FABRIC, - ORNITHE, - QUILT, - LITE_LOADER, - LEGACY_FABRIC, - PACK + UNKNOWN(null), + FORGE("FORGE"), + CLEANROOM("CLEANROOM"), + NEO_FORGED("NEOFORGE"), + FABRIC("FABRIC"), + ORNITHE("ORNITHE"), + QUILT("QUILT"), + LITE_LOADER("LITELOADER"), + LEGACY_FABRIC("LEGACYFABRIC"), + PACK(null); + + private final String id; + + ModLoaderType(String id){ + this.id = id; + } + + public String getId() { + return id; + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackExportTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackExportTask.java index 2f8eccd2ae..91320e0acf 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackExportTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackExportTask.java @@ -95,22 +95,11 @@ public void execute() throws Exception { // Mcbbs manifest List addons = new ArrayList<>(); addons.add(new McbbsModpackManifest.Addon(MINECRAFT.getPatchId(), gameVersion)); - analyzer.getVersion(FORGE).ifPresent(forgeVersion -> - addons.add(new McbbsModpackManifest.Addon(FORGE.getPatchId(), forgeVersion))); - analyzer.getVersion(CLEANROOM).ifPresent(cleanroomVersion -> - addons.add(new McbbsModpackManifest.Addon(CLEANROOM.getPatchId(), cleanroomVersion))); - analyzer.getVersion(NEO_FORGE).ifPresent(neoForgeVersion -> - addons.add(new McbbsModpackManifest.Addon(NEO_FORGE.getPatchId(), neoForgeVersion))); - analyzer.getVersion(LITELOADER).ifPresent(liteLoaderVersion -> - addons.add(new McbbsModpackManifest.Addon(LITELOADER.getPatchId(), liteLoaderVersion))); - analyzer.getVersion(OPTIFINE).ifPresent(optifineVersion -> - addons.add(new McbbsModpackManifest.Addon(OPTIFINE.getPatchId(), optifineVersion))); - analyzer.getVersion(FABRIC).ifPresent(fabricVersion -> - addons.add(new McbbsModpackManifest.Addon(FABRIC.getPatchId(), fabricVersion))); - analyzer.getVersion(QUILT).ifPresent(quiltVersion -> - addons.add(new McbbsModpackManifest.Addon(QUILT.getPatchId(), quiltVersion))); - analyzer.getVersion(LEGACY_FABRIC).ifPresent(legacyfabricVersion -> - addons.add(new McbbsModpackManifest.Addon(LEGACY_FABRIC.getPatchId(), legacyfabricVersion))); + for (LibraryAnalyzer.LibraryType type : analyzer.getLibraries()) { + if (type.isModLoader() && !(type == OPTIFINE)) continue; + if (type == MINECRAFT) addons.add(new McbbsModpackManifest.Addon(MINECRAFT.getPatchId(), gameVersion)); + else addons.add(new McbbsModpackManifest.Addon(type.getPatchId(), analyzer.getVersion(type).orElseThrow())); + } List libraries = new ArrayList<>(); // TODO libraries From cdef2d4b264ecdaab26f5e0f9f0e12a1fdd8a370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:55:32 +0800 Subject: [PATCH 21/23] =?UTF-8?q?=E6=9C=88=E5=84=BF=E5=BC=AF=E5=BC=AF=20?= =?UTF-8?q?=E7=83=9F=E7=81=AB=E6=BC=AB=E6=BC=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/src/main/resources/assets/lang/I18N.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_es.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_ru.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_uk.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_zh.properties | 4 ++-- HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties | 4 ++-- docs/README.md | 2 +- docs/README_en_Qabs.md | 2 +- docs/README_es.md | 2 +- docs/README_ja.md | 2 +- docs/README_lzh.md | 2 +- docs/README_ru.md | 2 +- docs/README_uk.md | 2 +- docs/README_zh.md | 2 +- docs/README_zh_Hant.md | 2 +- 15 files changed, 21 insertions(+), 21 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 67a7f11e9c..d45d0f6f1a 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -743,7 +743,7 @@ install.installer.install=Installing %s install.installer.install_offline=Install/Update from Local File install.installer.install_offline.tooltip=We support using the local (Neo)Forge, Cleanroom, and OptiFine installer. install.installer.install_online=Online Install -install.installer.install_online.tooltip=We currently support Forge, NeoForge, Cleanroom, OptiFine, Fabric, Legacy Fabric, Quilt, and LiteLoader. +install.installer.install_online.tooltip=We currently support Forge, NeoForge, Cleanroom, OptiFine, Fabric, Legacy Fabric, Ornithe, Quilt, and LiteLoader. install.installer.liteloader=LiteLoader install.installer.not_installed=Not installed install.installer.optifine=OptiFine @@ -1116,7 +1116,7 @@ mods.mcmod.page=MCMod Page mods.mcmod.search=Search in MCMod mods.modrinth=Modrinth mods.name=Name -mods.not_modded=You must install a modloader (Forge, NeoForge, Fabric, Legacy Fabric, Quilt, or LiteLoader) first to manage your mods! +mods.not_modded=You must install a modloader (Forge, NeoForge, Fabric, Legacy Fabric, Ornithe, Quilt, or LiteLoader) first to manage your mods! mods.restore=Restore mods.url=Official Page mods.update_modpack_mod.warning=Updating mods in a modpack can lead to irreparable results, possibly corrupting the modpack so that it cannot launch. Are you sure you want to update? diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index d488bc1df3..b2b514c894 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -697,7 +697,7 @@ install.installer.install=Instalando %s install.installer.install_offline=Instalar/actualizar desde archivo local install.installer.install_offline.tooltip=Apoyamos el uso del instalador local de (Neo)Forge/Cleanroom/OptiFine. install.installer.install_online=Instalación en línea -install.installer.install_online.tooltip=Actualmente soportamos Forge, NeoForge, Cleanroom, Fabric, Legacy Fabric, Quilt, LiteLoader y OptiFine. +install.installer.install_online.tooltip=Actualmente soportamos Forge, NeoForge, Cleanroom, Fabric, Legacy Fabric, Ornithe, Quilt, LiteLoader y OptiFine. install.installer.liteloader=LiteLoader install.installer.not_installed=No está instalado install.installer.optifine=OptiFine @@ -1060,7 +1060,7 @@ mods.mcmod.page=Página de MCMod mods.mcmod.search=Búsqueda en MCMod mods.modrinth=Modrinth mods.name=Nombre -mods.not_modded=¡Debes instalar primero un cargador de mods (Forge, NeoForge, Fabric, Legacy Fabric, Quilt o LiteLoader) para gestionar tus mods! +mods.not_modded=¡Debes instalar primero un cargador de mods (Forge, NeoForge, Fabric, Legacy Fabric, Ornithe, Quilt o LiteLoader) para gestionar tus mods! mods.restore=Restaurar mods.url=Página oficial mods.update_modpack_mod.warning=Actualizar mods en un modpack puede generar resultados irreparables, posiblemente corrompiendo el modpack para que no pueda iniciarse. ¿Seguro que quieres actualizar? diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index 68fa9a28b8..241f41873d 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -688,7 +688,7 @@ install.installer.install=Установить %s install.installer.install_offline=Установить/обновить из локального файла install.installer.install_offline.tooltip=Поддерживаются установщики (Neo)Forge/Cleanroom/OptiFine. install.installer.install_online=Установить с интернета -install.installer.install_online.tooltip=Поддерживаются Forge, NeoForge, Cleanroom, Fabric, Legacy Fabric, Quilt, LiteLoader и OptiFine. +install.installer.install_online.tooltip=Поддерживаются Forge, NeoForge, Cleanroom, Fabric, Legacy Fabric, Ornithe, Quilt, LiteLoader и OptiFine. install.installer.liteloader=LiteLoader install.installer.not_installed=Не установлено install.installer.optifine=OptiFine @@ -1053,7 +1053,7 @@ mods.mcmod.page=Страница MCMod mods.mcmod.search=Искать на MCMod mods.modrinth=Modrinth mods.name=Название -mods.not_modded=Для управления модами необходимо сначала установить загрузчик (Forge, NeoForge, Fabric, Legacy Fabric, Quilt или LiteLoader)! +mods.not_modded=Для управления модами необходимо сначала установить загрузчик (Forge, NeoForge, Fabric, Legacy Fabric, Ornithe, Quilt или LiteLoader)! mods.restore=Восстановить mods.url=Официальная страница mods.update_modpack_mod.warning=Обновление модов в пакете модов может привести к непоправимым результатам, возможно, повредить пакет модов так, что он не сможет запуститься. Вы уверены, что хотите обновить? diff --git a/HMCL/src/main/resources/assets/lang/I18N_uk.properties b/HMCL/src/main/resources/assets/lang/I18N_uk.properties index 7f2615b751..e1e6cfa37d 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_uk.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_uk.properties @@ -639,7 +639,7 @@ install.installer.install=Встановлення %s install.installer.install_offline=Встановити/Оновити з локального файлу install.installer.install_offline.tooltip=Ми підтримуємо використання локального інсталятора (Neo)Forge/Cleanroom/OptiFine. install.installer.install_online=Онлайн встановлення -install.installer.install_online.tooltip=Наразі ми підтримуємо Forge, NeoForge, Cleanroom, OptiFine, Fabric, Legacy Fabric, Quilt та LiteLoader. +install.installer.install_online.tooltip=Наразі ми підтримуємо Forge, NeoForge, Cleanroom, OptiFine, Fabric, Legacy Fabric, Ornithe, Quilt та LiteLoader. install.installer.liteloader=LiteLoader install.installer.not_installed=Не встановлено install.installer.optifine=OptiFine @@ -1000,7 +1000,7 @@ mods.mcmod.page=Сторінка MCMod mods.mcmod.search=Пошук в MCMod mods.modrinth=Modrinth mods.name=Назва -mods.not_modded=Ви повинні спочатку встановити завантажувач модів (Forge, NeoForge, Fabric, Legacy Fabric, Quilt або LiteLoader), щоб керувати своїми модами! +mods.not_modded=Ви повинні спочатку встановити завантажувач модів (Forge, NeoForge, Fabric, Legacy Fabric, Ornithe, Quilt або LiteLoader), щоб керувати своїми модами! mods.restore=Відновити mods.url=Офіційна сторінка mods.update_modpack_mod.warning=Оновлення модів у модпаку може призвести до непоправних наслідків, можливо, пошкодивши модпак так, що він не зможе запуститися. Ви впевнені, що хочете оновити? diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index b6bd2879d6..9afb1991c4 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -547,7 +547,7 @@ install.installer.install=安裝 %s install.installer.install_offline=從本機檔案安裝或升級 install.installer.install_offline.tooltip=支援匯入已經下載好的 (Neo)Forge、Cleanroom 及 OptiFine 安裝器 install.installer.install_online=線上安裝 -install.installer.install_online.tooltip=支援安裝 Forge、NeoForge、Cleanroom、Fabric、Legacy Fabric、Quilt、LiteLoader 和 OptiFine +install.installer.install_online.tooltip=支援安裝 Forge、NeoForge、Cleanroom、Fabric、Legacy Fabric、Ornithe、 Quilt、LiteLoader 和 OptiFine install.installer.liteloader=LiteLoader install.installer.not_installed=未安裝 install.installer.optifine=OptiFine @@ -910,7 +910,7 @@ mods.mcmod.page=MC 百科頁面 mods.mcmod.search=MC 百科檢索 mods.modrinth=Modrinth mods.name=名稱 -mods.not_modded=你需要先在「自動安裝」頁面安裝 Forge、NeoForge、Fabric、Legacy Fabric、Quilt 或 LiteLoader 才能管理模組。 +mods.not_modded=你需要先在「自動安裝」頁面安裝 Forge、NeoForge、Fabric、Legacy Fabric、Ornithe、 Quilt 或 LiteLoader 才能管理模組。 mods.restore=回退 mods.url=官方頁面 mods.update_modpack_mod.warning=更新模組包中的模組可能導致模組包損壞,使模組包無法正常啟動。該操作不可逆,確定要更新嗎? diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index 1053d1993f..69c3df3400 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -552,7 +552,7 @@ install.installer.install=安装 %s install.installer.install_offline=从本地文件安装/升级 install.installer.install_offline.tooltip=支持导入已经下载好的 (Neo)Forge、Cleanroom 和 OptiFine 安装器 install.installer.install_online=在线安装 -install.installer.install_online.tooltip=支持安装 Forge、NeoForge、Cleanroom、Fabric、Legacy Fabric、Quilt、LiteLoader 和 OptiFine +install.installer.install_online.tooltip=支持安装 Forge、NeoForge、Cleanroom、Fabric、Legacy Fabric、Ornithe、 Quilt、LiteLoader 和 OptiFine install.installer.liteloader=LiteLoader install.installer.not_installed=未安装 install.installer.optifine=OptiFine @@ -915,7 +915,7 @@ mods.mcmod.page=MC 百科页面 mods.mcmod.search=MC 百科搜索 mods.modrinth=Modrinth mods.name=名称 -mods.not_modded=你需要先在“自动安装”页面安装 Forge、NeoForge、Fabric、Legacy Fabric、Quilt 或 LiteLoader 才能管理模组。 +mods.not_modded=你需要先在“自动安装”页面安装 Forge、NeoForge、Fabric、Legacy Fabric、Ornithe、 Quilt 或 LiteLoader 才能管理模组。 mods.restore=回退 mods.url=官方页面 mods.update_modpack_mod.warning=更新整合包中的模组可能导致整合包损坏,使整合包无法正常启动。该操作不可逆,确定要更新吗? diff --git a/docs/README.md b/docs/README.md index 1379f65050..59f862b29a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -30,7 +30,7 @@ ## Introduction -HMCL is an open-source, cross-platform Minecraft launcher that supports Mod Management, Game Customizing, ModLoader Installing (Forge, NeoForge, Cleanroom, Fabric, Legacy Fabric, Quilt, LiteLoader, and OptiFine), Modpack Creating, UI Customization, and more. +HMCL is an open-source, cross-platform Minecraft launcher that supports Mod Management, Game Customizing, ModLoader Installing (Forge, NeoForge, Cleanroom, Fabric, Legacy Fabric, Ornithe, Quilt, LiteLoader, and OptiFine), Modpack Creating, UI Customization, and more. HMCL has amazing cross-platform capabilities. Not only does it run on different operating systems like Windows, Linux, macOS, and FreeBSD, but it also supports various CPU architectures such as x86, ARM, RISC-V, MIPS, and LoongArch. You can easily enjoy Minecraft across different platforms through HMCL. diff --git a/docs/README_en_Qabs.md b/docs/README_en_Qabs.md index 96c494ede9..e219693915 100644 --- a/docs/README_en_Qabs.md +++ b/docs/README_en_Qabs.md @@ -15,7 +15,7 @@ ˙˥ƆWH ɥƃnoɹɥʇ sɯɹoɟʇɐld ʇuǝɹǝɟɟᴉp ssoɹɔɐ ʇɟɐɹɔǝuᴉW ʎoɾuǝ ʎlᴉsɐǝ uɐɔ no⅄ ˙ɥɔɹ∀ƃuoo˥ puɐ 'SԀIW 'Λ-ƆSIɹ 'Wɹ∀ '98x sɐ ɥɔns sǝɹnʇɔǝʇᴉɥɔɹɐ ∩ԀƆ snoᴉɹɐʌ sʇɹoddns oslɐ ʇᴉ ʇnq 'pSqǝǝɹℲ puɐ 'SOɔɐɯ 'xnuᴉ˥ 'sʍopuᴉM ǝʞᴉl sɯǝʇsʎs ƃuᴉʇɐɹǝdo ʇuǝɹǝɟɟᴉp uo unɹ ʇᴉ sǝop ʎluo ʇoN ˙sǝᴉʇᴉlᴉqɐdɐɔ ɯɹoɟʇɐld-ssoɹɔ ƃuᴉzɐɯɐ sɐɥ ˥ƆWH -˙ǝɹoɯ puɐ 'uoᴉʇɐzᴉɯoʇsnƆ I∩ 'ƃuᴉʇɐǝɹƆ ʞɔɐdpoW '(ǝuᴉℲᴉʇdO puɐ 'ɹǝpɐo˥ǝʇᴉ˥ 'ʇlᴉnQ 'ɔᴉɹqɐℲ ʎɔɐᵷǝꞀ 'ɔᴉɹqɐℲ 'ɯooɹuɐǝlƆ 'ǝƃɹoℲoǝN 'ǝƃɹoℲ) ƃuᴉllɐʇsuI ɹǝpɐo˥poW 'ƃuᴉzᴉɯoʇsnƆ ǝɯɐפ 'ʇuǝɯǝƃɐuɐW poW sʇɹoddns ʇɐɥʇ ɹǝɥɔunɐl ʇɟɐɹɔǝuᴉW ɯɹoɟʇɐld-ssoɹɔ 'ǝɔɹnos-uǝdo uɐ sᴉ ˥ƆWH +˙ǝɹoɯ puɐ 'uoᴉʇɐzᴉɯoʇsnƆ I∩ 'ƃuᴉʇɐǝɹƆ ʞɔɐdpoW '(ǝuᴉℲᴉʇdO puɐ 'ɹǝpɐo˥ǝʇᴉ˥ 'ʇlᴉnQ 'ǝɥʇᴉuɹO 'ɔᴉɹqɐℲ ʎɔɐᵷǝꞀ 'ɔᴉɹqɐℲ 'ɯooɹuɐǝlƆ 'ǝƃɹoℲoǝN 'ǝƃɹoℲ) ƃuᴉllɐʇsuI ɹǝpɐo˥poW 'ƃuᴉzᴉɯoʇsnƆ ǝɯɐפ 'ʇuǝɯǝƃɐuɐW poW sʇɹoddns ʇɐɥʇ ɹǝɥɔunɐl ʇɟɐɹɔǝuᴉW ɯɹoɟʇɐld-ssoɹɔ 'ǝɔɹnos-uǝdo uɐ sᴉ ˥ƆWH ## pɐoluʍoᗡ diff --git a/docs/README_es.md b/docs/README_es.md index 55634b80ec..ceb373cbe3 100644 --- a/docs/README_es.md +++ b/docs/README_es.md @@ -30,7 +30,7 @@ English ([Standard](README.md), [uʍoᗡ ǝpᴉsd∩](README_en_Qabs.md)) | 中 ## Introducción -HMCL es un lanzador de Minecraft de código abierto y multiplataforma que admite la gestión de mods, personalización del juego, instalación de ModLoaders (Forge, NeoForge, Cleanroom, Fabric, Legacy Fabric, Quilt, LiteLoader y OptiFine), creación de modpacks, personalización de la interfaz de usuario y más. +HMCL es un lanzador de Minecraft de código abierto y multiplataforma que admite la gestión de mods, personalización del juego, instalación de ModLoaders (Forge, NeoForge, Cleanroom, Fabric, Legacy Fabric, Ornithe, Quilt, LiteLoader y OptiFine), creación de modpacks, personalización de la interfaz de usuario y más. HMCL tiene increíbles capacidades multiplataforma. No solo funciona en diferentes sistemas operativos como Windows, Linux, macOS y FreeBSD, sino que también es compatible con varias arquitecturas de CPU como x86, ARM, RISC-V, MIPS y LoongArch. Puedes disfrutar fácilmente de Minecraft en diferentes plataformas a través de HMCL. diff --git a/docs/README_ja.md b/docs/README_ja.md index 6d14e9f7b4..4557dd51a3 100644 --- a/docs/README_ja.md +++ b/docs/README_ja.md @@ -30,7 +30,7 @@ English ([Standard](README.md), [uʍoᗡ ǝpᴉsd∩](README_en_Qabs.md)) | 中 ## 紹介 -HMCLはオープンソースでクロスプラットフォーム対応のMinecraftランチャーです。Mod管理、ゲームカスタマイズ、Modローダーのインストール(Forge、NeoForge、Cleanroom、Fabric、Legacy Fabric、Quilt、LiteLoader、OptiFine)、Modパック作成、UIカスタマイズなど、さまざまな機能をサポートしています。 +HMCLはオープンソースでクロスプラットフォーム対応のMinecraftランチャーです。Mod管理、ゲームカスタマイズ、Modローダーのインストール(Forge、NeoForge、Cleanroom、Fabric、Legacy Fabric、Ornithe、 Quilt、LiteLoader、OptiFine)、Modパック作成、UIカスタマイズなど、さまざまな機能をサポートしています。 HMCLは優れたクロスプラットフォーム性能を持っています。Windows、Linux、macOS、FreeBSDなどの異なるオペレーティングシステムだけでなく、x86、ARM、RISC-V、MIPS、LoongArchなどのさまざまなCPUアーキテクチャにも対応しています。HMCLを使えば、さまざまなプラットフォームでMinecraftを簡単に楽しむことができます。 diff --git a/docs/README_lzh.md b/docs/README_lzh.md index e490dee194..845abfcfb6 100644 --- a/docs/README_lzh.md +++ b/docs/README_lzh.md @@ -30,7 +30,7 @@ English ([Standard](README.md), [uʍoᗡ ǝpᴉsd∩](README_en_Qabs.md)) | ** ### 概敘 -HMCL 者,開源之礦藝啟器也。善理改囊,可自定遊戲,自動裝設 Forge、NeoForge、Cleanroom、Fabric、Legacy Fabric、Quilt、LiteLoader、OptiFine 諸改囊,亦能制改囊集,界面隨心易之。 +HMCL 者,開源之礦藝啟器也。善理改囊,可自定遊戲,自動裝設 Forge、NeoForge、Cleanroom、Fabric、Legacy Fabric、Ornithe、 Quilt、LiteLoader、OptiFine 諸改囊,亦能制改囊集,界面隨心易之。 HMCL 跨域廣矣。Windows、Linux、macOS、FreeBSD 諸常見械綱,x86、ARM、RISC-V、MIPS、LoongArch 諸算器架構,皆可運行。 憑此器,可遊《礦藝》於諸機之間,無礙也。 diff --git a/docs/README_ru.md b/docs/README_ru.md index 762eb4922f..07abd5f41a 100644 --- a/docs/README_ru.md +++ b/docs/README_ru.md @@ -30,7 +30,7 @@ English ([Standard](README.md), [uʍoᗡ ǝpᴉsd∩](README_en_Qabs.md)) | 中 ## Введение -HMCL — это открытый, кроссплатформенный лаунчер для Minecraft с поддержкой управления модами, настройки игры, установки загрузчиков модов (Forge, NeoForge, Cleanroom, Fabric, Legacy Fabric, Quilt, LiteLoader и OptiFine), создания модпаков, настройки интерфейса и многого другого. +HMCL — это открытый, кроссплатформенный лаунчер для Minecraft с поддержкой управления модами, настройки игры, установки загрузчиков модов (Forge, NeoForge, Cleanroom, Fabric, Legacy Fabric, Ornithe, Quilt, LiteLoader и OptiFine), создания модпаков, настройки интерфейса и многого другого. HMCL обладает отличной кроссплатформенностью. Он работает не только на различных операционных системах, таких как Windows, Linux, macOS и FreeBSD, но и поддерживает различные архитектуры процессоров: x86, ARM, RISC-V, MIPS и LoongArch. Благодаря HMCL вы можете легко наслаждаться Minecraft на разных платформах. diff --git a/docs/README_uk.md b/docs/README_uk.md index 39d0d517a1..7b6398a935 100644 --- a/docs/README_uk.md +++ b/docs/README_uk.md @@ -30,7 +30,7 @@ English ([Standard](README.md), [uʍoᗡ ǝpᴉsd∩](README_en_Qabs.md)) | 中 ## Вступ -HMCL — це відкритий, кросплатформний лаунчер для Minecraft, який підтримує керування модами, налаштування гри, встановлення модлоадерів (Forge, NeoForge, Cleanroom, Fabric, Legacy Fabric, Quilt, LiteLoader та OptiFine), створення модпаків, налаштування інтерфейсу та багато іншого. +HMCL — це відкритий, кросплатформний лаунчер для Minecraft, який підтримує керування модами, налаштування гри, встановлення модлоадерів (Forge, NeoForge, Cleanroom, Fabric, Legacy Fabric, Ornithe, Quilt, LiteLoader та OptiFine), створення модпаків, налаштування інтерфейсу та багато іншого. HMCL має чудові кросплатформні можливості. Він працює не лише на різних операційних системах, таких як Windows, Linux, macOS і FreeBSD, а й підтримує різні архітектури процесорів, такі як x86, ARM, RISC-V, MIPS і LoongArch. Ви можете легко насолоджуватися Minecraft на різних платформах за допомогою HMCL. diff --git a/docs/README_zh.md b/docs/README_zh.md index 57cf1bb745..0282b437bb 100644 --- a/docs/README_zh.md +++ b/docs/README_zh.md @@ -30,7 +30,7 @@ English ([Standard](README.md), [uʍoᗡ ǝpᴉsd∩](README_en_Qabs.md)) | ** ## 简介 -HMCL 是一款开源、跨平台的 Minecraft 启动器,支持模组管理、游戏自定义、游戏自动安装 (Forge、NeoForge、Cleanroom、Fabric、Legacy Fabric、Quilt、LiteLoader 和 OptiFine)、整合包创建、界面自定义等功能。 +HMCL 是一款开源、跨平台的 Minecraft 启动器,支持模组管理、游戏自定义、游戏自动安装 (Forge、NeoForge、Cleanroom、Fabric、Legacy Fabric、Ornithe、 Quilt、LiteLoader 和 OptiFine)、整合包创建、界面自定义等功能。 HMCL 有着强大的跨平台能力。它不仅支持 Windows、Linux、macOS、FreeBSD 等常见的操作系统,同时也支持 x86、ARM、RISC-V、MIPS、LoongArch 等不同的 CPU 架构。你可以使用 HMCL 在不同平台上轻松地游玩 Minecraft。 diff --git a/docs/README_zh_Hant.md b/docs/README_zh_Hant.md index 59d0b0b638..3111b4c4b0 100644 --- a/docs/README_zh_Hant.md +++ b/docs/README_zh_Hant.md @@ -30,7 +30,7 @@ English ([Standard](README.md), [uʍoᗡ ǝpᴉsd∩](README_en_Qabs.md)) | ** ## 簡介 -HMCL 是一款開源、跨平臺的 Minecraft 啟動器,支援模組管理、遊戲客製化、遊戲自動安裝 (Forge、NeoForge、Cleanroom、Fabric、Legacy Fabric、Quilt、LiteLoader 和 OptiFine)、模組包建立、介面客製化等功能。 +HMCL 是一款開源、跨平臺的 Minecraft 啟動器,支援模組管理、遊戲客製化、遊戲自動安裝 (Forge、NeoForge、Cleanroom、Fabric、Legacy Fabric、Ornithe、 Quilt、LiteLoader 和 OptiFine)、模組包建立、介面客製化等功能。 HMCL 有著強大的跨平臺能力。它不僅支援 Windows、Linux、macOS、FreeBSD 等常見的作業系統,同時也支援 x86、ARM、RISC-V、MIPS、LoongArch 等不同的 CPU 架構。你可以使用 HMCL 在不同平臺上輕鬆地遊玩 Minecraft。 From 84f8db214f6ed7351e7f64b9763461002ccf4dc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:56:45 +0800 Subject: [PATCH 22/23] =?UTF-8?q?=E6=9C=88=E5=84=BF=E5=BC=AF=E5=BC=AF=20?= =?UTF-8?q?=E7=83=9F=E7=81=AB=E6=BC=AB=E6=BC=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/jackhuang/hmcl/mod/ModLoaderType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModLoaderType.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModLoaderType.java index 9efee90063..b542b940d4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModLoaderType.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModLoaderType.java @@ -31,7 +31,7 @@ public enum ModLoaderType { private final String id; - ModLoaderType(String id){ + ModLoaderType(String id) { this.id = id; } From 821aaa0ca8c222e3f6163dc4c0aeb56cffc84bc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sun, 29 Mar 2026 09:57:25 +0800 Subject: [PATCH 23/23] =?UTF-8?q?=E6=9C=88=E5=84=BF=E5=BC=AF=E5=BC=AF=20?= =?UTF-8?q?=E7=83=9F=E7=81=AB=E6=BC=AB=E6=BC=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java index a9ac9bb670..03fa432bea 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java @@ -43,6 +43,7 @@ import org.jackhuang.hmcl.download.liteloader.LiteLoaderRemoteVersion; import org.jackhuang.hmcl.download.neoforge.NeoForgeRemoteVersion; import org.jackhuang.hmcl.download.optifine.OptiFineRemoteVersion; +import org.jackhuang.hmcl.download.ornithe.OrnitheOSLRemoteVersion; import org.jackhuang.hmcl.download.ornithe.OrnitheRemoteVersion; import org.jackhuang.hmcl.download.quilt.QuiltAPIRemoteVersion; import org.jackhuang.hmcl.download.quilt.QuiltRemoteVersion; @@ -269,7 +270,7 @@ else if (remoteVersion instanceof CleanroomRemoteVersion) iconType = VersionIconType.CLEANROOM; else if (remoteVersion instanceof NeoForgeRemoteVersion) iconType = VersionIconType.NEO_FORGE; - else if (remoteVersion instanceof OrnitheRemoteVersion) + else if (remoteVersion instanceof OrnitheRemoteVersion || remoteVersion instanceof OrnitheOSLRemoteVersion) iconType = VersionIconType.ORNITHE; else if (remoteVersion instanceof LegacyFabricRemoteVersion || remoteVersion instanceof LegacyFabricAPIRemoteVersion) iconType = VersionIconType.LEGACY_FABRIC;