Fabric API

Fabric API

106M Downloads

Default item component modifications do not apply to the FoodComponent#usingConvertsTo item stack

haykam821 opened this issue ยท 0 comments

commented

When an ItemStack is constructed, the default components of the item are copied into the item stack's components map. This detail is normally not an issue, since stacks are usually created after item registration has completed and the DefaultItemComponentEvents.MODIFY event is invoked.

However, one notable exception is the 'using converts to' stack of the minecraft:food component, introduced in Minecraft snapshot 24w19a. Since this item stack is part of an item's components, it exists before item registration completes. As a result, any component modifications will not affect this item stack.

Reproduction Steps

As a minimal example, this code modifies bowls to be resistant to fire:

DefaultItemComponentEvents.MODIFY.register(context -> {
	context.modify(Items.BOWL, builder -> {
		builder.add(DataComponentTypes.FIRE_RESISTANT, Unit.INSTANCE);
	});
});

Obtain two bowls to demonstrate the issue:

  • One from eating a stew or soup
  • Another from a different method, such as /give

Notice that these bowls do not stack, and only the latter bowl is resistant to fire. However, running /data get entity @s Inventory reveals that they have the same NBT representation, and reloading the world correctly makes the first bowl resistant to fire.

If you are having trouble reproducing this issue, note that interacting with the first bowl in creative mode can cause the item stack to be recreated (CreativeInventoryActionC2SPacket). Since networking recreates item stacks, default components appear correct for the client.

Proposed Solutions

A fix for this issue would have to consider whether other instances of item stacks in components, such as in component types added by mods, should be resolved automatically as well.

The following mixin fixes this specific issue in Minecraft snapshot 24w20a, though it may not be the ideal solution:

@Mixin(PlayerEntity.class)
public class PlayerEntityMixin {
	@Redirect(method = "eatFood", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;copy()Lnet/minecraft/item/ItemStack;"))
	private ItemStack fixUsingConvertsToStackComponents(ItemStack usingConvertsTo) {
		return usingConvertsTo.withItem(usingConvertsTo.getItem());
	}
}