Skip to content

Commit 167c7d0

Browse files
committed
Fix handling of resultant crafting container from craftItemResult (Fixes #12300)
The result object of overhanging items is based upon a derived view of the provided crafting slots, meaning that we need to consider this when handing back the resultant slots
1 parent 6ea4202 commit 167c7d0

File tree

2 files changed

+67
-18
lines changed

2 files changed

+67
-18
lines changed

paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java

+27-17
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
import net.minecraft.world.inventory.TransientCraftingContainer;
8888
import net.minecraft.world.item.Item;
8989
import net.minecraft.world.item.MapItem;
90+
import net.minecraft.world.item.crafting.CraftingInput;
9091
import net.minecraft.world.item.crafting.CraftingRecipe;
9192
import net.minecraft.world.item.crafting.RecipeHolder;
9293
import net.minecraft.world.item.crafting.RecipeType;
@@ -1765,25 +1766,34 @@ public ItemCraftResult craftItemResult(ItemStack[] craftingMatrix, World world)
17651766

17661767
private CraftItemCraftResult createItemCraftResult(Optional<RecipeHolder<CraftingRecipe>> recipe, ItemStack itemStack, CraftingContainer inventoryCrafting, ServerLevel worldServer) {
17671768
CraftItemCraftResult craftItemResult = new CraftItemCraftResult(itemStack);
1768-
recipe.map((holder) -> holder.value().getRemainingItems(inventoryCrafting.asCraftInput())).ifPresent((remainingItems) -> {
1769-
// Set the resulting matrix items and overflow items
1770-
for (int i = 0; i < remainingItems.size(); ++i) {
1771-
net.minecraft.world.item.ItemStack itemstack1 = inventoryCrafting.getItem(i);
1772-
net.minecraft.world.item.ItemStack itemstack2 = (net.minecraft.world.item.ItemStack) remainingItems.get(i);
1769+
// tl;dr: this is an API adopted implementation of ResultSlot#onTake
1770+
final CraftingInput.Positioned positionedCraftInput = inventoryCrafting.asPositionedCraftInput();
1771+
final CraftingInput craftingInput = positionedCraftInput.input();
1772+
recipe.map((holder) -> holder.value().getRemainingItems(craftingInput)).ifPresent((remainingItems) -> {
17731773

1774-
if (!itemstack1.isEmpty()) {
1775-
inventoryCrafting.removeItem(i, 1);
1776-
itemstack1 = inventoryCrafting.getItem(i);
1777-
}
17781774

1779-
if (!itemstack2.isEmpty()) {
1780-
if (itemstack1.isEmpty()) {
1781-
inventoryCrafting.setItem(i, itemstack2);
1782-
} else if (net.minecraft.world.item.ItemStack.isSameItemSameComponents(itemstack1, itemstack2)) {
1783-
itemstack2.grow(itemstack1.getCount());
1784-
inventoryCrafting.setItem(i, itemstack2);
1785-
} else {
1786-
craftItemResult.getOverflowItems().add(CraftItemStack.asBukkitCopy(itemstack2));
1775+
System.out.println(remainingItems.stream().map(Object::toString).toList());
1776+
// Set the resulting matrix items and overflow items
1777+
for (int h = 0; h < craftingInput.height(); h++) {
1778+
for (int w = 0; w < craftingInput.width(); w++) {
1779+
final int inventorySlot = w + positionedCraftInput.left() + (h + positionedCraftInput.top()) * inventoryCrafting.getWidth();
1780+
net.minecraft.world.item.ItemStack itemstack1 = inventoryCrafting.getItem(inventorySlot);
1781+
net.minecraft.world.item.ItemStack itemstack2 = remainingItems.get(w + h * craftingInput.width());
1782+
1783+
if (!itemstack1.isEmpty()) {
1784+
inventoryCrafting.removeItem(inventorySlot, 1);
1785+
itemstack1 = inventoryCrafting.getItem(inventorySlot);
1786+
}
1787+
1788+
if (!itemstack2.isEmpty()) {
1789+
if (itemstack1.isEmpty()) {
1790+
inventoryCrafting.setItem(inventorySlot, itemstack2);
1791+
} else if (net.minecraft.world.item.ItemStack.isSameItemSameComponents(itemstack1, itemstack2)) {
1792+
itemstack2.grow(itemstack1.getCount());
1793+
inventoryCrafting.setItem(inventorySlot, itemstack2);
1794+
} else {
1795+
craftItemResult.getOverflowItems().add(CraftItemStack.asBukkitCopy(itemstack2));
1796+
}
17871797
}
17881798
}
17891799
}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,53 @@
11
package io.papermc.testplugin;
22

3+
import io.papermc.paper.command.brigadier.Commands;
4+
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents;
5+
import net.kyori.adventure.text.Component;
6+
import org.apache.logging.log4j.util.Strings;
7+
import org.bukkit.Bukkit;
8+
import org.bukkit.Material;
9+
import org.bukkit.entity.Player;
310
import org.bukkit.event.Listener;
11+
import org.bukkit.inventory.ItemCraftResult;
12+
import org.bukkit.inventory.ItemStack;
413
import org.bukkit.plugin.java.JavaPlugin;
14+
import java.util.Arrays;
515

616
public final class TestPlugin extends JavaPlugin implements Listener {
717

818
@Override
919
public void onEnable() {
1020
this.getServer().getPluginManager().registerEvents(this, this);
11-
21+
Bukkit.getLogger().info("TestPlugin enabled");
1222
// io.papermc.testplugin.brigtests.Registration.registerViaOnEnable(this);
23+
24+
this.getLifecycleManager().registerEventHandler(
25+
LifecycleEvents.COMMANDS.newHandler((handler) -> {
26+
handler.registrar().register(Commands.literal("testcraft").executes(context -> {
27+
if (context.getSource().getSender() instanceof Player player) {
28+
ItemStack bottle = ItemStack.of(Material.HONEY_BOTTLE);
29+
ItemStack air = ItemStack.empty();
30+
31+
ItemStack[] craftingGrid = {
32+
air.clone(), bottle.clone(), bottle.clone(),
33+
air.clone(), bottle.clone(), bottle.clone(),
34+
air.clone(), air.clone(), air.clone()
35+
};
36+
37+
ItemCraftResult result = Bukkit.craftItemResult(
38+
craftingGrid,
39+
player.getWorld(),
40+
player
41+
);
42+
ItemStack[] resultingMatrix = result.getResultingMatrix();
43+
player.sendMessage(Component.text(Arrays.toString(resultingMatrix)));
44+
}
45+
return 1;
46+
}).build());
47+
})
48+
);
49+
50+
51+
1352
}
1453
}

0 commit comments

Comments
 (0)