Skip to content

feat: support all fabric server versions#1719

Merged
derklaro merged 4 commits intonightlyfrom
fabric-multi-mc-support
Aug 17, 2025
Merged

feat: support all fabric server versions#1719
derklaro merged 4 commits intonightlyfrom
fabric-multi-mc-support

Conversation

@derklaro
Copy link
Member

Motivation

There were a lot of questions asking about support for more than the latest fabric version.

Modification

Use the nested mods feature of the fabric loader to load version-specific mods (nested mods are only loaded if possible depending on their version constraints). In all cases where no version mod is available, a fallback listener is registered on the services to mark them as online after a small delay to allow for the server to start. This comes with the downside that no player count and player data can be provided to the api, but that should not be much of a problem.

Result

All versions of minecraft (using the fabric mod loader) are now supported by the bridge module.

@derklaro derklaro added this to the 4.0.0-RC14 milestone Aug 11, 2025
@derklaro derklaro requested a review from 0utplay August 11, 2025 13:43
@derklaro derklaro self-assigned this Aug 11, 2025
@derklaro derklaro added v: 4.X This pull should be included in the 4.0 release t: improvement The pull request improves existing code in: module An issue/pull request releated to one of the internal modules labels Aug 11, 2025
@github-actions
Copy link

github-actions bot commented Aug 11, 2025

Test Results

 56 files  ±0   56 suites  ±0   2m 17s ⏱️ -28s
570 tests ±0  570 ✅ ±0  0 💤 ±0  0 ❌ ±0 
935 runs  ±0  935 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit 767e0f8. ± Comparison against base commit d15bed0.

This pull request removes 36 and adds 36 tests. Note that renamed tests count towards both.
eu.cloudnetservice.driver.impl.document.DocumentSerialisationTest ‑ [4] {"b":1,"s":2,"i":3,"l":4,"f":5.0,"d":6.0,"c":"/","string":"Hello, World!","bol":true,"cloud":["Ben?","Yes","No","HoHoHoHo"],"world":{"insane":"!","this":"is","hello":"world"}}, PRETTY
eu.cloudnetservice.driver.impl.document.gson.JavaTimeSerializerTest ‑ [14] 2025-08-06
eu.cloudnetservice.driver.impl.document.gson.JavaTimeSerializerTest ‑ [23] 10:08:08.055032157
eu.cloudnetservice.driver.impl.document.gson.JavaTimeSerializerTest ‑ [28] 10:08:08.055145128Z
eu.cloudnetservice.driver.impl.document.gson.JavaTimeSerializerTest ‑ [29] 10:08:08.055167309Z
eu.cloudnetservice.driver.impl.document.gson.JavaTimeSerializerTest ‑ [30] 10:08:08.055193538+05:00
eu.cloudnetservice.driver.impl.document.gson.JavaTimeSerializerTest ‑ [31] 10:08:08.055211622-03:00
eu.cloudnetservice.driver.impl.document.gson.JavaTimeSerializerTest ‑ [34] 2025-08-06T10:08:08.055346213
eu.cloudnetservice.driver.impl.document.gson.JavaTimeSerializerTest ‑ [39] 2025-08-06T10:08:08.055489720Z
eu.cloudnetservice.driver.impl.document.gson.JavaTimeSerializerTest ‑ [4] 2025-08-06T10:08:08.048340411Z
…
eu.cloudnetservice.driver.impl.document.DocumentSerialisationTest ‑ [4] {"b":1,"s":2,"i":3,"l":4,"f":5.0,"d":6.0,"c":"/","string":"Hello, World!","bol":true,"cloud":["Ben?","Yes","No","HoHoHoHo"],"world":{"this":"is","hello":"world","insane":"!"}}, PRETTY
eu.cloudnetservice.driver.impl.document.gson.JavaTimeSerializerTest ‑ [14] 2025-08-11
eu.cloudnetservice.driver.impl.document.gson.JavaTimeSerializerTest ‑ [23] 14:54:17.749975093
eu.cloudnetservice.driver.impl.document.gson.JavaTimeSerializerTest ‑ [28] 14:54:17.750086751Z
eu.cloudnetservice.driver.impl.document.gson.JavaTimeSerializerTest ‑ [29] 14:54:17.750109554Z
eu.cloudnetservice.driver.impl.document.gson.JavaTimeSerializerTest ‑ [30] 14:54:17.750134049+05:00
eu.cloudnetservice.driver.impl.document.gson.JavaTimeSerializerTest ‑ [31] 14:54:17.750154066-03:00
eu.cloudnetservice.driver.impl.document.gson.JavaTimeSerializerTest ‑ [34] 2025-08-11T14:54:17.750283367
eu.cloudnetservice.driver.impl.document.gson.JavaTimeSerializerTest ‑ [39] 2025-08-11T14:54:17.750419050Z
eu.cloudnetservice.driver.impl.document.gson.JavaTimeSerializerTest ‑ [4] 2025-08-11T14:54:17.741943302Z
…

♻️ This comment has been updated with latest results.

Comment on lines +80 to +84
.dropWhile(stackFrame -> {
var className = stackFrame.getClassName();
var isEntrypointClass = className.contains(".Generated") && className.endsWith("Entrypoint");
return !isEntrypointClass;
})
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drive-by improvement: due to the new extra reflection call when loading platform plugins, this method now needs to skip 3 frames. To make it resiliant against future changes, I changed it to actually searching the entrypoint class instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is needed due to the shadow update. It doesn't seem to be the case anymore that classes override each other in the way they did before, therefore, I just added this extra step that just uses reflection to call the runtime methods instead. Should not make a performance difference really.


# plugins
shadow = "8.3.8"
shadow = "9.0.1"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update is needed as v9 is actually capable of copying jar files into the final fat jar instead of unpacking them.

dependencies = {
@Dependency(name = "fabricloader", version = ">=0.16.6"),
@Dependency(name = "minecraft", version = "~1.21.6"),
@Dependency(name = "fabricloader", version = ">=0.17.0"),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v0.17 is needed due to our fallback version getter (FabricLoader.getInstance().getRawGameVersion()) which was introduced in that version.

@@ -31,7 +31,7 @@
version = "@version@",
dependencies = {
@Dependency(name = "fabricloader", version = ">=0.16.6"),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we can technically drop the requirement way down (to around v0.12 iirc)

alias(libs.plugins.spotless)
alias(libs.plugins.nexusPublish)
alias(libs.plugins.fabricLoom) apply false
alias(libs.plugins.shadow) apply false // must be here to enforce the bundled asm version
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somehow a way older asm version leaks into the classpath if we don't do this (previously loom provided the newer one) which causes the shadow remap operations to fail (relocation, minimizing, etc.)

@derklaro derklaro merged commit a96947c into nightly Aug 17, 2025
5 checks passed
@derklaro derklaro deleted the fabric-multi-mc-support branch August 17, 2025 13:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

in: module An issue/pull request releated to one of the internal modules t: improvement The pull request improves existing code v: 4.X This pull should be included in the 4.0 release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants