PrepareItemCraftEvent 问题 - 无法传递事件 PrepareItemCraftEvent

PrepareItemCraftEvent Issue - Could not pass event PrepareItemCraftEvent

有谁知道为什么这个活动不起作用?

启用代码:

Bukkit.getServer().getPluginManager().registerEvents(this, this);

事件代码:

@EventHandler(priority=EventPriority.HIGH)
public void customCrafting(PrepareItemCraftEvent e){    
    ItemStack singleCompressed = new ItemStack(Material.COBBLESTONE, 1);
    ItemStack nineCobblestone = new ItemStack(Material.COBBLESTONE, 9);
    ItemMeta singleCompressedMeta = singleCompressed.getItemMeta();
    singleCompressedMeta.setDisplayName("Compressed Cobblestone");
    singleCompressedMeta.setLore(Arrays.asList("x9 Cobblestone"));
    singleCompressed.setItemMeta(singleCompressedMeta);

    if(e.getInventory() instanceof CraftingInventory){
        CraftingInventory inv = (CraftingInventory) e.getInventory();
        ItemStack[] itm = inv.getMatrix();
        boolean canCraft = false;

        if (inv.getResult().getType() == Material.COBBLESTONE) {
            for (int i = 0; i < inv.getSize(); i++) {
                if(itm[i].getItemMeta().getLore().toString().toLowerCase().equals(singleCompressed.getItemMeta().getLore().toString().toLowerCase())) {
                    canCraft = true;
                }
            }
            if (canCraft == true) {
                inv.setResult(nineCobblestone);
                canCraft = false;   
            } else { 
                inv.setResult(null);
                canCraft = false;
            }
        }
    }
}

我在 onEnable 调用的 public void 中设置了这些食谱:

ShapedRecipe singleCompressedRecipe = new ShapedRecipe(singleCompressed);
    singleCompressedRecipe.shape("@@@","@@@","@@@");
    singleCompressedRecipe.setIngredient('@', Material.COBBLESTONE);

    ItemStack nineCobblestone = new ItemStack(Material.COBBLESTONE, 9);
    ShapelessRecipe decompressedRecipe = new ShapelessRecipe(nineCobblestone);
    decompressedRecipe.addIngredient(Material.COBBLESTONE);

    Bukkit.getServer().addRecipe(singleCompressedRecipe);
    Bukkit.getServer().addRecipe(decompressedRecipe);

出于某种原因,每当我尝试相应地制作时,我的控制台中都会出现以下错误:

10:00:34 PM CONSOLE: ERROR]: Could not pass event PrepareItemCraftEvent to     CompressedBlocks v1.0
10:00:35 PM CONSOLE: Source) [?:1.7.0_60]
10:00:35 PM CONSOLE: Source) [?:1.7.0_60]
10:00:35 PM CONSOLE: Source) [?:1.7.0_60]
10:00:35 PM CONSOLE: Method) ~[?:1.7.0_60]
10:00:35 PM CONSOLE: Source) ~[?:1.7.0_60]
10:00:35 PM CONSOLE: Source) ~[?:1.7.0_60]
10:00:35 PM CONSOLE: Source) ~[?:1.7.0_60]

就游戏中发生的事情而言,您可以使用普通鹅卵石和单个压缩鹅卵石制作 9 块鹅卵石,因此事件不会影响任何事情。我试图登录到控制台:itm[i].getItemMeta().getLore().toString().toLowerCase() 并且它等于 null.

该事件很可能抛出 NullPointerException,因为:

  1. 工艺矩阵中的一个槽位是空的
  2. 矩阵中的一项没有知识文本或元数据
  3. 工艺清单的结果槽也是空的

我会添加 null 检查以确保您使用的不是不存在的项目或元数据。

您的代码的其他一些部分可以改进以使压缩鹅卵石无缝工作。

您将 运行 解决的第一个问题是成型配方(将 9 块鹅卵石变成压缩物品的配方)。由于仅使用 Material 来定义成分,因此玩家可以使用 9 "compressed" 颗鹅卵石来制作另一颗鹅卵石,从而有效移除 72 颗鹅卵石。为了解决这个问题,每当所有 9 个制作槽都装满鹅卵石时,我们必须确保它们是 "simple" 个鹅卵石(没有元数据)。

我认为您试图用您的代码解决的第二个问题是玩家将普通鹅卵石而不是压缩鹅卵石变成 9 个鹅卵石,有效地欺骗了方块并给了玩家额外的 8 个鹅卵石。正如您可能已经注意到的那样,这又是因为无形配方的成分只是一个 Material 而不是 ItemStack。下面是解决这两个问题的一些示例代码(经过测试,似乎工作得很好):

public void onEnable() {
    getServer().getPluginManager().registerEvents(this, this);

    ItemStack result = new ItemStack(Material.COBBLESTONE, 1);
    ItemMeta meta = result.getItemMeta();
    meta.setDisplayName("Compressed Cobblestone");
    meta.setLore(Arrays.asList("9x Cobblestone"));
    result.setItemMeta(meta);

    //This recipe creates the problem that one can turn 9 compressed blocks into only one
    ShapedRecipe shaped = new ShapedRecipe(result);
    shaped.shape("@@@", "@@@", "@@@");
    shaped.setIngredient('@', Material.COBBLESTONE);

    //This recipe creates the problem that we can turn a regular cobblestone into 9
    ItemStack nine = new ItemStack(Material.COBBLESTONE, 9);
    ShapelessRecipe shapeless = new ShapelessRecipe(nine);
    shapeless.addIngredient(Material.COBBLESTONE);

    Bukkit.getServer().addRecipe(shaped);
    Bukkit.getServer().addRecipe(shapeless);
}

@EventHandler
public void onPrepareCraft(PrepareItemCraftEvent event) {
    ItemStack[] slots = event.getInventory().getMatrix();

    //The item list will only contain real itemstacks
    List<ItemStack> items = new ArrayList<ItemStack>();
    for (ItemStack slot : slots) {
        if (slot != null && slot.getType() != Material.AIR) { //We filter out air slots and null items
            items.add(slot);
        }
    }

    boolean canCraft = false;
    if (items.size() == 1) { //If we are dealing with a single item
        ItemStack item = items.get(0); //Get the first item
        if (item.getType() == Material.COBBLESTONE && item.hasItemMeta()) { //If this block is cobblestone and has metadata
            ItemMeta meta = item.getItemMeta();
            //Check if the metadata contains a display name and lore
            //If so, compare them with what they should be
            if (meta.hasDisplayName() && meta.hasLore() && meta.getDisplayName().equals("Compressed Cobblestone") && meta.getLore().toString().equals(Arrays.asList("9x Cobblestone").toString())) {
                canCraft = true;
            }
        }
    } else if (items.size() == 9) { //If we are dealing with 9 items
        boolean allCobblestone = true; //We need to check whether they are all cobblestone, otherwise we would interfere with other recipes that use all 9 slots
        for (ItemStack item : items) {
            if (item.getType() != Material.COBBLESTONE) {
                //If we find a non-cobblestone block, exit loop and let the player craft whatever he is trying to make
                allCobblestone = false;
                canCraft = true;
                break;
            }
        }
        if (allCobblestone) { //If we have 9 cobblestones in the matrix make sure none of them have metadata
            canCraft = true;
            for (ItemStack item : items) {
                if (item.hasItemMeta()) {
                    canCraft = false;
                    break;
                }
            }
        }
    }

    if (!canCraft) {
        event.getInventory().setResult(null);
    }
}