mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-02 07:23:43 +01:00
847ad16eed
This patch prevents entities from riding a vehicle they're already riding on. When trying to enter a boat the client will send up to two packets for each hand causing the server to think they should enter the boat twice, despite the first interaction being sufficient.
694 lines
28 KiB
Diff
694 lines
28 KiB
Diff
--- a/net/minecraft/server/Entity.java
|
|
+++ b/net/minecraft/server/Entity.java
|
|
@@ -21,8 +21,57 @@
|
|
import org.apache.logging.log4j.LogManager;
|
|
import org.apache.logging.log4j.Logger;
|
|
|
|
+// CraftBukkit start
|
|
+import org.bukkit.Bukkit;
|
|
+import org.bukkit.Location;
|
|
+import org.bukkit.Server;
|
|
+import org.bukkit.block.BlockFace;
|
|
+import org.bukkit.command.CommandSender;
|
|
+import org.bukkit.entity.Hanging;
|
|
+import org.bukkit.entity.LivingEntity;
|
|
+import org.bukkit.entity.Vehicle;
|
|
+import org.bukkit.event.entity.EntityCombustByEntityEvent;
|
|
+import org.bukkit.event.hanging.HangingBreakByEntityEvent;
|
|
+import org.bukkit.event.vehicle.VehicleBlockCollisionEvent;
|
|
+import org.bukkit.event.vehicle.VehicleEnterEvent;
|
|
+import org.bukkit.event.vehicle.VehicleExitEvent;
|
|
+import org.bukkit.craftbukkit.CraftWorld;
|
|
+import org.bukkit.craftbukkit.entity.CraftEntity;
|
|
+import org.bukkit.craftbukkit.entity.CraftPlayer;
|
|
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
|
+import org.bukkit.entity.Pose;
|
|
+import org.bukkit.event.entity.EntityAirChangeEvent;
|
|
+import org.bukkit.event.entity.EntityCombustEvent;
|
|
+import org.bukkit.event.entity.EntityDropItemEvent;
|
|
+import org.bukkit.event.entity.EntityPortalEvent;
|
|
+import org.bukkit.event.entity.EntityPoseChangeEvent;
|
|
+import org.bukkit.event.player.PlayerTeleportEvent;
|
|
+import org.bukkit.plugin.PluginManager;
|
|
+// CraftBukkit end
|
|
+
|
|
public abstract class Entity implements INamableTileEntity, ICommandListener {
|
|
|
|
+ // CraftBukkit start
|
|
+ private static final int CURRENT_LEVEL = 2;
|
|
+ static boolean isLevelAtLeast(NBTTagCompound tag, int level) {
|
|
+ return tag.hasKey("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level;
|
|
+ }
|
|
+
|
|
+ private CraftEntity bukkitEntity;
|
|
+
|
|
+ public CraftEntity getBukkitEntity() {
|
|
+ if (bukkitEntity == null) {
|
|
+ bukkitEntity = CraftEntity.getEntity(world.getServer(), this);
|
|
+ }
|
|
+ return bukkitEntity;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public CommandSender getBukkitSender(CommandListenerWrapper wrapper) {
|
|
+ return getBukkitEntity();
|
|
+ }
|
|
+ // CraftBukkit end
|
|
+
|
|
protected static final Logger LOGGER = LogManager.getLogger();
|
|
private static final AtomicInteger entityCount = new AtomicInteger();
|
|
private static final List<ItemStack> c = Collections.emptyList();
|
|
@@ -111,6 +160,20 @@
|
|
private long aG;
|
|
private EntitySize size;
|
|
private float headHeight;
|
|
+ // CraftBukkit start
|
|
+ public boolean persist = true;
|
|
+ public boolean valid;
|
|
+ public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only
|
|
+ public boolean forceExplosionKnockback; // SPIGOT-949
|
|
+
|
|
+ public float getBukkitYaw() {
|
|
+ return this.yaw;
|
|
+ }
|
|
+
|
|
+ public boolean isChunkLoaded() {
|
|
+ return world.isChunkLoaded((int) Math.floor(this.locX()) >> 4, (int) Math.floor(this.locZ()) >> 4);
|
|
+ }
|
|
+ // CraftBukkit end
|
|
|
|
public Entity(EntityTypes<?> entitytypes, World world) {
|
|
this.id = Entity.entityCount.incrementAndGet();
|
|
@@ -214,6 +277,12 @@
|
|
}
|
|
|
|
public void setPose(EntityPose entitypose) {
|
|
+ // CraftBukkit start
|
|
+ if (entitypose == this.getPose()) {
|
|
+ return;
|
|
+ }
|
|
+ this.world.getServer().getPluginManager().callEvent(new EntityPoseChangeEvent(this.getBukkitEntity(), Pose.values()[entitypose.ordinal()]));
|
|
+ // CraftBukkit end
|
|
this.datawatcher.set(Entity.POSE, entitypose);
|
|
}
|
|
|
|
@@ -230,6 +299,33 @@
|
|
}
|
|
|
|
protected void setYawPitch(float f, float f1) {
|
|
+ // CraftBukkit start - yaw was sometimes set to NaN, so we need to set it back to 0
|
|
+ if (Float.isNaN(f)) {
|
|
+ f = 0;
|
|
+ }
|
|
+
|
|
+ if (f == Float.POSITIVE_INFINITY || f == Float.NEGATIVE_INFINITY) {
|
|
+ if (this instanceof EntityPlayer) {
|
|
+ this.world.getServer().getLogger().warning(this.getName() + " was caught trying to crash the server with an invalid yaw");
|
|
+ ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite yaw (Hacking?)");
|
|
+ }
|
|
+ f = 0;
|
|
+ }
|
|
+
|
|
+ // pitch was sometimes set to NaN, so we need to set it back to 0
|
|
+ if (Float.isNaN(f1)) {
|
|
+ f1 = 0;
|
|
+ }
|
|
+
|
|
+ if (f1 == Float.POSITIVE_INFINITY || f1 == Float.NEGATIVE_INFINITY) {
|
|
+ if (this instanceof EntityPlayer) {
|
|
+ this.world.getServer().getLogger().warning(this.getName() + " was caught trying to crash the server with an invalid pitch");
|
|
+ ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite pitch (Hacking?)");
|
|
+ }
|
|
+ f1 = 0;
|
|
+ }
|
|
+ // CraftBukkit end
|
|
+
|
|
this.yaw = f % 360.0F;
|
|
this.pitch = f1 % 360.0F;
|
|
}
|
|
@@ -240,6 +336,7 @@
|
|
float f1 = this.size.height;
|
|
|
|
this.a(new AxisAlignedBB(d0 - (double) f, d1, d2 - (double) f, d0 + (double) f, d1 + (double) f1, d2 + (double) f));
|
|
+ if (valid) ((WorldServer) world).chunkCheck(this); // CraftBukkit
|
|
}
|
|
|
|
protected void ac() {
|
|
@@ -254,6 +351,15 @@
|
|
this.entityBaseTick();
|
|
}
|
|
|
|
+ // CraftBukkit start
|
|
+ public void postTick() {
|
|
+ // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle
|
|
+ if (!(this instanceof EntityPlayer)) {
|
|
+ this.doPortalTick();
|
|
+ }
|
|
+ }
|
|
+ // CraftBukkit end
|
|
+
|
|
public void entityBaseTick() {
|
|
this.world.getMethodProfiler().enter("entityBaseTick");
|
|
if (this.isPassenger() && this.getVehicle().dead) {
|
|
@@ -267,7 +373,7 @@
|
|
this.z = this.A;
|
|
this.lastPitch = this.pitch;
|
|
this.lastYaw = this.yaw;
|
|
- this.doPortalTick();
|
|
+ if (this instanceof EntityPlayer) this.doPortalTick(); // CraftBukkit - // Moved up to postTick
|
|
if (this.aK()) {
|
|
this.aL();
|
|
}
|
|
@@ -322,12 +428,44 @@
|
|
|
|
protected void burnFromLava() {
|
|
if (!this.isFireProof()) {
|
|
- this.setOnFire(15);
|
|
+ // CraftBukkit start - Fallen in lava TODO: this event spams!
|
|
+ if (this instanceof EntityLiving && fireTicks <= 0) {
|
|
+ // not on fire yet
|
|
+ // TODO: shouldn't be sending null for the block
|
|
+ org.bukkit.block.Block damager = null; // ((WorldServer) this.l).getWorld().getBlockAt(i, j, k);
|
|
+ org.bukkit.entity.Entity damagee = this.getBukkitEntity();
|
|
+ EntityCombustEvent combustEvent = new org.bukkit.event.entity.EntityCombustByBlockEvent(damager, damagee, 15);
|
|
+ this.world.getServer().getPluginManager().callEvent(combustEvent);
|
|
+
|
|
+ if (!combustEvent.isCancelled()) {
|
|
+ this.setOnFire(combustEvent.getDuration(), false);
|
|
+ }
|
|
+ } else {
|
|
+ // This will be called every single tick the entity is in lava, so don't throw an event
|
|
+ this.setOnFire(15, false);
|
|
+ }
|
|
+ // CraftBukkit end - we also don't throw an event unless the object in lava is living, to save on some event calls
|
|
this.damageEntity(DamageSource.LAVA, 4.0F);
|
|
}
|
|
}
|
|
|
|
public void setOnFire(int i) {
|
|
+ // CraftBukkit start
|
|
+ this.setOnFire(i, true);
|
|
+ }
|
|
+
|
|
+ public void setOnFire(int i, boolean callEvent) {
|
|
+ if (callEvent) {
|
|
+ EntityCombustEvent event = new EntityCombustEvent(this.getBukkitEntity(), i);
|
|
+ this.world.getServer().getPluginManager().callEvent(event);
|
|
+
|
|
+ if (event.isCancelled()) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ i = event.getDuration();
|
|
+ }
|
|
+ // CraftBukkit end
|
|
int j = i * 20;
|
|
|
|
if (this instanceof EntityLiving) {
|
|
@@ -424,6 +562,28 @@
|
|
block.a((IBlockAccess) this.world, this);
|
|
}
|
|
|
|
+ // CraftBukkit start
|
|
+ if (positionChanged && getBukkitEntity() instanceof Vehicle) {
|
|
+ Vehicle vehicle = (Vehicle) this.getBukkitEntity();
|
|
+ org.bukkit.block.Block bl = this.world.getWorld().getBlockAt(MathHelper.floor(this.locX()), MathHelper.floor(this.locY()), MathHelper.floor(this.locZ()));
|
|
+
|
|
+ if (vec3d.x > vec3d1.x) {
|
|
+ bl = bl.getRelative(BlockFace.EAST);
|
|
+ } else if (vec3d.x < vec3d1.x) {
|
|
+ bl = bl.getRelative(BlockFace.WEST);
|
|
+ } else if (vec3d.z > vec3d1.z) {
|
|
+ bl = bl.getRelative(BlockFace.SOUTH);
|
|
+ } else if (vec3d.z < vec3d1.z) {
|
|
+ bl = bl.getRelative(BlockFace.NORTH);
|
|
+ }
|
|
+
|
|
+ if (!bl.getType().isAir()) {
|
|
+ VehicleBlockCollisionEvent event = new VehicleBlockCollisionEvent(vehicle, bl);
|
|
+ world.getServer().getPluginManager().callEvent(event);
|
|
+ }
|
|
+ }
|
|
+ // CraftBukkit end
|
|
+
|
|
if (this.onGround && !this.br()) {
|
|
block.stepOn(this.world, blockposition, this);
|
|
}
|
|
@@ -698,6 +858,7 @@
|
|
AxisAlignedBB axisalignedbb = this.getBoundingBox();
|
|
|
|
this.setPositionRaw((axisalignedbb.minX + axisalignedbb.maxX) / 2.0D, axisalignedbb.minY, (axisalignedbb.minZ + axisalignedbb.maxZ) / 2.0D);
|
|
+ if (valid) ((WorldServer) world).chunkCheck(this); // CraftBukkit
|
|
}
|
|
|
|
protected SoundEffect getSoundSwim() {
|
|
@@ -1036,6 +1197,13 @@
|
|
}
|
|
|
|
public void spawnIn(World world) {
|
|
+ // CraftBukkit start
|
|
+ if (world == null) {
|
|
+ die();
|
|
+ this.world = ((CraftWorld) Bukkit.getServer().getWorlds().get(0)).getHandle();
|
|
+ return;
|
|
+ }
|
|
+ // CraftBukkit end
|
|
this.world = world;
|
|
}
|
|
|
|
@@ -1051,6 +1219,7 @@
|
|
this.pitch = MathHelper.a(f1, -90.0F, 90.0F) % 360.0F;
|
|
this.lastYaw = this.yaw;
|
|
this.lastPitch = this.pitch;
|
|
+ world.getChunkAt((int) Math.floor(this.locX()) >> 4, (int) Math.floor(this.locZ()) >> 4); // CraftBukkit
|
|
}
|
|
|
|
public void c(Vec3D vec3d) {
|
|
@@ -1235,7 +1404,7 @@
|
|
public boolean a_(NBTTagCompound nbttagcompound) {
|
|
String s = this.getSaveID();
|
|
|
|
- if (!this.dead && s != null) {
|
|
+ if (this.persist && !this.dead && s != null) { // CraftBukkit - persist flag
|
|
nbttagcompound.setString("id", s);
|
|
this.save(nbttagcompound);
|
|
return true;
|
|
@@ -1259,6 +1428,18 @@
|
|
Vec3D vec3d = this.getMot();
|
|
|
|
nbttagcompound.set("Motion", this.a(vec3d.x, vec3d.y, vec3d.z));
|
|
+
|
|
+ // CraftBukkit start - Checking for NaN pitch/yaw and resetting to zero
|
|
+ // TODO: make sure this is the best way to address this.
|
|
+ if (Float.isNaN(this.yaw)) {
|
|
+ this.yaw = 0;
|
|
+ }
|
|
+
|
|
+ if (Float.isNaN(this.pitch)) {
|
|
+ this.pitch = 0;
|
|
+ }
|
|
+ // CraftBukkit end
|
|
+
|
|
nbttagcompound.set("Rotation", this.a(this.yaw, this.pitch));
|
|
nbttagcompound.setFloat("FallDistance", this.fallDistance);
|
|
nbttagcompound.setShort("Fire", (short) this.fireTicks);
|
|
@@ -1267,6 +1448,12 @@
|
|
nbttagcompound.setBoolean("Invulnerable", this.invulnerable);
|
|
nbttagcompound.setInt("PortalCooldown", this.portalCooldown);
|
|
nbttagcompound.a("UUID", this.getUniqueID());
|
|
+ // CraftBukkit start
|
|
+ // PAIL: Check above UUID reads 1.8 properly, ie: UUIDMost / UUIDLeast
|
|
+ nbttagcompound.setLong("WorldUUIDLeast", ((WorldServer) this.world).getWorld().getUID().getLeastSignificantBits());
|
|
+ nbttagcompound.setLong("WorldUUIDMost", ((WorldServer) this.world).getWorld().getUID().getMostSignificantBits());
|
|
+ nbttagcompound.setInt("Bukkit.updateLevel", CURRENT_LEVEL);
|
|
+ // CraftBukkit end
|
|
IChatBaseComponent ichatbasecomponent = this.getCustomName();
|
|
|
|
if (ichatbasecomponent != null) {
|
|
@@ -1324,6 +1511,11 @@
|
|
}
|
|
}
|
|
|
|
+ // CraftBukkit start - stores eventually existing bukkit values
|
|
+ if (this.bukkitEntity != null) {
|
|
+ this.bukkitEntity.storeBukkitValues(nbttagcompound);
|
|
+ }
|
|
+ // CraftBukkit end
|
|
return nbttagcompound;
|
|
} catch (Throwable throwable) {
|
|
CrashReport crashreport = CrashReport.a(throwable, "Saving entity NBT");
|
|
@@ -1401,6 +1593,43 @@
|
|
} else {
|
|
throw new IllegalStateException("Entity has invalid position");
|
|
}
|
|
+
|
|
+ // CraftBukkit start
|
|
+ if (this instanceof EntityLiving) {
|
|
+ EntityLiving entity = (EntityLiving) this;
|
|
+
|
|
+ // Reset the persistence for tamed animals
|
|
+ if (entity instanceof EntityTameableAnimal && !isLevelAtLeast(nbttagcompound, 2) && !nbttagcompound.getBoolean("PersistenceRequired")) {
|
|
+ EntityInsentient entityinsentient = (EntityInsentient) entity;
|
|
+ entityinsentient.persistent = !entityinsentient.isTypeNotPersistent(0);
|
|
+ }
|
|
+ }
|
|
+ // CraftBukkit end
|
|
+
|
|
+ // CraftBukkit start - Reset world
|
|
+ if (this instanceof EntityPlayer) {
|
|
+ Server server = Bukkit.getServer();
|
|
+ org.bukkit.World bworld = null;
|
|
+
|
|
+ // TODO: Remove World related checks, replaced with WorldUID
|
|
+ String worldName = nbttagcompound.getString("world");
|
|
+
|
|
+ if (nbttagcompound.hasKey("WorldUUIDMost") && nbttagcompound.hasKey("WorldUUIDLeast")) {
|
|
+ UUID uid = new UUID(nbttagcompound.getLong("WorldUUIDMost"), nbttagcompound.getLong("WorldUUIDLeast"));
|
|
+ bworld = server.getWorld(uid);
|
|
+ } else {
|
|
+ bworld = server.getWorld(worldName);
|
|
+ }
|
|
+
|
|
+ if (bworld == null) {
|
|
+ bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getWorldServer(World.OVERWORLD).getWorld();
|
|
+ }
|
|
+
|
|
+ spawnIn(bworld == null ? null : ((CraftWorld) bworld).getHandle());
|
|
+ }
|
|
+ this.getBukkitEntity().readBukkitValues(nbttagcompound);
|
|
+ // CraftBukkit end
|
|
+
|
|
} catch (Throwable throwable) {
|
|
CrashReport crashreport = CrashReport.a(throwable, "Loading entity NBT");
|
|
CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being loaded");
|
|
@@ -1476,9 +1705,22 @@
|
|
} else if (this.world.isClientSide) {
|
|
return null;
|
|
} else {
|
|
+ // CraftBukkit start - Capture drops for death event
|
|
+ if (this instanceof EntityLiving && !((EntityLiving) this).forceDrops) {
|
|
+ ((EntityLiving) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack));
|
|
+ return null;
|
|
+ }
|
|
+ // CraftBukkit end
|
|
EntityItem entityitem = new EntityItem(this.world, this.locX(), this.locY() + (double) f, this.locZ(), itemstack);
|
|
|
|
entityitem.defaultPickupDelay();
|
|
+ // CraftBukkit start
|
|
+ EntityDropItemEvent event = new EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity());
|
|
+ Bukkit.getPluginManager().callEvent(event);
|
|
+ if (event.isCancelled()) {
|
|
+ return null;
|
|
+ }
|
|
+ // CraftBukkit end
|
|
this.world.addEntity(entityitem);
|
|
return entityitem;
|
|
}
|
|
@@ -1554,12 +1796,13 @@
|
|
return false;
|
|
} else {
|
|
if (this.isPassenger()) {
|
|
+ if (this.vehicle == entity) return true; // CraftBukkit - SPIGOT-5562: already riding
|
|
this.stopRiding();
|
|
}
|
|
|
|
this.setPose(EntityPose.STANDING);
|
|
this.vehicle = entity;
|
|
- this.vehicle.addPassenger(this);
|
|
+ if (!this.vehicle.addPassenger(this)) this.vehicle = null; // CraftBukkit
|
|
return true;
|
|
}
|
|
}
|
|
@@ -1584,7 +1827,7 @@
|
|
Entity entity = this.vehicle;
|
|
|
|
this.vehicle = null;
|
|
- entity.removePassenger(this);
|
|
+ if (!entity.removePassenger(this)) this.vehicle = entity; // CraftBukkit
|
|
}
|
|
|
|
}
|
|
@@ -1593,10 +1836,31 @@
|
|
this.bb();
|
|
}
|
|
|
|
- protected void addPassenger(Entity entity) {
|
|
+ protected boolean addPassenger(Entity entity) { // CraftBukkit
|
|
if (entity.getVehicle() != this) {
|
|
throw new IllegalStateException("Use x.startRiding(y), not y.addPassenger(x)");
|
|
} else {
|
|
+ // CraftBukkit start
|
|
+ com.google.common.base.Preconditions.checkState(!entity.passengers.contains(this), "Circular entity riding! %s %s", this, entity);
|
|
+
|
|
+ CraftEntity craft = (CraftEntity) entity.getBukkitEntity().getVehicle();
|
|
+ Entity orig = craft == null ? null : craft.getHandle();
|
|
+ if (getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) {
|
|
+ VehicleEnterEvent event = new VehicleEnterEvent(
|
|
+ (Vehicle) getBukkitEntity(),
|
|
+ entity.getBukkitEntity()
|
|
+ );
|
|
+ // Suppress during worldgen
|
|
+ if (this.valid) {
|
|
+ Bukkit.getPluginManager().callEvent(event);
|
|
+ }
|
|
+ CraftEntity craftn = (CraftEntity) entity.getBukkitEntity().getVehicle();
|
|
+ Entity n = craftn == null ? null : craftn.getHandle();
|
|
+ if (event.isCancelled() || n != orig) {
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ // CraftBukkit end
|
|
if (!this.world.isClientSide && entity instanceof EntityHuman && !(this.getRidingPassenger() instanceof EntityHuman)) {
|
|
this.passengers.add(0, entity);
|
|
} else {
|
|
@@ -1604,15 +1868,33 @@
|
|
}
|
|
|
|
}
|
|
+ return true; // CraftBukkit
|
|
}
|
|
|
|
- protected void removePassenger(Entity entity) {
|
|
+ protected boolean removePassenger(Entity entity) { // CraftBukkit
|
|
if (entity.getVehicle() == this) {
|
|
throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)");
|
|
} else {
|
|
+ // CraftBukkit start
|
|
+ CraftEntity craft = (CraftEntity) entity.getBukkitEntity().getVehicle();
|
|
+ Entity orig = craft == null ? null : craft.getHandle();
|
|
+ if (getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) {
|
|
+ VehicleExitEvent event = new VehicleExitEvent(
|
|
+ (Vehicle) getBukkitEntity(),
|
|
+ (LivingEntity) entity.getBukkitEntity()
|
|
+ );
|
|
+ Bukkit.getPluginManager().callEvent(event);
|
|
+ CraftEntity craftn = (CraftEntity) entity.getBukkitEntity().getVehicle();
|
|
+ Entity n = craftn == null ? null : craftn.getHandle();
|
|
+ if (event.isCancelled() || n != orig) {
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ // CraftBukkit end
|
|
this.passengers.remove(entity);
|
|
entity.j = 60;
|
|
}
|
|
+ return true; // CraftBukkit
|
|
}
|
|
|
|
protected boolean q(Entity entity) {
|
|
@@ -1665,7 +1947,13 @@
|
|
this.world.getMethodProfiler().enter("portal");
|
|
this.portalTicks = i;
|
|
this.portalCooldown = this.getDefaultPortalCooldown();
|
|
- this.a(worldserver1);
|
|
+ // CraftBukkit start
|
|
+ if (this instanceof EntityPlayer) {
|
|
+ ((EntityPlayer) this).a(worldserver1, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL);
|
|
+ } else {
|
|
+ this.a(worldserver1);
|
|
+ }
|
|
+ // CraftBukkit end
|
|
this.world.getMethodProfiler().exit();
|
|
}
|
|
|
|
@@ -1765,6 +2053,13 @@
|
|
}
|
|
|
|
public void setSwimming(boolean flag) {
|
|
+ // CraftBukkit start
|
|
+ if (this.isSwimming() != flag && this instanceof EntityLiving) {
|
|
+ if (CraftEventFactory.callToggleSwimEvent((EntityLiving) this, flag).isCancelled()) {
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+ // CraftBukkit end
|
|
this.setFlag(4, flag);
|
|
}
|
|
|
|
@@ -1825,16 +2120,56 @@
|
|
}
|
|
|
|
public void setAirTicks(int i) {
|
|
- this.datawatcher.set(Entity.AIR_TICKS, i);
|
|
+ // CraftBukkit start
|
|
+ EntityAirChangeEvent event = new EntityAirChangeEvent(this.getBukkitEntity(), i);
|
|
+ // Suppress during worldgen
|
|
+ if (this.valid) {
|
|
+ event.getEntity().getServer().getPluginManager().callEvent(event);
|
|
+ }
|
|
+ if (event.isCancelled()) {
|
|
+ return;
|
|
+ }
|
|
+ this.datawatcher.set(Entity.AIR_TICKS, event.getAmount());
|
|
+ // CraftBukkit end
|
|
}
|
|
|
|
public void onLightningStrike(EntityLightning entitylightning) {
|
|
this.setFireTicks(this.fireTicks + 1);
|
|
+ // CraftBukkit start
|
|
+ final org.bukkit.entity.Entity thisBukkitEntity = this.getBukkitEntity();
|
|
+ final org.bukkit.entity.Entity stormBukkitEntity = entitylightning.getBukkitEntity();
|
|
+ final PluginManager pluginManager = Bukkit.getPluginManager();
|
|
+ // CraftBukkit end
|
|
+
|
|
if (this.fireTicks == 0) {
|
|
- this.setOnFire(8);
|
|
+ // CraftBukkit start - Call a combust event when lightning strikes
|
|
+ EntityCombustByEntityEvent entityCombustEvent = new EntityCombustByEntityEvent(stormBukkitEntity, thisBukkitEntity, 8);
|
|
+ pluginManager.callEvent(entityCombustEvent);
|
|
+ if (!entityCombustEvent.isCancelled()) {
|
|
+ this.setOnFire(entityCombustEvent.getDuration(), false);
|
|
+ }
|
|
+ // CraftBukkit end
|
|
}
|
|
|
|
- this.damageEntity(DamageSource.LIGHTNING, 5.0F);
|
|
+ // CraftBukkit start
|
|
+ if (thisBukkitEntity instanceof Hanging) {
|
|
+ HangingBreakByEntityEvent hangingEvent = new HangingBreakByEntityEvent((Hanging) thisBukkitEntity, stormBukkitEntity);
|
|
+ pluginManager.callEvent(hangingEvent);
|
|
+
|
|
+ if (hangingEvent.isCancelled()) {
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (this.isFireProof()) {
|
|
+ return;
|
|
+ }
|
|
+ CraftEventFactory.entityDamage = entitylightning;
|
|
+ if (!this.damageEntity(DamageSource.LIGHTNING, 5.0F)) {
|
|
+ CraftEventFactory.entityDamage = null;
|
|
+ return;
|
|
+ }
|
|
+ // CraftBukkit end
|
|
}
|
|
|
|
public void k(boolean flag) {
|
|
@@ -1986,18 +2321,45 @@
|
|
|
|
@Nullable
|
|
public Entity a(WorldServer worldserver) {
|
|
+ // CraftBukkit start
|
|
+ return teleportTo(worldserver, null);
|
|
+ }
|
|
+
|
|
+ @Nullable
|
|
+ public Entity teleportTo(WorldServer worldserver, BlockPosition location) {
|
|
+ // CraftBukkit end
|
|
if (this.world instanceof WorldServer && !this.dead) {
|
|
this.world.getMethodProfiler().enter("changeDimension");
|
|
- this.decouple();
|
|
+ // CraftBukkit start
|
|
+ // this.decouple();
|
|
+ if (worldserver == null){
|
|
+ return null;
|
|
+ }
|
|
+ // CraftBukkit end
|
|
this.world.getMethodProfiler().enter("reposition");
|
|
Vec3D vec3d = this.getMot();
|
|
float f = 0.0F;
|
|
- BlockPosition blockposition;
|
|
+ BlockPosition blockposition = location; // CraftBukkit
|
|
|
|
+ if (blockposition == null) { // CraftBukkit
|
|
if (this.world.getDimensionKey() == World.THE_END && worldserver.getDimensionKey() == World.OVERWORLD) {
|
|
- blockposition = worldserver.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, worldserver.getSpawn());
|
|
+ // CraftBukkit start
|
|
+ EntityPortalEvent event = CraftEventFactory.callEntityPortalEvent(this, worldserver, worldserver.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, worldserver.getSpawn()), 0);
|
|
+ if (event == null) {
|
|
+ return null;
|
|
+ }
|
|
+ worldserver = ((CraftWorld) event.getTo().getWorld()).getHandle();
|
|
+ blockposition = new BlockPosition(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ());
|
|
+ // CraftBukkit end
|
|
} else if (worldserver.getDimensionKey() == World.THE_END) {
|
|
- blockposition = WorldServer.a;
|
|
+ // CraftBukkit start
|
|
+ EntityPortalEvent event = CraftEventFactory.callEntityPortalEvent(this, worldserver, WorldServer.a, 0);
|
|
+ if (event == null) {
|
|
+ return null;
|
|
+ }
|
|
+ worldserver = ((CraftWorld) event.getTo().getWorld()).getHandle();
|
|
+ blockposition = new BlockPosition(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ());
|
|
+ // CraftBukkit end
|
|
} else {
|
|
double d0 = this.locX();
|
|
double d1 = this.locZ();
|
|
@@ -2023,7 +2385,16 @@
|
|
Vec3D vec3d1 = this.getPortalOffset();
|
|
|
|
blockposition = new BlockPosition(d0, this.locY(), d1);
|
|
- ShapeDetector.Shape shapedetector_shape = worldserver.getTravelAgent().a(blockposition, vec3d, this.getPortalDirection(), vec3d1.x, vec3d1.y, this instanceof EntityHuman);
|
|
+ // CraftBukkit start
|
|
+ EntityPortalEvent event = CraftEventFactory.callEntityPortalEvent(this, worldserver, blockposition, 128);
|
|
+ if (event == null) {
|
|
+ return null;
|
|
+ }
|
|
+ worldserver = ((CraftWorld) event.getTo().getWorld()).getHandle();
|
|
+ blockposition = new BlockPosition(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ());
|
|
+ int searchRadius = event.getSearchRadius();
|
|
+ // CraftBukkit end
|
|
+ ShapeDetector.Shape shapedetector_shape = worldserver.getTravelAgent().findPortal(blockposition, vec3d, this.getPortalDirection(), vec3d1.x, vec3d1.y, this instanceof EntityHuman, searchRadius); // CraftBukkit - search radius
|
|
|
|
if (shapedetector_shape == null) {
|
|
return null;
|
|
@@ -2033,6 +2404,11 @@
|
|
vec3d = shapedetector_shape.velocity;
|
|
f = (float) shapedetector_shape.yaw;
|
|
}
|
|
+ } // CraftBukkit
|
|
+
|
|
+ // CraftBukkit start
|
|
+ this.decouple();
|
|
+ // CraftBukkit end
|
|
|
|
this.world.getMethodProfiler().exitEnter("reloading");
|
|
Entity entity = this.getEntityType().a((World) worldserver);
|
|
@@ -2043,8 +2419,16 @@
|
|
entity.setMot(vec3d);
|
|
worldserver.addEntityTeleport(entity);
|
|
if (worldserver.getDimensionKey() == World.THE_END) {
|
|
- WorldServer.a(worldserver);
|
|
+ WorldServer.a(worldserver, this); // CraftBukkit
|
|
+ }
|
|
+ // CraftBukkit start - Forward the CraftEntity to the new entity
|
|
+ this.getBukkitEntity().setHandle(entity);
|
|
+ entity.bukkitEntity = this.getBukkitEntity();
|
|
+
|
|
+ if (this instanceof EntityInsentient) {
|
|
+ ((EntityInsentient)this).unleash(true, false); // Unleash to prevent duping of leads.
|
|
}
|
|
+ // CraftBukkit end
|
|
}
|
|
|
|
this.bJ();
|
|
@@ -2253,7 +2637,26 @@
|
|
}
|
|
|
|
public void a(AxisAlignedBB axisalignedbb) {
|
|
- this.boundingBox = axisalignedbb;
|
|
+ // CraftBukkit start - block invalid bounding boxes
|
|
+ double minX = axisalignedbb.minX,
|
|
+ minY = axisalignedbb.minY,
|
|
+ minZ = axisalignedbb.minZ,
|
|
+ maxX = axisalignedbb.maxX,
|
|
+ maxY = axisalignedbb.maxY,
|
|
+ maxZ = axisalignedbb.maxZ;
|
|
+ double len = axisalignedbb.maxX - axisalignedbb.minX;
|
|
+ if (len < 0) maxX = minX;
|
|
+ if (len > 64) maxX = minX + 64.0;
|
|
+
|
|
+ len = axisalignedbb.maxY - axisalignedbb.minY;
|
|
+ if (len < 0) maxY = minY;
|
|
+ if (len > 64) maxY = minY + 64.0;
|
|
+
|
|
+ len = axisalignedbb.maxZ - axisalignedbb.minZ;
|
|
+ if (len < 0) maxZ = minZ;
|
|
+ if (len > 64) maxZ = minZ + 64.0;
|
|
+ this.boundingBox = new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ);
|
|
+ // CraftBukkit end
|
|
}
|
|
|
|
protected float getHeadHeight(EntityPose entitypose, EntitySize entitysize) {
|