Bukkit插件问题:点击橡木按钮无法销毁按钮及下方煤炭块求助
问题与解决:点击橡木按钮销毁自身及下方煤炭块(无掉落物)
问题描述
我希望实现点击橡木按钮时,销毁该橡木按钮及其下方的煤炭块,且煤炭块无需产生掉落物。但实际运行时触发了空指针异常,且使用getDrops().clear()无法阻止煤炭块掉落物生成。
原代码
package me.doshicshow.mycustomitems; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.block.BlockFace; import org.bukkit.block.Block; import java.util.logging.Logger; public class Customitems extends JavaPlugin implements Listener { private static Logger log = Logger.getLogger("Minecraft"); @Override public void onEnable() { getServer().getPluginManager().registerEvents(this, this); } @EventHandler public void onPlayerInteract(PlayerInteractEvent event) { if (event.getClickedBlock() != null && event.getClickedBlock().getType() == Material.OAK_BUTTON && event.getClickedBlock().getRelative(BlockFace.DOWN).getType() == Material.COAL_BLOCK) { log.info(String.format("Found object %s", event.getClickedBlock())); event.getClickedBlock().breakNaturally(); event.getClickedBlock().getDrops().clear(); event.getClickedBlock().getRelative(BlockFace.DOWN).getDrops().clear(); event.getClickedBlock().getRelative(BlockFace.DOWN).breakNaturally(); } } }
问题分析
- 空指针异常原因:调用
breakNaturally()后,方块已被销毁,此时再通过event.getClickedBlock()获取方块并调用getDrops(),会因为方块不存在触发空指针。 getDrops().clear()无效原因:getDrops()返回的是当前方块掉落物的副本集合,清空副本不会影响实际掉落;且breakNaturally()调用时就已经生成了掉落物,后续清空操作完全无效。
修改后的代码
package me.doshicshow.mycustomitems; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.plugin.java.JavaPlugin; import java.util.logging.Logger; public class Customitems extends JavaPlugin implements Listener { private static final Logger log = Logger.getLogger("Minecraft"); @Override public void onEnable() { getServer().getPluginManager().registerEvents(this, this); } @EventHandler public void onPlayerInteract(PlayerInteractEvent event) { Block clickedBlock = event.getClickedBlock(); // 先判空并检查是否为橡木按钮 if (clickedBlock == null || clickedBlock.getType() != Material.OAK_BUTTON) { return; } Block coalBlock = clickedBlock.getRelative(BlockFace.DOWN); // 检查下方是否为煤炭块 if (coalBlock.getType() != Material.COAL_BLOCK) { return; } log.info(String.format("Found object %s", clickedBlock)); // 直接设为AIR移除方块,无掉落物 clickedBlock.setType(Material.AIR); coalBlock.setType(Material.AIR); } }
修改说明
- 提前获取方块引用:先把橡木按钮和下方煤炭块的引用存起来,避免销毁后找不到对象导致空指针。
- 用
setType(Material.AIR)替代breakNaturally():这个方法直接移除方块,不会触发任何掉落物生成,完美满足煤炭块无掉落的需求;如果需要橡木按钮正常产生掉落,把clickedBlock.setType(Material.AIR)替换为clickedBlock.breakNaturally()即可。 - 拆分判断条件:减少嵌套层级,代码更易读,也能提前过滤不符合条件的情况。
内容的提问来源于stack exchange,提问作者Doshic
相关产品推荐
相关产品推荐

