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 <lynxplay101@gmail.com>
This commit is contained in:
CraftBukkit/Spigot 2021-06-14 10:01:19 +10:00
parent 9a2165ab37
commit 967b0303f3
7 changed files with 76 additions and 15 deletions

View file

@ -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<Boolean> DATA_STRAY_CONVERSION_ID = DataWatcher.a(EntitySkeleton.class, DataWatcherRegistry.BOOLEAN);
+ public static final DataWatcherObject<Boolean> 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<? extends EntitySkeleton> 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);
}

View file

@ -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)) {

View file

@ -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.");
}
}

View file

@ -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); }

View file

@ -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.");
}
}

View file

@ -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);

View file

@ -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);