Compare commits

...
Author SHA1 Message Date
Glavo ab6e8692ad 修复缓存异常时 FetchTask 无限循环的问题 (#4844) 2025-11-23 15:20:14 +08:00
辞庐 97ada51489 更新 amdgpu.ids (#4845) 2025-11-23 15:15:37 +08:00
Burning_TNT 8e9c2f27a1 Bump Terracotta to 0.3.14 (#4838)
* 更新 MacOS 元数据以增强本地化支持 by @burningtnt in
https://github.com/burningtnt/Terracotta/pull/69
* 重构 EasyTier 参数拼接逻辑 by @burningtnt in
https://github.com/burningtnt/Terracotta/pull/81
* 为 ET 添加 tcp://0.0.0.0:0 监听器 by @burningtnt in
https://github.com/burningtnt/Terracotta/pull/90
* 强制 ET 以 p2p_only 模式运行 by @burningtnt in
https://github.com/burningtnt/Terracotta/pull/97
* 支持联机房间码持久化 by @burningtnt in
https://github.com/burningtnt/Terracotta/pull/94
* 修复 'API c:player_profiles_list invocation failed: Host Profile is
consumed or invalid, machine_id may have conflict.' 的问题 by @burningtnt
in https://github.com/burningtnt/Terracotta/pull/98
2025-11-22 15:28:36 +08:00
mineDiamondandGlavo 8563db3654 添加对 1.21.11-pre1/2_unobfuscated 的支持 (#4829)
Co-authored-by: Glavo <zjx001202@gmail.com>
2025-11-21 22:06:51 +08:00
Glavo 2695b5c42f 使用 EdgeOne 分发 HMCL 元数据 (#4830) 2025-11-21 22:02:04 +08:00
Glavo bed87425e7 从首页打开子页面时应当打开默认标签页 (#4826) 2025-11-20 17:40:51 +08:00
Glavo d6ad1cbdf7 修复 TabHeader 相关动画问题 (#4822) 2025-11-19 15:32:18 +08:00
20 changed files with 138 additions and 101 deletions

No files matched your search

@@ -26,7 +26,6 @@ import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.util.Duration;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.construct.TabHeader;
import org.jetbrains.annotations.Nullable;
public class TransitionPane extends StackPane {
@@ -41,17 +40,6 @@ public class TransitionPane extends StackPane {
return currentNode;
}
public void bindTabHeader(TabHeader tabHeader) {
this.setContent(tabHeader.getSelectionModel().getSelectedItem().getNode(), ContainerAnimations.NONE);
FXUtils.onChange(tabHeader.getSelectionModel().selectedItemProperty(), newValue -> {
this.setContent(newValue.getNode(),
ContainerAnimations.SLIDE_UP_FADE_IN,
Motion.MEDIUM4,
Motion.EASE_IN_OUT_CUBIC_EMPHASIZED
);
});
}
public final void setContent(Node newView, AnimationProducer transition) {
setContent(newView, transition, Motion.SHORT4);
}
@@ -66,6 +54,7 @@ public class TransitionPane extends StackPane {
currentNode = newView;
if (!AnimationUtils.isAnimationEnabled() || previousNode == null || transition == ContainerAnimations.NONE) {
AnimationUtils.reset(newView, true);
getChildren().setAll(newView);
return;
}
@@ -36,12 +36,24 @@ import javafx.scene.transform.Rotate;
import javafx.scene.transform.Scale;
import javafx.util.Duration;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.animation.ContainerAnimations;
import org.jackhuang.hmcl.ui.animation.Motion;
import org.jackhuang.hmcl.ui.animation.TransitionPane;
import org.jackhuang.hmcl.util.javafx.MappedObservableList;
import org.jetbrains.annotations.Nullable;
@SuppressWarnings("deprecation")
public class TabHeader extends Control implements TabControl, PageAware {
private final TransitionPane contentPane;
public TabHeader(Tab<?>... tabs) {
this(null, tabs);
}
public TabHeader(@Nullable TransitionPane contentPane, Tab<?>... tabs) {
this.contentPane = contentPane;
getStyleClass().setAll("tab-header");
if (tabs != null) {
getTabs().addAll(tabs);
@@ -49,41 +61,48 @@ public class TabHeader extends Control implements TabControl, PageAware {
}
private final ObservableList<Tab<?>> tabs = FXCollections.observableArrayList();
private final ObjectProperty<Side> side = new SimpleObjectProperty<>(Side.TOP);
@Override
public ObservableList<Tab<?>> getTabs() {
return tabs;
}
private final ObjectProperty<SingleSelectionModel<Tab<?>>> selectionModel = new SimpleObjectProperty<>(this, "selectionModel", new TabControlSelectionModel(this));
private final SingleSelectionModel<Tab<?>> selectionModel = new TabControlSelectionModel(this);
public SingleSelectionModel<Tab<?>> getSelectionModel() {
return selectionModel.get();
}
public ObjectProperty<SingleSelectionModel<Tab<?>>> selectionModelProperty() {
return selectionModel;
}
public void setSelectionModel(SingleSelectionModel<Tab<?>> selectionModel) {
this.selectionModel.set(selectionModel);
public void select(Tab<?> tab) {
select(tab, true);
}
public void select(Tab<?> tab) {
public void select(Tab<?> tab, boolean playAnimation) {
Tab<?> oldTab = getSelectionModel().getSelectedItem();
if (oldTab != null) {
if (oldTab.getNode() instanceof PageAware) {
((PageAware) oldTab.getNode()).onPageHidden();
if (oldTab.getNode() instanceof PageAware pageAware) {
pageAware.onPageHidden();
}
}
tab.initializeIfNeeded();
if (tab.getNode() instanceof PageAware) {
((PageAware) tab.getNode()).onPageShown();
if (tab.getNode() instanceof PageAware pageAware) {
pageAware.onPageShown();
}
getSelectionModel().select(tab);
if (contentPane != null) {
if (playAnimation && contentPane.getCurrentNode() != null) {
contentPane.setContent(tab.getNode(),
ContainerAnimations.SLIDE_UP_FADE_IN,
Motion.MEDIUM4,
Motion.EASE_IN_OUT_CUBIC_EMPHASIZED
);
} else {
contentPane.setContent(tab.getNode(), ContainerAnimations.NONE);
}
}
}
@Override
@@ -106,12 +125,7 @@ public class TabHeader extends Control implements TabControl, PageAware {
}
}
/**
* The position to place the tabs.
*/
public Side getSide() {
return side.get();
}
private final ObjectProperty<Side> side = new SimpleObjectProperty<>(Side.TOP);
/**
* The position of the tabs.
@@ -120,6 +134,13 @@ public class TabHeader extends Control implements TabControl, PageAware {
return side;
}
/**
* The position to place the tabs.
*/
public Side getSide() {
return side.get();
}
/**
* The position the place the tabs in this TabHeader.
*/
@@ -39,7 +39,6 @@ import org.jackhuang.hmcl.ui.WeakListenerHolder;
import org.jackhuang.hmcl.ui.animation.TransitionPane;
import org.jackhuang.hmcl.ui.construct.AdvancedListBox;
import org.jackhuang.hmcl.ui.construct.MessageDialogPane;
import org.jackhuang.hmcl.ui.construct.TabControl;
import org.jackhuang.hmcl.ui.construct.TabHeader;
import org.jackhuang.hmcl.ui.decorator.DecoratorAnimatedPage;
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
@@ -99,12 +98,11 @@ public class DownloadPage extends DecoratorAnimatedPage implements DecoratorPage
resourcePackTab.setNodeSupplier(loadVersionFor(() -> HMCLLocalizedDownloadListPage.ofResourcePack((profile, version, file) -> download(profile, version, file, "resourcepacks"), true)));
shaderTab.setNodeSupplier(loadVersionFor(() -> new DownloadListPage(ModrinthRemoteModRepository.SHADER_PACKS, (profile, version, file) -> download(profile, version, file, "shaderpacks"), true)));
worldTab.setNodeSupplier(loadVersionFor(() -> new DownloadListPage(CurseForgeRemoteModRepository.WORLDS)));
tab = new TabHeader(newGameTab, modpackTab, modTab, resourcePackTab, shaderTab, worldTab);
tab = new TabHeader(transitionPane, newGameTab, modpackTab, modTab, resourcePackTab, shaderTab, worldTab);
Profiles.registerVersionsListener(this::loadVersions);
tab.select(newGameTab);
transitionPane.bindTabHeader(tab);
AdvancedListBox sideBar = new AdvancedListBox()
.startCategory(i18n("download.game").toUpperCase(Locale.ROOT))
@@ -121,13 +119,6 @@ public class DownloadPage extends DecoratorAnimatedPage implements DecoratorPage
setCenter(transitionPane);
}
private void selectTabIfCurseForgeAvailable(TabControl.Tab<?> newTab) {
if (CurseForgeRemoteModRepository.isAvailable())
tab.select(newTab);
else
Controllers.dialog(i18n("download.curseforge.unavailable"));
}
private static <T extends Node> Supplier<T> loadVersionFor(Supplier<T> nodeSupplier) {
return () -> {
T node = nodeSupplier.get();
@@ -202,20 +193,20 @@ public class DownloadPage extends DecoratorAnimatedPage implements DecoratorPage
}
public void showGameDownloads() {
tab.select(newGameTab);
tab.select(newGameTab, false);
}
public void showModpackDownloads() {
tab.select(modpackTab);
tab.select(modpackTab, false);
}
public DownloadListPage showModDownloads() {
tab.select(modTab);
tab.select(modTab, false);
return modTab.getNode();
}
public void showWorldDownloads() {
tab.select(worldTab);
tab.select(worldTab, false);
}
private static final class DownloadNavigator implements Navigation {
@@ -55,11 +55,10 @@ public class LauncherSettingsPage extends DecoratorAnimatedPage implements Decor
helpTab.setNodeSupplier(HelpPage::new);
feedbackTab.setNodeSupplier(FeedbackPage::new);
aboutTab.setNodeSupplier(AboutPage::new);
tab = new TabHeader(gameTab, javaManagementTab, settingsTab, personalizationTab, downloadTab, helpTab, feedbackTab, aboutTab);
tab = new TabHeader(transitionPane, gameTab, javaManagementTab, settingsTab, personalizationTab, downloadTab, helpTab, feedbackTab, aboutTab);
tab.select(gameTab);
addEventHandler(Navigator.NavigationEvent.NAVIGATED, event -> gameTab.getNode().loadVersion(Profiles.getSelectedProfile(), null));
transitionPane.bindTabHeader(tab);
AdvancedListBox sideBar = new AdvancedListBox()
.addNavigationDrawerTab(tab, gameTab, i18n("settings.type.global.manage"), SVG.STADIA_CONTROLLER, SVG.STADIA_CONTROLLER_FILL)
@@ -90,11 +89,11 @@ public class LauncherSettingsPage extends DecoratorAnimatedPage implements Decor
public void showGameSettings(Profile profile) {
gameTab.getNode().loadVersion(profile, null);
tab.select(gameTab);
tab.select(gameTab, false);
}
public void showFeedback() {
tab.select(feedbackTab);
tab.select(feedbackTab, false);
}
@Override
@@ -177,7 +177,10 @@ public class RootPage extends DecoratorAnimatedPage implements DecoratorPage {
downloadItem.setLeftGraphic(wrap(SVG.DOWNLOAD));
downloadItem.setActionButtonVisible(false);
downloadItem.setTitle(i18n("download"));
downloadItem.setOnAction(e -> Controllers.navigate(Controllers.getDownloadPage()));
downloadItem.setOnAction(e -> {
Controllers.getDownloadPage().showGameDownloads();
Controllers.navigate(Controllers.getDownloadPage());
});
FXUtils.installFastTooltip(downloadItem, i18n("download.hint"));
if (AnimationUtils.isAnimationEnabled()) {
FXUtils.prepareOnMouseEnter(downloadItem, Controllers::prepareDownloadPage);
@@ -188,7 +191,10 @@ public class RootPage extends DecoratorAnimatedPage implements DecoratorPage {
launcherSettingsItem.setLeftGraphic(wrap(SVG.SETTINGS));
launcherSettingsItem.setActionButtonVisible(false);
launcherSettingsItem.setTitle(i18n("settings"));
launcherSettingsItem.setOnAction(e -> Controllers.navigate(Controllers.getSettingsPage()));
launcherSettingsItem.setOnAction(e -> {
Controllers.getSettingsPage().showGameSettings(Profiles.getSelectedProfile());
Controllers.navigate(Controllers.getSettingsPage());
});
if (AnimationUtils.isAnimationEnabled()) {
FXUtils.prepareOnMouseEnter(launcherSettingsItem, Controllers::prepareSettingsPage);
}
@@ -56,9 +56,8 @@ public class TerracottaPage extends DecoratorAnimatedPage implements DecoratorPa
public TerracottaPage() {
statusPage.setNodeSupplier(TerracottaControllerPage::new);
tab = new TabHeader(statusPage);
tab = new TabHeader(transitionPane, statusPage);
tab.select(statusPage);
transitionPane.bindTabHeader(tab);
BorderPane left = new BorderPane();
FXUtils.setLimitWidth(left, 200);
@@ -71,13 +71,11 @@ public class VersionPage extends DecoratorAnimatedPage implements DecoratorPage
worldListTab.setNodeSupplier(loadVersionFor(WorldListPage::new));
schematicsTab.setNodeSupplier(loadVersionFor(SchematicsPage::new));
tab = new TabHeader(versionSettingsTab, installerListTab, modListTab, worldListTab, schematicsTab);
tab = new TabHeader(transitionPane, versionSettingsTab, installerListTab, modListTab, worldListTab, schematicsTab);
tab.select(versionSettingsTab);
addEventHandler(Navigator.NavigationEvent.NAVIGATED, this::onNavigated);
tab.select(versionSettingsTab);
transitionPane.bindTabHeader(tab);
listenerHolder.add(EventBus.EVENT_BUS.channel(RefreshedVersionsEvent.class).registerWeak(event -> checkSelectedVersion(), EventPriority.HIGHEST));
}
@@ -107,6 +105,10 @@ public class VersionPage extends DecoratorAnimatedPage implements DecoratorPage
};
}
public void showInstanceSettings() {
tab.select(versionSettingsTab, false);
}
public void setVersion(String version, Profile profile) {
this.version.set(new Profile.ProfileVersion(profile, version));
}
@@ -287,6 +287,7 @@ public final class Versions {
public static void modifyGameSettings(Profile profile, String version) {
Controllers.getVersionPage().setVersion(version, profile);
Controllers.getVersionPage().showInstanceSettings();
// VersionPage.loadVersion will be invoked after navigation
Controllers.navigate(Controllers.getVersionPage());
}
@@ -64,15 +64,13 @@ public final class WorldManagePage extends DecoratorAnimatedPage implements Deco
this.world = world;
this.backupsDir = backupsDir;
this.worldInfoTab.setNodeSupplier(() -> new WorldInfoPage(this));
this.worldBackupsTab.setNodeSupplier(() -> new WorldBackupsPage(this));
this.datapackTab.setNodeSupplier(() -> new DatapackListPage(this));
this.state = new SimpleObjectProperty<>(State.fromTitle(i18n("world.manage.title", world.getWorldName())));
this.header = new TabHeader(worldInfoTab, worldBackupsTab);
worldInfoTab.setNodeSupplier(() -> new WorldInfoPage(this));
worldBackupsTab.setNodeSupplier(() -> new WorldBackupsPage(this));
datapackTab.setNodeSupplier(() -> new DatapackListPage(this));
this.header = new TabHeader(transitionPane, worldInfoTab, worldBackupsTab);
header.select(worldInfoTab);
transitionPane.bindTabHeader(header);
setCenter(transitionPane);
@@ -112,7 +112,7 @@ public final class UpdateChecker {
try {
result = checkUpdate(channel, preview);
LOG.info("Latest version (" + channel + ", preview=" + preview + ") is " + result);
} catch (IOException e) {
} catch (Throwable e) {
LOG.warning("Failed to check for update", e);
}
@@ -30,7 +30,7 @@ public final class MinecraftWiki {
private static final Pattern SNAPSHOT_PATTERN = Pattern.compile("^[0-9]{2}w[0-9]{2}.+$");
public static String getWikiLink(SupportedLocale locale, GameRemoteVersion version) {
String wikiVersion = version.getSelfVersion();
String wikiVersion = StringUtils.removeSuffix(version.getSelfVersion(), "_unobfuscated");
var gameVersion = GameVersionNumber.asGameVersion(wikiVersion);
if (locale.getLocale().getLanguage().equals("lzh")) {
@@ -80,8 +80,6 @@ public final class MinecraftWiki {
if (SNAPSHOT_PATTERN.matcher(wikiVersion).matches()) {
if (wikiVersion.equals("22w13oneblockatatime"))
wikiVersion = "22w13oneBlockAtATime";
else
wikiVersion = StringUtils.removeSuffix(wikiVersion, "_unobfuscated");
return locale.i18n("wiki.version.game.snapshot", wikiVersion) + variantSuffix;
}
}
+14 -14
View File
@@ -1,21 +1,21 @@
{
"version_legacy": "0\\.3\\.([89]-rc\\.([0-9]|10)|10|11|12)",
"version_legacy": "0\\.3\\.([89]-rc\\.([0-9]|10)|(1[0-3]))",
"version_recent": [
"0.3.12"
"0.3.13"
],
"version_latest": "0.3.13",
"version_latest": "0.3.14",
"classifiers": {
"freebsd-x86_64": "sha256:0713e54ee552496416bda9d9e814e33a8950ca8f321f5b3c6dd2e07e79b0e3af",
"linux-arm64": "sha256:61affc46035337c182adeca3671b4cf4cc59c7b4e73039899f35416f7d00ad94",
"linux-x86_64": "sha256:9399e1627b77d518950e66d944c9a4b70c20d2e13ca2c0e2fed0ded637e7ae06",
"linux-loongarch64": "sha256:f3eb4c40dfccc25b5b355298c776abe3d399afb57a2af38803dd78089f0c182e",
"linux-riscv64": "sha256:26f95f8b5f83746c9cf9a8362ce0ef793ede8515897a1ba15e5e6f93c3d39533",
"macos-arm64": "sha256:35ba271c7dc924e91c2fdd8c1cabeff2ce3d060836748a7a07162b0a5900e8d5",
"macos-arm64.pkg": "sha256:90a613ec69f28713fe06188247c57b7cc91743c95112de5aed85ea252103beaa",
"macos-x86_64": "sha256:45b420b15a32d5450794a9776cf45a217871cf4333b29b65a35d7358c806b5b1",
"macos-x86_64.pkg": "sha256:587623becb3593ccb5fe542a201a67ab3a4029dfa847fcef758faff7ba6d38d5",
"windows-arm64.exe": "sha256:bd4e1acf2f304761cdabddd9ade94d046534f4c024bc3026ac98e6be58c2bc22",
"windows-x86_64.exe": "sha256:b89599bbcc92b00222cfc6f2e5ef636b7daf192c96efba1049a892e6cb59ee70"
"freebsd-x86_64": "sha256:ff8c50b701e55fde9701a1f7fbe9d7317b24087c28ca6337ba9d695c53ad499a",
"linux-arm64": "sha256:6912a14255cdeedee512244c686dd7f80dcc45d8dfbe129ea4ea3f1b22d3de60",
"linux-x86_64": "sha256:9b13f51dc41c5112f2ab163df5c0dccdff3d22deb793a6698c013e9c09badd00",
"linux-loongarch64": "sha256:729ca24ef643547b6a3917520ec3335b92e226ad1884c85d6bb6c2cfa917cb03",
"linux-riscv64": "sha256:afbd8cffeacc47431f18c3ae659f7a308e1d3f2efab0ab9c5ece5176d068bf30",
"macos-arm64": "sha256:9ed9c7a35b01dce440135c91e4a5e617d84f6c8ba13a117d13a2796dc69584f5",
"macos-arm64.pkg": "sha256:49dbebd608c4036c260f09d4005dedaacb26fc1582b10479ed51476baa48f4a9",
"macos-x86_64": "sha256:40a44703237b0a194b0fb18075e3b2361ace8f4319b60269cb56c5548d2afb3a",
"macos-x86_64.pkg": "sha256:95a9de782b9c3a352ae6ec702c2fc4ca34ba807e8e4a768e61902a0c78391332",
"windows-arm64.exe": "sha256:8428c6bc6228213c5f645ab3dd0f3b684da515be103ee53d5bdc4adf59fc8a5f",
"windows-x86_64.exe": "sha256:942b91888264e1c96a10b7c94bd134f4b10d3e352e3c731def0ff6a3069c8221"
},
"downloads": [
"https://github.com/burningtnt/Terracotta/releases/download/v${version}/terracotta-${version}-${classifier}"
@@ -82,8 +82,8 @@ public final class BMCLAPIDownloadProvider implements DownloadProvider {
pair("https://authlib-injector.yushi.moe", apiRoot + "/mirrors/authlib-injector"),
pair("https://repo1.maven.org/maven2", "https://mirrors.cloud.tencent.com/nexus/repository/maven-public"),
pair("https://repo.maven.apache.org/maven2", "https://mirrors.cloud.tencent.com/nexus/repository/maven-public"),
pair("https://hmcl-dev.github.io/metadata/cleanroom", "https://alist.8mi.tech/d/mirror/HMCL-Metadata/Auto/cleanroom"),
pair("https://hmcl-dev.github.io/metadata/fmllibs", "https://alist.8mi.tech/d/mirror/HMCL-Metadata/Auto/fmllibs"),
pair("https://hmcl.glavo.site/metadata/cleanroom", "https://alist.8mi.tech/d/mirror/HMCL-Metadata/Auto/cleanroom"),
pair("https://hmcl.glavo.site/metadata/fmllibs", "https://alist.8mi.tech/d/mirror/HMCL-Metadata/Auto/fmllibs"),
pair("https://zkitefly.github.io/unlisted-versions-of-minecraft", "https://alist.8mi.tech/d/mirror/unlisted-versions-of-minecraft/Auto")
// // https://github.com/mcmod-info-mirror/mcim-rust-api
// pair("https://api.modrinth.com", "https://mod.mcimirror.top/modrinth"),
@@ -27,8 +27,8 @@ import java.util.Collections;
public final class CleanroomVersionList extends VersionList<CleanroomRemoteVersion> {
private final DownloadProvider downloadProvider;
private static final String LOADER_LIST_URL = "https://hmcl-dev.github.io/metadata/cleanroom/index.json";
private static final String INSTALLER_URL = "https://hmcl-dev.github.io/metadata/cleanroom/files/cleanroom-%s-installer.jar";
private static final String LOADER_LIST_URL = "https://hmcl.glavo.site/metadata/cleanroom/index.json";
private static final String INSTALLER_URL = "https://hmcl.glavo.site/metadata/cleanroom/files/cleanroom-%s-installer.jar";
public CleanroomVersionList(DownloadProvider downloadProvider) {
this.downloadProvider = downloadProvider;
@@ -96,5 +96,5 @@ public final class ForgeVersionList extends VersionList<ForgeRemoteVersion> {
});
}
public static final URI FORGE_LIST = URI.create("https://hmcl-dev.github.io/metadata/forge/");
public static final URI FORGE_LIST = URI.create("https://hmcl.glavo.site/metadata/forge/");
}
@@ -149,7 +149,7 @@ public final class GameLibrariesTask extends Task<Void> {
Path file = libDir.resolve(fmlLib.name);
if (shouldDownloadFMLLib(fmlLib, file)) {
List<URI> uris = dependencyManager.getDownloadProvider()
.injectURLWithCandidates(fmlLib.getDownloadURI());
.injectURLWithCandidates(fmlLib.downloadUrl());
dependencies.add(new FileDownloadTask(uris, file)
.withCounter("hmcl.install.libraries"));
}
@@ -193,9 +193,12 @@ public final class GameLibrariesTask extends Task<Void> {
if (forgeVersion.startsWith("7.8.1.")) {
return List.of(
new FMLLib("argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51"),
new FMLLib("guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a"),
new FMLLib("asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58"),
new FMLLib("bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65"),
new FMLLib("guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a",
"https://repo1.maven.org/maven2/com/google/guava/guava/14.0-rc3/guava-14.0-rc3.jar"),
new FMLLib("asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58",
"https://repo1.maven.org/maven2/org/ow2/asm/asm-all/4.1/asm-all-4.1.jar"),
new FMLLib("bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65",
"https://repo1.maven.org/maven2/org/bouncycastle/bcprov-jdk15on/1.48/bcprov-jdk15on-1.48.jar"),
new FMLLib("deobfuscation_data_1.5.2.zip", "446e55cd986582c70fcf12cb27bc00114c5adfd9"),
new FMLLib("scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85")
);
@@ -204,9 +207,9 @@ public final class GameLibrariesTask extends Task<Void> {
return null;
}
private record FMLLib(String name, String sha1) {
public String getDownloadURI() {
return "https://hmcl-dev.github.io/metadata/fmllibs/" + name;
private record FMLLib(String name, String sha1, String downloadUrl) {
FMLLib(String name, String sha1) {
this(name, sha1, "https://hmcl.glavo.site/metadata/fmllibs/" + name);
}
}
}
@@ -187,7 +187,9 @@ public abstract class FetchTask<T> extends Task<T> {
ArrayList<IOException> exceptions = null;
for (int retryTime = 0; retryTime < retry; retryTime++) {
// If loading the cache fails, the cache should not be loaded again.
boolean useCachedResult = true;
for (int retryTime = 0, retryLimit = retry; retryTime < retryLimit; retryTime++) {
if (isCancelled()) {
throw new InterruptedException();
}
@@ -204,7 +206,7 @@ public abstract class FetchTask<T> extends Task<T> {
LinkedHashMap<String, String> headers = new LinkedHashMap<>();
headers.put("accept-encoding", "gzip");
if (checkETag)
if (useCachedResult && checkETag)
headers.putAll(repository.injectConnection(uri));
do {
@@ -248,7 +250,7 @@ public abstract class FetchTask<T> extends Task<T> {
} while (true);
int responseCode = response.statusCode();
if (responseCode == HttpURLConnection.HTTP_NOT_MODIFIED) {
if (useCachedResult && responseCode == HttpURLConnection.HTTP_NOT_MODIFIED) {
// Handle cache
try {
Path cache = repository.getCachedRemoteFile(currentURI, false);
@@ -260,9 +262,10 @@ public abstract class FetchTask<T> extends Task<T> {
} catch (IOException e) {
LOG.warning("Unable to use cached file, redownload " + NetworkUtils.dropQuery(uri), e);
repository.removeRemoteEntry(currentURI);
useCachedResult = false;
// Now we must reconnect the server since 304 may result in empty content,
// if we want to redownload the file, we must reconnect the server without etag settings.
retryTime--;
retryLimit++;
continue;
}
} else if (responseCode / 100 == 4) {
@@ -1,5 +1,19 @@
{
"versions": [
{
"id": "1.21.11-pre2_unobfuscated",
"type": "unobfuscated",
"url": "https://piston-meta.mojang.com/v1/packages/2955ce0af0512fdfe53ff0740b017344acf6f397/1.21.11-pre2_unobfuscated.json",
"time": "2025-11-21T12:07:21+00:00",
"releaseTime": "2025-11-21T12:07:21+00:00"
},
{
"id": "1.21.11-pre1_unobfuscated",
"type": "unobfuscated",
"url": "https://piston-meta.mojang.com/v1/packages/9c267f8dda2728bae55201a753cdd07b584709f1/1.21.11-pre1_unobfuscated.json",
"time": "2025-11-19T08:30:46+00:00",
"releaseTime": "2025-11-19T08:30:46+00:00"
},
{
"id": "25w46a_unobfuscated",
"type": "unobfuscated",
@@ -856,4 +856,8 @@
25w45a
25w45a_unobfuscated
25w46a
25w46a_unobfuscated
25w46a_unobfuscated
1.21.11-pre1
1.21.11-pre1_unobfuscated
1.21.11-pre2
1.21.11-pre2_unobfuscated
@@ -1,4 +1,4 @@
# https://gitlab.freedesktop.org/mesa/libdrm/-/blob/7d43d9b6fe5df4b234937fce9e51adb1b327ded1/data/amdgpu.ids
# https://gitlab.freedesktop.org/mesa/libdrm/-/blob/35a21916c8f621b35a67f3c5994280ae59a4981a/data/amdgpu.ids
#
# List of AMDGPU IDs
#
@@ -559,6 +559,7 @@
7448, 00, AMD Radeon Pro W7900
7449, 00, AMD Radeon Pro W7800 48GB
744A, 00, AMD Radeon Pro W7900 Dual Slot
744B, 00, AMD Radeon Pro W7900D
744C, C8, AMD Radeon RX 7900 XTX
744C, CC, AMD Radeon RX 7900 XT
744C, CE, AMD Radeon RX 7900 GRE
@@ -569,6 +570,7 @@
7470, 00, AMD Radeon Pro W7700
747E, C8, AMD Radeon RX 7800 XT
747E, D8, AMD Radeon RX 7800M
747E, DB, AMD Radeon RX 7700
747E, FF, AMD Radeon RX 7700 XT
7480, 00, AMD Radeon Pro W7600
7480, C0, AMD Radeon RX 7600 XT
@@ -586,6 +588,7 @@
74A1, 00, AMD Instinct MI300X
74A2, 00, AMD Instinct MI308X
74A5, 00, AMD Instinct MI325X
74A8, 00, AMD Instinct MI308X HF
74A9, 00, AMD Instinct MI300X HF
74B5, 00, AMD Instinct MI300X VF
74B6, 00, AMD Instinct MI308X
@@ -594,6 +597,12 @@
7550, C2, AMD Radeon RX 9070 GRE
7550, C3, AMD Radeon RX 9070
7551, C0, AMD Radeon AI PRO R9700
7590, C0, AMD Radeon RX 9060 XT
7590, C7, AMD Radeon RX 9060
75A0, C0, AMD Instinct MI350X
75A3, C0, AMD Instinct MI355X
75B0, C0, AMD Instinct MI350X VF
75B3, C0, AMD Instinct MI355X VF
9830, 00, AMD Radeon HD 8400 / R3 Series
9831, 00, AMD Radeon HD 8400E
9832, 00, AMD Radeon HD 8330
@@ -689,4 +698,4 @@
98E4, E9, AMD Radeon R4 Graphics
98E4, EA, AMD Radeon R4 Graphics
98E4, EB, AMD Radeon R3 Graphics
98E4, EB, AMD Radeon R4 Graphics
98E4, EB, AMD Radeon R4 Graphics