You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动