Spigot InventoryClickEvent空指针异常求助:特殊工作台配方检测异常
解决Spigot特殊工作台InventoryClickEvent的NullPointerException问题
我来帮你分析并解决这个困扰你的问题——从错误日志和描述来看,这个异常的核心原因很明确,咱们一步步拆解:
问题根源
你遇到的IllegalArgumentException: Result cannot be null其实是Bukkit.getRecipesFor()方法抛出的参数校验错误:当你放置第一个物品时,代码传入了null作为这个方法的参数。
看你控制台的第一次输出,全是null的数组,说明此时代码尝试读取的槽位数据还没更新——Spigot的InventoryClickEvent触发时机是在物品完成槽位放置之前,所以刚放第一个物品时,直接读取槽位会拿到更新前的空值,传入getRecipesFor()就触发了非空校验异常。而放第二个物品时,第一个物品已经稳定在槽位里,读取到的不是null,所以能正常执行。
具体修复方案
1. 先做Null校验,再调用配方API
在调用Bukkit.getRecipesFor()之前,必须先检查目标物品栈是否非null,避免触发参数错误:
// 假设你要读取合成槽的某个物品 ItemStack inputItem = event.getInventory().getItem(slotIndex); if (inputItem != null) { List<Recipe> matchingRecipes = Bukkit.getRecipesFor(inputItem); // 后续的配方匹配逻辑 } else { // 槽位为空时,跳过配方查询或者给出提示 return; }
2. 延迟读取槽位数据,确保物品放置完成
因为事件触发时物品还没真正放到槽位里,咱们可以延迟1 tick再执行配方查询,这样能拿到更新后的正确数据:
// 替换yourPluginInstance为你的插件主类实例 Bukkit.getScheduler().runTaskLater(yourPluginInstance, () -> { Inventory workbenchInv = event.getInventory(); ItemStack[] inputSlots = new ItemStack[9]; // 假设你的特殊工作台前9格是输入槽 for (int i = 0; i < 9; i++) { inputSlots[i] = workbenchInv.getItem(i); } // 在这里执行配方匹配逻辑,不管是原版还是自定义配方 }, 1L);
3. 分离自定义配方的匹配逻辑
自定义配方没必要依赖Bukkit.getRecipesFor(),建议提前把自定义配方存在一个Map里,比如用输入物品的组合作为Key,结果物品作为Value:
// 初始化自定义配方(可以在插件加载时完成) Map<List<ItemStack>, ItemStack> customRecipes = new HashMap<>(); // 示例:添加一个自定义配方,比如3个橡木木板换一个石剑 customRecipes.put(Arrays.asList(new ItemStack(Material.OAK_PLANKS), new ItemStack(Material.OAK_PLANKS), new ItemStack(Material.OAK_PLANKS)), new ItemStack(Material.STONE_SWORD)); // 匹配时直接遍历输入槽对比 List<ItemStack> currentInput = Arrays.asList(inputSlots); if (customRecipes.containsKey(currentInput)) { // 匹配到自定义配方,设置结果槽物品 workbenchInv.setItem(9, customRecipes.get(currentInput)); }
额外调试建议
- 打印日志时,别只输出数组,加上槽位索引和物品类型,能更清楚定位问题:
ItemStack[] contents = workbenchInv.getContents(); for (int i = 0; i < contents.length; i++) { ItemStack item = contents[i]; Bukkit.getLogger().info("槽位 " + i + ": " + (item == null ? "空" : item.getType().name())); } - 记得在事件监听里先判断当前打开的是不是你的特殊工作台,避免误处理普通工作台的事件:
if (!event.getView().getTitle().equals("你的特殊工作台标题")) { return; }
内容的提问来源于stack exchange,提问作者F4LS3
相关产品推荐
相关产品推荐

