You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bukkit 1.17.1通过飞行寻路计算玩家非固体路径距离实现聊天隔墙屏蔽

Bukkit 1.17.1 近场聊天遮挡判定解决方案

方案1:原生视线检测(推荐,性能更高)

你的需求本质是判断两名玩家之间是否存在固体方块遮挡,直接使用Bukkit原生提供的视线检测方法即可实现,无需调用复杂的NMS寻路接口,性能损耗极低,兼容性更好。
实现代码如下:

@EventHandler
public void onAsyncPlayerChat(AsyncPlayerChatEvent e) {
    Player sender = e.getPlayer();
    Location senderLoc = sender.getLocation();
    World world = senderLoc.getWorld();
    if (world == null) return;
    // 最大可接收聊天的距离阈值,单位为方块
    final double MAX_CHAT_DISTANCE = 100D;
    // 使用迭代器安全移除接收者
    Iterator<Player> receiverIter = e.getRecipients().iterator();
    while (receiverIter.hasNext()) {
        Player receiver = receiverIter.next();
        // 不同世界直接移除
        if (!receiver.getWorld().equals(world)) {
            receiverIter.remove();
            continue;
        }
        // 距离超过阈值直接移除
        double distance = senderLoc.distance(receiver.getLocation());
        if (distance > MAX_CHAT_DISTANCE) {
            receiverIter.remove();
            continue;
        }
        // 无视线通路直接移除
        if (!sender.hasLineOfSight(receiver)) {
            receiverIter.remove();
        }
    }
}

方案2:PathfinderFlying 正确获取路径长度方法

如果你确实需要计算非直线的可通行空气路径长度(比如允许玩家绕开小障碍物接收消息的场景),可以使用NMS寻路接口,你之前的调用方式存在两处问题:

  1. ChunkCache的Y轴范围设置错误,固定为0会导致高度不同的路径完全无法计算
  2. 你调用的a(PathPoint[] var0, PathPoint var1)是A*寻路内部的启发式估值方法,并非实际路径长度计算接口,所以会返回固定值

正确实现代码如下:

@EventHandler
public void onAsyncPlayerChat(AsyncPlayerChatEvent e) {
    Player sender = e.getPlayer();
    Location start = sender.getLocation();
    World bukkitWorld = start.getWorld();
    if (bukkitWorld == null) return;
    net.minecraft.world.level.World nmsWorld = ((CraftPlayer) sender).getHandle().getWorld();
    // 最大路径长度阈值、寻路范围阈值
    final int MAX_PATH_LENGTH = 100;
    final int SEARCH_RANGE = 128;
    PathfinderFlying pathfinder = new PathfinderFlying(256);
    EntityInsentientImplementation pathEntity = new EntityInsentientImplementation(EntityTypes.am, nmsWorld);
    // 配置寻路实体属性,忽略水、熔岩等非固体障碍,根据需求调整
    pathEntity.a(PathType.WATER, -1.0F);
    pathEntity.a(PathType.LAVA, -1.0F);
    Iterator<Player> receiverIter = e.getRecipients().iterator();
    while (receiverIter.hasNext()) {
        Player receiver = receiverIter.next();
        if (!receiver.getWorld().equals(bukkitWorld)) {
            receiverIter.remove();
            continue;
        }
        Location dest = receiver.getLocation();
        BlockPosition startPos = new BlockPosition(start.getX(), start.getY(), start.getZ());
        BlockPosition destPos = new BlockPosition(dest.getX(), dest.getY(), dest.getZ());
        // 生成完整路径
        Path path = pathfinder.a(nmsWorld, pathEntity, startPos, destPos, SEARCH_RANGE);
        // 路径不存在、未到达终点、长度超过阈值均移除
        if (path == null || !path.e() || path.getPathLength() > MAX_PATH_LENGTH) {
            receiverIter.remove();
        }
    }
}

注意:寻路操作CPU消耗极高,大量玩家同时聊天时容易触发服务器卡顿,非必要场景优先使用方案1。

内容的提问来源于stack exchange,提问作者Marvin Klar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 07:36:04