diff --git a/paper-api/src/main/java/org/bukkit/EntityEffect.java b/paper-api/src/main/java/org/bukkit/EntityEffect.java index 37c321067e..35641226d4 100644 --- a/paper-api/src/main/java/org/bukkit/EntityEffect.java +++ b/paper-api/src/main/java/org/bukkit/EntityEffect.java @@ -1,9 +1,14 @@ package org.bukkit; import com.google.common.base.Preconditions; -import org.bukkit.entity.Ageable; +import io.papermc.paper.datacomponent.DataComponentTypes; +import org.bukkit.entity.Allay; +import org.bukkit.entity.Animals; +import org.bukkit.entity.Armadillo; import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Arrow; import org.bukkit.entity.Cat; +import org.bukkit.entity.Creaking; import org.bukkit.entity.Dolphin; import org.bukkit.entity.Egg; import org.bukkit.entity.Entity; @@ -15,6 +20,8 @@ import org.bukkit.entity.Guardian; import org.bukkit.entity.Hoglin; import org.bukkit.entity.IronGolem; import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Mob; +import org.bukkit.entity.Ocelot; import org.bukkit.entity.Player; import org.bukkit.entity.Rabbit; import org.bukkit.entity.Ravager; @@ -23,7 +30,6 @@ import org.bukkit.entity.Sniffer; import org.bukkit.entity.Snowball; import org.bukkit.entity.Squid; import org.bukkit.entity.Tameable; -import org.bukkit.entity.TippedArrow; import org.bukkit.entity.Villager; import org.bukkit.entity.Warden; import org.bukkit.entity.Witch; @@ -32,32 +38,34 @@ import org.bukkit.entity.Zoglin; import org.bukkit.entity.ZombieVillager; import org.bukkit.entity.minecart.ExplosiveMinecart; import org.bukkit.entity.minecart.SpawnerMinecart; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; +import java.util.Set; /** - * A list of all Effects that can happen to entities. + * A list of all effects that can happen to entities. */ public enum EntityEffect { /** - * Colored particles from a tipped arrow. + * Colored particles from an arrow. */ - ARROW_PARTICLES(0, TippedArrow.class), + ARROW_PARTICLES(0, Arrow.class), /** * Rabbit jumping. */ RABBIT_JUMP(1, Rabbit.class), /** - * Resets a spawner minecart's delay to 200. Does not effect actual spawning - * delay, only the speed at which the entity in the spawner spins + * Resets a spawner minecart's delay to 200. Does not affect actual spawning + * delay, only the speed at which the entity in the spawner spins. */ RESET_SPAWNER_MINECART_DELAY(1, SpawnerMinecart.class), /** * When mobs get hurt. * - * @deprecated Use {@link LivingEntity#playHurtAnimation(float)} + * @deprecated use {@link LivingEntity#playHurtAnimation(float)} */ - @Deprecated(since = "1.20.1") + @Deprecated(since = "1.20.1", forRemoval = true) HURT(2, LivingEntity.class), /** * When a mob dies. @@ -65,58 +73,97 @@ public enum EntityEffect { * This will cause client-glitches! * * @deprecated split into individual effects - * @see #EGG_BREAK - * @see #SNOWBALL_BREAK + * @see #PROJECTILE_CRACK * @see #ENTITY_DEATH */ - @Deprecated(since = "1.12.2") + @Deprecated(since = "1.12.2", forRemoval = true) DEATH(3, Entity.class), /** - * Spawns the egg breaking particles + * Spawns the egg breaking particles. + * + * @deprecated use {@link #PROJECTILE_CRACK} */ + @Deprecated(since = "1.21.4", forRemoval = true) EGG_BREAK(3, Egg.class), /** - * Spawns the snowball breaking particles + * Spawns the snowball breaking particles. + * + * @deprecated use {@link #PROJECTILE_CRACK} */ + @Deprecated(since = "1.21.4", forRemoval = true) SNOWBALL_BREAK(3, Snowball.class), /** - * Plays the entity death sound and animation + * Shows the crack particles when a projectile + * hits something. + */ + PROJECTILE_CRACK(3, Egg.class, Snowball.class), + /** + * Plays the entity death sound and animation. *

* This will cause client-glitches! */ ENTITY_DEATH(3, LivingEntity.class), /** - * Plays the fang attack animation + * Plays the evoker's fang attack animation. + * + * @deprecated use {@link #ENTITY_ATTACK} */ + @Deprecated(since = "1.21.4", forRemoval = true) FANG_ATTACK(4, EvokerFangs.class), /** - * Plays the hoglin attack animation + * Plays the hoglin attack animation. + * + * @deprecated use {@link #ENTITY_ATTACK} */ + @Deprecated(since = "1.21.4", forRemoval = true) HOGLIN_ATTACK(4, Hoglin.class), /** - * Plays the iron golem attack animation + * Plays the iron golem attack animation. + * + * @deprecated use {@link #ENTITY_ATTACK} */ + @Deprecated(since = "1.21.4", forRemoval = true) IRON_GOLEN_ATTACK(4, IronGolem.class), /** - * Plays the ravager attack animation + * Plays the ravager attack animation. + * + * @deprecated use {@link #ENTITY_ATTACK} */ + @Deprecated(since = "1.21.4", forRemoval = true) RAVAGER_ATTACK(4, Ravager.class), /** - * Plays the warden attack animation + * Plays the warden attack animation. + * + * @deprecated use {@link #ENTITY_ATTACK} */ + @Deprecated(since = "1.21.4", forRemoval = true) WARDEN_ATTACK(4, Warden.class), /** - * Plays the zoglin attack animation + * Plays the zoglin attack animation. + * + * @deprecated use {@link #ENTITY_ATTACK} */ + @Deprecated(since = "1.21.4", forRemoval = true) ZOGLIN_ATTACK(4, Zoglin.class), + /** + * Plays an attack animation for the respective entities. + */ + ENTITY_ATTACK(4, EvokerFangs.class, Hoglin.class, IronGolem.class, Ravager.class, Warden.class, Zoglin.class, Creaking.class), // 5 - unused /** * The smoke when taming an entity fails. + * * @deprecated use {@link EntityEffect#TAMING_FAILED} */ - @Deprecated(since = "1.21") // Paper + @Deprecated(since = "1.21", forRemoval = true) WOLF_SMOKE(6, Tameable.class), - // Paper start - rename "wolf" effects + /** + * The hearts when taming an entity succeeds. + * + * @deprecated use {@link EntityEffect#TAMING_SUCCEEDED} + */ + @Deprecated(since = "1.21", forRemoval = true) + WOLF_HEARTS(7, Tameable.class), /** * The smoke when taming an entity fails. */ @@ -125,20 +172,13 @@ public enum EntityEffect { * The hearts when taming an entity succeeds. */ TAMING_SUCCEEDED(7, Tameable.class), - // Paper end - rename "wolf" effects - /** - * The hearts when taming an entity succeeds. - * @deprecated use {@link EntityEffect#TAMING_SUCCEEDED} - */ - @Deprecated(since = "1.21") // Paper - WOLF_HEARTS(7, Tameable.class), /** * When a wolf shakes (after being wet). * * @see EntityEffect#WOLF_SHAKE_STOP */ WOLF_SHAKE(8, Wolf.class), - // 9 - unused + // 9 - internal /** * When an entity eats a LONG_GRASS block. * @@ -146,10 +186,10 @@ public enum EntityEffect { * @see #SHEEP_EAT_GRASS * @see #TNT_MINECART_IGNITE */ - @Deprecated(since = "1.12.2") + @Deprecated(since = "1.12.2", forRemoval = true) SHEEP_EAT(10, Entity.class), /** - * Plays the sheep eating grass animation + * Plays the sheep eating grass animation. */ SHEEP_EAT_GRASS(10, Sheep.class), /** @@ -179,7 +219,8 @@ public enum EntityEffect { */ WITCH_MAGIC(15, Witch.class), /** - * When a zombie transforms into a villager by shaking violently. + * Plays the sound when a zombie villager is + * cured. */ ZOMBIE_TRANSFORM(16, ZombieVillager.class), /** @@ -187,9 +228,10 @@ public enum EntityEffect { */ FIREWORK_EXPLODE(17, Firework.class), /** - * Hearts from a breeding entity. + * Hearts from a breeding entity + * or when an Allay duplicates. */ - LOVE_HEARTS(18, Ageable.class), + LOVE_HEARTS(18, Animals.class, Allay.class), /** * Resets squid rotation. */ @@ -197,7 +239,7 @@ public enum EntityEffect { /** * Silverfish entering block, spawner spawning. */ - ENTITY_POOF(20, LivingEntity.class), + ENTITY_POOF(20, Mob.class), /** * Guardian plays the attack sound effect. */ @@ -218,9 +260,10 @@ public enum EntityEffect { ARMOR_STAND_HIT(32, ArmorStand.class), /** * Entity hurt by thorns attack. + * * @deprecated in favor of {@link LivingEntity#playHurtAnimation(float)} or {@link Entity#broadcastHurtAnimation(java.util.Collection)} */ - @Deprecated(since = "1.19.4", forRemoval = true) // Paper + @Deprecated(since = "1.19.4", forRemoval = true) THORNS_HURT(33, LivingEntity.class), /** * Iron golem puts away rose. @@ -228,16 +271,27 @@ public enum EntityEffect { IRON_GOLEM_SHEATH(34, IronGolem.class), /** * Totem prevents entity death. + * + * @deprecated see {@link #PROTECTED_FROM_DEATH} */ + @Deprecated(since = "1.21.2", forRemoval = true) TOTEM_RESURRECT(35, LivingEntity.class), + /** + * Item with {@link DataComponentTypes#DEATH_PROTECTION} prevents entity death. + * For player, the item selected will be shown for a moment on the screen, if the + * item is not found a totem will appear. + */ + PROTECTED_FROM_DEATH(35, Entity.class), /** * Entity hurt due to drowning damage. + * * @deprecated in favor of {@link LivingEntity#playHurtAnimation(float)} or {@link Entity#broadcastHurtAnimation(java.util.Collection)} */ @Deprecated(since = "1.19.4", forRemoval = true) HURT_DROWN(36, LivingEntity.class), /** * Entity hurt due to explosion damage. + * * @deprecated in favor of {@link LivingEntity#playHurtAnimation(float)} or {@link Entity#broadcastHurtAnimation(java.util.Collection)} */ @Deprecated(since = "1.19.4", forRemoval = true) @@ -252,66 +306,94 @@ public enum EntityEffect { RAVAGER_STUNNED(39, Ravager.class), /** * Cat taming failed. + * + * @deprecated use {@link #TRUSTING_FAILED} */ + @Deprecated(since = "1.14", forRemoval = true) CAT_TAME_FAIL(40, Cat.class), /** * Cat taming succeeded. + * + * @deprecated use {@link #TRUSTING_SUCCEEDED} */ + @Deprecated(since = "1.14", forRemoval = true) CAT_TAME_SUCCESS(41, Cat.class), + /** + * Ocelot trusting failed. + */ + TRUSTING_FAILED(40, Ocelot.class), + /** + * Ocelot trusting succeeded. + */ + TRUSTING_SUCCEEDED(41, Ocelot.class), /** * Villager splashes particles during a raid. */ VILLAGER_SPLASH(42, Villager.class), /** * Player's bad omen effect removed to start or increase raid difficult. + * * @deprecated raid system was overhauled in 1.20.5 */ @Deprecated(since = "1.20.5", forRemoval = true) PLAYER_BAD_OMEN_RAID(43, Player.class), /** * Entity hurt due to berry bush. Prickly! + * * @deprecated in favor of {@link LivingEntity#playHurtAnimation(float)} or {@link Entity#broadcastHurtAnimation(java.util.Collection)} */ @Deprecated(since = "1.19.4", forRemoval = true) HURT_BERRY_BUSH(44, LivingEntity.class), /** - * Fox chews the food in its mouth + * Fox chews the food in its mouth. */ FOX_CHEW(45, Fox.class), /** - * Entity teleported as a result of chorus fruit or as an enderman + * Entity teleported as a result of chorus fruit or as an enderman. */ TELEPORT_ENDER(46, LivingEntity.class), /** - * Entity breaks item in main hand + * Entity breaks item in main hand. + * + * @see org.bukkit.inventory.EquipmentSlot#HAND */ BREAK_EQUIPMENT_MAIN_HAND(47, LivingEntity.class), /** - * Entity breaks item in off hand + * Entity breaks item in off hand. + * + * @see org.bukkit.inventory.EquipmentSlot#OFF_HAND */ BREAK_EQUIPMENT_OFF_HAND(48, LivingEntity.class), /** - * Entity breaks item in helmet slot + * Entity breaks item in helmet slot. + * + * @see org.bukkit.inventory.EquipmentSlot#HEAD */ BREAK_EQUIPMENT_HELMET(49, LivingEntity.class), /** - * Entity breaks item in chestplate slot + * Entity breaks item in chestplate slot. + * + * @see org.bukkit.inventory.EquipmentSlot#CHEST */ BREAK_EQUIPMENT_CHESTPLATE(50, LivingEntity.class), /** - * Entity breaks item in legging slot + * Entity breaks item in legging slot. + * + * @see org.bukkit.inventory.EquipmentSlot#LEGS */ BREAK_EQUIPMENT_LEGGINGS(51, LivingEntity.class), /** - * Entity breaks item in boot slot + * Entity breaks item in boot slot. + * + * @see org.bukkit.inventory.EquipmentSlot#FEET */ BREAK_EQUIPMENT_BOOTS(52, LivingEntity.class), /** - * Spawns honey block slide particles at the entity's feet + * Spawns honey block slide particles at the entity's feet. */ HONEY_BLOCK_SLIDE_PARTICLES(53, Entity.class), /** - * Spawns honey block fall particles at the entity's feet + * Spawns honey block fall particles at the entity's feet. */ HONEY_BLOCK_FALL_PARTICLES(54, LivingEntity.class), /** @@ -319,110 +401,136 @@ public enum EntityEffect { */ SWAP_HAND_ITEMS(55, LivingEntity.class), /** - * Stops a wolf that is currently shaking + * Stops a wolf that is currently shaking. * * @see EntityEffect#WOLF_SHAKE */ WOLF_SHAKE_STOP(56, Wolf.class), // 57 - unused /** - * Goat lowers its head for ramming + * Goat lowers its head for ramming. * * @see #GOAT_RAISE_HEAD */ GOAT_LOWER_HEAD(58, Goat.class), /** - * Goat raises its head + * Goat raises its head. * * @see #GOAT_LOWER_HEAD */ GOAT_RAISE_HEAD(59, Goat.class), /** - * Spawns death smoke particles + * Spawns death smoke particles. */ SPAWN_DEATH_SMOKE(60, LivingEntity.class), /** - * Warden shakes its tendrils + * Warden shakes its tendrils. */ WARDEN_TENDRIL_SHAKE(61, Warden.class), /** - * Warden performs sonic attack animation
- * Does not play the sound or fire the beam + * Warden performs sonic attack animation. + *
+ * Does not play the sound or fire the beam. */ WARDEN_SONIC_ATTACK(62, Warden.class), /** - * Plays sniffer digging sound
+ * Plays sniffer digging sound. + *
* Sniffer must have a target and be in {@link Sniffer.State#SEARCHING} or - * {@link Sniffer.State#DIGGING} + * {@link Sniffer.State#DIGGING}. */ SNIFFER_DIG(63, Sniffer.class), - // Paper start - add missing EntityEffect /** * Armadillo peeks out of its shell */ - ARMADILLO_PEEK(64, org.bukkit.entity.Armadillo.class), + ARMADILLO_PEEK(64, Armadillo.class), /** - * {@link org.bukkit.inventory.EquipmentSlot#BODY} armor piece breaks + * {@link org.bukkit.inventory.EquipmentSlot#BODY} armor piece breaks. + * + * @deprecated use {@link #BREAK_EQUIPMENT_BODY} */ + @Deprecated(since = "1.21.4", forRemoval = true) BODY_BREAK(65, LivingEntity.class), + /** + * Entity breaks item in body slot. + * + * @see org.bukkit.inventory.EquipmentSlot#BODY + */ + BREAK_EQUIPMENT_BODY(65, LivingEntity.class), /** * A creaking transient shaking when being hit. * Does not apply to plain creaking entities as they are not invulnerable like the transient ones spawned by the * creaking heart. */ - SHAKE(66, org.bukkit.entity.Creaking.class); - // Paper end - add missing EntityEffect + SHAKE(66, Creaking.class); private final byte data; - private final Class applicable; + private final Set> applicableClasses; - EntityEffect(final int data, /*@NotNull*/ Class clazz) { + EntityEffect(int data, Class... applicableClasses) { + Preconditions.checkState(applicableClasses.length > 0, "Unknown applicable classes"); this.data = (byte) data; - this.applicable = clazz; + this.applicableClasses = Set.of(applicableClasses); } /** - * Gets the data value of this EntityEffect, may not be unique. + * Gets the data value of this entity effect, may not be unique. * - * @return The data value - * @apiNote Internal Use Only + * @return the data value */ - @org.jetbrains.annotations.ApiStatus.Internal // Paper + @ApiStatus.Internal public byte getData() { - return data; + return this.data; } /** - * Gets entity superclass which this affect is applicable to. + * Gets entity superclass which this entity effect is applicable to. * * @return applicable class + * @deprecated an entity effect can apply to multiple superclasses, see {@link #getApplicableClasses()} */ @NotNull + @Deprecated(since = "1.21.4") public Class getApplicable() { - return applicable; + return this.applicableClasses.iterator().next(); } /** - * Checks if this effect is applicable to the given entity. + * Gets the entity superclasses which this entity effect is applicable to. + * + * @return the applicable classes + */ + @NotNull + public Set> getApplicableClasses() { + return this.applicableClasses; + } + + /** + * Checks if this entity effect is applicable to the given entity. * * @param entity the entity to check - * @return true if applicable + * @return {@code true} if applicable */ public boolean isApplicableTo(@NotNull Entity entity) { Preconditions.checkArgument(entity != null, "Entity cannot be null"); - return isApplicableTo(entity.getClass()); + return this.isApplicableTo(entity.getClass()); } /** - * Checks if this effect is applicable to the given entity class. + * Checks if this entity effect is applicable to the given entity class. * * @param clazz the entity class to check - * @return true if applicable + * @return {@code true} if applicable */ public boolean isApplicableTo(@NotNull Class clazz) { Preconditions.checkArgument(clazz != null, "Class cannot be null"); - return applicable.isAssignableFrom(clazz); + for (Class applicableClass : this.applicableClasses) { + if (applicableClass.isAssignableFrom(clazz)) { + return true; + } + } + return false; } } diff --git a/paper-api/src/main/java/org/bukkit/Particle.java b/paper-api/src/main/java/org/bukkit/Particle.java index ddbcd977e3..31c3689343 100644 --- a/paper-api/src/main/java/org/bukkit/Particle.java +++ b/paper-api/src/main/java/org/bukkit/Particle.java @@ -146,12 +146,10 @@ public enum Particle implements Keyed { /** * Uses {@link BlockData} as DataType */ - @ApiStatus.Experimental BLOCK_CRUMBLE("block_crumble", BlockData.class), /** * Uses {@link Trail} as DataType */ - @ApiStatus.Experimental TRAIL("trail", Trail.class), OMINOUS_SPAWNING("ominous_spawning"), RAID_OMEN("raid_omen"), @@ -276,7 +274,6 @@ public enum Particle implements Keyed { /** * Options which can be applied to trail particles - a location, color and duration. */ - @ApiStatus.Experimental public static class Trail { private final Location target; diff --git a/paper-api/src/main/java/org/bukkit/entity/Entity.java b/paper-api/src/main/java/org/bukkit/entity/Entity.java index ddf7829eee..1dac39dec5 100644 --- a/paper-api/src/main/java/org/bukkit/entity/Entity.java +++ b/paper-api/src/main/java/org/bukkit/entity/Entity.java @@ -580,9 +580,9 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent *

* If the effect is not applicable to this class of entity, it will not play. * - * @param type Effect to play. + * @param effect Effect to play. */ - public void playEffect(@NotNull EntityEffect type); + public void playEffect(@NotNull EntityEffect effect); /** * Get the type of the entity. diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java index 659f0f9c7e..f8762064e0 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java @@ -544,13 +544,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { } @Override - public void playEffect(EntityEffect type) { - Preconditions.checkArgument(type != null, "Type cannot be null"); + public void playEffect(EntityEffect effect) { + Preconditions.checkArgument(effect != null, "Entity effect cannot be null"); Preconditions.checkState(!this.entity.generation, "Cannot play effect during world generation"); + Preconditions.checkArgument(effect.isApplicableTo(this), "Entity effect cannot apply to this entity"); - if (type.getApplicable().isInstance(this)) { - this.getHandle().level().broadcastEntityEvent(this.getHandle(), type.getData()); - } + this.getHandle().level().broadcastEntityEvent(this.getHandle(), effect.getData()); } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index baffa03607..3260f20b66 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -120,6 +120,7 @@ import org.bukkit.BanList; import org.bukkit.Bukkit; import org.bukkit.DyeColor; import org.bukkit.Effect; +import org.bukkit.EntityEffect; import org.bukkit.GameMode; import org.bukkit.Input; import org.bukkit.Instrument; @@ -3543,10 +3544,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player { // Paper start - entity effect API @Override - public void sendEntityEffect(final org.bukkit.EntityEffect effect, final org.bukkit.entity.Entity target) { - if (this.getHandle().connection == null || !effect.isApplicableTo(target)) { + public void sendEntityEffect(final EntityEffect effect, final org.bukkit.entity.Entity target) { + if (this.getHandle().connection == null) { return; } + Preconditions.checkArgument(effect.isApplicableTo(target), "Entity effect cannot apply to the target"); this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundEntityEventPacket(((CraftEntity) target).getHandle(), effect.getData())); } // Paper end - entity effect API