Repository navigation
fix(mods): check Mod updates by archive hash like Olympus, verify downloaded archives - #87
Merged
std-microblock merged 1 commit intoOct 13, 2026
Conversation
CeleMod decided whether an installed Mod was up to date by comparing the version in its `everest.yaml` with the version the catalog lists. Upstream archives do not always keep that number in sync: the aonHelper 0.19.8 file still declares `Version: 0.19.7` (a typo, GameBanana calls the file 0.19.8), so players whose installed archive declares 0.19.7 never see the update, while Olympus offers it. Olympus and Everest ignore the version for this check: they compare the xxHash64 of the installed archive with the hashes of the newest file in the update database. Do the same: * `archive_hash` hashes installed archives with xxHash64 (matching `Everest.GetChecksum`) and caches the result per file, so the Mod list keeps loading without reading every archive. * `get_mod_latest_info` now returns the catalog `xxHash` entries and `get_mod_archive_hashes` returns the installed archive hashes. * `collectModUpdates` reports an update when the version moved, or when the installed archive is not one of the newest file's hashes. Unpacked Mods and entries without a hash keep the version comparison. The update itself is also verified against the catalog hash now, and the next source (0x0ade mirror, then GameBanana) is tried when the archive does not match. The Chinese mirror serves an old LoennProjectManager archive under the newest file id, so every update installed the same v0.4.5 build again and the update badge never went away.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
群里的报告:CeleMod 认为 aonHelper 已经是最新(实际不是),用 Olympus 更新全部后游戏才正常打开;另外 LoennProjectManager 等 Lönn 系插件「更新不了」。两个症状是两回事,都在这里修。
根因 1:更新判定只看
everest.yaml的版本号updateNode之前用的判据是compareVersion(catalog.version, installed.version) > 0(Manage.tsx原 1307 行),而版本号两边都可能出错:celeste.weg.fan/api/v2/mod/list里 aonHelper 的version0.19.7submissionFile.gameBananaId/xxHash1827775/749a898300d45f58_sVersion、包内everest.yaml0.19.8/Version: 0.19.7(上游笔误)也就是说最新文件的
xxHash/文件 ID 已经换了,但version还停在 0.19.7,装上这个包的人读到的版本号也是 0.19.7 → CeleMod 判定「已是最新」,而 Olympus 会更新(它能更新 = 说明玩家的包确实不是最新文件,同时 CeleMod 没提示 = 玩家 yaml 里的号 ≥ 0.19.7,两边一夹就是「旧包 + yaml 0.19.7」,正好是这个判据的盲区)。Olympus/Everest 这一环不看版本号,看归档的 xxHash64(
Everest/Celeste.Mod.mm/Mod/Helpers/ModUpdaterHelper.cs:111ListAvailableUpdates):根因 2:镜像把旧包挂在新的文件 ID 上
Lönn Project Manager 最新文件是 GameBanana
1663608(v 0.4.7,103472 字节,包内Version: 0.4.7)。中国镜像(weg.fan,中文界面的默认源)两个下载接口给出的却是旧包:xxHashceleste.weg.fan/api/v2/download/gamebanana-files/1663608(=.../files/518525856676099948)0.4.5a95e42949b5295aagamebanana.com/mmdl/16636080.4.7970da23a3412a94dcelestemodupdater.0x0a.de/banana-mirror/1663608.zip0.4.7970da23a3412a94dweg.fan 那份和 GameBanana 上更早的
1555965(v 0.4.5)字节一致。所以 CeleMod 每次「更新」都装回同一个 v0.4.5,装完版本号还是 0.4.5 < 0.4.7,更新角标永远消不掉(「更新不了」),而 Olympus 用 mmdl/0x0a.de 拿到的是真包。改动
判定改用归档哈希(与 Olympus 一致)
src-tauri/src/archive_hash.rs:xxHash64(和Everest.GetChecksum同算法,测试里带空串/abc/xxhash的规范向量),结果按 (路径, 大小, 修改时间) 缓存,hash_file:40/cached_hash:59/ensure_hash:67。everest.rs:28目录条目带出xx_hash;backend.rs:5278get_mod_latest_info一并返回;backend.rs:5342新增get_mod_archive_hashes返回已装归档的哈希(只读一次,之后只 stat)。src/celemod-ui/src/modUpdates.ts:41collectModUpdates:版本号变大 或 已装归档不在最新文件的哈希列表里 → 提示更新;解包安装(文件夹)和目录没给哈希时退回原来的版本号比较。管理页Manage.tsx:1326用它算更新列表。更新包按目录哈希校验,不匹配就换源
Manage.tsx:1662起把更新流程改成「下载 → 校验 → 不行就换下一个源」:本机配置的镜像优先,然后 0x0ade 镜像、GameBanana 直链(0x0ade那份与 GameBanana 字节一致)。装完的归档哈希不在目录给出的列表里就算这次更新失败,不再默默留着旧包(Everest 的AutoModUpdater也是逐个镜像 +VerifyChecksum这么做的)。目录没提供哈希(例如自定义 URL 条目)时保持原行为。验证
cd src-tauri && cargo test --lib:110 passed(新增 3 个:xxHash 规范向量、缓存复用/失效、Mods 目录哈希扫描)。cd src/celemod-ui && pnpm test:mod-updates、pnpm typecheck、pnpm build通过(pnpm lint里那 5 条TS6133是仓库里既有的)。collectModUpdates入参就是上面表格里的真实数据):上游/镜像侧
everest.yaml的Version: 0.19.7是作者的笔误(GameBanana 文件本身叫v0.19.8),目录和 Everest 的 everest_update.yaml 都跟着写 0.19.7;本次改动让 CeleMod 不再被它挡住。