All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.nukkit.potion.Potion Maven / Gradle / Ivy

There is a newer version: 1.20.40-r1
Show newest version
package cn.nukkit.potion;

import cn.nukkit.Player;
import cn.nukkit.api.DeprecationDetails;
import cn.nukkit.api.PowerNukkitDifference;
import cn.nukkit.api.PowerNukkitOnly;
import cn.nukkit.api.Since;
import cn.nukkit.entity.Entity;
import cn.nukkit.entity.EntityLiving;
import cn.nukkit.event.entity.EntityDamageEvent;
import cn.nukkit.event.entity.EntityDamageEvent.DamageCause;
import cn.nukkit.event.entity.EntityRegainHealthEvent;
import cn.nukkit.event.potion.PotionApplyEvent;
import cn.nukkit.utils.ServerException;
import lombok.EqualsAndHashCode;

import javax.annotation.Nonnull;

/**
 * @author MagicDroidX (Nukkit Project)
 */
@PowerNukkitDifference(since = "FUTURE", info = "Implements equals() and hashcode() only in PowerNukkit")
@EqualsAndHashCode
public class Potion implements Cloneable {

    public static final int NO_EFFECTS = 0;
    public static final int WATER = 0;
    public static final int MUNDANE = 1;
    public static final int MUNDANE_II = 2;
    public static final int THICK = 3;
    public static final int AWKWARD = 4;
    public static final int NIGHT_VISION = 5;
    public static final int NIGHT_VISION_LONG = 6;
    public static final int INVISIBLE = 7;
    public static final int INVISIBLE_LONG = 8;
    public static final int LEAPING = 9;
    public static final int LEAPING_LONG = 10;
    public static final int LEAPING_II = 11;
    public static final int FIRE_RESISTANCE = 12;
    public static final int FIRE_RESISTANCE_LONG = 13;
    public static final int SPEED = 14;
    public static final int SPEED_LONG = 15;
    public static final int SPEED_II = 16;
    public static final int SLOWNESS = 17;
    public static final int SLOWNESS_LONG = 18;
    public static final int WATER_BREATHING = 19;
    public static final int WATER_BREATHING_LONG = 20;
    public static final int INSTANT_HEALTH = 21;
    public static final int INSTANT_HEALTH_II = 22;
    public static final int HARMING = 23;
    public static final int HARMING_II = 24;
    public static final int POISON = 25;
    public static final int POISON_LONG = 26;
    public static final int POISON_II = 27;
    public static final int REGENERATION = 28;
    public static final int REGENERATION_LONG = 29;
    public static final int REGENERATION_II = 30;
    public static final int STRENGTH = 31;
    public static final int STRENGTH_LONG = 32;
    public static final int STRENGTH_II = 33;
    public static final int WEAKNESS = 34;
    public static final int WEAKNESS_LONG = 35;
    public static final int WITHER_II = 36;
    public static final int TURTLE_MASTER = 37;
    public static final int TURTLE_MASTER_LONG = 38;
    public static final int TURTLE_MASTER_II = 39;
    public static final int SLOW_FALLING = 40;
    public static final int SLOW_FALLING_LONG = 41;
    @Since("1.4.0.0-PN") @PowerNukkitOnly public static final int SLOWNESS_IV = 42;

    @Since("1.4.0.0-PN")
    @Deprecated
    @DeprecationDetails(since = "FUTURE", by = "PowerNukkit", reason =
            "Incorrect name, there is vanilla potion with slowness long 2, the result of potion with slowness 1 + glowstone is slowness 4",
            replaceWith = "SLOWNESS_IV")
    public static final int SLOWNESS_LONG_II = SLOWNESS_IV;

    protected static Potion[] potions;

    public static void init() {
        potions = new Potion[256];

        potions[Potion.WATER] = new Potion(Potion.WATER);
        potions[Potion.MUNDANE] = new Potion(Potion.MUNDANE);
        potions[Potion.MUNDANE_II] = new Potion(Potion.MUNDANE_II, 2);
        potions[Potion.THICK] = new Potion(Potion.THICK);
        potions[Potion.AWKWARD] = new Potion(Potion.AWKWARD);
        potions[Potion.NIGHT_VISION] = new Potion(Potion.NIGHT_VISION);
        potions[Potion.NIGHT_VISION_LONG] = new Potion(Potion.NIGHT_VISION_LONG);
        potions[Potion.INVISIBLE] = new Potion(Potion.INVISIBLE);
        potions[Potion.INVISIBLE_LONG] = new Potion(Potion.INVISIBLE_LONG);
        potions[Potion.LEAPING] = new Potion(Potion.LEAPING);
        potions[Potion.LEAPING_LONG] = new Potion(Potion.LEAPING_LONG);
        potions[Potion.LEAPING_II] = new Potion(Potion.LEAPING_II, 2);
        potions[Potion.FIRE_RESISTANCE] = new Potion(Potion.FIRE_RESISTANCE);
        potions[Potion.FIRE_RESISTANCE_LONG] = new Potion(Potion.FIRE_RESISTANCE_LONG);
        potions[Potion.SPEED] = new Potion(Potion.SPEED);
        potions[Potion.SPEED_LONG] = new Potion(Potion.SPEED_LONG);
        potions[Potion.SPEED_II] = new Potion(Potion.SPEED_II, 2);
        potions[Potion.SLOWNESS] = new Potion(Potion.SLOWNESS);
        potions[Potion.SLOWNESS_LONG] = new Potion(Potion.SLOWNESS_LONG);
        potions[Potion.WATER_BREATHING] = new Potion(Potion.WATER_BREATHING);
        potions[Potion.WATER_BREATHING_LONG] = new Potion(Potion.WATER_BREATHING_LONG);
        potions[Potion.INSTANT_HEALTH] = new Potion(Potion.INSTANT_HEALTH);
        potions[Potion.INSTANT_HEALTH_II] = new Potion(Potion.INSTANT_HEALTH_II, 2);
        potions[Potion.HARMING] = new Potion(Potion.HARMING);
        potions[Potion.HARMING_II] = new Potion(Potion.HARMING_II, 2);
        potions[Potion.POISON] = new Potion(Potion.POISON);
        potions[Potion.POISON_LONG] = new Potion(Potion.POISON_LONG);
        potions[Potion.POISON_II] = new Potion(Potion.POISON_II, 2);
        potions[Potion.REGENERATION] = new Potion(Potion.REGENERATION);
        potions[Potion.REGENERATION_LONG] = new Potion(Potion.REGENERATION_LONG);
        potions[Potion.REGENERATION_II] = new Potion(Potion.REGENERATION_II, 2);
        potions[Potion.STRENGTH] = new Potion(Potion.STRENGTH);
        potions[Potion.STRENGTH_LONG] = new Potion(Potion.STRENGTH_LONG);
        potions[Potion.STRENGTH_II] = new Potion(Potion.STRENGTH_II, 2);
        potions[Potion.WEAKNESS] = new Potion(Potion.WEAKNESS);
        potions[Potion.WEAKNESS_LONG] = new Potion(Potion.WEAKNESS_LONG);
        potions[Potion.WITHER_II] = new Potion(Potion.WITHER_II, 2);
        potions[Potion.TURTLE_MASTER] = new Potion(Potion.TURTLE_MASTER);
        potions[Potion.TURTLE_MASTER_LONG] = new Potion(Potion.TURTLE_MASTER_LONG);
        potions[Potion.TURTLE_MASTER_II] = new Potion(Potion.TURTLE_MASTER_II, 2);
        potions[Potion.SLOW_FALLING] = new Potion(Potion.SLOW_FALLING);
        potions[Potion.SLOW_FALLING_LONG] = new Potion(Potion.SLOW_FALLING_LONG);
        potions[Potion.SLOWNESS_IV] = new Potion(Potion.SLOWNESS, 4);
    }

    public static Potion getPotion(int id) {
        if (id >= 0 && id < potions.length && potions[id] != null) {
            return potions[id].clone();
        } else {
            throw new ServerException("Effect id: " + id + " not found");
        }
    }

    public static Potion getPotionByName(String name) {
        try {
            byte id = Potion.class.getField(name.toUpperCase()).getByte(null);
            return getPotion(id);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    protected final int id;

    protected final int level;

    protected boolean splash = false;

    public Potion(int id) {
        this(id, 1);
    }

    public Potion(int id, int level) {
        this(id, level, false);
    }

    public Potion(int id, int level, boolean splash) {
        this.id = id;
        this.level = level;
        this.splash = splash;
    }

    public Effect getEffect() {
        return getEffect(this.getId(), this.isSplash());
    }

    public int getId() {
        return id;
    }

    public int getLevel() {
        return level;
    }

    public boolean isSplash() {
        return splash;
    }

    public Potion setSplash(boolean splash) {
        this.splash = splash;
        return this;
    }

    public void applyPotion(Entity entity) {
        applyPotion(entity, 0.5);
    }

    public void applyPotion(Entity entity, double health) {
        if (!(entity instanceof EntityLiving)) {
            return;
        }

        Effect applyEffect = getEffect(this.getId(), this.isSplash());

        if (applyEffect == null) {
            return;
        }

        if (entity instanceof Player) {
            if (!((Player) entity).isSurvival() && !((Player) entity).isAdventure() && applyEffect.isBad()) {
                return;
            }
        }

        PotionApplyEvent event = new PotionApplyEvent(this, applyEffect, entity);

        entity.getServer().getPluginManager().callEvent(event);
        if (event.isCancelled()) {
            return;
        }

        applyEffect = event.getApplyEffect();

        switch (this.getId()) {
            case INSTANT_HEALTH:
            case INSTANT_HEALTH_II:
                if (entity.isUndead())
                    entity.attack(new EntityDamageEvent(entity, DamageCause.MAGIC, (float) (health * (double) (6 << (applyEffect.getAmplifier() + 1)))));
                else
                    entity.heal(new EntityRegainHealthEvent(entity, (float) (health * (double) (4 << (applyEffect.getAmplifier() + 1))), EntityRegainHealthEvent.CAUSE_MAGIC));
                break;
            case HARMING:
            case HARMING_II:
                if (entity.isUndead())
                    entity.heal(new EntityRegainHealthEvent(entity, (float) (health * (double) (4 << (applyEffect.getAmplifier() + 1))), EntityRegainHealthEvent.CAUSE_MAGIC));
                else
                    entity.attack(new EntityDamageEvent(entity, DamageCause.MAGIC, (float) (health * (double) (6 << (applyEffect.getAmplifier() + 1)))));
                break;
            default:
                int duration = (int) ((isSplash() ? health : 1) * (double) applyEffect.getDuration() + 0.5);
                applyEffect.setDuration(duration);
                entity.addEffect(applyEffect);
        }
    }

    @Override
    public Potion clone() {
        try {
            return (Potion) super.clone();
        } catch (CloneNotSupportedException e) {
            return null;
        }
    }

    public static Effect getEffect(int potionType, boolean isSplash) {
        Effect effect;
        switch (potionType) {
            case NIGHT_VISION:
            case NIGHT_VISION_LONG:
                effect = Effect.getEffect(Effect.NIGHT_VISION);
                break;
            case INVISIBLE:
            case INVISIBLE_LONG:
                effect = Effect.getEffect(Effect.INVISIBILITY);
                break;
            case LEAPING:
            case LEAPING_LONG:
            case LEAPING_II:
                effect = Effect.getEffect(Effect.JUMP);
                break;
            case FIRE_RESISTANCE:
            case FIRE_RESISTANCE_LONG:
                effect = Effect.getEffect(Effect.FIRE_RESISTANCE);
                break;
            case SPEED:
            case SPEED_LONG:
            case SPEED_II:
                effect = Effect.getEffect(Effect.SPEED);
                break;
            case SLOWNESS:
            case SLOWNESS_LONG:
            case SLOWNESS_IV:
                effect = Effect.getEffect(Effect.SLOWNESS);
                break;
            case WATER_BREATHING:
            case WATER_BREATHING_LONG:
                effect = Effect.getEffect(Effect.WATER_BREATHING);
                break;
            case INSTANT_HEALTH:
            case INSTANT_HEALTH_II:
                return Effect.getEffect(Effect.HEALING);
            case HARMING:
            case HARMING_II:
                return Effect.getEffect(Effect.HARMING);
            case POISON:
            case POISON_LONG:
            case POISON_II:
                effect = Effect.getEffect(Effect.POISON);
                break;
            case REGENERATION:
            case REGENERATION_LONG:
            case REGENERATION_II:
                effect = Effect.getEffect(Effect.REGENERATION);
                break;
            case STRENGTH:
            case STRENGTH_LONG:
            case STRENGTH_II:
                effect = Effect.getEffect(Effect.STRENGTH);
                break;
            case WEAKNESS:
            case WEAKNESS_LONG:
                effect = Effect.getEffect(Effect.WEAKNESS);
                break;
            case WITHER_II:
                effect = Effect.getEffect(Effect.WITHER);
                break;
            default:
                return null;
        }

        if (getLevel(potionType) > 1) {
            effect.setAmplifier(1);
        }

        if (!isInstant(potionType)) {
            effect.setDuration(20 * getApplySeconds(potionType, isSplash));
        }

        return effect;
    }

    public static int getLevel(int potionType) {
        switch (potionType) {
            case SLOWNESS_IV:
                return 4;
            case MUNDANE_II:
            case LEAPING_II:
            case SPEED_II:
            case INSTANT_HEALTH_II:
            case HARMING_II:
            case POISON_II:
            case REGENERATION_II:
            case STRENGTH_II:
            case WITHER_II:
            case TURTLE_MASTER_II:
                return 2;
            default:
                return 1;
        }
    }

    public static boolean isInstant(int potionType) {
        switch (potionType) {
            case INSTANT_HEALTH:
            case INSTANT_HEALTH_II:
            case HARMING:
            case HARMING_II:
                return true;
            default:
                return false;
        }
    }

    public static int getApplySeconds(int potionType, boolean isSplash) {
        if (isSplash) {
            switch (potionType) {
                case NIGHT_VISION:
                case STRENGTH:
                case WATER_BREATHING:
                case SPEED:
                case FIRE_RESISTANCE:
                case LEAPING:
                case INVISIBLE:
                    return 135;
                case NIGHT_VISION_LONG:
                case STRENGTH_LONG:
                case WATER_BREATHING_LONG:
                case SPEED_LONG:
                case FIRE_RESISTANCE_LONG:
                case LEAPING_LONG:
                case INVISIBLE_LONG:
                    return 360;
                case LEAPING_II:
                case WEAKNESS:
                case STRENGTH_II:
                case SLOWNESS:
                case SPEED_II:
                    return 67;
                case SLOWNESS_LONG:
                case WEAKNESS_LONG:
                    return 180;
                case POISON:
                case REGENERATION:
                    return 33;
                case POISON_LONG:
                case REGENERATION_LONG:
                    return 90;
                case POISON_II:
                case REGENERATION_II:
                    return 16;
                case WITHER_II:
                    return 30;
                case SLOWNESS_IV:
                    return 15;
                default:
                    return 0;
            }
        } else {
            switch (potionType) {
                case NIGHT_VISION:
                case STRENGTH:
                case WATER_BREATHING:
                case SPEED:
                case FIRE_RESISTANCE:
                case LEAPING:
                case INVISIBLE:
                    return 180;
                case NIGHT_VISION_LONG:
                case STRENGTH_LONG:
                case WATER_BREATHING_LONG:
                case SPEED_LONG:
                case FIRE_RESISTANCE_LONG:
                case LEAPING_LONG:
                case INVISIBLE_LONG:
                    return 480;
                case LEAPING_II:
                case WEAKNESS:
                case STRENGTH_II:
                case SLOWNESS:
                    return 90;
                case SLOWNESS_LONG:
                case WEAKNESS_LONG:
                    return 240;
                case POISON:
                case REGENERATION:
                    return 45;
                case POISON_LONG:
                case REGENERATION_LONG:
                    return 120;
                case POISON_II:
                case REGENERATION_II:
                    return 22;
                case WITHER_II:
                    return 30;
                case SLOWNESS_IV:
                    return 20;
                case SPEED_II:
                    return 90;
                default:
                    return 0;
            }
        }
    }

    @PowerNukkitOnly
    @Since("FUTURE")
    @Nonnull
    public String getPotionTypeName() {
        switch (getId()) {
            case WATER:
                return "Water";
            case MUNDANE:
            case MUNDANE_II:
                return "Mundane";
            case THICK:
                return "Thick";
            case AWKWARD:
                return "Awkward";
            case NIGHT_VISION_LONG:
            case NIGHT_VISION:
                return "Night Vision";
            case INVISIBLE:
            case INVISIBLE_LONG:
                return "Invisibility";
            case LEAPING_LONG:
            case LEAPING_II:
            case LEAPING:
                return "Leaping";
            case FIRE_RESISTANCE_LONG:
            case FIRE_RESISTANCE:
                return "Fire Resistance";
            case SPEED:
            case SPEED_LONG:
            case SPEED_II:
                return "Swiftness";
            case SLOWNESS_LONG:
            case SLOWNESS:
            case SLOWNESS_IV:
                return "Slowness";
            case WATER_BREATHING_LONG:
            case WATER_BREATHING:
                return "Water Breathing";
            case INSTANT_HEALTH:
            case INSTANT_HEALTH_II:
                return "Healing";
            case HARMING:
            case HARMING_II:
                return "Harming";
            case POISON:
            case POISON_LONG:
            case POISON_II:
                return "Poison";
            case REGENERATION:
            case REGENERATION_LONG:
            case REGENERATION_II:
                return "Regeneration";
            case STRENGTH:
            case STRENGTH_LONG:
            case STRENGTH_II:
                return "Strength";
            case WEAKNESS:
            case WEAKNESS_LONG:
                return "Weakness";
            case WITHER_II:
                return "Decay";
            case TURTLE_MASTER:
            case TURTLE_MASTER_LONG:
            case TURTLE_MASTER_II:
                return "Turtle Master";
            case SLOW_FALLING:
            case SLOW_FALLING_LONG:
                return "Slow Falling";
            default:
                return "";
        }
    }

    @PowerNukkitOnly
    @Since("FUTURE")
    @Nonnull
    public String getName() {
        String name = getPotionTypeName();
        StringBuilder finalName = new StringBuilder(255).append("Potion");
        if (!name.isEmpty()) {
            int id = getId();
            if (id >= TURTLE_MASTER && id <= TURTLE_MASTER_II) {
                finalName.append(" of the ").append(name);
            } else if (id <= AWKWARD) {
                finalName.insert(0, name + " ");
            } else {
                finalName.append(" of ").append(name);
            }
        }

        int currentLevel = getLevel();
        if (currentLevel > 1) {
            finalName.append(' ');
            appendRoman(finalName, currentLevel);
        }
        return finalName.toString();
    }

    @PowerNukkitOnly
    @Since("FUTURE")
    @Nonnull
    public String getRomanLevel() {
        int currentLevel = getLevel();
        if (currentLevel == 0) {
            return "0";
        }

        StringBuilder sb = new StringBuilder(4);
        if (currentLevel < 0) {
            sb.append('-');
            currentLevel *= -1;
        }

        appendRoman(sb, currentLevel);
        return sb.toString();
    }

    private static void appendRoman(StringBuilder sb, int num) {
        int times;
        String[] romans = new String[] { "I", "IV", "V", "IX", "X", "XL", "L",
                "XC", "C", "CD", "D", "CM", "M" };
        int[] ints = new int[] { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500,
                900, 1000 };
        for (int i = ints.length - 1; i >= 0; i--) {
            times = num / ints[i];
            num %= ints[i];
            while (times > 0) {
                sb.append(romans[i]);
                times--;
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy