Fix Complex Recipes

Complex recipes were using the new Bukkit.craftItem() method which modifies the input recipe. So a copy of the matrix needs to made before hand to prevent it being modified. (The result is available in the CraftingResult record)
This commit is contained in:
James Peters 2021-12-20 16:23:08 +00:00
parent fa22a8b55a
commit 9ad0e41c6b
4 changed files with 14 additions and 38 deletions

View File

@ -2,30 +2,4 @@ package com.jamesdpeters.minecraft.chests;
import org.bukkit.inventory.ItemStack;
public class CraftingResult {
ItemStack result;
ItemStack[] matrixResult;
public CraftingResult(ItemStack result, ItemStack[] matrixResult) {
this.result = result;
this.matrixResult = matrixResult;
}
public CraftingResult() {}
public ItemStack[] getMatrixResult() {
return matrixResult;
}
public void setMatrixResult(ItemStack[] matrixResult) {
this.matrixResult = matrixResult;
}
public ItemStack getResult() {
return result;
}
public void setResult(ItemStack result) {
this.result = result;
}
}
public record CraftingResult(ItemStack result, ItemStack[] matrixResult) {}

View File

@ -8,15 +8,17 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.Recipe;
import java.util.Arrays;
public class Crafting implements CraftingProvider {
@Override
public CraftingResult craft(Player player, World world, ItemStack[] items) {
var item = Bukkit.craftItem(items, world, player);
CraftingResult result = new CraftingResult();
result.setResult(item);
result.setMatrixResult(items);
return result;
// Create copy of array since Bukkit#craftItem modifies the input array.
ItemStack[] itemsCopy = Arrays.copyOf(items, items.length);
var item = Bukkit.craftItem(itemsCopy, world, player);
return new CraftingResult(item, itemsCopy);
}
@Override

View File

@ -106,7 +106,7 @@ public class VirtualCraftingHolder implements InventoryHolder {
else if (recipe instanceof ShapelessRecipe) setCrafting((ShapelessRecipe) recipe);
else {
// For ComplexRecipes or other implementations just use the result and original matrix for choices.
result = ApiSpecific.getNmsProvider().getCraftingProvider().craft(storage.getOwner().getPlayer(), Bukkit.getWorlds().get(0), matrix).getResult();
result = ApiSpecific.getNmsProvider().getCraftingProvider().craft(storage.getOwner().getPlayer(), Bukkit.getWorlds().get(0), matrix).result();
for (int i = 0; i < matrix.length; i++) {
ItemStack item = matrix[i];
if (item != null) {
@ -419,20 +419,20 @@ public class VirtualCraftingHolder implements InventoryHolder {
// PrepareItemCraftEvent itemCraftEvent = new PrepareItemCraftEvent(craftingInventoryImpl, inventoryView, false);
// Bukkit.getPluginManager().callEvent(itemCraftEvent);
if (craftingResult.getResult() == null) return false;
if (craftingResult.result() == null) return false;
//If we reach here there are enough materials so check for space in the Hopper and update inventory.
//Check if output and input are the same inventory to avoid duplication.
Inventory tempOutput = sameInv ? sameInventory : Utils.copyInventory(output);
HashMap<Integer, ItemStack> map = tempOutput.addItem(craftingResult.getResult());
HashMap<Integer, ItemStack> map = tempOutput.addItem(craftingResult.result());
boolean isEmpty = Arrays.stream(craftingResult.getMatrixResult())
boolean isEmpty = Arrays.stream(craftingResult.matrixResult())
.anyMatch(itemStack -> (itemStack == null || itemStack.getType() == Material.AIR));
// Add any leftover items from the recipe e.g buckets.
HashMap<Integer, ItemStack> craftingMatrixLeftOvers =
isEmpty ? Maps.newHashMap()
: tempOutput.addItem(craftingResult.getMatrixResult());
: tempOutput.addItem(craftingResult.matrixResult());
//If result fits into output copy over the temporary inventories.
if (map.isEmpty() && craftingMatrixLeftOvers.isEmpty()) {

View File

@ -1,4 +1,4 @@
# Chests++ Language File (Version 2.5.1-Release)
# Chests++ Language File (Version 2.5.2-BETA)
# NOTE: This file gets replaced when the plugin launches! If you want to make modifications create a copy first!
# To create a new language file simply create a copy of this file and rename it to your desired choice for example 'en_US.properties'
# It should be located in the 'lang' folder