Смотри, посмотри как здесь реализована анимация падения суперновы а также её взрыв

package com.github.jewishbanana.deadlydisasters.events.disasters;

import com.github.jewishbanana.deadlydisasters.events.DestructionDisaster;
import com.github.jewishbanana.deadlydisasters.events.DestructionDisasterEvent;
import com.github.jewishbanana.deadlydisasters.events.Disaster;
import com.github.jewishbanana.deadlydisasters.listeners.DeathMessages;
import com.github.jewishbanana.deadlydisasters.utils.Metrics;
import com.github.jewishbanana.deadlydisasters.utils.RepeatingTask;
import com.github.jewishbanana.deadlydisasters.utils.Utils;
import com.github.jewishbanana.deadlydisasters.utils.VersionUtils;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Random;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.block.Block;
import org.bukkit.entity.EnderCrystal;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.util.BlockVector;
import org.bukkit.util.Vector;

public class Supernova extends DestructionDisaster {
    private double size;
    private double sizeMultiplier;
    private double particleMultiplier;
    private double fallSpeedMultiplier;
    private int tick = 1;
    private EnderCrystal crystal;
    private Particle particle;
    private Material[] materials;
    private boolean flash;
    private boolean farParticles;
    private int blocksDestroyed;

    public Supernova(int level, World world) {
        super(level, world);
        switch (level) {
            case 1:
            default:
                this.size = 35.0;
                break;
            case 2:
                this.size = 45.0;
                break;
            case 3:
                this.size = 57.0;
                break;
            case 4:
                this.size = 70.0;
                break;
            case 5:
                this.size = 85.0;
                break;
            case 6:
                this.size = 100.0;
        }

        this.volume = this.configFile.getDouble("supernova.volume");
        this.particleMultiplier = this.configFile.getDouble("supernova.particle_multiplier");
        this.flash = this.configFile.getBoolean("supernova.flash");
        this.sizeMultiplier = this.configFile.getDouble("supernova.size");
        this.particle = VersionUtils.getLargeExplosion();
        this.materials = new Material[]{Material.OBSIDIAN, Material.BLACK_CONCRETE, Material.FIRE};
        if (!this.configFile.getBoolean("supernova.place_fire")) {
            this.materials = new Material[]{Material.OBSIDIAN, Material.BLACK_CONCRETE};
        }

        this.farParticles = this.configFile.getBoolean("supernova.far_particles");
        this.fallSpeedMultiplier = this.configFile.getDouble("supernova.fall_speed_multiplier");
        this.type = Disaster.SUPERNOVA;
    }

    public void start(final Location loc, Player p) {
        DestructionDisasterEvent event = new DestructionDisasterEvent(this, loc, this.level, p);
        Bukkit.getPluginManager().callEvent(event);
        if (!event.isCancelled()) {
            this.loc = loc;
            ongoingDisasters.add(this);
            DeathMessages.supernovas.add(this);
            this.size *= this.sizeMultiplier;
            final World world = loc.getWorld();
            final Location top = loc.clone();
            top.setY(320.0);
            final Location crystalLoc = top.clone();
            this.crystal = (EnderCrystal)world.spawn(crystalLoc, EnderCrystal.class);
            this.crystal.setShowingBottom(false);
            this.crystal.setBeamTarget(top);
            final Vector vec = new Vector(0.0, -2.0 * this.fallSpeedMultiplier, 0.0);
            RepeatingTask var10000 = new RepeatingTask(this.plugin, 0, 1) {
                public void run() {
                    crystalLoc.add(vec);
                    if (vec.getY() < -0.5) {
                        vec.setY(vec.getY() + 0.01);
                    }

                    Supernova.this.crystal.remove();
                    Supernova.this.crystal = (EnderCrystal)world.spawn(crystalLoc, EnderCrystal.class);
                    Supernova.this.crystal.setShowingBottom(false);
                    Supernova.this.crystal.setBeamTarget(top);
                    world.spawnParticle(Particle.CLOUD, crystalLoc, 10, 0.5, 0.5, 0.5, 0.01, (Object)null, true);
                    world.spawnParticle(Particle.FLAME, crystalLoc, 10, 0.5, 0.5, 0.5, 0.01, (Object)null, true);
                    Block b = crystalLoc.clone().subtract(0.0, 1.0, 0.0).getBlock();
                    if (b.getType() != Material.AIR && !Utils.isBlockImmune(b.getType()) && !Utils.isZoneProtected(b.getLocation())) {
                        if (Supernova.this.plugin.CProtect) {
                            Utils.getCoreProtect().logRemoval("Deadly-Disasters", b.getLocation(), b.getType(), b.getBlockData());
                        }

                        b.setType(Material.AIR);
                        ++Supernova.this.blocksDestroyed;
                    }

                    if (crystalLoc.distance(loc) < 3.0) {
                        Supernova.this.crystal.remove();
                        this.cancel();
                        Supernova.this.explode(world);
                    }

                    if (Supernova.this.flash) {
                        Iterator var3 = world.getNearbyEntities(loc, 140.0, 100.0, 140.0).iterator();

                        while(var3.hasNext()) {
                            Entity e = (Entity)var3.next();
                            if (e instanceof Player) {
                                Location temp = e.getLocation();
                                ((Player)e).spawnParticle(Particle.FLASH, temp.clone().add((new Vector(temp.getX() - crystalLoc.getX(), temp.getY() - crystalLoc.getY(), temp.getZ() - crystalLoc.getZ())).normalize().multiply(-3)), 1, 1.0, 1.0, 1.0, 0.001);
                            }
                        }
                    }

                }
            };
            var10000 = new RepeatingTask(this.plugin, 0, 10) {
                public void run() {
                    if (Supernova.this.tick > 1) {
                        this.cancel();
                    }

                    if (Supernova.this.plugin.mcVersion >= 1.16) {
                        Iterator var2 = world.getNearbyEntities(loc, 140.0, 140.0, 140.0).iterator();

                        while(var2.hasNext()) {
                            Entity e = (Entity)var2.next();
                            if (e instanceof Player) {
                                Location temp = e.getLocation();
                                ((Player)e).playSound(temp.clone().add((new Vector(temp.getX() - crystalLoc.getX(), temp.getY() - crystalLoc.getY(), temp.getZ() - crystalLoc.getZ())).normalize().multiply(-4)), Sound.AMBIENT_NETHER_WASTES_MOOD, (float)((2.0 - 0.002 * crystalLoc.distance(e.getLocation())) * Supernova.this.volume), 0.5F);
                            }
                        }
                    }

                }
            };
        }
    }

    private void explode(final World world) {
        final BlockVector block = new BlockVector(this.loc.getX(), this.loc.getY(), this.loc.getZ());
        final Random rand = new Random();
        final boolean CP = this.plugin.CProtect;
        final Supernova instance = this;
        RepeatingTask var10000 = new RepeatingTask(this.plugin, 0, 1) {
            public void run() {
                if ((double)Supernova.this.tick > Supernova.this.size) {
                    this.cancel();
                    Supernova.ongoingDisasters.remove(instance);
                    DeathMessages.supernovas.remove(instance);
                    Metrics.incrementValue(Metrics.disasterDestroyedMap, Supernova.this.type.getMetricsLabel(), Supernova.this.blocksDestroyed);
                } else {
                    final Set<Block> blocks = new LinkedHashSet(Supernova.this.tick * Supernova.this.tick * Supernova.this.tick);

                    for(int x = -Supernova.this.tick; x < Supernova.this.tick; ++x) {
                        for(int y = -Supernova.this.tick; y < Supernova.this.tick; ++y) {
                            for(int z = -Supernova.this.tick; z < Supernova.this.tick; ++z) {
                                Vector position = block.clone().add(new Vector(x, y, z));
                                if (block.distance(position) >= (double)(Supernova.this.tick - 1) && block.distance(position) <= (double)Supernova.this.tick) {
                                    Block b = world.getBlockAt(position.toLocation(world));
                                    blocks.add(b);
                                    if (b.getType() != Material.AIR && !Utils.isBlockImmune(b.getType()) && !Utils.isZoneProtected(b.getLocation())) {
                                        if (CP) {
                                            Utils.getCoreProtect().logRemoval("Deadly-Disasters", b.getLocation(), b.getType(), b.getBlockData());
                                        }

                                        if ((double)Supernova.this.tick > Supernova.this.size - 2.0 && rand.nextInt(8) == 0) {
                                            Material mat = Supernova.this.materials[rand.nextInt(Supernova.this.materials.length)];
                                            if (CP) {
                                                Utils.getCoreProtect().logPlacement("Deadly-Disasters", b.getLocation(), mat, mat.createBlockData());
                                            }

                                            b.setType(mat);
                                            ++Supernova.this.blocksDestroyed;
                                        } else {
                                            b.setType(Material.AIR);
                                            ++Supernova.this.blocksDestroyed;
                                        }
                                    }
                                }
                            }
                        }
                    }

                    ++Supernova.this.tick;
                    Supernova.this.plugin.getServer().getScheduler().runTaskAsynchronously(Supernova.this.plugin, new Runnable() {
                        public void run() {
                            int chance = (int)Math.ceil((double)(1 + blocks.size() / 1000) * Supernova.this.particleMultiplier);
                            Iterator var3 = blocks.iterator();

                            while(var3.hasNext()) {
                                Block b = (Block)var3.next();
                                if (rand.nextInt(chance) == 0) {
                                    world.spawnParticle(Supernova.this.particle, b.getLocation(), 1, 0.0, 0.0, 0.0, 1.0, (Object)null, Supernova.this.farParticles);
                                }
                            }

                        }
                    });
                }
            }
        };
        var10000 = new RepeatingTask(this.plugin, 0, 10) {
            public void run() {
                if ((double)Supernova.this.tick > Supernova.this.size) {
                    this.cancel();
                } else {
                    Iterator var2 = world.getNearbyEntities(Supernova.this.loc, (double)(Supernova.this.tick + 100), (double)(Supernova.this.tick + 100), (double)(Supernova.this.tick + 100)).iterator();

                    while(true) {
                        Entity e;
                        do {
                            do {
                                do {
                                    while(true) {
                                        do {
                                            do {
                                                if (!var2.hasNext()) {
                                                    return;
                                                }

                                                e = (Entity)var2.next();
                                            } while(!(e instanceof LivingEntity));
                                        } while(e.isDead());

                                        if (Supernova.this.loc.distance(e.getLocation()) < (double)Supernova.this.tick) {
                                            break;
                                        }

                                        if (e instanceof Player) {
                                            Location temp = e.getLocation().clone().add((new Vector(e.getLocation().getX() - Supernova.this.loc.getX(), e.getLocation().getY() - Supernova.this.loc.getY(), e.getLocation().getZ() - Supernova.this.loc.getZ())).normalize().multiply(-4));
                                            float vol = (float)((2.0 - (5.0E-4 * Supernova.this.loc.distance(e.getLocation()) - (double)Supernova.this.tick)) * Supernova.this.volume);
                                            if (Supernova.this.plugin.mcVersion >= 1.16) {
                                                ((Player)e).playSound(temp, Sound.AMBIENT_WARPED_FOREST_MOOD, vol, 0.5F);
                                            }

                                            ((Player)e).playSound(temp, Sound.ENTITY_LIGHTNING_BOLT_THUNDER, vol, 0.5F);
                                            ((Player)e).playSound(temp, Sound.ENTITY_DRAGON_FIREBALL_EXPLODE, vol / 30.0F, 0.5F);
                                        }
                                    }
                                } while(Supernova.this.isEntityTypeProtected(e));
                            } while(Utils.isZoneProtected(e.getLocation()));
                        } while(e instanceof Player && Utils.isPlayerImmune((Player)e));

                        Utils.pureDamageEntity((LivingEntity)e, 20.0, "dd-supernova", true, DamageCause.BLOCK_EXPLOSION);
                    }
                }
            }
        };
    }

    public void removeCrystal() {
        if (this.crystal != null) {
            this.crystal.remove();
        }

    }

    public Location findApplicableLocation(Location temp, Player p) {
        temp = Utils.getBlockBelow(temp).getLocation();
        return temp.getBlockY() >= this.type.getMinHeight() && temp.getWorld().getEnvironment() != Environment.NETHER ? temp : null;
    }

    public void startAdjustment(Location loc, Player p) {
        this.start(Utils.getBlockBelow(loc).getLocation(), p);
    }

    public double getSizeMultiplier() {
        return this.sizeMultiplier;
    }

    public void setSizeMultiplier(double sizeMultiplier) {
        this.sizeMultiplier = sizeMultiplier;
    }

    public Particle getParticle() {
        return this.particle;
    }

    public void setParticle(Particle particle) {
        this.particle = particle;
    }

    public Material[] getMaterials() {
        return this.materials;
    }

    public void setMaterials(Material[] materials) {
        this.materials = materials;
    }

    public boolean isFlash() {
        return this.flash;
    }

    public void setFlash(boolean flash) {
        this.flash = flash;
    }

    public double getParticles() {
        return this.particleMultiplier;
    }

    public void setParticles(double particles) {
        this.particleMultiplier = particles;
    }
}