Explosion freezing server

Discussion in 'Plugin Development' started by Anrza, Aug 12, 2015.

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

    Anrza

    This code has a ~1% chance of freezing the server:

    Code:
    public static void playerExplosion(Player player, Location location, double damage, double radius, double knockbackForce, int fireTicks) {
            if (fireTicks < 1)
                location.getWorld().spigot().playEffect(location.add(0, 0.2, 0), Effect.CLOUD, 0, 0, .2F, .2F, .2F, 1F, 1000, 120);
            else
                location.getWorld().spigot().playEffect(location.add(0, 0.2, 0), Effect.FLAME, 0, 0, .2F, .2F, .2F, 1F, 1000, 120);
            World world = location.getWorld();
            world.playSound(location, Sound.EXPLODE, 10, 1);
            for (LivingEntity entity : (List<LivingEntity>) getNearbyEntities(location, radius, LivingEntity.class)) {
                Location entLoc = entity.getLocation();
                Double distance = entLoc.distance(location);
                if (distance < radius) {
                    if (canHurt(player, entity)) {
                        Double a = 1 - distance / radius;
                        Double b = a * a;
                        Double dmg = damage * b;
                        entity.damage(dmg, player);
                        Vector v = new Vector(location.getX() - entLoc.getX(), 0, location.getZ() - entLoc.getZ());
                        v.multiply(-1 * a * knockbackForce / v.length());
                        v.setY(Math.sqrt(knockbackForce) * a);
                        entity.setVelocity(v);
                        entity.setFireTicks(entity.getFireTicks() + (int) Math.floor(fireTicks * b));
                    }
                }
            }
        }
    
        public static List<? extends Entity> getNearbyEntities(Location location, double radius, Class<? extends Entity> instanceOf) {
            List<Entity> entityList = new ArrayList<>();
            for (Entity entity : getNearbyEntities(location, radius, radius, radius, instanceOf)) {
                if (entity.getLocation().distance(location) < radius)
                    entityList.add(entity);
            }
            return entityList;
        }
    
        public static List<? extends Entity> getNearbyEntities(Location location, double x, double y, double z, Class<? extends Entity> instanceOf) {
            List<Entity> entityList = new ArrayList<>();
            Location spawnloc = new Location(location.getWorld(), location.getX(), 512, location.getZ());
            ArmorStand fb = (ArmorStand) spawnloc.getWorld().spawnEntity(spawnloc, EntityType.ARMOR_STAND);
            fb.setVisible(false);
            fb.teleport(location);
            final List<Entity> ents = fb.getNearbyEntities(x, y, z);
            fb.remove();
            for (Entity entity : ents) {
                if (instanceOf.isInstance(entity))
                    entityList.add(entity);
            }
            return entityList;
        }
    The server's main thread freezes without any error whatsoever, as you'd see if a shitton of WorldEdit was being done.

    What I know doesn't cause it:
    * The getNearbyEntities() methods. The freeze happened before we started using them for this. And the code has been used literally over a million times without any problems. I included them here because you would've wanted to see them.
    *The canHurt() method. Again, used countless times.

    What clues I know:
    *I have only seen the server freeze when the canHurt() method returns false all iterations. This may be a false clue, as I've only seen it freeze twice and it may have been chance that there were no valid targets in range.
    *The chat can still be used, indicating that only the main thread is frozen. You do, however, lose connection after about a minute and you are unable to login again.

    EDIT: The server goes into an infinite loop. That's what happens. Still not solved though.
     
    Last edited: Aug 12, 2015
  2. Offline

    CoolDude53

    I've dealt with a few mysterious crashes, and I can say they are incredibly frustrating. My best guess is that the entity you are getting the location of may not be valid, so add a check for that. You say there is no trace of the crash, so does that mean the server doesn't actually stop?
     
    Anrza likes this.
  3. Offline

    Anrza

    Quite right, it goes into an infinite loop. I froze it 30 minutes ago and it's still pinging and telling me there's three players online, but it's actually frozen with no one online.

    Do you mean that the Entity is not valid or the Location? And in either case, what do you mean by "not valid"?
     
  4. Offline

    MisterErwin

    I suggest you to debug the loops (an output that would occur every run) - that way you would know WHAT is looping :)
     
    Anrza likes this.
  5. Offline

    CoolDude53

    ^ do that as well, and @Anrza I mean use the Entity#isValid() method to check the entities validity.
     
  6. Offline

    Anrza

  7. Offline

    mythbusterma

    @Anrza

    Your code is extremely difficult to follow and seems to be performing an O(n^3) operation on the entities of the server, if I'm reading it correctly.

    You should really clean up your code. Just rewrite it from scratch and hopefully it isn't so non-performant next time.
     
Thread Status:
Not open for further replies.

Share This Page