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

import com.lifeknight.relaymchub.Main;
import com.lifeknight.relaymchub.miscellaneous.Cooldown;
import com.lifeknight.relaymchub.player.HubPlayer;
import com.lifeknight.relayutils.basic.Miscellaneous;
import com.lifeknight.relayutils.player.cosmetics.Cosmetic;
import com.lifeknight.relayutils.utilities.PlayerUtilities;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.entity.*;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;

import java.util.HashMap;
import java.util.Map;

public class MorphCosmetic extends DefinedLobbyCosmetic {
    protected final Map<HubPlayer, Entity> playerToMorph = new HashMap<>();

    public final EntityType entityType;
    private EntityType projectile = null;
    private Material itemProjectile;
    private Particle particleProjectile = null;
    protected Location projectileLocation = null;
    protected Vector projectileVelocity = null;
    protected int projectileLife = 15;

    public MorphCosmetic(Cosmetic original, EntityType entity) {
        super(original);

        this.entityType = entity;
    }

    public MorphCosmetic setProjectile(EntityType entityType) {
        this.projectile = entityType;
        return this;
    }

    public MorphCosmetic setProjectile(Particle particle) {
        this.particleProjectile = particle;
        return this;
    }

    public MorphCosmetic setProjectile(Material material) {
        this.projectile = EntityType.DROPPED_ITEM;
        this.itemProjectile = material;

        return this;
    }

    public Entity getNewEntity(Location location, HubPlayer hubPlayer) {
        return Main.getWorld().spawnEntity(location, this.entityType);
    }

    @Override
    public void doEnable(HubPlayer hubPlayer) {
        super.doEnable(hubPlayer);
        Entity entity = this.getNewEntity(hubPlayer.getLocation(), hubPlayer);
        if (entity instanceof LivingEntity) {
            LivingEntity livingEntity = (LivingEntity) entity;
            livingEntity.setAI(false);
            livingEntity.setInvulnerable(true);
            if (livingEntity instanceof EnderDragon) {
                ((EnderDragon) livingEntity).setPhase(EnderDragon.Phase.CIRCLING);
                livingEntity.setAI(true);
            }
        }
        hubPlayer.getPlayer().setCollidable(false);
        entity.setSilent(false);
        //hubPlayer.getPlayer().setCustomNameVisible(false);
        //entity.setCustomNameVisible(true);
        this.playerToMorph.put(hubPlayer, entity);

        hubPlayer.getPlayer().setInvisible(true);
        entity.setCustomNameVisible(false);
    }

    @EventHandler
    public void onHit(EntityDamageByEntityEvent event) {
        HubPlayer hubPlayer;
        if ((hubPlayer = Miscellaneous.match(this.playerToMorph.keySet(), o -> o.getPlayer() == event.getDamager())) != null) {
            Entity entity = this.playerToMorph.get(hubPlayer);
            if (entity.getType() == this.entityType) {
                if (entity instanceof LivingEntity) {
                    ((LivingEntity) entity).swingMainHand();
                }
            }
        }
    }

    @EventHandler
    public void onInteract(PlayerInteractEvent event) {
        if (!(event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK)) {
            return;
        }
        HubPlayer hubPlayer;
        if ((hubPlayer = Miscellaneous.match(this.playerToMorph.keySet(), o -> o.getPlayer() == event.getPlayer())) != null) {
            Entity entity = this.playerToMorph.get(hubPlayer);
            if (entity.getType() == this.entityType) {
                if (hubPlayer.enoughSecondsHaveElapsed(Cooldown.MORPH_PROJECTILE)) {
                    hubPlayer.updateCooldown(Cooldown.MORPH_PROJECTILE);
                    this.activateAbility(hubPlayer, entity);
                    if (particleProjectile != null) {
                        this.launchParticleProjectile(hubPlayer, entity);
                    } else this.launchProjectile(hubPlayer, entity);
                } else {
                    hubPlayer.showCooldownWarning(Cooldown.MORPH_PROJECTILE);
                }
            }
        }
    }

    @EventHandler
    public void onInteract(PlayerInteractEntityEvent event) {
        HubPlayer hubPlayer;
        if ((hubPlayer = Miscellaneous.match(this.playerToMorph.keySet(), o -> o.getPlayer() == event.getPlayer())) != null) {
            Entity entity = this.playerToMorph.get(hubPlayer);
            if (entity.getType() == this.entityType) {
                if (hubPlayer.enoughSecondsHaveElapsed(Cooldown.MORPH_PROJECTILE)) {
                    this.activateAbility(hubPlayer, entity);
                    hubPlayer.updateCooldown(Cooldown.MORPH_PROJECTILE);
                    if (particleProjectile != null) {
                        this.launchParticleProjectile(hubPlayer, entity);
                    } else this.launchProjectile(hubPlayer, entity);
                } else {
                    hubPlayer.showCooldownWarning(Cooldown.MORPH_PROJECTILE);
                }
            }
        }
    }

    public void activateAbility(HubPlayer hubPlayer, Entity entity) {
    }

    private void launchParticleProjectile(HubPlayer hubPlayer, Entity entity) {
        Location particleLocation = entity instanceof LivingEntity ? ((LivingEntity) entity).getEyeLocation() : entity.getLocation().clone();

        Sound sound = switch (this.particleProjectile) {
            case EXPLOSION_HUGE -> Sound.ENTITY_GENERIC_EXPLODE;
            default -> Sound.ITEM_BOTTLE_FILL;
        };
        if (entity instanceof Tadpole) {
            getWorld().spawnParticle(particleProjectile, particleLocation, 2000, 25, 25, 25);
        } else getWorld().spawnParticle(particleProjectile, particleLocation, 1);
        getWorld().playSound(particleLocation, sound, 2, 1);
    }

    public void moveParticleProjectile(HubPlayer hubPlayer, Entity entity) {
        // for warden rn
    }

    @Override
    public void doDisable(HubPlayer hubPlayer) {
        super.doDisable(hubPlayer);

        Entity entity = this.playerToMorph.get(hubPlayer);
        this.playerToMorph.remove(hubPlayer);
        if (entity != null) {
            entity.remove();
        }
        hubPlayer.getPlayer().setInvisible(false);
        hubPlayer.getPlayer().setCustomNameVisible(true);
        hubPlayer.getPlayer().setCollidable(true);
    }

    @Override
    public boolean shouldDisable(DefinedLobbyCosmetic other) {
        return super.shouldDisable(other) || other instanceof MorphCosmetic || other instanceof ArmorCosmetic;
    }

    @Override
    public void tick(HubPlayer hubPlayer) {
        Entity entity = this.playerToMorph.get(hubPlayer);

        if (entity != null) {
            Player player = hubPlayer.getPlayer();
            entity.setVelocity(player.getVelocity());
            entity.teleport(player.getLocation());
            if (entity instanceof EnderDragon) {
                PlayerUtilities.setEntityDirection(entity, player);
            }
            entity.setFireTicks(0);
            if (projectileLocation != null && Main.ticks % 20 * 4 == 0)
                moveParticleProjectile(hubPlayer, entity);
        }

        if (!hubPlayer.getPlayer().isInvisible()) {
            this.disable(hubPlayer, true);
        }
    }

    public boolean hasProjectile() {
        return this.projectile != null;
    }

    public Entity spawnProjectile(HubPlayer hubPlayer, Entity entity) {
        if (!this.hasProjectile()) return null;
        if (this.itemProjectile != null) {
            Item item = getWorld().spawn(entity instanceof LivingEntity ? ((LivingEntity) entity).getEyeLocation() : entity.getLocation(), Item.class);
            item.setItemStack(new ItemStack(this.itemProjectile));
            item.setVelocity(new Vector(0, 0, 0));
            return item;
        }
        return getWorld().spawnEntity(entity instanceof LivingEntity ? ((LivingEntity) entity).getEyeLocation() : entity.getLocation(), this.projectile);
    }

    public void launchProjectile(HubPlayer hubPlayer, Entity entity) {
        Entity projectile = this.spawnProjectile(hubPlayer, entity);
        if (projectile != null) {
            projectile.setSilent(false);
            projectile.setVelocity(hubPlayer.getLocation().getDirection().multiply(this.itemProjectile == null ? 1.5 : 0.7));
        }

        Sound sound = switch (this.projectile) {
            case FIREBALL, SMALL_FIREBALL, DRAGON_FIREBALL -> Sound.ITEM_FIRECHARGE_USE;
            case DROPPED_ITEM -> Sound.ENTITY_ITEM_PICKUP;
            case ENDER_PEARL -> Sound.ENTITY_ENDER_PEARL_THROW;
            case SNOWBALL -> Sound.ENTITY_SNOWBALL_THROW;
            case WITHER_SKULL -> Sound.ENTITY_WITHER_SHOOT;
            case ARROW -> Sound.ENTITY_ARROW_SHOOT;
            default -> Sound.ITEM_BOTTLE_FILL;
        };

        getWorld().playSound(projectile, sound, 1, 1);

        Main.scheduleSyncDelayedTask(projectile::remove, 5);
    }
}