Minecraft Java插件问题:信标位置显示一致但破坏检测不生效
解决Minecraft信标破坏检测失效的问题
我一眼就看出问题出在Block对象的比对方式上了——你现在存储的是Block实例,但Java里对象比对用的是引用,不是实际的位置坐标。哪怕两个Block的x/y/z完全一样,它们也是不同的对象,所以beaconStore.containsValue(block)永远找不到匹配项,哪怕你输出位置看起来完全一致。
下面是具体的修复方案,分两步走:
1. 把存储的Block换成Location
别存Block对象了,改成存Location(位置对象),它专门用来表示方块的坐标和所在世界,而且自带正确的equals比对逻辑。
修改你的存储集合定义:
// 原来的: // public HashMap<Integer, Block> beaconStore = new HashMap<>(); // 改成: public HashMap<Integer, Location> beaconStore = new HashMap<>();
然后在从配置文件读取信标位置时,把读取到的世界名、x/y/z转换成Location存进去:
// 举个例子,假设你从config里读出来的是这些值 String worldName = getConfig().getString("beacons." + id + ".world"); double x = getConfig().getDouble("beacons." + id + ".x"); double y = getConfig().getDouble("beacons." + id + ".y"); double z = getConfig().getDouble("beacons." + id + ".z"); World world = Bukkit.getWorld(worldName); Location beaconLoc = new Location(world, x, y, z); beaconStore.put(id, beaconLoc);
2. 修改破坏事件的检测逻辑
在BlockBreakEvent里,获取被破坏方块的Location,然后和存储的Location比对就行——Location的equals()方法会自动帮你比对世界和坐标,完全符合需求:
@EventHandler public void onBlockBreak(BlockBreakEvent event) { Block brokenBlock = event.getBlock(); Location brokenLoc = brokenBlock.getLocation(); // 遍历存储的所有信标位置 for (Map.Entry<Integer, Location> entry : beaconStore.entrySet()) { Location storedLoc = entry.getValue(); if (brokenLoc.equals(storedLoc)) { // 找到了匹配的信标!执行你的业务逻辑 event.getPlayer().sendMessage("检测到被破坏的信标,ID:" + entry.getKey()); // 比如从集合里移除这个信标,或者更新配置文件 beaconStore.remove(entry.getKey()); saveConfig(); break; } } }
额外提醒
之前存Block对象还有个隐藏坑:服务器重启后,这些Block实例会失效,因为Block是和当前服务器运行时绑定的。换成Location就没这个问题,因为它可以轻松序列化到配置文件,重启后也能正确读取。
内容的提问来源于stack exchange,提问作者EssemCSH




