From 60076f268bf39f16b9b32e9381fbbf27f4ab682a Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 21 Sep 2026 06:07:46 +0000 Subject: [PATCH 1/2] Register the damage-indicated fluid container handler at the lowest priority DamageIndicatedItemFluidContainer registers a generic FluidHandlerItemCapacity for every subclass. A subclass whose own mod registers a more specific handler for the same item ends up with two competing providers, and NeoForge returns the first registered non-null one. RegisterCapabilitiesEvent is dispatched per event priority first and per mod second, so at equal priority the winner is decided by the mod load order between cyclopscore and the subclass' mod. That order is a topological tie-break over mod file discovery order whenever the dependency declares ordering="NONE", so it shifts with the rest of the mod set. EvilCraft's creative blood drop hits this: when cyclopscore registers first, a fresh stack resolves to the generic finite handler and reports an empty container, which silently turns the item into a useless one. It showed up as a blood infuser game test failing in the bigger pack test mod sets only. This handler is a fallback, so it now registers at EventPriority.LOWEST and any subclass registration wins regardless of mod load order. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01FZV1n6KyUT6snFM4rf4hVs --- .../item/DamageIndicatedItemFluidContainer.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/item/DamageIndicatedItemFluidContainer.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/item/DamageIndicatedItemFluidContainer.java index df8019a93ea..e36c8db9d13 100644 --- a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/item/DamageIndicatedItemFluidContainer.java +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/item/DamageIndicatedItemFluidContainer.java @@ -10,6 +10,7 @@ import net.minecraft.world.item.component.TooltipDisplay; import net.minecraft.world.level.Level; import net.minecraft.world.level.material.Fluid; +import net.neoforged.bus.api.EventPriority; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent; import net.neoforged.neoforge.transfer.ResourceHandler; @@ -53,7 +54,11 @@ public DamageIndicatedItemFluidContainer(Item.Properties builder, int capacity, this.fluid = fluid; init(); - CyclopsCoreNeoForge._instance.getModEventBus().addListener(this::registerCapability); + // Register at the lowest priority: this is a generic fallback handler, so a subclass that registers + // its own fluid handler for the same item must win. NeoForge returns the first registered non-null + // provider, and RegisterCapabilitiesEvent is dispatched per priority first and per mod second, so + // without this the winner would depend on the mod load order between cyclopscore and the subclass' mod. + CyclopsCoreNeoForge._instance.getModEventBus().addListener(EventPriority.LOWEST, this::registerCapability); } private void registerCapability(RegisterCapabilitiesEvent event) { From fdac1a36d5662b6fb0cb538f3d61a669f99a13dc Mon Sep 17 00:00:00 2001 From: Ruben Taelman Date: Mon, 21 Sep 2026 16:36:32 +0200 Subject: [PATCH 2/2] Apply suggestion from @rubensworks --- .../cyclopscore/item/DamageIndicatedItemFluidContainer.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/item/DamageIndicatedItemFluidContainer.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/item/DamageIndicatedItemFluidContainer.java index e36c8db9d13..d17be508bc4 100644 --- a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/item/DamageIndicatedItemFluidContainer.java +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/item/DamageIndicatedItemFluidContainer.java @@ -54,10 +54,7 @@ public DamageIndicatedItemFluidContainer(Item.Properties builder, int capacity, this.fluid = fluid; init(); - // Register at the lowest priority: this is a generic fallback handler, so a subclass that registers - // its own fluid handler for the same item must win. NeoForge returns the first registered non-null - // provider, and RegisterCapabilitiesEvent is dispatched per priority first and per mod second, so - // without this the winner would depend on the mod load order between cyclopscore and the subclass' mod. + // Register at lowest priority to allow other mods to override it. CyclopsCoreNeoForge._instance.getModEventBus().addListener(EventPriority.LOWEST, this::registerCapability); }