Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The client and server mods loading order inconsistent #387

Open
SAGESSE-CN opened this issue Dec 2, 2023 · 7 comments
Open

The client and server mods loading order inconsistent #387

SAGESSE-CN opened this issue Dec 2, 2023 · 7 comments

Comments

@SAGESSE-CN
Copy link

SAGESSE-CN commented Dec 2, 2023

Exception

I found that the loading order of the Quilt loader on the server and client is different.

I know has some client mods do not exist on the server, but after excluding this mods, they are still in inconsistent order.

The client mods order: full client logs

Index Mod ID Version Type File Hash (SHA-1) File(s) Sub-File
22 Terraform Wood API (v1) terraform-wood-api-v1 4.2.0 Fabric 5b81eda6459643db8298e28dbc29cf28dced3894 \blockus-2.5.11+1.19.2.jar /META-INF/jars/terraform-wood-api-v1-4.2.0.jar
198 Armourer's Workshop armourers_workshop 2.0.11-dev.192 Fabric 05c872cf84b08063568947032daa648c09378012 \armourersworkshop-fabric-1.19.2-2.0.11-dev.192.jar
277 FrozenLib frozenlib 1.2.6-Fabric+1.19.2 Fabric 54991dce2a303ca2ad47affa9e4eebf951b34ecc \FrozenLib-1.2.6-Fabric+1.19.2.jar
226 Fzzy Core fzzy_core 0.2.7+1.19 Fabric 0d74ec51d8da7b8f002fedea30d34a416c8bcf8f \fzzy_core-0.2.7+1.19.jar

The server mods order: full server logs

Index Mod ID Version Type File Hash (SHA-1) File(s) Sub-File
23 Terraform Wood API (v1) terraform-wood-api-v1 4.2.0 Fabric 5b81eda6459643db8298e28dbc29cf28dced3894 /bewitchment-1.19-7.jar /META-INF/jars/terraform-wood-api-v1-4.2.0.jar
133 FrozenLib frozenlib 1.2.6-Fabric+1.19.2 Fabric 71f835f32763869c10c0f45b0e88ea8b54ec00c2 /FrozenLib-1.2.6-Fabric+1.19.2.jar
227 Fzzy Core fzzy_core 0.2.7+1.19 Fabric 0d74ec51d8da7b8f002fedea30d34a416c8bcf8f /fzzy_core-0.2.7+1.19.jar
278 Armourer's Workshop armourers_workshop 2.0.11-dev.192 Fabric 05c872cf84b08063568947032daa648c09378012 /armourersworkshop-fabric-1.19.2-2.0.11-dev.192.jar

Why loading order is important?

The entity serializer relies heavily on loading order, when the loading order changes, the entity serializer id will be completely different.

The client entity serializers:

Entity Serializer ID Registered Class Mod ID
23 com.terraformersmc.terraform.boat.impl.TerraformBoatTrackedData Terraform Wood API (v1)
24 moe.plushie.armourers_workshop.init.platform.fabric.proxy Armourer's Workshop
25 net.frozenblock.wilderwild.entity.variant.FireflyColor FrozenLib
26 net.frozenblock.wilderwild.entity.variant.JellyfishVariant FrozenLib
27 me.fzzyhmstrs.amethyst_imbuement.entity.living.HamsterVariant Fzzy Core

The Server entity serializers:

Entity Serializer ID Registered Class Mod ID
23 com.terraformersmc.terraform.boat.impl.TerraformBoatTrackedData Terraform Wood API (v1)
24 net.frozenblock.wilderwild.entity.variant.FireflyColor FrozenLib
25 net.frozenblock.wilderwild.entity.variant.JellyfishVariant FrozenLib
26 me.fzzyhmstrs.amethyst_imbuement.entity.living.HamsterVariant Fzzy Core
27 moe.plushie.armourers_workshop.init.platform.fabric.proxy Armourer's Workshop

The entity serializer register entry:

net.fabricmc.api.ModInitializer.onInitialize
org.quiltmc.loader.impl.game.minecraft.Hooks.lambda$startClient$0(Hooks.java:55)
org.quiltmc.loader.impl.entrypoint.EntrypointUtils.lambda$invoke$0(EntrypointUtils.java:36)
org.quiltmc.loader.impl.entrypoint.EntrypointUtils.invoke0(EntrypointUtils.java:62)
org.quiltmc.loader.impl.entrypoint.EntrypointUtils.invokeContainer(EntrypointUtils.java:49)
org.quiltmc.loader.impl.entrypoint.EntrypointUtils.invoke(EntrypointUtils.java:36)
org.quiltmc.loader.impl.game.minecraft.Hooks.startClient(Hooks.java:55)
net.minecraft.class_310.<init>(class_310.java:459)
net.minecraft.client.main.Main.method_44604(Main.java:205)
net.minecraft.client.main.Main.main(Main.java:51)
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.base/java.lang.reflect.Method.invoke(Method.java:568)
org.quiltmc.loader.impl.game.minecraft.MinecraftGameProvider.launch(MinecraftGameProvider.java:551)
org.quiltmc.loader.impl.launch.knot.Knot.launch(Knot.java:84)
org.quiltmc.loader.impl.launch.knot.KnotClient.main(KnotClient.java:28)
org.prismlauncher.launcher.impl.StandardLauncher.launch(StandardLauncher.java:87)
org.prismlauncher.EntryPoint.listen(EntryPoint.java:130)
org.prismlauncher.EntryPoint.main(EntryPoint.java:70)
@SAGESSE-CN
Copy link
Author

have any plan?

@AlexIIL
Copy link
Contributor

AlexIIL commented Jul 7, 2024

Realistically this means doing one of the following:

  • Adding a flag to force a different load order algorithm.
  • Changing the default load order algorithm to be consistent between mod ids.
  • Changing the load order to be alphabetical (or similar)

Basically this needs us to add different load order algorithms.

(In theory QSL could go in and sort entity serializer IDs, but that assumes you even use QSL)

@OroArmor
Copy link
Member

OroArmor commented Jul 7, 2024

QSL does have an api for syncing these, but it does require the mods to use the api. There is effectively no way to sync the handlers without additional information, and there should be an warning printed to the log when this happens.

@SAGESSE-CN
Copy link
Author

SAGESSE-CN commented Jul 8, 2024

The entity serializer IDs is just one of problems, and any code that uses mixin may face this problem.

I think the problem is here.

int seed = modIds.hashCode();
Collections.shuffle(modList, new Random(seed));

When the size of the mod list is inconsistent, the seed will be different.

@TropheusJ
Copy link

Mod load order is undefined on fabric as well (and intentionally shuffled in dev), and that should not change.

the solution is an API that avoids order-dependent problems, which quilt has, and fabric doesn’t. Fabric needs to get one (it’s one of the oldest issues on the repo), but in the meantime, mods need to avoid using the dangerous vanillla method.

I have a mod that finds this dangerous behavior as well as a few others. I’ve reported most of the ones you listed already.

@SAGESSE-CN
Copy link
Author

SAGESSE-CN commented Jul 8, 2024

The shuffled(although I don't know why need this) list not is a problem, the big problem is server side and client have a different load behaviors.

If QSL maintains the same loading behavior on both side (even use filename order, like forge), the mod developers will found issues and fix issue (use some QSL API).
But now that because the QSL loading behavior completely unpredictable, you can't expect a developer to fix an quantum problem (maybe exist, maybe not exist).

The my problem is one of loading problems, even though I solved the problem by using the QSL API (still has register order problem, I don't know your how to solve it), the load problem still exists.
I think the loader job is ensure loading same order, but seem your think it's the mod developer job.

@SAGESSE-CN
Copy link
Author

SAGESSE-CN commented Jul 8, 2024

A minimal changes suggestion, splite two mod list by (client only, server), use the same seed for shuffle.

var clientModLists = modList.stream().filter(it -> is client only)...
var serverModLists = modList.stream().filter(it -> has server)...
int seed = serverModLists.stream().map(it -> it.id).toList().hasCode(); 
Collections.shuffle(serverModLists, new Random(seed)); 
Collections.shuffle(clientModLists, new Random(seed)); 
modList = serverModLists + clientModLists

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants