Under certain circumstances with Quilt Loader, QFAPI / QSL, Botania, and Porting Lib installed, all loot tables appear to be empty
unilock opened this issue ยท 16 comments
(mostly copied from the relevant issue on Botania's issue tracker: VazkiiMods/Botania#4539)
Mod Loader
Quilt (not Fabric!)
Minecraft Version
1.20.1
Porting Lib version
2.1.1175+1.20.1
Modloader version
Quilt Loader 0.23.0 + QFAPI 7.4.0 / Fabric API 0.90.0
The latest.log file
https://gist.github.com/unilock/102676f783706c3df48a78b89980b897
Issue description
Under very certain conditions (namely, the specific set of mods installed), all loot tables appear to be empty - blocks drop nothing, slain mobs drop nothing, etc.
Steps to reproduce
- Install Quilt Loader 0.23.0
- Install the exact set of mods listed below
- Start the game, create a new superflat world in survival mode with cheats enabled
- Try breaking a Grass Block by hand; nothing is dropped
/give <username> minecraft:netherite_sword/summon minecraft:sheep- Kill the Sheep with the Netherite Sword; nothing is dropped
Other information
This issue does not occur reliably across all modded environments; rather, it seems dependent on which mods are installed at the time. I suspect this is due to the mod loading order being semi-random on Fabric / Quilt; I'm guessing it's deterministic based on the current mod set. My theory is that some loot-related mixin is being applied before / after some other loot-related mixin in an incompatible manner, ultimately causing the issue.
Due to this issue being so random, it's been very difficult to narrow down the mod set to only those related to the issue. Here is the smallest set of mods I've been able to reproduce the issue with thus far:
badpackets-fabric-0.4.3.jarbalm-fabric-1.20.1-7.2.1.jar*Botania-1.20.1-443-FABRIC.jar*can-i-mine-this-block-1.4.0.jarCrafty-Crashes-1.0.jarctrlq-fabric-mc1.19.3+-1.9.jaremi-1.0.29+1.20.1+fabric.jarmacos-input-fixes-1.6.jarmixintrace-1.1.1+1.17.jarmodmenu-7.2.2.jarMouseTweaks-fabric-mc1.20-2.25.jarPatchouli-1.20.1-84-FABRIC.jarporting_lib-2.1.1175+1.20.1.jar*qfapi-7.4.0_qsl-6.1.2_fapi-0.90.0_mc-1.20.1.jar*quilt-kotlin-libraries-2.1.3+kt.1.9.10+flk.1.10.10.jartrinkets-3.7.1.jarwthit-quilt-8.4.3.jar
Mods marked with a * are noted to have a mixin targetting net/minecraft/world/level/storage/loot/LootTable (Mojmap) / net/minecraft/loot/LootTable (Yarn).
I'm fairly certain this issue is caused by, or at least related to Botania and/or Porting Lib, as removing either mod results in the issue resolving itself, even after several other changes to the mod set.
Notes
Another Fabric-based 1.20.1 modpack, All of Fabric 7, appears to have also had this issue after adding Botania and Create (and thus Porting Lib): TeamAOF/All-of-Fabric-7#66
According to their Discord guild, this is apparently a recurring issue - though it seems to only occur after their server(s) have been running for a while (instead of immediately), and is usually fixed by restarting the server. Neither is the case for me.
Links to some relevant messages in said Discord guild: 2024-01-07, 2024-01-04, 2024-01-04, 2023-12-31 (with relevant discussion)
Tested ^ on Fabric 0.15.7 with only Botania (+libs) and CraftTweaker with multiple launches, and Loot Tables were working. The export:
public void method_328(class_47 $$0, Consumer<class_1799> $$1) {
$$1 = this.localvar$blg000$porting_lib_loot$wrapConsumer($$1);
$$1 = this.localvar$zhm000$botania$filterDisposables($$1, $$0);
$$1 = this.localvar$zlg000$crafttweaker$getRandomItemsRaw$injectCapturingConsumer($$1, $$0);
class_47.class_8487<?> $$2 = class_47.method_51185(this);
if ($$0.method_298($$2)) {
Consumer<class_1799> $$3 = class_117.method_513(this.field_945, $$1, $$0);
class_55[] var5 = this.field_943;
int var6 = var5.length;
for(int var7 = 0; var7 < var6; ++var7) {
class_55 $$4 = var5[var7];
$$4.method_341($$3, $$0);
}
$$0.method_295($$2);
} else {
field_946.warn("Detected infinite loop in loot tables");
}
this.handler$zhm000$botania$addGogSeeds($$0, $$1, (CallbackInfo)null);
this.handler$zlg000$crafttweaker$getRandomItemsRaw$runLootModifiers($$0, $$1, (CallbackInfo)null);
this.handler$blh000$porting_lib_loot$finishCollectingLoot($$0, $$1, (CallbackInfo)null);
}
(keep in mind this is just for one launch and tested without Quilt, but previously this would have effected Fabric too)
If I may suggest, if this is the fix you've been looking for, pushing an update to Create-Fabric since those PortingLib jar-in-jars are quite old? Thanks!
an update has been in the works for months.
Please do one more test with this build, I figured out a much more sensical method
Still works.
public void method_328(class_47 $$0, Consumer<class_1799> $$1) {
$$1 = this.localvar$blg000$porting_lib_loot$wrapConsumer($$1);
$$1 = this.localvar$zhm000$botania$filterDisposables($$1, $$0);
$$1 = this.localvar$zlg000$crafttweaker$getRandomItemsRaw$injectCapturingConsumer($$1, $$0);
class_47.class_8487<?> $$2 = class_47.method_51185(this);
if ($$0.method_298($$2)) {
Consumer<class_1799> $$3 = class_117.method_513(this.field_945, $$1, $$0);
class_55[] var5 = this.field_943;
int var6 = var5.length;
for(int var7 = 0; var7 < var6; ++var7) {
class_55 $$4 = var5[var7];
$$4.method_341($$3, $$0);
}
$$0.method_295($$2);
} else {
field_946.warn("Detected infinite loop in loot tables");
}
this.handler$zhm000$botania$addGogSeeds($$0, $$1, (CallbackInfo)null);
this.handler$zlg000$crafttweaker$getRandomItemsRaw$runLootModifiers($$0, $$1, (CallbackInfo)null);
this.handler$blh000$porting_lib_loot$finishCollectingLoot($$0, $$1, (CallbackInfo)null);
}
I cannot reproduce with Fabric Loader 0.14.2 OR 0.15.3, porting_lib-2.1.1168+1.20.1 OR porting_lib-2.1.1175+1.20.1, and Botania-1.20.1-443-FABRIC. It seems to me like Quilt or QFAPI may be involved.
Just to be clear (and to help with finding the issue), Create Fabric's portinglib jars are not necessarily the same versions. As of writing, the portinglib jars inside of the latest Create Fabric (pictured here on the left) are at least 4 months old

I think the AoF7 issue may be unrelated entirely.
With further testing, I cannot get this issue to occur under Fabric. The issue, then, is likely a three-way incompatibility between Botania, Porting Lib, and QFAPI or QSL. Great!!
I exported class_52 (LootTable) using Mixin's debug features twice: once when loot tables were working, and once when they were not.
This is method_328 (getRandomItemsRaw (Mojmap) / generateUnprocessedLoot (Yarn)) when loot tables are working:
public void method_328(class_47 $$0, Consumer<class_1799> $$1) {
$$1 = this.localvar$bif000$botania$filterDisposables($$1, $$0);
$$1 = this.localvar$cff000$porting_lib_loot$wrapConsumer($$1);
class_8487<?> $$2 = class_47.method_51185(this);
if ($$0.method_298($$2)) {
Consumer<class_1799> $$3 = class_117.method_513(this.field_945, $$1, $$0);
for(class_55 $$4 : this.field_943) {
$$4.method_341($$3, $$0);
}
$$0.method_295($$2);
} else {
field_946.warn("Detected infinite loop in loot tables");
}
this.handler$bif000$botania$addGogSeeds($$0, $$1, null);
this.handler$cff000$porting_lib_loot$finishCollectingLoot($$0, $$1, null);
}...and this is that method when loot tables are not working:
public void method_328(class_47 $$0, Consumer<class_1799> $$1) {
$$1 = this.localvar$bmd000$porting_lib_loot$wrapConsumer($$1);
$$1 = this.localvar$bpa000$botania$filterDisposables($$1, $$0);
class_8487<?> $$2 = class_47.method_51185(this);
if ($$0.method_298($$2)) {
Consumer<class_1799> $$3 = class_117.method_513(this.field_945, $$1, $$0);
for(class_55 $$4 : this.field_943) {
$$4.method_341($$3, $$0);
}
$$0.method_295($$2);
} else {
field_946.warn("Detected infinite loop in loot tables");
}
this.handler$bmd000$porting_lib_loot$finishCollectingLoot($$0, $$1, null);
this.handler$bpa000$botania$addGogSeeds($$0, $$1, null);
}If I'm reading it correctly, loot tables work when Botania is loaded before Porting Lib, but not when Porting Lib is loaded before Botania.
Maybe one of the mixins can have its priority changed, and we can just call it a day...
Could you test this build and see if it's fixed?
Could you test this build and see if it's fixed?
Nope, the issue persists.
Here's method_328 with that build:
public void method_328(class_47 $$0, Consumer<class_1799> $$1) {
$$1 = this.localvar$bme000$porting_lib_loot$wrapConsumer($$1);
$$1 = this.localvar$bpb000$botania$filterDisposables($$1, $$0);
class_8487<?> $$2 = class_47.method_51185(this);
if ($$0.method_298($$2)) {
Consumer<class_1799> $$3 = class_117.method_513(this.field_945, $$1, $$0);
for(class_55 $$4 : this.field_943) {
$$4.method_341($$3, $$0);
}
$$0.method_295($$2);
} else {
field_946.warn("Detected infinite loop in loot tables");
}
this.handler$bpb000$botania$addGogSeeds($$0, $$1, null);
this.handler$bmf000$porting_lib_loot$finishCollectingLoot($$0, $$1, null);
}Are the mixin priorities backwards...?
This could be fixed on botania's end by setting their mixin priority to be even earlier than porting lib's, like 50. But #77 exists, probably because CT is doing the same thing as botania.
This approach is causing a lot of problems but I can't think of a better one.
That would only fix it for botania, and cause other problems.
In the general case, wrapping should apply as early as possible to catch all modded use of the consumer. Botania is an exception to this, where it should apply after.
However, to apply after botania, that needs a priority > default, because that's what it uses. That means it will also apply after pretty much every other mod too.
I think I have a way to fix this (for CT too), but it requires botania lowering it's priority (<1000).
Actually, that shouldn't be needed I'm pretty sure. I should try actually implementing it
Would it not be sufficient to just make Porting Lib's LootTable mixins apply last? (by setting the priority lower than 1000)
That way, Botania can do its thing to the original consumer, then Porting Lib can take over, instead of the other way around (which is what causes issues, I think).
I'm not sure how that would work with CraftTweaker, though...
Botania's mixin:
https://github.com/VazkiiMods/Botania/blob/c70b5d12aefa8bfe899d1b71006b83df11271e5f/Xplat/src/main/java/vazkii/botania/mixin/LootTableMixin.java
CraftTweaker's mixin:
https://github.com/CraftTweaker/CraftTweaker/blob/4d52fac7a96d2812bebd94d14fc020f7235e2e6f/Fabric/src/main/java/com/blamejared/crafttweaker/mixin/common/transform/loot/MixinLootTable.java
Could you test this build with CT and botania? And can you get a new mixin export of the method