Untitled

 avatar
unknown
java
a year ago
6.2 kB
2
Indexable
    public void handleFireball(Fireball explosive) {
        debug("fireball detected");
        BlockManager blockManager = arena.getBlockManager();

        Set<Block> explodingBlocks = getExplodingBlocks(
                FIREBALL_INVULNERABLE,
                explosive.getLocation().getBlock(),
                3
        );

        explodingBlocks.forEach(blockManager::breakBlock);

        handleExplosionBehavior(
                explosive,
                explodingBlocks,
                new Vector(0.55, 0.485, 0.55),
                6,
                5.5
        );
    }

    public void handleTnt(TNTPrimed explosive) {
        debug("tnt detected");
        BlockManager blockManager = arena.getBlockManager();

        Set<Block> explodingBlocks = getExplodingBlocks(
                TNT_INVULNERABLE,
                explosive.getLocation().getBlock(),
                4
        );

        explodingBlocks.forEach(blockManager::breakBlock);

        handleExplosionBehavior(
                explosive,
                explodingBlocks,
                new Vector(0.55, 0.485, 0.55),
                8,
                6.5
        );
    }

    private Vector scaledBisector(Vector v1, Vector v2) {
        Vector normBisector = v1.clone().add(v2).normalize();
        return normBisector.multiply(v1.length() / normBisector.length());
    }

    @SuppressWarnings("deprecation")
    public void handleExplosionBehavior(Entity explosive,
                                        Set<Block> explodingBlocks,
                                        Vector modifier,
                                        double radius,
                                        double maxDamage) {

        Location sourceLocation = explosive.getLocation();
        World world = sourceLocation.getWorld();

        Arena arena = Arena.byWorld(world).get();

        WorldServer worldServer = ((CraftWorld) world).getHandle();
        boolean isTNT = explosive.getType() == EntityType.PRIMED_TNT;

        world.playSound(sourceLocation,
                Sound.EXPLODE,
                isTNT ? worldServer.paperSpigotConfig.tntExplosionVolume : 8.0F,
                (1.0F + (worldServer.random.nextFloat() - worldServer.random.nextFloat()) * 0.2F) * 0.7F
        );

        world.getPlayers().forEach(worldPlayer -> {
            if (isTNT) {
                PacketUtils.sendEffectData(worldPlayer, EnumParticle.EXPLOSION_HUGE, sourceLocation, true, 0.1f, 0.1f, 0.1f, 1f, 1);
            } else {
                PacketUtils.sendEffectData(worldPlayer, EnumParticle.EXPLOSION_LARGE, sourceLocation, true, 1f, 1f, 1f, 1f, 2);
            }
            explodingBlocks.forEach(block -> PacketUtils.sendEffectData(worldPlayer, EnumParticle.SMOKE_NORMAL, block.getLocation(), true, 0.1f, 0.1f, 0.1f, 0.05f, 7));
        });

        WorldUtils.getNearbyEntities(sourceLocation, radius).forEach(entity -> {
            EntityType type = entity.getType();

            if (type == EntityType.PLAYER) {
                Player player = (Player) entity;

                if (arena.isRespawning(player) || arena.isSpectator(player)) {
                    return;
                }
            }

            Location entityLocation = entity.getLocation();
            Location headLocation = type == EntityType.PLAYER ?
                    ((Player) entity).getEyeLocation() :
                    entityLocation.clone().add(0, 1, 0);

            Vector flyDir = headLocation.toVector().subtract(sourceLocation.toVector());

            double distance = entityLocation.distance(sourceLocation);

            if (type == EntityType.PLAYER) {
                Bukkit.broadcastMessage(entity.getVelocity().toString());
                Bukkit.broadcastMessage(String.valueOf(distance));
            }

            double deltaX = entityLocation.getX() - sourceLocation.getX();
            double deltaZ = entityLocation.getZ() - sourceLocation.getZ();

            double horizontalDistance = Math.sqrt(deltaX * deltaX + deltaZ * deltaZ);

            flyDir.normalize();
            flyDir.multiply(Math.max(0, 4 * (1 - distance / radius)));
            flyDir.multiply(modifier);

            Vector jumpVector = new Vector(0, (distance <= closeDistance ? closeMul : 2.5f) * (horizontalDistance / radius), 0);

            flyDir = scaledBisector(scaledBisector(flyDir, jumpVector), entity.getVelocity());

            // Velocity minecraft yejoori kar mikone ke nemitone bishtar as 4 too packet bede, pas momkene player false bokhore ya har etefaghi biofte
            // Behtar ine ke velocity ro be 4 limit kard, ya baze baze apply kard
            // ya age bekhai mishe too config disable esh kard
            // See:
            // - https://github.com/PaperMC/Paper/issues/536
            // - CraftEntity#setVelocity()

            double damage = maxDamage * (1 - distance / radius);

            if (type == EntityType.PLAYER) {
                Player player = (Player) entity;

                damage = player.isBlocking() ? damage / 1.25 : damage;

                entity.setVelocity(entity.getVelocity().add(player.isBlocking() ? flyDir.multiply(6 / 7) : flyDir));
            } else if (type == EntityType.PRIMED_TNT) {
                entity.setVelocity(flyDir.multiply(0.5f));
            } else {
                entity.setVelocity(flyDir);
            }

            if (entity instanceof LivingEntity) {
                LivingEntity livingEntity = (LivingEntity) entity;

                EntityDamageByEntityEvent damageEvent = new EntityDamageByEntityEvent(
                        explosive,
                        livingEntity,
                        DamageCause.ENTITY_EXPLOSION,
                        damage
                );

                BukkitUtils.callEvent(damageEvent);

                if (!damageEvent.isCancelled()) {
                    double finalDamage = damageEvent.getFinalDamage();

                    livingEntity.setLastDamageCause(new EntityDamageEvent(livingEntity, DamageCause.ENTITY_EXPLOSION, finalDamage));
                    livingEntity.damage(finalDamage);
                }
            }
        });
    }
Leave a Comment