getNearbyEntities() of a Location

Discussion in 'Plugin Development' started by iZanax, Sep 18, 2012.

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

    iZanax

    How can i get the nearby entities of a Location?
    Without looping thru all entities, if this is possible.

    PHP:
    Location loc = new Location(player.getWorld(),337,16,1087);
     
  2. Offline

    bergerkiller

    iZanax
    You have to loop through entities. If you want to somehow use a quicker version, use the net.minecraft.server.World getNearbyEntities. It does require you to use a lot of native code. To be honest, I don't understand how to use it either. Something with passing in a box which gives you all the entities that intersect with that box.

    How often do you want to get the nearby entities exactly?

    For comparison, I use this from within a native entity:
    Code:
        public List<net.minecraft.server.Entity> getNearbyEntities(double radius) {
            return this.getNearbyEntities(radius, radius, radius);
        }
        @SuppressWarnings("unchecked")
        public List<net.minecraft.server.Entity> getNearbyEntities(double x, double y, double z) {
            return this.world.getEntities(this, this.boundingBox.grow(x, y, z));
        }
     
  3. Offline

    makskay

    I've occasionally created and then immediately removed an unobtrusive "dummy entity" at the location to use its .getNearbyEntities() method. Not sure how efficient that is compared to using net.minecraft.server code.
     
  4. Offline

    iZanax

    bergerkiller
    Once for each Location in a Hashmap ( around 10-15 locations )
    and then i need to do a distance calculation for entity (instanceof Player && group x) between de location.

    What can u recommand?
     
  5. Offline

    bergerkiller

    iZanax
    If this is a distance between multiple points to players in the world, don't work with entities. Instead, get all the players on the world of the location, and compare distances that way. You can use distanceSquared instead of distance to make the calculation even faster. (no square root)

    You will not notice any lag problem with this method, 200 * 10 locations is 2000 distance(squared) checks, which is nothing in comparison. Do make sure you handle this properly memory-wise; try to re-use your Location objects where possible. It can make a big difference, as I noticed in Nolagg's item stacker. (which loops through a list of all items on the world, no lag up to 20K items)
     
  6. Offline

    heisan213

    I use this. Get's nearby entities in a box around the location.
    Code:JAVA
    1.  
    2. public static List<Entity> getNearbyEntities(Location where, int range) {
    3. List<Entity> found = new ArrayList<Entity>();
    4.  
    5. for (Entity entity : where.getWorld().getEntities()) {
    6. if (isInBorder(where, entity.getLocation(), range)) {
    7. found.add(entity);
    8. }
    9. }
    10. return found;
    11. }

    And isInBorder()...
    Code:JAVA
    1.  
    2. public static boolean isInBorder(Location center, Location notCenter, int range) {
    3. int x = center.getBlockX(), z = center.getBlockZ();
    4. int x1 = notCenter.getBlockX(), z1 = notCenter.getBlockZ();
    5.  
    6. if (x1 >= (x + range) || z1 >= (z + range) || x1 <= (x - range) || z1 <= (z - range)) {
    7. return false;
    8. }
    9. return true;
    10. }
    11.  

    iZanax
    Just noticed it ignores Y coord, but you can figure that out! ;)
     
  7. Offline

    skore87

    This code will get all entities in a radius around a location. It includes the chunk the location is in and does a minimum of 9 chunks for the search and expands depending on the radius you give it (in blocks). Also, this isn't the cuboid "radius" that the player.getNearbyEntities() gives, it is an actual sphere shape so it costs a little more to the server to use.

    Code:
        public static Entity[]  getNearbyEntities(Location l, int radius){
            int chunkRadius = radius < 16 ? 1 : (radius - (radius % 16))/16;
            HashSet<Entity> radiusEntities = new HashSet<Entity>();
                for (int chX = 0 -chunkRadius; chX <= chunkRadius; chX ++){
                    for (int chZ = 0 -chunkRadius; chZ <= chunkRadius; chZ++){
                        int x=(int) l.getX(),y=(int) l.getY(),z=(int) l.getZ();
                        for (Entity e : new Location(l.getWorld(),x+(chX*16),y,z+(chZ*16)).getChunk().getEntities()){
                            if (e.getLocation().distance(l) <= radius && e.getLocation().getBlock() != l.getBlock()) radiusEntities.add(e);
                        }
                    }
                }
            return radiusEntities.toArray(new Entity[radiusEntities.size()]);
        }
     
  8. Offline

    iZanax

    Thanks for all the advice so far!
    (it helped a lot!)

    What is the difference between Distance(Location) and DistanceSquared(Location)?
    # Is the DistanceSquared a faster option and less lagg making then Distance option?
    # Distance result in blocks distance (int). and Squared is giving a much higher number,
    i can't resolve the number, how can i make it into block distance (int) if Squared is a better option?
     
  9. Offline

    desht

    iZanax

    location.distanceSquared() basically does:
    PHP:
    return (x1 x2) * (x1 x2) + (y1 y2) * (y1 y2) + (z1 z2) * (z1 z2);
    location.distance() just takes that value and applies Math.sqrt() to it. Math.sqrt() is a somewhat expensive calculation in CPU terms.

    Therefore, if you're running location.distance() inside a loop (as a getNearbyEntities() method would need to), it's much more efficient to square the distance before the loop starts, and use location.distanceSquared() on the distance squared.
     
Thread Status:
Not open for further replies.

Share This Page