mirror of
https://github.com/PaperMC/Paper.git
synced 2025-01-03 17:52:28 +01:00
#992: Add API to get full result of crafting items
By: md_5 <git@md-5.net>
This commit is contained in:
parent
e002bc102b
commit
33f761a92c
2 changed files with 116 additions and 11 deletions
|
@ -24,7 +24,6 @@ import java.io.FileNotFoundException;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
@ -45,7 +44,6 @@ import java.util.logging.Logger;
|
|||
import java.util.stream.Collectors;
|
||||
import javax.imageio.ImageIO;
|
||||
import jline.console.ConsoleReader;
|
||||
import net.minecraft.advancements.Advancement;
|
||||
import net.minecraft.advancements.AdvancementHolder;
|
||||
import net.minecraft.commands.CommandDispatcher;
|
||||
import net.minecraft.commands.CommandListenerWrapper;
|
||||
|
@ -53,6 +51,7 @@ import net.minecraft.commands.arguments.ArgumentEntity;
|
|||
import net.minecraft.core.BlockPosition;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.core.IRegistry;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.nbt.DynamicOpsNBT;
|
||||
|
@ -94,7 +93,6 @@ import net.minecraft.world.inventory.InventoryCrafting;
|
|||
import net.minecraft.world.inventory.TransientCraftingContainer;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemWorldMap;
|
||||
import net.minecraft.world.item.crafting.IRecipe;
|
||||
import net.minecraft.world.item.crafting.RecipeCrafting;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.item.crafting.RecipeRepair;
|
||||
|
@ -170,6 +168,7 @@ import org.bukkit.craftbukkit.help.SimpleHelpMap;
|
|||
import org.bukkit.craftbukkit.inventory.CraftBlastingRecipe;
|
||||
import org.bukkit.craftbukkit.inventory.CraftCampfireRecipe;
|
||||
import org.bukkit.craftbukkit.inventory.CraftFurnaceRecipe;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemCraftResult;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemFactory;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.inventory.CraftMerchantCustom;
|
||||
|
@ -228,6 +227,7 @@ import org.bukkit.inventory.FurnaceRecipe;
|
|||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.bukkit.inventory.ItemCraftResult;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.Merchant;
|
||||
import org.bukkit.inventory.Recipe;
|
||||
|
@ -1325,8 +1325,7 @@ public final class CraftServer implements Server {
|
|||
return getServer().getRecipeManager().byKey(CraftNamespacedKey.toMinecraft(recipeKey)).map(RecipeHolder::toBukkitRecipe).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Recipe getCraftingRecipe(ItemStack[] craftingMatrix, World world) {
|
||||
private InventoryCrafting createInventoryCrafting() {
|
||||
// Create a players Crafting Inventory
|
||||
Container container = new Container(null, -1) {
|
||||
@Override
|
||||
|
@ -1345,12 +1344,21 @@ public final class CraftServer implements Server {
|
|||
}
|
||||
};
|
||||
InventoryCrafting inventoryCrafting = new TransientCraftingContainer(container, 3, 3);
|
||||
return inventoryCrafting;
|
||||
}
|
||||
|
||||
return getNMSRecipe(craftingMatrix, inventoryCrafting, (CraftWorld) world).map(RecipeHolder::toBukkitRecipe).orElse(null);
|
||||
@Override
|
||||
public Recipe getCraftingRecipe(ItemStack[] craftingMatrix, World world) {
|
||||
return getNMSRecipe(craftingMatrix, createInventoryCrafting(), (CraftWorld) world).map(RecipeHolder::toBukkitRecipe).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack craftItem(ItemStack[] craftingMatrix, World world, Player player) {
|
||||
return craftItemResult(craftingMatrix, world, player).getResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemCraftResult craftItemResult(ItemStack[] craftingMatrix, World world, Player player) {
|
||||
Preconditions.checkArgument(world != null, "world cannot be null");
|
||||
Preconditions.checkArgument(player != null, "player cannot be null");
|
||||
|
||||
|
@ -1377,13 +1385,66 @@ public final class CraftServer implements Server {
|
|||
// Call Bukkit event to check for matrix/result changes.
|
||||
net.minecraft.world.item.ItemStack result = CraftEventFactory.callPreCraftEvent(inventoryCrafting, craftResult, itemstack, container.getBukkitView(), recipe.map(RecipeHolder::toBukkitRecipe).orElse(null) instanceof RecipeRepair);
|
||||
|
||||
// Set the resulting matrix items
|
||||
for (int i = 0; i < craftingMatrix.length; i++) {
|
||||
Item remaining = inventoryCrafting.getContents().get(i).getItem().getCraftingRemainingItem();
|
||||
craftingMatrix[i] = (remaining != null) ? CraftItemStack.asBukkitCopy(remaining.getDefaultInstance()) : null;
|
||||
return createItemCraftResult(CraftItemStack.asBukkitCopy(result), inventoryCrafting, craftWorld.getHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack craftItem(ItemStack[] craftingMatrix, World world) {
|
||||
return craftItemResult(craftingMatrix, world).getResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemCraftResult craftItemResult(ItemStack[] craftingMatrix, World world) {
|
||||
Preconditions.checkArgument(world != null, "world must not be null");
|
||||
|
||||
CraftWorld craftWorld = (CraftWorld) world;
|
||||
|
||||
// Create a players Crafting Inventory and get the recipe
|
||||
InventoryCrafting inventoryCrafting = createInventoryCrafting();
|
||||
|
||||
Optional<RecipeHolder<RecipeCrafting>> recipe = getNMSRecipe(craftingMatrix, inventoryCrafting, craftWorld);
|
||||
|
||||
// Generate the resulting ItemStack from the Crafting Matrix
|
||||
net.minecraft.world.item.ItemStack itemStack = net.minecraft.world.item.ItemStack.EMPTY;
|
||||
|
||||
if (recipe.isPresent()) {
|
||||
itemStack = recipe.get().value().assemble(inventoryCrafting, craftWorld.getHandle().registryAccess());
|
||||
}
|
||||
|
||||
return CraftItemStack.asBukkitCopy(result);
|
||||
return createItemCraftResult(CraftItemStack.asBukkitCopy(itemStack), inventoryCrafting, craftWorld.getHandle());
|
||||
}
|
||||
|
||||
private CraftItemCraftResult createItemCraftResult(ItemStack itemStack, InventoryCrafting inventoryCrafting, WorldServer worldServer) {
|
||||
CraftItemCraftResult craftItemResult = new CraftItemCraftResult(itemStack);
|
||||
NonNullList<net.minecraft.world.item.ItemStack> remainingItems = getServer().getRecipeManager().getRemainingItemsFor(Recipes.CRAFTING, inventoryCrafting, worldServer);
|
||||
|
||||
// Set the resulting matrix items and overflow items
|
||||
for (int i = 0; i < remainingItems.size(); ++i) {
|
||||
net.minecraft.world.item.ItemStack itemstack1 = inventoryCrafting.getItem(i);
|
||||
net.minecraft.world.item.ItemStack itemstack2 = (net.minecraft.world.item.ItemStack) remainingItems.get(i);
|
||||
|
||||
if (!itemstack1.isEmpty()) {
|
||||
inventoryCrafting.removeItem(i, 1);
|
||||
itemstack1 = inventoryCrafting.getItem(i);
|
||||
}
|
||||
|
||||
if (!itemstack2.isEmpty()) {
|
||||
if (itemstack1.isEmpty()) {
|
||||
inventoryCrafting.setItem(i, itemstack2);
|
||||
} else if (net.minecraft.world.item.ItemStack.isSameItemSameTags(itemstack1, itemstack2)) {
|
||||
itemstack2.grow(itemstack1.getCount());
|
||||
inventoryCrafting.setItem(i, itemstack2);
|
||||
} else {
|
||||
craftItemResult.getOverflowItems().add(CraftItemStack.asBukkitCopy(itemstack2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < inventoryCrafting.getContents().size(); i++) {
|
||||
craftItemResult.setResultMatrix(i, CraftItemStack.asBukkitCopy(inventoryCrafting.getItem(i)));
|
||||
}
|
||||
|
||||
return craftItemResult;
|
||||
}
|
||||
|
||||
private Optional<RecipeHolder<RecipeCrafting>> getNMSRecipe(ItemStack[] craftingMatrix, InventoryCrafting inventoryCrafting, CraftWorld world) {
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package org.bukkit.craftbukkit.inventory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemCraftResult;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public final class CraftItemCraftResult implements ItemCraftResult {
|
||||
|
||||
private final ItemStack result;
|
||||
private final ItemStack[] resultMatrix;
|
||||
private final List<ItemStack> overflowItems;
|
||||
|
||||
public CraftItemCraftResult(ItemStack result) {
|
||||
this.result = Objects.requireNonNullElseGet(result, () -> new ItemStack(Material.AIR));
|
||||
this.resultMatrix = new ItemStack[9];
|
||||
this.overflowItems = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < resultMatrix.length; i++) {
|
||||
resultMatrix[i] = new ItemStack(Material.AIR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack[] getResultingMatrix() {
|
||||
return resultMatrix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getOverflowItems() {
|
||||
return overflowItems;
|
||||
}
|
||||
|
||||
public void setResultMatrix(int i, ItemStack itemStack) {
|
||||
resultMatrix[i] = Objects.requireNonNullElseGet(itemStack, () -> new ItemStack(Material.AIR));
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue