From 967b0303f3e9472ec3c920512ef74828084bbd1f Mon Sep 17 00:00:00 2001 From: CraftBukkit/Spigot Date: Mon, 14 Jun 2021 10:01:19 +1000 Subject: [PATCH] SPIGOT-6507: Implement abstract skeleton and stray conversion The previous layout and class hierarchy of the skeleton API defined variances of the skeleton, such as the wither skeleton or the stray, as child types of the normal skeleton variance, which is technically incorrect, yet did not produce any specific issue as the normal skeleton variance did not have any unique logic. With the introduction of powdered snow in the 1.17 update, the normal skeleton variance now has unique logic, specifically the conversion to a stay when stuck inside powdered snow, which cannot be represented in the current API layout due to the prior mentioned hierarchy. This commit implements the hierarchy changes made in the bukkit repository by representing the new hierarchy on the craftbukkit side through the CraftAbstractSkeleton and the respective additions to the skeleton implementation in regards to the stray conversion. This commit does not break ABI yet breaks backwards compatibility due to the mentioned hierarchy changes. Plugins that previously used the Skelton interface to compute whether or not an entity is skeleton-like through instanceOf checks will now only match the normal skeleton variance instead of any skeleton-like entity. By: Bjarne Koll --- .../world/entity/monster/EntitySkeleton.patch | 24 ++++++++++++ .../org/bukkit/craftbukkit/CraftWorld.java | 5 ++- .../entity/CraftAbstractSkeleton.java | 18 +++++++++ .../craftbukkit/entity/CraftEntity.java | 3 +- .../craftbukkit/entity/CraftSkeleton.java | 37 ++++++++++++++----- .../bukkit/craftbukkit/entity/CraftStray.java | 2 +- .../entity/CraftWitherSkeleton.java | 2 +- 7 files changed, 76 insertions(+), 15 deletions(-) create mode 100644 paper-server/nms-patches/net/minecraft/world/entity/monster/EntitySkeleton.patch create mode 100644 paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractSkeleton.java diff --git a/paper-server/nms-patches/net/minecraft/world/entity/monster/EntitySkeleton.patch b/paper-server/nms-patches/net/minecraft/world/entity/monster/EntitySkeleton.patch new file mode 100644 index 0000000000..d82aa533e8 --- /dev/null +++ b/paper-server/nms-patches/net/minecraft/world/entity/monster/EntitySkeleton.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/world/entity/monster/EntitySkeleton.java ++++ b/net/minecraft/world/entity/monster/EntitySkeleton.java +@@ -16,10 +16,10 @@ + + public class EntitySkeleton extends EntitySkeletonAbstract { + +- private static final DataWatcherObject DATA_STRAY_CONVERSION_ID = DataWatcher.a(EntitySkeleton.class, DataWatcherRegistry.BOOLEAN); ++ public static final DataWatcherObject DATA_STRAY_CONVERSION_ID = DataWatcher.a(EntitySkeleton.class, DataWatcherRegistry.BOOLEAN); // PAIL private -> public + public static final String CONVERSION_TAG = "StrayConversionTime"; + private int inPowderSnowTime; +- private int conversionTime; ++ public int conversionTime; // PAIL private -> public + + public EntitySkeleton(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -80,7 +80,7 @@ + + } + +- private void a(int i) { ++ public void a(int i) { // PAIL private -> public // PAIL rename startStrayConversion + this.conversionTime = i; + this.entityData.set(EntitySkeleton.DATA_STRAY_CONVERSION_ID, true); + } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index d64110281f..dfaffdc67c 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -129,6 +129,7 @@ import org.bukkit.craftbukkit.util.CraftMagicNumbers; import org.bukkit.craftbukkit.util.CraftRayTraceResult; import org.bukkit.entity.AbstractArrow; import org.bukkit.entity.AbstractHorse; +import org.bukkit.entity.AbstractSkeleton; import org.bukkit.entity.AbstractVillager; import org.bukkit.entity.Ambient; import org.bukkit.entity.AreaEffectCloud; @@ -1590,12 +1591,12 @@ public class CraftWorld implements World { } else { entity = EntityTypes.HORSE.a(world); } - } else if (Skeleton.class.isAssignableFrom(clazz)) { + } else if (AbstractSkeleton.class.isAssignableFrom(clazz)) { if (Stray.class.isAssignableFrom(clazz)) { entity = EntityTypes.STRAY.a(world); } else if (WitherSkeleton.class.isAssignableFrom(clazz)) { entity = EntityTypes.WITHER_SKELETON.a(world); - } else { + } else if (Skeleton.class.isAssignableFrom(clazz)) { entity = EntityTypes.SKELETON.a(world); } } else if (Slime.class.isAssignableFrom(clazz)) { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractSkeleton.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractSkeleton.java new file mode 100644 index 0000000000..650556fdd1 --- /dev/null +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractSkeleton.java @@ -0,0 +1,18 @@ +package org.bukkit.craftbukkit.entity; + +import net.minecraft.world.entity.monster.EntitySkeletonAbstract; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.entity.AbstractSkeleton; +import org.bukkit.entity.Skeleton; + +public abstract class CraftAbstractSkeleton extends CraftMonster implements AbstractSkeleton { + + public CraftAbstractSkeleton(CraftServer server, EntitySkeletonAbstract entity) { + super(server, entity); + } + + @Override + public void setSkeletonType(Skeleton.SkeletonType type) { + throw new UnsupportedOperationException("Not supported."); + } +} 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 5c4f6169d5..1f990cbfa6 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 @@ -98,6 +98,7 @@ import net.minecraft.world.entity.monster.EntityPillager; import net.minecraft.world.entity.monster.EntityRavager; import net.minecraft.world.entity.monster.EntityShulker; import net.minecraft.world.entity.monster.EntitySilverfish; +import net.minecraft.world.entity.monster.EntitySkeleton; import net.minecraft.world.entity.monster.EntitySkeletonAbstract; import net.minecraft.world.entity.monster.EntitySkeletonStray; import net.minecraft.world.entity.monster.EntitySkeletonWither; @@ -272,7 +273,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { else if (entity instanceof EntitySkeletonAbstract) { if (entity instanceof EntitySkeletonStray) { return new CraftStray(server, (EntitySkeletonStray) entity); } else if (entity instanceof EntitySkeletonWither) { return new CraftWitherSkeleton(server, (EntitySkeletonWither) entity); } - else { return new CraftSkeleton(server, (EntitySkeletonAbstract) entity); } + else if (entity instanceof EntitySkeleton){ return new CraftSkeleton(server, (EntitySkeleton) entity); } } else if (entity instanceof EntityBlaze) { return new CraftBlaze(server, (EntityBlaze) entity); } else if (entity instanceof EntityWitch) { return new CraftWitch(server, (EntityWitch) entity); } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java index cebb90fd4a..17e8af2cc0 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java @@ -1,20 +1,42 @@ package org.bukkit.craftbukkit.entity; +import com.google.common.base.Preconditions; +import net.minecraft.world.entity.monster.EntitySkeleton; import net.minecraft.world.entity.monster.EntitySkeletonAbstract; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.EntityType; import org.bukkit.entity.Skeleton; -import org.bukkit.entity.Skeleton.SkeletonType; -public class CraftSkeleton extends CraftMonster implements Skeleton { +public class CraftSkeleton extends CraftAbstractSkeleton implements Skeleton { - public CraftSkeleton(CraftServer server, EntitySkeletonAbstract entity) { + public CraftSkeleton(CraftServer server, EntitySkeleton entity) { super(server, entity); } @Override - public EntitySkeletonAbstract getHandle() { - return (EntitySkeletonAbstract) entity; + public boolean isConverting() { + return this.getHandle().fw(); // PAIL rename isStrayConverting + } + + @Override + public int getConversionTime() { + Preconditions.checkState(this.isConverting(), "Entity is not converting"); + return this.getHandle().conversionTime; + } + + @Override + public void setConversionTime(int time) { + if (time < 0) { + this.getHandle().conversionTime = -1; + this.getHandle().getDataWatcher().set(EntitySkeleton.DATA_STRAY_CONVERSION_ID, false); + } else { + this.getHandle().a(time); // PAIL rename startStrayConversion + } + } + + @Override + public EntitySkeleton getHandle() { + return (EntitySkeleton) entity; } @Override @@ -31,9 +53,4 @@ public class CraftSkeleton extends CraftMonster implements Skeleton { public SkeletonType getSkeletonType() { return SkeletonType.NORMAL; } - - @Override - public void setSkeletonType(SkeletonType type) { - throw new UnsupportedOperationException("Not supported."); - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftStray.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftStray.java index 14d6308375..81193374df 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftStray.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftStray.java @@ -6,7 +6,7 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.Skeleton.SkeletonType; import org.bukkit.entity.Stray; -public class CraftStray extends CraftSkeleton implements Stray { +public class CraftStray extends CraftAbstractSkeleton implements Stray { public CraftStray(CraftServer server, EntitySkeletonStray entity) { super(server, entity); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWitherSkeleton.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWitherSkeleton.java index 3f35d939d5..65055a057f 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWitherSkeleton.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWitherSkeleton.java @@ -6,7 +6,7 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.Skeleton.SkeletonType; import org.bukkit.entity.WitherSkeleton; -public class CraftWitherSkeleton extends CraftSkeleton implements WitherSkeleton { +public class CraftWitherSkeleton extends CraftAbstractSkeleton implements WitherSkeleton { public CraftWitherSkeleton(CraftServer server, EntitySkeletonWither entity) { super(server, entity);