如何开发触发方块破坏事件后向指定玩家发消息的Bukkit插件?
解决Bukkit插件BlockBreakEvent索引越界问题并完整实现监控需求
问题根源分析
- 配置文件格式错误:你的
config.yml中-me缺少短横线后的空格,YAML语法要求列表项的-后必须跟空格,否则无法被识别为列表,导致getStringList("MinePlayers")返回空列表,触发IndexOutOfBoundsException。 - 硬编码索引取值:直接通过
get(0)、get(1)获取列表元素,完全忽略列表实际长度,只要列表元素数量不足就会报错。 - 变量作用域错误:
if(m1!=null)内部重新声明Player tm1=m1;,这是局部变量,不会修改外部的tm1,导致后续调用printmsg时传入的还是初始的null。 - 未实现方块检查逻辑:原代码没有对被破坏的方块是否属于指定列表做判断,不符合需求。
完整解决方案
1. 修正配置文件 config.yml
添加监控方块列表,并修正玩家列表格式:
# 需要通知的在线玩家列表 MinePlayers: - me - someone_else # 需要监控的方块类型(使用Bukkit官方Material枚举名称) MonitoredBlocks: - DIAMOND_ORE - EMERALD_ORE - NETHERITE_ORE - COAL_ORE
2. 重构监听器代码
优化逻辑,避免索引越界,实现完整需求:
import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.plugin.Plugin; public class AntiXrayListener implements Listener { private final Plugin plugin; // 通过构造方法注入插件实例,避免静态依赖问题 public AntiXrayListener(Plugin plugin) { this.plugin = plugin; // 自动生成默认配置文件(如果不存在) plugin.saveDefaultConfig(); } @EventHandler public void onBlockBreak(BlockBreakEvent event) { Player breaker = event.getPlayer(); Block brokenBlock = event.getBlock(); Material blockType = brokenBlock.getType(); // 先检查当前方块是否在监控列表中,不在则直接返回 if (!plugin.getConfig().getStringList("MonitoredBlocks").contains(blockType.name())) { return; } // 遍历配置中的玩家列表,仅向在线玩家发送通知 for (String targetName : plugin.getConfig().getStringList("MinePlayers")) { Player targetPlayer = Bukkit.getPlayerExact(targetName); if (targetPlayer != null && targetPlayer.isOnline()) { sendMonitorMessage(targetPlayer, breaker, blockType); } } } // 封装消息发送逻辑,便于修改格式 private void sendMonitorMessage(Player target, Player breaker, Material blockType) { // 自定义消息格式,支持颜色代码(§开头) String message = String.format("§e[%s] §7破坏了一个 §b%s§7!", breaker.getName(), blockType.name()); target.sendMessage(message); } }
3. 插件主类注册监听器
在你的TestPlugin类中正确注册监听器:
import org.bukkit.plugin.java.JavaPlugin; public class TestPlugin extends JavaPlugin { @Override public void onEnable() { // 注册监听器,传入插件实例 getServer().getPluginManager().registerEvents(new AntiXrayListener(this), this); getLogger().info("方块监控插件已启用!"); } @Override public void onDisable() { getLogger().info("方块监控插件已禁用!"); } }
关键优化点
- 动态遍历玩家列表:不再依赖固定索引,无论配置中添加多少玩家都不会报错
- 提前过滤非监控方块:减少不必要的逻辑执行,提升性能
- 正确处理在线状态:仅向在线玩家发送消息,避免空指针
- 配置文件自动生成:首次运行会自动生成默认配置,无需手动创建
- 代码解耦:通过构造方法注入插件实例,避免静态调用的潜在问题
内容的提问来源于stack exchange,提问作者FR0314
相关产品推荐
相关产品推荐

