Nearby players

Discussion in 'Spigot Plugin Development' started by 97WaterPolo, May 19, 2015.

Thread Status:
Not open for further replies.
  1. Hello.

    Would it be better to get all nearby entities within 150blocks and check to see if they are players, OR loop through all online players and see if the distance of their location is <= 150? Which would be the least taxing way? I am under the impression if the number of players is less than the # of entities I should use that instead, but should I have a check where if onlinePlayers <= 200 loop through online players, else use nearby entities.

    TL;DR

    Which option is better:
    1.
    Code (Text):
    for (Player p : Bukkit.getOnlinePlayers())
        if (player.getLocation().distance(p.getLocation()) <= 150)
            //Stuff to do
    2.
    Code (Text):
    for (Entity e : player.getNearbyEntities(150,150,150))
      if (e instanceof Player)
          //Staff to do
     
     
  2. Probably have to say the first one. This thread sorta outlines it and may be of interest: https://bukkit.org/threads/how-can-i-get-all-players-nearby-a-specific-player.87882/
     
    • Like Like x 1
    • Agree Agree x 1
  3. I'd assume that #1 would be faster based on the fact that there are usually a lot more entities than there are players.
    The benefit of using #1 is that it scales better.
    The potential cons of using #1 might be that the a^2 + b^2 = c`2 calculation is a bit heavy, although with less than 10,000 players this is unlikely to become an issue. The impact this would have could be reduced by replacing it with distanceSquared, and checking to see if it's <= 22500.

    This optimization is, however, quite minimal and you might want to leave it as you had it for the sake of readability.

    hockeymikey's link explains the issues with both methods rather well, so you should read that as well.
     
  4. Yeah the first one. Maybe you could run that thread outside of the main thread to increase performance or call it as an Async ?
     
  5. Thanks! I ended up using this for performance optimization.
    Code (Text):

    int sq = 150 * 150;
           for (Player p : player.getWorld().getPlayers()) {
             if (p.getLocation().distanceSquared(player.getLocation()) <= sq) {
               p.sendMessage(ChatColor.translateAlternateColorCodes('&', format) + msg);
             }
           }
     
     
  6. I think it would be better to use getOnlinePlayers since getPlayers() iterates over all entities.
     
  7. Really? I was under the impression both iterate over all entities, but onlinePlayers() would return players in other worlds?
     
  8. onlineplayers just returns an array I believe and you can just check against the player's world.
     
    • Like Like x 1
  9. For convieniance, I have methods for these already included in my lib:

    Code (Text):
        /**
         * Gets any players within range of a specific location
         *
         * @since 0.0.1
         * @version 0.0.1
         *
         * @param range The range in which to look for players
         * @param origin The {@link Location} representing the center of the circle
         * @return Any players within the radius range of the origin, mapped to
         *         the distance away they are
         */
        public static Map<Player, Double> getPlayersInRange(int range, Location origin) {
            Map<Player, Double> back = new HashMap<>();
            origin.getWorld().getPlayers().forEach((p) -> {
                        double d = p.getLocation().distanceSquared(origin);
                        if (d <= range) {
                            back.put(p, d);
                        }
                    });
            return back;
        }
    https://github.com/CodeLanx/Codelan...om/codelanx/codelanxlib/util/Players.java#L59

    (Actually could be simplified more)

    Code (Text):
        /**
         * Returns the closest {@link Player} to a specific {@link Location}
         *
         * @since 0.1.0
         * @version 0.1.0
         *
         * @param loc The {@link Location} representing the origin to search from
         * @return The closest {@link Player}, or {@code null} if no one is in the
         *         world
         */
        public static Player getClosestPlayer(Location loc) {
            return loc.getWorld().getPlayers().stream().min((o1, o2) -> {
                return Double.compare(o1.getLocation().distanceSquared(loc), o2.getLocation().distanceSquared(loc));
            }).orElse(null);
        }
    https://github.com/CodeLanx/Codelan...m/codelanx/codelanxlib/util/Players.java#L118
     
    #9 1Rogue, May 19, 2015
    Last edited: May 19, 2015
    • Like Like x 1
Thread Status:
Not open for further replies.