PrepareItemCraftEvent问题 - 无法传递事件PrepareItemCraftEvent

时间:2015-06-27 21:06:50

标签: java minecraft bukkit

有没有人知道为什么这个事件不起作用?

OnEnable Code:

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调用:

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。

1 个答案:

答案 0 :(得分:1)

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

  1. 制作矩阵中的一个插槽是空的
  2. 矩阵中的一个项目没有传说文本或元数据
  3. 制作广告资源的结果广告位也是空的
  4. 我会添加空检查,以确保您不使用不存在的项目或元数据。

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

    您将遇到的第一个问题是形状配方(将9个鹅卵石变成压缩物品的配方)。由于成分仅使用材料定义,玩家可以使用9“压缩”鹅卵石来制作另一个,有效地移除72个鹅卵石。要解决这个问题,每当所有9个工艺槽都装满鹅卵石时,我们必须确保它们是“简单”的鹅卵石(没有元数据)。

    我认为你试图用你的代码修复的第二个问题是玩家将常规鹅卵石而不是压缩的鹅卵石变成9个鹅卵石,有效地重复块并给玩家额外的8个鹅卵石。正如您可能已经注意到的那样,这再一次是因为无形配方的成分只是一种材料而不是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);
        }
    }