Hub / src / main / java / com / lifeknight / relaymchub / cosmetics / Cosmetics.java
Cosmetics.java
Raw
package com.lifeknight.relaymchub.cosmetics;

import com.lifeknight.relaymchub.ExtraListeners;
import com.lifeknight.relaymchub.Main;
import com.lifeknight.relaymchub.cosmetics.types.ChestplateApplication;
import com.lifeknight.relaymchub.player.HubPlayer;
import com.lifeknight.relaymcutils.RelayMCUtils;
import com.lifeknight.relaymcutils.utilities.SmartNPC;
import com.lifeknight.relayutils.basic.Miscellaneous;
import com.lifeknight.relayutils.player.Group;
import com.lifeknight.relayutils.player.cosmetics.Cosmetic;
import com.lifeknight.relayutils.utilities.ComponentBuilder;
import com.lifeknight.relayutils.utilities.ItemUtilities;
import com.lifeknight.relayutils.utilities.PlayerUtilities;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.entity.*;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.FireworkMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.util.Vector;

import java.util.ArrayList;
import java.util.List;

import static org.bukkit.ChatColor.GOLD;
import static org.bukkit.ChatColor.GREEN;

public class Cosmetics {
    public static List<DefinedLobbyCosmetic> getDefaultCosmeticItemsForPlayer(HubPlayer hubPlayer) {
        if (hubPlayer.isAdministrator()) return DefinedLobbyCosmetic.getCosmetics();

        List<DefinedLobbyCosmetic> cosmeticItems = new ArrayList<>();

        if (hubPlayer.hasRankOrHigher(Group.TIERI)) {
            cosmeticItems.add(SPEEDSTER_CROCS);
            cosmeticItems.add(RABBIT_LEGS);
        }
        if (hubPlayer.hasRankOrHigher(Group.TIERII)) {
            cosmeticItems.add(LIGHTNING_SHOES);
            cosmeticItems.add(SLIMES_TROUSERS);
        }
        if (hubPlayer.hasRankOrHigher(Group.TIERIII)) {
            cosmeticItems.add(USAIN_BOLTS_BOOTS);
            cosmeticItems.add(BOUNCY_JEANS);
        }
        if (hubPlayer.hasRankOrHigher(Group.CHAMPION)) {
            cosmeticItems.add(LIGHT_SPEED_SANDALS);
            cosmeticItems.add(WINGS);
            cosmeticItems.add(ZOMBIE_MORPH);
            cosmeticItems.add(PLUNGING_PANTALONES);
        }
        for (Cosmetic cosmetic : Cosmetic.getCosmeticsUnderLevel(hubPlayer.getNetworkLevel())) {
            DefinedLobbyCosmetic definedLobbyCosmetic = DefinedLobbyCosmetic.getCosmetic(cosmetic);
            if (definedLobbyCosmetic != null) {
                cosmeticItems.add(definedLobbyCosmetic);
            }
        }
        return cosmeticItems;
    }

    public static final ArmorCosmetic SPEEDSTER_CROCS = (ArmorCosmetic) new ArmorCosmetic(Cosmetic.SPEEDSTER_CROCS, EquipmentSlot.FEET).addPotionApplication(PotionEffectType.SPEED, 2);

    public static final ArmorCosmetic LIGHTNING_SHOES = (ArmorCosmetic) new ArmorCosmetic(Cosmetic.LIGHTNING_SHOES, EquipmentSlot.FEET).addPotionApplication(PotionEffectType.SPEED, 4);

    public static final ArmorCosmetic USAIN_BOLTS_BOOTS = (ArmorCosmetic) new ArmorCosmetic(Cosmetic.USAIN_BOLTS_BOOTS, EquipmentSlot.FEET).addPotionApplication(PotionEffectType.SPEED, 6);

    public static final ArmorCosmetic LIGHT_SPEED_SANDALS = (ArmorCosmetic) new ArmorCosmetic(Cosmetic.LIGHT_SPEED_SANDALS, EquipmentSlot.FEET).addPotionApplication(PotionEffectType.SPEED, 10);

    public static final ArmorCosmetic DONT_PRESS_W = (ArmorCosmetic) new ArmorCosmetic(Cosmetic.DONT_PRESS_W, EquipmentSlot.FEET).addPotionApplication(PotionEffectType.SPEED, 90);

    public static final ArmorCosmetic RABBIT_LEGS = (ArmorCosmetic) new ArmorCosmetic(Cosmetic.RABBIT_LEGS, EquipmentSlot.LEGS).addPotionApplication(PotionEffectType.JUMP, 2);

    public static final ArmorCosmetic SLIMES_TROUSERS = (ArmorCosmetic) new ArmorCosmetic(Cosmetic.SLIMES_TROUSERS, EquipmentSlot.LEGS).addPotionApplication(PotionEffectType.JUMP, 4);

    public static final ArmorCosmetic BOUNCY_JEANS = (ArmorCosmetic) new ArmorCosmetic(Cosmetic.BOUNCY_JEANS, EquipmentSlot.LEGS).addPotionApplication(PotionEffectType.JUMP, 6);

    public static final ArmorCosmetic BOUNCE_BREECHES = (ArmorCosmetic) new ArmorCosmetic(Cosmetic.BOUNCE_BREECHES, EquipmentSlot.LEGS).addPotionApplication(PotionEffectType.JUMP, 8);

    public static final ArmorCosmetic PLUNGING_PANTALONES = (ArmorCosmetic) new ArmorCosmetic(Cosmetic.PLUNGING_PANTALONES, EquipmentSlot.LEGS).addPotionApplication(PotionEffectType.JUMP, 12);

    public static final ArmorCosmetic JUMPANTS = (ArmorCosmetic) new ArmorCosmetic(Cosmetic.JUMPANTS, EquipmentSlot.LEGS).addPotionApplication(PotionEffectType.JUMP, 30);

    public static final ArmorCosmetic DONT_PRESS_SPACE = (ArmorCosmetic) new ArmorCosmetic(Cosmetic.DONT_PRESS_SPACE, EquipmentSlot.LEGS).addPotionApplication(PotionEffectType.JUMP, 90);

    public static final ArmorCosmetic VANISHING_CAP = new ArmorCosmetic(Cosmetic.VANISHING_CAP, EquipmentSlot.HEAD) {
        @Override
        public void tick(HubPlayer hubPlayer) {
            if (hubPlayer.getLocation().distance(hubPlayer.getLastLocation()) >= 0.05) {
                if (!hubPlayer.getPlayer().hasPotionEffect(PotionEffectType.INVISIBILITY))
                    hubPlayer.getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 10, 0).withParticles(false).withIcon(false).withAmbient(false));
            }
        }
    };

    public static final ArmorCosmetic FANCY_CAP = new ArmorCosmetic(Cosmetic.FANCY_CAP, EquipmentSlot.HEAD) {
        @Override
        public void tick(HubPlayer hubPlayer) {
            ItemStack[] newArmor = new ItemStack[4];
            ItemStack[] armorContents = hubPlayer.getInventory().getArmorContents();
            for (int i = 0; i < armorContents.length; i++) {
                ItemStack armorPiece = armorContents[i];
                if (armorContents[i] == null) {
                    newArmor[i] = null;
                    continue;
                }
                if (armorPiece.getItemMeta() instanceof LeatherArmorMeta armorMeta) {
                    java.awt.Color chromaColor = ComponentBuilder.currentChroma();
                    armorMeta.setColor(Color.fromRGB(chromaColor.getRed(), chromaColor.getBlue(), chromaColor.getGreen()));

                    armorPiece.setItemMeta(armorMeta);
                }
                newArmor[i] = armorPiece;
            }
            hubPlayer.getInventory().setArmorContents(newArmor);
        }
    };

    public static final MorphCosmetic ZOMBIE_MORPH = new MorphCosmetic(Cosmetic.ZOMBIE_MORPH, EntityType.ZOMBIE).setProjectile(Material.ROTTEN_FLESH);

    public static final MorphCosmetic SKELETON_MORPH = new MorphCosmetic(Cosmetic.SKELETON_MORPH, EntityType.SKELETON).setProjectile(EntityType.ARROW);

    public static final MorphCosmetic PIGLIN_MORPH = new MorphCosmetic(Cosmetic.PIGLIN_MORPH, EntityType.PIGLIN).setProjectile(Material.GOLD_INGOT);

    public static final MorphCosmetic BLAZE_MORPH = new MorphCosmetic(Cosmetic.BLAZE_MORPH, EntityType.BLAZE).setProjectile(EntityType.SMALL_FIREBALL);

    public static final MorphCosmetic BAT_MORPH = new MorphCosmetic(Cosmetic.BAT_MORPH, EntityType.BAT) {
        @Override
        public Entity getNewEntity(Location location, HubPlayer hubPlayer) {
            Bat bat = (Bat) super.getNewEntity(location, hubPlayer);
            bat.setAwake(true);
            return bat;
        }
    };

    public static final MorphCosmetic ENDERMAN_MORPH = new MorphCosmetic(Cosmetic.ENDERMAN_MORPH, EntityType.ENDERMAN).setProjectile(EntityType.ENDER_PEARL);
    public static final MorphCosmetic ELDER_GUARDIAN_MORPH = new MorphCosmetic(Cosmetic.ELDER_GUARDIAN_MORPH, EntityType.ELDER_GUARDIAN);
    public static final MorphCosmetic WITHER_MORPH = new MorphCosmetic(Cosmetic.WITHER_MORPH, EntityType.WITHER).setProjectile(EntityType.WITHER_SKULL);
    public static final MorphCosmetic WARDEN_MORPH = new MorphCosmetic(Cosmetic.WARDEN_MORPH, EntityType.WARDEN) {
        @Override
        public void moveParticleProjectile(HubPlayer hubPlayer, Entity entity) {
            if (projectileLife <= 0) {
                projectileLocation = null;
                projectileVelocity = null;
                return;
            }
            int count = 0;
            for (HubPlayer player : this.getNearbyPlayers(projectileLocation, 2.5)) {
                if (player == hubPlayer)
                    continue;
                count++;
            }
            if (count != 0) {
                getWorld().playSound(hubPlayer.getLocation(), Sound.ENTITY_WARDEN_AGITATED, 1, 1);
                for (HubPlayer player : this.getNearbyPlayers(projectileLocation, 6)) {
                    if (player == hubPlayer)
                        continue;
                    Location location = player.getLocation();
                    Vector direction = PlayerUtilities.getDirectionVector(hubPlayer.getLocation().toVector(), location.toVector()).setY(-1);
                    if (Double.isFinite(direction.getX()) && Double.isFinite(direction.getY()) && Double.isFinite(direction.getZ())) {
                        player.setVelocity(direction.multiply(-0.6));
                    }
                    player.sendInfoMessage("You were Sonic Boomed by %s!", hubPlayer.getFormattedName());
                }
                projectileLocation = null;
                projectileVelocity = null;
            }
            getWorld().spawnParticle(Particle.SONIC_BOOM, projectileLocation, 1);
            getWorld().playSound(projectileLocation, Sound.ENTITY_WARDEN_SONIC_BOOM, 2, 1);
            projectileLocation.add(projectileVelocity);

            projectileLife--;
        }
        @Override
        public void activateAbility(HubPlayer hubPlayer, Entity entity) {
            if (projectileLocation == null) {
                projectileLocation = entity instanceof LivingEntity ? ((LivingEntity) entity).getEyeLocation() : entity.getLocation().clone();;
                projectileVelocity = hubPlayer.getLocation().getDirection().multiply(2.1);
                projectileLife = 20;
            }
        }
    };
    public static final MorphCosmetic ENDER_DRAGON_MORPH = new MorphCosmetic(Cosmetic.ENDER_DRAGON_MORPH, EntityType.ENDER_DRAGON).setProjectile(EntityType.DRAGON_FIREBALL);

    public static final BlockMorphCosmetic SAND_MORPH = new BlockMorphCosmetic(Cosmetic.SAND_MORPH, Material.SAND).setProjectile(Material.SAND);
    public static final BlockMorphCosmetic DIAMOND_BLOCK_MORPH = new BlockMorphCosmetic(Cosmetic.DIAMOND_BLOCK_MORPH, Material.DIAMOND_BLOCK).setProjectile(Material.DIAMOND);

    public static final MorphCosmetic BABY_TURTLE_MORPH = new MorphCosmetic(Cosmetic.BABY_TURTLE_MORPH, EntityType.TURTLE) {
        @Override
        public Entity getNewEntity(Location location, HubPlayer hubPlayer) {
            Turtle turtle = (Turtle) super.getNewEntity(location, hubPlayer);
            turtle.setBaby();
            return turtle;
        }
    };
    public static final MorphCosmetic TAD_POLE_MORPH = new MorphCosmetic(Cosmetic.TAD_POLE_MORPH, EntityType.TADPOLE).setProjectile(Particle.EXPLOSION_HUGE);
    public static final MorphCosmetic RAVAGER_MORPH = new MorphCosmetic(Cosmetic.RAVAGER_MORPH, EntityType.RAVAGER) {
        @Override
        public void activateAbility(HubPlayer hubPlayer, Entity entity) {
            int count = 0;
            for (HubPlayer player : this.getNearbyPlayers(hubPlayer, 4)) {
                Location location = player.getLocation();
                Vector direction = PlayerUtilities.getDirectionVector(hubPlayer.getLocation().toVector(), location.toVector()).setY(-1);
                if (Double.isFinite(direction.getX()) && Double.isFinite(direction.getY()) && Double.isFinite(direction.getZ())) {
                    player.setVelocity(direction.multiply(-1));
                }
                player.sendInfoMessage("You were Screeched by %s!", hubPlayer.getFormattedName());
                count++;
            }

            if (count != 0) {
                getWorld().playSound(hubPlayer.getLocation(), Sound.ENTITY_RAVAGER_ROAR, 1, 1);
                hubPlayer.sendSuccessMessage("Screeched %s%d%s player%s!", GOLD, count, GREEN, count == 1 ? "" : "s");
            }

            hubPlayer.sendErrorMessage("No players close enough.");
            hubPlayer.playErrorSound();
        }
    };
    public static final ItemCosmetic WINGS = (ItemCosmetic) new ItemCosmetic(Cosmetic.WINGS, Material.EMERALD_BLOCK) {
        @Override
        public boolean onUse(HubPlayer hubPlayer, boolean rightClick) {
            if (hubPlayer.isGliding()) {
                hubPlayer.boostElytra(ItemUtilities.edit(Material.FIREWORK_ROCKET, itemMeta -> {
                    FireworkMeta fireworkMeta = (FireworkMeta) itemMeta;
                    java.awt.Color nameColor = hubPlayer.getFormattedNameColor().asBungee().getColor();
                    fireworkMeta.addEffect(FireworkEffect.builder().withColor(
                                    Color.fromRGB(nameColor.getRed(), nameColor.getGreen(), nameColor.getBlue()))
                            .with(FireworkEffect.Type.BURST)
                            .trail(true)
                            .build());
                    fireworkMeta.setPower(Miscellaneous.getRandomIntBetweenRange(1, 3));
                }));
                return true;
            } else {
                hubPlayer.sendErrorMessage("You must be gliding to use this!");
            }

            return false;
        }
    }.setCooldown(3).addApplication(new ChestplateApplication(Material.ELYTRA));

    public static final ItemCosmetic SLIME_BOUNCE = new ItemCosmetic(Cosmetic.SLIME_BOUNCE) {
        @Override
        public boolean onUse(HubPlayer hubPlayer, boolean rightClick) {
            Player player = hubPlayer.getPlayer();

            player.setVelocity(player.getLocation().getDirection().multiply(2));
            hubPlayer.playSound(Sound.ENTITY_SLIME_JUMP);

            return true;
        }
    }.setCooldown(1.5);

    public static final ItemCosmetic FIREWORK_MENACE = new ItemCosmetic(Cosmetic.FIREWORK_MENACE) {
        @Override
        public boolean onUse(HubPlayer hubPlayer, boolean rightClick) {
            for (int i = 0; i < 5; i++) {
                RelayMCUtils.scheduleSyncDelayedTask(() -> {
                    for (HubPlayer onlineHubPlayer : HubPlayer.getOnlineHubPlayers()) {
                        if (!onlineHubPlayer.isVanished()) {
                            Location location = onlineHubPlayer.getEyeLocation();
                            Firework firework = (Firework) onlineHubPlayer.getWorld().spawnEntity(location, EntityType.FIREWORK);
                            FireworkMeta fireworkMeta = firework.getFireworkMeta();
                            for (int j = 0; j < Miscellaneous.getRandomIntBetweenRange(1, 5); j++) {
                                fireworkMeta.addEffect(this.createRandomFireWorkEffect());
                            }
                            fireworkMeta.setPower(Miscellaneous.getRandomIntBetweenRange(1, 5));
                            firework.setFireworkMeta(fireworkMeta);
                        }
                    }
                }, i * 0.5);
            }

            return true;
        }

        private FireworkEffect createRandomFireWorkEffect() {
            return FireworkEffect.builder().withColor(this.randomColor())
                    .with(Miscellaneous.getRandomEntry(FireworkEffect.Type.values()))
                    .withTrail()
                    .flicker(Miscellaneous.getRandomTrueOrFalse())
                    .withFade(this.randomFade())
                    .build();
        }

        private Color randomColor() {
            return Color.fromRGB(
                    Miscellaneous.getRandomIntBetweenRange(0, 255),
                    Miscellaneous.getRandomIntBetweenRange(0, 255),
                    Miscellaneous.getRandomIntBetweenRange(0, 255));
        }

        private List<Color> randomFade() {
            List<Color> colors = new ArrayList<>();

            for (int i = 0; i < Miscellaneous.getRandomIntBetweenRange(0, 3); i++) {
                colors.add(this.randomColor());
            }

            return colors;
        }
    }.setCooldown(60);

    public static final ItemCosmetic MAGIC_SNOWBALL = new ItemCosmetic(Cosmetic.MAGIC_SNOWBALL) {
        @Override
        public boolean onUse(HubPlayer hubPlayer, boolean rightClick) {
            Snowball snowball = (Snowball) hubPlayer.getWorld().spawnEntity(hubPlayer.getEyeLocation().add(0, 3, 0), EntityType.SNOWBALL);
            snowball.setVelocity(hubPlayer.getDirection().multiply(1.25));
            hubPlayer.playSound(Sound.ENTITY_SNOWBALL_THROW);
            Main.scheduleSyncDelayedTask(() -> snowball.addPassenger(hubPlayer.getPlayer()), 0.05);
            return true;
        }
    }.setCooldown(5);

    public static final ItemCosmetic ENDERMANS_LEG = new ItemCosmetic(Cosmetic.ENDERMANS_LEG) {
        @Override
        public boolean onUse(HubPlayer hubPlayer, boolean rightClick) {
            final double maxDistance = 35;
            Block block = hubPlayer.rayTraceBlocks(maxDistance);

            if (block == null) {
                hubPlayer.sendErrorMessage("No block within 35 meters found.");
                hubPlayer.playErrorSound();
                return false;
            } else if (ExtraListeners.getArenaBoundingBox().contains(block.getLocation().toVector())) {
                hubPlayer.sendErrorMessage("You cannot teleport into the arena.");
                return false;
            }

            Location location = PlayerUtilities.getNearestTwoBlockSpaceAbove(block.getLocation());
            if (hubPlayer.distance(location) <= maxDistance) {
                hubPlayer.teleport(location.setDirection(hubPlayer.getDirection()));
                hubPlayer.playSound(Sound.ENTITY_ENDERMAN_TELEPORT);
                return true;
            }

            hubPlayer.sendErrorMessage("No block within 35 meters found.");
            hubPlayer.playErrorSound();

            return true;
        }
    }.setCooldown(5);

    public static final ItemCosmetic RYDER = new ItemCosmetic(Cosmetic.RYDER) {
        @Override
        public boolean onUse(HubPlayer hubPlayer, boolean rightClick) {
            Entity entity = hubPlayer.rayTraceEntity(30);

            boolean npc = false;

            if (entity != null) {
                for (SmartNPC smartNPC : SmartNPC.getSmartNPCs()) {
                    if (smartNPC.asCraftPlayer().getEntityId() == entity.getEntityId()) {
                        npc = true;
                        break;
                    }
                }
            }

            if (entity == null || entity.getType() != EntityType.PLAYER || npc || entity == hubPlayer.getPlayer()) {
                hubPlayer.sendErrorMessage("You must be looking at a player to use this.");
                hubPlayer.playErrorSound();
                return false;
            }

            List<Entity> passengers = entity.getPassengers();

            if (passengers.isEmpty()) {
                entity.addPassenger(hubPlayer.getPlayer());
            } else {
                Miscellaneous.getLastEntry(passengers).addPassenger(hubPlayer.getPlayer());
            }

            return true;
        }
    };

    public static final ArmorCosmetic MAGIC_CAP = new ArmorCosmetic(Cosmetic.MAGIC_CAP, EquipmentSlot.HEAD) {
        @Override
        public void tick(HubPlayer hubPlayer) {
            if (hubPlayer.isSneaking()) {
                hubPlayer.setVelocity(hubPlayer.getDirection().multiply(0.75));
            } else if (hubPlayer.isSprinting()) {
                hubPlayer.setVelocity(hubPlayer.getDirection().multiply(12));
            } else {
                hubPlayer.setVelocity(hubPlayer.getDirection().multiply(3));
            }
        }

        @Override
        public void doEnable(HubPlayer hubPlayer) {
            super.doEnable(hubPlayer);
            hubPlayer.getPlayer().setGravity(false);
        }

        @Override
        public void doDisable(HubPlayer hubPlayer) {
            super.doDisable(hubPlayer);
            hubPlayer.getPlayer().setGravity(true);
        }
    };

    public static final ItemCosmetic POWER = new ItemCosmetic(Cosmetic.POWER) {
        @Override
        public boolean onUse(HubPlayer hubPlayer, boolean rightClick) {
            Entity entity = hubPlayer.rayTraceEntity(50);

            boolean npc = false;

            if (entity != null) {
                for (SmartNPC smartNPC : SmartNPC.getSmartNPCs()) {
                    if (smartNPC.asCraftPlayer().getEntityId() == entity.getEntityId()) {
                        npc = true;
                        break;
                    }
                }
            }

            if (entity == null || entity.getType() != EntityType.PLAYER || npc || entity == hubPlayer.getPlayer()) {
                hubPlayer.sendErrorMessage("You must be looking at a player to use this.");
                hubPlayer.playErrorSound();
                return false;
            }

            HubPlayer toCrash = HubPlayer.getHubPlayer(entity.getUniqueId());
            if (toCrash != null) {
                toCrash.sendToHell();
                hubPlayer.sendSuccessMessage("Condemned.");
            }

            return true;
        }
    };

    public static final ItemCosmetic REPULSOR = new ItemCosmetic(Cosmetic.REPULSOR) {
        @Override
        public boolean onUse(HubPlayer hubPlayer, boolean rightClick) {
            int count = 0;
            for (HubPlayer player : this.getNearbyPlayers(hubPlayer, 10)) {
                Location location = player.getLocation();
                Vector direction = PlayerUtilities.getDirectionVector(hubPlayer.getLocation().toVector(), location.toVector()).setY(-2);
                if (Double.isFinite(direction.getX()) && Double.isFinite(direction.getY()) && Double.isFinite(direction.getZ())) {
                    player.setVelocity(direction.multiply(-5));
                }
                player.sendInfoMessage("You were repulsed by %s!", hubPlayer.getFormattedName());
                count++;
            }

            if (count != 0) {
                getWorld().playSound(hubPlayer.getLocation(), Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, 2, 1);
                hubPlayer.sendSuccessMessage("Repulsed %s%d%s player%s!", GOLD, count, GREEN, count == 1 ? "" : "s");
                return true;
            }

            hubPlayer.sendErrorMessage("No players close enough.");
            hubPlayer.playErrorSound();
            return false;
        }
    }.setCooldown(5);

    public static final PhysicalCosmetic LAUNCHER = new PhysicalCosmetic(Cosmetic.LAUNCHER, 3) {
        @Override
        public void createBlueprint() {
            this.putPlatform(-1, -1, 1, 1, 0, Material.OBSIDIAN);
            this.put(0, 0, 0, Material.RED_TERRACOTTA);
            for (int y = 1; y < 4; y++) {
                this.putPlatform(-1, -1, 1, 1, y, Material.GLASS);
                this.clear(0, y, 0);
            }
            this.putPlatform(-1, -1, 1, 1, 4, Material.OBSIDIAN);
            this.clear(0, 4, 0);
        }

        @Override
        public boolean onUse(HubPlayer hubPlayer, boolean rightClick) {
            int count = 0;

            for (HubPlayer launched : getNearbyPlayers(hubPlayer, 7, true)) {
                if (this.place(hubPlayer, launched.getLocation())) {
                    Location toTeleport = launched.getLocation().set(launched.getLocation().getBlockX() + 0.5, launched.getLocation().getBlockY() + 1, launched.getLocation().getBlockZ() + 0.5);
                    launched.teleport(toTeleport);

                    count++;
                    launched.sendInfoMessage("You have been placed in a launcher by %s!", hubPlayer.getFormattedName());
                    hubPlayer.sendSuccessMessage("Placed %s%s in a launcher.", launched.getFormattedName(), GREEN);
                    getWorld().playSound(launched.getLocation(), Sound.ENTITY_TNT_PRIMED, 2, 0);
                }
            }


            if (count == 0) {
                hubPlayer.sendErrorMessage("No players in viable areas found.");
                hubPlayer.playErrorSound();
            }

            return count > 0;
        }

        @Override
        public void tickInstance(Instance instance) {
            if (instance.ticks == 40) {
                List<Player> closest = Miscellaneous.getList(getWorld().getNearbyEntitiesByType(Player.class, instance.center, 2));
                if (!closest.isEmpty()) {
                    Player player = closest.get(0);
                    player.setVelocity(new Vector(0, 100, 0));
                    getWorld().playSound(instance.center, Sound.ENTITY_GENERIC_EXPLODE, 2, 0);
                }
            }
        }
    }.setCooldown(30);
}