@@ -218,6 +218,19 @@ private void checkUpdateForEntry(ModEntry entry) throws Exception {
218218 ? fileVersion .get ("project_id" ).getAsString () : null ;
219219 if (projectId == null ) return ;
220220
221+ // The version this exact jar belongs to, per Modrinth. This is the
222+ // canonical identity we compare against below — NOT the file name.
223+ // Mods installed from a modpack are saved under whatever file name the
224+ // pack's modrinth.index.json recorded, which can legitimately differ
225+ // from Modrinth's current "primary file" name for that same version
226+ // (the content/hash is identical, only the on-disk name differs). A
227+ // name-only comparison flags those as having an update every time,
228+ // and clicking "update" just re-downloads the identical version under
229+ // Modrinth's canonical name — after which the name matches and the
230+ // false positive disappears, i.e. it only happens once per mod.
231+ String currentVersionId = fileVersion .has ("id" )
232+ ? fileVersion .get ("id" ).getAsString () : null ;
233+
221234 // 3. Get all versions of the project filtered by our mc version + loader
222235 java .util .HashMap <String , Object > params = new java .util .HashMap <>();
223236 if (!mFilterMcVersion .isEmpty ()) params .put ("game_versions" , "[\" " + mFilterMcVersion + "\" ]" );
@@ -229,6 +242,11 @@ private void checkUpdateForEntry(ModEntry entry) throws Exception {
229242 // Modrinth returns newest first — index 0 is the latest
230243 JsonObject latest = versions .get (0 ).getAsJsonObject ();
231244
245+ // If the installed file is already the latest version, there's
246+ // nothing to do — regardless of what its file name happens to be.
247+ String latestVersionId = latest .has ("id" ) ? latest .get ("id" ).getAsString () : null ;
248+ if (currentVersionId != null && currentVersionId .equals (latestVersionId )) return ;
249+
232250 // 4. Get the latest version's primary file name
233251 JsonArray files = latest .getAsJsonArray ("files" );
234252 if (files == null || files .size () == 0 ) return ;
@@ -248,14 +266,11 @@ private void checkUpdateForEntry(ModEntry entry) throws Exception {
248266 String latestFileName = latestUrl .substring (latestUrl .lastIndexOf ('/' ) + 1 );
249267 if (latestFileName .contains ("?" )) latestFileName = latestFileName .substring (0 , latestFileName .indexOf ('?' ));
250268
251- // 5. Compare — if the file name differs, an update is available
252- String currentName = entry .file .getName ();
253- if (currentName .endsWith (".disabled" )) currentName = currentName .replace (".disabled" , "" );
254-
255- if (!currentName .equalsIgnoreCase (latestFileName )) {
256- entry .updateUrl = latestUrl ;
257- entry .updateFileName = latestFileName ;
258- }
269+ // 5. Reaching here means the early-return above didn't fire, i.e. the
270+ // installed file's version id is missing or genuinely differs from
271+ // the latest version id — a real update, independent of file naming.
272+ entry .updateUrl = latestUrl ;
273+ entry .updateFileName = latestFileName ;
259274 }
260275
261276 /** Downloads the update, replaces the existing jar, refreshes the entry. */
0 commit comments