diff --git a/patches/net/minecraft/world/inventory/FurnaceResultSlot.java.patch b/patches/net/minecraft/world/inventory/FurnaceResultSlot.java.patch index b437d67b28c..e7e60046f5d 100644 --- a/patches/net/minecraft/world/inventory/FurnaceResultSlot.java.patch +++ b/patches/net/minecraft/world/inventory/FurnaceResultSlot.java.patch @@ -1,9 +1,12 @@ --- a/net/minecraft/world/inventory/FurnaceResultSlot.java +++ b/net/minecraft/world/inventory/FurnaceResultSlot.java -@@ -49,5 +_,6 @@ +@@ -48,6 +_,9 @@ + abstractfurnaceblockentity.awardUsedRecipesAndPopExperience(serverplayer); } ++ if (this.removeCount != 0) { ++ net.neoforged.neoforge.event.EventHooks.firePlayerSmeltedEvent(this.player, p_39558_, this.removeCount); ++ } this.removeCount = 0; -+ net.neoforged.neoforge.event.EventHooks.firePlayerSmeltedEvent(this.player, p_39558_); } } diff --git a/src/main/java/net/neoforged/neoforge/event/EventHooks.java b/src/main/java/net/neoforged/neoforge/event/EventHooks.java index cca9ed385c6..bc8047bba56 100644 --- a/src/main/java/net/neoforged/neoforge/event/EventHooks.java +++ b/src/main/java/net/neoforged/neoforge/event/EventHooks.java @@ -908,8 +908,8 @@ public static void firePlayerCraftingEvent(Player player, ItemStack crafted, Con NeoForge.EVENT_BUS.post(new PlayerEvent.ItemCraftedEvent(player, crafted, craftMatrix)); } - public static void firePlayerSmeltedEvent(Player player, ItemStack smelted) { - NeoForge.EVENT_BUS.post(new PlayerEvent.ItemSmeltedEvent(player, smelted)); + public static void firePlayerSmeltedEvent(Player player, ItemStack smelted, int amountRemoved) { + NeoForge.EVENT_BUS.post(new PlayerEvent.ItemSmeltedEvent(player, smelted, amountRemoved)); } /** diff --git a/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerEvent.java b/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerEvent.java index 020c86cb0ee..66c55569e4a 100644 --- a/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerEvent.java +++ b/src/main/java/net/neoforged/neoforge/event/entity/player/PlayerEvent.java @@ -408,15 +408,21 @@ public Container getInventory() { public static class ItemSmeltedEvent extends PlayerEvent { private final ItemStack smelting; + private final int amountRemoved; - public ItemSmeltedEvent(Player player, ItemStack crafting) { + public ItemSmeltedEvent(Player player, ItemStack crafting, int amountRemoved) { super(player); this.smelting = crafting; + this.amountRemoved = amountRemoved; } public ItemStack getSmelting() { return this.smelting; } + + public int getAmountRemoved() { + return this.amountRemoved; + } } public static class PlayerLoggedInEvent extends PlayerEvent { diff --git a/tests/src/main/java/net/neoforged/neoforge/debug/crafting/CraftingEventTests.java b/tests/src/main/java/net/neoforged/neoforge/debug/crafting/CraftingEventTests.java new file mode 100644 index 00000000000..50bba2ac2e5 --- /dev/null +++ b/tests/src/main/java/net/neoforged/neoforge/debug/crafting/CraftingEventTests.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) NeoForged and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.neoforged.neoforge.debug.crafting; + +import com.mojang.blaze3d.platform.InputConstants; +import java.util.concurrent.atomic.AtomicInteger; +import net.minecraft.core.BlockPos; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.GameType; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.FurnaceBlockEntity; +import net.neoforged.neoforge.event.entity.player.PlayerEvent; +import net.neoforged.testframework.DynamicTest; +import net.neoforged.testframework.annotation.ForEachTest; +import net.neoforged.testframework.annotation.TestHolder; +import net.neoforged.testframework.gametest.EmptyTemplate; + +@ForEachTest(groups = "crafting.event") +public class CraftingEventTests { + @GameTest + @EmptyTemplate + @TestHolder(description = "Tests that ItemSmeltedEvent is fired correctly") + static void itemSmeltedEventTest(final DynamicTest test) { + AtomicInteger timesFired = new AtomicInteger(0); + test.whenEnabled(listeners -> { + listeners.forge().addListener((final PlayerEvent.ItemSmeltedEvent event) -> { + timesFired.incrementAndGet(); + var removed = event.getAmountRemoved(); + if (removed != 32) { + test.fail("Test should be removing half of a stack, yet extracted a different amount"); + } + }); + }); + test.onGameTest(helper -> { + helper.setBlock(BlockPos.ZERO, Blocks.FURNACE); + var be = helper.getBlockEntity(BlockPos.ZERO, FurnaceBlockEntity.class); + helper.assertFalse(be == null, "FurnaceBlockEntity was not found for furnace position"); + // Slot 2 is the result slot + be.setItem(2, new ItemStack(Items.IRON_INGOT, 64)); + var player = helper.makeTickingMockServerPlayerInLevel(GameType.CREATIVE); + player.openMenu(be); + // Test that right-clicking half of the stack out of the FurnaceResultSlot functions as expected + player.containerMenu.clicked(2, InputConstants.MOUSE_BUTTON_RIGHT, ClickType.PICKUP, player); + player.containerMenu.setCarried(ItemStack.EMPTY); + // Test that shift-left-clicking the rest of the stack out works (should only fire once, not twice) + player.containerMenu.clicked(2, InputConstants.MOUSE_BUTTON_LEFT, ClickType.QUICK_MOVE, player); + helper.assertTrue(timesFired.getPlain() == 2, "Event was not fired the expected number of times. Fired: " + timesFired.getPlain()); + helper.succeed(); + }); + } +}