#1266: Add support for virtual entities

By: Jishuna <joshl5324@gmail.com>
This commit is contained in:
CraftBukkit/Spigot
2023-11-19 19:03:35 +13:00
parent 9a3c24e787
commit 95e4221adf
13 changed files with 472 additions and 61 deletions

View File

@@ -75,7 +75,7 @@
public int tickCount;
private int remainingFireTicks;
public boolean wasTouchingWater;
@@ -241,6 +298,25 @@
@@ -241,6 +298,26 @@
public boolean hasVisualFire;
@Nullable
private IBlockData feetBlockState;
@@ -83,6 +83,7 @@
+ public boolean persist = true;
+ public boolean visibleByDefault = true;
+ public boolean valid;
+ public boolean inWorld = false;
+ public boolean generation;
+ public int maxAirTicks = getDefaultMaxAirSupply(); // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
+ public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only
@@ -101,7 +102,7 @@
public Entity(EntityTypes<?> entitytypes, World world) {
this.id = Entity.ENTITY_COUNTER.incrementAndGet();
@@ -374,6 +450,12 @@
@@ -374,6 +451,12 @@
public void onClientRemoval() {}
public void setPose(EntityPose entitypose) {
@@ -114,7 +115,7 @@
this.entityData.set(Entity.DATA_POSE, entitypose);
}
@@ -398,6 +480,33 @@
@@ -398,6 +481,33 @@
}
protected void setRot(float f, float f1) {
@@ -148,7 +149,7 @@
this.setYRot(f % 360.0F);
this.setXRot(f1 % 360.0F);
}
@@ -439,6 +548,15 @@
@@ -439,6 +549,15 @@
this.baseTick();
}
@@ -164,7 +165,7 @@
public void baseTick() {
this.level().getProfiler().push("entityBaseTick");
this.feetBlockState = null;
@@ -453,7 +571,7 @@
@@ -453,7 +572,7 @@
this.walkDistO = this.walkDist;
this.xRotO = this.getXRot();
this.yRotO = this.getYRot();
@@ -173,7 +174,7 @@
if (this.canSpawnSprintParticle()) {
this.spawnSprintParticle();
}
@@ -488,6 +606,10 @@
@@ -488,6 +607,10 @@
if (this.isInLava()) {
this.lavaHurt();
this.fallDistance *= 0.5F;
@@ -184,7 +185,7 @@
}
this.checkBelowWorld();
@@ -539,15 +661,48 @@
@@ -539,15 +662,48 @@
public void lavaHurt() {
if (!this.fireImmune()) {
@@ -234,7 +235,7 @@
int j = i * 20;
if (this instanceof EntityLiving) {
@@ -698,6 +853,28 @@
@@ -698,6 +854,28 @@
block.updateEntityAfterFallOn(this.level(), this);
}
@@ -263,7 +264,7 @@
if (this.onGround()) {
block.stepOn(this.level(), blockposition, iblockdata, this);
}
@@ -1025,6 +1202,20 @@
@@ -1025,6 +1203,20 @@
return SoundEffects.GENERIC_SPLASH;
}
@@ -284,7 +285,7 @@
protected void checkInsideBlocks() {
AxisAlignedBB axisalignedbb = this.getBoundingBox();
BlockPosition blockposition = BlockPosition.containing(axisalignedbb.minX + 1.0E-7D, axisalignedbb.minY + 1.0E-7D, axisalignedbb.minZ + 1.0E-7D);
@@ -1439,6 +1630,7 @@
@@ -1439,6 +1631,7 @@
this.yo = d1;
this.zo = d4;
this.setPos(d3, d1, d4);
@@ -292,7 +293,7 @@
}
public void moveTo(Vec3D vec3d) {
@@ -1633,6 +1825,12 @@
@@ -1633,6 +1826,12 @@
return false;
}
@@ -305,7 +306,18 @@
public void awardKillScore(Entity entity, int i, DamageSource damagesource) {
if (entity instanceof EntityPlayer) {
CriterionTriggers.ENTITY_KILLED_PLAYER.trigger((EntityPlayer) entity, this, damagesource);
@@ -1666,7 +1864,7 @@
@@ -1661,16 +1860,22 @@
}
public boolean saveAsPassenger(NBTTagCompound nbttagcompound) {
+ // CraftBukkit start - allow excluding certain data when saving
+ return saveAsPassenger(nbttagcompound, true);
+ }
+
+ public boolean saveAsPassenger(NBTTagCompound nbttagcompound, boolean includeAll) {
+ // CraftBukkit end
if (this.removalReason != null && !this.removalReason.shouldSave()) {
return false;
} else {
String s = this.getEncodeId();
@@ -314,7 +326,36 @@
return false;
} else {
nbttagcompound.putString("id", s);
@@ -1691,6 +1889,18 @@
- this.saveWithoutId(nbttagcompound);
+ this.saveWithoutId(nbttagcompound, includeAll); // CraftBukkit - pass on includeAll
return true;
}
}
@@ -1681,16 +1886,38 @@
}
public NBTTagCompound saveWithoutId(NBTTagCompound nbttagcompound) {
+ // CraftBukkit start - allow excluding certain data when saving
+ return saveWithoutId(nbttagcompound, true);
+ }
+
+ public NBTTagCompound saveWithoutId(NBTTagCompound nbttagcompound, boolean includeAll) {
+ // CraftBukkit end
try {
- if (this.vehicle != null) {
- nbttagcompound.put("Pos", this.newDoubleList(this.vehicle.getX(), this.getY(), this.vehicle.getZ()));
- } else {
- nbttagcompound.put("Pos", this.newDoubleList(this.getX(), this.getY(), this.getZ()));
+ // CraftBukkit start - selectively save position
+ if (includeAll) {
+ if (this.vehicle != null) {
+ nbttagcompound.put("Pos", this.newDoubleList(this.vehicle.getX(), this.getY(), this.vehicle.getZ()));
+ } else {
+ nbttagcompound.put("Pos", this.newDoubleList(this.getX(), this.getY(), this.getZ()));
+ }
}
+ // CraftBukkit end
Vec3D vec3d = this.getDeltaMovement();
nbttagcompound.put("Motion", this.newDoubleList(vec3d.x, vec3d.y, vec3d.z));
@@ -333,14 +374,18 @@
nbttagcompound.put("Rotation", this.newFloatList(this.getYRot(), this.getXRot()));
nbttagcompound.putFloat("FallDistance", this.fallDistance);
nbttagcompound.putShort("Fire", (short) this.remainingFireTicks);
@@ -1699,6 +1909,25 @@
@@ -1698,7 +1925,28 @@
nbttagcompound.putBoolean("OnGround", this.onGround());
nbttagcompound.putBoolean("Invulnerable", this.invulnerable);
nbttagcompound.putInt("PortalCooldown", this.portalCooldown);
nbttagcompound.putUUID("UUID", this.getUUID());
+ // CraftBukkit start
+ // PAIL: Check above UUID reads 1.8 properly, ie: UUIDMost / UUIDLeast
+ nbttagcompound.putLong("WorldUUIDLeast", ((WorldServer) this.level).getWorld().getUID().getLeastSignificantBits());
+ nbttagcompound.putLong("WorldUUIDMost", ((WorldServer) this.level).getWorld().getUID().getMostSignificantBits());
- nbttagcompound.putUUID("UUID", this.getUUID());
+ // CraftBukkit start - selectively save uuid and world
+ if (includeAll) {
+ nbttagcompound.putUUID("UUID", this.getUUID());
+ // PAIL: Check above UUID reads 1.8 properly, ie: UUIDMost / UUIDLeast
+ nbttagcompound.putLong("WorldUUIDLeast", ((WorldServer) this.level).getWorld().getUID().getLeastSignificantBits());
+ nbttagcompound.putLong("WorldUUIDMost", ((WorldServer) this.level).getWorld().getUID().getMostSignificantBits());
+ }
+ nbttagcompound.putInt("Bukkit.updateLevel", CURRENT_LEVEL);
+ if (!this.persist) {
+ nbttagcompound.putBoolean("Bukkit.persist", this.persist);
@@ -359,7 +404,25 @@
IChatBaseComponent ichatbasecomponent = this.getCustomName();
if (ichatbasecomponent != null) {
@@ -1766,6 +1995,11 @@
@@ -1747,7 +1995,7 @@
nbttagcompound.put("Tags", nbttaglist);
}
- this.addAdditionalSaveData(nbttagcompound);
+ this.addAdditionalSaveData(nbttagcompound, includeAll); // CraftBukkit - pass on includeAll
if (this.isVehicle()) {
nbttaglist = new NBTTagList();
iterator = this.getPassengers().iterator();
@@ -1756,7 +2004,7 @@
Entity entity = (Entity) iterator.next();
NBTTagCompound nbttagcompound1 = new NBTTagCompound();
- if (entity.saveAsPassenger(nbttagcompound1)) {
+ if (entity.saveAsPassenger(nbttagcompound1, includeAll)) { // CraftBukkit - pass on includeAll
nbttaglist.add(nbttagcompound1);
}
}
@@ -1766,6 +2014,11 @@
}
}
@@ -371,7 +434,7 @@
return nbttagcompound;
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT");
@@ -1849,6 +2083,45 @@
@@ -1849,6 +2102,45 @@
} else {
throw new IllegalStateException("Entity has invalid position");
}
@@ -417,7 +480,20 @@
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT");
CrashReportSystemDetails crashreportsystemdetails = crashreport.addCategory("Entity being loaded");
@@ -1924,9 +2197,22 @@
@@ -1870,6 +2162,12 @@
return entitytypes.canSerialize() && minecraftkey != null ? minecraftkey.toString() : null;
}
+ // CraftBukkit start - allow excluding certain data when saving
+ protected void addAdditionalSaveData(NBTTagCompound nbttagcompound, boolean includeAll) {
+ addAdditionalSaveData(nbttagcompound);
+ }
+ // CraftBukkit end
+
protected abstract void readAdditionalSaveData(NBTTagCompound nbttagcompound);
protected abstract void addAdditionalSaveData(NBTTagCompound nbttagcompound);
@@ -1924,9 +2222,22 @@
} else if (this.level().isClientSide) {
return null;
} else {
@@ -440,7 +516,7 @@
this.level().addFreshEntity(entityitem);
return entityitem;
}
@@ -2024,6 +2310,18 @@
@@ -2024,6 +2335,18 @@
if (!flag && (!this.canRide(entity) || !entity.canAddPassenger(this))) {
return false;
} else {
@@ -459,7 +535,7 @@
if (this.isPassenger()) {
this.stopRiding();
}
@@ -2057,7 +2355,7 @@
@@ -2057,7 +2380,7 @@
Entity entity = this.vehicle;
this.vehicle = null;
@@ -468,7 +544,7 @@
}
}
@@ -2088,10 +2386,29 @@
@@ -2088,10 +2411,29 @@
}
}
@@ -499,7 +575,7 @@
if (this.passengers.size() == 1 && this.passengers.get(0) == entity) {
this.passengers = ImmutableList.of();
} else {
@@ -2103,6 +2420,7 @@
@@ -2103,6 +2445,7 @@
entity.boardingCooldown = 60;
this.gameEvent(GameEvent.ENTITY_DISMOUNT, entity);
}
@@ -507,7 +583,7 @@
}
protected boolean canAddPassenger(Entity entity) {
@@ -2189,14 +2507,20 @@
@@ -2189,14 +2532,20 @@
if (this.isInsidePortal) {
MinecraftServer minecraftserver = worldserver.getServer();
@@ -531,7 +607,7 @@
this.level().getProfiler().pop();
}
@@ -2320,6 +2644,13 @@
@@ -2320,6 +2669,13 @@
}
public void setSwimming(boolean flag) {
@@ -545,7 +621,7 @@
this.setSharedFlag(4, flag);
}
@@ -2369,8 +2700,12 @@
@@ -2369,8 +2725,12 @@
return this.getTeam() != null ? this.getTeam().isAlliedTo(scoreboardteambase) : false;
}
@@ -559,7 +635,7 @@
}
public boolean getSharedFlag(int i) {
@@ -2389,7 +2724,7 @@
@@ -2389,7 +2749,7 @@
}
public int getMaxAirSupply() {
@@ -568,7 +644,7 @@
}
public int getAirSupply() {
@@ -2397,7 +2732,18 @@
@@ -2397,7 +2757,18 @@
}
public void setAirSupply(int i) {
@@ -588,7 +664,7 @@
}
public int getTicksFrozen() {
@@ -2424,11 +2770,41 @@
@@ -2424,11 +2795,41 @@
public void thunderHit(WorldServer worldserver, EntityLightning entitylightning) {
this.setRemainingFireTicks(this.remainingFireTicks + 1);
@@ -632,7 +708,7 @@
}
public void onAboveBubbleCol(boolean flag) {
@@ -2593,15 +2969,38 @@
@@ -2593,15 +2994,38 @@
@Nullable
public Entity changeDimension(WorldServer worldserver) {
@@ -673,27 +749,33 @@
this.level().getProfiler().popPush("reloading");
Entity entity = this.getType().create(worldserver);
@@ -2610,9 +3009,17 @@
@@ -2609,10 +3033,22 @@
entity.restoreFrom(this);
entity.moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, entity.getXRot());
entity.setDeltaMovement(shapedetectorshape.speed);
worldserver.addDuringTeleport(entity);
- worldserver.addDuringTeleport(entity);
- if (worldserver.dimension() == World.END) {
- WorldServer.makeObsidianPlatform(worldserver);
+ if (worldserver.getTypeKey() == WorldDimension.END) { // CraftBukkit
+ WorldServer.makeObsidianPlatform(worldserver, this); // CraftBukkit
}
+ // CraftBukkit start - Don't spawn the new entity if the current entity isn't spawned
+ if (this.inWorld) {
+ worldserver.addDuringTeleport(entity);
+ if (worldserver.getTypeKey() == WorldDimension.END) { // CraftBukkit
+ WorldServer.makeObsidianPlatform(worldserver, this); // CraftBukkit
+ }
+ }
+ // CraftBukkit end
+ // CraftBukkit start - Forward the CraftEntity to the new entity
+ this.getBukkitEntity().setHandle(entity);
+ entity.bukkitEntity = this.getBukkitEntity();
+
+ if (this instanceof EntityInsentient) {
+ ((EntityInsentient) this).dropLeash(true, false); // Unleash to prevent duping of leads.
+ }
}
+ // CraftBukkit end
}
this.removeAfterChangingDimensions();
@@ -2633,20 +3040,34 @@
@@ -2633,20 +3069,34 @@
@Nullable
protected ShapeDetectorShape findDimensionEntryPoint(WorldServer worldserver) {
@@ -733,7 +815,7 @@
IBlockData iblockdata = this.level().getBlockState(this.portalEntrancePos);
EnumDirection.EnumAxis enumdirection_enumaxis;
Vec3D vec3d;
@@ -2663,8 +3084,8 @@
@@ -2663,8 +3113,8 @@
vec3d = new Vec3D(0.5D, 0.0D, 0.0D);
}
@@ -744,7 +826,7 @@
}
} else {
BlockPosition blockposition1;
@@ -2674,8 +3095,14 @@
@@ -2674,8 +3124,14 @@
} else {
blockposition1 = worldserver.getHeightmapPos(HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, worldserver.getSharedSpawnPos());
}
@@ -760,7 +842,7 @@
}
}
@@ -2683,8 +3110,23 @@
@@ -2683,8 +3139,23 @@
return BlockPortalShape.getRelativePosition(blockutil_rectangle, enumdirection_enumaxis, this.position(), this.getDimensions(this.getPose()));
}
@@ -786,7 +868,7 @@
}
public boolean canChangeDimensions() {
@@ -2804,6 +3246,12 @@
@@ -2804,6 +3275,12 @@
}
}
@@ -799,7 +881,20 @@
public boolean teleportTo(WorldServer worldserver, double d0, double d1, double d2, Set<RelativeMovement> set, float f, float f1) {
float f2 = MathHelper.clamp(f1, -90.0F, 90.0F);
@@ -2929,7 +3377,26 @@
@@ -2823,7 +3300,11 @@
entity.moveTo(d0, d1, d2, f, f2);
entity.setYHeadRot(f);
this.setRemoved(Entity.RemovalReason.CHANGED_DIMENSION);
- worldserver.addDuringTeleport(entity);
+ // CraftBukkit start - Don't spawn the new entity if the current entity isn't spawned
+ if (inWorld) {
+ worldserver.addDuringTeleport(entity);
+ }
+ // CraftBukkit end
}
return true;
@@ -2929,7 +3410,26 @@
}
public final void setBoundingBox(AxisAlignedBB axisalignedbb) {
@@ -827,7 +922,7 @@
}
protected float getEyeHeight(EntityPose entitypose, EntitySize entitysize) {
@@ -3240,6 +3707,11 @@
@@ -3240,6 +3740,11 @@
vec3d = vec3d.add(vec3d1);
++k1;
}

View File

@@ -13,7 +13,29 @@
public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityBird {
public static final float FLAP_DEGREES_PER_TICK = 120.32113F;
@@ -242,7 +248,7 @@
@@ -187,12 +193,19 @@
@Override
public void addAdditionalSaveData(NBTTagCompound nbttagcompound) {
+ // CraftBukkit start - selectively save data
+ addAdditionalSaveData(nbttagcompound, true);
+ }
+
+ @Override
+ public void addAdditionalSaveData(NBTTagCompound nbttagcompound, boolean includeAll) {
+ // CraftBukkit end
super.addAdditionalSaveData(nbttagcompound);
- if (this.hasHive()) {
+ if (includeAll && this.hasHive()) { // CraftBukkit - selectively save hive
nbttagcompound.put("HivePos", GameProfileSerializer.writeBlockPos(this.getHivePos()));
}
- if (this.hasSavedFlowerPos()) {
+ if (includeAll && this.hasSavedFlowerPos()) { // CraftBukkit - selectively save flower
nbttagcompound.put("FlowerPos", GameProfileSerializer.writeBlockPos(this.getSavedFlowerPos()));
}
@@ -242,7 +255,7 @@
}
if (b0 > 0) {
@@ -22,7 +44,7 @@
}
}
@@ -640,11 +646,14 @@
@@ -640,11 +653,14 @@
if (this.isInvulnerableTo(damagesource)) {
return false;
} else {
@@ -39,7 +61,7 @@
}
}
@@ -999,7 +1008,7 @@
@@ -999,7 +1015,7 @@
e() {
super();
@@ -48,7 +70,7 @@
this.blacklistedTargets = Lists.newArrayList();
this.setFlags(EnumSet.of(PathfinderGoal.Type.MOVE));
}
@@ -1116,7 +1125,7 @@
@@ -1116,7 +1132,7 @@
f() {
super();
@@ -57,7 +79,7 @@
this.setFlags(EnumSet.of(PathfinderGoal.Type.MOVE));
}
@@ -1216,7 +1225,7 @@
@@ -1216,7 +1232,7 @@
}
}
@@ -66,7 +88,7 @@
EntityBee.this.level().levelEvent(2005, blockposition, 0);
EntityBee.this.level().setBlockAndUpdate(blockposition, iblockdata1);
EntityBee.this.incrementNumCropsGrownSincePollination();
@@ -1289,7 +1298,7 @@
@@ -1289,7 +1305,7 @@
@Override
protected void alertOther(EntityInsentient entityinsentient, EntityLiving entityliving) {
if (entityinsentient instanceof EntityBee && this.mob.hasLineOfSight(entityliving)) {
@@ -75,7 +97,7 @@
}
}
@@ -1298,7 +1307,7 @@
@@ -1298,7 +1314,7 @@
private static class c extends PathfinderGoalNearestAttackableTarget<EntityHuman> {
c(EntityBee entitybee) {

View File

@@ -147,7 +147,7 @@
this.kill();
this.dropItem((Entity) null);
}
@@ -186,7 +251,7 @@
@@ -186,13 +251,22 @@
@Override
public void push(double d0, double d1, double d2) {
@@ -156,3 +156,18 @@
this.kill();
this.dropItem((Entity) null);
}
}
+ // CraftBukkit start - selectively save tile position
+ @Override
+ public void addAdditionalSaveData(NBTTagCompound nbttagcompound, boolean includeAll) {
+ if (includeAll) {
+ addAdditionalSaveData(nbttagcompound);
+ }
+ }
+ // CraftBukkit end
+
@Override
public void addAdditionalSaveData(NBTTagCompound nbttagcompound) {
BlockPosition blockposition = this.getPos();

View File

@@ -54,7 +54,7 @@
+
for (int i = 0; i < b0; ++i) {
- EntityChicken entitychicken = (EntityChicken) EntityTypes.CHICKEN.create(this.level());
+ Entity entitychicken = this.level().getWorld().createEntity(new org.bukkit.Location(this.level().getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F), hatchingType.getEntityClass()); // CraftBukkit
+ Entity entitychicken = this.level().getWorld().makeEntity(new org.bukkit.Location(this.level().getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F), hatchingType.getEntityClass()); // CraftBukkit
if (entitychicken != null) {
- entitychicken.setAge(-24000);