22 Commits
Author SHA1 Message Date
Glavo 3164a93414 Add 3.17.0.357 changelog (#497) 2026-09-20 22:06:33 +08:00
Jingyu LiuandZkitefly d81793250a 更新了首页内容。 (#495)
Co-authored-by: Zkitefly <zkitefly@foxmail.com>
2026-09-18 11:53:52 +08:00
Glavo b720c78692 Add changelogs for versions 3.16.4 and 3.17.0.356 (#496) 2026-09-17 21:12:58 +08:00
Glavo 1a97f19d9e Add 3.17.0.355 changelog (#494)
continuous-integration/drone/push Build is passing
2026-09-06 20:03:55 +08:00
Jingyu Liu 1665129a05 更新了关于近期发现的多人联机问题。 (#493)
continuous-integration/drone/push Build is passing
2026-09-06 18:13:21 +08:00
neveler bb8bc0c862 PR 预览构建时不再启用 webp 依赖 (#489)
continuous-integration/drone/push Build is passing
2026-08-15 20:49:32 +08:00
neveler 9d0091ad5e 优化 HMCL 文件校验页面 (#488) 2026-08-15 20:44:58 +08:00
Glavo 8c9f18ba9c Add 3.17.0.354 changelog (#487)
continuous-integration/drone/push Build is passing
2026-08-13 20:27:50 +08:00
Glavo 36efcfc1c1 Add 3.17.0.353 changelog (#486)
continuous-integration/drone/push Build is passing
2026-08-02 19:26:40 +08:00
Glavo 2b8fb9709b Add 3.17.0.353 changelog (#485)
continuous-integration/drone/push Build is passing
2026-07-28 21:04:05 +08:00
Glavo cf33394353 Add 3.16.3 changelog (#484)
continuous-integration/drone/push Build is passing
2026-07-25 22:12:48 +08:00
neveler 03bacac889 update screenshot (#483)
continuous-integration/drone/push Build is passing
2026-07-25 19:22:34 +08:00
Glavo 8bb1cc0a2d Add 3.17.0.351 changelog (#482)
continuous-integration/drone/push Build is passing
2026-07-18 21:02:20 +08:00
Glavo 350274a91f Add 3.16.2 changelog (#481)
continuous-integration/drone/push Build is passing
2026-07-15 22:03:52 +08:00
Glavo d5afe3a337 Add 3.17.0.350 changlog (#480)
continuous-integration/drone/push Build is passing
2026-07-14 20:44:57 +08:00
Glavo 7a8998e1bf Add 3.16.1 changelog (#479)
continuous-integration/drone/push Build is passing
2026-07-13 21:49:20 +08:00
Glavo c47cea9a04 Update Bilibili link in 3.15.3 changelog (#478)
continuous-integration/drone/push Build is passing
2026-07-10 21:59:50 +08:00
Glavo fb83fad8d9 Add 3.15.3 changelog (#477) 2026-07-10 21:58:33 +08:00
Glavo 41199fa1d5 添加“验证 HMCL 文件”页面 (#476)
continuous-integration/drone/push Build is passing
2026-07-08 21:57:40 +08:00
Glavo 8442d41998 Add 3.16.0.347 and 3.16.0.348 changelog (#475)
continuous-integration/drone/push Build is passing
2026-07-05 21:22:38 +08:00
TyMxy 506ead891d 修正内容 (#473)
continuous-integration/drone/push Build is passing
2026-06-26 22:16:57 +08:00
neveler 1f08ed13ef 移除静态资源中的重复图片 (#471) 2026-06-26 22:16:14 +08:00
52 changed files with 1084 additions and 28 deletions
-1
View File
@@ -11,7 +11,6 @@ concurrency:
cancel-in-progress: false cancel-in-progress: false
env: env:
JEKYLL_ENV: production JEKYLL_ENV: production
ENABLE_WEBP_AUTO_CONVERSION: "true"
GITHUB_PR_NUMBER: ${{ github.event_name == 'issue_comment' && github.event.issue.number || github.event.pull_request.number }} GITHUB_PR_NUMBER: ${{ github.event_name == 'issue_comment' && github.event.issue.number || github.event.pull_request.number }}
jobs: jobs:
cache-refresh: cache-refresh:
+52
View File
@@ -0,0 +1,52 @@
---
---
[详细版本介绍 (Bilibili)](https://www.bilibili.com/opus/1219755787108220949)
- GP-6122: 重构启动器配置模型 (by Glavo)
- GP-6229: 重构主题系统 (by Glavo)
- GP-6186: 为版本列表设置固定列表项高度 (by 快乐凤爪王)
- GP-6188: 完善乌克兰语翻译 (by Shadow)
- GP-6204: 优化外置登录账号名称展示 (by 辞庐)
- GP-6196: 统一“使用非官方构建时的提示”的用词 (by 辞庐)
- GP-6169: CurseForge 下载文件时也使用 API Key (by Calboot)
- GP-6168: 更新 `versions.txt` 至 26.2 (by 3gf8jv4dv)
- GP-6095: 在非主界面或已有对话框显示时暂缓弹出启动器更新对话框 (by Calboot)
- GP-6101: 支持置顶日志窗口 (by 辞庐)
- GP-6176: 整理 Addon 相关类和翻译 (by Calboot, 3gf8jv4dv)
- GP-6217: 补全 `.gitignore` (by 快乐凤爪王)
- GP-6219: 使用 HttpURLConnection 替换 HttpClient 实现 (by Glavo)
- GP-6250: 更新“关于 -> 依赖”列表 (by 辞庐)
- GP-6265: 更新 Chunkbase 种子地图 (by Wulian233)
- GP-6214: 修正默认游戏内容下载源的翻译键 (by 快乐凤爪王)
- GP-6267: 翻译模组分类的 Cursed 类别 (by Wulian233)
- GP-6270: 优化主题包管理页面列表项 (by 辞庐)
- GP-6273: 重构游戏目录管理逻辑 (by Glavo)
- GP-6274: 为主题包信息对话框添加水波纹效果 (by 快乐凤爪王)
- GP-6271: 主题包管理界面支持拖拽导入 (by 辞庐)
- GP-6231: 重构离线账户换肤对话框 (by 快乐凤爪王)
- GP-6207: 下载界面的依赖列表采用按项目 slug 排序 (by Calboot)
- GP-6258: 为预设创建和重命名添加名称重复校验 (by 快乐凤爪王)
- GP-6266: 对下载线程数输入框添加校验 (by Wulian233)
- GP-6115: 优化导出整合包时的文件选择 (by Calboot, Glavo)
错误修复:
- GP-6160: 修复无法为 MC 1.21.11 安装 Forge 的问题 (by Glavo)
- GP-6171: 修复 `versions.txt` 中 26w14a 的位置 (by 3gf8jv4dv)
- GP-6183: 修复多语言资源缺失、占位符错误与本地构建依赖路径问题 (by Shadow)
- GP-6170: 修复无法下载 SHA-1 为空字符串的文件的问题 (by Glavo)
- GP-6211: 修复游戏下载列表的对齐问题 (by 快乐凤爪王)
- GP-6155: 修复实例下载页面的布局时序问题 (by SaltWood_233, 辞庐)
- GP-6227: 修复陶瓦联机页面图标对齐问题 (by 快乐凤爪王)
- GP-6226: 修复模组文件名不能包含感叹号的问题 (by Calboot)
- GP-6256: 修复 Java 管理页面点击列表项时 Tag 闪烁的问题 (by 庐庐绫)
- GP-6263: 修复图片容器底部间距过大的问题 (by 快乐凤爪王)
- GP-6264: 修复版本页面 Tag 消失的问题 (by 快乐凤爪王)
- GP-6257: 修复已弃用 JVM 内存设置的内存单位对齐问题 (by 快乐凤爪王)
- GP-6262: 修复 toast 消息未居中的问题 (by 快乐凤爪王)
- GP-6249: 修复 Java 管理无法安装部分 Java 的问题 (by 辞庐, Glavo)
- GP-6244: 修复在实例列表加载完成前切换实例文件夹导致的空指针问题 (by NoClassDefFoundError)
- GP-6240: 修复 `mmc-bootstrap` 已存在时仍被覆盖的问题 (by Burning_TNT)
- GP-6109: 修复陶瓦联机界面账号快速切换列表右侧滚动条错位以及列表莫名抽搐的问题 (by 辞庐, Glavo)
- GP-6185: 修复 Curse 整合包更新后未移除旧的模组 (by Zkitefly)
+30
View File
@@ -0,0 +1,30 @@
---
---
[详细版本介绍 (Bilibili)](https://www.bilibili.com/opus/1221569517396688935)
- GP-6277: 将更多类转换为 record (by Calboot)
- GP-6284: 导出主题时支持设置主题版本 (by Wulian233)
- GP-6292: 不再将从旧版本游戏文件夹设置中迁移出的游戏预设名称设置为文件夹名称 (by Glavo)
- GP-6105: 始终显示关闭愚人节模式的按钮 (by Calboot)
- GP-6287: 调整旧版实例设置迁移与默认父预设解析逻辑 (by Glavo)
- GP-6253: 支持读取 Forge 新模组元数据中的 logo 文件 (by Zkitefly)
- GP-6298: 调整预设管理相关术语 (by Glavo)
- GP-6310: 禁用密码框右键菜单中的“剪切”和“复制”按钮 (by 辞庐)
- GP-6300: 根据游戏版本控制图形后端选项显示 (by Glavo)
- GP-6314: 为游戏退出日志行添加时间戳 (by 辞庐)
- GP-6316: 根据游戏版本优化渲染器选择 (by Glavo)
- GP-6278: 优化 `default_addon_source` 的中文翻译 (by Calboot)
- GP-6235: 同步本地化 README 内容 (by Haoran Xu)
错误修复:
- GP-6285: 修复颜色选择器与文本框高度不一致的问题 (by 快乐凤爪王)
- GP-6288: 修复版本列表固定列表项高度可能失效的问题 (by 快乐凤爪王)
- GP-6260: 修复 JVM 内存输入框允许输入非数字字符的问题 (by 快乐凤爪王)
- GP-6248: 修复安装手动打包整合包时任务名未本地化的问题 (by 辞庐)
- GP-6297: 修复 CurseForge 文件下载未带有 API Key 的问题 (by Calboot, Glavo)
- GP-6315: 修复复制 UUID 按钮显示冗余 `SpinnerPane` 的问题 (by 辞庐)
- GP-6302: 修复账户列表项间距问题 (by 快乐凤爪王)
- GP-6301: 修复 `authlib-injector` 警告文本被截断的问题 (by 快乐凤爪王)
- GP-6247: 修复联机核心第三方下载渠道按钮高度不一致的问题 (by 庐庐绫)
+43
View File
@@ -0,0 +1,43 @@
---
---
[详细版本介绍 (Bilibili)](https://www.bilibili.com/opus/1224900509377232921)
- GP-6387: 使用 Gradle Wrapper Neo 代替 Gradle Wrapper (by Glavo)
- GP-6388: 更新 Gradle 至 9.6.1 (by Glavo)
- GP-6390: 更新 authlib-injector 至 1.2.8 (by 辞庐)
- GP-6341: 重构启动按钮 (by 快乐凤爪王)
- GP-6330: 优化内存分配选项与预设管理 (by Glavo)
- GP-6334: 为 Java 运行时列表项添加带编号的方形标签 (by 快乐凤爪王)
- GP-6313: 优化日志窗口配色 (by 辞庐)
- GP-6346: 移除 `allow_auto_agent.subtitle` 中不必要的标点 (by 快乐凤爪王)
- GP-6312: 为 `HttpRequest` 添加 `PUT` 与 `DELETE` 请求支持 (by 辞庐)
- GP-6344: 菜单按钮弹出时逆时针旋转箭头 (by 快乐凤爪王)
- GP-6366: 在滚动条处于按下状态时保持不透明 (by Glavo)
- GP-6368: 在模组下载列表中添加“未找到结果”提示 (by 快乐凤爪王)
- GP-6370: 移除模组下载列表页面中冗余的下载源下拉框 (by 快乐凤爪王)
- GP-6374: 优化下载线程数设置界面 (by Glavo)
- GP-6377: 优化整合包 Java 包类型名称显示 (by 快乐凤爪王)
- GP-6251: 更新 `fatal.unsupported_platform` 设置指引 (by 辞庐, 3gf8jv4dv)
- GP-6382: 固定默认游戏文件夹和官方启动器游戏文件夹的 ID (by Glavo)
- GP-6335: 优化安装器项目不兼容时的状态标签透明度 (by 快乐凤爪王)
- GP-6383: 添加“窗口透明”选项 (by Glavo)
- GP-6385: 支持主题色跟随系统 (by Glavo)
错误修复:
- GP-6339: 修复世界列表项标签显示问题 (by 快乐凤爪王)
- GP-6340: 修复 macOS 导出整合包的默认名称包含两个后缀名的问题 (by Calboot)
- GP-6333: 修复 MCIM 描述未对齐的问题 (by 辞庐)
- GP-6337: 修复游戏列表项间距问题 (by 快乐凤爪王)
- GP-6325: 修复实例高级列表项在游戏仓库加载完成前加载图标的问题 (by Glavo)
- GP-6329: 修复远程版本列表项复用时副标题未恢复的问题 (by 快乐凤爪王)
- GP-6347: 修复模组和资源包信息列表项的图标尺寸问题 (by 快乐凤爪王)
- GP-6356: 修复自动分配内存逻辑异常的问题 (by Glavo)
- GP-6355: 修复安装新实例时 Fabric API 安装路径未遵循版本隔离策略的问题 (by Glavo)
- GP-6365: 修复在 `JFXComboBox` 弹出窗口的滚动条上释放鼠标时窗口隐藏的问题 (by Glavo)
- GP-6373: 修复 `JFXPasswordField` 导致 CPU 占用率异常增高的问题 (by Glavo)
- GP-6371: 修复整合包安装界面高度限制失效的问题 (by 辞庐)
- GP-6369: 修复账户列表项刷新按钮宽度变化导致布局偏移的问题 (by 快乐凤爪王)
- GP-6386: 修复 Minecraft 26.1+ 无法安装 Quilt 的问题 (by Glavo)
+21
View File
@@ -0,0 +1,21 @@
---
---
[详细版本介绍 (Bilibili)](https://www.bilibili.com/opus/1226389999698575383)
- GP-6405: 处理升级至 Gradle 9.6.1 后的弃用警告 (by Calboot)
- GP-6415: 完善游戏设置页面帮助文本 (by Glavo)
- GP-6409: 使用 WebURL for Java 替代已弃用的 `URL` 构造函数 (by 快乐凤爪王)
- GP-6420: 提前加载配置文件 (by Glavo)
- GP-6381: 添加 PR 大小标签工作流 (by 3gf8jv4dv)
- GP-6425: 在非官方支持的平台上支持 Minecraft 26.3-snapshot-4+ (by Glavo)
- GP-6427: 支持拖入 `.nbt` 文件 (by 辞庐)
- GP-6423: 优化模组信息对话框样式 (by 快乐凤爪王)
- GP-6429: 更新内置主题相关译文 (by Glavo)
错误修复:
- GP-6404: 修复在 Minecraft 1.21.1 中安装信雅互联后仍显示不支持 Fabric 模组的问题 (by Calboot)
- GP-6410: 修复游戏内容下载页面中的下载源下拉框消失的问题 (by 辞庐)
- GP-6419: 修复游戏 Java 路径显示滞后的问题 (by Apostrophe)
- GP-6140: 修复任务窗口中速度文本与取消按钮未对齐的问题 (by 辞庐)
+44
View File
@@ -0,0 +1,44 @@
---
---
[详细版本介绍 (Bilibili)](https://www.bilibili.com/opus/1230100722593300480)
- GP-6424: 为游戏日志窗口添加自动换行开关 (by ZZZank)
- GP-6426: 为实例内容列表添加空状态和“搜索无结果”提示 (by 快乐凤爪王)
- GP-6431: 避免在代码中直接引用 `Controllers.getStage()` (by Glavo)
- GP-6462: 移除繁体中文本地化文件中的多余空格 (by neveler)
- GP-6463: 将 FreeBSD x86-64 平台的 JavaFX 更新至 21.0.11 (by Glavo)
- GP-6466: 更新多种语言翻译 (by neveler)
- GP-6467: 移除对 JavaFX 14 的兼容代码 (by Glavo)
- GP-6456: 在更新时启动新进程的日志中隐藏敏感命令行参数 (by 辞庐)
- GP-6451: 为主题包管理页面添加“搜索无结果”提示 (by 快乐凤爪王)
- GP-6449: 复用统一的“搜索无结果”译文并清理重复条目 (by 快乐凤爪王)
- GP-6435: 为游戏目录列表添加随选中状态变化的文件夹图标 (by 快乐凤爪王)
- GP-6349: 优化新建游戏页面的实例名称输入框并添加清空、重置按钮 (by 快乐凤爪王)
- GP-6474: 移除未使用的 `VanillaInstallWizardProvider` (by 辞庐)
- GP-6472: 移除已废弃的 `game.crash.reason.mod_repeat_installation` 译文 (by neveler)
- GP-6458: 将 PR 大小标签工作流中的 JavaScript 代码提取到独立文件 (by neveler)
- GP-6481: 在非官方支持的平台上支持 Minecraft 26.3-snapshot-5+ (by Glavo)
- GP-6492: 复制实例时同步保存游戏设置 (by Glavo)
- GP-6491: 更新 Modrinth 资源包分辨率分类的多语言译文 (by neveler)
- GP-6493: 将“新建游戏”和“导入整合包”按钮移至实例列表工具栏 (by 辞庐)
- GP-6500: 移除模组管理页面中冗余的“实例无模组加载器”提示 (by 辞庐)
- GP-6477: 使用 `kala-encoding-detector` 改进文本编码检测 (by Glavo)
- GP-6494: 让空实例列表提示直接打开新建游戏页面 (by 辞庐)
- GP-6515: 优化模组信息读取速度 (by Glavo)
- GP-6516: 为主题包导出对话框预填名称、版本和作者 (by Calboot)
- GP-6422: 在 Windows 高刷新率屏幕上自动提高动画帧率 (by Glavo)
错误修复:
- GP-6434: 修复 Modrinth 资源的 Legacy Fabric 加载器类型未被识别的问题 (by 快乐凤爪王)
- GP-6446: 修复整合包安装完成回调使用的执行器不一致的问题 (by 辞庐)
- GP-6450: 修复背景不透明度百分比标签未居中对齐的问题 (by 快乐凤爪王)
- GP-6468: 修复切换版本隔离设置后其他子页面未自动刷新的问题 (by 辞庐)
- GP-6457: 修复 `NetworkUtils#doPost(URI, Map)` 未对表单参数进行 URL 编码的问题 (by 辞庐)
- GP-6478: 修复切换实例时模组列表可能检查错误实例更新的问题 (by 庐庐绫)
- GP-6445: 修复 `GameAdvancedListItem#loadVersion` 的 UI 操作可能未在 JavaFX 线程上运行的问题 (by 辞庐)
- GP-6498: 修复 `TabControl` 中对 `Tab<?>` 的原始类型使用 (by 辞庐)
- GP-6487: 修复下载整合包时任务名称未设置的问题 (by 辞庐)
- GP-6351: 修复资源包管理读写非 UTF-8 编码的 `options.txt` 文件出错的问题 (by Calboot, Glavo)
- GP-6525: 修复游戏结束后重新显示启动器时窗口仍处于最小化状态的问题 (by 庐庐绫)
+29
View File
@@ -0,0 +1,29 @@
---
---
[详细版本介绍 (Bilibili)](https://www.bilibili.com/opus/1231931439530901506)
- GP-6543: 更新模组数据(2026-07-21) (by Glavo)
- GP-6561: 将 HelloNBT 更新至 0.4.0 (by Glavo)
- GP-6562: 将 Gson 更新至 2.14.0 (by Glavo)
- GP-6322: 不再使用 `Version` 表示游戏实例 (by Glavo)
- GP-6499: 统一管理页面工具栏中的“下载”按钮文案 (by 辞庐, Glavo)
- GP-6495: 为实例列表左侧的游戏文件夹列表添加平滑滚动 (by 辞庐, Glavo)
- GP-6550: 优化整合包选择页面关闭文件选择器后的导航行为 (by 快乐凤爪王)
- GP-6542: 在 Windows 平台上支持将 HMCL 固定到任务栏 (by Glavo)
- GP-6545: 清理 `CurseManifestMinecraft` (by 辞庐)
- GP-6441: 为下载页面的附加组件渠道图标添加颜色 (by 快乐凤爪王)
- GP-6535: 补全从 `mod` 到 `addon` 的重命名 (by Calboot)
- GP-6345: 优化 Java 管理页面样式 (by 快乐凤爪王)
- GP-6566: 为游戏列表添加“搜索无结果”提示 (by 快乐凤爪王)
- GP-5420: 支持 Windows 高性能模式设置 (by 辞庐)
- GP-6557: 重构 `Decorator` (by Glavo)
错误修复:
- GP-6303: 修复 Linux 桌面环境的程序坞或任务栏中缺少 HMCL 图标的问题 (by Mike Lei)
- GP-6363: 修复导出整合包时文件选择界面阻塞 UI 线程的问题 (by Calboot)
- GP-6547: 修复重启后非当前背景图片选项的配置丢失的问题 (by 庐庐绫)
- GP-6551: 修复整合包选择页面遇到非 `IOException` 异常时崩溃的问题 (by 快乐凤爪王)
- GP-6564: 修复模组下载列表末尾项的内边距问题 (by 快乐凤爪王)
- GP-6563: 修复已禁用 Java 项目的标签仍会响应鼠标事件的问题 (by 快乐凤爪王)
+26
View File
@@ -0,0 +1,26 @@
---
---
[详细版本介绍 (Bilibili)](https://www.bilibili.com/opus/1235313039077539877)
- GP-6560: 在 I/O 线程上清理下载缓存 (by ToobLac)
- GP-6536: 优化附加内容类型推断逻辑 (by ToobLac)
- GP-6581: 关闭动画时跳过侧边栏图标过渡动画 (by 辞庐, Glavo)
- GP-6604: 同步 Modrinth 官方“Modded”分类的简体中文翻译 (by 快乐凤爪王)
- GP-6583: 禁用动画时禁用 JFXCheckbox 过渡动画 (by 辞庐)
- GP-6098: 支持查看模组等游戏内容的更新日志并完善 HTML 渲染器 (by ToobLac, Calboot, CalbootOnceMore, CiiLu)
- GP-6613: 改进图像类型探测功能 (by Glavo)
- GP-6620: 让模组和资源包信息对话框中的 CurseForge、Modrinth 链接跳转至对应网页 (by ToobLac)
- GP-6617: 优化 HTML 内容的间距 (by ToobLac)
- GP-6641: 优化 32 位平台自动分配内存策略 (by Glavo)
错误修复:
- GP-6590: 修复附加内容版本列表中的推荐条目标题均显示为“模组”的问题 (by 3gf8jv4dv)
- GP-6584: 修复无法正确安装 MultiMC 整合包的问题 (by Burning_TNT)
- GP-6593: 修复取消更新整合包时可能删除原整合包的问题 (by bluebullet)
- GP-6592: 修复实例“版本隔离”选项的说明存在歧义的问题 (by 3gf8jv4dv)
- GP-6630: 修复导出包含大量文件的 MCBBS 整合包时可能内存不足的问题 (by Apostrophe)
- GP-6633: 修复再次点击实例菜单按钮时菜单重新弹出的问题 (by Glavo)
- GP-6636: 修复异步任务内存不足后界面假死且无错误提示的问题 (by Apostrophe)
- GP-6649: 修复导出日志文件时文件为空的问题 (by Glavo)
+67
View File
@@ -0,0 +1,67 @@
---
---
[详细版本介绍 (Bilibili)](https://www.bilibili.com/opus/1244928526007664646)
- GP-6790: 将 fxsvgimage 更新至 1.9.1 (by Glavo)
- GP-6792: 将 jsoup 更新至 1.23.2 (by Glavo)
- GP-6794: 将 JUnit 更新至 6.1.3 (by Glavo)
- GP-6793: 将 commonmark 更新至 0.30.0 (by Glavo)
- GP-6809: 将 kala-compress 更新至 1.27.1-4 (by Glavo)
- GP-6670: 支持在 Linux 双显卡平台上优先使用 NVIDIA 显卡 (by Glavo)
- GP-6675: 完善乌克兰语翻译 (by BANER)
- GP-6658: 移除“操作被取消”提示 (by 辞庐)
- GP-6664: 优化投影管理中文件夹已存在时的提示 (by 辞庐, Glavo)
- GP-6677: 完善德语翻译 (by BANER)
- GP-6705: 优化无验证服务器提示 (by 辞庐)
- GP-6580: 重构 `GameRepository` (by Glavo)
- GP-6692: 将 Checkstyle 报告同步至 Pull Request 审查评论 (by neveler)
- GP-6465: 将 `ModpackHelper#findMinecraftDirectoryInManuallyCreatedModpack` 迁移至 `kala-compress` (by 辞庐)
- GP-6715: 主动修剪堆内存 (by Glavo)
- GP-6731: 优先按照游戏版本排序实例 (by Calboot)
- GP-6732: 清理游戏实例时删除版本目录根部的所有日志文件 (by Calboot)
- GP-6696: 支持使用系统 SDL (by 辞庐)
- GP-6704: 优化验证服务器选择样式 (by 辞庐, Glavo)
- GP-6771: 优化 `LineSelectButton` 弹出菜单的副标题配色 (by 辞庐)
- GP-6775: 点击主页“下载”按钮时保留先前打开的页面 (by 辞庐)
- GP-6767: 优化微软登录扫描二维码界面布局 (by 辞庐)
- GP-6763: 清理 `PropertyUtils` (by 辞庐)
- GP-6778: 优化修改实例游戏版本页面的标题 (by 辞庐)
- GP-6762: 使用相同逻辑提取验证服务器的展示域名 (by 辞庐)
- GP-6758: 更新 `launch.advice.lwjgl_3_4_1` 文案 (by 辞庐)
- GP-6787: 重构游戏管理功能 (by Glavo)
- GP-6729: 将 `ModListPageSkin` 移至 `ModListPage` 内部 (by Calboot)
- GP-6203: 在选择磁盘根目录作为游戏目录时弹出警告 (by 辞庐)
- GP-6197: 简化 `DefaultLauncher#getEnvVars` (by 辞庐, Glavo)
- GP-6811: 让 `OAuthServer` 仅监听 `localhost` (by 辞庐)
错误修复:
- GP-6653: 修复 `.gitignore` 缺少 `hmcl-mod-update-list-*` 的问题 (by 辞庐)
- GP-6586: 修复列表中的涟漪状态不更新的问题 (by Calboot)
- GP-6676: 修复在 Linux 平台上错误地将 Intel 核显探测为独立显卡的问题 (by Glavo)
- GP-6656: 修复 macOS 上打开对话框后按 Command+Q 无法退出的问题 (by Calboot)
- GP-6643: 修复 Cleanroom 和 LiteLoader 实例不读取子文件夹中模组的问题 (by Calboot)
- GP-6631: 修复导出包含大型文件的 Modrinth 整合包时可能内存不足的问题 (by Apostrophe, Glavo)
- GP-6671: 修复 Modrinth 分类的中英文翻译与上游不一致的问题 (by 3gf8jv4dv)
- GP-6695: 修复 Modrinth 分类的西里尔字母语言翻译与上游不一致的问题 (by 3gf8jv4dv)
- GP-6712: 修复无法读取以 `.zip` 为扩展名的模组的问题 (by Calboot)
- GP-6496: 修复可通过本地安装同时安装 Cleanroom 与 Forge 的问题 (by 辞庐)
- GP-6716: 修复使用相对路径的 `DefaultGameRepository` 无法安装实例的问题 (by Glavo)
- GP-6718: 修复安装新实例时未将 patch 合并到主 manifest 中的问题 (by Glavo)
- GP-6736: 修复 KDE Wayland 下 HMCL 不跟随系统缩放的问题 (by olivezane, Glavo)
- GP-6753: 修复选择组件版本页面标题异常的问题 (by 辞庐)
- GP-6757: 修复更换游戏组件版本对话框消息文本异常的问题 (by 辞庐)
- GP-6784: 修复 Legacy Fabric 实例图标异常的问题 (by 辞庐)
- GP-6779: 修复全局实例设置页面可能缺少“Vulkan 渲染器/驱动”选项的问题 (by 辞庐)
- GP-6777: 修复更改模组加载器版本时下载依赖项任务未正确归类的问题 (by 辞庐)
- GP-6789: 修复缩放 SVG 图片时会加载 `JFXPanel` 类的问题 (by Glavo)
- GP-6764: 修复初次进入新增游戏目录页面时不会自动填充 `.minecraft` 上级目录名称的问题 (by 辞庐)
- GP-6774: 修复实例列表中新快照图标错误的问题 (by 辞庐)
- GP-6709: 修复列表首次点击时不显示涟漪以及滚动时仍保持涟漪的问题 (by Calboot)
- GP-6805: 修复 `GameDirectoryPage` 缺少 `MessageDialogPane` 导入语句的问题 (by 陈梦泽)
- GP-6746: 修复自动安装页面重复显示已安装项目的问题 (by 辞庐)
- GP-6807: 修复 Minecraft 1.4.7 安装 Legacy Fabric 后无法正常启动的问题 (by Glavo)
- GP-6808: 修复 Java 列表无法刷新版本信息的问题 (by Wulian233)
- GP-6532: 修复下载附加内容时依赖列表因文件缺失而加载失败以及类别标题未居中的问题 (by Calboot)
- GP-6812: 修复通过不同方式打开的游戏选择弹出菜单文字大小不一致的问题 (by 辞庐)
+39
View File
@@ -0,0 +1,39 @@
---
---
[详细版本介绍 (Bilibili)](https://www.bilibili.com/opus/1247918016512917523)
- GP-6837: 将 kala-compress 更新至 1.27.1-5 (by Glavo)
- GP-4017: 不再支持导出 MultiMC 整合包 (by Burning_TNT)
- GP-6826: 将部分文案中的 Hello Minecraft! Launcher 简写为 HMCL (by 辞庐)
- GP-6834: 打开 ZIP 文件时忽略本地文件头 (by Glavo)
- GP-6838: 优化 `ArchiveFileTree` 构建性能 (by Glavo)
- GP-6836: 完善游戏安装任务取消或失败后的资源清理 (by Glavo)
- GP-6816: 优化实例图标设置操作按钮 (by 辞庐)
- GP-6840: 将整合包文件选择控件移至可复用的树单元格中 (by Glavo)
- GP-6475: 在修改游戏版本时清除已选的模组加载器 (by 辞庐)
- GP-6730: 延后加载并缓存资源包图标 (by Calboot)
- GP-6595: 为 CurseForge 请求添加失败重试,并完善整合包模组下载的完整性校验与缓存复用 (by bluebullet, Glavo)
- GP-6286: 启动器检查更新失败时显示提示 (by Calboot)
- GP-6038: 支持在实例列表中右键编辑游戏目录 (by NWMA-FYWF, Glavo)
- GP-6813: 支持在 macOS 上通过 Command+W 关闭游戏崩溃、HMCL 崩溃窗口,以及游戏结束后的日志窗口 (by Calboot)
- GP-6853: 为简体中文资源使用 `zh-Hans` 语言标签 (by Glavo)
- GP-6849: 添加 Minecraft 26.3 快照版和候选发布版的版本信息 (by Glavo)
- GP-6857: 重构本地库检测逻辑 (by Glavo)
错误修复:
- GP-6830: 修复导出包含已禁用模组的 Modrinth 整合包时出错的问题 (by Xirren)
- GP-6824: 修复无法启动新版本 Cleanroom 的问题 (by 辞庐)
- GP-6823: 修复实例管理工具栏文字变小的问题 (by Wulian233)
- GP-6832: 修复父实例缺失的实例仍显示在实例列表中的问题 (by Glavo)
- GP-6839: 修复无法启动安装了 Forge 的 Minecraft 1.6.4 实例的问题 (by Glavo)
- GP-6436: 修复名称过长的模组显示异常的问题 (by ZZZank)
- GP-6289: 修复模组版本页面不显示未受支持的模组加载器标签的问题 (by Calboot, Glavo)
- GP-6619: 修复 CurseForge 搜索结果排序不合理的问题,并移除无实际意义的搜索排序方式 (by Calboot)
- GP-6555: 修复 macOS 上主题模式无法跟随系统设置的问题 (by Calboot)
- GP-6843: 修复更新游戏实例时未同步客户端 JAR 文件的问题 (by Glavo)
- GP-6209: 修复 Yggdrasil 账户后续登录时未重新验证访问令牌的问题 (by lcxn123)
- GP-6854: 修复右键部分选项时游戏选择弹出菜单重复叠加的问题 (by Wulian233)
- GP-6844: 修复带标签列表项的宽度计算错误的问题 (by Glavo)
+16
View File
@@ -0,0 +1,16 @@
---
---
[详细版本介绍 (Bilibili)](https://www.bilibili.com/opus/1250156214145253401)
- GP-1771: 支持在安装整合包时选择可选文件 (by CaveNightingale)
- GP-6859: 完善俄语翻译 (by Ivan Epikhin)
- GP-6870: 支持在非官方支持的平台上启动 Minecraft 26.3-snapshot-10 及更新版本 (by Glavo)
- GP-6877: 添加 Minecraft 26.3-rc-3 的版本信息 (by Glavo)
- GP-6094: 优化原理图管理,新增支持 `.schematic`、`.schem` 和 `.nbt` 文件 (by Calboot, 3gf8jv4dv)
错误修复:
- GP-6866: 修复编辑游戏目录时不修改名称就无法保存的问题 (by Apostrophe)
- GP-6886: 在 Cleanroom 环境中移除 `icu4j-core-mojang` 依赖 (by 辞庐)
+9
View File
@@ -0,0 +1,9 @@
---
---
[详细版本介绍 (Bilibili)](https://www.bilibili.com/opus/1223435654904414214)
**下载**
- GP-6364: 从 CurseForge 下载文件时传递 API Key (by Glavo, ToobLac)
+117
View File
@@ -0,0 +1,117 @@
---
---
[详细版本介绍 (Bilibili)](https://www.bilibili.com/opus/1224535325471146002)
**启动器**
- GP-6122: 重构启动器配置模型 (by Glavo)
- GP-6095: 在非主界面或已有对话框显示时暂缓弹出启动器更新对话框 (by Calboot)
- GP-6101: 支持置顶日志窗口 (by 辞庐)
- GP-6250: 更新"关于 -> 依赖"列表 (by 辞庐)
- GP-6105: 始终显示关闭愚人节模式的按钮 (by Calboot)
- GP-6314: 为游戏退出日志行添加时间戳 (by 辞庐)
- GP-6334: 为 Java 运行时列表项添加带编号的方形标签 (by 快乐凤爪王)
**实例管理**
- GP-6273: 重构游戏目录管理逻辑 (by Glavo)
- GP-6258: 为预设创建和重命名添加名称重复校验 (by 快乐凤爪王)
**世界管理**
- GP-6265: 更新 Chunkbase 种子地图 (by Wulian233)
**账户**
- GP-6204: 优化外置登录账户名称展示 (by 辞庐)
- GP-6231: 重构离线账户换肤对话框 (by 快乐凤爪王)
- GP-6390: 修复外置账户对 Minecraft 26.3 不生效的问题 (by 辞庐)
**整合包**
- GP-6115: 优化导出整合包时的文件选择 (by Calboot, Glavo)
- GP-6377: 优化整合包 Java 包类型名称显示 (by 快乐凤爪王)
**外观**
- GP-6229: 重构主题系统 (by Glavo)
- GP-6270: 优化主题包管理页面列表项 (by 辞庐)
- GP-6274: 为主题包信息对话框添加水波纹效果 (by 快乐凤爪王)
- GP-6271: 主题包管理界面支持拖拽导入 (by 辞庐)
- GP-6284: 导出主题时支持设置主题版本 (by Wulian233)
- GP-6341: 优化启动按钮样式 (by 快乐凤爪王)
- GP-6313: 优化日志窗口配色 (by 辞庐)
- GP-6344: 菜单按钮弹出时逆时针旋转箭头 (by 快乐凤爪王)
- GP-6366: 在滚动条处于按下状态时保持不透明 (by Glavo)
- GP-6335: 优化安装器项目不兼容时的状态标签透明度 (by 快乐凤爪王)
- GP-6383: 添加"窗口透明"选项 (by Glavo)
- GP-6385: 支持主题色跟随系统 (by Glavo)
**下载**
- GP-6186: 为版本列表设置固定列表项高度 (by 快乐凤爪王)
- GP-6266: 对下载线程数输入框添加校验 (by Wulian233)
- GP-6253: 支持读取 Forge 新模组元数据中的 logo 文件 (by Zkitefly)
- GP-6207: 下载界面的依赖列表按项目 slug 排序 (by Calboot)
- GP-6368: 在模组下载列表中添加"未找到结果"提示 (by 快乐凤爪王)
- GP-6370: 移除模组下载列表页面中冗余的下载源下拉框 (by 快乐凤爪王)
**本地化**
- GP-6176: 整理 Addon 相关类和翻译 (by Calboot, 3gf8jv4dv)
- GP-6188: 完善乌克兰语翻译 (by Shadow)
- GP-6196: 统一"使用非官方构建时的提示"的用词 (by 辞庐)
- GP-6251: 更新 `fatal.unsupported_platform` 设置指引 (by 辞庐, 3gf8jv4dv)
- GP-6252: 清理过期 i18n 键值 (by 辞庐)
- GP-6259: 移除 `java_permanent_generation_space.prompt` (by 快乐凤爪王)
- GP-6214: 修正默认游戏内容下载源的翻译键 (by 快乐凤爪王)
- GP-6267: 翻译模组分类的 Cursed 类别 (by Wulian233)
- GP-6278: 优化 `default_addon_source` 的中文翻译 (by Calboot)
- GP-6346: 移除 `allow_auto_agent.subtitle` 中不必要的标点 (by 快乐凤爪王)
- GP-6235: 同步本地化 README 内容 (by Haoran Xu)
**错误修复**
- GP-6171: 修复 `versions.txt` 中 26w14a 的位置 (by 3gf8jv4dv)
- GP-6183: 修复多语言资源缺失、占位符错误与本地构建依赖路径问题 (by Shadow)
- GP-6170: 修复无法下载 SHA-1 为空字符串的文件的问题 (by Glavo)
- GP-6211: 修复游戏下载列表的对齐问题 (by 快乐凤爪王)
- GP-6155: 修复实例下载页面的布局时序问题 (by SaltWood_233, 辞庐)
- GP-6227: 修复陶瓦联机页面图标对齐问题 (by 快乐凤爪王)
- GP-6226: 修复模组文件名不能包含感叹号的问题 (by Calboot)
- GP-6256: 修复 Java 管理页面点击列表项时标签闪烁的问题 (by 庐庐绫)
- GP-6263: 修复图片容器底部间距过大的问题 (by 快乐凤爪王)
- GP-6264: 修复版本页面标签消失的问题 (by 快乐凤爪王)
- GP-6257: 修复已弃用 JVM 内存设置的内存单位对齐问题 (by 快乐凤爪王)
- GP-6262: 修复 toast 消息未居中的问题 (by 快乐凤爪王)
- GP-6269: 修复主题包管理页面缺少 `gray-background` 的问题 (by 辞庐)
- GP-6249: 修复 Java 管理无法安装部分 Java 的问题 (by 辞庐, Glavo)
- GP-6244: 修复在实例列表加载完成前切换实例文件夹导致的空指针问题 (by NoClassDefFoundError)
- GP-6240: 修复 `mmc-bootstrap` 已存在时仍被覆盖的问题 (by Burning_TNT)
- GP-6109: 修复陶瓦联机账户快速切换列表滚动条错位及列表异常抖动的问题 (by 辞庐, Glavo)
- GP-6185: 修复 Curse 整合包更新后未移除旧模组的问题 (by Zkitefly)
- GP-6285: 修复颜色选择器与文本框高度不一致的问题 (by 快乐凤爪王)
- GP-6288: 修复版本列表固定列表项高度可能失效的问题 (by 快乐凤爪王)
- GP-6260: 修复 JVM 内存输入框允许输入非数字字符的问题 (by 快乐凤爪王)
- GP-6248: 修复安装手动打包整合包时任务名未本地化的问题 (by 辞庐)
- GP-6297: 修复 CurseForge 文件下载未带有 API Key 的问题 (by Calboot, Glavo)
- GP-6315: 修复复制 UUID 按钮显示冗余 `SpinnerPane` 的问题 (by 辞庐)
- GP-6302: 修复账户列表项间距问题 (by 快乐凤爪王)
- GP-6301: 修复 `authlib-injector` 警告文本被截断的问题 (by 快乐凤爪王)
- GP-6247: 修复联机核心第三方下载渠道按钮高度不一致的问题 (by 庐庐绫)
- GP-6339: 修复世界列表项标签显示问题 (by 快乐凤爪王)
- GP-6333: 修复 MCIM 描述未对齐的问题 (by 辞庐)
- GP-6337: 修复游戏列表项间距问题 (by 快乐凤爪王)
- GP-6325: 修复实例高级列表项在游戏仓库加载完成前加载图标的问题 (by Glavo)
- GP-6329: 修复远程版本列表项复用时副标题未恢复的问题 (by 快乐凤爪王)
- GP-6347: 修复模组和资源包信息列表项的图标尺寸问题 (by 快乐凤爪王)
- GP-6356: 修复自动分配内存逻辑异常的问题 (by Glavo)
- GP-6355: 修复安装新实例时 Fabric API 安装路径未遵循版本隔离策略的问题 (by Glavo)
- GP-6365: 修复在 `JFXComboBox` 弹出窗口的滚动条上释放鼠标时窗口隐藏的问题 (by Glavo)
- GP-6373: 修复 `JFXPasswordField` 导致 CPU 占用率异常增高的问题 (by Glavo)
- GP-6371: 修复整合包安装界面高度限制失效的问题 (by 辞庐)
- GP-6369: 修复账户列表项刷新按钮宽度变化导致布局偏移的问题 (by 快乐凤爪王)
- GP-6340: 修复 macOS 导出整合包的默认名称包含两个后缀名的问题 (by Calboot)
- GP-6386: 修复 Minecraft 26.1+ 无法安装 Quilt 的问题 (by Glavo)
+14
View File
@@ -0,0 +1,14 @@
---
---
[详细版本介绍 (Bilibili)](https://www.bilibili.com/opus/1225292274827526160)
**游戏设置**
- GP-6415: 完善游戏设置页面帮助文本 (by Glavo)
**错误修复**
- GP-6413: 修复游戏内容下载页面中的下载源下拉框消失的问题 (by 辞庐)
- GP-6414: 修复在 Minecraft 1.21.1 中安装信雅互联后仍显示不支持 Fabric 模组的问题 (by ToobLac)
+22
View File
@@ -0,0 +1,22 @@
---
---
[详细版本介绍 (Bilibili)](https://www.bilibili.com/opus/1229004896063193125)
**启动器**
- GP-6504: 支持在 FreeBSD x86-64、Linux Arm64、Linux LoongArch64 和 Linux RISC-V64 平台上启动 Minecraft 26.3-snapshot-4 及更高版本 (by Glavo)
**实例管理**
- GP-6503: 复制实例时同步保存游戏设置 (by Glavo)
**本地化**
- GP-6507: 更新内置主题相关译文 (by Glavo)
**错误修复**
- GP-6505: 修复切换版本隔离设置后其他子页面未自动刷新的问题 (by 辞庐)
- GP-6506: 修复实例高级列表项可能在非 JavaFX 线程更新界面的问题 (by 辞庐)
- GP-6508: 修复游戏 Java 路径显示滞后的问题 (by Apostrophe)
+27
View File
@@ -0,0 +1,27 @@
---
---
[详细版本介绍 (Bilibili)](https://www.bilibili.com/opus/1249018945486192640)
**启动器**
- GP-6871: 支持在 FreeBSD x86-64、Linux Arm64、Linux LoongArch64 和 Linux RISC-V64 平台上启动 Minecraft 26.3-snapshot-10 及更高版本 (by Glavo)
- GP-6879: 补充 Minecraft 26.3 快照版、预发布版、候选发布版和正式版的版本信息 (by Glavo)
**实例管理**
GP-6878: 优化模组列表的加载性能 (by Glavo)
**外观**
GP-6873: 改进 SVG 图像的识别与加载 (by Glavo)
**下载**
GP-6872: 更新模组数据(2026-07-21) (by Glavo)
**错误修复**
- GP-6874: 修复 Legacy Fabric 实例图标异常的问题 (by Glavo)
- GP-6875: 修复无法读取以 `.zip` 为扩展名的模组的问题 (by Glavo, ToobLac)
- GP-6876: 修复导出包含大型文件的 Modrinth 整合包时可能内存不足的问题 (by Glavo, Apostrophe)
+3
View File
@@ -340,6 +340,8 @@ post_process:
- /assets/js/plugins/smooth-scroll.js - /assets/js/plugins/smooth-scroll.js
- /assets/js/plugins/jquery.auto-redirect.js - /assets/js/plugins/jquery.auto-redirect.js
- /assets/js/_main.js - /assets/js/_main.js
/assets/js/hmcl-signature-verify.min.js:
- /assets/js/hmcl-signature-verify.js
remove_dirs: remove_dirs:
- /assets/images/ - /assets/images/
- /assets/js/plugins/ - /assets/js/plugins/
@@ -350,3 +352,4 @@ post_process:
- /assets/js/theme.js - /assets/js/theme.js
- /assets/js/settings.js - /assets/js/settings.js
- /assets/js/main.min.js.map - /assets/js/main.min.js.map
- /assets/js/hmcl-signature-verify.js
+2
View File
@@ -49,6 +49,8 @@ docs:
url: /changelog/dev.html url: /changelog/dev.html
- title: 其他 - title: 其他
children: children:
- title: HMCL 校验
url: /verify.html
- title: 用户协议 - title: 用户协议
url: /eula/hmcl.html url: /eula/hmcl.html
- title: 贡献指南 - title: 贡献指南
+3 -2
View File
@@ -63,9 +63,10 @@ author: zkitefly
z-index: 20; z-index: 20;
} }
#alert-modal img { #alert-modal img {
display: inline;
height: 1.5em;
vertical-align: middle; vertical-align: middle;
margin-block: -0.5em;
display: inline;
height: 2.5em;
} }
</style> </style>
<script> <script>
+14 -8
View File
@@ -1,16 +1,17 @@
--- ---
title: 各大问题集合 title: 各大问题集合
date: 2025-09-19 13:40:00 +0800 date: 2026-09-12 23:50:00 +0800
authors: authors:
- LIPiston - LIPiston
- Mine-diamond - Mine-diamond
- SinetianLiu
--- ---
> 这是一个提供给新手或小白的阅读文档,旨在用最简单的方式帮你快速上手 HMCL 启动器和 Minecraft 游戏。如需深入了解某个主题,可点击文中提供的链接查看详细文档。 > 这是一个提供给新手或小白的阅读文档,旨在用最简单的方式帮你快速上手 HMCL 启动器和 Minecraft 游戏。如需深入了解某个主题,可点击文中提供的链接查看详细文档。
> 这不是什么 Minecraft 速通指南/如何活过第一夜一类的东西。如果想要按教程游玩 Minecraft、充分享受其乐趣,那么[Minecraft Wiki 中文站的教程](https://zh.minecraft.wiki/w/教程)或许更适合你。
### 如何登录账户 ### 如何登录账户
你需要使用微软账户购买游戏才能游玩 Minecraft,或者使用离线账户/外置账户。 通常来讲,你需要使用微软账户购买游戏才能游玩 Minecraft;或者,也可以使用离线账户/外置账户。
你可以在 [Minecraft 官网](https://www.minecraft.net/store/minecraft-java-bedrock-edition-pc?tabs=%7B%22details%22%3A0%7D) 或 [Xbox 商店](https://www.xbox.com/games/store/minecraft-java-bedrock-edition-for-pc/9nxp44l49shj) 购买游戏。 你可以在 [Minecraft 官网](https://www.minecraft.net/store/minecraft-java-bedrock-edition-pc?tabs=%7B%22details%22%3A0%7D) 或 [Xbox 商店](https://www.xbox.com/games/store/minecraft-java-bedrock-edition-for-pc/9nxp44l49shj) 购买游戏。
@@ -47,6 +48,7 @@ authors:
作为一款沙盒游戏,简单的说,核心玩法就是 **「破坏」** 和 **「创造」** 。你可以自由地探索世界、收集资源、建造家园、挑战怪物…… 作为一款沙盒游戏,简单的说,核心玩法就是 **「破坏」** 和 **「创造」** 。你可以自由地探索世界、收集资源、建造家园、挑战怪物……
对于新手而言,下面这些官方中文 Wiki 链接是你的最佳起点: 对于新手而言,下面这些官方中文 Wiki 链接是你的最佳起点:
- **新手入门必读**:[Minecraft Wiki 新手手册](https://zh.minecraft.wiki/w/%E6%95%99%E7%A8%8B/%E6%96%B0%E6%89%8B%E6%89%8B%E5%86%8C) - **新手入门必读**:[Minecraft Wiki 新手手册](https://zh.minecraft.wiki/w/%E6%95%99%E7%A8%8B/%E6%96%B0%E6%89%8B%E6%89%8B%E5%86%8C)
- **生存第一天指南**:[教程:第一天怎么过](https://zh.minecraft.wiki/w/Tutorial:%E7%AC%AC%E4%B8%80%E5%A4%A9) - **生存第一天指南**:[教程:第一天怎么过](https://zh.minecraft.wiki/w/Tutorial:%E7%AC%AC%E4%B8%80%E5%A4%A9)
@@ -66,6 +68,7 @@ authors:
- **想制作自己的资源包?** 深入了解 [资源包详细资料](https://zh.minecraft.wiki/w/%E8%B5%84%E6%BA%90%E5%8C%85)。 - **想制作自己的资源包?** 深入了解 [资源包详细资料](https://zh.minecraft.wiki/w/%E8%B5%84%E6%BA%90%E5%8C%85)。
你可以在下列网站获取资源包: 你可以在下列网站获取资源包:
- [CurseForge](https://www.curseforge.com/minecraft/texture-packs) - [CurseForge](https://www.curseforge.com/minecraft/texture-packs)
- [Modrinth](https://modrinth.com/resourcepacks) - [Modrinth](https://modrinth.com/resourcepacks)
@@ -74,6 +77,7 @@ authors:
你可能听说过我的世界拥有丰富的模组(Mod)资源。模组是一类能改变或增加游戏内容的强大工具,它允许你新增方块、生物、物品与机制等内容。通过安装模组,你可以获得更丰富的内容、更顺手的玩法体验和更出色的视听表现。 你可能听说过我的世界拥有丰富的模组(Mod)资源。模组是一类能改变或增加游戏内容的强大工具,它允许你新增方块、生物、物品与机制等内容。通过安装模组,你可以获得更丰富的内容、更顺手的玩法体验和更出色的视听表现。
你可以在下列网站获取模组信息,并在 HMCL 内下载和安装: 你可以在下列网站获取模组信息,并在 HMCL 内下载和安装:
- [MC 百科](https://www.mcmod.cn/) - [MC 百科](https://www.mcmod.cn/)
- [CurseForge](https://www.curseforge.com/minecraft/search?class=mc-mods) - [CurseForge](https://www.curseforge.com/minecraft/search?class=mc-mods)
- [Modrinth](https://modrinth.com/mods) - [Modrinth](https://modrinth.com/mods)
@@ -84,7 +88,7 @@ HMCL 自动安装与使用模组教程: [跳转](/_launcher/auto-installing.md
安装模组后游戏无法启动或崩溃是常见的情况,通常是模组冲突或缺少前置模组导致的。别担心,大部分问题都能轻松解决。 安装模组后游戏无法启动或崩溃是常见的情况,通常是模组冲突或缺少前置模组导致的。别担心,大部分问题都能轻松解决。
在 HMCL《自动安装与模组下载简介》的末尾讲到了常用的解决方法: [跳转](/_launcher/auto-installing.md#安装-mod-后游戏报错无法启动) 在 HMCL《自动安装与模组下载简介》的末尾讲到了常用的解决方法: [跳转](/_launcher/auto-installing.md#%E5%AE%89%E8%A3%85-mod-%E5%90%8E%E6%B8%B8%E6%88%8F%E6%8A%A5%E9%94%99%E6%97%A0%E6%B3%95%E5%90%AF%E5%8A%A8)
或者前往模组包报错排查手册中查看: [跳转](/_modpack/error-handbook.md) 或者前往模组包报错排查手册中查看: [跳转](/_modpack/error-handbook.md)
@@ -92,17 +96,19 @@ HMCL 自动安装与使用模组教程: [跳转](/_launcher/auto-installing.md
### 如何选择游戏的 Java 版本 ### 如何选择游戏的 Java 版本
HMCL 会自动管理 Java,并针对不同版本的游戏自动选择合适的 Java 版本。若在启动游戏时未检测到合适的 Java,HMCL 也会提示下载 Java(点击“下载”即可完成安装)。对于新手玩家,使用默认设置即可。 HMCL 会自动管理 Java,并针对不同版本的游戏自动选择合适的 Java 版本。若在启动游戏时未检测到合适的 Java,HMCL 也会提示下载 Java(点击“下载”即可完成安装)。对于新手玩家,并不建议手动更改Java版本——这可能会导致游戏崩溃。使用默认设置即可。
如果你确实需要手动安装并指定 Java 版本: 如果你确实需要手动安装并指定 Java 版本:
**安装 Java:** **安装 Java:**
1. 进入 **设置 -> Java 管理**,此处会展示 HMCL 安装的或系统中已安装的 Java。
1. 进入 **设置 -&gt; Java 管理**,此处会展示 HMCL 安装的或系统中已安装的 Java。
2. 如果需要下载 Java,点击「下载 Java」,选择所需的版本,然后点击「确定」。 2. 如果需要下载 Java,点击「下载 Java」,选择所需的版本,然后点击「确定」。
3. 如果你安装了 Java 但是没有被 HMCL 识别,选择「添加 Java」,找到你需要的 Java 安装路径下的 `java.exe` 文件(仅 Windows)或 `java` 文件(仅 Linux/macOS),然后点击确定。 3. 如果你安装了 Java 但是没有被 HMCL 识别,选择「添加 Java」,找到你需要的 Java 安装路径下的 `java.exe` 文件(仅 Windows)或 `java` 文件(仅 Linux/macOS),然后点击确定。
**选择 Java:** **选择 Java:**
- 如果希望所有实例都使用同一 Java 版本,进入「设置 -> 全局游戏设置」,选择要使用的 Java。该 Java 将用于所有使用全局游戏设置的实例(一般不推荐)。
- 如果仅需为某个实例指定 Java 版本,进入该实例的「实例管理界面 -> 游戏设置」(勾选“启用实例特定游戏设置”),然后选择要使用的 Java。该 Java 仅用于该实例的启动。 - 如果希望所有实例都使用同一 Java 版本,进入「设置 -&gt; 全局游戏设置」,选择要使用的 Java。该 Java 将用于所有使用全局游戏设置的实例(一般不推荐)。
- 如果仅需为某个实例指定 Java 版本,进入该实例的「实例管理界面 -&gt; 游戏设置」(勾选“启用实例特定游戏设置”),然后选择要使用的 Java。该 Java 仅用于该实例的启动。
> **重要提示**:如果你在更换 Java 后遇到任何游戏崩溃或无法启动的问题,**请立即切换回 HMCL 默认的 Java 版本**。 > **重要提示**:如果你在更换 Java 后遇到任何游戏崩溃或无法启动的问题,**请立即切换回 HMCL 默认的 Java 版本**。
+1 -1
View File
@@ -24,7 +24,7 @@ authors:
在对应的游戏版本管理页面,点击 `自动安装` ,你会看到有个 `OptiFine` 的选项。 在对应的游戏版本管理页面,点击 `自动安装` ,你会看到有个 `OptiFine` 的选项。
![OptiFine_AutoInstaller](/assets/img/docs/shader/install_auto-16338577874692.png) ![OptiFine_AutoInstaller](/assets/img/docs/shader/install_auto.png)
点开之后选择合适的版本然后等待安装完成即可。 点开之后选择合适的版本然后等待安装完成即可。
目前,如果要在 `Fabric` 使用 `OptiFine` ,需要通过 **方式四** 安装。 目前,如果要在 `Fabric` 使用 `OptiFine` ,需要通过 **方式四** 安装。
+4 -5
View File
@@ -1,16 +1,15 @@
--- ---
title: 多人联机反馈 title: 多人联机反馈
date: 2025-10-07T18:44:00+08:00 date: 2025-10-07T18:44:00+08:00
last_modified_at: 2025-12-03T16:39:00+08:00 last_modified_at: 2026-06-18T12:07:00+08:00
authors: authors:
- Burning_TNT - Burning_TNT
- TyMxy - TyMxy
--- ---
## Terracotta | 陶瓦联机 ## Terracotta | 陶瓦联机
> [!TIP] > [!TIP]
> 欢迎您填写<a href="https://f.kdocs.cn/ksform/w/write/njMwdtgD?channel=mdlsjp" data-delay="10" data-redirect>反馈表单</a>。 > 欢迎您填写[反馈表单](https://f.kdocs.cn/ksform/w/write/njMwdtgD?channel=mdlsjp)。
我们注意到了 EasyTier 项目。它提供了一种简单、安全、去中心化的异地组网方案,足以承载 Minecraft 的联机需求。 我们注意到了 EasyTier 项目。它提供了一种简单、安全、去中心化的异地组网方案,足以承载 Minecraft 的联机需求。
在 EasyTier 开发团队的帮助下,我们决定重新在启动器内提供联机服务。 在 EasyTier 开发团队的帮助下,我们决定重新在启动器内提供联机服务。
@@ -18,11 +17,11 @@ authors:
如要体验陶瓦联机,请遵循以下步骤: 如要体验陶瓦联机,请遵循以下步骤:
打开 HMCL,然后您可通过 HMCL 左下角 **多人联机** 入口体验 Terracotta | 陶瓦联机。 打开 HMCL,然后您可通过 HMCL 左下角 **多人联机** 入口体验 Terracotta | 陶瓦联机。
目前,HMCL、PCL CE 已实现最基本的互通支持。我们欢迎其他启动器接入 Scaffolding 协议实现更完整的互通功能。 目前,HMCL、PCL CE和FCL已实现最基本的互通支持。我们欢迎其他启动器接入 Scaffolding 协议实现更完整的互通功能。
为向尽可能多的玩家免费开放基本联机功能,陶瓦联机将极大程度上基于 P2P。 为向尽可能多的玩家免费开放基本联机功能,陶瓦联机将极大程度上基于 P2P。
简单而言,陶瓦联机不会比市面上基于服务器中继的联机方案稳定,但其开销将远远低于其他联机方案。 简单而言,陶瓦联机不会比市面上基于服务器中继的联机方案稳定,但其开销将远远低于其他联机方案。
需要特别提醒的是:联机功能不会更不能取代 Minecraft: Java Edition 服务器。 需要特别提醒的是:联机功能不会更不能取代 Minecraft: Java Edition 服务器。
它的主要目标依然是让朋友之间能共同游玩,而不是长时间的对外开放。 它的主要目标依然是让朋友之间能共同游玩,而不是长时间的对外开放。
最后,我想感谢一切参与到 EasyTier、Terracotta \| 陶瓦联机开发和测试、为 EasyTier 提供打洞和中继服务器的社区志愿者。欢迎大家访问 [easytier.cn](https://easytier.cn) 深入了解这一项目。 最后,我想感谢一切参与到 EasyTier、Terracotta | 陶瓦联机开发和测试、为 EasyTier 提供打洞和中继服务器的社区志愿者。欢迎大家访问 [EastTier官网](https://easytier.cn) 深入了解这一项目。
+14
View File
@@ -0,0 +1,14 @@
---
title: 多人联机在macOS 15+的已知问题
date: 2025-10-07T18:44:00+08:00
last_modified_at: 2026-06-18T12:07:00+08:00
authors:
- SinetianLiu
---
## 来源
在较新的macOS中,引入了“本地网络”权限。而欲申请这一权限,进程必须以macOS原生app运行。这导致由裸Java启动的Minecraft进程**无法申请这一权限**,也就无法连接本地网络,进而导致无法正常联机。
## 现况
无法解决。请尝试别的联机方式。
+40
View File
@@ -0,0 +1,40 @@
---
title: HMCL 校验
permalink: /verify.html
classes: wide
toc: false
---
检查 HMCL 文件是否是官方构建。
<div id="hmcl-verify" class="notice">
<div id="hmcl-verify-alert">点击并选择文件或将文件拖拽到此处进行校验</div>
<div id="hmcl-verify-file"></div>
<input id="hmcl-verify-input" type="file" accept=".jar,.exe,.sh">
</div>
<style>
#hmcl-verify {
gap: 2em;
display: flex;
cursor: pointer;
user-select: none;
text-align: center;
align-items: center;
aspect-ratio: 16 / 9;
flex-direction: column;
justify-content: center;
transition: background-color .3s ease;
}
#hmcl-verify-alert {
font-size: 2em;
}
#hmcl-verify-file {
font-size: 1.5em;
}
#hmcl-verify-input {
display: none;
}
</style>
<script src="/assets/js/hmcl-signature-verify.min.js"></script>
+4
View File
@@ -105,6 +105,10 @@ module KramdownEnhancer
if el.value == "a" && el.attr["href"].is_a?(String) if el.value == "a" && el.attr["href"].is_a?(String)
el.attr["href"] = relative_url(el.attr["href"]) el.attr["href"] = relative_url(el.attr["href"])
el.options[:relative] = true el.options[:relative] = true
elsif el.value == "script" && el.attr["src"].is_a?(String)
puts el.attr["src"]
el.attr["src"] = relative_url(el.attr["src"])
el.options[:relative] = true
elsif el.value == "img" && el.attr["src"].is_a?(String) elsif el.value == "img" && el.attr["src"].is_a?(String)
src = el.attr["src"] src = el.attr["src"]
el.attr["src"] = relative_url(el.attr["src"]) el.attr["src"] = relative_url(el.attr["src"])
Binary file not shown.

Before

Width:  |  Height:  |  Size: 446 KiB

After

Width:  |  Height:  |  Size: 499 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 KiB

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 446 KiB

After

Width:  |  Height:  |  Size: 498 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 856 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 KiB

After

Width:  |  Height:  |  Size: 498 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 447 KiB

After

Width:  |  Height:  |  Size: 498 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 438 KiB

After

Width:  |  Height:  |  Size: 490 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 363 KiB

After

Width:  |  Height:  |  Size: 417 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 199 KiB

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 KiB

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 KiB

After

Width:  |  Height:  |  Size: 366 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

+430
View File
@@ -0,0 +1,430 @@
(function () {
"use strict";
const SIGNATURE_ENTRY_NAME = "META-INF/hmcl_signature";
const PUBLIC_KEY_ENTRY_NAME = "assets/hmcl_signature_publickey.der";
const LAUNCHER_ENTRY_NAMES = ["assets/HMCLauncher.exe", "assets/HMCLauncher.sh"];
const PUBLIC_KEY_DER_BASE64 = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAypkXnIxC3KzQsICAK9lEan3icR8OUREbW1vqANzi7ne0EXAyFh1Ow10HIY+SIWHVhsIkS/mvNyUyW5TIPc22djWNQKf6OukOY2/htJpolj4l/uhPGe4BoFiV8m2jvyKq0X7truazc9/BDrLKkoIVIkXb0PenVs1AlFLnXzLEu9Lj4kxfkRO4zdV4CMHYWLWLLP9Dj0/Xg+tj9n/QX/IWVVrBporKiJgg99WztKw7wQ/Zd+Syu8vfa6IjpgRojtOiCb8MUvEUHcs8RG/PPRACJ8bNwCaNc0RNLoyfVGjjZGFh95XPr6huJYmn/11j45GTB9I5w77JnF83AWwAPyx15z6yHKm4epzXJ9yFrTK5nATQGD1H2i8rdg4ZvsjFE4nxEYTWDTkk9nQdZs3n5Os+pUh8hyyjsa4Hh2yjmfcivcE/KzyP8JH15OWH9QOHwdfRTDu3v4AxSZCuQKlhaSpYbHFahE+jqP+Pr0+Bc/e5ybu6SdAELlOJrVYU6pkgrvYJmkV6Ahfm3P8OZKt72MAGxDfdYNUA70QWMMC1YP+GQYedC+oLA4/BhQ1Su9AfUUdQGN0a8a6uaZFX5QyiA/6KrRUC06dQdXi9ZOCx8LY28Snl7TjgmOef15HnnmmQTbARJuR0eenprzOXJXJzkS6/Vx1ak/9gNRA8yMiVM9lIilsCAwEAAQ==";
const PUBLIC_KEY_DER = base64ToUint8Array(PUBLIC_KEY_DER_BASE64);
const VerificationErrorCode = Object.freeze({
MISSING_PUBLIC_KEY: "missing-public-key",
MISSING_SIGNATURE: "missing-signature",
INVALID_PUBLIC_KEY: "invalid-public-key",
INVALID_SIGNATURE: "invalid-signature",
INVALID_LAUNCHER_HEADER: "invalid-launcher-header",
INVALID_ZIP: "invalid-zip",
UNSUPPORTED_ZIP: "unsupported-zip",
UNSUPPORTED_BROWSER: "unsupported-browser",
});
class VerificationError extends Error {
constructor(code, message, cause) {
super(message);
this.name = "VerificationError";
this.code = code;
this.cause = cause;
}
}
const container = document.getElementById("hmcl-verify");
if (!container) return;
["dragenter", "dragover", "dragleave", "drop"].forEach(eventName => {
container.addEventListener(eventName, (e) => {
e.preventDefault();
e.stopPropagation();
}, false);
});
["dragenter", "dragover"].forEach(eventName => {
container.addEventListener(eventName, () => {
container.className = "notice--info";
}, false);
});
["dragleave", "drop"].forEach(eventName => {
container.addEventListener(eventName, () => {
container.className = "notice";
}, false);
});
container.addEventListener("drop", (event) => handleFiles(event.dataTransfer.files), false);
const fileInput = document.getElementById("hmcl-verify-input");
if (!fileInput) return;
container.addEventListener("click", () => fileInput.click());
const resultElement = document.getElementById("hmcl-verify-alert");
const selectedFileElement = document.getElementById("hmcl-verify-file");
if (!fileInput || !resultElement) {
return;
}
fileInput.addEventListener("change", async () => handleFiles(fileInput.files));
let verificationRequestId = 0;
async function handleFiles(files) {
const requestId = ++verificationRequestId;
const file = files && files[0];
if (!file) {
setSelectedFileName("");
return;
}
setSelectedFileName(file.name);
setResult("正在校验中");
try {
await verifyHmclFile(file);
if (!isCurrentVerification(requestId)) {
return;
}
setResult(
"校验成功,该文件是 HMCL 的官方构建,可以放心使用",
"ok"
);
} catch (error) {
if (!isCurrentVerification(requestId)) {
return;
}
setResult(`校验失败,${formatVerificationError(error)}`, "error");
}
}
function isCurrentVerification(requestId) {
return requestId === verificationRequestId;
}
async function verifyHmclFile(file) {
const fileBuffer = await file.arrayBuffer();
const archive = readZipArchive(fileBuffer);
const entries = archive.entries;
const publicKeyEntry = entries.find((entry) => entry.name === PUBLIC_KEY_ENTRY_NAME);
const signatureEntry = entries.find((entry) => entry.name === SIGNATURE_ENTRY_NAME);
if (!publicKeyEntry) {
throw new VerificationError(VerificationErrorCode.MISSING_PUBLIC_KEY, `missing ${PUBLIC_KEY_ENTRY_NAME}`);
}
if (!signatureEntry) {
throw new VerificationError(VerificationErrorCode.MISSING_SIGNATURE, `missing ${SIGNATURE_ENTRY_NAME}`);
}
const bundledPublicKey = await readEntryContent(fileBuffer, publicKeyEntry);
if (!bytesEqual(bundledPublicKey, PUBLIC_KEY_DER)) {
throw new VerificationError(VerificationErrorCode.INVALID_PUBLIC_KEY, "public key mismatch");
}
const signature = await readEntryContent(fileBuffer, signatureEntry);
const signedEntries = entries
.filter((entry) => entry.name !== SIGNATURE_ENTRY_NAME)
.sort((left, right) => {
if (left.name < right.name) {
return -1;
}
if (left.name > right.name) {
return 1;
}
return 0;
});
const signedDataChunks = [];
for (const entry of signedEntries) {
const nameBytes = new TextEncoder().encode(entry.name);
const content = await readEntryContent(fileBuffer, entry);
signedDataChunks.push(await sha512(nameBytes));
signedDataChunks.push(await sha512(content));
}
const publicKey = await crypto.subtle.importKey(
"spki",
PUBLIC_KEY_DER,
{
name: "RSASSA-PKCS1-v1_5",
hash: "SHA-512",
},
false,
["verify"]
);
const valid = await crypto.subtle.verify(
"RSASSA-PKCS1-v1_5",
publicKey,
signature,
concatUint8Arrays(signedDataChunks)
);
if (!valid) {
throw new VerificationError(VerificationErrorCode.INVALID_SIGNATURE, "invalid signature");
}
await verifyLauncherPrefix(fileBuffer, archive);
}
function readZipArchive(buffer) {
const view = new DataView(buffer);
const end = findEndOfCentralDirectory(view);
const totalEntries = view.getUint16(end + 10, true);
const centralDirectorySize = view.getUint32(end + 12, true);
const centralDirectoryOffset = view.getUint32(end + 16, true);
if (centralDirectorySize === 0xffffffff || centralDirectoryOffset === 0xffffffff) {
throw new VerificationError(VerificationErrorCode.UNSUPPORTED_ZIP, "Zip64 is not supported");
}
const zipStartOffset = end - centralDirectorySize - centralDirectoryOffset;
if (zipStartOffset < 0) {
throw new VerificationError(VerificationErrorCode.INVALID_ZIP, "invalid zip offsets");
}
const entries = [];
let offset = zipStartOffset + centralDirectoryOffset;
const centralDirectoryEnd = offset + centralDirectorySize;
for (let index = 0; index < totalEntries; index += 1) {
if (offset + 46 > view.byteLength || view.getUint32(offset, true) !== 0x02014b50) {
throw new VerificationError(VerificationErrorCode.INVALID_ZIP, "invalid central directory");
}
const flags = view.getUint16(offset + 8, true);
const method = view.getUint16(offset + 10, true);
const compressedSize = view.getUint32(offset + 20, true);
const uncompressedSize = view.getUint32(offset + 24, true);
const fileNameLength = view.getUint16(offset + 28, true);
const extraLength = view.getUint16(offset + 30, true);
const commentLength = view.getUint16(offset + 32, true);
const localHeaderOffset = view.getUint32(offset + 42, true);
const fileNameStart = offset + 46;
const fileNameEnd = fileNameStart + fileNameLength;
const name = decodeEntryName(new Uint8Array(view.buffer, fileNameStart, fileNameLength), flags);
entries.push({
name,
method,
compressedSize,
uncompressedSize,
localHeaderOffset: zipStartOffset + localHeaderOffset,
});
offset = fileNameEnd + extraLength + commentLength;
}
if (offset !== centralDirectoryEnd) {
throw new VerificationError(VerificationErrorCode.INVALID_ZIP, "central directory size mismatch");
}
return {
entries,
zipStartOffset,
};
}
function findEndOfCentralDirectory(view) {
const minOffset = Math.max(0, view.byteLength - 22 - 0xffff);
for (let offset = view.byteLength - 22; offset >= minOffset; offset -= 1) {
if (view.getUint32(offset, true) === 0x06054b50) {
const commentLength = view.getUint16(offset + 20, true);
if (offset + 22 + commentLength === view.byteLength) {
return offset;
}
}
}
throw new VerificationError(VerificationErrorCode.INVALID_ZIP, "end of central directory not found");
}
async function readEntryContent(buffer, entry) {
const view = new DataView(buffer);
const offset = entry.localHeaderOffset;
if (offset + 30 > view.byteLength || view.getUint32(offset, true) !== 0x04034b50) {
throw new VerificationError(VerificationErrorCode.INVALID_ZIP, `invalid local header: ${entry.name}`);
}
const fileNameLength = view.getUint16(offset + 26, true);
const extraLength = view.getUint16(offset + 28, true);
const dataStart = offset + 30 + fileNameLength + extraLength;
const dataEnd = dataStart + entry.compressedSize;
if (dataEnd > view.byteLength) {
throw new VerificationError(VerificationErrorCode.INVALID_ZIP, `entry data is truncated: ${entry.name}`);
}
const compressedData = new Uint8Array(buffer, dataStart, entry.compressedSize);
if (entry.method === 0) {
return compressedData;
}
if (entry.method === 8) {
return inflateRaw(compressedData, entry.name, entry.uncompressedSize);
}
throw new VerificationError(
VerificationErrorCode.UNSUPPORTED_ZIP,
`unsupported compression method ${entry.method}: ${entry.name}`
);
}
async function verifyLauncherPrefix(buffer, archive) {
const prefixLength = archive.zipStartOffset;
if (prefixLength === 0) {
return;
}
const prefix = new Uint8Array(buffer, 0, prefixLength);
for (const entryName of LAUNCHER_ENTRY_NAMES) {
const launcherEntry = archive.entries.find((entry) => entry.name === entryName);
if (!launcherEntry) {
continue;
}
const launcherContent = await readEntryContent(buffer, launcherEntry);
if (bytesEqual(prefix, launcherContent)) {
return;
}
}
throw new VerificationError(
VerificationErrorCode.INVALID_LAUNCHER_HEADER,
"launcher header does not match signed assets"
);
}
async function inflateRaw(data, entryName, expectedSize) {
if (typeof DecompressionStream === "undefined") {
throw new VerificationError(
VerificationErrorCode.UNSUPPORTED_BROWSER,
"this browser does not support DecompressionStream"
);
}
let stream;
try {
stream = new Blob([data]).stream().pipeThrough(new DecompressionStream("deflate-raw"));
} catch (error) {
throw new VerificationError(
VerificationErrorCode.UNSUPPORTED_BROWSER,
`this browser cannot decompress deflated zip entries: ${entryName}`,
error
);
}
let output;
try {
output = new Uint8Array(await new Response(stream).arrayBuffer());
} catch (error) {
throw new VerificationError(
VerificationErrorCode.INVALID_ZIP,
`cannot decompress entry: ${entryName}`,
error
);
}
if (output.byteLength !== expectedSize) {
throw new VerificationError(
VerificationErrorCode.INVALID_ZIP,
`uncompressed size mismatch: ${entryName}`
);
}
return output;
}
function decodeEntryName(bytes, flags) {
if ((flags & 0x0800) === 0) {
return new TextDecoder("utf-8").decode(bytes);
}
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
}
async function sha512(data) {
return new Uint8Array(await crypto.subtle.digest("SHA-512", data));
}
function concatUint8Arrays(chunks) {
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);
const result = new Uint8Array(totalLength);
let offset = 0;
for (const chunk of chunks) {
result.set(chunk, offset);
offset += chunk.byteLength;
}
return result;
}
function bytesEqual(left, right) {
if (left.byteLength !== right.byteLength) {
return false;
}
for (let index = 0; index < left.byteLength; index += 1) {
if (left[index] !== right[index]) {
return false;
}
}
return true;
}
function base64ToUint8Array(base64) {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let index = 0; index < binary.length; index += 1) {
bytes[index] = binary.charCodeAt(index);
}
return bytes;
}
function formatVerificationError(error) {
switch (error && error.code) {
case VerificationErrorCode.MISSING_PUBLIC_KEY:
return "这不是可验证的 HMCL 文件,或者 HMCL 版本过低,无法验证";
case VerificationErrorCode.MISSING_SIGNATURE:
return "这是非官方构建,请谨慎甄别其来源";
case VerificationErrorCode.INVALID_PUBLIC_KEY:
case VerificationErrorCode.INVALID_SIGNATURE:
case VerificationErrorCode.INVALID_LAUNCHER_HEADER:
return "该 HMCL 文件可能被篡改或已损坏,请不要使用此文件;你可以从 HMCL 官方网站重新下载 HMCL";
case VerificationErrorCode.INVALID_ZIP:
return "这个文件不是有效的 HMCL 文件,或文件已经损坏";
case VerificationErrorCode.UNSUPPORTED_ZIP:
return "暂不支持验证这种文件格式";
case VerificationErrorCode.UNSUPPORTED_BROWSER:
return "当前浏览器不支持读取这个文件,请换用新版 Chrome、Edge 或 Firefox";
default:
return "无法完成验证,请确认你选择的是从官方渠道下载的 HMCL 文件";
}
}
function setResult(message, state) {
resultElement.textContent = message;
resultElement.style.display = "block";
if (state === "ok") {
container.className = "notice--success";
} else if (state === "error") {
container.className = "notice--danger";
} else {
container.className = "notice";
}
}
function setSelectedFileName(fileName) {
if (selectedFileElement) {
selectedFileElement.textContent = fileName || "未选择文件";
}
}
})();
+2
View File
@@ -18,6 +18,8 @@ title: 新手导航
> 如果您遇到 BUG,请及时在 [HMCL/issues](https://github.com/HMCL-dev/HMCL/issues) 发送反馈。\ > 如果您遇到 BUG,请及时在 [HMCL/issues](https://github.com/HMCL-dev/HMCL/issues) 发送反馈。\
> 您也可以在这里提交您的建议。 > 您也可以在这里提交您的建议。
这里是HMCL的官方帮助文档。如欲了解HMCL的使用方法、解决常见问题,请翻阅下方目录。如欲咨询崩溃原因,可前往[QQ群](https://docs.hmcl.net/groups.html)或[Discord群](https://discord.com/invite/jVvC7HfM6U)寻求帮助。
{% include toc %} {% include toc %}
{% for group in site.data.navigation.docs -%} {% for group in site.data.navigation.docs -%}