Search code examples
locationbukkitnms

Get distance between two locations using non-solid blocks with bukkit


My goal is to achieve that players on my bukkit server only hear each other, when there are no walls between them. So my idea was to get the distance between the sender of a message on the AsyncPlayerChatEvent and the recipient (getRecipients()) using a (Flying)Pathfinder(Goal), so that there is a path (throught the air) to the other player. If there is no way or the path is too long, I would remove the recipient from the list.

What I have so far:

    @EventHandler
    public void onAsyncPlayerChat(AsyncPlayerChatEvent e) {
        Player p = e.getPlayer();
        Location start = p.getLocation();
        if (start.getWorld() == null) {
            return;
        }
        PathfinderFlying pathfinder = new PathfinderFlying();
        World world = ((CraftPlayer) p).getHandle().getWorld();
        ChunkCache chunkCache = new ChunkCache(world,
                new BlockPosition(start.getX() - 500, 0, start.getZ() - 500),
                new BlockPosition(start.getX() + 500, 0, start.getZ() + 500)); //Dunno if this is correct
        // EntityInsentientImplementation is basically: EntityInsentientImplementation extends EntityInsentient with default constructor
        pathfinder.a(chunkCache, new EntityInsentientImplementation(EntityTypes.am, world));
        for (Player target : e.getRecipients()) {
            Location dest = target.getLocation();
            // How do I get the distance?
        }
    }

I already thried the function public int a(PathPoint[] var0, PathPoint var1) { from PathfinderFlying but this seems to return a static value (26) when var0 is the location of th sender and var1 is the location of the recipient.

I'm using bukkit 1.17.1.


Solution

  • I was working on how to find the best way to go at specific location. So, I made BaritoneCalculator.

    You should do like that to use it :

    GoalBlock goal = new GoalBlock(x, y, z); // create direction goal
    BaritoneAPI.getProvider().getNewBaritone(p).getPathingBehavior().startGoal(goal);
    

    Now, it will calculate the better path.

    To get the path, use this :

    BaritoneAPI.getProvider().getBaritone(p).getPathingBehavior().getPath();
    

    Or, you can also use an event: PathCalculatedEvent.

    Full code to count all positions to pass through (i.e. your issue) :

    PathingBehavior pathing = BaritoneAPI.getProvider().getNewBaritone(p).getPathingBehavior();
    GoalBlock goal = new GoalBlock(x, y, z); // create direction goal
    pathing.startGoal(goal); // start goal and calculate
    Optional<IPath> optPath = pathing.getPath();
    if(optPath.isPresent()) { // can be not found yet, use event to be sure
       int distance = pathing.get().positions().size() -1; // -1 to don't count current player position
       // now you have the distance
    } else {
       // failed to find way
    }
    

    More informations (and updated) on readme.