Mod data packs load with lower priority than Vanilla data packs
LemmaEOF opened this issue · 22 comments
Currently, mod data packs are added before the vanilla data pack is, resulting in them having a lower priority. This means that a mod can't use its data pack to override vanilla data like recipes. The insertion point for mod data packs should go after the insertion point for vanilla.
While I agree with this in principle, it's sadly not that easy. The way that resource pack loading (and by extension data packs since they're 90% the same code) is designed, you have essentially two insertion points - bottom and top. The actual resulting order is processing order dependent, with each pack being inserted at the current bottom or top of the priority order as appropriate. Trying to reliably load Vanilla's resources before mod resources would require quite a bit of finegling due to this.
Well as it is now, it's currently inserting all mod data packs with lower priority than vanilla's, at least according to the ordered list I get when I run /datapack list
.
Yes, because their insertion location is set to "bottom" and they're registered after Vanilla. In theory it could be as simple as registering them before Vanilla, but in practice that could cause a lot of potential issues.
Yeah, that's fair. I might take a crack at it and see what I can do at some point.
What would be functionally optimal would be to modify the Vanilla behavior so that the default data pack was always loaded first no matter what, and inserting at the bottom inserted just above Vanilla, but that breaks the core principle of preserving Vanilla behavior if just the loader and API are installed. Not entirely sure what / how much can be done here.
well I mean one could argue that the current vanilla behavior is that the default data pack is always loaded first no matter what.
That's only true in practice, not in implementation. The fact that there is an option to insert below Vanilla, even if it's currently unused, is something that needs to be preserved; otherwise, it'll cause problems if they ever do use it.
Ah, that's a fair point. I'll take a look into what can be done; I might end up making a separate lib if needed.
So after a bit of experimentation, I came up with this Mixin to make my data pack have higher priority than Vanilla's:
@Mixin(NamespaceResourceManager.class)
public abstract class NamespaceResourceManagerMixin {
@Shadow @Final protected List<ResourcePack> packList;
private ResourcePack capturedPack = null;
private boolean hasVanillaGone = false;
@Inject(method = "addPack", at = @At("HEAD"), cancellable = true)
private void captureResourcePack(ResourcePack resourcePack_1, CallbackInfo ci) {
if (resourcePack_1.getName().equals("Default")) {
hasVanillaGone = true;
}
if (resourcePack_1.getName().equals("Nice to Have") && !hasVanillaGone) {
capturedPack = resourcePack_1;
}
}
@Inject(method = "addPack", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", shift = At.Shift.AFTER))
private void addCapturedPack(ResourcePack resourcePack_1, CallbackInfo ci) {
if (hasVanillaGone && capturedPack != null) {
NamespaceResourceManager self = ((NamespaceResourceManager)(Object)this);
ResourcePack pack = capturedPack;
packList.remove(capturedPack);
capturedPack = null;
self.addPack(pack);
}
}
}
This could easily be adapted to allow multiple resource packs to get captured. Additionally, a key in fabric.mod.json
could indicate whether or not the modder wants their pack to be inserted below vanilla so that that option is preserved.
Note that the captured pack is removed from the list after the vanilla pack gets added otherwise the ModelManager can't find any mod models from the captured pack.
Hm, that seems like it might be doable, since Fabric has a list of all the mod names. It doesn’t look like capturePackList
needs to be cancellable.
62841ce swaps using the insertion order from bottom to top which may be related. I assumed that it was the issue before fixing the other issue (since it was a discrepancy from Vanilla resource pack loading) but that may be causing unexpected behavior.
Hm, that seems like it might be doable, since Fabric has a list of all the mod names. It doesn’t look like
capturePackList
needs to be cancellable.
Yeah, that was leftover from when I tried to cancel it to prevent duplication in the list...and is how I discovered that the ModelManager is really fussy about things.
Also, you wouldn't need the mod name since all mod resource & data packs are represented by the ModNioResourcePack
, which contains its mod's metadata.
Good news: My method does not cause #66 to occur.
#66 was caused by the behavior of java's jar based resource functionality causing the Default pack to load mod resources which is entirely different from the issue here.
sigh, I was saying that my solution to this issue did not cause the same problems as setting the insertion position to the bottom did.
Yes, I understand. But what I was trying to say is that the the insertion order being BOTTOM may have actually been correct and that should be tested.
No problem, that was something that was an oversight with my work and I just wanted to make sure that it was properly investigated since what I did could be causing the issue!
Would it just be a matter of swapping the insertion order back or does something in MixinDefaultResourcePack
have to be changed as well?
Just swapping the insertion order back is worth a shot, since it hasn't been specifically tested yet.
Closing this issue as it was fixed a little while ago when the injections points of resource-loader were rewritten.
Tested again to make sure and modded datapacks take higher priority over the vanilla datapack.